diff options
-rw-r--r-- | src/scriptapi.cpp | 1510 |
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 |