ShadowNinja
2013-12-20 731a82169b01116a4b707d9ecca3c7c9ca930abc
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
731a82 11 wrench = {}
S 12
13 local modpath = minetest.get_modpath(minetest.get_current_modname())
14 dofile(modpath.."/support.lua")
15 dofile(modpath.."/technic.lua")
16
17 local function get_meta_type(name, metaname)
18     local def = wrench.registered_nodes[name]
19     if not def or not def.metas or not def.metas[metaname] then
20         return nil
21c96a 21     end
731a82 22     return def.metas[metaname]
21c96a 23 end
M 24
731a82 25 local function get_pickup_name(name)
S 26     return "wrench:picked_up_"..(name:gsub(":", "_"))
27 end
28
29 local function restore(pos, placer, itemstack)
30     local name = itemstack:get_name()
31     local meta = minetest.get_meta(pos)
32     local inv = meta:get_inventory()
33     local data = minetest.deserialize(itemstack:get_metadata())
34     minetest.set_node(pos, {name = data.name})
35     local lists = data.lists
36     for listname, list in pairs(lists) do
37         inv:set_list(listname, list)
38     end
39     for name, value in pairs(data.metas) do
40         local meta_type = get_meta_type(data.name, name)
41         if meta_type == wrench.META_TYPE_INT then
42             meta:set_int(name, value)
43         elseif meta_type == wrench.META_TYPE_FLOAT then
44             meta:set_float(name, value)
45         elseif meta_type == wrench.META_TYPE_STRING then
46             meta:set_string(name, value)
47         end
48     end
49     itemstack:take_item()
50     return itemstack
51 end
52
53 for name, info in pairs(wrench.registered_nodes) do
21c96a 54     local olddef = minetest.registered_nodes[name]
731a82 55     if olddef then
21c96a 56         local newdef = {}
731a82 57         for key, value in pairs(olddef) do
21c96a 58             newdef[key] = value
M 59         end
60         newdef.stack_max = 1
61         newdef.description = newdef.description.." with items"
3b7695 62         newdef.groups = {}
21c96a 63         newdef.groups.not_in_creative_inventory = 1
M 64         newdef.on_construct = nil
65         newdef.on_destruct = nil
731a82 66         newdef.after_place_node = restore
S 67         minetest.register_node(":"..get_pickup_name(name), newdef)
21c96a 68     end
M 69 end
70
71 minetest.register_tool("wrench:wrench", {
72     description = "Wrench",
73     inventory_image = "technic_wrench.png",
74     tool_capabilities = {
75         full_punch_interval = 0.9,
76         max_drop_level = 0,
77         groupcaps = {
78             crumbly = {times={[2]=3.00, [3]=0.70}, uses=0, maxlevel=1},
79             snappy = {times={[3]=0.40}, uses=0, maxlevel=1},
731a82 80             oddly_breakable_by_hand = {times={[1]=7.00,[2]=4.00,[3]=1.40},
S 81                         uses=0, maxlevel=3}
21c96a 82         },
M 83         damage_groups = {fleshy=1},
84     },
85     on_place = function(itemstack, placer, pointed_thing)
86         local pos = pointed_thing.under
731a82 87         if not placer or not pos then
S 88             return
89         end
90         if minetest.is_protected(pos, placer:get_player_name()) then
91             minetest.record_protection_violation(pos, placer:get_player_name())
92             return
93         end
21c96a 94         local name = minetest.get_node(pos).name
731a82 95         local def = wrench.registered_nodes[name]
S 96         if not def then
97             return
98         end
99
100         local stack = ItemStack(get_pickup_name(name))
101         local player_inv = placer:get_inventory()
102         if not player_inv:room_for_item("main", stack) then
103             return
104         end
3b7695 105         local meta = minetest.get_meta(pos)
731a82 106         if def.owned then
d5c554 107             local owner = meta:get_string("owner")
731a82 108             if owner and owner ~= placer:get_player_name() then
S 109                 minetest.log("action", placer:get_player_name()..
110                     " tried to pick up a owned node belonging to "..
d5c554 111                     owner.." at "..
3b7695 112                     minetest.pos_to_string(pos))
731a82 113                 return
21c96a 114             end
M 115         end
731a82 116
S 117         local metadata = {}
118         metadata.name = name
3b7695 119         
M 120         local inv = meta:get_inventory()
731a82 121         local lists = {}
S 122         for _, listname in pairs(def.lists or {}) do
123             if not inv:is_empty(listname) then
124                 empty = false
21c96a 125             end
731a82 126             local list = inv:get_list(listname)
S 127             for i, stack in pairs(list) do
128                 list[i] = stack:to_string()
129             end
130             lists[listname] = list
21c96a 131         end
731a82 132         metadata.lists = lists
3b7695 133         
731a82 134         local metas = {}
S 135         for name, meta_type in pairs(def.metas or {}) do
136             if meta_type == wrench.META_TYPE_INT then
137                 metas[name] = meta:get_int(name)
138             elseif meta_type == wrench.META_TYPE_FLOAT then
139                 metas[name] = meta:get_float(name)
140             elseif meta_type == wrench.META_TYPE_STRING then
141                 metas[name] = meta:get_string(name)
3b7695 142             end
M 143         end
731a82 144         metadata.metas = metas
3b7695 145         
731a82 146         stack:set_metadata(minetest.serialize(metadata))
S 147         minetest.remove_node(pos)
148         itemstack:add_wear(65535 / 20)
149         player_inv:add_item("main", stack)
21c96a 150         return itemstack
M 151     end,
152 })
153
154 minetest.register_craft({
155     output = "wrench:wrench",
156     recipe = {
731a82 157         {"default:steel_ingot", "",                    "default:steel_ingot"},
S 158         {"",                    "default:steel_ingot", ""},
159         {"",                    "default:steel_ingot", ""},
21c96a 160     },
3b32bf 161 })