From 9b7c44b4530bf82790af495ac574a998656cade9 Mon Sep 17 00:00:00 2001 From: SmallJoker <mk939@ymail.com> Date: Sun, 29 Jan 2023 13:11:37 +0100 Subject: [PATCH] Wrench: Fix node registration from other mods --- wrench/init.lua | 144 ++++++++++++++++++++++++----------------------- 1 files changed, 74 insertions(+), 70 deletions(-) diff --git a/wrench/init.lua b/wrench/init.lua index f0a0e00..7696df5 100644 --- a/wrench/init.lua +++ b/wrench/init.lua @@ -6,6 +6,9 @@ The wrench has the same tool capability as the normal hand. To pickup a node simply right click on it. If the node contains a formspec, you will need to shift+right click instead. +Because it enables arbitrary nesting of chests, and so allows the player +to carry an unlimited amount of material at once, this wrench is not +available to survival-mode players. --]] local LATEST_SERIALIZATION_VERSION = 1 @@ -17,19 +20,11 @@ dofile(modpath.."/technic.lua") -- Boilerplate to support localized strings if intllib mod is installed. -local S -if 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) @@ -37,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"), @@ -97,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() @@ -141,32 +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, -}) - -minetest.register_craft({ - output = "wrench:wrench", - recipe = { - {"technic:carbon_steel_ingot", "", "technic:carbon_steel_ingot"}, - {"", "technic:carbon_steel_ingot", ""}, - {"", "technic:carbon_steel_ingot", ""}, - }, }) -- Gitblit v1.8.0