mirror of
https://github.com/minetest-mods/technic.git
synced 2024-12-21 13:25:43 +01:00
0f6bdb1bde
Also includes a few code opimizations: - Combined mining drill functions - Shorter alias registration (unused?) - Add TODOs to address later
174 lines
5.2 KiB
Lua
174 lines
5.2 KiB
Lua
--[[
|
|
Wrench mod
|
|
|
|
Adds a wrench that allows the player to pickup nodes that contain an inventory
|
|
with items or metadata that needs perserving.
|
|
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
|
|
|
|
wrench = {}
|
|
|
|
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
|
dofile(modpath.."/support.lua")
|
|
dofile(modpath.."/technic.lua")
|
|
|
|
-- Boilerplate to support localized strings if intllib mod is installed.
|
|
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]
|
|
return def and def.metas and def.metas[metaname] or nil
|
|
end
|
|
|
|
local function get_pickup_name(name)
|
|
return "wrench:picked_up_"..(name:gsub(":", "_"))
|
|
end
|
|
|
|
local function restore(pos, placer, itemstack)
|
|
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()
|
|
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(key, value)
|
|
elseif meta_type == wrench.META_TYPE_FLOAT then
|
|
meta:set_float(key, value)
|
|
elseif meta_type == wrench.META_TYPE_STRING then
|
|
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
|
|
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
|
|
|
|
minetest.register_tool("wrench:wrench", {
|
|
description = S("Wrench"),
|
|
inventory_image = "technic_wrench.png",
|
|
tool_capabilities = {
|
|
full_punch_interval = 0.9,
|
|
max_drop_level = 0,
|
|
groupcaps = {
|
|
crumbly = {times={[2]=3.00, [3]=0.70}, uses=0, maxlevel=1},
|
|
snappy = {times={[3]=0.40}, uses=0, maxlevel=1},
|
|
oddly_breakable_by_hand = {times={[1]=7.00,[2]=4.00,[3]=1.40},
|
|
uses=0, maxlevel=3}
|
|
},
|
|
damage_groups = {fleshy=1},
|
|
},
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
local pos = pointed_thing.under
|
|
if not placer or not pos then
|
|
return
|
|
end
|
|
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 node_name = minetest.get_node(pos).name
|
|
local def = wrench.registered_nodes[node_name]
|
|
if not def then
|
|
return
|
|
end
|
|
|
|
local stack_pickup = ItemStack(get_pickup_name(node_name))
|
|
local player_inv = placer:get_inventory()
|
|
if not player_inv:room_for_item("main", stack_pickup) then
|
|
return
|
|
end
|
|
local meta = minetest.get_meta(pos)
|
|
if def.owned and not minetest.check_player_privs(placer, "protection_bypass") then
|
|
local owner = meta:get_string("owner")
|
|
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 = 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
|
|
local list = inv:get_list(listname)
|
|
for i, stack in pairs(list) do
|
|
list[i] = stack:to_string()
|
|
end
|
|
lists[listname] = list
|
|
end
|
|
metadata.lists = lists
|
|
|
|
-- 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
|
|
metadata.metas[key] = meta:get_int(key)
|
|
elseif meta_type == wrench.META_TYPE_FLOAT then
|
|
metadata.metas[key] = meta:get_float(key)
|
|
elseif meta_type == wrench.META_TYPE_STRING then
|
|
metadata.metas[key] = meta:get_string(key)
|
|
end
|
|
end
|
|
|
|
item_meta:set_string("data", minetest.serialize(metadata))
|
|
minetest.remove_node(pos)
|
|
itemstack:add_wear(65535 / 20)
|
|
player_inv:add_item("main", stack_pickup)
|
|
return itemstack
|
|
end,
|
|
})
|