Add minetest.unregister_item and minetest.register_alias_force
authorpaly2 <plangrognet@laposte.net>
Sun, 10 Jul 2016 13:15:43 +0000 (15:15 +0200)
committerkwolekr <kwolekr@minetest.net>
Thu, 8 Sep 2016 07:26:52 +0000 (03:26 -0400)
builtin/game/register.lua
doc/lua_api.txt
src/itemdef.cpp
src/itemdef.h
src/nodedef.cpp
src/nodedef.h
src/script/lua_api/l_item.cpp
src/script/lua_api/l_item.h

index f330491a21cf797be12db5c6895c444e9be3fcc3..05dc5fef83da73be5243b27fc0d4f640861ecd4d 100644 (file)
@@ -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
index 579fe796e18f30a68657f48ec6df91ffb029626c..da9ebb9f1f8bc485d183040194b1c8f7a1afb065 100644 (file)
@@ -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)`
index a618ad631b078666a682ec39d944b129b2096884..a6c627a037a5992639be2848efc6ea780c2434e1 100644 (file)
@@ -466,11 +466,17 @@ public:
                        infostream<<"ItemDefManager: erased alias "<<def.name
                                        <<" because item was defined"<<std::endl;
        }
+       virtual void unregisterItem(const std::string &name)
+       {
+               verbosestream<<"ItemDefManager: unregistering \""<<name<<"\""<<std::endl;
+
+               delete m_item_definitions[name];
+               m_item_definitions.erase(name);
+       }
        virtual void registerAlias(const std::string &name,
                        const std::string &convert_to)
        {
-               if(m_item_definitions.find(name) == m_item_definitions.end())
-               {
+               if (m_item_definitions.find(name) == m_item_definitions.end()) {
                        verbosestream<<"ItemDefManager: setting alias "<<name
                                <<" -> "<<convert_to<<std::endl;
                        m_aliases[name] = convert_to;
index 805b4aa5dd09bfb8b977bad71b93177a4d7bdcef..b14ed41f7f2a5a0b21acea8a436c98db4f454585 100644 (file)
@@ -144,6 +144,7 @@ public:
        virtual void clear()=0;
        // Register item definition
        virtual void registerItem(const ItemDefinition &def)=0;
+       virtual void unregisterItem(const std::string &name)=0;
        // Set an alias so that items named <name> will load as <convert_to>.
        // Alias is not set if <name> has already been defined.
        // Alias will be removed if <name> is defined at a later point of time.
index 646375575d5483946feffe719c3fd9490855ce29..bfb2999bd33bf1bd57f6a8763ec1d0af9c6fd27d 100644 (file)
@@ -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<std::string, GroupItems>::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<std::string> all = idef->getAll();
index f17c53727a6393e5a36688f4fcef795e9267bc9b..80396f992308db095f40871d6ec5a4723286692f 100644 (file)
@@ -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.
index 5381cba7616c0c62378372d4e57b3273e5b17c83..ff0baea14ee6bab42ba1c18bffee1e154c312cbe 100644 (file)
@@ -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);
index 0f9e4ba9bdfbdd0bb9d94a0b12b66b73caba82a8..be919b70193e60f56ae5b4722d5fdafb555216a9 100644 (file)
@@ -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);