diff options
Diffstat (limited to '')
-rw-r--r-- | src/script/lua_api/l_item.cpp (renamed from src/scriptapi_item.cpp) | 480 |
1 files changed, 117 insertions, 363 deletions
diff --git a/src/scriptapi_item.cpp b/src/script/lua_api/l_item.cpp index b266d856d..e9997d489 100644 --- a/src/scriptapi_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -17,284 +17,12 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include "scriptapi.h" +#include "lua_api/l_item.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "cpp_api/scriptapi.h" #include "server.h" -#include "script.h" -#include "tool.h" -#include "nodedef.h" -#include "util/pointedthing.h" -#include "scriptapi_item.h" -#include "scriptapi_types.h" -#include "scriptapi_common.h" -#include "scriptapi_object.h" -#include "scriptapi_content.h" - - -struct EnumString es_ItemType[] = -{ - {ITEM_NONE, "none"}, - {ITEM_NODE, "node"}, - {ITEM_CRAFT, "craft"}, - {ITEM_TOOL, "tool"}, - {0, NULL}, -}; - - -/* - ItemDefinition -*/ - -ItemDefinition read_item_definition(lua_State *L, int index, - ItemDefinition default_def) -{ - if(index < 0) - index = lua_gettop(L) + 1 + index; - - // Read the item definition - ItemDefinition def = default_def; - - def.type = (ItemType)getenumfield(L, index, "type", - es_ItemType, ITEM_NONE); - getstringfield(L, index, "name", def.name); - getstringfield(L, index, "description", def.description); - getstringfield(L, index, "inventory_image", def.inventory_image); - getstringfield(L, index, "wield_image", def.wield_image); - - lua_getfield(L, index, "wield_scale"); - if(lua_istable(L, -1)){ - def.wield_scale = check_v3f(L, -1); - } - lua_pop(L, 1); - - def.stack_max = getintfield_default(L, index, "stack_max", def.stack_max); - if(def.stack_max == 0) - def.stack_max = 1; - - lua_getfield(L, index, "on_use"); - def.usable = lua_isfunction(L, -1); - lua_pop(L, 1); - - getboolfield(L, index, "liquids_pointable", def.liquids_pointable); - - warn_if_field_exists(L, index, "tool_digging_properties", - "deprecated: use tool_capabilities"); - - lua_getfield(L, index, "tool_capabilities"); - if(lua_istable(L, -1)){ - def.tool_capabilities = new ToolCapabilities( - read_tool_capabilities(L, -1)); - } - - // If name is "" (hand), ensure there are ToolCapabilities - // because it will be looked up there whenever any other item has - // no ToolCapabilities - if(def.name == "" && def.tool_capabilities == NULL){ - def.tool_capabilities = new ToolCapabilities(); - } - - lua_getfield(L, index, "groups"); - read_groups(L, -1, def.groups); - lua_pop(L, 1); - - lua_getfield(L, index, "sounds"); - if(lua_istable(L, -1)){ - lua_getfield(L, -1, "place"); - read_soundspec(L, -1, def.sound_place); - lua_pop(L, 1); - } - lua_pop(L, 1); - - // Client shall immediately place this node when player places the item. - // Server will update the precise end result a moment later. - // "" = no prediction - getstringfield(L, index, "node_placement_prediction", - def.node_placement_prediction); - - return def; -} - -// register_item_raw({lots of stuff}) -int l_register_item_raw(lua_State *L) -{ - luaL_checktype(L, 1, LUA_TTABLE); - int table = 1; - - // Get the writable item and node definition managers from the server - IWritableItemDefManager *idef = - get_server(L)->getWritableItemDefManager(); - IWritableNodeDefManager *ndef = - get_server(L)->getWritableNodeDefManager(); - - // Check if name is defined - std::string name; - lua_getfield(L, table, "name"); - if(lua_isstring(L, -1)){ - name = lua_tostring(L, -1); - verbosestream<<"register_item_raw: "<<name<<std::endl; - } else { - throw LuaError(L, "register_item_raw: name is not defined or not a string"); - } - - // Check if on_use is defined - - ItemDefinition def; - // Set a distinctive default value to check if this is set - def.node_placement_prediction = "__default"; - - // Read the item definition - def = read_item_definition(L, table, def); - - // Default to having client-side placement prediction for nodes - // ("" in item definition sets it off) - if(def.node_placement_prediction == "__default"){ - if(def.type == ITEM_NODE) - def.node_placement_prediction = name; - else - def.node_placement_prediction = ""; - } - - // Register item definition - idef->registerItem(def); - - // Read the node definition (content features) and register it - if(def.type == ITEM_NODE) - { - ContentFeatures f = read_content_features(L, table); - ndef->set(f.name, f); - } - - return 0; /* number of results */ -} - -// register_alias_raw(name, convert_to_name) -int l_register_alias_raw(lua_State *L) -{ - std::string name = luaL_checkstring(L, 1); - std::string convert_to = luaL_checkstring(L, 2); - - // Get the writable item definition manager from the server - IWritableItemDefManager *idef = - get_server(L)->getWritableItemDefManager(); - - idef->registerAlias(name, convert_to); - - return 0; /* number of results */ -} - -// Retrieves minetest.registered_items[name][callbackname] -// If that is nil or on error, return false and stack is unchanged -// If that is a function, returns true and pushes the -// function onto the stack -// If minetest.registered_items[name] doesn't exist, minetest.nodedef_default -// is tried instead so unknown items can still be manipulated to some degree -bool get_item_callback(lua_State *L, - const char *name, const char *callbackname) -{ - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "registered_items"); - lua_remove(L, -2); - luaL_checktype(L, -1, LUA_TTABLE); - lua_getfield(L, -1, name); - lua_remove(L, -2); - // Should be a table - if(lua_type(L, -1) != LUA_TTABLE) - { - // Report error and clean up - errorstream<<"Item \""<<name<<"\" not defined"<<std::endl; - lua_pop(L, 1); - - // Try minetest.nodedef_default instead - lua_getglobal(L, "minetest"); - lua_getfield(L, -1, "nodedef_default"); - lua_remove(L, -2); - luaL_checktype(L, -1, LUA_TTABLE); - } - lua_getfield(L, -1, callbackname); - lua_remove(L, -2); - // Should be a function or nil - if(lua_type(L, -1) == LUA_TFUNCTION) - { - return true; - } - else if(lua_isnil(L, -1)) - { - lua_pop(L, 1); - return false; - } - else - { - errorstream<<"Item \""<<name<<"\" callback \"" - <<callbackname<<" is not a function"<<std::endl; - lua_pop(L, 1); - return false; - } -} - -bool scriptapi_item_on_drop(lua_State *L, ItemStack &item, - ServerActiveObject *dropper, v3f pos) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Push callback function on stack - if(!get_item_callback(L, item.name.c_str(), "on_drop")) - return false; - - // Call function - LuaItemStack::create(L, item); - objectref_get_or_create(L, dropper); - pushFloatPos(L, pos); - if(lua_pcall(L, 3, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnil(L, -1)) - item = read_item(L, -1); - return true; -} - -bool scriptapi_item_on_place(lua_State *L, ItemStack &item, - ServerActiveObject *placer, const PointedThing &pointed) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Push callback function on stack - if(!get_item_callback(L, item.name.c_str(), "on_place")) - return false; - - // Call function - LuaItemStack::create(L, item); - objectref_get_or_create(L, placer); - push_pointed_thing(L, pointed); - if(lua_pcall(L, 3, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnil(L, -1)) - item = read_item(L, -1); - return true; -} - -bool scriptapi_item_on_use(lua_State *L, ItemStack &item, - ServerActiveObject *user, const PointedThing &pointed) -{ - realitycheck(L); - assert(lua_checkstack(L, 20)); - StackUnroller stack_unroller(L); - - // Push callback function on stack - if(!get_item_callback(L, item.name.c_str(), "on_use")) - return false; - - // Call function - LuaItemStack::create(L, item); - objectref_get_or_create(L, user); - push_pointed_thing(L, pointed); - if(lua_pcall(L, 3, 1, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - if(!lua_isnil(L, -1)) - item = read_item(L, -1); - return true; -} +#include "common/c_internal.h" // garbage collector int LuaItemStack::gc_object(lua_State *L) @@ -307,6 +35,7 @@ int LuaItemStack::gc_object(lua_State *L) // is_empty(self) -> true/false int LuaItemStack::l_is_empty(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; lua_pushboolean(L, item.empty()); @@ -316,6 +45,7 @@ int LuaItemStack::l_is_empty(lua_State *L) // get_name(self) -> string int LuaItemStack::l_get_name(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; lua_pushstring(L, item.name.c_str()); @@ -325,6 +55,7 @@ int LuaItemStack::l_get_name(lua_State *L) // get_count(self) -> number int LuaItemStack::l_get_count(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; lua_pushinteger(L, item.count); @@ -334,6 +65,7 @@ int LuaItemStack::l_get_count(lua_State *L) // get_wear(self) -> number int LuaItemStack::l_get_wear(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; lua_pushinteger(L, item.wear); @@ -343,6 +75,7 @@ int LuaItemStack::l_get_wear(lua_State *L) // get_metadata(self) -> string int LuaItemStack::l_get_metadata(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; lua_pushlstring(L, item.metadata.c_str(), item.metadata.size()); @@ -352,6 +85,7 @@ int LuaItemStack::l_get_metadata(lua_State *L) // clear(self) -> true int LuaItemStack::l_clear(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); o->m_stack.clear(); lua_pushboolean(L, true); @@ -361,8 +95,9 @@ int LuaItemStack::l_clear(lua_State *L) // replace(self, itemstack or itemstring or table or nil) -> true int LuaItemStack::l_replace(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); - o->m_stack = read_item(L, 2); + o->m_stack = read_item(L,2,STACK_TO_SERVER(L)); lua_pushboolean(L, true); return 1; } @@ -370,6 +105,7 @@ int LuaItemStack::l_replace(lua_State *L) // to_string(self) -> string int LuaItemStack::l_to_string(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); std::string itemstring = o->m_stack.getItemString(); lua_pushstring(L, itemstring.c_str()); @@ -379,6 +115,7 @@ int LuaItemStack::l_to_string(lua_State *L) // to_table(self) -> table or nil int LuaItemStack::l_to_table(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); const ItemStack &item = o->m_stack; if(item.empty()) @@ -403,18 +140,20 @@ int LuaItemStack::l_to_table(lua_State *L) // get_stack_max(self) -> number int LuaItemStack::l_get_stack_max(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - lua_pushinteger(L, item.getStackMax(get_server(L)->idef())); + lua_pushinteger(L, item.getStackMax(STACK_TO_SERVER(L)->idef())); return 1; } // get_free_space(self) -> number int LuaItemStack::l_get_free_space(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - lua_pushinteger(L, item.freeSpace(get_server(L)->idef())); + lua_pushinteger(L, item.freeSpace(STACK_TO_SERVER(L)->idef())); return 1; } @@ -422,9 +161,10 @@ int LuaItemStack::l_get_free_space(lua_State *L) // Checks if the item is defined. int LuaItemStack::l_is_known(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - bool is_known = item.isKnown(get_server(L)->idef()); + bool is_known = item.isKnown(STACK_TO_SERVER(L)->idef()); lua_pushboolean(L, is_known); return 1; } @@ -434,6 +174,7 @@ int LuaItemStack::l_is_known(lua_State *L) // or a fallback one (name="unknown") int LuaItemStack::l_get_definition(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; @@ -455,10 +196,11 @@ int LuaItemStack::l_get_definition(lua_State *L) // Returns those of the hand ("") if this item has none associated. int LuaItemStack::l_get_tool_capabilities(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; const ToolCapabilities &prop = - item.getToolCapabilities(get_server(L)->idef()); + item.getToolCapabilities(STACK_TO_SERVER(L)->idef()); push_tool_capabilities(L, prop); return 1; } @@ -469,10 +211,11 @@ int LuaItemStack::l_get_tool_capabilities(lua_State *L) // Returns true if the item is (or was) a tool. int LuaItemStack::l_add_wear(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; int amount = lua_tointeger(L, 2); - bool result = item.addWear(amount, get_server(L)->idef()); + bool result = item.addWear(amount, STACK_TO_SERVER(L)->idef()); lua_pushboolean(L, result); return 1; } @@ -481,10 +224,11 @@ int LuaItemStack::l_add_wear(lua_State *L) // Returns leftover item stack int LuaItemStack::l_add_item(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L, 2); - ItemStack leftover = item.addItem(newitem, get_server(L)->idef()); + ItemStack newitem = read_item(L,-2, STACK_TO_SERVER(L)); + ItemStack leftover = item.addItem(newitem, STACK_TO_SERVER(L)->idef()); create(L, leftover); return 1; } @@ -494,11 +238,12 @@ int LuaItemStack::l_add_item(lua_State *L) // Second return value is the would-be-left-over item stack int LuaItemStack::l_item_fits(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; - ItemStack newitem = read_item(L, 2); + ItemStack newitem = read_item(L, 2 ,STACK_TO_SERVER(L)); ItemStack restitem; - bool fits = item.itemFits(newitem, &restitem, get_server(L)->idef()); + bool fits = item.itemFits(newitem, &restitem, STACK_TO_SERVER(L)->idef()); lua_pushboolean(L, fits); // first return value create(L, restitem); // second return value return 2; @@ -507,6 +252,7 @@ int LuaItemStack::l_item_fits(lua_State *L) // take_item(self, takecount=1) -> itemstack int LuaItemStack::l_take_item(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; u32 takecount = 1; @@ -520,6 +266,7 @@ int LuaItemStack::l_take_item(lua_State *L) // peek_item(self, peekcount=1) -> itemstack int LuaItemStack::l_peek_item(lua_State *L) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = checkobject(L, 1); ItemStack &item = o->m_stack; u32 peekcount = 1; @@ -552,7 +299,8 @@ ItemStack& LuaItemStack::getItem() // Creates an LuaItemStack and leaves it on top of stack int LuaItemStack::create_object(lua_State *L) { - ItemStack item = read_item(L, 1); + NO_MAP_LOCK_REQUIRED; + ItemStack item = read_item(L,1,STACK_TO_SERVER(L)); LuaItemStack *o = new LuaItemStack(item); *(void **)(lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, className); @@ -562,6 +310,7 @@ int LuaItemStack::create_object(lua_State *L) // Not callable from Lua int LuaItemStack::create(lua_State *L, const ItemStack &item) { + NO_MAP_LOCK_REQUIRED; LuaItemStack *o = new LuaItemStack(item); *(void **)(lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, className); @@ -629,90 +378,95 @@ const luaL_reg LuaItemStack::methods[] = { {0,0} }; -ItemStack read_item(lua_State *L, int index) +ModApiItemMod::ModApiItemMod() { +} + +/* + ItemDefinition +*/ + +// register_item_raw({lots of stuff}) +int ModApiItemMod::l_register_item_raw(lua_State *L) { - if(index < 0) - index = lua_gettop(L) + 1 + index; + NO_MAP_LOCK_REQUIRED; + luaL_checktype(L, 1, LUA_TTABLE); + int table = 1; - if(lua_isnil(L, index)) - { - return ItemStack(); - } - else if(lua_isuserdata(L, index)) - { - // Convert from LuaItemStack - LuaItemStack *o = LuaItemStack::checkobject(L, index); - return o->getItem(); - } - else if(lua_isstring(L, index)) - { - // Convert from itemstring - std::string itemstring = lua_tostring(L, index); - IItemDefManager *idef = get_server(L)->idef(); - try - { - ItemStack item; - item.deSerialize(itemstring, idef); - return item; - } - catch(SerializationError &e) - { - infostream<<"WARNING: unable to create item from itemstring" - <<": "<<itemstring<<std::endl; - return ItemStack(); - } + ScriptApi* scriptIface = get_scriptapi(L); + + // Get the writable item and node definition managers from the server + IWritableItemDefManager *idef = + scriptIface->getServer()->getWritableItemDefManager(); + IWritableNodeDefManager *ndef = + scriptIface->getServer()->getWritableNodeDefManager(); + + // Check if name is defined + std::string name; + lua_getfield(L, table, "name"); + if(lua_isstring(L, -1)){ + name = lua_tostring(L, -1); + verbosestream<<"register_item_raw: "<<name<<std::endl; + } else { + throw LuaError(L, "register_item_raw: name is not defined or not a string"); } - else if(lua_istable(L, index)) - { - // Convert from table - IItemDefManager *idef = get_server(L)->idef(); - std::string name = getstringfield_default(L, index, "name", ""); - int count = getintfield_default(L, index, "count", 1); - int wear = getintfield_default(L, index, "wear", 0); - std::string metadata = getstringfield_default(L, index, "metadata", ""); - return ItemStack(name, count, wear, metadata, idef); + + // Check if on_use is defined + + ItemDefinition def; + // Set a distinctive default value to check if this is set + def.node_placement_prediction = "__default"; + + // Read the item definition + def = read_item_definition(L, table, def); + + // Default to having client-side placement prediction for nodes + // ("" in item definition sets it off) + if(def.node_placement_prediction == "__default"){ + if(def.type == ITEM_NODE) + def.node_placement_prediction = name; + else + def.node_placement_prediction = ""; } - else + + // Register item definition + idef->registerItem(def); + + // Read the node definition (content features) and register it + if(def.type == ITEM_NODE) { - throw LuaError(L, "Expecting itemstack, itemstring, table or nil"); + ContentFeatures f = read_content_features(L, table); + ndef->set(f.name, f); } + + return 0; /* number of results */ } -std::vector<ItemStack> read_items(lua_State *L, int index) +// register_alias_raw(name, convert_to_name) +int ModApiItemMod::l_register_alias_raw(lua_State *L) { - if(index < 0) - index = lua_gettop(L) + 1 + index; - - std::vector<ItemStack> items; - luaL_checktype(L, index, LUA_TTABLE); - lua_pushnil(L); - while(lua_next(L, index) != 0){ - // key at index -2 and value at index -1 - items.push_back(read_item(L, -1)); - // removes value, keeps key for next iteration - lua_pop(L, 1); - } - return items; + NO_MAP_LOCK_REQUIRED; + std::string name = luaL_checkstring(L, 1); + std::string convert_to = luaL_checkstring(L, 2); + + // Get the writable item definition manager from the server + IWritableItemDefManager *idef = + STACK_TO_SERVER(L)->getWritableItemDefManager(); + + idef->registerAlias(name, convert_to); + + return 0; /* number of results */ } -// creates a table of ItemStacks -void push_items(lua_State *L, const std::vector<ItemStack> &items) -{ - // 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; i<items.size(); i++){ - ItemStack item = items[i]; - lua_pushvalue(L, table_insert); - lua_pushvalue(L, table); - LuaItemStack::create(L, item); - if(lua_pcall(L, 2, 0, 0)) - script_error(L, "error: %s", lua_tostring(L, -1)); - } - lua_remove(L, -2); // Remove table - lua_remove(L, -2); // Remove insert +bool ModApiItemMod::Initialize(lua_State *L,int top) { + + bool retval = true; + + retval &= API_FCT(register_item_raw); + retval &= API_FCT(register_alias_raw); + + LuaItemStack::Register(L); + + return retval; } + +ModApiItemMod modapi_item_prototyp; |