aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/scriptapi.cpp1510
1 files changed, 792 insertions, 718 deletions
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 8a4e0b0d9..f30aab41c 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -218,7 +218,7 @@ static ServerEnvironment* get_env(lua_State *L)
return (ServerEnvironment*)lua_touserdata(L, -1);
}
-static v3f readFloatPos(lua_State *L, int index)
+static v3f read_v3f(lua_State *L, int index)
{
v3f pos;
luaL_checktype(L, index, LUA_TTABLE);
@@ -231,7 +231,22 @@ static v3f readFloatPos(lua_State *L, int index)
lua_getfield(L, index, "z");
pos.Z = lua_tonumber(L, -1);
lua_pop(L, 1);
- pos *= BS; // Scale to internal format
+ return pos;
+}
+
+static v3f check_v3f(lua_State *L, int index)
+{
+ v3f pos;
+ luaL_checktype(L, index, LUA_TTABLE);
+ lua_getfield(L, index, "x");
+ pos.X = luaL_checknumber(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, index, "y");
+ pos.Y = luaL_checknumber(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, index, "z");
+ pos.Z = luaL_checknumber(L, -1);
+ lua_pop(L, 1);
return pos;
}
@@ -241,7 +256,12 @@ static void pushFloatPos(lua_State *L, v3f p)
push_v3f(L, p);
}
-static void pushpos(lua_State *L, v3s16 p)
+static v3f checkFloatPos(lua_State *L, int index)
+{
+ return check_v3f(L, index) * BS;
+}
+
+static void push_v3s16(lua_State *L, v3s16 p)
{
lua_newtable(L);
lua_pushnumber(L, p.X);
@@ -252,11 +272,18 @@ static void pushpos(lua_State *L, v3s16 p)
lua_setfield(L, -2, "z");
}
-static v3s16 readpos(lua_State *L, int index)
+static v3s16 read_v3s16(lua_State *L, int index)
{
// Correct rounding at <0
- v3f pf = readFloatPos(L, index);
- return floatToInt(pf, BS);
+ v3f pf = read_v3f(L, index);
+ return floatToInt(pf, 1.0);
+}
+
+static v3s16 check_v3s16(lua_State *L, int index)
+{
+ // Correct rounding at <0
+ v3f pf = check_v3f(L, index);
+ return floatToInt(pf, 1.0);
}
static void pushnode(lua_State *L, const MapNode &n, INodeDefManager *ndef)
@@ -390,6 +417,15 @@ static bool getboolfield(lua_State *L, int table,
return got;
}
+static std::string checkstringfield(lua_State *L, int table,
+ const char *fieldname)
+{
+ lua_getfield(L, table, fieldname);
+ std::string s = luaL_checkstring(L, -1);
+ lua_pop(L, 1);
+ return s;
+}
+
static std::string getstringfield_default(lua_State *L, int table,
const char *fieldname, const std::string &default_)
{
@@ -747,696 +783,6 @@ struct EnumString es_Diggability[] =
};
/*
- Global functions
-*/
-
-static int l_register_nodedef_defaults(lua_State *L)
-{
- luaL_checktype(L, 1, LUA_TTABLE);
-
- lua_pushvalue(L, 1); // Explicitly put parameter 1 on top of stack
- lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
-
- return 0;
-}
-
-// Register new object prototype
-// register_entity(name, prototype)
-static int l_register_entity(lua_State *L)
-{
- std::string name = luaL_checkstring(L, 1);
- check_modname_prefix(L, name);
- //infostream<<"register_entity: "<<name<<std::endl;
- luaL_checktype(L, 2, LUA_TTABLE);
-
- // Get minetest.registered_entities
- lua_getglobal(L, "minetest");
- lua_getfield(L, -1, "registered_entities");
- luaL_checktype(L, -1, LUA_TTABLE);
- int registered_entities = lua_gettop(L);
- lua_pushvalue(L, 2); // Object = param 2 -> stack top
- // registered_entities[name] = object
- lua_setfield(L, registered_entities, name.c_str());
-
- // Get registered object to top of stack
- lua_pushvalue(L, 2);
-
- // Set __index to point to itself
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "__index");
-
- // Set metatable.__index = metatable
- luaL_getmetatable(L, "minetest.entity");
- lua_pushvalue(L, -1); // duplicate metatable
- lua_setfield(L, -2, "__index");
- // Set object metatable
- lua_setmetatable(L, -2);
-
- return 0; /* number of results */
-}
-
-class LuaABM : public ActiveBlockModifier
-{
-private:
- lua_State *m_lua;
- int m_id;
-
- std::set<std::string> m_trigger_contents;
- std::set<std::string> m_required_neighbors;
- float m_trigger_interval;
- u32 m_trigger_chance;
-public:
- LuaABM(lua_State *L, int id,
- const std::set<std::string> &trigger_contents,
- const std::set<std::string> &required_neighbors,
- float trigger_interval, u32 trigger_chance):
- m_lua(L),
- m_id(id),
- m_trigger_contents(trigger_contents),
- m_required_neighbors(required_neighbors),
- m_trigger_interval(trigger_interval),
- m_trigger_chance(trigger_chance)
- {
- }
- virtual std::set<std::string> getTriggerContents()
- {
- return m_trigger_contents;
- }
- virtual std::set<std::string> getRequiredNeighbors()
- {
- return m_required_neighbors;
- }
- virtual float getTriggerInterval()
- {
- return m_trigger_interval;
- }
- virtual u32 getTriggerChance()
- {
- return m_trigger_chance;
- }
- virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
- u32 active_object_count, u32 active_object_count_wider)
- {
- lua_State *L = m_lua;
-
- realitycheck(L);
- assert(lua_checkstack(L, 20));
- StackUnroller stack_unroller(L);
-
- // Get minetest.registered_abms
- lua_getglobal(L, "minetest");
- lua_getfield(L, -1, "registered_abms");
- luaL_checktype(L, -1, LUA_TTABLE);
- int registered_abms = lua_gettop(L);
-
- // Get minetest.registered_abms[m_id]
- lua_pushnumber(L, m_id);
- lua_gettable(L, registered_abms);
- if(lua_isnil(L, -1))
- assert(0);
-
- // Call action
- luaL_checktype(L, -1, LUA_TTABLE);
- lua_getfield(L, -1, "action");
- luaL_checktype(L, -1, LUA_TFUNCTION);
- pushpos(L, p);
- 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, 0))
- script_error(L, "error: %s", lua_tostring(L, -1));
- }
-};
-
-// register_abm({...})
-static int l_register_abm(lua_State *L)
-{
- //infostream<<"register_abm"<<std::endl;
- luaL_checktype(L, 1, LUA_TTABLE);
-
- // Get minetest.registered_abms
- lua_getglobal(L, "minetest");
- lua_getfield(L, -1, "registered_abms");
- luaL_checktype(L, -1, LUA_TTABLE);
- int registered_abms = lua_gettop(L);
-
- int id = 1;
- // Find free id
- for(;;){
- lua_pushnumber(L, id);
- lua_gettable(L, registered_abms);
- if(lua_isnil(L, -1))
- break;
- lua_pop(L, 1);
- id++;
- }
- lua_pop(L, 1);
-
- infostream<<"register_abm: id="<<id<<std::endl;
-
- // registered_abms[id] = spec
- lua_pushnumber(L, id);
- lua_pushvalue(L, 1);
- lua_settable(L, registered_abms);
-
- return 0; /* number of results */
-}
-
-// register_tool(name, {lots of stuff})
-static int l_register_tool(lua_State *L)
-{
- std::string name = luaL_checkstring(L, 1);
- check_modname_prefix(L, name);
- //infostream<<"register_tool: "<<name<<std::endl;
- luaL_checktype(L, 2, LUA_TTABLE);
- int table = 2;
-
- // Get the writable tool definition manager from the server
- IWritableToolDefManager *tooldef =
- get_server(L)->getWritableToolDefManager();
-
- ToolDefinition def = read_tool_definition(L, table);
-
- tooldef->registerTool(name, def);
- return 0; /* number of results */
-}
-
-// register_craftitem(name, {lots of stuff})
-static int l_register_craftitem(lua_State *L)
-{
- std::string name = luaL_checkstring(L, 1);
- check_modname_prefix(L, name);
- //infostream<<"register_craftitem: "<<name<<std::endl;
- luaL_checktype(L, 2, LUA_TTABLE);
- int table = 2;
-
- // Get the writable CraftItem definition manager from the server
- IWritableCraftItemDefManager *craftitemdef =
- get_server(L)->getWritableCraftItemDefManager();
-
- // Check if on_drop is defined
- lua_getfield(L, table, "on_drop");
- bool got_on_drop = !lua_isnil(L, -1);
- lua_pop(L, 1);
-
- // Check if on_use is defined
- lua_getfield(L, table, "on_use");
- bool got_on_use = !lua_isnil(L, -1);
- lua_pop(L, 1);
-
- CraftItemDefinition def;
-
- getstringfield(L, table, "image", def.imagename);
- getstringfield(L, table, "cookresult_itemstring", def.cookresult_item);
- getfloatfield(L, table, "furnace_cooktime", def.furnace_cooktime);
- getfloatfield(L, table, "furnace_burntime", def.furnace_burntime);
- def.usable = getboolfield_default(L, table, "usable", got_on_use);
- getboolfield(L, table, "liquids_pointable", def.liquids_pointable);
- def.dropcount = getintfield_default(L, table, "dropcount", def.dropcount);
- def.stack_max = getintfield_default(L, table, "stack_max", def.stack_max);
-
- // If an on_drop callback is defined, force dropcount to 1
- if (got_on_drop)
- def.dropcount = 1;
-
- // Register it
- craftitemdef->registerCraftItem(name, def);
-
- lua_pushvalue(L, table);
- scriptapi_add_craftitem(L, name.c_str());
-
- return 0; /* number of results */
-}
-
-// register_node(name, {lots of stuff})
-static int l_register_node(lua_State *L)
-{
- std::string name = luaL_checkstring(L, 1);
- check_modname_prefix(L, name);
- //infostream<<"register_node: "<<name<<std::endl;
- luaL_checktype(L, 2, LUA_TTABLE);
- int nodedef_table = 2;
-
- // Get the writable node definition manager from the server
- IWritableNodeDefManager *nodedef =
- get_server(L)->getWritableNodeDefManager();
-
- // Get default node definition from registry
- lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
- int nodedef_default = lua_gettop(L);
-
- /*
- Add to minetest.registered_nodes with default as metatable
- */
-
- // Get the node definition table given as parameter
- lua_pushvalue(L, nodedef_table);
-
- // Set __index to point to itself
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "__index");
-
- // Set nodedef_default as metatable for the definition
- lua_pushvalue(L, nodedef_default);
- lua_setmetatable(L, nodedef_table);
-
- // minetest.registered_nodes[name] = nodedef
- lua_getglobal(L, "minetest");
- lua_getfield(L, -1, "registered_nodes");
- luaL_checktype(L, -1, LUA_TTABLE);
- lua_pushstring(L, name.c_str());
- lua_pushvalue(L, nodedef_table);
- lua_settable(L, -3);
-
- /*
- Create definition
- */
-
- ContentFeatures f;
-
- // Default to getting the corresponding NodeItem when dug
- f.dug_item = std::string("NodeItem \"")+name+"\" 1";
-
- // Default to unknown_block.png as all textures
- f.setAllTextures("unknown_block.png");
-
- /*
- Read definiton from Lua
- */
-
- f.name = name;
-
- /* Visual definition */
-
- f.drawtype = (NodeDrawType)getenumfield(L, nodedef_table, "drawtype", es_DrawType,
- NDT_NORMAL);
- getfloatfield(L, nodedef_table, "visual_scale", f.visual_scale);
-
- lua_getfield(L, nodedef_table, "tile_images");
- if(lua_istable(L, -1)){
- int table = lua_gettop(L);
- lua_pushnil(L);
- int i = 0;
- while(lua_next(L, table) != 0){
- // key at index -2 and value at index -1
- if(lua_isstring(L, -1))
- f.tname_tiles[i] = lua_tostring(L, -1);
- else
- f.tname_tiles[i] = "";
- // removes value, keeps key for next iteration
- lua_pop(L, 1);
- i++;
- if(i==6){
- lua_pop(L, 1);
- break;
- }
- }
- // Copy last value to all remaining textures
- if(i >= 1){
- std::string lastname = f.tname_tiles[i-1];
- while(i < 6){
- f.tname_tiles[i] = lastname;
- i++;
- }
- }
- }
- lua_pop(L, 1);
-
- getstringfield(L, nodedef_table, "inventory_image", f.tname_inventory);
-
- lua_getfield(L, nodedef_table, "special_materials");
- if(lua_istable(L, -1)){
- int table = lua_gettop(L);
- lua_pushnil(L);
- int i = 0;
- while(lua_next(L, table) != 0){
- // key at index -2 and value at index -1
- int smtable = lua_gettop(L);
- std::string tname = getstringfield_default(
- L, smtable, "image", "");
- bool backface_culling = getboolfield_default(
- L, smtable, "backface_culling", true);
- MaterialSpec mspec(tname, backface_culling);
- f.setSpecialMaterial(i, mspec);
- // removes value, keeps key for next iteration
- lua_pop(L, 1);
- i++;
- if(i==6){
- lua_pop(L, 1);
- break;
- }
- }
- }
- lua_pop(L, 1);
-
- f.alpha = getintfield_default(L, nodedef_table, "alpha", 255);
-
- /* Other stuff */
-
- lua_getfield(L, nodedef_table, "post_effect_color");
- if(!lua_isnil(L, -1))
- f.post_effect_color = readARGB8(L, -1);
- lua_pop(L, 1);
-
- f.param_type = (ContentParamType)getenumfield(L, nodedef_table, "paramtype",
- es_ContentParamType, CPT_NONE);
-
- // True for all ground-like things like stone and mud, false for eg. trees
- getboolfield(L, nodedef_table, "is_ground_content", f.is_ground_content);
- f.light_propagates = (f.param_type == CPT_LIGHT);
- warn_if_field_exists(L, nodedef_table, "light_propagates",
- "deprecated: determined from paramtype");
- getboolfield(L, nodedef_table, "sunlight_propagates", f.sunlight_propagates);
- // This is used for collision detection.
- // Also for general solidness queries.
- getboolfield(L, nodedef_table, "walkable", f.walkable);
- // Player can point to these
- getboolfield(L, nodedef_table, "pointable", f.pointable);
- // Player can dig these
- getboolfield(L, nodedef_table, "diggable", f.diggable);
- // Player can climb these
- getboolfield(L, nodedef_table, "climbable", f.climbable);
- // Player can build on these
- getboolfield(L, nodedef_table, "buildable_to", f.buildable_to);
- // If true, param2 is set to direction when placed. Used for torches.
- // NOTE: the direction format is quite inefficient and should be changed
- getboolfield(L, nodedef_table, "wall_mounted", f.wall_mounted);
- // Whether this content type often contains mineral.
- // Used for texture atlas creation.
- // Currently only enabled for CONTENT_STONE.
- getboolfield(L, nodedef_table, "often_contains_mineral", f.often_contains_mineral);
- // Inventory item string as which the node appears in inventory when dug.
- // Mineral overrides this.
- getstringfield(L, nodedef_table, "dug_item", f.dug_item);
- // Extra dug item and its rarity
- getstringfield(L, nodedef_table, "extra_dug_item", f.extra_dug_item);
- // Usual get interval for extra dug item
- getintfield(L, nodedef_table, "extra_dug_item_rarity", f.extra_dug_item_rarity);
- // Metadata name of node (eg. "furnace")
- getstringfield(L, nodedef_table, "metadata_name", f.metadata_name);
- // Whether the node is non-liquid, source liquid or flowing liquid
- f.liquid_type = (LiquidType)getenumfield(L, nodedef_table, "liquidtype",
- es_LiquidType, LIQUID_NONE);
- // If the content is liquid, this is the flowing version of the liquid.
- getstringfield(L, nodedef_table, "liquid_alternative_flowing",
- f.liquid_alternative_flowing);
- // If the content is liquid, this is the source version of the liquid.
- getstringfield(L, nodedef_table, "liquid_alternative_source",
- f.liquid_alternative_source);
- // Viscosity for fluid flow, ranging from 1 to 7, with
- // 1 giving almost instantaneous propagation and 7 being
- // the slowest possible
- f.liquid_viscosity = getintfield_default(L, nodedef_table,
- "liquid_viscosity", f.liquid_viscosity);
- // Amount of light the node emits
- f.light_source = getintfield_default(L, nodedef_table,
- "light_source", f.light_source);
- f.damage_per_second = getintfield_default(L, nodedef_table,
- "damage_per_second", f.damage_per_second);
-
- lua_getfield(L, nodedef_table, "selection_box");
- if(lua_istable(L, -1)){
- f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
- es_NodeBoxType, NODEBOX_REGULAR);
-
- lua_getfield(L, -1, "fixed");
- if(lua_istable(L, -1))
- f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
- lua_pop(L, 1);
-
- lua_getfield(L, -1, "wall_top");
- if(lua_istable(L, -1))
- f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
- lua_pop(L, 1);
-
- lua_getfield(L, -1, "wall_bottom");
- if(lua_istable(L, -1))
- f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
- lua_pop(L, 1);
-
- lua_getfield(L, -1, "wall_side");
- if(lua_istable(L, -1))
- f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
- lua_pop(L, 1);
- }
- lua_pop(L, 1);
-
- lua_getfield(L, nodedef_table, "material");
- if(lua_istable(L, -1)){
- f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
- es_Diggability, DIGGABLE_NORMAL);
-
- getfloatfield(L, -1, "constant_time", f.material.constant_time);
- getfloatfield(L, -1, "weight", f.material.weight);
- getfloatfield(L, -1, "crackiness", f.material.crackiness);
- getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
- getfloatfield(L, -1, "cuttability", f.material.cuttability);
- getfloatfield(L, -1, "flammability", f.material.flammability);
- }
- lua_pop(L, 1);
-
- getstringfield(L, nodedef_table, "cookresult_itemstring", f.cookresult_item);
- getfloatfield(L, nodedef_table, "furnace_cooktime", f.furnace_cooktime);
- getfloatfield(L, nodedef_table, "furnace_burntime", f.furnace_burntime);
-
- /*
- Register it
- */
-
- nodedef->set(name, f);
-
- return 0; /* number of results */
-}
-
-// alias_node(name, convert_to_name)
-static int l_alias_node(lua_State *L)
-{
- std::string name = luaL_checkstring(L, 1);
- std::string convert_to = luaL_checkstring(L, 2);
-
- // Get the writable node definition manager from the server
- IWritableNodeDefManager *nodedef =
- get_server(L)->getWritableNodeDefManager();
-
- nodedef->setAlias(name, convert_to);
-
- return 0; /* number of results */
-}
-
-// alias_tool(name, convert_to_name)
-static int l_alias_tool(lua_State *L)
-{
- std::string name = luaL_checkstring(L, 1);
- std::string convert_to = luaL_checkstring(L, 2);
-
- // Get the writable tool definition manager from the server
- IWritableToolDefManager *tooldef =
- get_server(L)->getWritableToolDefManager();
-
- tooldef->setAlias(name, convert_to);
-
- return 0; /* number of results */
-}
-
-// alias_craftitem(name, convert_to_name)
-static int l_alias_craftitem(lua_State *L)
-{
- std::string name = luaL_checkstring(L, 1);
- std::string convert_to = luaL_checkstring(L, 2);
-
- // Get the writable CraftItem definition manager from the server
- IWritableCraftItemDefManager *craftitemdef =
- get_server(L)->getWritableCraftItemDefManager();
-
- craftitemdef->setAlias(name, convert_to);
-
- return 0; /* number of results */
-}
-
-// register_craft({output=item, recipe={{item00,item10},{item01,item11}})
-static int l_register_craft(lua_State *L)
-{
- //infostream<<"register_craft"<<std::endl;
- luaL_checktype(L, 1, LUA_TTABLE);
- int table0 = 1;
-
- // Get the writable craft definition manager from the server
- IWritableCraftDefManager *craftdef =
- get_server(L)->getWritableCraftDefManager();
-
- std::string output;
- int width = 0;
- std::vector<std::string> input;
-
- lua_getfield(L, table0, "output");
- luaL_checktype(L, -1, LUA_TSTRING);
- if(lua_isstring(L, -1))
- output = lua_tostring(L, -1);
- lua_pop(L, 1);
-
- lua_getfield(L, table0, "recipe");
- luaL_checktype(L, -1, LUA_TTABLE);
- if(lua_istable(L, -1)){
- int table1 = lua_gettop(L);
- lua_pushnil(L);
- int rowcount = 0;
- while(lua_next(L, table1) != 0){
- int colcount = 0;
- // key at index -2 and value at index -1
- luaL_checktype(L, -1, LUA_TTABLE);
- if(lua_istable(L, -1)){
- int table2 = lua_gettop(L);
- lua_pushnil(L);
- while(lua_next(L, table2) != 0){
- // key at index -2 and value at index -1
- luaL_checktype(L, -1, LUA_TSTRING);
- input.push_back(lua_tostring(L, -1));
- // removes value, keeps key for next iteration
- lua_pop(L, 1);
- colcount++;
- }
- }
- if(rowcount == 0){
- width = colcount;
- } else {
- if(colcount != width){
- std::string error;
- error += "Invalid crafting recipe (output=\""
- + output + "\")";
- throw LuaError(L, error);
- }
- }
- // removes value, keeps key for next iteration
- lua_pop(L, 1);
- rowcount++;
- }
- }
- lua_pop(L, 1);
-
- CraftDefinition def(output, width, input);
- craftdef->registerCraft(def);
-
- return 0; /* number of results */
-}
-
-// setting_get(name)
-static int l_setting_get(lua_State *L)
-{
- const char *name = luaL_checkstring(L, 1);
- try{
- std::string value = g_settings->get(name);
- lua_pushstring(L, value.c_str());
- } catch(SettingNotFoundException &e){
- lua_pushnil(L);
- }
- return 1;
-}
-
-// setting_getbool(name)
-static int l_setting_getbool(lua_State *L)
-{
- const char *name = luaL_checkstring(L, 1);
- try{
- bool value = g_settings->getBool(name);
- lua_pushboolean(L, value);
- } catch(SettingNotFoundException &e){
- lua_pushnil(L);
- }
- return 1;
-}
-
-// chat_send_all(text)
-static int l_chat_send_all(lua_State *L)
-{
- const char *text = luaL_checkstring(L, 1);
- // Get server from registry
- Server *server = get_server(L);
- // Send
- server->notifyPlayers(narrow_to_wide(text));
- return 0;
-}
-
-// chat_send_player(name, text)
-static int l_chat_send_player(lua_State *L)
-{
- const char *name = luaL_checkstring(L, 1);
- const char *text = luaL_checkstring(L, 2);
- // Get server from registry
- Server *server = get_server(L);
- // Send
- server->notifyPlayer(name, narrow_to_wide(text));
- return 0;
-}
-
-// get_player_privs(name, text)
-static int l_get_player_privs(lua_State *L)
-{
- const char *name = luaL_checkstring(L, 1);
- // Get server from registry
- Server *server = get_server(L);
- // Do it
- lua_newtable(L);
- int table = lua_gettop(L);
- u64 privs_i = server->getPlayerAuthPrivs(name);
- // Special case for the "name" setting (local player / server owner)
- if(name == g_settings->get("name"))
- privs_i = PRIV_ALL;
- std::set<std::string> privs_s = privsToSet(privs_i);
- for(std::set<std::string>::const_iterator
- i = privs_s.begin(); i != privs_s.end(); i++){
- lua_pushboolean(L, true);
- lua_setfield(L, table, i->c_str());
- }
- lua_pushvalue(L, table);
- return 1;
-}
-
-// get_modpath(modname)
-static int l_get_modpath(lua_State *L)
-{
- const char *modname = luaL_checkstring(L, 1);
- // Get server from registry
- lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
- Server *server = (Server*)lua_touserdata(L, -1);
- // Do it
- const ModSpec *mod = server->getModSpec(modname);
- if(!mod){
- lua_pushnil(L);
- return 1;
- }
- lua_pushstring(L, mod->path.c_str());
- return 1;
-}
-
-static const struct luaL_Reg minetest_f [] = {
- {"register_nodedef_defaults", l_register_nodedef_defaults},
- {"register_entity", l_register_entity},
- {"register_tool", l_register_tool},
- {"register_craftitem", l_register_craftitem},
- {"register_node", l_register_node},
- {"register_craft", l_register_craft},
- {"register_abm", l_register_abm},
- {"alias_node", l_alias_node},
- {"alias_tool", l_alias_tool},
- {"alias_craftitem", l_alias_craftitem},
- {"setting_get", l_setting_get},
- {"setting_getbool", l_setting_getbool},
- {"chat_send_all", l_chat_send_all},
- {"chat_send_player", l_chat_send_player},
- {"get_player_privs", l_get_player_privs},
- {"get_modpath", l_get_modpath},
- {NULL, NULL}
-};
-
-/*
- LuaEntity functions
-*/
-
-static const struct luaL_Reg minetest_entity_m [] = {
- {NULL, NULL}
-};
-
-/*
Getters for stuff in main tables
*/
@@ -1673,6 +1019,20 @@ private:
return 0;
}
+ // get_size(self, listname)
+ static int l_get_size(lua_State *L)
+ {
+ InvRef *ref = checkobject(L, 1);
+ const char *listname = luaL_checkstring(L, 2);
+ InventoryList *list = getlist(L, ref, listname);
+ if(list){
+ lua_pushinteger(L, list->getSize());
+ } else {
+ lua_pushinteger(L, 0);
+ }
+ return 1;
+ }
+
// set_size(self, listname, size)
static int l_set_size(lua_State *L)
{
@@ -1790,6 +1150,7 @@ public:
};
const char InvRef::className[] = "InvRef";
const luaL_reg InvRef::methods[] = {
+ method(InvRef, get_size),
method(InvRef, set_size),
method(InvRef, get_stack),
method(InvRef, set_stack),
@@ -2256,7 +1617,7 @@ private:
ServerActiveObject *co = getobject(ref);
if(co == NULL) return 0;
// pos
- v3f pos = readFloatPos(L, 2);
+ v3f pos = checkFloatPos(L, 2);
// Do it
co->setPos(pos);
return 0;
@@ -2270,7 +1631,7 @@ private:
ServerActiveObject *co = getobject(ref);
if(co == NULL) return 0;
// pos
- v3f pos = readFloatPos(L, 2);
+ v3f pos = checkFloatPos(L, 2);
// continuous
bool continuous = lua_toboolean(L, 3);
// Do it
@@ -2434,7 +1795,7 @@ private:
LuaEntitySAO *co = getluaobject(ref);
if(co == NULL) return 0;
// pos
- v3f pos = readFloatPos(L, 2);
+ v3f pos = checkFloatPos(L, 2);
// Do it
co->setVelocity(pos);
return 0;
@@ -2447,7 +1808,7 @@ private:
LuaEntitySAO *co = getluaobject(ref);
if(co == NULL) return 0;
// pos
- v3f pos = readFloatPos(L, 2);
+ v3f pos = checkFloatPos(L, 2);
// Do it
co->setAcceleration(pos);
return 0;
@@ -2743,7 +2104,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// pos
- v3s16 pos = readpos(L, 2);
+ v3s16 pos = read_v3s16(L, 2);
// content
MapNode n = readnode(L, 3, env->getGameDef()->ndef());
// Do it
@@ -2761,7 +2122,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// pos
- v3s16 pos = readpos(L, 2);
+ v3s16 pos = read_v3s16(L, 2);
// Do it
bool succeeded = env->getMap().removeNodeWithEvent(pos);
lua_pushboolean(L, succeeded);
@@ -2777,7 +2138,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// pos
- v3s16 pos = readpos(L, 2);
+ v3s16 pos = read_v3s16(L, 2);
// Do it
MapNode n = env->getMap().getNodeNoEx(pos);
// Return node
@@ -2794,7 +2155,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// pos
- v3s16 pos = readpos(L, 2);
+ v3s16 pos = read_v3s16(L, 2);
// Do it
try{
MapNode n = env->getMap().getNode(pos);
@@ -2817,7 +2178,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// Do it
- v3s16 pos = readpos(L, 2);
+ v3s16 pos = read_v3s16(L, 2);
u32 time_of_day = env->getTimeOfDay();
if(lua_isnumber(L, 3))
time_of_day = 24000.0 * lua_tonumber(L, 3);
@@ -2845,7 +2206,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// pos
- v3f pos = readFloatPos(L, 2);
+ v3f pos = checkFloatPos(L, 2);
// content
const char *name = luaL_checkstring(L, 3);
// Do it
@@ -2863,7 +2224,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// pos
- v3f pos = readFloatPos(L, 2);
+ v3f pos = checkFloatPos(L, 2);
// inventorystring
const char *inventorystring = luaL_checkstring(L, 3);
// Do it
@@ -2881,7 +2242,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// pos
- v3f pos = readFloatPos(L, 2);
+ v3f pos = checkFloatPos(L, 2);
// Do it
ServerActiveObject *obj = new RatSAO(env, pos);
env->addActiveObject(obj);
@@ -2897,7 +2258,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// pos
- v3f pos = readFloatPos(L, 2);
+ v3f pos = checkFloatPos(L, 2);
// Do it
ServerActiveObject *obj = new FireflySAO(env, pos);
env->addActiveObject(obj);
@@ -2912,7 +2273,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// Do it
- v3s16 p = readpos(L, 2);
+ v3s16 p = read_v3s16(L, 2);
NodeMetaRef::create(L, p, env);
return 1;
}
@@ -2948,7 +2309,7 @@ private:
ServerEnvironment *env = o->m_env;
if(env == NULL) return 0;
// Do it
- v3f pos = readFloatPos(L, 2);
+ v3f pos = checkFloatPos(L, 2);
float radius = luaL_checknumber(L, 3) * BS;
std::set<u16> ids = env->getObjectsInsideRadius(pos, radius);
lua_newtable(L);
@@ -3047,6 +2408,719 @@ const luaL_reg EnvRef::methods[] = {
};
/*
+ Global functions
+*/
+
+static int l_register_nodedef_defaults(lua_State *L)
+{
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ lua_pushvalue(L, 1); // Explicitly put parameter 1 on top of stack
+ lua_setfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
+
+ return 0;
+}
+
+// Register new object prototype
+// register_entity(name, prototype)
+static int l_register_entity(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ check_modname_prefix(L, name);
+ //infostream<<"register_entity: "<<name<<std::endl;
+ luaL_checktype(L, 2, LUA_TTABLE);
+
+ // Get minetest.registered_entities
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "registered_entities");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int registered_entities = lua_gettop(L);
+ lua_pushvalue(L, 2); // Object = param 2 -> stack top
+ // registered_entities[name] = object
+ lua_setfield(L, registered_entities, name.c_str());
+
+ // Get registered object to top of stack
+ lua_pushvalue(L, 2);
+
+ // Set __index to point to itself
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+
+ // Set metatable.__index = metatable
+ luaL_getmetatable(L, "minetest.entity");
+ lua_pushvalue(L, -1); // duplicate metatable
+ lua_setfield(L, -2, "__index");
+ // Set object metatable
+ lua_setmetatable(L, -2);
+
+ return 0; /* number of results */
+}
+
+class LuaABM : public ActiveBlockModifier
+{
+private:
+ lua_State *m_lua;
+ int m_id;
+
+ std::set<std::string> m_trigger_contents;
+ std::set<std::string> m_required_neighbors;
+ float m_trigger_interval;
+ u32 m_trigger_chance;
+public:
+ LuaABM(lua_State *L, int id,
+ const std::set<std::string> &trigger_contents,
+ const std::set<std::string> &required_neighbors,
+ float trigger_interval, u32 trigger_chance):
+ m_lua(L),
+ m_id(id),
+ m_trigger_contents(trigger_contents),
+ m_required_neighbors(required_neighbors),
+ m_trigger_interval(trigger_interval),
+ m_trigger_chance(trigger_chance)
+ {
+ }
+ virtual std::set<std::string> getTriggerContents()
+ {
+ return m_trigger_contents;
+ }
+ virtual std::set<std::string> getRequiredNeighbors()
+ {
+ return m_required_neighbors;
+ }
+ virtual float getTriggerInterval()
+ {
+ return m_trigger_interval;
+ }
+ virtual u32 getTriggerChance()
+ {
+ return m_trigger_chance;
+ }
+ virtual void trigger(ServerEnvironment *env, v3s16 p, MapNode n,
+ u32 active_object_count, u32 active_object_count_wider)
+ {
+ lua_State *L = m_lua;
+
+ realitycheck(L);
+ assert(lua_checkstack(L, 20));
+ StackUnroller stack_unroller(L);
+
+ // Get minetest.registered_abms
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "registered_abms");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int registered_abms = lua_gettop(L);
+
+ // Get minetest.registered_abms[m_id]
+ lua_pushnumber(L, m_id);
+ lua_gettable(L, registered_abms);
+ if(lua_isnil(L, -1))
+ assert(0);
+
+ // Call action
+ luaL_checktype(L, -1, LUA_TTABLE);
+ lua_getfield(L, -1, "action");
+ luaL_checktype(L, -1, LUA_TFUNCTION);
+ push_v3s16(L, p);
+ 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, 0))
+ script_error(L, "error: %s", lua_tostring(L, -1));
+ }
+};
+
+// register_abm({...})
+static int l_register_abm(lua_State *L)
+{
+ //infostream<<"register_abm"<<std::endl;
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ // Get minetest.registered_abms
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "registered_abms");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ int registered_abms = lua_gettop(L);
+
+ int id = 1;
+ // Find free id
+ for(;;){
+ lua_pushnumber(L, id);
+ lua_gettable(L, registered_abms);
+ if(lua_isnil(L, -1))
+ break;
+ lua_pop(L, 1);
+ id++;
+ }
+ lua_pop(L, 1);
+
+ infostream<<"register_abm: id="<<id<<std::endl;
+
+ // registered_abms[id] = spec
+ lua_pushnumber(L, id);
+ lua_pushvalue(L, 1);
+ lua_settable(L, registered_abms);
+
+ return 0; /* number of results */
+}
+
+// register_tool(name, {lots of stuff})
+static int l_register_tool(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ check_modname_prefix(L, name);
+ //infostream<<"register_tool: "<<name<<std::endl;
+ luaL_checktype(L, 2, LUA_TTABLE);
+ int table = 2;
+
+ // Get the writable tool definition manager from the server
+ IWritableToolDefManager *tooldef =
+ get_server(L)->getWritableToolDefManager();
+
+ ToolDefinition def = read_tool_definition(L, table);
+
+ tooldef->registerTool(name, def);
+ return 0; /* number of results */
+}
+
+// register_craftitem(name, {lots of stuff})
+static int l_register_craftitem(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ check_modname_prefix(L, name);
+ //infostream<<"register_craftitem: "<<name<<std::endl;
+ luaL_checktype(L, 2, LUA_TTABLE);
+ int table = 2;
+
+ // Get the writable CraftItem definition manager from the server
+ IWritableCraftItemDefManager *craftitemdef =
+ get_server(L)->getWritableCraftItemDefManager();
+
+ // Check if on_drop is defined
+ lua_getfield(L, table, "on_drop");
+ bool got_on_drop = !lua_isnil(L, -1);
+ lua_pop(L, 1);
+
+ // Check if on_use is defined
+ lua_getfield(L, table, "on_use");
+ bool got_on_use = !lua_isnil(L, -1);
+ lua_pop(L, 1);
+
+ CraftItemDefinition def;
+
+ getstringfield(L, table, "image", def.imagename);
+ getstringfield(L, table, "cookresult_itemstring", def.cookresult_item);
+ getfloatfield(L, table, "furnace_cooktime", def.furnace_cooktime);
+ getfloatfield(L, table, "furnace_burntime", def.furnace_burntime);
+ def.usable = getboolfield_default(L, table, "usable", got_on_use);
+ getboolfield(L, table, "liquids_pointable", def.liquids_pointable);
+ def.dropcount = getintfield_default(L, table, "dropcount", def.dropcount);
+ def.stack_max = getintfield_default(L, table, "stack_max", def.stack_max);
+
+ // If an on_drop callback is defined, force dropcount to 1
+ if (got_on_drop)
+ def.dropcount = 1;
+
+ // Register it
+ craftitemdef->registerCraftItem(name, def);
+
+ lua_pushvalue(L, table);
+ scriptapi_add_craftitem(L, name.c_str());
+
+ return 0; /* number of results */
+}
+
+// register_node(name, {lots of stuff})
+static int l_register_node(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ check_modname_prefix(L, name);
+ //infostream<<"register_node: "<<name<<std::endl;
+ luaL_checktype(L, 2, LUA_TTABLE);
+ int nodedef_table = 2;
+
+ // Get the writable node definition manager from the server
+ IWritableNodeDefManager *nodedef =
+ get_server(L)->getWritableNodeDefManager();
+
+ // Get default node definition from registry
+ lua_getfield(L, LUA_REGISTRYINDEX, "minetest_nodedef_default");
+ int nodedef_default = lua_gettop(L);
+
+ /*
+ Add to minetest.registered_nodes with default as metatable
+ */
+
+ // Get the node definition table given as parameter
+ lua_pushvalue(L, nodedef_table);
+
+ // Set __index to point to itself
+ lua_pushvalue(L, -1);
+ lua_setfield(L, -2, "__index");
+
+ // Set nodedef_default as metatable for the definition
+ lua_pushvalue(L, nodedef_default);
+ lua_setmetatable(L, nodedef_table);
+
+ // minetest.registered_nodes[name] = nodedef
+ lua_getglobal(L, "minetest");
+ lua_getfield(L, -1, "registered_nodes");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ lua_pushstring(L, name.c_str());
+ lua_pushvalue(L, nodedef_table);
+ lua_settable(L, -3);
+
+ /*
+ Create definition
+ */
+
+ ContentFeatures f;
+
+ // Default to getting the corresponding NodeItem when dug
+ f.dug_item = std::string("NodeItem \"")+name+"\" 1";
+
+ // Default to unknown_block.png as all textures
+ f.setAllTextures("unknown_block.png");
+
+ /*
+ Read definiton from Lua
+ */
+
+ f.name = name;
+
+ /* Visual definition */
+
+ f.drawtype = (NodeDrawType)getenumfield(L, nodedef_table, "drawtype", es_DrawType,
+ NDT_NORMAL);
+ getfloatfield(L, nodedef_table, "visual_scale", f.visual_scale);
+
+ lua_getfield(L, nodedef_table, "tile_images");
+ if(lua_istable(L, -1)){
+ int table = lua_gettop(L);
+ lua_pushnil(L);
+ int i = 0;
+ while(lua_next(L, table) != 0){
+ // key at index -2 and value at index -1
+ if(lua_isstring(L, -1))
+ f.tname_tiles[i] = lua_tostring(L, -1);
+ else
+ f.tname_tiles[i] = "";
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ i++;
+ if(i==6){
+ lua_pop(L, 1);
+ break;
+ }
+ }
+ // Copy last value to all remaining textures
+ if(i >= 1){
+ std::string lastname = f.tname_tiles[i-1];
+ while(i < 6){
+ f.tname_tiles[i] = lastname;
+ i++;
+ }
+ }
+ }
+ lua_pop(L, 1);
+
+ getstringfield(L, nodedef_table, "inventory_image", f.tname_inventory);
+
+ lua_getfield(L, nodedef_table, "special_materials");
+ if(lua_istable(L, -1)){
+ int table = lua_gettop(L);
+ lua_pushnil(L);
+ int i = 0;
+ while(lua_next(L, table) != 0){
+ // key at index -2 and value at index -1
+ int smtable = lua_gettop(L);
+ std::string tname = getstringfield_default(
+ L, smtable, "image", "");
+ bool backface_culling = getboolfield_default(
+ L, smtable, "backface_culling", true);
+ MaterialSpec mspec(tname, backface_culling);
+ f.setSpecialMaterial(i, mspec);
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ i++;
+ if(i==6){
+ lua_pop(L, 1);
+ break;
+ }
+ }
+ }
+ lua_pop(L, 1);
+
+ f.alpha = getintfield_default(L, nodedef_table, "alpha", 255);
+
+ /* Other stuff */
+
+ lua_getfield(L, nodedef_table, "post_effect_color");
+ if(!lua_isnil(L, -1))
+ f.post_effect_color = readARGB8(L, -1);
+ lua_pop(L, 1);
+
+ f.param_type = (ContentParamType)getenumfield(L, nodedef_table, "paramtype",
+ es_ContentParamType, CPT_NONE);
+
+ // True for all ground-like things like stone and mud, false for eg. trees
+ getboolfield(L, nodedef_table, "is_ground_content", f.is_ground_content);
+ f.light_propagates = (f.param_type == CPT_LIGHT);
+ warn_if_field_exists(L, nodedef_table, "light_propagates",
+ "deprecated: determined from paramtype");
+ getboolfield(L, nodedef_table, "sunlight_propagates", f.sunlight_propagates);
+ // This is used for collision detection.
+ // Also for general solidness queries.
+ getboolfield(L, nodedef_table, "walkable", f.walkable);
+ // Player can point to these
+ getboolfield(L, nodedef_table, "pointable", f.pointable);
+ // Player can dig these
+ getboolfield(L, nodedef_table, "diggable", f.diggable);
+ // Player can climb these
+ getboolfield(L, nodedef_table, "climbable", f.climbable);
+ // Player can build on these
+ getboolfield(L, nodedef_table, "buildable_to", f.buildable_to);
+ // If true, param2 is set to direction when placed. Used for torches.
+ // NOTE: the direction format is quite inefficient and should be changed
+ getboolfield(L, nodedef_table, "wall_mounted", f.wall_mounted);
+ // Whether this content type often contains mineral.
+ // Used for texture atlas creation.
+ // Currently only enabled for CONTENT_STONE.
+ getboolfield(L, nodedef_table, "often_contains_mineral", f.often_contains_mineral);
+ // Inventory item string as which the node appears in inventory when dug.
+ // Mineral overrides this.
+ getstringfield(L, nodedef_table, "dug_item", f.dug_item);
+ // Extra dug item and its rarity
+ getstringfield(L, nodedef_table, "extra_dug_item", f.extra_dug_item);
+ // Usual get interval for extra dug item
+ getintfield(L, nodedef_table, "extra_dug_item_rarity", f.extra_dug_item_rarity);
+ // Metadata name of node (eg. "furnace")
+ getstringfield(L, nodedef_table, "metadata_name", f.metadata_name);
+ // Whether the node is non-liquid, source liquid or flowing liquid
+ f.liquid_type = (LiquidType)getenumfield(L, nodedef_table, "liquidtype",
+ es_LiquidType, LIQUID_NONE);
+ // If the content is liquid, this is the flowing version of the liquid.
+ getstringfield(L, nodedef_table, "liquid_alternative_flowing",
+ f.liquid_alternative_flowing);
+ // If the content is liquid, this is the source version of the liquid.
+ getstringfield(L, nodedef_table, "liquid_alternative_source",
+ f.liquid_alternative_source);
+ // Viscosity for fluid flow, ranging from 1 to 7, with
+ // 1 giving almost instantaneous propagation and 7 being
+ // the slowest possible
+ f.liquid_viscosity = getintfield_default(L, nodedef_table,
+ "liquid_viscosity", f.liquid_viscosity);
+ // Amount of light the node emits
+ f.light_source = getintfield_default(L, nodedef_table,
+ "light_source", f.light_source);
+ f.damage_per_second = getintfield_default(L, nodedef_table,
+ "damage_per_second", f.damage_per_second);
+
+ lua_getfield(L, nodedef_table, "selection_box");
+ if(lua_istable(L, -1)){
+ f.selection_box.type = (NodeBoxType)getenumfield(L, -1, "type",
+ es_NodeBoxType, NODEBOX_REGULAR);
+
+ lua_getfield(L, -1, "fixed");
+ if(lua_istable(L, -1))
+ f.selection_box.fixed = read_aabbox3df32(L, -1, BS);
+ lua_pop(L, 1);
+
+ lua_getfield(L, -1, "wall_top");
+ if(lua_istable(L, -1))
+ f.selection_box.wall_top = read_aabbox3df32(L, -1, BS);
+ lua_pop(L, 1);
+
+ lua_getfield(L, -1, "wall_bottom");
+ if(lua_istable(L, -1))
+ f.selection_box.wall_bottom = read_aabbox3df32(L, -1, BS);
+ lua_pop(L, 1);
+
+ lua_getfield(L, -1, "wall_side");
+ if(lua_istable(L, -1))
+ f.selection_box.wall_side = read_aabbox3df32(L, -1, BS);
+ lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
+
+ lua_getfield(L, nodedef_table, "material");
+ if(lua_istable(L, -1)){
+ f.material.diggability = (Diggability)getenumfield(L, -1, "diggability",
+ es_Diggability, DIGGABLE_NORMAL);
+
+ getfloatfield(L, -1, "constant_time", f.material.constant_time);
+ getfloatfield(L, -1, "weight", f.material.weight);
+ getfloatfield(L, -1, "crackiness", f.material.crackiness);
+ getfloatfield(L, -1, "crumbliness", f.material.crumbliness);
+ getfloatfield(L, -1, "cuttability", f.material.cuttability);
+ getfloatfield(L, -1, "flammability", f.material.flammability);
+ }
+ lua_pop(L, 1);
+
+ getstringfield(L, nodedef_table, "cookresult_itemstring", f.cookresult_item);
+ getfloatfield(L, nodedef_table, "furnace_cooktime", f.furnace_cooktime);
+ getfloatfield(L, nodedef_table, "furnace_burntime", f.furnace_burntime);
+
+ /*
+ Register it
+ */
+
+ nodedef->set(name, f);
+
+ return 0; /* number of results */
+}
+
+// alias_node(name, convert_to_name)
+static int l_alias_node(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ std::string convert_to = luaL_checkstring(L, 2);
+
+ // Get the writable node definition manager from the server
+ IWritableNodeDefManager *nodedef =
+ get_server(L)->getWritableNodeDefManager();
+
+ nodedef->setAlias(name, convert_to);
+
+ return 0; /* number of results */
+}
+
+// alias_tool(name, convert_to_name)
+static int l_alias_tool(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ std::string convert_to = luaL_checkstring(L, 2);
+
+ // Get the writable tool definition manager from the server
+ IWritableToolDefManager *tooldef =
+ get_server(L)->getWritableToolDefManager();
+
+ tooldef->setAlias(name, convert_to);
+
+ return 0; /* number of results */
+}
+
+// alias_craftitem(name, convert_to_name)
+static int l_alias_craftitem(lua_State *L)
+{
+ std::string name = luaL_checkstring(L, 1);
+ std::string convert_to = luaL_checkstring(L, 2);
+
+ // Get the writable CraftItem definition manager from the server
+ IWritableCraftItemDefManager *craftitemdef =
+ get_server(L)->getWritableCraftItemDefManager();
+
+ craftitemdef->setAlias(name, convert_to);
+
+ return 0; /* number of results */
+}
+
+// register_craft({output=item, recipe={{item00,item10},{item01,item11}})
+static int l_register_craft(lua_State *L)
+{
+ //infostream<<"register_craft"<<std::endl;
+ luaL_checktype(L, 1, LUA_TTABLE);
+ int table0 = 1;
+
+ // Get the writable craft definition manager from the server
+ IWritableCraftDefManager *craftdef =
+ get_server(L)->getWritableCraftDefManager();
+
+ std::string output;
+ int width = 0;
+ std::vector<std::string> input;
+
+ lua_getfield(L, table0, "output");
+ luaL_checktype(L, -1, LUA_TSTRING);
+ if(lua_isstring(L, -1))
+ output = lua_tostring(L, -1);
+ lua_pop(L, 1);
+
+ lua_getfield(L, table0, "recipe");
+ luaL_checktype(L, -1, LUA_TTABLE);
+ if(lua_istable(L, -1)){
+ int table1 = lua_gettop(L);
+ lua_pushnil(L);
+ int rowcount = 0;
+ while(lua_next(L, table1) != 0){
+ int colcount = 0;
+ // key at index -2 and value at index -1
+ luaL_checktype(L, -1, LUA_TTABLE);
+ if(lua_istable(L, -1)){
+ int table2 = lua_gettop(L);
+ lua_pushnil(L);
+ while(lua_next(L, table2) != 0){
+ // key at index -2 and value at index -1
+ luaL_checktype(L, -1, LUA_TSTRING);
+ input.push_back(lua_tostring(L, -1));
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ colcount++;
+ }
+ }
+ if(rowcount == 0){
+ width = colcount;
+ } else {
+ if(colcount != width){
+ std::string error;
+ error += "Invalid crafting recipe (output=\""
+ + output + "\")";
+ throw LuaError(L, error);
+ }
+ }
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ rowcount++;
+ }
+ }
+ lua_pop(L, 1);
+
+ CraftDefinition def(output, width, input);
+ craftdef->registerCraft(def);
+
+ return 0; /* number of results */
+}
+
+// setting_get(name)
+static int l_setting_get(lua_State *L)
+{
+ const char *name = luaL_checkstring(L, 1);
+ try{
+ std::string value = g_settings->get(name);
+ lua_pushstring(L, value.c_str());
+ } catch(SettingNotFoundException &e){
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+// setting_getbool(name)
+static int l_setting_getbool(lua_State *L)
+{
+ const char *name = luaL_checkstring(L, 1);
+ try{
+ bool value = g_settings->getBool(name);
+ lua_pushboolean(L, value);
+ } catch(SettingNotFoundException &e){
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+// chat_send_all(text)
+static int l_chat_send_all(lua_State *L)
+{
+ const char *text = luaL_checkstring(L, 1);
+ // Get server from registry
+ Server *server = get_server(L);
+ // Send
+ server->notifyPlayers(narrow_to_wide(text));
+ return 0;
+}
+
+// chat_send_player(name, text)
+static int l_chat_send_player(lua_State *L)
+{
+ const char *name = luaL_checkstring(L, 1);
+ const char *text = luaL_checkstring(L, 2);
+ // Get server from registry
+ Server *server = get_server(L);
+ // Send
+ server->notifyPlayer(name, narrow_to_wide(text));
+ return 0;
+}
+
+// get_player_privs(name, text)
+static int l_get_player_privs(lua_State *L)
+{
+ const char *name = luaL_checkstring(L, 1);
+ // Get server from registry
+ Server *server = get_server(L);
+ // Do it
+ lua_newtable(L);
+ int table = lua_gettop(L);
+ u64 privs_i = server->getPlayerAuthPrivs(name);
+ // Special case for the "name" setting (local player / server owner)
+ if(name == g_settings->get("name"))
+ privs_i = PRIV_ALL;
+ std::set<std::string> privs_s = privsToSet(privs_i);
+ for(std::set<std::string>::const_iterator
+ i = privs_s.begin(); i != privs_s.end(); i++){
+ lua_pushboolean(L, true);
+ lua_setfield(L, table, i->c_str());
+ }
+ lua_pushvalue(L, table);
+ return 1;
+}
+
+// get_inventory(location)
+static int l_get_inventory(lua_State *L)
+{
+ InventoryLocation loc;
+
+ std::string type = checkstringfield(L, 1, "type");
+ if(type == "player"){
+ std::string name = checkstringfield(L, 1, "name");
+ loc.setPlayer(name);
+ } else if(type == "node"){
+ lua_getfield(L, 1, "pos");
+ v3s16 pos = check_v3s16(L, -1);
+ loc.setNodeMeta(pos);
+ }
+
+ if(get_server(L)->getInventory(loc) != NULL)
+ InvRef::create(L, loc);
+ else
+ lua_pushnil(L);
+ return 1;
+}
+
+// get_modpath(modname)
+static int l_get_modpath(lua_State *L)
+{
+ const char *modname = luaL_checkstring(L, 1);
+ // Get server from registry
+ lua_getfield(L, LUA_REGISTRYINDEX, "minetest_server");
+ Server *server = (Server*)lua_touserdata(L, -1);
+ // Do it
+ const ModSpec *mod = server->getModSpec(modname);
+ if(!mod){
+ lua_pushnil(L);
+ return 1;
+ }
+ lua_pushstring(L, mod->path.c_str());
+ return 1;
+}
+
+static const struct luaL_Reg minetest_f [] = {
+ {"register_nodedef_defaults", l_register_nodedef_defaults},
+ {"register_entity", l_register_entity},
+ {"register_tool", l_register_tool},
+ {"register_craftitem", l_register_craftitem},
+ {"register_node", l_register_node},
+ {"register_craft", l_register_craft},
+ {"register_abm", l_register_abm},
+ {"alias_node", l_alias_node},
+ {"alias_tool", l_alias_tool},
+ {"alias_craftitem", l_alias_craftitem},
+ {"setting_get", l_setting_get},
+ {"setting_getbool", l_setting_getbool},
+ {"chat_send_all", l_chat_send_all},
+ {"chat_send_player", l_chat_send_player},
+ {"get_player_privs", l_get_player_privs},
+ {"get_inventory", l_get_inventory},
+ {"get_modpath", l_get_modpath},
+ {NULL, NULL}
+};
+
+/*
+ LuaEntity functions
+*/
+
+static const struct luaL_Reg minetest_entity_m [] = {
+ {NULL, NULL}
+};
+
+/*
Main export function
*/
@@ -3397,9 +3471,9 @@ static void pushPointedThing(lua_State *L, const PointedThing& pointed)
{
lua_pushstring(L, "node");
lua_setfield(L, -2, "type");
- pushpos(L, pointed.node_undersurface);
+ push_v3s16(L, pointed.node_undersurface);
lua_setfield(L, -2, "under");
- pushpos(L, pointed.node_abovesurface);
+ push_v3s16(L, pointed.node_abovesurface);
lua_setfield(L, -2, "above");
}
else if(pointed.type == POINTEDTHING_OBJECT)
@@ -3595,7 +3669,7 @@ void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode,
// key at index -2 and value at index -1
luaL_checktype(L, -1, LUA_TFUNCTION);
// Call function
- pushpos(L, p);
+ push_v3s16(L, p);
pushnode(L, newnode, ndef);
objectref_get_or_create(L, placer);
if(lua_pcall(L, 3, 0, 0))
@@ -3627,7 +3701,7 @@ void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode,
// key at index -2 and value at index -1
luaL_checktype(L, -1, LUA_TFUNCTION);
// Call function
- pushpos(L, p);
+ push_v3s16(L, p);
pushnode(L, oldnode, ndef);
objectref_get_or_create(L, digger);
if(lua_pcall(L, 3, 0, 0))
@@ -3659,7 +3733,7 @@ void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node,
// key at index -2 and value at index -1
luaL_checktype(L, -1, LUA_TFUNCTION);
// Call function
- pushpos(L, p);
+ push_v3s16(L, p);
pushnode(L, node, ndef);
objectref_get_or_create(L, puncher);
if(lua_pcall(L, 3, 0, 0))
@@ -3686,8 +3760,8 @@ void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
// key at index -2 and value at index -1
luaL_checktype(L, -1, LUA_TFUNCTION);
// Call function
- pushpos(L, minp);
- pushpos(L, maxp);
+ push_v3s16(L, minp);
+ push_v3s16(L, maxp);
if(lua_pcall(L, 2, 0, 0))
script_error(L, "error: %s", lua_tostring(L, -1));
// value removed, keep key for next iteration