summaryrefslogtreecommitdiff
path: root/src/script/lua_api
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/lua_api')
-rw-r--r--src/script/lua_api/CMakeLists.txt6
-rw-r--r--src/script/lua_api/l_areastore.cpp401
-rw-r--r--src/script/lua_api/l_areastore.h70
-rw-r--r--src/script/lua_api/l_base.cpp40
-rw-r--r--src/script/lua_api/l_base.h4
-rw-r--r--src/script/lua_api/l_craft.cpp183
-rw-r--r--src/script/lua_api/l_env.cpp147
-rw-r--r--src/script/lua_api/l_env.h8
-rw-r--r--src/script/lua_api/l_internal.h13
-rw-r--r--src/script/lua_api/l_mainmenu.cpp115
-rw-r--r--src/script/lua_api/l_mainmenu.h2
-rw-r--r--src/script/lua_api/l_mapgen.cpp986
-rw-r--r--src/script/lua_api/l_mapgen.h35
-rw-r--r--src/script/lua_api/l_nodemeta.cpp27
-rw-r--r--src/script/lua_api/l_noise.cpp338
-rw-r--r--src/script/lua_api/l_noise.h54
-rw-r--r--src/script/lua_api/l_object.cpp584
-rw-r--r--src/script/lua_api/l_object.h58
-rw-r--r--src/script/lua_api/l_particles.cpp214
-rw-r--r--src/script/lua_api/l_server.cpp63
-rw-r--r--src/script/lua_api/l_server.h8
-rw-r--r--src/script/lua_api/l_settings.cpp2
-rw-r--r--src/script/lua_api/l_util.cpp90
-rw-r--r--src/script/lua_api/l_util.h12
-rw-r--r--src/script/lua_api/l_vmanip.cpp50
25 files changed, 2569 insertions, 941 deletions
diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt
index 08960d2ad..2501ce6d6 100644
--- a/src/script/lua_api/CMakeLists.txt
+++ b/src/script/lua_api/CMakeLists.txt
@@ -1,5 +1,5 @@
-# Used by server and client
set(common_SCRIPT_LUA_API_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/l_areastore.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_base.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_craft.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp
@@ -18,7 +18,7 @@ set(common_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_settings.cpp
PARENT_SCOPE)
-# Used by client only
-set(minetest_SCRIPT_LUA_API_SRCS
+set(client_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp
PARENT_SCOPE)
+
diff --git a/src/script/lua_api/l_areastore.cpp b/src/script/lua_api/l_areastore.cpp
new file mode 100644
index 000000000..1e9075119
--- /dev/null
+++ b/src/script/lua_api/l_areastore.cpp
@@ -0,0 +1,401 @@
+/*
+Minetest
+Copyright (C) 2015 est31 <mtest31@outlook.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+
+#include "lua_api/l_areastore.h"
+#include "lua_api/l_internal.h"
+#include "common/c_converter.h"
+#include "cpp_api/s_security.h"
+#include "areastore.h"
+#include "filesys.h"
+#ifndef ANDROID
+ #include "cmake_config.h"
+#endif
+#include <fstream>
+
+static inline void get_data_and_border_flags(lua_State *L, u8 start_i,
+ bool *borders, bool *data)
+{
+ if (!lua_isboolean(L, start_i))
+ return;
+ *borders = lua_toboolean(L, start_i);
+ if (!lua_isboolean(L, start_i + 1))
+ return;
+ *data = lua_toboolean(L, start_i + 1);
+}
+
+static void push_area(lua_State *L, const Area *a,
+ bool include_borders, bool include_data)
+{
+ if (!include_borders && !include_data) {
+ lua_pushboolean(L, true);
+ }
+ lua_newtable(L);
+ if (include_borders) {
+ push_v3s16(L, a->minedge);
+ lua_setfield(L, -2, "min");
+ push_v3s16(L, a->maxedge);
+ lua_setfield(L, -2, "max");
+ }
+ if (include_data) {
+ lua_pushlstring(L, a->data.c_str(), a->data.size());
+ lua_setfield(L, -2, "data");
+ }
+}
+
+static inline void push_areas(lua_State *L, const std::vector<Area *> &areas,
+ bool borders, bool data)
+{
+ lua_newtable(L);
+ size_t cnt = areas.size();
+ for (size_t i = 0; i < cnt; i++) {
+ lua_pushnumber(L, areas[i]->id);
+ push_area(L, areas[i], borders, data);
+ lua_settable(L, -3);
+ }
+}
+
+// garbage collector
+int LuaAreaStore::gc_object(lua_State *L)
+{
+ LuaAreaStore *o = *(LuaAreaStore **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+// get_area(id, include_borders, include_data)
+int LuaAreaStore::l_get_area(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ u32 id = luaL_checknumber(L, 2);
+
+ bool include_borders = true;
+ bool include_data = false;
+ get_data_and_border_flags(L, 3, &include_borders, &include_data);
+
+ const Area *res;
+
+ res = ast->getArea(id);
+ push_area(L, res, include_borders, include_data);
+
+ return 1;
+}
+
+// get_areas_for_pos(pos, include_borders, include_data)
+int LuaAreaStore::l_get_areas_for_pos(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ v3s16 pos = check_v3s16(L, 2);
+
+ bool include_borders = true;
+ bool include_data = false;
+ get_data_and_border_flags(L, 3, &include_borders, &include_data);
+
+ std::vector<Area *> res;
+
+ ast->getAreasForPos(&res, pos);
+ push_areas(L, res, include_borders, include_data);
+
+ return 1;
+}
+
+// get_areas_in_area(edge1, edge2, accept_overlap, include_borders, include_data)
+int LuaAreaStore::l_get_areas_in_area(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ v3s16 minedge = check_v3s16(L, 2);
+ v3s16 maxedge = check_v3s16(L, 3);
+
+ bool include_borders = true;
+ bool include_data = false;
+ bool accept_overlap = false;
+ if (lua_isboolean(L, 4)) {
+ accept_overlap = lua_toboolean(L, 4);
+ get_data_and_border_flags(L, 5, &include_borders, &include_data);
+ }
+ std::vector<Area *> res;
+
+ ast->getAreasInArea(&res, minedge, maxedge, accept_overlap);
+ push_areas(L, res, include_borders, include_data);
+
+ return 1;
+}
+
+// insert_area(edge1, edge2, data)
+int LuaAreaStore::l_insert_area(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ Area a;
+
+ a.minedge = check_v3s16(L, 2);
+ a.maxedge = check_v3s16(L, 3);
+
+ a.extremifyEdges();
+ a.id = ast->getFreeId(a.minedge, a.maxedge);
+
+ if (a.id == AREA_ID_INVALID) {
+ // couldn't get free id
+ lua_pushnil(L);
+ return 1;
+ }
+
+ size_t d_len;
+ const char *data = luaL_checklstring(L, 4, &d_len);
+
+ a.data = std::string(data, d_len);
+
+ ast->insertArea(a);
+
+ lua_pushnumber(L, a.id);
+ return 1;
+}
+
+// reserve(count)
+int LuaAreaStore::l_reserve(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ size_t count = luaL_checknumber(L, 2);
+ ast->reserve(count);
+ return 0;
+}
+
+// remove_area(id)
+int LuaAreaStore::l_remove_area(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ u32 id = luaL_checknumber(L, 2);
+ bool success = ast->removeArea(id);
+
+ lua_pushboolean(L, success);
+ return 1;
+}
+
+// set_cache_params(params)
+int LuaAreaStore::l_set_cache_params(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ luaL_checktype(L, 2, LUA_TTABLE);
+
+ bool enabled = getboolfield_default(L, 2, "enabled", true);
+ u8 block_radius = getintfield_default(L, 2, "block_radius", 64);
+ size_t limit = getintfield_default(L, 2, "block_radius", 1000);
+
+ ast->setCacheParams(enabled, block_radius, limit);
+
+ return 0;
+}
+
+#if 0
+// to_string()
+int LuaAreaStore::l_to_string(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ std::ostringstream os(std::ios_base::binary);
+ ast->serialize(os);
+ std::string str = os.str();
+
+ lua_pushlstring(L, str.c_str(), str.length());
+ return 1;
+}
+
+// to_file(filename)
+int LuaAreaStore::l_to_file(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ const char *filename = luaL_checkstring(L, 2);
+ CHECK_SECURE_PATH_OPTIONAL(L, filename);
+
+ std::ostringstream os(std::ios_base::binary);
+ ast->serialize(os);
+
+ lua_pushboolean(L, fs::safeWriteToFile(filename, os.str()));
+ return 1;
+}
+
+// from_string(str)
+int LuaAreaStore::l_from_string(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ size_t len;
+ const char *str = luaL_checklstring(L, 2, &len);
+
+ std::istringstream is(std::string(str, len), std::ios::binary);
+ bool success = ast->deserialize(is);
+
+ lua_pushboolean(L, success);
+ return 1;
+}
+
+// from_file(filename)
+int LuaAreaStore::l_from_file(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = checkobject(L, 1);
+ AreaStore *ast = o->as;
+
+ const char *filename = luaL_checkstring(L, 2);
+ CHECK_SECURE_PATH_OPTIONAL(L, filename);
+
+ std::ifstream is(filename, std::ios::binary);
+ bool success = ast->deserialize(is);
+
+ lua_pushboolean(L, success);
+ return 1;
+}
+#endif
+
+LuaAreaStore::LuaAreaStore()
+{
+#if USE_SPATIAL
+ this->as = new SpatialAreaStore();
+#else
+ this->as = new VectorAreaStore();
+#endif
+}
+
+LuaAreaStore::LuaAreaStore(const std::string &type)
+{
+#if USE_SPATIAL
+ if (type == "LibSpatial") {
+ this->as = new SpatialAreaStore();
+ } else
+#endif
+ {
+ this->as = new VectorAreaStore();
+ }
+}
+
+LuaAreaStore::~LuaAreaStore()
+{
+ delete as;
+}
+
+// LuaAreaStore()
+// Creates an LuaAreaStore and leaves it on top of stack
+int LuaAreaStore::create_object(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaAreaStore *o = (lua_isstring(L, 1)) ?
+ new LuaAreaStore(lua_tostring(L, 1)) :
+ new LuaAreaStore();
+
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ return 1;
+}
+
+LuaAreaStore *LuaAreaStore::checkobject(lua_State *L, int narg)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+
+ void *ud = luaL_checkudata(L, narg, className);
+ if (!ud)
+ luaL_typerror(L, narg, className);
+
+ return *(LuaAreaStore **)ud; // unbox pointer
+}
+
+void LuaAreaStore::Register(lua_State *L)
+{
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1); // drop metatable
+
+ luaL_openlib(L, 0, methods, 0); // fill methodtable
+ lua_pop(L, 1); // drop methodtable
+
+ // Can be created from Lua (AreaStore())
+ lua_register(L, className, create_object);
+}
+
+const char LuaAreaStore::className[] = "AreaStore";
+const luaL_reg LuaAreaStore::methods[] = {
+ luamethod(LuaAreaStore, get_area),
+ luamethod(LuaAreaStore, get_areas_for_pos),
+ luamethod(LuaAreaStore, get_areas_in_area),
+ luamethod(LuaAreaStore, insert_area),
+ luamethod(LuaAreaStore, reserve),
+ luamethod(LuaAreaStore, remove_area),
+ luamethod(LuaAreaStore, set_cache_params),
+ /* luamethod(LuaAreaStore, to_string),
+ luamethod(LuaAreaStore, to_file),
+ luamethod(LuaAreaStore, from_string),
+ luamethod(LuaAreaStore, from_file),*/
+ {0,0}
+};
diff --git a/src/script/lua_api/l_areastore.h b/src/script/lua_api/l_areastore.h
new file mode 100644
index 000000000..a25529627
--- /dev/null
+++ b/src/script/lua_api/l_areastore.h
@@ -0,0 +1,70 @@
+/*
+Minetest
+Copyright (C) 2015 est31 <mtest31@outlook.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef L_AREASTORE_H_
+#define L_AREASTORE_H_
+
+#include "lua_api/l_base.h"
+#include "irr_v3d.h"
+#include "areastore.h"
+
+/*
+ AreaStore
+ */
+class LuaAreaStore : public ModApiBase {
+private:
+
+ static const char className[];
+ static const luaL_reg methods[];
+
+ static int gc_object(lua_State *L);
+
+ static int l_get_area(lua_State *L);
+
+ static int l_get_areas_for_pos(lua_State *L);
+ static int l_get_areas_in_area(lua_State *L);
+ static int l_insert_area(lua_State *L);
+ static int l_reserve(lua_State *L);
+ static int l_remove_area(lua_State *L);
+
+ static int l_set_cache_params(lua_State *L);
+
+ /* static int l_to_string(lua_State *L);
+ static int l_to_file(lua_State *L);
+
+ static int l_from_string(lua_State *L);
+ static int l_from_file(lua_State *L); */
+
+public:
+ AreaStore *as;
+
+ LuaAreaStore();
+ LuaAreaStore(const std::string &type);
+ ~LuaAreaStore();
+
+ // AreaStore()
+ // Creates a AreaStore and leaves it on top of stack
+ static int create_object(lua_State *L);
+
+ static LuaAreaStore *checkobject(lua_State *L, int narg);
+
+ static void Register(lua_State *L);
+};
+
+#endif /* L_AREASTORE_H_ */
diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp
index b8d673ee4..6ad3e4ba2 100644
--- a/src/script/lua_api/l_base.cpp
+++ b/src/script/lua_api/l_base.cpp
@@ -20,8 +20,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_base.h"
#include "lua_api/l_internal.h"
#include "cpp_api/s_base.h"
+#include <mods.h>
+#include <server.h>
-ScriptApiBase* ModApiBase::getScriptApiBase(lua_State *L) {
+ScriptApiBase *ModApiBase::getScriptApiBase(lua_State *L)
+{
// Get server from registry
lua_getfield(L, LUA_REGISTRYINDEX, "scriptapi");
ScriptApiBase *sapi_ptr = (ScriptApiBase*) lua_touserdata(L, -1);
@@ -29,23 +32,42 @@ ScriptApiBase* ModApiBase::getScriptApiBase(lua_State *L) {
return sapi_ptr;
}
-Server* ModApiBase::getServer(lua_State *L) {
+Server *ModApiBase::getServer(lua_State *L)
+{
return getScriptApiBase(L)->getServer();
}
-Environment* ModApiBase::getEnv(lua_State *L) {
+Environment *ModApiBase::getEnv(lua_State *L)
+{
return getScriptApiBase(L)->getEnv();
}
-GUIEngine* ModApiBase::getGuiEngine(lua_State *L) {
+GUIEngine *ModApiBase::getGuiEngine(lua_State *L)
+{
return getScriptApiBase(L)->getGuiEngine();
}
-bool ModApiBase::registerFunction(lua_State *L,
- const char *name,
- lua_CFunction fct,
- int top
- ) {
+std::string ModApiBase::getCurrentModPath(lua_State *L)
+{
+ lua_getfield(L, LUA_REGISTRYINDEX, SCRIPT_MOD_NAME_FIELD);
+ const char *current_mod_name = lua_tostring(L, -1);
+ if (!current_mod_name)
+ return ".";
+
+ const ModSpec *mod = getServer(L)->getModSpec(current_mod_name);
+ if (!mod)
+ return ".";
+
+ return mod->path;
+}
+
+
+bool ModApiBase::registerFunction(
+ lua_State *L,
+ const char *name,
+ lua_CFunction fct,
+ int top)
+{
//TODO check presence first!
lua_pushstring(L,name);
diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h
index debbcd09b..641013dfd 100644
--- a/src/script/lua_api/l_base.h
+++ b/src/script/lua_api/l_base.h
@@ -35,11 +35,13 @@ class GUIEngine;
class ModApiBase {
-protected:
+public:
static ScriptApiBase* getScriptApiBase(lua_State *L);
static Server* getServer(lua_State *L);
static Environment* getEnv(lua_State *L);
static GUIEngine* getGuiEngine(lua_State *L);
+ // When we are not loading the mod, this function returns "."
+ static std::string getCurrentModPath(lua_State *L);
// Get an arbitrary subclass of ScriptApiBase
// by using dynamic_cast<> on getScriptApiBase()
diff --git a/src/script/lua_api/l_craft.cpp b/src/script/lua_api/l_craft.cpp
index 8f8efbfbc..391a0133d 100644
--- a/src/script/lua_api/l_craft.cpp
+++ b/src/script/lua_api/l_craft.cpp
@@ -173,7 +173,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
CraftDefinition *def = new CraftDefinitionShaped(
output, width, recipe, replacements);
- craftdef->registerCraft(def);
+ craftdef->registerCraft(def, getServer(L));
}
/*
CraftDefinitionShapeless
@@ -205,7 +205,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
CraftDefinition *def = new CraftDefinitionShapeless(
output, recipe, replacements);
- craftdef->registerCraft(def);
+ craftdef->registerCraft(def, getServer(L));
}
/*
CraftDefinitionToolRepair
@@ -216,7 +216,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
CraftDefinition *def = new CraftDefinitionToolRepair(
additional_wear);
- craftdef->registerCraft(def);
+ craftdef->registerCraft(def, getServer(L));
}
/*
CraftDefinitionCooking
@@ -246,7 +246,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
CraftDefinition *def = new CraftDefinitionCooking(
output, recipe, cooktime, replacements);
- craftdef->registerCraft(def);
+ craftdef->registerCraft(def, getServer(L));
}
/*
CraftDefinitionFuel
@@ -270,7 +270,7 @@ int ModApiCraft::l_register_craft(lua_State *L)
CraftDefinition *def = new CraftDefinitionFuel(
recipe, burntime, replacements);
- craftdef->registerCraft(def);
+ craftdef->registerCraft(def, getServer(L));
}
else
{
@@ -303,18 +303,23 @@ int ModApiCraft::l_get_craft_result(lua_State *L)
ICraftDefManager *cdef = gdef->cdef();
CraftInput input(method, width, items);
CraftOutput output;
- bool got = cdef->getCraftResult(input, output, true, gdef);
+ std::vector<ItemStack> output_replacements;
+ bool got = cdef->getCraftResult(input, output, output_replacements, true, gdef);
lua_newtable(L); // output table
- if(got){
+ if (got) {
ItemStack item;
item.deSerialize(output.item, gdef->idef());
LuaItemStack::create(L, item);
lua_setfield(L, -2, "item");
setintfield(L, -1, "time", output.time);
+ push_items(L, output_replacements);
+ lua_setfield(L, -2, "replacements");
} else {
LuaItemStack::create(L, ItemStack());
lua_setfield(L, -2, "item");
setintfield(L, -1, "time", 0);
+ lua_newtable(L);
+ lua_setfield(L, -2, "replacements");
}
lua_newtable(L); // decremented input table
lua_pushstring(L, method_s.c_str());
@@ -326,56 +331,82 @@ int ModApiCraft::l_get_craft_result(lua_State *L)
return 2;
}
+
+static void push_craft_recipe(lua_State *L, IGameDef *gdef,
+ const CraftDefinition *recipe,
+ const CraftOutput &tmpout)
+{
+ CraftInput input = recipe->getInput(tmpout, gdef);
+ CraftOutput output = recipe->getOutput(input, gdef);
+
+ lua_newtable(L); // items
+ std::vector<ItemStack>::const_iterator iter = input.items.begin();
+ for (u16 j = 1; iter != input.items.end(); iter++, j++) {
+ if (iter->empty())
+ continue;
+ lua_pushstring(L, iter->name.c_str());
+ lua_rawseti(L, -2, j);
+ }
+ lua_setfield(L, -2, "items");
+ setintfield(L, -1, "width", input.width);
+ switch (input.method) {
+ case CRAFT_METHOD_NORMAL:
+ lua_pushstring(L, "normal");
+ break;
+ case CRAFT_METHOD_COOKING:
+ lua_pushstring(L, "cooking");
+ break;
+ case CRAFT_METHOD_FUEL:
+ lua_pushstring(L, "fuel");
+ break;
+ default:
+ lua_pushstring(L, "unknown");
+ }
+ lua_setfield(L, -2, "type");
+ lua_pushstring(L, output.item.c_str());
+ lua_setfield(L, -2, "output");
+}
+
+static void push_craft_recipes(lua_State *L, IGameDef *gdef,
+ const std::vector<CraftDefinition*> &recipes,
+ const CraftOutput &output)
+{
+ lua_createtable(L, recipes.size(), 0);
+
+ if (recipes.empty()) {
+ lua_pushnil(L);
+ return;
+ }
+
+ std::vector<CraftDefinition*>::const_iterator it = recipes.begin();
+ for (unsigned i = 0; it != recipes.end(); ++it) {
+ lua_newtable(L);
+ push_craft_recipe(L, gdef, *it, output);
+ lua_rawseti(L, -2, ++i);
+ }
+}
+
+
// get_craft_recipe(result item)
int ModApiCraft::l_get_craft_recipe(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- int k = 1;
- int input_i = 1;
- std::string o_item = luaL_checkstring(L,input_i);
+ std::string item = luaL_checkstring(L, 1);
+ Server *server = getServer(L);
+ CraftOutput output(item, 0);
+ std::vector<CraftDefinition*> recipes = server->cdef()
+ ->getCraftRecipes(output, server, 1);
- IGameDef *gdef = getServer(L);
- ICraftDefManager *cdef = gdef->cdef();
- CraftInput input;
- CraftOutput output(o_item,0);
- bool got = cdef->getCraftRecipe(input, output, gdef);
- lua_newtable(L); // output table
- if(got){
- lua_newtable(L);
- for(std::vector<ItemStack>::const_iterator
- i = input.items.begin();
- i != input.items.end(); i++, k++)
- {
- if (i->empty())
- {
- continue;
- }
- lua_pushinteger(L,k);
- lua_pushstring(L,i->name.c_str());
- lua_settable(L, -3);
- }
- lua_setfield(L, -2, "items");
- setintfield(L, -1, "width", input.width);
- switch (input.method) {
- case CRAFT_METHOD_NORMAL:
- lua_pushstring(L,"normal");
- break;
- case CRAFT_METHOD_COOKING:
- lua_pushstring(L,"cooking");
- break;
- case CRAFT_METHOD_FUEL:
- lua_pushstring(L,"fuel");
- break;
- default:
- lua_pushstring(L,"unknown");
- }
- lua_setfield(L, -2, "type");
- } else {
+ lua_createtable(L, 1, 0);
+
+ if (recipes.empty()) {
lua_pushnil(L);
lua_setfield(L, -2, "items");
setintfield(L, -1, "width", 0);
+ return 1;
}
+ push_craft_recipe(L, server, recipes[0], output);
return 1;
}
@@ -384,59 +415,13 @@ int ModApiCraft::l_get_all_craft_recipes(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- std::string o_item = luaL_checkstring(L,1);
- IGameDef *gdef = getServer(L);
- ICraftDefManager *cdef = gdef->cdef();
- CraftInput input;
- CraftOutput output(o_item,0);
- std::vector<CraftDefinition*> recipes_list;
- recipes_list = cdef->getCraftRecipes(output, gdef);
- if (recipes_list.empty()) {
- lua_pushnil(L);
- return 1;
- }
+ std::string item = luaL_checkstring(L, 1);
+ Server *server = getServer(L);
+ CraftOutput output(item, 0);
+ std::vector<CraftDefinition*> recipes = server->cdef()
+ ->getCraftRecipes(output, server);
- lua_createtable(L, recipes_list.size(), 0);
- std::vector<CraftDefinition*>::const_iterator iter = recipes_list.begin();
- for (u16 i = 0; iter != recipes_list.end(); iter++) {
- CraftOutput tmpout;
- tmpout.item = "";
- tmpout.time = 0;
- tmpout = (*iter)->getOutput(input, gdef);
- std::string query = tmpout.item;
- char *fmtpos, *fmt = &query[0];
- if (strtok_r(fmt, " ", &fmtpos) == output.item) {
- input = (*iter)->getInput(output, gdef);
- lua_newtable(L);
- lua_newtable(L); // items
- std::vector<ItemStack>::const_iterator iter = input.items.begin();
- for (u16 j = 1; iter != input.items.end(); iter++, j++) {
- if (iter->empty())
- continue;
- lua_pushstring(L, iter->name.c_str());
- lua_rawseti(L, -2, j);
- }
- lua_setfield(L, -2, "items");
- setintfield(L, -1, "width", input.width);
- switch (input.method) {
- case CRAFT_METHOD_NORMAL:
- lua_pushstring(L, "normal");
- break;
- case CRAFT_METHOD_COOKING:
- lua_pushstring(L, "cooking");
- break;
- case CRAFT_METHOD_FUEL:
- lua_pushstring(L, "fuel");
- break;
- default:
- lua_pushstring(L, "unknown");
- }
- lua_setfield(L, -2, "type");
- lua_pushstring(L, &tmpout.item[0]);
- lua_setfield(L, -2, "output");
- lua_rawseti(L, -2, ++i);
- }
- }
+ push_craft_recipes(L, server, recipes, output);
return 1;
}
diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp
index cd5d253ac..28afdd071 100644
--- a/src/script/lua_api/l_env.cpp
+++ b/src/script/lua_api/l_env.cpp
@@ -49,7 +49,7 @@ void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
scriptIface->realityCheck();
lua_State *L = scriptIface->getStack();
- assert(lua_checkstack(L, 20));
+ sanity_check(lua_checkstack(L, 20));
StackUnroller stack_unroller(L);
lua_pushcfunction(L, script_error_handler);
@@ -65,9 +65,11 @@ void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
lua_pushnumber(L, m_id);
lua_gettable(L, -2);
if(lua_isnil(L, -1))
- assert(0);
+ FATAL_ERROR("");
lua_remove(L, -2); // Remove registered_abms
+ scriptIface->setOriginFromTable(-1);
+
// Call action
luaL_checktype(L, -1, LUA_TTABLE);
lua_getfield(L, -1, "action");
@@ -77,8 +79,11 @@ void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n,
pushnode(L, n, env->getGameDef()->ndef());
lua_pushnumber(L, active_object_count);
lua_pushnumber(L, active_object_count_wider);
- if(lua_pcall(L, 4, 0, errorhandler))
- script_error(L);
+
+ int result = lua_pcall(L, 4, 0, errorhandler);
+ if (result)
+ scriptIface->scriptError(result, "LuaABM::trigger");
+
lua_pop(L, 1); // Pop error handler
}
@@ -334,6 +339,22 @@ int ModApiEnvMod::l_add_node_level(lua_State *L)
return 1;
}
+// find_nodes_with_meta(pos1, pos2)
+int ModApiEnvMod::l_find_nodes_with_meta(lua_State *L)
+{
+ GET_ENV_PTR;
+
+ std::vector<v3s16> positions = env->getMap().findNodesWithMetadata(
+ check_v3s16(L, 1), check_v3s16(L, 2));
+
+ lua_newtable(L);
+ for (size_t i = 0; i != positions.size(); i++) {
+ push_v3s16(L, positions[i]);
+ lua_rawseti(L, -2, i + 1);
+ }
+
+ return 1;
+}
// get_meta(pos)
int ModApiEnvMod::l_get_meta(lua_State *L)
@@ -402,23 +423,11 @@ int ModApiEnvMod::l_add_item(lua_State *L)
return 0;
lua_pushvalue(L, 1);
lua_pushstring(L, item.getItemString().c_str());
- if(lua_pcall(L, 2, 1, errorhandler))
- script_error(L);
+
+ PCALL_RESL(L, lua_pcall(L, 2, 1, errorhandler));
+
lua_remove(L, errorhandler); // Remove error handler
return 1;
- /*lua_pushvalue(L, 1);
- lua_pushstring(L, "__builtin:item");
- lua_pushstring(L, item.getItemString().c_str());
- return l_add_entity(L);*/
- /*// Do it
- ServerActiveObject *obj = createItemSAO(env, pos, item.getItemString());
- int objectid = env->addActiveObject(obj);
- // If failed to add, return nothing (reads as nil)
- if(objectid == 0)
- return 0;
- // Return ObjectRef
- objectrefGetOrCreate(L, obj);
- return 1;*/
}
// get_player_by_name(name)
@@ -451,10 +460,11 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
// Do it
v3f pos = checkFloatPos(L, 1);
float radius = luaL_checknumber(L, 2) * BS;
- std::set<u16> ids = env->getObjectsInsideRadius(pos, radius);
+ std::vector<u16> ids;
+ env->getObjectsInsideRadius(ids, pos, radius);
ScriptApiBase *script = getScriptApiBase(L);
lua_createtable(L, ids.size(), 0);
- std::set<u16>::const_iterator iter = ids.begin();
+ std::vector<u16>::const_iterator iter = ids.begin();
for(u32 i = 0; iter != ids.end(); iter++) {
ServerActiveObject *obj = env->getActiveObject(*iter);
// Insert object reference into table
@@ -472,7 +482,7 @@ int ModApiEnvMod::l_set_timeofday(lua_State *L)
// Do it
float timeofday_f = luaL_checknumber(L, 1);
- assert(timeofday_f >= 0.0 && timeofday_f <= 1.0);
+ sanity_check(timeofday_f >= 0.0 && timeofday_f <= 1.0);
int timeofday_mh = (int)(timeofday_f * 24000.0);
// This should be set directly in the environment but currently
// such changes aren't immediately sent to the clients, so call
@@ -530,9 +540,8 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
}
for(int d=1; d<=radius; d++){
- std::list<v3s16> list;
- getFacePositions(list, d);
- for(std::list<v3s16>::iterator i = list.begin();
+ std::vector<v3s16> list = FacePositionCache::getFacePositions(d);
+ for(std::vector<v3s16>::iterator i = list.begin();
i != list.end(); ++i){
v3s16 p = pos + (*i);
content_t c = env->getMap().getNodeNoEx(p).getContent();
@@ -555,30 +564,92 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
v3s16 minp = read_v3s16(L, 1);
v3s16 maxp = read_v3s16(L, 2);
std::set<content_t> filter;
- if(lua_istable(L, 3)){
+ if(lua_istable(L, 3)) {
int table = 3;
lua_pushnil(L);
- while(lua_next(L, table) != 0){
+ while(lua_next(L, table) != 0) {
// key at index -2 and value at index -1
luaL_checktype(L, -1, LUA_TSTRING);
ndef->getIds(lua_tostring(L, -1), filter);
// removes value, keeps key for next iteration
lua_pop(L, 1);
}
- } else if(lua_isstring(L, 3)){
+ } else if(lua_isstring(L, 3)) {
+ ndef->getIds(lua_tostring(L, 3), filter);
+ }
+
+ std::map<content_t, u16> individual_count;
+
+ lua_newtable(L);
+ u64 i = 0;
+ for (s16 x = minp.X; x <= maxp.X; x++)
+ for (s16 y = minp.Y; y <= maxp.Y; y++)
+ for (s16 z = minp.Z; z <= maxp.Z; z++) {
+ v3s16 p(x, y, z);
+ content_t c = env->getMap().getNodeNoEx(p).getContent();
+ if (filter.count(c) != 0) {
+ push_v3s16(L, p);
+ lua_rawseti(L, -2, ++i);
+ individual_count[c]++;
+ }
+ }
+ lua_newtable(L);
+ for (std::set<content_t>::iterator it = filter.begin();
+ it != filter.end(); ++it) {
+ lua_pushnumber(L, individual_count[*it]);
+ lua_setfield(L, -2, ndef->get(*it).name.c_str());
+ }
+ return 2;
+}
+
+// find_nodes_in_area_under_air(minp, maxp, nodenames) -> list of positions
+// nodenames: e.g. {"ignore", "group:tree"} or "default:dirt"
+int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
+{
+ /* Note: A similar but generalized (and therefore slower) version of this
+ * function could be created -- e.g. find_nodes_in_area_under -- which
+ * would accept a node name (or ID?) or list of names that the "above node"
+ * should be.
+ * TODO
+ */
+
+ GET_ENV_PTR;
+
+ INodeDefManager *ndef = getServer(L)->ndef();
+ v3s16 minp = read_v3s16(L, 1);
+ v3s16 maxp = read_v3s16(L, 2);
+ std::set<content_t> filter;
+
+ if (lua_istable(L, 3)) {
+ int table = 3;
+ lua_pushnil(L);
+ while(lua_next(L, table) != 0) {
+ // key at index -2 and value at index -1
+ luaL_checktype(L, -1, LUA_TSTRING);
+ ndef->getIds(lua_tostring(L, -1), filter);
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ }
+ } else if (lua_isstring(L, 3)) {
ndef->getIds(lua_tostring(L, 3), filter);
}
lua_newtable(L);
u64 i = 0;
- for(s16 x = minp.X; x <= maxp.X; x++)
- for(s16 y = minp.Y; y <= maxp.Y; y++)
- for(s16 z = minp.Z; z <= maxp.Z; z++) {
+ for (s16 x = minp.X; x <= maxp.X; x++)
+ for (s16 z = minp.Z; z <= maxp.Z; z++) {
+ s16 y = minp.Y;
v3s16 p(x, y, z);
content_t c = env->getMap().getNodeNoEx(p).getContent();
- if(filter.count(c) != 0) {
- push_v3s16(L, p);
- lua_rawseti(L, -2, ++i);
+ for (; y <= maxp.Y; y++) {
+ v3s16 psurf(x, y + 1, z);
+ content_t csurf = env->getMap().getNodeNoEx(psurf).getContent();
+ if(c != CONTENT_AIR && csurf == CONTENT_AIR &&
+ filter.count(c) != 0) {
+ push_v3s16(L, v3s16(x, y, z));
+ lua_rawseti(L, -2, ++i);
+ }
+ c = csurf;
}
}
return 1;
@@ -702,10 +773,12 @@ int ModApiEnvMod::l_delete_area(lua_State *L)
for (s16 y = bpmin.Y; y <= bpmax.Y; y++)
for (s16 x = bpmin.X; x <= bpmax.X; x++) {
v3s16 bp(x, y, z);
- if (map.deleteBlock(bp))
+ if (map.deleteBlock(bp)) {
+ env->setStaticForActiveObjectsInBlock(bp, false);
event.modified_blocks.insert(bp);
- else
+ } else {
success = false;
+ }
}
map.dispatchEvent(&event);
@@ -872,6 +945,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
API_FCT(set_node_level);
API_FCT(add_node_level);
API_FCT(add_entity);
+ API_FCT(find_nodes_with_meta);
API_FCT(get_meta);
API_FCT(get_node_timer);
API_FCT(get_player_by_name);
@@ -881,6 +955,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
API_FCT(get_gametime);
API_FCT(find_node_near);
API_FCT(find_nodes_in_area);
+ API_FCT(find_nodes_in_area_under_air);
API_FCT(delete_area);
API_FCT(get_perlin);
API_FCT(get_perlin_map);
diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h
index bfaea1c4d..0d4ca788e 100644
--- a/src/script/lua_api/l_env.h
+++ b/src/script/lua_api/l_env.h
@@ -64,7 +64,6 @@ private:
// pos = {x=num, y=num, z=num}
static int l_punch_node(lua_State *L);
-
// get_node_max_level(pos)
// pos = {x=num, y=num, z=num}
static int l_get_node_max_level(lua_State *L);
@@ -81,6 +80,9 @@ private:
// pos = {x=num, y=num, z=num}
static int l_add_node_level(lua_State *L);
+ // find_nodes_with_meta(pos1, pos2)
+ static int l_find_nodes_with_meta(lua_State *L);
+
// get_meta(pos)
static int l_get_meta(lua_State *L);
@@ -119,6 +121,10 @@ private:
// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
static int l_find_nodes_in_area(lua_State *L);
+ // find_surface_nodes_in_area(minp, maxp, nodenames) -> list of positions
+ // nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
+ static int l_find_nodes_in_area_under_air(lua_State *L);
+
// delete_area(p1, p2) -> true/false
static int l_delete_area(lua_State *L);
diff --git a/src/script/lua_api/l_internal.h b/src/script/lua_api/l_internal.h
index 5936ac046..1e40c5c4a 100644
--- a/src/script/lua_api/l_internal.h
+++ b/src/script/lua_api/l_internal.h
@@ -33,13 +33,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define API_FCT(name) registerFunction(L, #name, l_##name,top)
#define ASYNC_API_FCT(name) engine.registerFunction(#name, l_##name)
-#if (defined(WIN32) || defined(_WIN32_WCE))
#define NO_MAP_LOCK_REQUIRED
+
+/*
+#if (defined(WIN32) || defined(_WIN32_WCE))
+ #define NO_MAP_LOCK_REQUIRED
#else
-#include "main.h"
-#include "profiler.h"
-#define NO_MAP_LOCK_REQUIRED \
- ScopeProfiler nolocktime(g_profiler,"Scriptapi: unlockable time",SPT_ADD)
+ #include "profiler.h"
+ #define NO_MAP_LOCK_REQUIRED \
+ ScopeProfiler nolocktime(g_profiler,"Scriptapi: unlockable time",SPT_ADD)
#endif
+*/
#endif /* L_INTERNAL_H_ */
diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp
index 2bed2a255..92311d6fc 100644
--- a/src/script/lua_api/l_mainmenu.cpp
+++ b/src/script/lua_api/l_mainmenu.cpp
@@ -34,7 +34,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "emerge.h"
#include "sound.h"
#include "settings.h"
-#include "main.h" // for g_settings
#include "log.h"
#include "EDriverTypes.h"
@@ -90,7 +89,7 @@ int ModApiMainMenu::getBoolData(lua_State *L, std::string name,bool& valid)
int ModApiMainMenu::l_update_formspec(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
if (engine->m_startgame)
return 0;
@@ -109,21 +108,25 @@ int ModApiMainMenu::l_update_formspec(lua_State *L)
int ModApiMainMenu::l_start(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
//update c++ gamedata from lua table
bool valid = false;
+ MainMenuData *data = engine->m_data;
- engine->m_data->selected_world = getIntegerData(L, "selected_world",valid) -1;
- engine->m_data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid);
- engine->m_data->name = getTextData(L,"playername");
- engine->m_data->password = getTextData(L,"password");
- engine->m_data->address = getTextData(L,"address");
- engine->m_data->port = getTextData(L,"port");
- engine->m_data->serverdescription = getTextData(L,"serverdescription");
- engine->m_data->servername = getTextData(L,"servername");
+ data->selected_world = getIntegerData(L, "selected_world",valid) -1;
+ data->simple_singleplayer_mode = getBoolData(L,"singleplayer",valid);
+ data->do_reconnect = getBoolData(L, "do_reconnect", valid);
+ if (!data->do_reconnect) {
+ data->name = getTextData(L,"playername");
+ data->password = getTextData(L,"password");
+ data->address = getTextData(L,"address");
+ data->port = getTextData(L,"port");
+ }
+ data->serverdescription = getTextData(L,"serverdescription");
+ data->servername = getTextData(L,"servername");
//close menu next time
engine->m_startgame = true;
@@ -134,7 +137,7 @@ int ModApiMainMenu::l_start(lua_State *L)
int ModApiMainMenu::l_close(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
engine->m_kill = true;
return 0;
@@ -144,7 +147,7 @@ int ModApiMainMenu::l_close(lua_State *L)
int ModApiMainMenu::l_set_background(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
std::string backgroundlevel(luaL_checkstring(L, 1));
std::string texturename(luaL_checkstring(L, 2));
@@ -189,7 +192,7 @@ int ModApiMainMenu::l_set_background(lua_State *L)
int ModApiMainMenu::l_set_clouds(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
bool value = lua_toboolean(L,1);
@@ -209,9 +212,9 @@ int ModApiMainMenu::l_get_textlist_index(lua_State *L)
int ModApiMainMenu::l_get_table_index(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
- std::wstring tablename(narrow_to_wide(luaL_checkstring(L, 1)));
+ std::string tablename(luaL_checkstring(L, 1));
GUITable *table = engine->m_menu->getTable(tablename);
s32 selection = table ? table->getSelected() : 0;
@@ -617,7 +620,7 @@ int ModApiMainMenu::l_delete_favorite(lua_State *L)
int ModApiMainMenu::l_show_keys_menu(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
GUIKeyChangeMenu *kmenu
= new GUIKeyChangeMenu( engine->m_device->getGUIEnvironment(),
@@ -644,15 +647,12 @@ int ModApiMainMenu::l_create_world(lua_State *L)
(gameidx < (int) games.size())) {
// Create world if it doesn't exist
- if(!initializeWorld(path, games[gameidx].id)){
+ if (!loadGameConfAndInitWorld(path, games[gameidx])) {
lua_pushstring(L, "Failed to initialize world");
-
- }
- else {
- lua_pushnil(L);
+ } else {
+ lua_pushnil(L);
}
- }
- else {
+ } else {
lua_pushstring(L, "Invalid game index");
}
return 1;
@@ -692,7 +692,7 @@ int ModApiMainMenu::l_delete_world(lua_State *L)
int ModApiMainMenu::l_set_topleft_text(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
std::string text = "";
@@ -758,30 +758,6 @@ int ModApiMainMenu::l_get_texturepath_share(lua_State *L)
}
/******************************************************************************/
-int ModApiMainMenu::l_get_dirlist(lua_State *L)
-{
- const char *path = luaL_checkstring(L, 1);
- bool dironly = lua_toboolean(L, 2);
-
- std::vector<fs::DirListNode> dirlist = fs::GetDirListing(path);
-
- unsigned int index = 1;
- lua_newtable(L);
- int table = lua_gettop(L);
-
- for (unsigned int i=0;i< dirlist.size(); i++) {
- if ((dirlist[i].dir) || (dironly == false)) {
- lua_pushnumber(L,index);
- lua_pushstring(L,dirlist[i].name.c_str());
- lua_settable(L, table);
- index++;
- }
- }
-
- return 1;
-}
-
-/******************************************************************************/
int ModApiMainMenu::l_create_dir(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
@@ -843,7 +819,7 @@ int ModApiMainMenu::l_copy_dir(lua_State *L)
int ModApiMainMenu::l_extract_zip(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine);
const char *zipfile = luaL_checkstring(L, 1);
const char *destination = luaL_checkstring(L, 2);
@@ -860,7 +836,7 @@ int ModApiMainMenu::l_extract_zip(lua_State *L)
return 1;
}
- assert(fs->getFileArchiveCount() > 0);
+ sanity_check(fs->getFileArchiveCount() > 0);
/**********************************************************************/
/* WARNING this is not threadsafe!! */
@@ -931,7 +907,7 @@ int ModApiMainMenu::l_extract_zip(lua_State *L)
int ModApiMainMenu::l_get_mainmenu_path(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
lua_pushstring(L,engine->getScriptDir().c_str());
return 1;
@@ -963,7 +939,7 @@ bool ModApiMainMenu::isMinetestPath(std::string path)
int ModApiMainMenu::l_show_file_open_dialog(lua_State *L)
{
GUIEngine* engine = getGuiEngine(L);
- assert(engine != 0);
+ sanity_check(engine != NULL);
const char *formname= luaL_checkstring(L, 1);
const char *title = luaL_checkstring(L, 2);
@@ -983,7 +959,7 @@ int ModApiMainMenu::l_show_file_open_dialog(lua_State *L)
/******************************************************************************/
int ModApiMainMenu::l_get_version(lua_State *L)
{
- lua_pushstring(L, minetest_version_simple);
+ lua_pushstring(L, g_version_string);
return 1;
}
@@ -1060,10 +1036,32 @@ int ModApiMainMenu::l_get_video_drivers(lua_State *L)
}
/******************************************************************************/
+int ModApiMainMenu::l_get_video_modes(lua_State *L)
+{
+ std::vector<core::vector3d<u32> > videomodes
+ = porting::getSupportedVideoModes();
+
+ lua_newtable(L);
+ for (u32 i = 0; i != videomodes.size(); i++) {
+ lua_newtable(L);
+ lua_pushnumber(L, videomodes[i].X);
+ lua_setfield(L, -2, "w");
+ lua_pushnumber(L, videomodes[i].Y);
+ lua_setfield(L, -2, "h");
+ lua_pushnumber(L, videomodes[i].Z);
+ lua_setfield(L, -2, "depth");
+
+ lua_rawseti(L, -2, i + 1);
+ }
+
+ return 1;
+}
+
+/******************************************************************************/
int ModApiMainMenu::l_gettext(lua_State *L)
{
std::wstring wtext = wstrgettext((std::string) luaL_checkstring(L, 1));
- lua_pushstring(L, wide_to_narrow(wtext).c_str());
+ lua_pushstring(L, wide_to_utf8(wtext).c_str());
return 1;
}
@@ -1118,8 +1116,8 @@ int ModApiMainMenu::l_do_async_callback(lua_State *L)
const char* serialized_param_raw = luaL_checklstring(L, 2, &param_length);
- assert(serialized_func_raw != NULL);
- assert(serialized_param_raw != NULL);
+ sanity_check(serialized_func_raw != NULL);
+ sanity_check(serialized_param_raw != NULL);
std::string serialized_func = std::string(serialized_func_raw, func_length);
std::string serialized_param = std::string(serialized_param_raw, param_length);
@@ -1152,7 +1150,6 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
API_FCT(get_gamepath);
API_FCT(get_texturepath);
API_FCT(get_texturepath_share);
- API_FCT(get_dirlist);
API_FCT(create_dir);
API_FCT(delete_dir);
API_FCT(copy_dir);
@@ -1167,6 +1164,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top)
API_FCT(sound_stop);
API_FCT(gettext);
API_FCT(get_video_drivers);
+ API_FCT(get_video_modes);
API_FCT(get_screen_info);
API_FCT(get_min_supp_proto);
API_FCT(get_max_supp_proto);
@@ -1185,7 +1183,6 @@ void ModApiMainMenu::InitializeAsync(AsyncEngine& engine)
ASYNC_API_FCT(get_gamepath);
ASYNC_API_FCT(get_texturepath);
ASYNC_API_FCT(get_texturepath_share);
- ASYNC_API_FCT(get_dirlist);
ASYNC_API_FCT(create_dir);
ASYNC_API_FCT(delete_dir);
ASYNC_API_FCT(copy_dir);
diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h
index 8b21a93aa..9c1fed272 100644
--- a/src/script/lua_api/l_mainmenu.h
+++ b/src/script/lua_api/l_mainmenu.h
@@ -137,6 +137,8 @@ private:
static int l_get_video_drivers(lua_State *L);
+ static int l_get_video_modes(lua_State *L);
+
//version compatibility
static int l_get_min_supp_proto(lua_State *L);
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp
index d470cef88..d30b68054 100644
--- a/src/script/lua_api/l_mapgen.cpp
+++ b/src/script/lua_api/l_mapgen.cpp
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_vmanip.h"
#include "common/c_converter.h"
#include "common/c_content.h"
+#include "cpp_api/s_security.h"
#include "util/serialize.h"
#include "server.h"
#include "environment.h"
@@ -32,18 +33,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mg_schematic.h"
#include "mapgen_v5.h"
#include "mapgen_v7.h"
+#include "filesys.h"
#include "settings.h"
-#include "main.h"
#include "log.h"
-
struct EnumString ModApiMapgen::es_BiomeTerrainType[] =
{
- {BIOME_TYPE_NORMAL, "normal"},
- {BIOME_TYPE_LIQUID, "liquid"},
- {BIOME_TYPE_NETHER, "nether"},
- {BIOME_TYPE_AETHER, "aether"},
- {BIOME_TYPE_FLAT, "flat"},
+ {BIOME_NORMAL, "normal"},
+ {BIOME_LIQUID, "liquid"},
+ {BIOME_NETHER, "nether"},
+ {BIOME_AETHER, "aether"},
+ {BIOME_FLAT, "flat"},
{0, NULL},
};
@@ -68,10 +68,10 @@ struct EnumString ModApiMapgen::es_MapgenObject[] =
struct EnumString ModApiMapgen::es_OreType[] =
{
- {ORE_TYPE_SCATTER, "scatter"},
- {ORE_TYPE_SHEET, "sheet"},
- {ORE_TYPE_BLOB, "blob"},
- {ORE_TYPE_VEIN, "vein"},
+ {ORE_SCATTER, "scatter"},
+ {ORE_SHEET, "sheet"},
+ {ORE_BLOB, "blob"},
+ {ORE_VEIN, "vein"},
{0, NULL},
};
@@ -85,116 +85,238 @@ struct EnumString ModApiMapgen::es_Rotation[] =
{0, NULL},
};
+struct EnumString ModApiMapgen::es_SchematicFormatType[] =
+{
+ {SCHEM_FMT_HANDLE, "handle"},
+ {SCHEM_FMT_MTS, "mts"},
+ {SCHEM_FMT_LUA, "lua"},
+ {0, NULL},
+};
+
+ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr);
+
+Biome *get_or_load_biome(lua_State *L, int index,
+ BiomeManager *biomemgr);
+Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef);
+size_t get_biome_list(lua_State *L, int index,
+ BiomeManager *biomemgr, std::set<u8> *biome_id_list);
+
+Schematic *get_or_load_schematic(lua_State *L, int index,
+ SchematicManager *schemmgr, StringMap *replace_names);
+Schematic *load_schematic(lua_State *L, int index, INodeDefManager *ndef,
+ StringMap *replace_names);
+Schematic *load_schematic_from_def(lua_State *L, int index,
+ INodeDefManager *ndef, StringMap *replace_names);
+bool read_schematic_def(lua_State *L, int index,
+ Schematic *schem, std::vector<std::string> *names);
+
+bool read_deco_simple(lua_State *L, DecoSimple *deco);
+bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic *deco);
+
///////////////////////////////////////////////////////////////////////////////
+ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr)
+{
+ if (index < 0)
+ index = lua_gettop(L) + 1 + index;
-bool read_schematic(lua_State *L, int index, Schematic *schem,
- INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
+ // If a number, assume this is a handle to an object def
+ if (lua_isnumber(L, index))
+ return objmgr->get(lua_tointeger(L, index));
+
+ // If a string, assume a name is given instead
+ if (lua_isstring(L, index))
+ return objmgr->getByName(lua_tostring(L, index));
+
+ return NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+Schematic *get_or_load_schematic(lua_State *L, int index,
+ SchematicManager *schemmgr, StringMap *replace_names)
{
+ if (index < 0)
+ index = lua_gettop(L) + 1 + index;
+
+ Schematic *schem = (Schematic *)get_objdef(L, index, schemmgr);
+ if (schem)
+ return schem;
+
+ schem = load_schematic(L, index, schemmgr->getNodeDef(),
+ replace_names);
+ if (!schem)
+ return NULL;
+
+ if (schemmgr->add(schem) == OBJDEF_INVALID_HANDLE) {
+ delete schem;
+ return NULL;
+ }
+
+ return schem;
+}
+
+
+Schematic *load_schematic(lua_State *L, int index, INodeDefManager *ndef,
+ StringMap *replace_names)
+{
+ if (index < 0)
+ index = lua_gettop(L) + 1 + index;
+
+ Schematic *schem = NULL;
+
+ if (lua_istable(L, index)) {
+ schem = load_schematic_from_def(L, index, ndef,
+ replace_names);
+ if (!schem) {
+ delete schem;
+ return NULL;
+ }
+ } else if (lua_isnumber(L, index)) {
+ return NULL;
+ } else if (lua_isstring(L, index)) {
+ schem = SchematicManager::create(SCHEMATIC_NORMAL);
+
+ std::string filepath = lua_tostring(L, index);
+ if (!fs::IsPathAbsolute(filepath))
+ filepath = ModApiBase::getCurrentModPath(L) + DIR_DELIM + filepath;
+
+ if (!schem->loadSchematicFromFile(filepath, ndef,
+ replace_names)) {
+ delete schem;
+ return NULL;
+ }
+ }
+
+ return schem;
+}
+
+
+Schematic *load_schematic_from_def(lua_State *L, int index,
+ INodeDefManager *ndef, StringMap *replace_names)
+{
+ Schematic *schem = SchematicManager::create(SCHEMATIC_NORMAL);
+
+ if (!read_schematic_def(L, index, schem, &schem->m_nodenames)) {
+ delete schem;
+ return NULL;
+ }
+
+ size_t num_nodes = schem->m_nodenames.size();
+
+ schem->m_nnlistsizes.push_back(num_nodes);
+
+ if (replace_names) {
+ for (size_t i = 0; i != num_nodes; i++) {
+ StringMap::iterator it = replace_names->find(schem->m_nodenames[i]);
+ if (it != replace_names->end())
+ schem->m_nodenames[i] = it->second;
+ }
+ }
+
+ if (ndef)
+ ndef->pendNodeResolve(schem);
+
+ return schem;
+}
+
+
+bool read_schematic_def(lua_State *L, int index,
+ Schematic *schem, std::vector<std::string> *names)
+{
+ if (!lua_istable(L, index))
+ return false;
+
//// Get schematic size
lua_getfield(L, index, "size");
- v3s16 size = read_v3s16(L, -1);
+ v3s16 size = check_v3s16(L, -1);
lua_pop(L, 1);
+ schem->size = size;
+
//// Get schematic data
lua_getfield(L, index, "data");
luaL_checktype(L, -1, LUA_TTABLE);
- int numnodes = size.X * size.Y * size.Z;
- MapNode *schemdata = new MapNode[numnodes];
- int i = 0;
+ u32 numnodes = size.X * size.Y * size.Z;
+ schem->schemdata = new MapNode[numnodes];
- lua_pushnil(L);
- while (lua_next(L, -2)) {
- if (i >= numnodes) {
- i++;
- lua_pop(L, 1);
+ size_t names_base = names->size();
+ std::map<std::string, content_t> name_id_map;
+
+ u32 i = 0;
+ for (lua_pushnil(L); lua_next(L, -2); i++, lua_pop(L, 1)) {
+ if (i >= numnodes)
continue;
- }
- // same as readnode, except param1 default is MTSCHEM_PROB_CONST
- lua_getfield(L, -1, "name");
- std::string name = luaL_checkstring(L, -1);
- lua_pop(L, 1);
+ //// Read name
+ std::string name;
+ if (!getstringfield(L, -1, "name", name))
+ throw LuaError("Schematic data definition with missing name field");
+ //// Read param1/prob
u8 param1;
- lua_getfield(L, -1, "param1");
- param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS;
- lua_pop(L, 1);
-
- u8 param2;
- lua_getfield(L, -1, "param2");
- param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0;
- lua_pop(L, 1);
-
- std::map<std::string, std::string>::iterator it;
- it = replace_names.find(name);
- if (it != replace_names.end())
- name = it->second;
+ if (!getintfield(L, -1, "param1", param1) &&
+ !getintfield(L, -1, "prob", param1))
+ param1 = MTSCHEM_PROB_ALWAYS_OLD;
+
+ //// Read param2
+ u8 param2 = getintfield_default(L, -1, "param2", 0);
+
+ //// Find or add new nodename-to-ID mapping
+ std::map<std::string, content_t>::iterator it = name_id_map.find(name);
+ content_t name_index;
+ if (it != name_id_map.end()) {
+ name_index = it->second;
+ } else {
+ name_index = names->size() - names_base;
+ name_id_map[name] = name_index;
+ names->push_back(name);
+ }
- schemdata[i] = MapNode(ndef, name, param1, param2);
+ //// Perform probability/force_place fixup on param1
+ param1 >>= 1;
+ if (getboolfield_default(L, -1, "force_place", false))
+ param1 |= MTSCHEM_FORCE_PLACE;
- i++;
- lua_pop(L, 1);
+ //// Actually set the node in the schematic
+ schem->schemdata[i] = MapNode(name_index, param1, param2);
}
if (i != numnodes) {
- errorstream << "read_schematic: incorrect number of "
+ errorstream << "read_schematic_def: incorrect number of "
"nodes provided in raw schematic data (got " << i <<
", expected " << numnodes << ")." << std::endl;
- delete schemdata;
return false;
}
//// Get Y-slice probability values (if present)
- u8 *slice_probs = new u8[size.Y];
- for (i = 0; i != size.Y; i++)
- slice_probs[i] = MTSCHEM_PROB_ALWAYS;
+ schem->slice_probs = new u8[size.Y];
+ for (i = 0; i != (u32) size.Y; i++)
+ schem->slice_probs[i] = MTSCHEM_PROB_ALWAYS;
lua_getfield(L, index, "yslice_prob");
if (lua_istable(L, -1)) {
- lua_pushnil(L);
- while (lua_next(L, -2)) {
- if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) {
- slice_probs[i] = getintfield_default(L, -1,
- "prob", MTSCHEM_PROB_ALWAYS);
- }
- lua_pop(L, 1);
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ u16 ypos;
+ if (!getintfield(L, -1, "ypos", ypos) || (ypos >= size.Y) ||
+ !getintfield(L, -1, "prob", schem->slice_probs[ypos]))
+ continue;
+
+ schem->slice_probs[ypos] >>= 1;
}
}
- // Here, we read the nodes directly from the INodeDefManager - there is no
- // need for pending node resolutions so we'll mark this schematic as updated
- schem->flags = SCHEM_CIDS_UPDATED;
-
- schem->size = size;
- schem->schemdata = schemdata;
- schem->slice_probs = slice_probs;
return true;
}
-bool get_schematic(lua_State *L, int index, Schematic *schem,
- INodeDefManager *ndef, std::map<std::string, std::string> &replace_names)
+void read_schematic_replacements(lua_State *L, int index, StringMap *replace_names)
{
if (index < 0)
index = lua_gettop(L) + 1 + index;
- if (lua_istable(L, index)) {
- return read_schematic(L, index, schem, ndef, replace_names);
- } else if (lua_isstring(L, index)) {
- const char *filename = lua_tostring(L, index);
- return schem->loadSchematicFromFile(filename, ndef, replace_names);
- } else {
- return false;
- }
-}
-
-
-void read_schematic_replacements(lua_State *L,
- std::map<std::string, std::string> &replace_names, int index)
-{
lua_pushnil(L);
while (lua_next(L, index)) {
std::string replace_from;
@@ -213,11 +335,119 @@ void read_schematic_replacements(lua_State *L,
replace_to = lua_tostring(L, -1);
}
- replace_names[replace_from] = replace_to;
+ replace_names->insert(std::make_pair(replace_from, replace_to));
lua_pop(L, 1);
}
}
+///////////////////////////////////////////////////////////////////////////////
+
+Biome *get_or_load_biome(lua_State *L, int index, BiomeManager *biomemgr)
+{
+ if (index < 0)
+ index = lua_gettop(L) + 1 + index;
+
+ Biome *biome = (Biome *)get_objdef(L, index, biomemgr);
+ if (biome)
+ return biome;
+
+ biome = read_biome_def(L, index, biomemgr->getNodeDef());
+ if (!biome)
+ return NULL;
+
+ if (biomemgr->add(biome) == OBJDEF_INVALID_HANDLE) {
+ delete biome;
+ return NULL;
+ }
+
+ return biome;
+}
+
+
+Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef)
+{
+ if (!lua_istable(L, index))
+ return NULL;
+
+ BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
+ ModApiMapgen::es_BiomeTerrainType, BIOME_NORMAL);
+ Biome *b = BiomeManager::create(biometype);
+
+ b->name = getstringfield_default(L, index, "name", "");
+ b->depth_top = getintfield_default(L, index, "depth_top", 0);
+ b->depth_filler = getintfield_default(L, index, "depth_filler", -31000);
+ b->depth_water_top = getintfield_default(L, index, "depth_water_top", 0);
+ b->y_min = getintfield_default(L, index, "y_min", -31000);
+ b->y_max = getintfield_default(L, index, "y_max", 31000);
+ b->heat_point = getfloatfield_default(L, index, "heat_point", 0.f);
+ b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f);
+ b->flags = 0; //reserved
+
+ std::vector<std::string> &nn = b->m_nodenames;
+ nn.push_back(getstringfield_default(L, index, "node_top", ""));
+ nn.push_back(getstringfield_default(L, index, "node_filler", ""));
+ nn.push_back(getstringfield_default(L, index, "node_stone", ""));
+ nn.push_back(getstringfield_default(L, index, "node_water_top", ""));
+ nn.push_back(getstringfield_default(L, index, "node_water", ""));
+ nn.push_back(getstringfield_default(L, index, "node_river_water", ""));
+ nn.push_back(getstringfield_default(L, index, "node_dust", ""));
+ ndef->pendNodeResolve(b);
+
+ return b;
+}
+
+
+size_t get_biome_list(lua_State *L, int index,
+ BiomeManager *biomemgr, std::set<u8> *biome_id_list)
+{
+ if (index < 0)
+ index = lua_gettop(L) + 1 + index;
+
+ if (lua_isnil(L, index))
+ return 0;
+
+ bool is_single = true;
+ if (lua_istable(L, index)) {
+ lua_getfield(L, index, "name");
+ is_single = !lua_isnil(L, -1);
+ lua_pop(L, 1);
+ }
+
+ if (is_single) {
+ Biome *biome = get_or_load_biome(L, index, biomemgr);
+ if (!biome) {
+ errorstream << "get_biome_list: failed to get biome '"
+ << (lua_isstring(L, index) ? lua_tostring(L, index) : "")
+ << "'." << std::endl;
+ return 1;
+ }
+
+ biome_id_list->insert(biome->index);
+ return 0;
+ }
+
+ // returns number of failed resolutions
+ size_t fail_count = 0;
+ size_t count = 0;
+
+ for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1)) {
+ count++;
+ Biome *biome = get_or_load_biome(L, -1, biomemgr);
+ if (!biome) {
+ fail_count++;
+ errorstream << "get_biome_list: failed to get biome '"
+ << (lua_isstring(L, -1) ? lua_tostring(L, -1) : "")
+ << "'" << std::endl;
+ continue;
+ }
+
+ biome_id_list->insert(biome->index);
+ }
+
+ return fail_count;
+}
+
+///////////////////////////////////////////////////////////////////////////////
// get_mapgen_object(objectname)
// returns the requested object used during map generation
@@ -239,92 +469,98 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L)
size_t maplen = mg->csize.X * mg->csize.Z;
switch (mgobj) {
- case MGOBJ_VMANIP: {
- MMVManip *vm = mg->vm;
+ case MGOBJ_VMANIP: {
+ MMVManip *vm = mg->vm;
- // VoxelManip object
- LuaVoxelManip *o = new LuaVoxelManip(vm, true);
- *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
- luaL_getmetatable(L, "VoxelManip");
- lua_setmetatable(L, -2);
+ // VoxelManip object
+ LuaVoxelManip *o = new LuaVoxelManip(vm, true);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, "VoxelManip");
+ lua_setmetatable(L, -2);
- // emerged min pos
- push_v3s16(L, vm->m_area.MinEdge);
+ // emerged min pos
+ push_v3s16(L, vm->m_area.MinEdge);
- // emerged max pos
- push_v3s16(L, vm->m_area.MaxEdge);
+ // emerged max pos
+ push_v3s16(L, vm->m_area.MaxEdge);
- return 3;
+ return 3;
+ }
+ case MGOBJ_HEIGHTMAP: {
+ if (!mg->heightmap)
+ return 0;
+
+ lua_newtable(L);
+ for (size_t i = 0; i != maplen; i++) {
+ lua_pushinteger(L, mg->heightmap[i]);
+ lua_rawseti(L, -2, i + 1);
}
- case MGOBJ_HEIGHTMAP: {
- if (!mg->heightmap)
- return 0;
-
- lua_newtable(L);
- for (size_t i = 0; i != maplen; i++) {
- lua_pushinteger(L, mg->heightmap[i]);
- lua_rawseti(L, -2, i + 1);
- }
- return 1;
+ return 1;
+ }
+ case MGOBJ_BIOMEMAP: {
+ if (!mg->biomemap)
+ return 0;
+
+ lua_newtable(L);
+ for (size_t i = 0; i != maplen; i++) {
+ lua_pushinteger(L, mg->biomemap[i]);
+ lua_rawseti(L, -2, i + 1);
}
- case MGOBJ_BIOMEMAP: {
- if (!mg->biomemap)
- return 0;
- lua_newtable(L);
- for (size_t i = 0; i != maplen; i++) {
- lua_pushinteger(L, mg->biomemap[i]);
- lua_rawseti(L, -2, i + 1);
- }
-
- return 1;
+ return 1;
+ }
+ case MGOBJ_HEATMAP: {
+ if (!mg->heatmap)
+ return 0;
+
+ lua_newtable(L);
+ for (size_t i = 0; i != maplen; i++) {
+ lua_pushnumber(L, mg->heatmap[i]);
+ lua_rawseti(L, -2, i + 1);
}
- case MGOBJ_HEATMAP: { // Mapgen V7 specific objects
- case MGOBJ_HUMIDMAP:
- if (strcmp(emerge->params.mg_name.c_str(), "v7"))
- return 0;
-
- MapgenV7 *mgv7 = (MapgenV7 *)mg;
- float *arr = (mgobj == MGOBJ_HEATMAP) ?
- mgv7->noise_heat->result : mgv7->noise_humidity->result;
- if (!arr)
- return 0;
+ return 1;
+ }
- lua_newtable(L);
- for (size_t i = 0; i != maplen; i++) {
- lua_pushnumber(L, arr[i]);
- lua_rawseti(L, -2, i + 1);
- }
+ case MGOBJ_HUMIDMAP: {
+ if (!mg->humidmap)
+ return 0;
- return 1;
+ lua_newtable(L);
+ for (size_t i = 0; i != maplen; i++) {
+ lua_pushnumber(L, mg->humidmap[i]);
+ lua_rawseti(L, -2, i + 1);
}
- case MGOBJ_GENNOTIFY: {
- std::map<std::string, std::vector<v3s16> >event_map;
- std::map<std::string, std::vector<v3s16> >::iterator it;
- mg->gennotify.getEvents(event_map);
+ return 1;
+ }
+ case MGOBJ_GENNOTIFY: {
+ std::map<std::string, std::vector<v3s16> >event_map;
+ std::map<std::string, std::vector<v3s16> >::iterator it;
- lua_newtable(L);
- for (it = event_map.begin(); it != event_map.end(); ++it) {
- lua_newtable(L);
+ mg->gennotify.getEvents(event_map);
- for (size_t j = 0; j != it->second.size(); j++) {
- push_v3s16(L, it->second[j]);
- lua_rawseti(L, -2, j + 1);
- }
+ lua_newtable(L);
+ for (it = event_map.begin(); it != event_map.end(); ++it) {
+ lua_newtable(L);
- lua_setfield(L, -2, it->first.c_str());
+ for (size_t j = 0; j != it->second.size(); j++) {
+ push_v3s16(L, it->second[j]);
+ lua_rawseti(L, -2, j + 1);
}
- return 1;
+ lua_setfield(L, -2, it->first.c_str());
}
+
+ return 1;
+ }
}
return 0;
}
+
int ModApiMapgen::l_get_mapgen_params(lua_State *L)
{
MapgenParams *params = &getServer(L)->getEmergeManager()->params;
@@ -350,6 +586,7 @@ int ModApiMapgen::l_get_mapgen_params(lua_State *L)
return 1;
}
+
// set_mapgen_params(params)
// set mapgen parameters
int ModApiMapgen::l_set_mapgen_params(lua_State *L)
@@ -389,6 +626,7 @@ int ModApiMapgen::l_set_mapgen_params(lua_State *L)
return 0;
}
+
// set_noiseparams(name, noiseparams, set_default)
// set global config values for noise parameters
int ModApiMapgen::l_set_noiseparams(lua_State *L)
@@ -406,6 +644,21 @@ int ModApiMapgen::l_set_noiseparams(lua_State *L)
return 0;
}
+
+// get_noiseparams(name)
+int ModApiMapgen::l_get_noiseparams(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+
+ NoiseParams np;
+ if (!g_settings->getNoiseParams(name, np))
+ return 0;
+
+ push_noiseparams(L, &np);
+ return 1;
+}
+
+
// set_gen_notify(flags, {deco_id_table})
int ModApiMapgen::l_set_gen_notify(lua_State *L)
{
@@ -421,7 +674,7 @@ int ModApiMapgen::l_set_gen_notify(lua_State *L)
lua_pushnil(L);
while (lua_next(L, 2)) {
if (lua_isnumber(L, -1))
- emerge->gen_notify_on_deco_ids.insert(lua_tonumber(L, -1));
+ emerge->gen_notify_on_deco_ids.insert((u32)lua_tonumber(L, -1));
lua_pop(L, 1);
}
}
@@ -429,6 +682,26 @@ int ModApiMapgen::l_set_gen_notify(lua_State *L)
return 0;
}
+
+// get_gen_notify()
+int ModApiMapgen::l_get_gen_notify(lua_State *L)
+{
+ EmergeManager *emerge = getServer(L)->getEmergeManager();
+ push_flags_string(L, flagdesc_gennotify, emerge->gen_notify_on,
+ emerge->gen_notify_on);
+
+ lua_newtable(L);
+ int i = 1;
+ for (std::set<u32>::iterator it = emerge->gen_notify_on_deco_ids.begin();
+ it != emerge->gen_notify_on_deco_ids.end(); ++it) {
+ lua_pushnumber(L, *it);
+ lua_rawseti(L, -2, i);
+ i++;
+ }
+ return 2;
+}
+
+
// register_biome({lots of stuff})
int ModApiMapgen::l_register_biome(lua_State *L)
{
@@ -438,66 +711,20 @@ int ModApiMapgen::l_register_biome(lua_State *L)
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
- enum BiomeType biometype = (BiomeType)getenumfield(L, index, "type",
- es_BiomeTerrainType, BIOME_TYPE_NORMAL);
- Biome *b = bmgr->create(biometype);
-
- b->name = getstringfield_default(L, index, "name", "");
- b->depth_top = getintfield_default(L, index, "depth_top", 1);
- b->depth_filler = getintfield_default(L, index, "depth_filler", 3);
- b->height_shore = getintfield_default(L, index, "height_shore", 3);
- b->depth_water_top = getintfield_default(L, index, "depth_water_top", 0);
- b->y_min = getintfield_default(L, index, "y_min", -31000);
- b->y_max = getintfield_default(L, index, "y_max", 31000);
- b->heat_point = getfloatfield_default(L, index, "heat_point", 0.f);
- b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f);
- b->flags = 0; //reserved
+ Biome *biome = read_biome_def(L, index, ndef);
+ if (!biome)
+ return 0;
- u32 id = bmgr->add(b);
- if (id == (u32)-1) {
- delete b;
+ ObjDefHandle handle = bmgr->add(biome);
+ if (handle == OBJDEF_INVALID_HANDLE) {
+ delete biome;
return 0;
}
- NodeResolveInfo *nri = new NodeResolveInfo(b);
- std::list<std::string> &nnames = nri->nodenames;
- nnames.push_back(getstringfield_default(L, index, "node_top", ""));
- nnames.push_back(getstringfield_default(L, index, "node_filler", ""));
- nnames.push_back(getstringfield_default(L, index, "node_shore_top", ""));
- nnames.push_back(getstringfield_default(L, index, "node_shore_filler", ""));
- nnames.push_back(getstringfield_default(L, index, "node_underwater", ""));
- nnames.push_back(getstringfield_default(L, index, "node_stone", ""));
- nnames.push_back(getstringfield_default(L, index, "node_water_top", ""));
- nnames.push_back(getstringfield_default(L, index, "node_water", ""));
- nnames.push_back(getstringfield_default(L, index, "node_dust", ""));
- ndef->pendNodeResolve(nri);
-
- verbosestream << "register_biome: " << b->name << std::endl;
-
- lua_pushinteger(L, id);
+ lua_pushinteger(L, handle);
return 1;
}
-int ModApiMapgen::l_clear_registered_biomes(lua_State *L)
-{
- BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
- bmgr->clear();
- return 0;
-}
-
-int ModApiMapgen::l_clear_registered_decorations(lua_State *L)
-{
- DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr;
- dmgr->clear();
- return 0;
-}
-
-int ModApiMapgen::l_clear_registered_ores(lua_State *L)
-{
- OreManager *omgr = getServer(L)->getEmergeManager()->oremgr;
- omgr->clear();
- return 0;
-}
// register_decoration({lots of stuff})
int ModApiMapgen::l_register_decoration(lua_State *L)
@@ -508,6 +735,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr;
BiomeManager *biomemgr = getServer(L)->getEmergeManager()->biomemgr;
+ SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
enum DecorationType decotype = (DecorationType)getenumfield(L, index,
"deco_type", es_DecorationType, -1);
@@ -515,7 +743,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
Decoration *deco = decomgr->create(decotype);
if (!deco) {
errorstream << "register_decoration: decoration placement type "
- << decotype << " not implemented";
+ << decotype << " not implemented" << std::endl;
return 0;
}
@@ -531,15 +759,11 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
return 0;
}
- NodeResolveInfo *nri = new NodeResolveInfo(deco);
-
//// Get node name(s) to place decoration on
- std::vector<const char *> place_on_names;
- getstringlistfield(L, index, "place_on", place_on_names);
- nri->nodelistinfo.push_back(NodeListInfo(place_on_names.size()));
- for (size_t i = 0; i != place_on_names.size(); i++)
- nri->nodenames.push_back(place_on_names[i]);
+ size_t nread = getstringlistfield(L, index, "place_on", &deco->m_nodenames);
+ deco->m_nnlistsizes.push_back(nread);
+ //// Get decoration flags
getflagsfield(L, index, "flags", flagdesc_deco, &deco->flags, NULL);
//// Get NoiseParams to define how decoration is placed
@@ -549,51 +773,45 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
lua_pop(L, 1);
//// Get biomes associated with this decoration (if any)
- std::vector<const char *> biome_list;
- getstringlistfield(L, index, "biomes", biome_list);
- for (size_t i = 0; i != biome_list.size(); i++) {
- Biome *b = (Biome *)biomemgr->getByName(biome_list[i]);
- if (!b)
- continue;
-
- deco->biomes.insert(b->id);
- }
+ lua_getfield(L, index, "biomes");
+ if (get_biome_list(L, -1, biomemgr, &deco->biomes))
+ errorstream << "register_decoration: couldn't get all biomes " << std::endl;
+ lua_pop(L, 1);
//// Handle decoration type-specific parameters
bool success = false;
switch (decotype) {
- case DECO_SIMPLE:
- success = regDecoSimple(L, nri, (DecoSimple *)deco);
- break;
- case DECO_SCHEMATIC:
- success = regDecoSchematic(L, ndef, (DecoSchematic *)deco);
- break;
- case DECO_LSYSTEM:
- break;
+ case DECO_SIMPLE:
+ success = read_deco_simple(L, (DecoSimple *)deco);
+ break;
+ case DECO_SCHEMATIC:
+ success = read_deco_schematic(L, schemmgr, (DecoSchematic *)deco);
+ break;
+ case DECO_LSYSTEM:
+ break;
}
- ndef->pendNodeResolve(nri);
-
if (!success) {
delete deco;
return 0;
}
- u32 id = decomgr->add(deco);
- if (id == (u32)-1) {
+ ndef->pendNodeResolve(deco);
+
+ ObjDefHandle handle = decomgr->add(deco);
+ if (handle == OBJDEF_INVALID_HANDLE) {
delete deco;
return 0;
}
- verbosestream << "register_decoration: " << deco->name << std::endl;
-
- lua_pushinteger(L, id);
+ lua_pushinteger(L, handle);
return 1;
}
-bool ModApiMapgen::regDecoSimple(lua_State *L,
- NodeResolveInfo *nri, DecoSimple *deco)
+
+bool read_deco_simple(lua_State *L, DecoSimple *deco)
{
+ size_t nnames;
int index = 1;
deco->deco_height = getintfield_default(L, index, "height", 1);
@@ -606,60 +824,48 @@ bool ModApiMapgen::regDecoSimple(lua_State *L,
return false;
}
- std::vector<const char *> deco_names;
- getstringlistfield(L, index, "decoration", deco_names);
- if (deco_names.size() == 0) {
+ nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames);
+ deco->m_nnlistsizes.push_back(nnames);
+ if (nnames == 0) {
errorstream << "register_decoration: no decoration nodes "
"defined" << std::endl;
return false;
}
- nri->nodelistinfo.push_back(NodeListInfo(deco_names.size()));
- for (size_t i = 0; i != deco_names.size(); i++)
- nri->nodenames.push_back(deco_names[i]);
- std::vector<const char *> spawnby_names;
- getstringlistfield(L, index, "spawn_by", spawnby_names);
- if (deco->nspawnby != -1 && spawnby_names.size() == 0) {
+ nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames);
+ deco->m_nnlistsizes.push_back(nnames);
+ if (nnames == 0 && deco->nspawnby != -1) {
errorstream << "register_decoration: no spawn_by nodes defined,"
" but num_spawn_by specified" << std::endl;
return false;
}
- nri->nodelistinfo.push_back(NodeListInfo(spawnby_names.size()));
- for (size_t i = 0; i != spawnby_names.size(); i++)
- nri->nodenames.push_back(spawnby_names[i]);
return true;
}
-bool ModApiMapgen::regDecoSchematic(lua_State *L, INodeDefManager *ndef,
- DecoSchematic *deco)
+
+bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic *deco)
{
int index = 1;
deco->rotation = (Rotation)getenumfield(L, index, "rotation",
- es_Rotation, ROTATE_0);
+ ModApiMapgen::es_Rotation, ROTATE_0);
- std::map<std::string, std::string> replace_names;
+ StringMap replace_names;
lua_getfield(L, index, "replacements");
if (lua_istable(L, -1))
- read_schematic_replacements(L, replace_names, lua_gettop(L));
+ read_schematic_replacements(L, -1, &replace_names);
lua_pop(L, 1);
- // TODO(hmmmm): get a ref from registered schematics
- Schematic *schem = new Schematic;
lua_getfield(L, index, "schematic");
- if (!get_schematic(L, -1, schem, ndef, replace_names)) {
- lua_pop(L, 1);
- delete schem;
- return false;
- }
+ Schematic *schem = get_or_load_schematic(L, -1, schemmgr, &replace_names);
lua_pop(L, 1);
deco->schematic = schem;
-
- return true;
+ return schem != NULL;
}
+
// register_ore({lots of stuff})
int ModApiMapgen::l_register_ore(lua_State *L)
{
@@ -667,10 +873,11 @@ int ModApiMapgen::l_register_ore(lua_State *L)
luaL_checktype(L, index, LUA_TTABLE);
INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+ BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
OreManager *oremgr = getServer(L)->getEmergeManager()->oremgr;
enum OreType oretype = (OreType)getenumfield(L, index,
- "ore_type", es_OreType, ORE_TYPE_SCATTER);
+ "ore_type", es_OreType, ORE_SCATTER);
Ore *ore = oremgr->create(oretype);
if (!ore) {
errorstream << "register_ore: ore_type " << oretype << " not implemented";
@@ -686,6 +893,7 @@ int ModApiMapgen::l_register_ore(lua_State *L)
ore->noise = NULL;
ore->flags = 0;
+ //// Get y_min/y_max
warn_if_field_exists(L, index, "height_min",
"Deprecated: new name is \"y_min\".");
warn_if_field_exists(L, index, "height_max",
@@ -708,8 +916,16 @@ int ModApiMapgen::l_register_ore(lua_State *L)
return 0;
}
+ //// Get flags
getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL);
+ //// Get biomes associated with this decoration (if any)
+ lua_getfield(L, index, "biomes");
+ if (get_biome_list(L, -1, bmgr, &ore->biomes))
+ errorstream << "register_ore: couldn't get all biomes " << std::endl;
+ lua_pop(L, 1);
+
+ //// Get noise parameters if needed
lua_getfield(L, index, "noise_params");
if (read_noiseparams(L, -1, &ore->np)) {
ore->flags |= OREFLAG_USE_NOISE;
@@ -721,45 +937,152 @@ int ModApiMapgen::l_register_ore(lua_State *L)
}
lua_pop(L, 1);
- if (oretype == ORE_TYPE_VEIN) {
+ if (oretype == ORE_VEIN) {
OreVein *orevein = (OreVein *)ore;
orevein->random_factor = getfloatfield_default(L, index,
"random_factor", 1.f);
}
- u32 id = oremgr->add(ore);
- if (id == (u32)-1) {
+ ObjDefHandle handle = oremgr->add(ore);
+ if (handle == OBJDEF_INVALID_HANDLE) {
delete ore;
return 0;
}
- NodeResolveInfo *nri = new NodeResolveInfo(ore);
- nri->nodenames.push_back(getstringfield_default(L, index, "ore", ""));
+ ore->m_nodenames.push_back(getstringfield_default(L, index, "ore", ""));
+
+ size_t nnames = getstringlistfield(L, index, "wherein", &ore->m_nodenames);
+ ore->m_nnlistsizes.push_back(nnames);
+
+ ndef->pendNodeResolve(ore);
+
+ lua_pushinteger(L, handle);
+ return 1;
+}
+
- std::vector<const char *> wherein_names;
- getstringlistfield(L, index, "wherein", wherein_names);
- nri->nodelistinfo.push_back(NodeListInfo(wherein_names.size()));
- for (size_t i = 0; i != wherein_names.size(); i++)
- nri->nodenames.push_back(wherein_names[i]);
+// register_schematic({schematic}, replacements={})
+int ModApiMapgen::l_register_schematic(lua_State *L)
+{
+ SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
+
+ StringMap replace_names;
+ if (lua_istable(L, 2))
+ read_schematic_replacements(L, 2, &replace_names);
- ndef->pendNodeResolve(nri);
+ Schematic *schem = load_schematic(L, 1, schemmgr->getNodeDef(),
+ &replace_names);
+ if (!schem)
+ return 0;
- verbosestream << "register_ore: " << ore->name << std::endl;
+ ObjDefHandle handle = schemmgr->add(schem);
+ if (handle == OBJDEF_INVALID_HANDLE) {
+ delete schem;
+ return 0;
+ }
- lua_pushinteger(L, id);
+ lua_pushinteger(L, handle);
return 1;
}
-// create_schematic(p1, p2, probability_list, filename)
+
+// clear_registered_biomes()
+int ModApiMapgen::l_clear_registered_biomes(lua_State *L)
+{
+ BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr;
+ bmgr->clear();
+ return 0;
+}
+
+
+// clear_registered_decorations()
+int ModApiMapgen::l_clear_registered_decorations(lua_State *L)
+{
+ DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr;
+ dmgr->clear();
+ return 0;
+}
+
+
+// clear_registered_ores()
+int ModApiMapgen::l_clear_registered_ores(lua_State *L)
+{
+ OreManager *omgr = getServer(L)->getEmergeManager()->oremgr;
+ omgr->clear();
+ return 0;
+}
+
+
+// clear_registered_schematics()
+int ModApiMapgen::l_clear_registered_schematics(lua_State *L)
+{
+ SchematicManager *smgr = getServer(L)->getEmergeManager()->schemmgr;
+ smgr->clear();
+ return 0;
+}
+
+
+// generate_ores(vm, p1, p2, [ore_id])
+int ModApiMapgen::l_generate_ores(lua_State *L)
+{
+ EmergeManager *emerge = getServer(L)->getEmergeManager();
+
+ Mapgen mg;
+ mg.seed = emerge->params.seed;
+ mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
+ mg.ndef = getServer(L)->getNodeDefManager();
+
+ v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) :
+ mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE;
+ v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) :
+ mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE;
+ sortBoxVerticies(pmin, pmax);
+
+ u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed);
+
+ emerge->oremgr->placeAllOres(&mg, blockseed, pmin, pmax);
+
+ return 0;
+}
+
+
+// generate_decorations(vm, p1, p2, [deco_id])
+int ModApiMapgen::l_generate_decorations(lua_State *L)
+{
+ EmergeManager *emerge = getServer(L)->getEmergeManager();
+
+ Mapgen mg;
+ mg.seed = emerge->params.seed;
+ mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
+ mg.ndef = getServer(L)->getNodeDefManager();
+
+ v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) :
+ mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE;
+ v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) :
+ mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE;
+ sortBoxVerticies(pmin, pmax);
+
+ u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed);
+
+ emerge->decomgr->placeAllDecos(&mg, blockseed, pmin, pmax);
+
+ return 0;
+}
+
+
+// create_schematic(p1, p2, probability_list, filename, y_slice_prob_list)
int ModApiMapgen::l_create_schematic(lua_State *L)
{
- Schematic schem;
+ INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+
+ const char *filename = luaL_checkstring(L, 4);
+ CHECK_SECURE_PATH_OPTIONAL(L, filename);
Map *map = &(getEnv(L)->getMap());
- INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+ Schematic schem;
- v3s16 p1 = read_v3s16(L, 1);
- v3s16 p2 = read_v3s16(L, 2);
+ v3s16 p1 = check_v3s16(L, 1);
+ v3s16 p2 = check_v3s16(L, 2);
sortBoxVerticies(p1, p2);
std::vector<std::pair<v3s16, u8> > prob_list;
@@ -768,7 +1091,7 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
while (lua_next(L, 3)) {
if (lua_istable(L, -1)) {
lua_getfield(L, -1, "pos");
- v3s16 pos = read_v3s16(L, -1);
+ v3s16 pos = check_v3s16(L, -1);
lua_pop(L, 1);
u8 prob = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS);
@@ -793,8 +1116,6 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
}
}
- const char *filename = luaL_checkstring(L, 4);
-
if (!schem.getSchematicFromMap(map, p1, p2)) {
errorstream << "create_schematic: failed to get schematic "
"from map" << std::endl;
@@ -807,60 +1128,25 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
actionstream << "create_schematic: saved schematic file '"
<< filename << "'." << std::endl;
+ lua_pushboolean(L, true);
return 1;
}
-// generate_ores(vm, [ore_id])
-int ModApiMapgen::l_generate_ores(lua_State *L)
-{
- EmergeManager *emerge = getServer(L)->getEmergeManager();
-
- Mapgen mg;
- mg.seed = emerge->params.seed;
- mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
- mg.ndef = getServer(L)->getNodeDefManager();
-
- u32 blockseed = Mapgen::getBlockSeed(mg.vm->m_area.MinEdge, mg.seed);
-
- emerge->oremgr->placeAllOres(&mg, blockseed,
- mg.vm->m_area.MinEdge, mg.vm->m_area.MaxEdge);
-
- return 0;
-}
-
-// generate_decorations(vm, [deco_id])
-int ModApiMapgen::l_generate_decorations(lua_State *L)
-{
- EmergeManager *emerge = getServer(L)->getEmergeManager();
-
- Mapgen mg;
- mg.seed = emerge->params.seed;
- mg.vm = LuaVoxelManip::checkobject(L, 1)->vm;
- mg.ndef = getServer(L)->getNodeDefManager();
-
- u32 blockseed = Mapgen::getBlockSeed(mg.vm->m_area.MinEdge, mg.seed);
-
- emerge->decomgr->placeAllDecos(&mg, blockseed,
- mg.vm->m_area.MinEdge, mg.vm->m_area.MaxEdge);
-
- return 0;
-}
// place_schematic(p, schematic, rotation, replacement)
int ModApiMapgen::l_place_schematic(lua_State *L)
{
- Schematic schem;
-
Map *map = &(getEnv(L)->getMap());
- INodeDefManager *ndef = getServer(L)->getNodeDefManager();
+ SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
//// Read position
- v3s16 p = read_v3s16(L, 1);
+ v3s16 p = check_v3s16(L, 1);
//// Read rotation
int rot = ROTATE_0;
- if (lua_isstring(L, 3))
- string_to_enum(es_Rotation, rot, std::string(lua_tostring(L, 3)));
+ const char *enumstr = lua_tostring(L, 3);
+ if (enumstr)
+ string_to_enum(es_Rotation, rot, std::string(enumstr));
//// Read force placement
bool force_placement = true;
@@ -868,21 +1154,73 @@ int ModApiMapgen::l_place_schematic(lua_State *L)
force_placement = lua_toboolean(L, 5);
//// Read node replacements
- std::map<std::string, std::string> replace_names;
+ StringMap replace_names;
if (lua_istable(L, 4))
- read_schematic_replacements(L, replace_names, 4);
+ read_schematic_replacements(L, 4, &replace_names);
//// Read schematic
- if (!get_schematic(L, 2, &schem, ndef, replace_names)) {
+ Schematic *schem = get_or_load_schematic(L, 2, schemmgr, &replace_names);
+ if (!schem) {
errorstream << "place_schematic: failed to get schematic" << std::endl;
return 0;
}
- schem.placeStructure(map, p, 0, (Rotation)rot, force_placement, ndef);
+ schem->placeStructure(map, p, 0, (Rotation)rot, force_placement);
+
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+// serialize_schematic(schematic, format, options={...})
+int ModApiMapgen::l_serialize_schematic(lua_State *L)
+{
+ SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
+
+ //// Read options
+ bool use_comments = getboolfield_default(L, 3, "lua_use_comments", false);
+ u32 indent_spaces = getintfield_default(L, 3, "lua_num_indent_spaces", 0);
+
+ //// Get schematic
+ bool was_loaded = false;
+ Schematic *schem = (Schematic *)get_objdef(L, 1, schemmgr);
+ if (!schem) {
+ schem = load_schematic(L, 1, NULL, NULL);
+ was_loaded = true;
+ }
+ if (!schem) {
+ errorstream << "serialize_schematic: failed to get schematic" << std::endl;
+ return 0;
+ }
+
+ //// Read format of definition to save as
+ int schem_format = SCHEM_FMT_MTS;
+ const char *enumstr = lua_tostring(L, 2);
+ if (enumstr)
+ string_to_enum(es_SchematicFormatType, schem_format, std::string(enumstr));
+
+ //// Serialize to binary string
+ std::ostringstream os(std::ios_base::binary);
+ switch (schem_format) {
+ case SCHEM_FMT_MTS:
+ schem->serializeToMts(&os, schem->m_nodenames);
+ break;
+ case SCHEM_FMT_LUA:
+ schem->serializeToLua(&os, schem->m_nodenames,
+ use_comments, indent_spaces);
+ break;
+ default:
+ return 0;
+ }
+
+ if (was_loaded)
+ delete schem;
+ std::string ser = os.str();
+ lua_pushlstring(L, ser.c_str(), ser.length());
return 1;
}
+
void ModApiMapgen::Initialize(lua_State *L, int top)
{
API_FCT(get_mapgen_object);
@@ -890,19 +1228,23 @@ void ModApiMapgen::Initialize(lua_State *L, int top)
API_FCT(get_mapgen_params);
API_FCT(set_mapgen_params);
API_FCT(set_noiseparams);
+ API_FCT(get_noiseparams);
API_FCT(set_gen_notify);
+ API_FCT(get_gen_notify);
API_FCT(register_biome);
API_FCT(register_decoration);
API_FCT(register_ore);
+ API_FCT(register_schematic);
API_FCT(clear_registered_biomes);
API_FCT(clear_registered_decorations);
API_FCT(clear_registered_ores);
+ API_FCT(clear_registered_schematics);
API_FCT(generate_ores);
API_FCT(generate_decorations);
-
API_FCT(create_schematic);
API_FCT(place_schematic);
+ API_FCT(serialize_schematic);
}
diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h
index e17d1b85a..7440d1285 100644
--- a/src/script/lua_api/l_mapgen.h
+++ b/src/script/lua_api/l_mapgen.h
@@ -22,11 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_base.h"
-class INodeDefManager;
-struct NodeResolveInfo;
-class DecoSimple;
-class DecoSchematic;
-
class ModApiMapgen : public ModApiBase {
private:
// get_mapgen_object(objectname)
@@ -44,9 +39,15 @@ private:
// set_noiseparam_defaults(name, noiseparams, set_default)
static int l_set_noiseparams(lua_State *L);
+ // get_noiseparam_defaults(name)
+ static int l_get_noiseparams(lua_State *L);
+
// set_gen_notify(flagstring)
static int l_set_gen_notify(lua_State *L);
+ // set_gen_notify(flagstring)
+ static int l_get_gen_notify(lua_State *L);
+
// register_biome({lots of stuff})
static int l_register_biome(lua_State *L);
@@ -56,16 +57,22 @@ private:
// register_ore({lots of stuff})
static int l_register_ore(lua_State *L);
+ // register_schematic({schematic}, replacements={})
+ static int l_register_schematic(lua_State *L);
+
// clear_registered_biomes()
static int l_clear_registered_biomes(lua_State *L);
// clear_registered_decorations()
static int l_clear_registered_decorations(lua_State *L);
- // generate_ores(vm)
+ // clear_registered_schematics()
+ static int l_clear_registered_schematics(lua_State *L);
+
+ // generate_ores(vm, p1, p2)
static int l_generate_ores(lua_State *L);
- // generate_decorations(vm)
+ // generate_decorations(vm, p1, p2)
static int l_generate_decorations(lua_State *L);
// clear_registered_ores
@@ -77,19 +84,19 @@ private:
// place_schematic(p, schematic, rotation, replacement)
static int l_place_schematic(lua_State *L);
- static bool regDecoSimple(lua_State *L,
- NodeResolveInfo *nri, DecoSimple *deco);
- static bool regDecoSchematic(lua_State *L,
- INodeDefManager *ndef, DecoSchematic *deco);
+ // serialize_schematic(schematic, format, options={...})
+ static int l_serialize_schematic(lua_State *L);
+
+public:
+ static void Initialize(lua_State *L, int top);
static struct EnumString es_BiomeTerrainType[];
static struct EnumString es_DecorationType[];
static struct EnumString es_MapgenObject[];
static struct EnumString es_OreType[];
static struct EnumString es_Rotation[];
-
-public:
- static void Initialize(lua_State *L, int top);
+ static struct EnumString es_SchematicFormatType[];
+ static struct EnumString es_NodeResolveMethod[];
};
#endif /* L_MAPGEN_H_ */
diff --git a/src/script/lua_api/l_nodemeta.cpp b/src/script/lua_api/l_nodemeta.cpp
index 4f20e56f9..6cdbe5c68 100644
--- a/src/script/lua_api/l_nodemeta.cpp
+++ b/src/script/lua_api/l_nodemeta.cpp
@@ -63,9 +63,10 @@ void NodeMetaRef::reportMetadataChange(NodeMetaRef *ref)
ref->m_env->getMap().dispatchEvent(&event);
// Set the block to be saved
MapBlock *block = ref->m_env->getMap().getBlockNoCreateNoEx(blockpos);
- if(block)
+ if (block) {
block->raiseModified(MOD_STATE_WRITE_NEEDED,
- "NodeMetaRef::reportMetadataChange");
+ MOD_REASON_REPORT_META_CHANGE);
+ }
}
// Exported functions
@@ -189,32 +190,34 @@ int NodeMetaRef::l_to_table(lua_State *L)
NodeMetaRef *ref = checkobject(L, 1);
NodeMetadata *meta = getmeta(ref, true);
- if(meta == NULL){
+ if (meta == NULL) {
lua_pushnil(L);
return 1;
}
lua_newtable(L);
+
// fields
lua_newtable(L);
{
- std::map<std::string, std::string> fields = meta->getStrings();
- for(std::map<std::string, std::string>::const_iterator
- i = fields.begin(); i != fields.end(); i++){
- const std::string &name = i->first;
- const std::string &value = i->second;
+ StringMap fields = meta->getStrings();
+ for (StringMap::const_iterator
+ it = fields.begin(); it != fields.end(); ++it) {
+ const std::string &name = it->first;
+ const std::string &value = it->second;
lua_pushlstring(L, name.c_str(), name.size());
lua_pushlstring(L, value.c_str(), value.size());
lua_settable(L, -3);
}
}
lua_setfield(L, -2, "fields");
+
// inventory
lua_newtable(L);
Inventory *inv = meta->getInventory();
- if(inv){
- std::vector<const InventoryList*> lists = inv->getLists();
- for(std::vector<const InventoryList*>::const_iterator
- i = lists.begin(); i != lists.end(); i++){
+ if (inv) {
+ std::vector<const InventoryList *> lists = inv->getLists();
+ for(std::vector<const InventoryList *>::const_iterator
+ i = lists.begin(); i != lists.end(); i++) {
push_inventory_list(L, inv, (*i)->getName().c_str());
lua_setfield(L, -2, (*i)->getName().c_str());
}
diff --git a/src/script/lua_api/l_noise.cpp b/src/script/lua_api/l_noise.cpp
index 5a82b6485..c8dc2d2dc 100644
--- a/src/script/lua_api/l_noise.cpp
+++ b/src/script/lua_api/l_noise.cpp
@@ -23,12 +23,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/c_content.h"
#include "log.h"
-// garbage collector
-int LuaPerlinNoise::gc_object(lua_State *L)
+///////////////////////////////////////
+/*
+ LuaPerlinNoise
+*/
+
+LuaPerlinNoise::LuaPerlinNoise(NoiseParams *params) :
+ np(*params)
+{
+}
+
+
+LuaPerlinNoise::~LuaPerlinNoise()
{
- LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
- delete o;
- return 0;
}
@@ -36,7 +43,7 @@ int LuaPerlinNoise::l_get2d(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
LuaPerlinNoise *o = checkobject(L, 1);
- v2f p = read_v2f(L, 2);
+ v2f p = check_v2f(L, 2);
lua_Number val = NoisePerlin2D(&o->np, p.X, p.Y, 0);
lua_pushnumber(L, val);
return 1;
@@ -47,26 +54,13 @@ int LuaPerlinNoise::l_get3d(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
LuaPerlinNoise *o = checkobject(L, 1);
- v3f p = read_v3f(L, 2);
+ v3f p = check_v3f(L, 2);
lua_Number val = NoisePerlin3D(&o->np, p.X, p.Y, p.Z, 0);
lua_pushnumber(L, val);
return 1;
}
-LuaPerlinNoise::LuaPerlinNoise(NoiseParams *params) :
- np(*params)
-{
-}
-
-
-LuaPerlinNoise::~LuaPerlinNoise()
-{
-}
-
-
-// LuaPerlinNoise(seed, octaves, persistence, scale)
-// Creates an LuaPerlinNoise and leaves it on top of stack
int LuaPerlinNoise::create_object(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
@@ -91,14 +85,22 @@ int LuaPerlinNoise::create_object(lua_State *L)
}
-LuaPerlinNoise* LuaPerlinNoise::checkobject(lua_State *L, int narg)
+int LuaPerlinNoise::gc_object(lua_State *L)
+{
+ LuaPerlinNoise *o = *(LuaPerlinNoise **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+
+LuaPerlinNoise *LuaPerlinNoise::checkobject(lua_State *L, int narg)
{
NO_MAP_LOCK_REQUIRED;
luaL_checktype(L, narg, LUA_TUSERDATA);
void *ud = luaL_checkudata(L, narg, className);
if (!ud)
luaL_typerror(L, narg, className);
- return *(LuaPerlinNoise**)ud; // unbox pointer
+ return *(LuaPerlinNoise **)ud;
}
@@ -111,7 +113,7 @@ void LuaPerlinNoise::Register(lua_State *L)
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable);
- lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+ lua_settable(L, metatable);
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
@@ -121,12 +123,11 @@ void LuaPerlinNoise::Register(lua_State *L)
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
- lua_pop(L, 1); // drop metatable
+ lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0); // fill methodtable
- lua_pop(L, 1); // drop methodtable
+ luaL_openlib(L, 0, methods, 0);
+ lua_pop(L, 1);
- // Can be created from Lua (PerlinNoise(seed, octaves, persistence)
lua_register(L, className, create_object);
}
@@ -138,16 +139,26 @@ const luaL_reg LuaPerlinNoise::methods[] = {
{0,0}
};
-
+///////////////////////////////////////
/*
- PerlinNoiseMap
- */
+ LuaPerlinNoiseMap
+*/
-int LuaPerlinNoiseMap::gc_object(lua_State *L)
+LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, int seed, v3s16 size)
{
- LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
- delete o;
- return 0;
+ m_is3d = size.Z > 1;
+ np = *params;
+ try {
+ noise = new Noise(&np, seed, size.X, size.Y, size.Z);
+ } catch (InvalidNoiseParamsException &e) {
+ throw LuaError(e.what());
+ }
+}
+
+
+LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
+{
+ delete noise;
}
@@ -157,15 +168,15 @@ int LuaPerlinNoiseMap::l_get2dMap(lua_State *L)
size_t i = 0;
LuaPerlinNoiseMap *o = checkobject(L, 1);
- v2f p = read_v2f(L, 2);
+ v2f p = check_v2f(L, 2);
Noise *n = o->noise;
n->perlinMap2D(p.X, p.Y);
lua_newtable(L);
- for (int y = 0; y != n->sy; y++) {
+ for (u32 y = 0; y != n->sy; y++) {
lua_newtable(L);
- for (int x = 0; x != n->sx; x++) {
+ for (u32 x = 0; x != n->sx; x++) {
lua_pushnumber(L, n->result[i++]);
lua_rawseti(L, -2, x + 1);
}
@@ -180,14 +191,19 @@ int LuaPerlinNoiseMap::l_get2dMap_flat(lua_State *L)
NO_MAP_LOCK_REQUIRED;
LuaPerlinNoiseMap *o = checkobject(L, 1);
- v2f p = read_v2f(L, 2);
+ v2f p = check_v2f(L, 2);
+ bool use_buffer = lua_istable(L, 3);
Noise *n = o->noise;
n->perlinMap2D(p.X, p.Y);
size_t maplen = n->sx * n->sy;
- lua_newtable(L);
+ if (use_buffer)
+ lua_pushvalue(L, 3);
+ else
+ lua_newtable(L);
+
for (size_t i = 0; i != maplen; i++) {
lua_pushnumber(L, n->result[i]);
lua_rawseti(L, -2, i + 1);
@@ -202,7 +218,7 @@ int LuaPerlinNoiseMap::l_get3dMap(lua_State *L)
size_t i = 0;
LuaPerlinNoiseMap *o = checkobject(L, 1);
- v3f p = read_v3f(L, 2);
+ v3f p = check_v3f(L, 2);
if (!o->m_is3d)
return 0;
@@ -211,11 +227,11 @@ int LuaPerlinNoiseMap::l_get3dMap(lua_State *L)
n->perlinMap3D(p.X, p.Y, p.Z);
lua_newtable(L);
- for (int z = 0; z != n->sz; z++) {
+ for (u32 z = 0; z != n->sz; z++) {
lua_newtable(L);
- for (int y = 0; y != n->sy; y++) {
+ for (u32 y = 0; y != n->sy; y++) {
lua_newtable(L);
- for (int x = 0; x != n->sx; x++) {
+ for (u32 x = 0; x != n->sx; x++) {
lua_pushnumber(L, n->result[i++]);
lua_rawseti(L, -2, x + 1);
}
@@ -232,7 +248,8 @@ int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
NO_MAP_LOCK_REQUIRED;
LuaPerlinNoiseMap *o = checkobject(L, 1);
- v3f p = read_v3f(L, 2);
+ v3f p = check_v3f(L, 2);
+ bool use_buffer = lua_istable(L, 3);
if (!o->m_is3d)
return 0;
@@ -242,7 +259,11 @@ int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
size_t maplen = n->sx * n->sy * n->sz;
- lua_newtable(L);
+ if (use_buffer)
+ lua_pushvalue(L, 3);
+ else
+ lua_newtable(L);
+
for (size_t i = 0; i != maplen; i++) {
lua_pushnumber(L, n->result[i]);
lua_rawseti(L, -2, i + 1);
@@ -251,26 +272,61 @@ int LuaPerlinNoiseMap::l_get3dMap_flat(lua_State *L)
}
-LuaPerlinNoiseMap::LuaPerlinNoiseMap(NoiseParams *params, int seed, v3s16 size)
+int LuaPerlinNoiseMap::l_calc2dMap(lua_State *L)
{
- m_is3d = size.Z > 1;
- np = *params;
- try {
- noise = new Noise(&np, seed, size.X, size.Y, size.Z);
- } catch (InvalidNoiseParamsException &e) {
- throw LuaError(e.what());
- }
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaPerlinNoiseMap *o = checkobject(L, 1);
+ v2f p = check_v2f(L, 2);
+
+ Noise *n = o->noise;
+ n->perlinMap2D(p.X, p.Y);
+
+ return 0;
}
+int LuaPerlinNoiseMap::l_calc3dMap(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
-LuaPerlinNoiseMap::~LuaPerlinNoiseMap()
+ LuaPerlinNoiseMap *o = checkobject(L, 1);
+ v3f p = check_v3f(L, 2);
+
+ if (!o->m_is3d)
+ return 0;
+
+ Noise *n = o->noise;
+ n->perlinMap3D(p.X, p.Y, p.Z);
+
+ return 0;
+}
+
+
+int LuaPerlinNoiseMap::l_getMapSlice(lua_State *L)
{
- delete noise;
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaPerlinNoiseMap *o = checkobject(L, 1);
+ v3s16 slice_offset = read_v3s16(L, 2);
+ v3s16 slice_size = read_v3s16(L, 3);
+ bool use_buffer = lua_istable(L, 4);
+
+ Noise *n = o->noise;
+
+ if (use_buffer)
+ lua_pushvalue(L, 3);
+ else
+ lua_newtable(L);
+
+ write_array_slice_float(L, lua_gettop(L), n->result,
+ v3u16(n->sx, n->sy, n->sz),
+ v3u16(slice_offset.X, slice_offset.Y, slice_offset.Z),
+ v3u16(slice_size.X, slice_size.Y, slice_size.Z));
+
+ return 1;
}
-// LuaPerlinNoiseMap(np, size)
-// Creates an LuaPerlinNoiseMap and leaves it on top of stack
int LuaPerlinNoiseMap::create_object(lua_State *L)
{
NoiseParams np;
@@ -286,6 +342,14 @@ int LuaPerlinNoiseMap::create_object(lua_State *L)
}
+int LuaPerlinNoiseMap::gc_object(lua_State *L)
+{
+ LuaPerlinNoiseMap *o = *(LuaPerlinNoiseMap **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+
LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
{
luaL_checktype(L, narg, LUA_TUSERDATA);
@@ -294,7 +358,7 @@ LuaPerlinNoiseMap *LuaPerlinNoiseMap::checkobject(lua_State *L, int narg)
if (!ud)
luaL_typerror(L, narg, className);
- return *(LuaPerlinNoiseMap **)ud; // unbox pointer
+ return *(LuaPerlinNoiseMap **)ud;
}
@@ -307,7 +371,7 @@ void LuaPerlinNoiseMap::Register(lua_State *L)
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable);
- lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+ lua_settable(L, metatable);
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
@@ -317,12 +381,11 @@ void LuaPerlinNoiseMap::Register(lua_State *L)
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
- lua_pop(L, 1); // drop metatable
+ lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0); // fill methodtable
- lua_pop(L, 1); // drop methodtable
+ luaL_openlib(L, 0, methods, 0);
+ lua_pop(L, 1);
- // Can be created from Lua (PerlinNoiseMap(np, size)
lua_register(L, className, create_object);
}
@@ -331,37 +394,31 @@ const char LuaPerlinNoiseMap::className[] = "PerlinNoiseMap";
const luaL_reg LuaPerlinNoiseMap::methods[] = {
luamethod(LuaPerlinNoiseMap, get2dMap),
luamethod(LuaPerlinNoiseMap, get2dMap_flat),
+ luamethod(LuaPerlinNoiseMap, calc2dMap),
luamethod(LuaPerlinNoiseMap, get3dMap),
luamethod(LuaPerlinNoiseMap, get3dMap_flat),
+ luamethod(LuaPerlinNoiseMap, calc3dMap),
+ luamethod(LuaPerlinNoiseMap, getMapSlice),
{0,0}
};
+///////////////////////////////////////
/*
LuaPseudoRandom
*/
-// garbage collector
-int LuaPseudoRandom::gc_object(lua_State *L)
-{
- LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
- delete o;
- return 0;
-}
-
-
-// next(self, min=0, max=32767) -> get next value
int LuaPseudoRandom::l_next(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
LuaPseudoRandom *o = checkobject(L, 1);
int min = 0;
int max = 32767;
- lua_settop(L, 3); // Fill 2 and 3 with nil if they don't exist
- if(!lua_isnil(L, 2))
+ lua_settop(L, 3);
+ if (lua_isnumber(L, 2))
min = luaL_checkinteger(L, 2);
- if(!lua_isnil(L, 3))
+ if (lua_isnumber(L, 3))
max = luaL_checkinteger(L, 3);
- if(max < min){
+ if (max < min) {
errorstream<<"PseudoRandom.next(): max="<<max<<" min="<<min<<std::endl;
throw LuaError("PseudoRandom.next(): max < min");
}
@@ -378,34 +435,107 @@ int LuaPseudoRandom::l_next(lua_State *L)
}
-LuaPseudoRandom::LuaPseudoRandom(int seed):
- m_pseudo(seed)
+int LuaPseudoRandom::create_object(lua_State *L)
{
+ int seed = luaL_checknumber(L, 1);
+ LuaPseudoRandom *o = new LuaPseudoRandom(seed);
+ *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
+ luaL_getmetatable(L, className);
+ lua_setmetatable(L, -2);
+ return 1;
}
-LuaPseudoRandom::~LuaPseudoRandom()
+int LuaPseudoRandom::gc_object(lua_State *L)
{
+ LuaPseudoRandom *o = *(LuaPseudoRandom **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
}
-const PseudoRandom& LuaPseudoRandom::getItem() const
+LuaPseudoRandom *LuaPseudoRandom::checkobject(lua_State *L, int narg)
{
- return m_pseudo;
+ luaL_checktype(L, narg, LUA_TUSERDATA);
+ void *ud = luaL_checkudata(L, narg, className);
+ if (!ud)
+ luaL_typerror(L, narg, className);
+ return *(LuaPseudoRandom **)ud;
}
-PseudoRandom& LuaPseudoRandom::getItem()
+
+void LuaPseudoRandom::Register(lua_State *L)
{
- return m_pseudo;
+ lua_newtable(L);
+ int methodtable = lua_gettop(L);
+ luaL_newmetatable(L, className);
+ int metatable = lua_gettop(L);
+
+ lua_pushliteral(L, "__metatable");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__index");
+ lua_pushvalue(L, methodtable);
+ lua_settable(L, metatable);
+
+ lua_pushliteral(L, "__gc");
+ lua_pushcfunction(L, gc_object);
+ lua_settable(L, metatable);
+
+ lua_pop(L, 1);
+
+ luaL_openlib(L, 0, methods, 0);
+ lua_pop(L, 1);
+
+ lua_register(L, className, create_object);
}
-// LuaPseudoRandom(seed)
-// Creates an LuaPseudoRandom and leaves it on top of stack
-int LuaPseudoRandom::create_object(lua_State *L)
+const char LuaPseudoRandom::className[] = "PseudoRandom";
+const luaL_reg LuaPseudoRandom::methods[] = {
+ luamethod(LuaPseudoRandom, next),
+ {0,0}
+};
+
+///////////////////////////////////////
+/*
+ LuaPcgRandom
+*/
+
+int LuaPcgRandom::l_next(lua_State *L)
{
- int seed = luaL_checknumber(L, 1);
- LuaPseudoRandom *o = new LuaPseudoRandom(seed);
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaPcgRandom *o = checkobject(L, 1);
+ u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
+ u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
+
+ lua_pushinteger(L, o->m_rnd.range(min, max));
+ return 1;
+}
+
+
+int LuaPcgRandom::l_rand_normal_dist(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+
+ LuaPcgRandom *o = checkobject(L, 1);
+ u32 min = lua_isnumber(L, 2) ? lua_tointeger(L, 2) : o->m_rnd.RANDOM_MIN;
+ u32 max = lua_isnumber(L, 3) ? lua_tointeger(L, 3) : o->m_rnd.RANDOM_MAX;
+ int num_trials = lua_isnumber(L, 4) ? lua_tointeger(L, 4) : 6;
+
+ lua_pushinteger(L, o->m_rnd.randNormalDist(min, max, num_trials));
+ return 1;
+}
+
+
+int LuaPcgRandom::create_object(lua_State *L)
+{
+ lua_Integer seed = luaL_checknumber(L, 1);
+ LuaPcgRandom *o = lua_isnumber(L, 2) ?
+ new LuaPcgRandom(seed, lua_tointeger(L, 2)) :
+ new LuaPcgRandom(seed);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
lua_setmetatable(L, -2);
@@ -413,17 +543,25 @@ int LuaPseudoRandom::create_object(lua_State *L)
}
-LuaPseudoRandom* LuaPseudoRandom::checkobject(lua_State *L, int narg)
+int LuaPcgRandom::gc_object(lua_State *L)
+{
+ LuaPcgRandom *o = *(LuaPcgRandom **)(lua_touserdata(L, 1));
+ delete o;
+ return 0;
+}
+
+
+LuaPcgRandom *LuaPcgRandom::checkobject(lua_State *L, int narg)
{
luaL_checktype(L, narg, LUA_TUSERDATA);
void *ud = luaL_checkudata(L, narg, className);
if (!ud)
luaL_typerror(L, narg, className);
- return *(LuaPseudoRandom**)ud; // unbox pointer
+ return *(LuaPcgRandom **)ud;
}
-void LuaPseudoRandom::Register(lua_State *L)
+void LuaPcgRandom::Register(lua_State *L)
{
lua_newtable(L);
int methodtable = lua_gettop(L);
@@ -432,7 +570,7 @@ void LuaPseudoRandom::Register(lua_State *L)
lua_pushliteral(L, "__metatable");
lua_pushvalue(L, methodtable);
- lua_settable(L, metatable); // hide metatable from Lua getmetatable()
+ lua_settable(L, metatable);
lua_pushliteral(L, "__index");
lua_pushvalue(L, methodtable);
@@ -442,18 +580,18 @@ void LuaPseudoRandom::Register(lua_State *L)
lua_pushcfunction(L, gc_object);
lua_settable(L, metatable);
- lua_pop(L, 1); // drop metatable
+ lua_pop(L, 1);
- luaL_openlib(L, 0, methods, 0); // fill methodtable
- lua_pop(L, 1); // drop methodtable
+ luaL_openlib(L, 0, methods, 0);
+ lua_pop(L, 1);
- // Can be created from Lua (LuaPseudoRandom(seed))
lua_register(L, className, create_object);
}
-const char LuaPseudoRandom::className[] = "PseudoRandom";
-const luaL_reg LuaPseudoRandom::methods[] = {
- luamethod(LuaPseudoRandom, next),
+const char LuaPcgRandom::className[] = "PcgRandom";
+const luaL_reg LuaPcgRandom::methods[] = {
+ luamethod(LuaPcgRandom, next),
+ luamethod(LuaPcgRandom, rand_normal_dist),
{0,0}
};
diff --git a/src/script/lua_api/l_noise.h b/src/script/lua_api/l_noise.h
index 3e22ac7a0..e958c5a23 100644
--- a/src/script/lua_api/l_noise.h
+++ b/src/script/lua_api/l_noise.h
@@ -64,6 +64,9 @@ class LuaPerlinNoiseMap : public ModApiBase {
static const char className[];
static const luaL_reg methods[];
+ // Exported functions
+
+ // garbage collector
static int gc_object(lua_State *L);
static int l_get2dMap(lua_State *L);
@@ -71,6 +74,10 @@ class LuaPerlinNoiseMap : public ModApiBase {
static int l_get3dMap(lua_State *L);
static int l_get3dMap_flat(lua_State *L);
+ static int l_calc2dMap(lua_State *L);
+ static int l_calc3dMap(lua_State *L);
+ static int l_getMapSlice(lua_State *L);
+
public:
LuaPerlinNoiseMap(NoiseParams *np, int seed, v3s16 size);
@@ -104,18 +111,51 @@ private:
static int l_next(lua_State *L);
public:
- LuaPseudoRandom(int seed);
-
- ~LuaPseudoRandom();
-
- const PseudoRandom& getItem() const;
- PseudoRandom& getItem();
+ LuaPseudoRandom(int seed) :
+ m_pseudo(seed) {}
// LuaPseudoRandom(seed)
// Creates an LuaPseudoRandom and leaves it on top of stack
static int create_object(lua_State *L);
- static LuaPseudoRandom* checkobject(lua_State *L, int narg);
+ static LuaPseudoRandom *checkobject(lua_State *L, int narg);
+
+ static void Register(lua_State *L);
+};
+
+/*
+ LuaPcgRandom
+*/
+class LuaPcgRandom : public ModApiBase {
+private:
+ PcgRandom m_rnd;
+
+ static const char className[];
+ static const luaL_reg methods[];
+
+ // Exported functions
+
+ // garbage collector
+ static int gc_object(lua_State *L);
+
+ // next(self, min=-2147483648, max=2147483647) -> get next value
+ static int l_next(lua_State *L);
+
+ // rand_normal_dist(self, min=-2147483648, max=2147483647, num_trials=6) ->
+ // get next normally distributed random value
+ static int l_rand_normal_dist(lua_State *L);
+
+public:
+ LuaPcgRandom(u64 seed) :
+ m_rnd(seed) {}
+ LuaPcgRandom(u64 seed, u64 seq) :
+ m_rnd(seed, seq) {}
+
+ // LuaPcgRandom(seed)
+ // Creates an LuaPcgRandom and leaves it on top of stack
+ static int create_object(lua_State *L);
+
+ static LuaPcgRandom *checkobject(lua_State *L, int narg);
static void Register(lua_State *L);
};
diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp
index 4286840fe..3ac8eeefb 100644
--- a/src/script/lua_api/l_object.cpp
+++ b/src/script/lua_api/l_object.cpp
@@ -26,11 +26,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h"
#include "tool.h"
#include "serverobject.h"
-#include "content_object.h"
#include "content_sao.h"
#include "server.h"
#include "hud.h"
+#include "scripting_game.h"
+#define GET_ENV_PTR ServerEnvironment* env = \
+ dynamic_cast<ServerEnvironment*>(getEnv(L)); \
+ if (env == NULL) return 0
struct EnumString es_HudElementType[] =
{
@@ -65,6 +68,7 @@ struct EnumString es_HudBuiltinElement[] =
{HUD_FLAG_CROSSHAIR_VISIBLE, "crosshair"},
{HUD_FLAG_WIELDITEM_VISIBLE, "wielditem"},
{HUD_FLAG_BREATHBAR_VISIBLE, "breathbar"},
+ {HUD_FLAG_MINIMAP_VISIBLE, "minimap"},
{0, NULL},
};
@@ -77,7 +81,7 @@ ObjectRef* ObjectRef::checkobject(lua_State *L, int narg)
{
luaL_checktype(L, narg, LUA_TUSERDATA);
void *ud = luaL_checkudata(L, narg, className);
- if(!ud) luaL_typerror(L, narg, className);
+ if (!ud) luaL_typerror(L, narg, className);
return *(ObjectRef**)ud; // unbox pointer
}
@@ -90,9 +94,9 @@ ServerActiveObject* ObjectRef::getobject(ObjectRef *ref)
LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
{
ServerActiveObject *obj = getobject(ref);
- if(obj == NULL)
+ if (obj == NULL)
return NULL;
- if(obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
+ if (obj->getType() != ACTIVEOBJECT_TYPE_LUAENTITY)
return NULL;
return (LuaEntitySAO*)obj;
}
@@ -100,9 +104,9 @@ LuaEntitySAO* ObjectRef::getluaobject(ObjectRef *ref)
PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
{
ServerActiveObject *obj = getobject(ref);
- if(obj == NULL)
+ if (obj == NULL)
return NULL;
- if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
+ if (obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
return NULL;
return (PlayerSAO*)obj;
}
@@ -110,7 +114,7 @@ PlayerSAO* ObjectRef::getplayersao(ObjectRef *ref)
Player* ObjectRef::getplayer(ObjectRef *ref)
{
PlayerSAO *playersao = getplayersao(ref);
- if(playersao == NULL)
+ if (playersao == NULL)
return NULL;
return playersao->getPlayer();
}
@@ -129,9 +133,22 @@ int ObjectRef::gc_object(lua_State *L) {
int ObjectRef::l_remove(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
+ GET_ENV_PTR;
+
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL)
+ return 0;
+ if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
+ return 0;
+
+ std::set<int> child_ids = co->getAttachmentChildIds();
+ std::set<int>::iterator it;
+ for (it = child_ids.begin(); it != child_ids.end(); ++it) {
+ ServerActiveObject *child = env->getActiveObject(*it);
+ child->setAttachment(0, "", v3f(0, 0, 0), v3f(0, 0, 0));
+ }
+
verbosestream<<"ObjectRef::l_remove(): id="<<co->getId()<<std::endl;
co->m_removed = true;
return 0;
@@ -144,7 +161,7 @@ int ObjectRef::l_getpos(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
v3f pos = co->getBasePosition() / BS;
lua_newtable(L);
lua_pushnumber(L, pos.X);
@@ -163,7 +180,7 @@ int ObjectRef::l_setpos(lua_State *L)
ObjectRef *ref = checkobject(L, 1);
//LuaEntitySAO *co = getluaobject(ref);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// pos
v3f pos = checkFloatPos(L, 2);
// Do it
@@ -178,7 +195,7 @@ int ObjectRef::l_moveto(lua_State *L)
ObjectRef *ref = checkobject(L, 1);
//LuaEntitySAO *co = getluaobject(ref);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// pos
v3f pos = checkFloatPos(L, 2);
// continuous
@@ -196,20 +213,36 @@ int ObjectRef::l_punch(lua_State *L)
ObjectRef *puncher_ref = checkobject(L, 2);
ServerActiveObject *co = getobject(ref);
ServerActiveObject *puncher = getobject(puncher_ref);
- if(co == NULL) return 0;
- if(puncher == NULL) return 0;
+ if (co == NULL) return 0;
+ if (puncher == NULL) return 0;
v3f dir;
- if(lua_type(L, 5) != LUA_TTABLE)
+ if (lua_type(L, 5) != LUA_TTABLE)
dir = co->getBasePosition() - puncher->getBasePosition();
else
dir = read_v3f(L, 5);
float time_from_last_punch = 1000000;
- if(lua_isnumber(L, 3))
+ if (lua_isnumber(L, 3))
time_from_last_punch = lua_tonumber(L, 3);
ToolCapabilities toolcap = read_tool_capabilities(L, 4);
dir.normalize();
+
+ s16 src_original_hp = co->getHP();
+ s16 dst_origin_hp = puncher->getHP();
+
// Do it
co->punch(dir, &toolcap, puncher, time_from_last_punch);
+
+ // If the punched is a player, and its HP changed
+ if (src_original_hp != co->getHP() &&
+ co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+ getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co);
+ }
+
+ // If the puncher is a player, and its HP changed
+ if (dst_origin_hp != puncher->getHP() &&
+ puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+ getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher);
+ }
return 0;
}
@@ -221,8 +254,8 @@ int ObjectRef::l_right_click(lua_State *L)
ObjectRef *ref2 = checkobject(L, 2);
ServerActiveObject *co = getobject(ref);
ServerActiveObject *co2 = getobject(ref2);
- if(co == NULL) return 0;
- if(co2 == NULL) return 0;
+ if (co == NULL) return 0;
+ if (co2 == NULL) return 0;
// Do it
co->rightClick(co2);
return 0;
@@ -237,12 +270,15 @@ int ObjectRef::l_set_hp(lua_State *L)
ObjectRef *ref = checkobject(L, 1);
luaL_checknumber(L, 2);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
int hp = lua_tonumber(L, 2);
/*infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
<<" hp="<<hp<<std::endl;*/
// Do it
co->setHP(hp);
+ if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
+ getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co);
+
// Return
return 0;
}
@@ -255,7 +291,7 @@ int ObjectRef::l_get_hp(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL){
+ if (co == NULL) {
// Default hp is 1
lua_pushnumber(L, 1);
return 1;
@@ -274,10 +310,10 @@ int ObjectRef::l_get_inventory(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
InventoryLocation loc = co->getInventoryLocation();
- if(getServer(L)->getInventory(loc) != NULL)
+ if (getServer(L)->getInventory(loc) != NULL)
InvRef::create(L, loc);
else
lua_pushnil(L); // An object may have no inventory (nil)
@@ -290,7 +326,7 @@ int ObjectRef::l_get_wield_list(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
lua_pushstring(L, co->getWieldList().c_str());
return 1;
@@ -302,7 +338,7 @@ int ObjectRef::l_get_wield_index(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
lua_pushinteger(L, co->getWieldIndex() + 1);
return 1;
@@ -314,7 +350,7 @@ int ObjectRef::l_get_wielded_item(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL){
+ if (co == NULL) {
// Empty ItemStack
LuaItemStack::create(L, ItemStack());
return 1;
@@ -330,10 +366,13 @@ int ObjectRef::l_set_wielded_item(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
ItemStack item = read_item(L, 2, getServer(L));
bool success = co->setWieldedItem(item);
+ if (success && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+ getServer(L)->SendInventory(((PlayerSAO*)co));
+ }
lua_pushboolean(L, success);
return 1;
}
@@ -344,7 +383,7 @@ int ObjectRef::l_set_armor_groups(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
ItemGroupList groups;
read_groups(L, 2, groups);
@@ -352,13 +391,27 @@ int ObjectRef::l_set_armor_groups(lua_State *L)
return 0;
}
+// get_armor_groups(self)
+int ObjectRef::l_get_armor_groups(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ ServerActiveObject *co = getobject(ref);
+ if (co == NULL)
+ return 0;
+ // Do it
+ ItemGroupList groups = co->getArmorGroups();
+ push_groups(L, groups);
+ return 1;
+}
+
// set_physics_override(self, physics_override_speed, physics_override_jump,
// physics_override_gravity, sneak, sneak_glitch)
int ObjectRef::l_set_physics_override(lua_State *L)
{
ObjectRef *ref = checkobject(L, 1);
PlayerSAO *co = (PlayerSAO *) getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
if (lua_istable(L, 2)) {
co->m_physics_override_speed = getfloatfield_default(L, 2, "speed", co->m_physics_override_speed);
@@ -369,15 +422,15 @@ int ObjectRef::l_set_physics_override(lua_State *L)
co->m_physics_override_sent = false;
} else {
// old, non-table format
- if(!lua_isnil(L, 2)){
+ if (!lua_isnil(L, 2)) {
co->m_physics_override_speed = lua_tonumber(L, 2);
co->m_physics_override_sent = false;
}
- if(!lua_isnil(L, 3)){
+ if (!lua_isnil(L, 3)) {
co->m_physics_override_jump = lua_tonumber(L, 3);
co->m_physics_override_sent = false;
}
- if(!lua_isnil(L, 4)){
+ if (!lua_isnil(L, 4)) {
co->m_physics_override_gravity = lua_tonumber(L, 4);
co->m_physics_override_sent = false;
}
@@ -385,27 +438,74 @@ int ObjectRef::l_set_physics_override(lua_State *L)
return 0;
}
-// set_animation(self, frame_range, frame_speed, frame_blend)
+// get_physics_override(self)
+int ObjectRef::l_get_physics_override(lua_State *L)
+{
+ ObjectRef *ref = checkobject(L, 1);
+ PlayerSAO *co = (PlayerSAO *)getobject(ref);
+ if (co == NULL)
+ return 0;
+ // Do it
+ lua_newtable(L);
+ lua_pushnumber(L, co->m_physics_override_speed);
+ lua_setfield(L, -2, "speed");
+ lua_pushnumber(L, co->m_physics_override_jump);
+ lua_setfield(L, -2, "jump");
+ lua_pushnumber(L, co->m_physics_override_gravity);
+ lua_setfield(L, -2, "gravity");
+ lua_pushboolean(L, co->m_physics_override_sneak);
+ lua_setfield(L, -2, "sneak");
+ lua_pushboolean(L, co->m_physics_override_sneak_glitch);
+ lua_setfield(L, -2, "sneak_glitch");
+ return 1;
+}
+
+// set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
int ObjectRef::l_set_animation(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
v2f frames = v2f(1, 1);
- if(!lua_isnil(L, 2))
+ if (!lua_isnil(L, 2))
frames = read_v2f(L, 2);
float frame_speed = 15;
- if(!lua_isnil(L, 3))
+ if (!lua_isnil(L, 3))
frame_speed = lua_tonumber(L, 3);
float frame_blend = 0;
- if(!lua_isnil(L, 4))
+ if (!lua_isnil(L, 4))
frame_blend = lua_tonumber(L, 4);
- co->setAnimation(frames, frame_speed, frame_blend);
+ bool frame_loop = true;
+ if (lua_isboolean(L, 5))
+ frame_loop = lua_toboolean(L, 5);
+ co->setAnimation(frames, frame_speed, frame_blend, frame_loop);
return 0;
}
+// get_animation(self)
+int ObjectRef::l_get_animation(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ ServerActiveObject *co = getobject(ref);
+ if (co == NULL)
+ return 0;
+ // Do it
+ v2f frames = v2f(1,1);
+ float frame_speed = 15;
+ float frame_blend = 0;
+ bool frame_loop = true;
+ co->getAnimation(&frames, &frame_speed, &frame_blend, &frame_loop);
+
+ push_v2f(L, frames);
+ lua_pushnumber(L, frame_speed);
+ lua_pushnumber(L, frame_blend);
+ lua_pushboolean(L, frame_loop);
+ return 4;
+}
+
// set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed)
int ObjectRef::l_set_local_animation(lua_State *L)
{
@@ -417,11 +517,11 @@ int ObjectRef::l_set_local_animation(lua_State *L)
// Do it
v2s32 frames[4];
for (int i=0;i<4;i++) {
- if(!lua_isnil(L, 2+1))
+ if (!lua_isnil(L, 2+1))
frames[i] = read_v2s32(L, 2+i);
}
float frame_speed = 30;
- if(!lua_isnil(L, 6))
+ if (!lua_isnil(L, 6))
frame_speed = lua_tonumber(L, 6);
if (!getServer(L)->setLocalPlayerAnimations(player, frames, frame_speed))
@@ -431,6 +531,27 @@ int ObjectRef::l_set_local_animation(lua_State *L)
return 0;
}
+// get_local_animation(self)
+int ObjectRef::l_get_local_animation(lua_State *L)
+{
+ //NO_MAP_LOCK_REQUIRED
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if (player == NULL)
+ return 0;
+
+ v2s32 frames[4];
+ float frame_speed;
+ player->getLocalAnimations(frames, &frame_speed);
+
+ for (int i = 0; i < 4; i++) {
+ push_v2s32(L, frames[i]);
+ }
+
+ lua_pushnumber(L, frame_speed);
+ return 5;
+}
+
// set_eye_offset(self, v3f first pv, v3f third pv)
int ObjectRef::l_set_eye_offset(lua_State *L)
{
@@ -443,9 +564,9 @@ int ObjectRef::l_set_eye_offset(lua_State *L)
v3f offset_first = v3f(0, 0, 0);
v3f offset_third = v3f(0, 0, 0);
- if(!lua_isnil(L, 2))
+ if (!lua_isnil(L, 2))
offset_first = read_v3f(L, 2);
- if(!lua_isnil(L, 3))
+ if (!lua_isnil(L, 3))
offset_third = read_v3f(L, 3);
// Prevent abuse of offset values (keep player always visible)
@@ -461,60 +582,154 @@ int ObjectRef::l_set_eye_offset(lua_State *L)
return 0;
}
+// get_eye_offset(self)
+int ObjectRef::l_get_eye_offset(lua_State *L)
+{
+ //NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if (player == NULL)
+ return 0;
+ // Do it
+ push_v3f(L, player->eye_offset_first);
+ push_v3f(L, player->eye_offset_third);
+ return 2;
+}
+
// set_bone_position(self, std::string bone, v3f position, v3f rotation)
int ObjectRef::l_set_bone_position(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
std::string bone = "";
- if(!lua_isnil(L, 2))
+ if (!lua_isnil(L, 2))
bone = lua_tostring(L, 2);
v3f position = v3f(0, 0, 0);
- if(!lua_isnil(L, 3))
+ if (!lua_isnil(L, 3))
position = read_v3f(L, 3);
v3f rotation = v3f(0, 0, 0);
- if(!lua_isnil(L, 4))
+ if (!lua_isnil(L, 4))
rotation = read_v3f(L, 4);
co->setBonePosition(bone, position, rotation);
return 0;
}
+// get_bone_position(self, bone)
+int ObjectRef::l_get_bone_position(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ ServerActiveObject *co = getobject(ref);
+ if (co == NULL)
+ return 0;
+ // Do it
+ std::string bone = "";
+ if (!lua_isnil(L, 2))
+ bone = lua_tostring(L, 2);
+
+ v3f position = v3f(0, 0, 0);
+ v3f rotation = v3f(0, 0, 0);
+ co->getBonePosition(bone, &position, &rotation);
+
+ push_v3f(L, position);
+ push_v3f(L, rotation);
+ return 2;
+}
+
// set_attach(self, parent, bone, position, rotation)
int ObjectRef::l_set_attach(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
+ GET_ENV_PTR;
+
ObjectRef *ref = checkobject(L, 1);
ObjectRef *parent_ref = checkobject(L, 2);
ServerActiveObject *co = getobject(ref);
ServerActiveObject *parent = getobject(parent_ref);
- if(co == NULL) return 0;
- if(parent == NULL) return 0;
+ if (co == NULL)
+ return 0;
+ if (parent == NULL)
+ return 0;
// Do it
+ int parent_id = 0;
std::string bone = "";
- if(!lua_isnil(L, 3))
- bone = lua_tostring(L, 3);
v3f position = v3f(0, 0, 0);
- if(!lua_isnil(L, 4))
- position = read_v3f(L, 4);
v3f rotation = v3f(0, 0, 0);
- if(!lua_isnil(L, 5))
+ co->getAttachment(&parent_id, &bone, &position, &rotation);
+ if (parent_id) {
+ ServerActiveObject *old_parent = env->getActiveObject(parent_id);
+ old_parent->removeAttachmentChild(co->getId());
+ }
+
+ bone = "";
+ if (!lua_isnil(L, 3))
+ bone = lua_tostring(L, 3);
+ position = v3f(0, 0, 0);
+ if (!lua_isnil(L, 4))
+ position = read_v3f(L, 4);
+ rotation = v3f(0, 0, 0);
+ if (!lua_isnil(L, 5))
rotation = read_v3f(L, 5);
co->setAttachment(parent->getId(), bone, position, rotation);
+ parent->addAttachmentChild(co->getId());
return 0;
}
+// get_attach(self)
+int ObjectRef::l_get_attach(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ GET_ENV_PTR;
+
+ ObjectRef *ref = checkobject(L, 1);
+ ServerActiveObject *co = getobject(ref);
+ if (co == NULL)
+ return 0;
+
+ // Do it
+ int parent_id = 0;
+ std::string bone = "";
+ v3f position = v3f(0, 0, 0);
+ v3f rotation = v3f(0, 0, 0);
+ co->getAttachment(&parent_id, &bone, &position, &rotation);
+ if (!parent_id)
+ return 0;
+ ServerActiveObject *parent = env->getActiveObject(parent_id);
+
+ getScriptApiBase(L)->objectrefGetOrCreate(L, parent);
+ lua_pushlstring(L, bone.c_str(), bone.size());
+ push_v3f(L, position);
+ push_v3f(L, rotation);
+ return 4;
+}
+
// set_detach(self)
int ObjectRef::l_set_detach(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
+ GET_ENV_PTR;
+
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL)
+ return 0;
+
+ int parent_id = 0;
+ std::string bone = "";
+ v3f position;
+ v3f rotation;
+ co->getAttachment(&parent_id, &bone, &position, &rotation);
+ ServerActiveObject *parent = NULL;
+ if (parent_id)
+ parent = env->getActiveObject(parent_id);
+
// Do it
co->setAttachment(0, "", v3f(0,0,0), v3f(0,0,0));
+ if (parent != NULL)
+ parent->removeAttachmentChild(co->getId());
return 0;
}
@@ -524,15 +739,40 @@ int ObjectRef::l_set_properties(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
ServerActiveObject *co = getobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
ObjectProperties *prop = co->accessObjectProperties();
- if(!prop)
+ if (!prop)
return 0;
read_object_properties(L, 2, prop);
co->notifyObjectPropertiesModified();
return 0;
}
+// get_properties(self)
+int ObjectRef::l_get_properties(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ ServerActiveObject *co = getobject(ref);
+ if (co == NULL)
+ return 0;
+ ObjectProperties *prop = co->accessObjectProperties();
+ if (!prop)
+ return 0;
+ push_object_properties(L, prop);
+ return 1;
+}
+
+// is_player(self)
+int ObjectRef::l_is_player(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ lua_pushboolean(L, (player != NULL));
+ return 1;
+}
+
/* LuaEntitySAO-only */
// setvelocity(self, {x=num, y=num, z=num})
@@ -541,7 +781,7 @@ int ObjectRef::l_setvelocity(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
v3f pos = checkFloatPos(L, 2);
// Do it
co->setVelocity(pos);
@@ -554,7 +794,7 @@ int ObjectRef::l_getvelocity(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
v3f v = co->getVelocity();
pushFloatPos(L, v);
@@ -567,7 +807,7 @@ int ObjectRef::l_setacceleration(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// pos
v3f pos = checkFloatPos(L, 2);
// Do it
@@ -581,7 +821,7 @@ int ObjectRef::l_getacceleration(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
v3f v = co->getAcceleration();
pushFloatPos(L, v);
@@ -594,7 +834,7 @@ int ObjectRef::l_setyaw(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
// Do it
co->setYaw(yaw);
@@ -607,7 +847,7 @@ int ObjectRef::l_getyaw(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
float yaw = co->getYaw() * core::DEGTORAD;
lua_pushnumber(L, yaw);
@@ -620,7 +860,7 @@ int ObjectRef::l_settexturemod(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
std::string mod = luaL_checkstring(L, 2);
co->setTextureMod(mod);
@@ -634,19 +874,19 @@ int ObjectRef::l_setsprite(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
v2s16 p(0,0);
- if(!lua_isnil(L, 2))
+ if (!lua_isnil(L, 2))
p = read_v2s16(L, 2);
int num_frames = 1;
- if(!lua_isnil(L, 3))
+ if (!lua_isnil(L, 3))
num_frames = lua_tonumber(L, 3);
float framelength = 0.2;
- if(!lua_isnil(L, 4))
+ if (!lua_isnil(L, 4))
framelength = lua_tonumber(L, 4);
bool select_horiz_by_yawpitch = false;
- if(!lua_isnil(L, 5))
+ if (!lua_isnil(L, 5))
select_horiz_by_yawpitch = lua_toboolean(L, 5);
co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch);
return 0;
@@ -660,7 +900,7 @@ int ObjectRef::l_get_entity_name(lua_State *L)
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
log_deprecated(L,"Deprecated call to \"get_entity_name");
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
std::string name = co->getName();
lua_pushstring(L, name.c_str());
@@ -673,7 +913,7 @@ int ObjectRef::l_get_luaentity(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
LuaEntitySAO *co = getluaobject(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
luaentity_get(L, co->getId());
return 1;
@@ -681,16 +921,6 @@ int ObjectRef::l_get_luaentity(lua_State *L)
/* Player-only */
-// is_player(self)
-int ObjectRef::l_is_player(lua_State *L)
-{
- NO_MAP_LOCK_REQUIRED;
- ObjectRef *ref = checkobject(L, 1);
- Player *player = getplayer(ref);
- lua_pushboolean(L, (player != NULL));
- return 1;
-}
-
// is_player_connected(self)
int ObjectRef::l_is_player_connected(lua_State *L)
{
@@ -707,7 +937,7 @@ int ObjectRef::l_get_player_name(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
- if(player == NULL){
+ if (player == NULL) {
lua_pushlstring(L, "", 0);
return 1;
}
@@ -716,13 +946,28 @@ int ObjectRef::l_get_player_name(lua_State *L)
return 1;
}
+// get_player_velocity(self)
+int ObjectRef::l_get_player_velocity(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if (player == NULL) {
+ lua_pushnil(L);
+ return 1;
+ }
+ // Do it
+ push_v3f(L, player->getSpeed() / BS);
+ return 1;
+}
+
// get_look_dir(self)
int ObjectRef::l_get_look_dir(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
- if(player == NULL) return 0;
+ if (player == NULL) return 0;
// Do it
float pitch = player->getRadPitch();
float yaw = player->getRadYaw();
@@ -737,7 +982,7 @@ int ObjectRef::l_get_look_pitch(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
- if(player == NULL) return 0;
+ if (player == NULL) return 0;
// Do it
lua_pushnumber(L, player->getRadPitch());
return 1;
@@ -749,7 +994,7 @@ int ObjectRef::l_get_look_yaw(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
- if(player == NULL) return 0;
+ if (player == NULL) return 0;
// Do it
lua_pushnumber(L, player->getRadYaw());
return 1;
@@ -761,7 +1006,7 @@ int ObjectRef::l_set_look_pitch(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
PlayerSAO* co = getplayersao(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
float pitch = luaL_checknumber(L, 2) * core::RADTODEG;
// Do it
co->setPitch(pitch);
@@ -774,7 +1019,7 @@ int ObjectRef::l_set_look_yaw(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
PlayerSAO* co = getplayersao(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
float yaw = luaL_checknumber(L, 2) * core::RADTODEG;
// Do it
co->setYaw(yaw);
@@ -787,11 +1032,15 @@ int ObjectRef::l_set_breath(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
PlayerSAO* co = getplayersao(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
u16 breath = luaL_checknumber(L, 2);
// Do it
co->setBreath(breath);
- co->m_breath_not_sent = true;
+
+ // If the object is a player sent the breath to client
+ if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
+ getServer(L)->SendPlayerBreath(((PlayerSAO*)co)->getPeerID());
+
return 0;
}
@@ -801,7 +1050,7 @@ int ObjectRef::l_get_breath(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
PlayerSAO* co = getplayersao(ref);
- if(co == NULL) return 0;
+ if (co == NULL) return 0;
// Do it
u16 breath = co->getBreath();
lua_pushinteger (L, breath);
@@ -814,7 +1063,7 @@ int ObjectRef::l_set_inventory_formspec(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
- if(player == NULL) return 0;
+ if (player == NULL) return 0;
std::string formspec = luaL_checkstring(L, 2);
player->inventory_formspec = formspec;
@@ -829,7 +1078,7 @@ int ObjectRef::l_get_inventory_formspec(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
- if(player == NULL) return 0;
+ if (player == NULL) return 0;
std::string formspec = player->inventory_formspec;
lua_pushlstring(L, formspec.c_str(), formspec.size());
@@ -842,7 +1091,7 @@ int ObjectRef::l_get_player_control(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
- if(player == NULL){
+ if (player == NULL) {
lua_pushlstring(L, "", 0);
return 1;
}
@@ -876,7 +1125,7 @@ int ObjectRef::l_get_player_control_bits(lua_State *L)
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkobject(L, 1);
Player *player = getplayer(ref);
- if(player == NULL){
+ if (player == NULL) {
lua_pushlstring(L, "", 0);
return 1;
}
@@ -1136,6 +1385,8 @@ int ObjectRef::l_hud_get_flags(lua_State *L)
lua_setfield(L, -2, "wielditem");
lua_pushboolean(L, player->hud_flags & HUD_FLAG_BREATHBAR_VISIBLE);
lua_setfield(L, -2, "breathbar");
+ lua_pushboolean(L, player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
+ lua_setfield(L, -2, "minimap");
return 1;
}
@@ -1157,6 +1408,20 @@ int ObjectRef::l_hud_set_hotbar_itemcount(lua_State *L)
return 1;
}
+// hud_get_hotbar_itemcount(self)
+int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
+{
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if (player == NULL)
+ return 0;
+
+ s32 hotbar_itemcount = getServer(L)->hudGetHotbarItemcount(player);
+
+ lua_pushnumber(L, hotbar_itemcount);
+ return 1;
+}
+
// hud_set_hotbar_image(self, name)
int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
{
@@ -1171,6 +1436,19 @@ int ObjectRef::l_hud_set_hotbar_image(lua_State *L)
return 1;
}
+// hud_get_hotbar_image(self)
+int ObjectRef::l_hud_get_hotbar_image(lua_State *L)
+{
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if (player == NULL)
+ return 0;
+
+ std::string name = getServer(L)->hudGetHotbarImage(player);
+ lua_pushlstring(L, name.c_str(), name.size());
+ return 1;
+}
+
// hud_set_hotbar_selected_image(self, name)
int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
{
@@ -1185,6 +1463,19 @@ int ObjectRef::l_hud_set_hotbar_selected_image(lua_State *L)
return 1;
}
+// hud_get_hotbar_selected_image(self)
+int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L)
+{
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if (player == NULL)
+ return 0;
+
+ std::string name = getServer(L)->hudGetHotbarSelectedImage(player);
+ lua_pushlstring(L, name.c_str(), name.size());
+ return 1;
+}
+
// set_sky(self, bgcolor, type, list)
int ObjectRef::l_set_sky(lua_State *L)
{
@@ -1194,8 +1485,7 @@ int ObjectRef::l_set_sky(lua_State *L)
return 0;
video::SColor bgcolor(255,255,255,255);
- if (!lua_isnil(L, 2))
- bgcolor = readARGB8(L, 2);
+ read_color(L, 2, &bgcolor);
std::string type = luaL_checkstring(L, 3);
@@ -1224,6 +1514,33 @@ int ObjectRef::l_set_sky(lua_State *L)
return 1;
}
+// get_sky(self)
+int ObjectRef::l_get_sky(lua_State *L)
+{
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if (player == NULL)
+ return 0;
+ video::SColor bgcolor(255, 255, 255, 255);
+ std::string type;
+ std::vector<std::string> params;
+
+ player->getSky(&bgcolor, &type, &params);
+ type = type == "" ? "regular" : type;
+
+ push_ARGB8(L, bgcolor);
+ lua_pushlstring(L, type.c_str(), type.size());
+ lua_newtable(L);
+ s16 i = 1;
+ for (std::vector<std::string>::iterator it = params.begin();
+ it != params.end(); ++it) {
+ lua_pushlstring(L, it->c_str(), it->size());
+ lua_rawseti(L, -2, i);
+ i++;
+ }
+ return 3;
+}
+
// override_day_night_ratio(self, brightness=0...1)
int ObjectRef::l_override_day_night_ratio(lua_State *L)
{
@@ -1234,7 +1551,7 @@ int ObjectRef::l_override_day_night_ratio(lua_State *L)
bool do_override = false;
float ratio = 0.0f;
- if (!lua_isnil(L, 2)){
+ if (!lua_isnil(L, 2)) {
do_override = true;
ratio = luaL_checknumber(L, 2);
}
@@ -1246,6 +1563,65 @@ int ObjectRef::l_override_day_night_ratio(lua_State *L)
return 1;
}
+// get_day_night_ratio(self)
+int ObjectRef::l_get_day_night_ratio(lua_State *L)
+{
+ ObjectRef *ref = checkobject(L, 1);
+ Player *player = getplayer(ref);
+ if (player == NULL)
+ return 0;
+
+ bool do_override;
+ float ratio;
+ player->getDayNightRatio(&do_override, &ratio);
+
+ if (do_override)
+ lua_pushnumber(L, ratio);
+ else
+ lua_pushnil(L);
+
+ return 1;
+}
+
+// set_nametag_attributes(self, attributes)
+int ObjectRef::l_set_nametag_attributes(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ PlayerSAO *playersao = getplayersao(ref);
+ if (playersao == NULL)
+ return 0;
+
+ lua_getfield(L, 2, "color");
+ if (!lua_isnil(L, -1)) {
+ video::SColor color = playersao->getNametagColor();
+ if (!read_color(L, -1, &color))
+ return 0;
+ playersao->setNametagColor(color);
+ }
+
+ lua_pushboolean(L, true);
+ return 1;
+}
+
+// get_nametag_attributes(self)
+int ObjectRef::l_get_nametag_attributes(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ ObjectRef *ref = checkobject(L, 1);
+ PlayerSAO *playersao = getplayersao(ref);
+ if (playersao == NULL)
+ return 0;
+
+ video::SColor color = playersao->getNametagColor();
+
+ lua_newtable(L);
+ push_ARGB8(L, color);
+ lua_setfield(L, -2, "color");
+
+ return 1;
+}
+
ObjectRef::ObjectRef(ServerActiveObject *object):
m_object(object)
{
@@ -1254,7 +1630,7 @@ ObjectRef::ObjectRef(ServerActiveObject *object):
ObjectRef::~ObjectRef()
{
- /*if(m_object)
+ /*if (m_object)
infostream<<"ObjectRef destructing for id="
<<m_object->getId()<<std::endl;
else
@@ -1323,12 +1699,16 @@ const luaL_reg ObjectRef::methods[] = {
luamethod(ObjectRef, get_wielded_item),
luamethod(ObjectRef, set_wielded_item),
luamethod(ObjectRef, set_armor_groups),
- luamethod(ObjectRef, set_physics_override),
+ luamethod(ObjectRef, get_armor_groups),
luamethod(ObjectRef, set_animation),
+ luamethod(ObjectRef, get_animation),
luamethod(ObjectRef, set_bone_position),
+ luamethod(ObjectRef, get_bone_position),
luamethod(ObjectRef, set_attach),
+ luamethod(ObjectRef, get_attach),
luamethod(ObjectRef, set_detach),
luamethod(ObjectRef, set_properties),
+ luamethod(ObjectRef, get_properties),
// LuaEntitySAO-only
luamethod(ObjectRef, setvelocity),
luamethod(ObjectRef, getvelocity),
@@ -1344,6 +1724,7 @@ const luaL_reg ObjectRef::methods[] = {
luamethod(ObjectRef, is_player),
luamethod(ObjectRef, is_player_connected),
luamethod(ObjectRef, get_player_name),
+ luamethod(ObjectRef, get_player_velocity),
luamethod(ObjectRef, get_look_dir),
luamethod(ObjectRef, get_look_pitch),
luamethod(ObjectRef, get_look_yaw),
@@ -1355,6 +1736,8 @@ const luaL_reg ObjectRef::methods[] = {
luamethod(ObjectRef, get_inventory_formspec),
luamethod(ObjectRef, get_player_control),
luamethod(ObjectRef, get_player_control_bits),
+ luamethod(ObjectRef, set_physics_override),
+ luamethod(ObjectRef, get_physics_override),
luamethod(ObjectRef, hud_add),
luamethod(ObjectRef, hud_remove),
luamethod(ObjectRef, hud_change),
@@ -1362,11 +1745,20 @@ const luaL_reg ObjectRef::methods[] = {
luamethod(ObjectRef, hud_set_flags),
luamethod(ObjectRef, hud_get_flags),
luamethod(ObjectRef, hud_set_hotbar_itemcount),
+ luamethod(ObjectRef, hud_get_hotbar_itemcount),
luamethod(ObjectRef, hud_set_hotbar_image),
+ luamethod(ObjectRef, hud_get_hotbar_image),
luamethod(ObjectRef, hud_set_hotbar_selected_image),
+ luamethod(ObjectRef, hud_get_hotbar_selected_image),
luamethod(ObjectRef, set_sky),
+ luamethod(ObjectRef, get_sky),
luamethod(ObjectRef, override_day_night_ratio),
+ luamethod(ObjectRef, get_day_night_ratio),
luamethod(ObjectRef, set_local_animation),
+ luamethod(ObjectRef, get_local_animation),
luamethod(ObjectRef, set_eye_offset),
+ luamethod(ObjectRef, get_eye_offset),
+ luamethod(ObjectRef, set_nametag_attributes),
+ luamethod(ObjectRef, get_nametag_attributes),
{0,0}
};
diff --git a/src/script/lua_api/l_object.h b/src/script/lua_api/l_object.h
index d51ca379f..a4457cc05 100644
--- a/src/script/lua_api/l_object.h
+++ b/src/script/lua_api/l_object.h
@@ -101,25 +101,46 @@ private:
// set_armor_groups(self, groups)
static int l_set_armor_groups(lua_State *L);
+ // get_armor_groups(self)
+ static int l_get_armor_groups(lua_State *L);
+
// set_physics_override(self, physics_override_speed, physics_override_jump,
// physics_override_gravity, sneak, sneak_glitch)
static int l_set_physics_override(lua_State *L);
- // set_animation(self, frame_range, frame_speed, frame_blend)
+ // get_physics_override(self)
+ static int l_get_physics_override(lua_State *L);
+
+ // set_animation(self, frame_range, frame_speed, frame_blend, frame_loop)
static int l_set_animation(lua_State *L);
+ // get_animation(self)
+ static int l_get_animation(lua_State *L);
+
// set_bone_position(self, std::string bone, v3f position, v3f rotation)
static int l_set_bone_position(lua_State *L);
+ // get_bone_position(self, bone)
+ static int l_get_bone_position(lua_State *L);
+
// set_attach(self, parent, bone, position, rotation)
static int l_set_attach(lua_State *L);
+ // get_attach(self)
+ static int l_get_attach(lua_State *L);
+
// set_detach(self)
static int l_set_detach(lua_State *L);
// set_properties(self, properties)
static int l_set_properties(lua_State *L);
+ // get_properties(self)
+ static int l_get_properties(lua_State *L);
+
+ // is_player(self)
+ static int l_is_player(lua_State *L);
+
/* LuaEntitySAO-only */
// setvelocity(self, {x=num, y=num, z=num})
@@ -156,15 +177,15 @@ private:
/* Player-only */
- // is_player(self)
- static int l_is_player(lua_State *L);
-
// is_player_connected(self)
static int l_is_player_connected(lua_State *L);
// get_player_name(self)
static int l_get_player_name(lua_State *L);
+ // get_player_velocity(self)
+ static int l_get_player_velocity(lua_State *L);
+
// get_look_dir(self)
static int l_get_look_dir(lua_State *L);
@@ -222,24 +243,51 @@ private:
// hud_set_hotbar_itemcount(self, hotbar_itemcount)
static int l_hud_set_hotbar_itemcount(lua_State *L);
+ // hud_get_hotbar_itemcount(self)
+ static int l_hud_get_hotbar_itemcount(lua_State *L);
+
// hud_set_hotbar_image(self, name)
static int l_hud_set_hotbar_image(lua_State *L);
+ // hud_get_hotbar_image(self)
+ static int l_hud_get_hotbar_image(lua_State *L);
+
// hud_set_hotbar_selected_image(self, name)
static int l_hud_set_hotbar_selected_image(lua_State *L);
+ // hud_get_hotbar_selected_image(self)
+ static int l_hud_get_hotbar_selected_image(lua_State *L);
+
// set_sky(self, type, list)
static int l_set_sky(lua_State *L);
- // override_day_night_ratio(self, type, list)
+ // get_sky(self, type, list)
+ static int l_get_sky(lua_State *L);
+
+ // override_day_night_ratio(self, type)
static int l_override_day_night_ratio(lua_State *L);
+ // get_day_night_ratio(self)
+ static int l_get_day_night_ratio(lua_State *L);
+
// set_local_animation(self, {stand/idle}, {walk}, {dig}, {walk+dig}, frame_speed)
static int l_set_local_animation(lua_State *L);
+ // get_local_animation(self)
+ static int l_get_local_animation(lua_State *L);
+
// set_eye_offset(self, v3f first pv, v3f third pv)
static int l_set_eye_offset(lua_State *L);
+ // get_eye_offset(self)
+ static int l_get_eye_offset(lua_State *L);
+
+ // set_nametag_attributes(self, attributes)
+ static int l_set_nametag_attributes(lua_State *L);
+
+ // get_nametag_attributes(self)
+ static int l_get_nametag_attributes(lua_State *L);
+
public:
ObjectRef(ServerActiveObject *object);
diff --git a/src/script/lua_api/l_particles.cpp b/src/script/lua_api/l_particles.cpp
index 6769f5c23..2532b2b08 100644
--- a/src/script/lua_api/l_particles.cpp
+++ b/src/script/lua_api/l_particles.cpp
@@ -34,17 +34,20 @@ int ModApiParticles::l_add_particle(lua_State *L)
{
// Get parameters
v3f pos, vel, acc;
- pos= vel= acc= v3f(0, 0, 0);
+ pos = vel = acc = v3f(0, 0, 0);
+
float expirationtime, size;
- expirationtime= size= 1;
+ expirationtime = size = 1;
+
bool collisiondetection, vertical;
- collisiondetection= vertical= false;
+ collisiondetection = vertical = false;
+
std::string texture = "";
- const char *playername = "";
+ std::string playername = "";
if (lua_gettop(L) > 1) // deprecated
{
- log_deprecated(L,"Deprecated add_particle call with individual parameters instead of definition");
+ log_deprecated(L, "Deprecated add_particle call with individual parameters instead of definition");
pos = check_v3f(L, 1);
vel = check_v3f(L, 2);
acc = check_v3f(L, 3);
@@ -57,44 +60,44 @@ int ModApiParticles::l_add_particle(lua_State *L)
}
else if (lua_istable(L, 1))
{
- int table = lua_gettop(L);
- lua_pushnil(L);
- while (lua_next(L, table) != 0)
- {
- const char *key = lua_tostring(L, -2);
- if(strcmp(key,"pos")==0){
- pos=check_v3f(L, -1);
- }else if(strcmp(key,"vel")==0){
- vel=check_v3f(L, -1);
- }else if(strcmp(key,"acc")==0){
- acc=check_v3f(L, -1);
- }else if(strcmp(key,"expirationtime")==0){
- expirationtime=luaL_checknumber(L, -1);
- }else if(strcmp(key,"size")==0){
- size=luaL_checknumber(L, -1);
- }else if(strcmp(key,"collisiondetection")==0){
- collisiondetection=lua_toboolean(L, -1);
- }else if(strcmp(key,"vertical")==0){
- vertical=lua_toboolean(L, -1);
- }else if(strcmp(key,"texture")==0){
- texture=luaL_checkstring(L, -1);
- }else if(strcmp(key,"playername")==0){
- playername=luaL_checkstring(L, -1);
- }
- lua_pop(L, 1);
+ lua_getfield(L, 1, "pos");
+ pos = lua_istable(L, -1) ? check_v3f(L, -1) : v3f();
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "vel");
+ if (lua_istable(L, -1)) {
+ vel = check_v3f(L, -1);
+ log_deprecated(L, "The use of vel is deprecated. "
+ "Use velocity instead");
}
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "velocity");
+ vel = lua_istable(L, -1) ? check_v3f(L, -1) : vel;
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "acc");
+ if (lua_istable(L, -1)) {
+ acc = check_v3f(L, -1);
+ log_deprecated(L, "The use of acc is deprecated. "
+ "Use acceleration instead");
+ }
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "acceleration");
+ acc = lua_istable(L, -1) ? check_v3f(L, -1) : acc;
+ lua_pop(L, 1);
+
+ expirationtime = getfloatfield_default(L, 1, "expirationtime", 1);
+ size = getfloatfield_default(L, 1, "size", 1);
+ collisiondetection = getboolfield_default(L, 1,
+ "collisiondetection", collisiondetection);
+ vertical = getboolfield_default(L, 1, "vertical", vertical);
+ texture = getstringfield_default(L, 1, "texture", "");
+ playername = getstringfield_default(L, 1, "playername", "");
}
- if (strcmp(playername, "")==0) // spawn for all players
- {
- getServer(L)->spawnParticleAll(pos, vel, acc,
+ getServer(L)->spawnParticle(playername, pos, vel, acc,
expirationtime, size, collisiondetection, vertical, texture);
- }
- else
- {
- getServer(L)->spawnParticle(playername,
- pos, vel, acc, expirationtime,
- size, collisiondetection, vertical, texture);
- }
return 1;
}
@@ -125,7 +128,7 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
bool collisiondetection, vertical;
collisiondetection= vertical= false;
std::string texture = "";
- const char *playername = "";
+ std::string playername = "";
if (lua_gettop(L) > 1) //deprecated
{
@@ -149,74 +152,55 @@ int ModApiParticles::l_add_particlespawner(lua_State *L)
}
else if (lua_istable(L, 1))
{
- int table = lua_gettop(L);
- lua_pushnil(L);
- while (lua_next(L, table) != 0)
- {
- const char *key = lua_tostring(L, -2);
- if(strcmp(key,"amount")==0){
- amount=luaL_checknumber(L, -1);
- }else if(strcmp(key,"time")==0){
- time=luaL_checknumber(L, -1);
- }else if(strcmp(key,"minpos")==0){
- minpos=check_v3f(L, -1);
- }else if(strcmp(key,"maxpos")==0){
- maxpos=check_v3f(L, -1);
- }else if(strcmp(key,"minvel")==0){
- minvel=check_v3f(L, -1);
- }else if(strcmp(key,"maxvel")==0){
- maxvel=check_v3f(L, -1);
- }else if(strcmp(key,"minacc")==0){
- minacc=check_v3f(L, -1);
- }else if(strcmp(key,"maxacc")==0){
- maxacc=check_v3f(L, -1);
- }else if(strcmp(key,"minexptime")==0){
- minexptime=luaL_checknumber(L, -1);
- }else if(strcmp(key,"maxexptime")==0){
- maxexptime=luaL_checknumber(L, -1);
- }else if(strcmp(key,"minsize")==0){
- minsize=luaL_checknumber(L, -1);
- }else if(strcmp(key,"maxsize")==0){
- maxsize=luaL_checknumber(L, -1);
- }else if(strcmp(key,"collisiondetection")==0){
- collisiondetection=lua_toboolean(L, -1);
- }else if(strcmp(key,"vertical")==0){
- vertical=lua_toboolean(L, -1);
- }else if(strcmp(key,"texture")==0){
- texture=luaL_checkstring(L, -1);
- }else if(strcmp(key,"playername")==0){
- playername=luaL_checkstring(L, -1);
- }
- lua_pop(L, 1);
- }
- }
- if (strcmp(playername, "")==0) //spawn for all players
- {
- u32 id = getServer(L)->addParticleSpawnerAll( amount, time,
- minpos, maxpos,
- minvel, maxvel,
- minacc, maxacc,
- minexptime, maxexptime,
- minsize, maxsize,
- collisiondetection,
- vertical,
- texture);
- lua_pushnumber(L, id);
- }
- else
- {
- u32 id = getServer(L)->addParticleSpawner(playername,
- amount, time,
- minpos, maxpos,
- minvel, maxvel,
- minacc, maxacc,
- minexptime, maxexptime,
- minsize, maxsize,
- collisiondetection,
- vertical,
- texture);
- lua_pushnumber(L, id);
+ amount = getintfield_default(L, 1, "amount", amount);
+ time = getfloatfield_default(L, 1, "time", time);
+
+ lua_getfield(L, 1, "minpos");
+ minpos = lua_istable(L, -1) ? check_v3f(L, -1) : minpos;
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "maxpos");
+ maxpos = lua_istable(L, -1) ? check_v3f(L, -1) : maxpos;
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "minvel");
+ minvel = lua_istable(L, -1) ? check_v3f(L, -1) : minvel;
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "maxvel");
+ maxvel = lua_istable(L, -1) ? check_v3f(L, -1) : maxvel;
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "minacc");
+ minacc = lua_istable(L, -1) ? check_v3f(L, -1) : minacc;
+ lua_pop(L, 1);
+
+ lua_getfield(L, 1, "maxacc");
+ maxacc = lua_istable(L, -1) ? check_v3f(L, -1) : maxacc;
+ lua_pop(L, 1);
+
+ minexptime = getfloatfield_default(L, 1, "minexptime", minexptime);
+ maxexptime = getfloatfield_default(L, 1, "maxexptime", maxexptime);
+ minsize = getfloatfield_default(L, 1, "minsize", minsize);
+ maxsize = getfloatfield_default(L, 1, "maxsize", maxsize);
+ collisiondetection = getboolfield_default(L, 1,
+ "collisiondetection", collisiondetection);
+ vertical = getboolfield_default(L, 1, "vertical", vertical);
+ texture = getstringfield_default(L, 1, "texture", "");
+ playername = getstringfield_default(L, 1, "playername", "");
}
+
+ u32 id = getServer(L)->addParticleSpawner(amount, time,
+ minpos, maxpos,
+ minvel, maxvel,
+ minacc, maxacc,
+ minexptime, maxexptime,
+ minsize, maxsize,
+ collisiondetection,
+ vertical,
+ texture, playername);
+ lua_pushnumber(L, id);
+
return 1;
}
@@ -226,16 +210,12 @@ int ModApiParticles::l_delete_particlespawner(lua_State *L)
{
// Get parameters
u32 id = luaL_checknumber(L, 1);
-
- if (lua_gettop(L) == 2) // only delete for one player
- {
- const char *playername = luaL_checkstring(L, 2);
- getServer(L)->deleteParticleSpawner(playername, id);
- }
- else // delete for all players
- {
- getServer(L)->deleteParticleSpawnerAll(id);
+ std::string playername = "";
+ if (lua_gettop(L) == 2) {
+ playername = luaL_checkstring(L, 2);
}
+
+ getServer(L)->deleteParticleSpawner(playername, id);
return 1;
}
diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp
index 8d7f6512e..73eca9d60 100644
--- a/src/script/lua_api/l_server.cpp
+++ b/src/script/lua_api/l_server.cpp
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_internal.h"
#include "common/c_converter.h"
#include "common/c_content.h"
+#include "cpp_api/s_base.h"
#include "server.h"
#include "environment.h"
#include "player.h"
@@ -29,7 +30,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
// request_shutdown()
int ModApiServer::l_request_shutdown(lua_State *L)
{
- getServer(L)->requestShutdown();
+ const char *msg = lua_tolstring(L, 1, NULL);
+ bool reconnect = lua_toboolean(L, 2);
+ getServer(L)->requestShutdown(msg ? msg : "", reconnect);
return 0;
}
@@ -306,7 +309,7 @@ int ModApiServer::l_kick_player(lua_State *L)
lua_pushboolean(L, false); // No such player
return 1;
}
- getServer(L)->DenyAccess(player->peer_id, narrow_to_wide(message));
+ getServer(L)->DenyAccess_Legacy(player->peer_id, utf8_to_wide(message));
lua_pushboolean(L, true);
return 1;
}
@@ -342,7 +345,7 @@ int ModApiServer::l_show_formspec(lua_State *L)
int ModApiServer::l_get_current_modname(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- lua_getfield(L, LUA_REGISTRYINDEX, "current_modname");
+ lua_getfield(L, LUA_REGISTRYINDEX, SCRIPT_MOD_NAME_FIELD);
return 1;
}
@@ -367,33 +370,18 @@ int ModApiServer::l_get_modnames(lua_State *L)
NO_MAP_LOCK_REQUIRED;
// Get a list of mods
- std::list<std::string> mods_unsorted, mods_sorted;
- getServer(L)->getModNames(mods_unsorted);
+ std::vector<std::string> modlist;
+ getServer(L)->getModNames(modlist);
// Take unsorted items from mods_unsorted and sort them into
// mods_sorted; not great performance but the number of mods on a
// server will likely be small.
- for(std::list<std::string>::iterator i = mods_unsorted.begin();
- i != mods_unsorted.end(); ++i) {
- bool added = false;
- for(std::list<std::string>::iterator x = mods_sorted.begin();
- x != mods_sorted.end(); ++x) {
- // I doubt anybody using Minetest will be using
- // anything not ASCII based :)
- if(i->compare(*x) <= 0) {
- mods_sorted.insert(x, *i);
- added = true;
- break;
- }
- }
- if(!added)
- mods_sorted.push_back(*i);
- }
+ std::sort(modlist.begin(), modlist.end());
// Package them up for Lua
- lua_createtable(L, mods_sorted.size(), 0);
- std::list<std::string>::iterator iter = mods_sorted.begin();
- for (u16 i = 0; iter != mods_sorted.end(); iter++) {
+ lua_createtable(L, modlist.size(), 0);
+ std::vector<std::string>::iterator iter = modlist.begin();
+ for (u16 i = 0; iter != modlist.end(); iter++) {
lua_pushstring(L, iter->c_str());
lua_rawseti(L, -2, ++i);
}
@@ -450,6 +438,31 @@ int ModApiServer::l_notify_authentication_modified(lua_State *L)
return 0;
}
+// get_last_run_mod()
+int ModApiServer::l_get_last_run_mod(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ lua_getfield(L, LUA_REGISTRYINDEX, SCRIPT_MOD_NAME_FIELD);
+ const char *current_mod = lua_tostring(L, -1);
+ if (current_mod == NULL || current_mod[0] == '\0') {
+ lua_pop(L, 1);
+ lua_pushstring(L, getScriptApiBase(L)->getOrigin().c_str());
+ }
+ return 1;
+}
+
+// set_last_run_mod(modname)
+int ModApiServer::l_set_last_run_mod(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+#ifdef SCRIPTAPI_DEBUG
+ const char *mod = lua_tostring(L, 1);
+ getScriptApiBase(L)->setOriginDirect(mod);
+ //printf(">>>> last mod set from Lua: %s\n", mod);
+#endif
+ return 0;
+}
+
#ifndef NDEBUG
// cause_error(type_of_error)
int ModApiServer::l_cause_error(lua_State *L)
@@ -507,6 +520,8 @@ void ModApiServer::Initialize(lua_State *L, int top)
API_FCT(unban_player_or_ip);
API_FCT(notify_authentication_modified);
+ API_FCT(get_last_run_mod);
+ API_FCT(set_last_run_mod);
#ifndef NDEBUG
API_FCT(cause_error);
#endif
diff --git a/src/script/lua_api/l_server.h b/src/script/lua_api/l_server.h
index fd85a8975..df31f325f 100644
--- a/src/script/lua_api/l_server.h
+++ b/src/script/lua_api/l_server.h
@@ -24,7 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
class ModApiServer : public ModApiBase {
private:
- // request_shutdown()
+ // request_shutdown([message], [reconnect])
static int l_request_shutdown(lua_State *L);
// get_server_status()
@@ -88,6 +88,12 @@ private:
// notify_authentication_modified(name)
static int l_notify_authentication_modified(lua_State *L);
+ // get_last_run_mod()
+ static int l_get_last_run_mod(lua_State *L);
+
+ // set_last_run_mod(modname)
+ static int l_set_last_run_mod(lua_State *L);
+
#ifndef NDEBUG
// cause_error(type_of_error)
static int l_cause_error(lua_State *L);
diff --git a/src/script/lua_api/l_settings.cpp b/src/script/lua_api/l_settings.cpp
index 9c88a3e05..35b82b435 100644
--- a/src/script/lua_api/l_settings.cpp
+++ b/src/script/lua_api/l_settings.cpp
@@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_settings.h"
#include "lua_api/l_internal.h"
+#include "cpp_api/s_security.h"
#include "settings.h"
#include "log.h"
@@ -188,6 +189,7 @@ int LuaSettings::create_object(lua_State* L)
{
NO_MAP_LOCK_REQUIRED;
const char* filename = luaL_checkstring(L, 1);
+ CHECK_SECURE_PATH_OPTIONAL(L, filename);
LuaSettings* o = new LuaSettings(filename);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;
luaL_getmetatable(L, className);
diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp
index eb6c1835d..12146e80a 100644
--- a/src/script/lua_api/l_util.cpp
+++ b/src/script/lua_api/l_util.cpp
@@ -24,13 +24,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "cpp_api/s_async.h"
#include "serialization.h"
#include "json/json.h"
+#include "cpp_api/s_security.h"
+#include "areastore.h"
#include "debug.h"
#include "porting.h"
#include "log.h"
#include "tool.h"
#include "filesys.h"
#include "settings.h"
-#include "main.h" //required for g_settings, g_settings_path
+#include "util/auth.h"
+#include <algorithm>
// debug(...)
// Writes a line to dstream
@@ -92,12 +95,19 @@ int ModApiUtil::l_log(lua_State *L)
return 0;
}
+#define CHECK_SECURE_SETTING(L, name) \
+ if (name.compare(0, 7, "secure.") == 0) {\
+ lua_pushliteral(L, "Attempt to set secure setting.");\
+ lua_error(L);\
+ }
+
// setting_set(name, value)
int ModApiUtil::l_setting_set(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- const char *name = luaL_checkstring(L, 1);
- const char *value = luaL_checkstring(L, 2);
+ std::string name = luaL_checkstring(L, 1);
+ std::string value = luaL_checkstring(L, 2);
+ CHECK_SECURE_SETTING(L, name);
g_settings->set(name, value);
return 0;
}
@@ -120,8 +130,9 @@ int ModApiUtil::l_setting_get(lua_State *L)
int ModApiUtil::l_setting_setbool(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
- const char *name = luaL_checkstring(L, 1);
+ std::string name = luaL_checkstring(L, 1);
bool value = lua_toboolean(L, 2);
+ CHECK_SECURE_SETTING(L, name);
g_settings->setBool(name, value);
return 0;
}
@@ -256,8 +267,7 @@ int ModApiUtil::l_get_password_hash(lua_State *L)
NO_MAP_LOCK_REQUIRED;
std::string name = luaL_checkstring(L, 1);
std::string raw_password = luaL_checkstring(L, 2);
- std::string hash = translatePassword(name,
- narrow_to_wide(raw_password));
+ std::string hash = translatePassword(name, raw_password);
lua_pushstring(L, hash.c_str());
return 1;
}
@@ -308,7 +318,7 @@ int ModApiUtil::l_compress(lua_State *L)
int ModApiUtil::l_decompress(lua_State *L)
{
size_t size;
- const char * data = luaL_checklstring(L, 1, &size);
+ const char *data = luaL_checklstring(L, 1, &size);
std::istringstream is(std::string(data, size));
std::ostringstream os;
@@ -320,6 +330,64 @@ int ModApiUtil::l_decompress(lua_State *L)
return 1;
}
+// mkdir(path)
+int ModApiUtil::l_mkdir(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ const char *path = luaL_checkstring(L, 1);
+ CHECK_SECURE_PATH_OPTIONAL(L, path);
+ lua_pushboolean(L, fs::CreateAllDirs(path));
+ return 1;
+}
+
+// get_dir_list(path, is_dir)
+int ModApiUtil::l_get_dir_list(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ const char *path = luaL_checkstring(L, 1);
+ short is_dir = lua_isboolean(L, 2) ? lua_toboolean(L, 2) : -1;
+
+ CHECK_SECURE_PATH_OPTIONAL(L, path);
+
+ std::vector<fs::DirListNode> list = fs::GetDirListing(path);
+
+ int index = 0;
+ lua_newtable(L);
+
+ for (size_t i = 0; i < list.size(); i++) {
+ if (is_dir == -1 || is_dir == list[i].dir) {
+ lua_pushstring(L, list[i].name.c_str());
+ lua_rawseti(L, -2, ++index);
+ }
+ }
+
+ return 1;
+}
+
+int ModApiUtil::l_request_insecure_environment(lua_State *L)
+{
+ NO_MAP_LOCK_REQUIRED;
+ if (!ScriptApiSecurity::isSecure(L)) {
+ lua_getglobal(L, "_G");
+ return 1;
+ }
+ lua_getfield(L, LUA_REGISTRYINDEX, SCRIPT_MOD_NAME_FIELD);
+ if (!lua_isstring(L, -1)) {
+ lua_pushnil(L);
+ return 1;
+ }
+ const char *mod_name = lua_tostring(L, -1);
+ std::string trusted_mods = g_settings->get("secure.trusted_mods");
+ std::vector<std::string> mod_list = str_split(trusted_mods, ',');
+ if (std::find(mod_list.begin(), mod_list.end(), mod_name) == mod_list.end()) {
+ lua_pushnil(L);
+ return 1;
+ }
+ lua_getfield(L, LUA_REGISTRYINDEX, "globals_backup");
+ return 1;
+}
+
+
void ModApiUtil::Initialize(lua_State *L, int top)
{
API_FCT(debug);
@@ -345,6 +413,11 @@ void ModApiUtil::Initialize(lua_State *L, int top)
API_FCT(compress);
API_FCT(decompress);
+
+ API_FCT(mkdir);
+ API_FCT(get_dir_list);
+
+ API_FCT(request_insecure_environment);
}
void ModApiUtil::InitializeAsync(AsyncEngine& engine)
@@ -367,5 +440,8 @@ void ModApiUtil::InitializeAsync(AsyncEngine& engine)
ASYNC_API_FCT(compress);
ASYNC_API_FCT(decompress);
+
+ ASYNC_API_FCT(mkdir);
+ ASYNC_API_FCT(get_dir_list);
}
diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h
index e82432381..e75aa28cb 100644
--- a/src/script/lua_api/l_util.h
+++ b/src/script/lua_api/l_util.h
@@ -78,7 +78,7 @@ private:
// is_yes(arg)
static int l_is_yes(lua_State *L);
- // get_scriptdir()
+ // get_builtin_path()
static int l_get_builtin_path(lua_State *L);
// compress(data, method, ...)
@@ -87,6 +87,15 @@ private:
// decompress(data, method, ...)
static int l_decompress(lua_State *L);
+ // mkdir(path)
+ static int l_mkdir(lua_State *L);
+
+ // get_dir_list(path, is_dir)
+ static int l_get_dir_list(lua_State *L);
+
+ // request_insecure_environment()
+ static int l_request_insecure_environment(lua_State *L);
+
public:
static void Initialize(lua_State *L, int top);
@@ -95,3 +104,4 @@ public:
};
#endif /* L_UTIL_H_ */
+
diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp
index de7612115..ac6c10303 100644
--- a/src/script/lua_api/l_vmanip.cpp
+++ b/src/script/lua_api/l_vmanip.cpp
@@ -46,8 +46,8 @@ int LuaVoxelManip::l_read_from_map(lua_State *L)
LuaVoxelManip *o = checkobject(L, 1);
MMVManip *vm = o->vm;
- v3s16 bp1 = getNodeBlockPos(read_v3s16(L, 2));
- v3s16 bp2 = getNodeBlockPos(read_v3s16(L, 3));
+ v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2));
+ v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3));
sortBoxVerticies(bp1, bp2);
vm->initialEmerge(bp1, bp2);
@@ -63,12 +63,18 @@ int LuaVoxelManip::l_get_data(lua_State *L)
NO_MAP_LOCK_REQUIRED;
LuaVoxelManip *o = checkobject(L, 1);
+ bool use_buffer = lua_istable(L, 2);
+
MMVManip *vm = o->vm;
- int volume = vm->m_area.getVolume();
+ u32 volume = vm->m_area.getVolume();
- lua_newtable(L);
- for (int i = 0; i != volume; i++) {
+ if (use_buffer)
+ lua_pushvalue(L, 2);
+ else
+ lua_newtable(L);
+
+ for (u32 i = 0; i != volume; i++) {
lua_Integer cid = vm->m_data[i].getContent();
lua_pushinteger(L, cid);
lua_rawseti(L, -2, i + 1);
@@ -87,8 +93,8 @@ int LuaVoxelManip::l_set_data(lua_State *L)
if (!lua_istable(L, 2))
return 0;
- int volume = vm->m_area.getVolume();
- for (int i = 0; i != volume; i++) {
+ u32 volume = vm->m_area.getVolume();
+ for (u32 i = 0; i != volume; i++) {
lua_rawgeti(L, 2, i + 1);
content_t c = lua_tointeger(L, -1);
@@ -116,7 +122,7 @@ int LuaVoxelManip::l_get_node_at(lua_State *L)
GET_ENV_PTR;
LuaVoxelManip *o = checkobject(L, 1);
- v3s16 pos = read_v3s16(L, 2);
+ v3s16 pos = check_v3s16(L, 2);
pushnode(L, o->vm->getNodeNoExNoEmerge(pos), env->getGameDef()->ndef());
return 1;
@@ -128,7 +134,7 @@ int LuaVoxelManip::l_set_node_at(lua_State *L)
GET_ENV_PTR;
LuaVoxelManip *o = checkobject(L, 1);
- v3s16 pos = read_v3s16(L, 2);
+ v3s16 pos = check_v3s16(L, 2);
MapNode n = readnode(L, 3, env->getGameDef()->ndef());
o->vm->setNodeNoEmerge(pos, n);
@@ -171,8 +177,8 @@ int LuaVoxelManip::l_calc_lighting(lua_State *L)
v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
v3s16 fpmin = vm->m_area.MinEdge;
v3s16 fpmax = vm->m_area.MaxEdge;
- v3s16 pmin = lua_istable(L, 2) ? read_v3s16(L, 2) : fpmin + yblock;
- v3s16 pmax = lua_istable(L, 3) ? read_v3s16(L, 3) : fpmax - yblock;
+ v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : fpmin + yblock;
+ v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : fpmax - yblock;
sortBoxVerticies(pmin, pmax);
if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
@@ -206,8 +212,8 @@ int LuaVoxelManip::l_set_lighting(lua_State *L)
MMVManip *vm = o->vm;
v3s16 yblock = v3s16(0, 1, 0) * MAP_BLOCKSIZE;
- v3s16 pmin = lua_istable(L, 3) ? read_v3s16(L, 3) : vm->m_area.MinEdge + yblock;
- v3s16 pmax = lua_istable(L, 4) ? read_v3s16(L, 4) : vm->m_area.MaxEdge - yblock;
+ v3s16 pmin = lua_istable(L, 3) ? check_v3s16(L, 3) : vm->m_area.MinEdge + yblock;
+ v3s16 pmax = lua_istable(L, 4) ? check_v3s16(L, 4) : vm->m_area.MaxEdge - yblock;
sortBoxVerticies(pmin, pmax);
if (!vm->m_area.contains(VoxelArea(pmin, pmax)))
@@ -228,10 +234,10 @@ int LuaVoxelManip::l_get_light_data(lua_State *L)
LuaVoxelManip *o = checkobject(L, 1);
MMVManip *vm = o->vm;
- int volume = vm->m_area.getVolume();
+ u32 volume = vm->m_area.getVolume();
lua_newtable(L);
- for (int i = 0; i != volume; i++) {
+ for (u32 i = 0; i != volume; i++) {
lua_Integer light = vm->m_data[i].param1;
lua_pushinteger(L, light);
lua_rawseti(L, -2, i + 1);
@@ -250,8 +256,8 @@ int LuaVoxelManip::l_set_light_data(lua_State *L)
if (!lua_istable(L, 2))
return 0;
- int volume = vm->m_area.getVolume();
- for (int i = 0; i != volume; i++) {
+ u32 volume = vm->m_area.getVolume();
+ for (u32 i = 0; i != volume; i++) {
lua_rawgeti(L, 2, i + 1);
u8 light = lua_tointeger(L, -1);
@@ -270,10 +276,10 @@ int LuaVoxelManip::l_get_param2_data(lua_State *L)
LuaVoxelManip *o = checkobject(L, 1);
MMVManip *vm = o->vm;
- int volume = vm->m_area.getVolume();
+ u32 volume = vm->m_area.getVolume();
lua_newtable(L);
- for (int i = 0; i != volume; i++) {
+ for (u32 i = 0; i != volume; i++) {
lua_Integer param2 = vm->m_data[i].param2;
lua_pushinteger(L, param2);
lua_rawseti(L, -2, i + 1);
@@ -292,8 +298,8 @@ int LuaVoxelManip::l_set_param2_data(lua_State *L)
if (!lua_istable(L, 2))
return 0;
- int volume = vm->m_area.getVolume();
- for (int i = 0; i != volume; i++) {
+ u32 volume = vm->m_area.getVolume();
+ for (u32 i = 0; i != volume; i++) {
lua_rawgeti(L, 2, i + 1);
u8 param2 = lua_tointeger(L, -1);
@@ -402,7 +408,7 @@ int LuaVoxelManip::create_object(lua_State *L)
Map *map = &(env->getMap());
LuaVoxelManip *o = (lua_istable(L, 1) && lua_istable(L, 2)) ?
- new LuaVoxelManip(map, read_v3s16(L, 1), read_v3s16(L, 2)) :
+ new LuaVoxelManip(map, check_v3s16(L, 1), check_v3s16(L, 2)) :
new LuaVoxelManip(map);
*(void **)(lua_newuserdata(L, sizeof(void *))) = o;