objects from removed mod

Post Reply
rgh
Member
Posts: 46
Joined: Fri Oct 07, 2016 13:32

objects from removed mod

by rgh » Post

What happens if I install a mod that allows the creation of, say sheep, in the world & then remove that mod?
Are all the sheep automatically removed?

This thread:

viewtopic.php?f=11&t=2777

offers a mod to delete such objects, but it was a thread started back in 2012. What is the current situation?

ph8jPf9M
Member
Posts: 77
Joined: Sat Jul 16, 2016 10:29
GitHub: 22i

Re: objects from removed mod

by ph8jPf9M » Post

The moment you remove the mob mod all the mob entieties still remain but appear as unknown objects. when hovering over unknown objects it tells you what thing it was.
Image

Image

also in teh forum thread that you shared i found this code which works wounders by prestidigitator license: WTFPL the code works like this i think: each 10 seconds it checks for any unknown things close to you and removes them. When i tried it it removed all the unknown objects - still works

1. Make a folder called 'clean'. (Without quotes)
2. Right click, scroll to 'New'. Click 'Text files' in the context menu.
3. Rename text file to 'init.lua' (Without quotes). Open it.
4. Copy entire stuff in the code box.
5. Paste stuff into new text file you made.
6. Just to be sure, click 'File', 'Save As...' and type "init.lua" (WITH Quotes) and save.

Code: Select all

    local MOD_NAME = minetest.get_current_modname();
    local CLEANUP_PERIOD__S = 10.0;
    local ENTITY_CLEANUP_RADIUS = 80.0;
    local NODES_PER_BLOCK = 80;
    local FRESHNESS_META_KEY = MOD_NAME..":freshness";
    local MAX_TODO_SIZE = 100;
    local BATCH_SIZE = 3;

    local startTime = minetest.get_gametime();

    local function nodePosToBlockPos(pos)
       return {
                 x = math.floor(pos.x / NODES_PER_BLOCK),
                 y = math.floor(pos.y / NODES_PER_BLOCK),
                 z = math.floor(pos.z / NODES_PER_BLOCK)
              };
    end

    local function blockPosToNodePos(pos)
       return {
                 x = NODES_PER_BLOCK * pos.x,
                 y = NODES_PER_BLOCK * pos.y,
                 z = NODES_PER_BLOCK * pos.z
              };
    end

    local function cleanupEntitiesNear(pos)
       local objs = minetest.get_objects_inside_radius(pos, ENTITY_CLEANUP_RADIUS);
       for _, obj in ipairs(objs) do
          local pname = obj.get_player_name and obj:get_player_name();
          local entity = obj.get_luaentity and obj:get_luaentity();
          if entity then
             if entity.name == "__builtin:item" then
                local istr = entity.itemstring;
                local itemName = istr and ItemStack(istr):get_name();
                local def = itemName and itemName ~= "" and
                            (minetest.registered_entities[itemName] or
                             minetest.registered_items[itemName] or
                             minetest.registered_nodes[itemName] or
                             minetest.registered_craftitems[itemName] or
                             minetest.registered_tools[itemName]);
                if not def then
                   obj:remove();
                end
             end
          elseif not pname or pname == "" then
             obj:remove();
          end
       end
    end

    local function isBlockFresh(blockPos)
       local pos = blockPosToNodePos(blockPos);
       return minetest.get_meta(pos):get_int(FRESHNESS_META_KEY) == startTime;
    end

    local function setBlockFresh(blockPos)
       local pos = blockPosToNodePos(blockPos);
       minetest.get_meta(pos):set_int(FRESHNESS_META_KEY, startTime);
    end

    local addToDo;
    local removeToDo;
    do
       local size = 0;
       local head = nil;
       local tail = nil;

       addToDo = function(pos)
          if size >= MAX_TODO_SIZE then return false; end
          local n = { pos = pos };
          if head then
             tail.next = n;
             tail = n;
          else
             head = n;
             tail = n;
          end
          size = size + 1;
          return true;
       end

       removeToDo = function()
          if not head then return nil; end

          local n = head;
          head = n.next;
          if not head then tail = nil; end
          size = size - 1;

          return n.pos;
       end
    end

    local function markNodesClean(minp, maxp)
       local bpmin = nodePosToBlockPos(minp);
       local bpmax = nodePosToBlockPos(maxp);
       for x = bpmin.x, bpmax.x do
          for y = bpmin.y, bpmax.y do
             for z = bpmin.z, bpmax.z do
                setBlockFresh({ x = x, y = y, z = z });
             end
          end
       end
    end

    local function registerCleanupBlocks(pos)
       local bp = nodePosToBlockPos(pos);
       for x = bp.x-1, bp.x+1 do
          for y = bp.y-1, bp.y+1 do
             for z = bp.z-1, bp.z+1 do
                local bp = { x = x, y = y, z = z };
                if not isBlockFresh(bp) then
                   local willDo = addToDo(bp);
                   if willDo then setBlockFresh(bp); end
                end
             end
          end
       end
    end

    local function cleanupBlock()
       local bp = removeToDo();
       if not bp then return false; end

       local pmin = blockPosToNodePos(bp);
       local pmax = blockPosToNodePos({ x = bp.x+1, y = bp.y+1, z = bp.z+1 });
       pmax.x = pmax.x-1; -- make inclusive
       pmax.y = pmax.y-1;
       pmax.z = pmax.z-1;

       local vm = VoxelManip();
       pmin, pmax = vm:read_from_map(pmin, pmax);
       local va = VoxelArea:new({ MinEdge = pmin, MaxEdge = pmax });

       local data = vm:get_data();
       local airCid = minetest.get_content_id("air");
       local replaced = 0;
       for i, cid in ipairs(data) do
          local nodeName = minetest.get_name_from_content_id(cid);
          if not minetest.registered_nodes[nodeName] then
             data[i] = airCid;
             replaced = replaced + 1;
          end
       end
       if replaced > 0 then
          vm:set_data(data);
          vm:write_to_map();
          vm:update_map();
          vm:update_liquids();
       end

       return true;
    end

    local function cleanup()
       for _, player in ipairs(minetest.get_connected_players()) do
          local pos = player:getpos();
          cleanupEntitiesNear(pos);
          registerCleanupBlocks(pos);
       end
       for i = 1, BATCH_SIZE do
          if not cleanupBlock() then break; end
       end
    end

    do
       local elapsedTime_s = 0;
       minetest.register_globalstep(
          function(dt_s)
             elapsedTime_s = elapsedTime_s + dt_s;
             if elapsedTime_s >= CLEANUP_PERIOD__S then
                elapsedTime_s = 0;
                cleanup();
             end
          end);
    end

    minetest.register_on_generated(
       function(minp, maxp, blockSeed)
          markNodesClean(minp, maxp);
       end);
Attachments
catsmissing
catsmissing
catsmissing.png (260.1 KiB) Viewed 228 times
cats
cats
cats.png (265.91 KiB) Viewed 228 times

rgh
Member
Posts: 46
Joined: Fri Oct 07, 2016 13:32

Re: objects from removed mod

by rgh » Post

Thanks ph8jPf9M.

Seems a bit expensive to me, checking every 10 seconds when all that's needed is to scan the entire map just once, when you have removed a mod.

I'll experiment with it.

User avatar
kaeza
Moderator
Posts: 2162
Joined: Thu Oct 18, 2012 05:00
GitHub: kaeza
IRC: kaeza diemartin blaaaaargh
In-game: kaeza
Location: Montevideo, Uruguay
Contact:

Re: objects from removed mod

by kaeza » Post

PilzAdam's version removes objects once the game loads the entity. It is way more efficient than checkiing every N seconds.

It still worked last time I checked. If it does not, feel free to bump that thread with a bug report (viewtopic.php?f=6&t=5073#p75272).
Your signature is not the place for a blog post. Please keep it as concise as possible. Thank you!

Check out my stuff! | Donations greatly appreciated! PayPal

Post Reply

Who is online

Users browsing this forum: No registered users and 11 guests