Zefram
2014-05-16 68b7bcc28e39bdf0926072b834eeeeec0ee6c721
commit | author | age
d5c554 1 --[[
731a82 2 Wrench mod
S 3
4 Adds a wrench that allows the player to pickup nodes that contain an inventory
5 with items or metadata that needs perserving.
6 The wrench has the same tool capability as the normal hand.
7 To pickup a node simply right click on it. If the node contains a formspec,
8 you will need to shift+right click instead.
d5c554 9 --]]
21c96a 10
c5a2f0 11 local LATEST_SERIALIZATION_VERSION = 1
S 12
731a82 13 wrench = {}
S 14
15 local modpath = minetest.get_modpath(minetest.get_current_modname())
16 dofile(modpath.."/support.lua")
17 dofile(modpath.."/technic.lua")
18
39c41a 19 -- Boilerplate to support localized strings if intllib mod is installed.
X 20 local S
21 if intllib then
22     S = intllib.Getter()
23 else
24     S = function(s) return s end
25 end
26
731a82 27 local function get_meta_type(name, metaname)
S 28     local def = wrench.registered_nodes[name]
29     if not def or not def.metas or not def.metas[metaname] then
30         return nil
21c96a 31     end
731a82 32     return def.metas[metaname]
21c96a 33 end
M 34
731a82 35 local function get_pickup_name(name)
S 36     return "wrench:picked_up_"..(name:gsub(":", "_"))
37 end
38
39 local function restore(pos, placer, itemstack)
40     local name = itemstack:get_name()
41     local meta = minetest.get_meta(pos)
42     local inv = meta:get_inventory()
43     local data = minetest.deserialize(itemstack:get_metadata())
44     minetest.set_node(pos, {name = data.name})
45     local lists = data.lists
46     for listname, list in pairs(lists) do
47         inv:set_list(listname, list)
48     end
49     for name, value in pairs(data.metas) do
50         local meta_type = get_meta_type(data.name, name)
51         if meta_type == wrench.META_TYPE_INT then
52             meta:set_int(name, value)
53         elseif meta_type == wrench.META_TYPE_FLOAT then
54             meta:set_float(name, value)
55         elseif meta_type == wrench.META_TYPE_STRING then
56             meta:set_string(name, value)
57         end
58     end
59     itemstack:take_item()
60     return itemstack
61 end
62
63 for name, info in pairs(wrench.registered_nodes) do
21c96a 64     local olddef = minetest.registered_nodes[name]
731a82 65     if olddef then
21c96a 66         local newdef = {}
731a82 67         for key, value in pairs(olddef) do
21c96a 68             newdef[key] = value
M 69         end
70         newdef.stack_max = 1
39c41a 71         newdef.description = S("%s with items"):format(newdef.description)
3b7695 72         newdef.groups = {}
21c96a 73         newdef.groups.not_in_creative_inventory = 1
M 74         newdef.on_construct = nil
75         newdef.on_destruct = nil
731a82 76         newdef.after_place_node = restore
S 77         minetest.register_node(":"..get_pickup_name(name), newdef)
21c96a 78     end
M 79 end
80
81 minetest.register_tool("wrench:wrench", {
39c41a 82     description = S("Wrench"),
21c96a 83     inventory_image = "technic_wrench.png",
M 84     tool_capabilities = {
85         full_punch_interval = 0.9,
86         max_drop_level = 0,
87         groupcaps = {
88             crumbly = {times={[2]=3.00, [3]=0.70}, uses=0, maxlevel=1},
89             snappy = {times={[3]=0.40}, uses=0, maxlevel=1},
731a82 90             oddly_breakable_by_hand = {times={[1]=7.00,[2]=4.00,[3]=1.40},
S 91                         uses=0, maxlevel=3}
21c96a 92         },
M 93         damage_groups = {fleshy=1},
94     },
95     on_place = function(itemstack, placer, pointed_thing)
96         local pos = pointed_thing.under
731a82 97         if not placer or not pos then
S 98             return
99         end
100         if minetest.is_protected(pos, placer:get_player_name()) then
101             minetest.record_protection_violation(pos, placer:get_player_name())
102             return
103         end
21c96a 104         local name = minetest.get_node(pos).name
731a82 105         local def = wrench.registered_nodes[name]
S 106         if not def then
107             return
108         end
109
110         local stack = ItemStack(get_pickup_name(name))
111         local player_inv = placer:get_inventory()
112         if not player_inv:room_for_item("main", stack) then
113             return
114         end
3b7695 115         local meta = minetest.get_meta(pos)
731a82 116         if def.owned then
d5c554 117             local owner = meta:get_string("owner")
731a82 118             if owner and owner ~= placer:get_player_name() then
S 119                 minetest.log("action", placer:get_player_name()..
120                     " tried to pick up a owned node belonging to "..
d5c554 121                     owner.." at "..
3b7695 122                     minetest.pos_to_string(pos))
731a82 123                 return
21c96a 124             end
M 125         end
731a82 126
S 127         local metadata = {}
128         metadata.name = name
c5a2f0 129         metadata.version = LATEST_SERIALIZATION_VERSION
S 130
3b7695 131         local inv = meta:get_inventory()
731a82 132         local lists = {}
S 133         for _, listname in pairs(def.lists or {}) do
134             if not inv:is_empty(listname) then
135                 empty = false
21c96a 136             end
731a82 137             local list = inv:get_list(listname)
S 138             for i, stack in pairs(list) do
139                 list[i] = stack:to_string()
140             end
141             lists[listname] = list
21c96a 142         end
731a82 143         metadata.lists = lists
3b7695 144         
731a82 145         local metas = {}
S 146         for name, meta_type in pairs(def.metas or {}) do
147             if meta_type == wrench.META_TYPE_INT then
148                 metas[name] = meta:get_int(name)
149             elseif meta_type == wrench.META_TYPE_FLOAT then
150                 metas[name] = meta:get_float(name)
151             elseif meta_type == wrench.META_TYPE_STRING then
152                 metas[name] = meta:get_string(name)
3b7695 153             end
M 154         end
731a82 155         metadata.metas = metas
3b7695 156         
731a82 157         stack:set_metadata(minetest.serialize(metadata))
S 158         minetest.remove_node(pos)
159         itemstack:add_wear(65535 / 20)
160         player_inv:add_item("main", stack)
21c96a 161         return itemstack
M 162     end,
163 })
164
165 minetest.register_craft({
166     output = "wrench:wrench",
167     recipe = {
68b7bc 168         {"technic:carbon_steel_ingot", "",                           "technic:carbon_steel_ingot"},
Z 169         {"",                           "technic:carbon_steel_ingot", ""},
170         {"",                           "technic:carbon_steel_ingot", ""},
21c96a 171     },
3b32bf 172 })