diff --git a/builtin/game/register.lua b/builtin/game/register.lua index f330491a2..05dc5fef8 100644 --- a/builtin/game/register.lua +++ b/builtin/game/register.lua @@ -7,6 +7,9 @@ local register_item_raw = core.register_item_raw core.register_item_raw = nil +local unregister_item_raw = core.unregister_item_raw +core.unregister_item_raw = nil + local register_alias_raw = core.register_alias_raw core.register_alias_raw = nil @@ -172,6 +175,27 @@ function core.register_item(name, itemdef) register_item_raw(itemdef) end +function core.unregister_item(name) + if not core.registered_items[name] then + core.log("warning", "Not unregistering item " ..name.. + " because it doesn't exist.") + return + end + -- Erase from registered_* table + local type = core.registered_items[name].type + if type == "node" then + core.registered_nodes[name] = nil + elseif type == "craft" then + core.registered_craftitems[name] = nil + elseif type == "tool" then + core.registered_tools[name] = nil + end + core.registered_items[name] = nil + + + unregister_item_raw(name) +end + function core.register_node(name, nodedef) nodedef.type = "node" core.register_item(name, nodedef) @@ -242,6 +266,20 @@ function core.register_alias(name, convert_to) end end +function core.register_alias_force(name, convert_to) + if forbidden_item_names[name] then + error("Unable to register alias: Name is forbidden: " .. name) + end + if core.registered_items[name] ~= nil then + core.unregister_item(name) + core.log("info", "Removed item " ..name.. + " while attempting to force add an alias") + end + --core.log("Registering alias: " .. name .. " -> " .. convert_to) + core.registered_aliases[name] = convert_to + register_alias_raw(name, convert_to) +end + function core.on_craft(itemstack, player, old_craft_list, craft_inv) for _, func in ipairs(core.registered_on_crafts) do itemstack = func(itemstack, player, old_craft_list, craft_inv) or itemstack diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 579fe796e..da9ebb9f1 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -208,11 +208,17 @@ when registering it. The `:` prefix can also be used for maintaining backwards compatibility. ### Aliases -Aliases can be added by using `minetest.register_alias(name, convert_to)`. +Aliases can be added by using `minetest.register_alias(name, convert_to)` or +`minetest.register_alias_force(name, convert_to). This will make Minetest to convert things called name to things called `convert_to`. +The only difference between `minetest.register_alias` and +`minetest.register_alias_force` is that if an item called `name` exists, +`minetest.register_alias` will do nothing while +`minetest.register_alias_force` will unregister it. + This can be used for maintaining backwards compatibility. This can be also used for setting quick access names for things, e.g. if @@ -464,6 +470,11 @@ the global `minetest.registered_*` tables. * `minetest.register_craftitem(name, item definition)` * added to `minetest.registered_items[name]` +* `minetest.unregister_item(name)` + * Unregisters the item name from engine, and deletes the entry with key + * `name` from `minetest.registered_items` and from the associated item + * table according to its nature: minetest.registered_nodes[] etc + * `minetest.register_biome(biome definition)` * returns an integer uniquely identifying the registered biome * added to `minetest.registered_biome` with the key of `biome.name` @@ -1883,7 +1894,9 @@ Call these functions only at load time! * `minetest.register_node(name, node definition)` * `minetest.register_tool(name, item definition)` * `minetest.register_craftitem(name, item definition)` +* `minetest.unregister_item(name)` * `minetest.register_alias(name, convert_to)` +* `minetest.register_alias_force(name, convert_to)` * `minetest.register_craft(recipe)` * Check recipe table syntax for different types below. * `minetest.clear_craft(recipe)` diff --git a/src/itemdef.cpp b/src/itemdef.cpp index a618ad631..a6c627a03 100644 --- a/src/itemdef.cpp +++ b/src/itemdef.cpp @@ -466,11 +466,17 @@ public: infostream<<"ItemDefManager: erased alias "< "< will load as . // Alias is not set if has already been defined. // Alias will be removed if is defined at a later point of time. diff --git a/src/nodedef.cpp b/src/nodedef.cpp index 646375575..bfb2999bd 100644 --- a/src/nodedef.cpp +++ b/src/nodedef.cpp @@ -778,6 +778,7 @@ public: content_t allocateId(); virtual content_t set(const std::string &name, const ContentFeatures &def); virtual content_t allocateDummy(const std::string &name); + virtual void removeNode(const std::string &name); virtual void updateAliases(IItemDefManager *idef); virtual void applyTextureOverrides(const std::string &override_filepath); virtual void updateTextures(IGameDef *gamedef, @@ -1072,6 +1073,40 @@ content_t CNodeDefManager::allocateDummy(const std::string &name) } +void CNodeDefManager::removeNode(const std::string &name) +{ + // Pre-condition + assert(name != ""); + + // Erase name from name ID mapping + content_t id = CONTENT_IGNORE; + if (m_name_id_mapping.getId(name, id)) { + m_name_id_mapping.eraseName(name); + m_name_id_mapping_with_aliases.erase(name); + } + + // Erase node content from all groups it belongs to + for (std::map::iterator iter_groups = + m_group_to_items.begin(); + iter_groups != m_group_to_items.end();) { + GroupItems &items = iter_groups->second; + for (GroupItems::iterator iter_groupitems = items.begin(); + iter_groupitems != items.end();) { + if (iter_groupitems->first == id) + items.erase(iter_groupitems++); + else + iter_groupitems++; + } + + // Check if group is empty + if (items.size() == 0) + m_group_to_items.erase(iter_groups++); + else + iter_groups++; + } +} + + void CNodeDefManager::updateAliases(IItemDefManager *idef) { std::set all = idef->getAll(); diff --git a/src/nodedef.h b/src/nodedef.h index f17c53727..80396f992 100644 --- a/src/nodedef.h +++ b/src/nodedef.h @@ -384,6 +384,8 @@ public: const ContentFeatures &def)=0; // If returns CONTENT_IGNORE, could not allocate id virtual content_t allocateDummy(const std::string &name)=0; + // Remove a node + virtual void removeNode(const std::string &name)=0; /* Update item alias mapping. diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index 5381cba76..ff0baea14 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -525,6 +525,27 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) return 0; /* number of results */ } +// unregister_item(name) +int ModApiItemMod::l_unregister_item_raw(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + std::string name = luaL_checkstring(L, 1); + + IWritableItemDefManager *idef = + getServer(L)->getWritableItemDefManager(); + + // Unregister the node + if (idef->get(name).type == ITEM_NODE) { + IWritableNodeDefManager *ndef = + getServer(L)->getWritableNodeDefManager(); + ndef->removeNode(name); + } + + idef->unregisterItem(name); + + return 0; /* number of results */ +} + // register_alias_raw(name, convert_to_name) int ModApiItemMod::l_register_alias_raw(lua_State *L) { @@ -570,6 +591,7 @@ int ModApiItemMod::l_get_name_from_content_id(lua_State *L) void ModApiItemMod::Initialize(lua_State *L, int top) { API_FCT(register_item_raw); + API_FCT(unregister_item_raw); API_FCT(register_alias_raw); API_FCT(get_content_id); API_FCT(get_name_from_content_id); diff --git a/src/script/lua_api/l_item.h b/src/script/lua_api/l_item.h index 0f9e4ba9b..be919b701 100644 --- a/src/script/lua_api/l_item.h +++ b/src/script/lua_api/l_item.h @@ -135,6 +135,7 @@ public: class ModApiItemMod : public ModApiBase { private: static int l_register_item_raw(lua_State *L); + static int l_unregister_item_raw(lua_State *L); static int l_register_alias_raw(lua_State *L); static int l_get_content_id(lua_State *L); static int l_get_name_from_content_id(lua_State *L);