SmallJoker
2023-01-29 9b7c44b4530bf82790af495ac574a998656cade9
wrench/init.lua
@@ -20,19 +20,11 @@
dofile(modpath.."/technic.lua")
-- Boilerplate to support localized strings if intllib mod is installed.
local S
if rawget(_G, "intllib") then
   S = intllib.Getter()
else
   S = function(s) return s end
end
local S = rawget(_G, "intllib") and intllib.Getter() or function(s) return s end
local function get_meta_type(name, metaname)
   local def = wrench.registered_nodes[name]
   if not def or not def.metas or not def.metas[metaname] then
      return nil
   end
   return def.metas[metaname]
   return def and def.metas and def.metas[metaname] or nil
end
local function get_pickup_name(name)
@@ -40,46 +32,63 @@
end
local function restore(pos, placer, itemstack)
   local name = itemstack:get_name()
   local data = itemstack:get_meta():get_string("data")
   data = (data ~= "" and data) or   itemstack:get_metadata()
   data = minetest.deserialize(data)
   if not data then
      minetest.remove_node(pos)
      minetest.log("error", placer:get_player_name().." wanted to place "..
            itemstack:get_name().." at "..minetest.pos_to_string(pos)..
            ", but it had no data.")
      minetest.log("verbose", "itemstack: "..itemstack:to_string())
      return true
   end
   local node = minetest.get_node(pos)
   minetest.set_node(pos, {name = data.name, param2 = node.param2})
   -- Apply stored metadata to the current node
   local meta = minetest.get_meta(pos)
   local inv = meta:get_inventory()
   local data = minetest.deserialize(itemstack:get_metadata())
   minetest.set_node(pos, {name = data.name})
   local lists = data.lists
   for listname, list in pairs(lists) do
      inv:set_list(listname, list)
   end
   for name, value in pairs(data.metas) do
      local meta_type = get_meta_type(data.name, name)
   for key, value in pairs(data.metas) do
      local meta_type = get_meta_type(data.name, key)
      if meta_type == wrench.META_TYPE_INT then
         meta:set_int(name, value)
         meta:set_int(key, value)
      elseif meta_type == wrench.META_TYPE_FLOAT then
         meta:set_float(name, value)
         meta:set_float(key, value)
      elseif meta_type == wrench.META_TYPE_STRING then
         meta:set_string(name, value)
         meta:set_string(key, value)
      end
   end
   for listname, list in pairs(data.lists) do
      inv:set_list(listname, list)
   end
   itemstack:take_item()
   return itemstack
end
for name, info in pairs(wrench.registered_nodes) do
   local olddef = minetest.registered_nodes[name]
   if olddef then
      local newdef = {}
      for key, value in pairs(olddef) do
         newdef[key] = value
minetest.register_on_mods_loaded(function()
   -- Delayed registration for foreign mod support
   for name, info in pairs(wrench.registered_nodes) do
      local olddef = minetest.registered_nodes[name]
      if olddef then
         local newdef = {}
         for key, value in pairs(olddef) do
            newdef[key] = value
         end
         newdef.stack_max = 1
         newdef.description = S("%s with items"):format(newdef.description)
         newdef.groups = {}
         newdef.groups.not_in_creative_inventory = 1
         newdef.on_construct = nil
         newdef.on_destruct = nil
         newdef.after_place_node = restore
         minetest.register_node(":"..get_pickup_name(name), newdef)
      end
      newdef.stack_max = 1
      newdef.description = S("%s with items"):format(newdef.description)
      newdef.groups = {}
      newdef.groups.not_in_creative_inventory = 1
      newdef.on_construct = nil
      newdef.on_destruct = nil
      newdef.after_place_node = restore
      minetest.register_node(":"..get_pickup_name(name), newdef)
   end
end
end)
minetest.register_tool("wrench:wrench", {
   description = S("Wrench"),
@@ -100,43 +109,43 @@
      if not placer or not pos then
         return
      end
      if minetest.is_protected(pos, placer:get_player_name()) then
         minetest.record_protection_violation(pos, placer:get_player_name())
      local player_name = placer:get_player_name()
      if minetest.is_protected(pos, player_name) then
         minetest.record_protection_violation(pos, player_name)
         return
      end
      local name = minetest.get_node(pos).name
      local def = wrench.registered_nodes[name]
      local node_name = minetest.get_node(pos).name
      local def = wrench.registered_nodes[node_name]
      if not def then
         return
      end
      local stack = ItemStack(get_pickup_name(name))
      local stack_pickup = ItemStack(get_pickup_name(node_name))
      local player_inv = placer:get_inventory()
      if not player_inv:room_for_item("main", stack) then
      if not player_inv:room_for_item("main", stack_pickup) then
         return
      end
      local meta = minetest.get_meta(pos)
      if def.owned then
      if def.owned and not minetest.check_player_privs(placer, "protection_bypass") then
         local owner = meta:get_string("owner")
         if owner and owner ~= placer:get_player_name() then
            minetest.log("action", placer:get_player_name()..
               " tried to pick up a owned node belonging to "..
         if owner and owner ~= player_name then
            minetest.log("action", player_name..
               " tried to pick up an owned node belonging to "..
               owner.." at "..
               minetest.pos_to_string(pos))
            return
         end
      end
      -- Do the actual pickup:
      local metadata = {}
      metadata.name = name
      metadata.name = node_name
      metadata.version = LATEST_SERIALIZATION_VERSION
      -- Serialize inventory lists + items
      local inv = meta:get_inventory()
      local lists = {}
      for _, listname in pairs(def.lists or {}) do
         if not inv:is_empty(listname) then
            empty = false
         end
         local list = inv:get_list(listname)
         for i, stack in pairs(list) do
            list[i] = stack:to_string()
@@ -144,23 +153,24 @@
         lists[listname] = list
      end
      metadata.lists = lists
      local metas = {}
      for name, meta_type in pairs(def.metas or {}) do
      -- Serialize node metadata fields
      local item_meta = stack_pickup:get_meta()
      metadata.metas = {}
      for key, meta_type in pairs(def.metas or {}) do
         if meta_type == wrench.META_TYPE_INT then
            metas[name] = meta:get_int(name)
            metadata.metas[key] = meta:get_int(key)
         elseif meta_type == wrench.META_TYPE_FLOAT then
            metas[name] = meta:get_float(name)
            metadata.metas[key] = meta:get_float(key)
         elseif meta_type == wrench.META_TYPE_STRING then
            metas[name] = meta:get_string(name)
            metadata.metas[key] = meta:get_string(key)
         end
      end
      metadata.metas = metas
      stack:set_metadata(minetest.serialize(metadata))
      item_meta:set_string("data", minetest.serialize(metadata))
      minetest.remove_node(pos)
      itemstack:add_wear(65535 / 20)
      player_inv:add_item("main", stack)
      player_inv:add_item("main", stack_pickup)
      return itemstack
   end,
})