X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fscriptapi.cpp;h=be136673783029c26da33ad7d08c13203866ed91;hb=d96cd236f3e983ff35ef16f7c9979c8341d5ae0c;hp=8a3d4a4964e76e5f39e6a5fdb9d92b40a2650722;hpb=cd563473fa298db3b910009f26ba263bacd84be9;p=dragonfireclient.git diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp index 8a3d4a496..be1366737 100644 --- a/src/scriptapi.cpp +++ b/src/scriptapi.cpp @@ -107,6 +107,59 @@ class StackUnroller } }; +class ModNameStorer +{ +private: + lua_State *L; +public: + ModNameStorer(lua_State *L_, const std::string modname): + L(L_) + { + // Store current modname in registry + lua_pushstring(L, modname.c_str()); + lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); + } + ~ModNameStorer() + { + // Clear current modname in registry + lua_pushnil(L); + lua_setfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); + } +}; + +std::string get_current_modname(lua_State *L) +{ + lua_getfield(L, LUA_REGISTRYINDEX, "minetest_current_modname"); + std::string modname = ""; + if(lua_type(L, -1) == LUA_TSTRING) + modname = lua_tostring(L, -1); + lua_pop(L, 1); + return modname; +} + +void check_modname_prefix(lua_State *L, std::string &name) +{ + if(name.size() == 0) + throw LuaError(L, std::string("Name is empty")); + + if(name[0] == ':'){ + name = name.substr(1); + return; + } + + std::string modname = get_current_modname(L); + assert(modname != ""); + + // For __builtin, anything goes + if(modname == "__builtin") + return; + + if(name.substr(0, modname.size()+1) != modname + "_") + throw LuaError(L, std::string("Name \"")+name + +"\" does not follow naming conventions: " + +"\"modname_\" or \":\" prefix required)"); +} + static v3f readFloatPos(lua_State *L, int index) { v3f pos; @@ -386,6 +439,163 @@ static int getenumfield(lua_State *L, int table, return result; } +static void setfloatfield(lua_State *L, int table, + const char *fieldname, float value) +{ + lua_pushnumber(L, value); + if(table < 0) + table -= 1; + lua_setfield(L, table, fieldname); +} + +/* + Inventory stuff +*/ + +static void inventory_set_list_from_lua(Inventory *inv, const char *name, + lua_State *L, int tableindex, IGameDef *gamedef, int forcesize=-1) +{ + if(tableindex < 0) + tableindex = lua_gettop(L) + 1 + tableindex; + // If nil, delete list + if(lua_isnil(L, tableindex)){ + inv->deleteList(name); + return; + } + // Otherwise set list + std::list items; + luaL_checktype(L, tableindex, LUA_TTABLE); + int table = tableindex; + lua_pushnil(L); + while(lua_next(L, table) != 0){ + // key at index -2 and value at index -1 + luaL_checktype(L, -1, LUA_TSTRING); + std::string itemstring = lua_tostring(L, -1); + items.push_back(itemstring); + // removes value, keeps key for next iteration + lua_pop(L, 1); + } + int listsize = (forcesize != -1) ? forcesize : items.size(); + InventoryList *invlist = inv->addList(name, listsize); + int index = 0; + for(std::list::const_iterator + i = items.begin(); i != items.end(); i++){ + if(forcesize != -1 && index == forcesize) + break; + const std::string &itemstring = *i; + InventoryItem *newitem = NULL; + if(itemstring != "") + newitem = InventoryItem::deSerialize(itemstring, + gamedef); + InventoryItem *olditem = invlist->changeItem(index, newitem); + delete olditem; + index++; + } + while(forcesize != -1 && index < forcesize){ + InventoryItem *olditem = invlist->changeItem(index, NULL); + delete olditem; + index++; + } +} + +static void inventory_get_list_to_lua(Inventory *inv, const char *name, + lua_State *L) +{ + InventoryList *invlist = inv->getList(name); + if(invlist == NULL){ + lua_pushnil(L); + return; + } + // Get the table insert function + lua_getglobal(L, "table"); + lua_getfield(L, -1, "insert"); + int table_insert = lua_gettop(L); + // Create and fill table + lua_newtable(L); + int table = lua_gettop(L); + for(u32 i=0; igetSize(); i++){ + InventoryItem *item = invlist->getItem(i); + lua_pushvalue(L, table_insert); + lua_pushvalue(L, table); + if(item == NULL){ + lua_pushstring(L, ""); + } else { + lua_pushstring(L, item->getItemString().c_str()); + } + if(lua_pcall(L, 2, 0, 0)) + script_error(L, "error: %s", lua_tostring(L, -1)); + } +} + +/* + ToolDiggingProperties +*/ + +static ToolDiggingProperties read_tool_digging_properties( + lua_State *L, int table) +{ + ToolDiggingProperties prop; + getfloatfield(L, table, "full_punch_interval", prop.full_punch_interval); + getfloatfield(L, table, "basetime", prop.basetime); + getfloatfield(L, table, "dt_weight", prop.dt_weight); + getfloatfield(L, table, "dt_crackiness", prop.dt_crackiness); + getfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness); + getfloatfield(L, table, "dt_cuttability", prop.dt_cuttability); + getfloatfield(L, table, "basedurability", prop.basedurability); + getfloatfield(L, table, "dd_weight", prop.dd_weight); + getfloatfield(L, table, "dd_crackiness", prop.dd_crackiness); + getfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness); + getfloatfield(L, table, "dd_cuttability", prop.dd_cuttability); + return prop; +} + +static void set_tool_digging_properties(lua_State *L, int table, + const ToolDiggingProperties &prop) +{ + setfloatfield(L, table, "full_punch_interval", prop.full_punch_interval); + setfloatfield(L, table, "basetime", prop.basetime); + setfloatfield(L, table, "dt_weight", prop.dt_weight); + setfloatfield(L, table, "dt_crackiness", prop.dt_crackiness); + setfloatfield(L, table, "dt_crumbliness", prop.dt_crumbliness); + setfloatfield(L, table, "dt_cuttability", prop.dt_cuttability); + setfloatfield(L, table, "basedurability", prop.basedurability); + setfloatfield(L, table, "dd_weight", prop.dd_weight); + setfloatfield(L, table, "dd_crackiness", prop.dd_crackiness); + setfloatfield(L, table, "dd_crumbliness", prop.dd_crumbliness); + setfloatfield(L, table, "dd_cuttability", prop.dd_cuttability); +} + +static void push_tool_digging_properties(lua_State *L, + const ToolDiggingProperties &prop) +{ + lua_newtable(L); + set_tool_digging_properties(L, -1, prop); +} + +/* + ToolDefinition +*/ + +static ToolDefinition read_tool_definition(lua_State *L, int table) +{ + ToolDefinition def; + getstringfield(L, table, "image", def.imagename); + def.properties = read_tool_digging_properties(L, table); + return def; +} + +static void push_tool_definition(lua_State *L, const ToolDefinition &def) +{ + lua_newtable(L); + lua_pushstring(L, def.imagename.c_str()); + lua_setfield(L, -2, "image"); + set_tool_digging_properties(L, -1, def.properties); +} + +/* + EnumString definitions +*/ + struct EnumString es_DrawType[] = { {NDT_NORMAL, "normal"}, @@ -454,8 +664,9 @@ static int l_register_nodedef_defaults(lua_State *L) // register_entity(name, prototype) static int l_register_entity(lua_State *L) { - const char *name = luaL_checkstring(L, 1); - infostream<<"register_entity: "< stack top // registered_entities[name] = object - lua_setfield(L, registered_entities, name); + lua_setfield(L, registered_entities, name.c_str()); // Get registered object to top of stack lua_pushvalue(L, 2); @@ -546,14 +757,14 @@ class LuaABM : public ActiveBlockModifier 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\n", lua_tostring(L, -1)); + script_error(L, "error: %s", lua_tostring(L, -1)); } }; // register_abm({...}) static int l_register_abm(lua_State *L) { - infostream<<"register_abm"<getWritableToolDefManager(); - ToolDefinition def; - - getstringfield(L, table, "image", def.imagename); - getfloatfield(L, table, "basetime", def.properties.basetime); - getfloatfield(L, table, "dt_weight", def.properties.dt_weight); - getfloatfield(L, table, "dt_crackiness", def.properties.dt_crackiness); - getfloatfield(L, table, "dt_crumbliness", def.properties.dt_crumbliness); - getfloatfield(L, table, "dt_cuttability", def.properties.dt_cuttability); - getfloatfield(L, table, "basedurability", def.properties.basedurability); - getfloatfield(L, table, "dd_weight", def.properties.dd_weight); - getfloatfield(L, table, "dd_crackiness", def.properties.dd_crackiness); - getfloatfield(L, table, "dd_crumbliness", def.properties.dd_crumbliness); - getfloatfield(L, table, "dd_cuttability", def.properties.dd_cuttability); + ToolDefinition def = read_tool_definition(L, table); tooldef->registerTool(name, def); return 0; /* number of results */ @@ -620,8 +820,9 @@ static int l_register_tool(lua_State *L) // register_craftitem(name, {lots of stuff}) static int l_register_craftitem(lua_State *L) { - const char *name = luaL_checkstring(L, 1); - infostream<<"register_craftitem: "<registerCraftItem(name, def); lua_pushvalue(L, table); - scriptapi_add_craftitem(L, name); + scriptapi_add_craftitem(L, name.c_str()); return 0; /* number of results */ } @@ -669,8 +870,9 @@ static int l_register_craftitem(lua_State *L) // register_node(name, {lots of stuff}) static int l_register_node(lua_State *L) { - const char *name = luaL_checkstring(L, 1); - infostream<<"register_node: "<getInventory(); - std::string name = lua_tostring(L, 2); - // If nil, delete list - if(lua_isnil(L, 3)){ - inv->deleteList(name); - return 0; - } - // Otherwise set list - std::list items; - luaL_checktype(L, 3, LUA_TTABLE); - int table = 3; - lua_pushnil(L); - infostream<<"items: "; - while(lua_next(L, table) != 0){ - // key at index -2 and value at index -1 - luaL_checktype(L, -1, LUA_TSTRING); - std::string itemstring = lua_tostring(L, -1); - infostream<<"\""<addList(name, items.size()); - int index = 0; - for(std::list::const_iterator - i = items.begin(); i != items.end(); i++){ - const std::string &itemstring = *i; - InventoryItem *newitem = NULL; - if(itemstring != "") - newitem = InventoryItem::deSerialize(itemstring, - ref->m_env->getGameDef()); - InventoryItem *olditem = invlist->changeItem(index, newitem); - delete olditem; - index++; - } + const char *name = lua_tostring(L, 2); + inventory_set_list_from_lua(inv, name, L, 3, + ref->m_env->getGameDef()); reportMetadataChange(ref); return 0; } @@ -1299,31 +1472,8 @@ class NodeMetaRef if(meta == NULL) return 0; // Do it Inventory *inv = meta->getInventory(); - std::string name = lua_tostring(L, 2); - InventoryList *invlist = inv->getList(name); - if(invlist == NULL){ - lua_pushnil(L); - return 1; - } - // Get the table insert function - lua_getglobal(L, "table"); - lua_getfield(L, -1, "insert"); - int table_insert = lua_gettop(L); - // Create and fill table - lua_newtable(L); - int table = lua_gettop(L); - for(u32 i=0; igetSize(); i++){ - InventoryItem *item = invlist->getItem(i); - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - if(item == NULL){ - lua_pushnil(L); - } else { - lua_pushstring(L, item->getItemString().c_str()); - } - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s\n", lua_tostring(L, -1)); - } + const char *name = lua_tostring(L, 2); + inventory_get_list_to_lua(inv, name, L); return 1; } @@ -1670,65 +1820,16 @@ class ObjectRef return 0; } - // get_wielded_itemstring(self) - static int l_get_wielded_itemstring(lua_State *L) + // get_wield_digging_properties(self) + static int l_get_wield_digging_properties(lua_State *L) { ObjectRef *ref = checkobject(L, 1); ServerActiveObject *co = getobject(ref); if(co == NULL) return 0; // Do it - InventoryItem *item = co->getWieldedItem(); - if(item == NULL){ - lua_pushnil(L); - return 1; - } - lua_pushstring(L, item->getItemString().c_str()); - return 1; - } - - // get_wielded_item(self) - static int l_get_wielded_item(lua_State *L) - { - ObjectRef *ref = checkobject(L, 1); - ServerActiveObject *co = getobject(ref); - if(co == NULL) return 0; - // Do it - InventoryItem *item0 = co->getWieldedItem(); - if(item0 == NULL){ - lua_pushnil(L); - return 1; - } - if(std::string("MaterialItem") == item0->getName()){ - MaterialItem *item = (MaterialItem*)item0; - lua_newtable(L); - lua_pushstring(L, "NodeItem"); - lua_setfield(L, -2, "type"); - lua_pushstring(L, item->getNodeName().c_str()); - lua_setfield(L, -2, "name"); - } - else if(std::string("CraftItem") == item0->getName()){ - CraftItem *item = (CraftItem*)item0; - lua_newtable(L); - lua_pushstring(L, "CraftItem"); - lua_setfield(L, -2, "type"); - lua_pushstring(L, item->getSubName().c_str()); - lua_setfield(L, -2, "name"); - } - else if(std::string("ToolItem") == item0->getName()){ - ToolItem *item = (ToolItem*)item0; - lua_newtable(L); - lua_pushstring(L, "ToolItem"); - lua_setfield(L, -2, "type"); - lua_pushstring(L, item->getToolName().c_str()); - lua_setfield(L, -2, "name"); - lua_pushstring(L, itos(item->getWear()).c_str()); - lua_setfield(L, -2, "wear"); - } - else{ - errorstream<<"l_get_wielded_item: Unknown item name: \"" - <getName()<<"\""<getWieldDiggingProperties(&prop); + push_tool_digging_properties(L, prop); return 1; } @@ -1769,7 +1870,7 @@ class ObjectRef // Return lua_pushboolean(L, added); if(!added) - lua_pushstring(L, "does not fit"); + lua_pushstring(L, "failed to add item"); return 2; } catch(SerializationError &e){ // Return @@ -1913,7 +2014,111 @@ class ObjectRef co->setSprite(p, num_frames, framelength, select_horiz_by_yawpitch); return 0; } + + /* Player-only */ + // get_player_name(self) + static int l_get_player_name(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerRemotePlayer *player = getplayer(ref); + if(player == NULL){ + lua_pushnil(L); + return 1; + } + // Do it + lua_pushstring(L, player->getName()); + return 1; + } + + // inventory_set_list(self, name, {item1, item2, ...}) + static int l_inventory_set_list(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerRemotePlayer *player = getplayer(ref); + if(player == NULL) return 0; + const char *name = lua_tostring(L, 2); + // Do it + inventory_set_list_from_lua(&player->inventory, name, L, 3, + player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE); + player->m_inventory_not_sent = true; + return 0; + } + + // inventory_get_list(self, name) + static int l_inventory_get_list(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerRemotePlayer *player = getplayer(ref); + if(player == NULL) return 0; + const char *name = lua_tostring(L, 2); + // Do it + inventory_get_list_to_lua(&player->inventory, name, L); + return 1; + } + + // get_wielded_itemstring(self) + static int l_get_wielded_itemstring(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerRemotePlayer *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + InventoryItem *item = player->getWieldedItem(); + if(item == NULL){ + lua_pushnil(L); + return 1; + } + lua_pushstring(L, item->getItemString().c_str()); + return 1; + } + + // get_wielded_item(self) + static int l_get_wielded_item(lua_State *L) + { + ObjectRef *ref = checkobject(L, 1); + ServerRemotePlayer *player = getplayer(ref); + if(player == NULL) return 0; + // Do it + InventoryItem *item0 = player->getWieldedItem(); + if(item0 == NULL){ + lua_pushnil(L); + return 1; + } + if(std::string("MaterialItem") == item0->getName()){ + MaterialItem *item = (MaterialItem*)item0; + lua_newtable(L); + lua_pushstring(L, "NodeItem"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, item->getNodeName().c_str()); + lua_setfield(L, -2, "name"); + } + else if(std::string("CraftItem") == item0->getName()){ + CraftItem *item = (CraftItem*)item0; + lua_newtable(L); + lua_pushstring(L, "CraftItem"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, item->getSubName().c_str()); + lua_setfield(L, -2, "name"); + } + else if(std::string("ToolItem") == item0->getName()){ + ToolItem *item = (ToolItem*)item0; + lua_newtable(L); + lua_pushstring(L, "ToolItem"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, item->getToolName().c_str()); + lua_setfield(L, -2, "name"); + lua_pushstring(L, itos(item->getWear()).c_str()); + lua_setfield(L, -2, "wear"); + } + else{ + errorstream<<"l_get_wielded_item: Unknown item name: \"" + <getName()<<"\""<inventory, "main", L, -1, + player->getEnv()->getGameDef(), PLAYER_INVENTORY_SIZE); +} + /* craftitem */ @@ -2648,7 +2885,7 @@ bool scriptapi_craftitem_on_drop(lua_State *L, const char *name, objectref_get_or_create(L, dropper); pushFloatPos(L, pos); if(lua_pcall(L, 3, 1, 0)) - script_error(L, "error: %s\n", lua_tostring(L, -1)); + script_error(L, "error: %s", lua_tostring(L, -1)); result = lua_toboolean(L, -1); } return result; @@ -2672,7 +2909,7 @@ bool scriptapi_craftitem_on_place_on_ground(lua_State *L, const char *name, objectref_get_or_create(L, placer); pushFloatPos(L, pos); if(lua_pcall(L, 3, 1, 0)) - script_error(L, "error: %s\n", lua_tostring(L, -1)); + script_error(L, "error: %s", lua_tostring(L, -1)); result = lua_toboolean(L, -1); } return result; @@ -2696,7 +2933,7 @@ bool scriptapi_craftitem_on_use(lua_State *L, const char *name, objectref_get_or_create(L, user); pushPointedThing(L, pointed); if(lua_pcall(L, 3, 1, 0)) - script_error(L, "error: %s\n", lua_tostring(L, -1)); + script_error(L, "error: %s", lua_tostring(L, -1)); result = lua_toboolean(L, -1); } return result; @@ -2726,7 +2963,7 @@ void scriptapi_environment_step(lua_State *L, float dtime) // Call function lua_pushnumber(L, dtime); if(lua_pcall(L, 1, 0, 0)) - script_error(L, "error: %s\n", lua_tostring(L, -1)); + script_error(L, "error: %s", lua_tostring(L, -1)); // value removed, keep key for next iteration } } @@ -2761,7 +2998,7 @@ void scriptapi_environment_on_placenode(lua_State *L, v3s16 p, MapNode newnode, pushnode(L, newnode, ndef); objectref_get_or_create(L, placer); if(lua_pcall(L, 3, 0, 0)) - script_error(L, "error: %s\n", lua_tostring(L, -1)); + script_error(L, "error: %s", lua_tostring(L, -1)); // value removed, keep key for next iteration } } @@ -2796,7 +3033,7 @@ void scriptapi_environment_on_dignode(lua_State *L, v3s16 p, MapNode oldnode, pushnode(L, oldnode, ndef); objectref_get_or_create(L, digger); if(lua_pcall(L, 3, 0, 0)) - script_error(L, "error: %s\n", lua_tostring(L, -1)); + script_error(L, "error: %s", lua_tostring(L, -1)); // value removed, keep key for next iteration } } @@ -2831,7 +3068,7 @@ void scriptapi_environment_on_punchnode(lua_State *L, v3s16 p, MapNode node, pushnode(L, node, ndef); objectref_get_or_create(L, puncher); if(lua_pcall(L, 3, 0, 0)) - script_error(L, "error: %s\n", lua_tostring(L, -1)); + script_error(L, "error: %s", lua_tostring(L, -1)); // value removed, keep key for next iteration } } @@ -2857,7 +3094,7 @@ void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp) pushpos(L, minp); pushpos(L, maxp); if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s\n", lua_tostring(L, -1)); + script_error(L, "error: %s", lua_tostring(L, -1)); // value removed, keep key for next iteration } } @@ -3060,9 +3297,9 @@ void scriptapi_luaentity_step(lua_State *L, u16 id, float dtime) script_error(L, "error running function 'on_step': %s\n", lua_tostring(L, -1)); } -// Calls entity:on_punch(ObjectRef puncher) +// Calls entity:on_punch(ObjectRef puncher, time_from_last_punch) void scriptapi_luaentity_punch(lua_State *L, u16 id, - ServerActiveObject *puncher) + ServerActiveObject *puncher, float time_from_last_punch) { realitycheck(L); assert(lua_checkstack(L, 20)); @@ -3080,8 +3317,9 @@ void scriptapi_luaentity_punch(lua_State *L, u16 id, luaL_checktype(L, -1, LUA_TFUNCTION); lua_pushvalue(L, object); // self objectref_get_or_create(L, puncher); // Clicker reference + lua_pushnumber(L, time_from_last_punch); // Call with 2 arguments, 0 results - if(lua_pcall(L, 2, 0, 0)) + if(lua_pcall(L, 3, 0, 0)) script_error(L, "error running function 'on_punch': %s\n", lua_tostring(L, -1)); }