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