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. |
0cf413
|
9 |
Because it enables arbitrary nesting of chests, and so allows the player |
Z |
10 |
to carry an unlimited amount of material at once, this wrench is not |
|
11 |
available to survival-mode players. |
d5c554
|
12 |
--]] |
21c96a
|
13 |
|
c5a2f0
|
14 |
local LATEST_SERIALIZATION_VERSION = 1 |
S |
15 |
|
731a82
|
16 |
wrench = {} |
S |
17 |
|
|
18 |
local modpath = minetest.get_modpath(minetest.get_current_modname()) |
|
19 |
dofile(modpath.."/support.lua") |
|
20 |
dofile(modpath.."/technic.lua") |
|
21 |
|
39c41a
|
22 |
-- Boilerplate to support localized strings if intllib mod is installed. |
41a10a
|
23 |
local S = rawget(_G, "intllib") and intllib.Getter() or function(s) return s end |
39c41a
|
24 |
|
731a82
|
25 |
local function get_meta_type(name, metaname) |
S |
26 |
local def = wrench.registered_nodes[name] |
161462
|
27 |
return def and def.metas and def.metas[metaname] or nil |
21c96a
|
28 |
end |
M |
29 |
|
731a82
|
30 |
local function get_pickup_name(name) |
S |
31 |
return "wrench:picked_up_"..(name:gsub(":", "_")) |
|
32 |
end |
|
33 |
|
|
34 |
local function restore(pos, placer, itemstack) |
9167d4
|
35 |
local data = itemstack:get_meta():get_string("data") |
D |
36 |
data = (data ~= "" and data) or itemstack:get_metadata() |
|
37 |
data = minetest.deserialize(data) |
0f6bdb
|
38 |
|
161462
|
39 |
if not data then |
D |
40 |
minetest.remove_node(pos) |
|
41 |
minetest.log("error", placer:get_player_name().." wanted to place ".. |
0f6bdb
|
42 |
itemstack:get_name().." at "..minetest.pos_to_string(pos).. |
161462
|
43 |
", but it had no data.") |
D |
44 |
minetest.log("verbose", "itemstack: "..itemstack:to_string()) |
|
45 |
return true |
|
46 |
end |
0f6bdb
|
47 |
|
S |
48 |
local node = minetest.get_node(pos) |
78bfa4
|
49 |
minetest.set_node(pos, {name = data.name, param2 = node.param2}) |
0f6bdb
|
50 |
|
S |
51 |
-- Apply stored metadata to the current node |
|
52 |
local meta = minetest.get_meta(pos) |
|
53 |
local inv = meta:get_inventory() |
|
54 |
for key, value in pairs(data.metas) do |
|
55 |
local meta_type = get_meta_type(data.name, key) |
731a82
|
56 |
if meta_type == wrench.META_TYPE_INT then |
0f6bdb
|
57 |
meta:set_int(key, value) |
731a82
|
58 |
elseif meta_type == wrench.META_TYPE_FLOAT then |
0f6bdb
|
59 |
meta:set_float(key, value) |
731a82
|
60 |
elseif meta_type == wrench.META_TYPE_STRING then |
0f6bdb
|
61 |
meta:set_string(key, value) |
731a82
|
62 |
end |
S |
63 |
end |
0f6bdb
|
64 |
|
S |
65 |
for listname, list in pairs(data.lists) do |
4874e2
|
66 |
inv:set_list(listname, list) |
R |
67 |
end |
731a82
|
68 |
itemstack:take_item() |
S |
69 |
return itemstack |
|
70 |
end |
|
71 |
|
9b7c44
|
72 |
minetest.register_on_mods_loaded(function() |
S |
73 |
-- Delayed registration for foreign mod support |
|
74 |
for name, info in pairs(wrench.registered_nodes) do |
|
75 |
local olddef = minetest.registered_nodes[name] |
|
76 |
if olddef then |
|
77 |
local newdef = {} |
|
78 |
for key, value in pairs(olddef) do |
|
79 |
newdef[key] = value |
|
80 |
end |
|
81 |
newdef.stack_max = 1 |
|
82 |
newdef.description = S("%s with items"):format(newdef.description) |
|
83 |
newdef.groups = {} |
|
84 |
newdef.groups.not_in_creative_inventory = 1 |
|
85 |
newdef.on_construct = nil |
|
86 |
newdef.on_destruct = nil |
|
87 |
newdef.after_place_node = restore |
|
88 |
minetest.register_node(":"..get_pickup_name(name), newdef) |
21c96a
|
89 |
end |
M |
90 |
end |
9b7c44
|
91 |
end) |
21c96a
|
92 |
|
M |
93 |
minetest.register_tool("wrench:wrench", { |
39c41a
|
94 |
description = S("Wrench"), |
21c96a
|
95 |
inventory_image = "technic_wrench.png", |
M |
96 |
tool_capabilities = { |
|
97 |
full_punch_interval = 0.9, |
|
98 |
max_drop_level = 0, |
|
99 |
groupcaps = { |
|
100 |
crumbly = {times={[2]=3.00, [3]=0.70}, uses=0, maxlevel=1}, |
|
101 |
snappy = {times={[3]=0.40}, uses=0, maxlevel=1}, |
731a82
|
102 |
oddly_breakable_by_hand = {times={[1]=7.00,[2]=4.00,[3]=1.40}, |
S |
103 |
uses=0, maxlevel=3} |
21c96a
|
104 |
}, |
M |
105 |
damage_groups = {fleshy=1}, |
|
106 |
}, |
|
107 |
on_place = function(itemstack, placer, pointed_thing) |
|
108 |
local pos = pointed_thing.under |
731a82
|
109 |
if not placer or not pos then |
S |
110 |
return |
|
111 |
end |
9167d4
|
112 |
local player_name = placer:get_player_name() |
D |
113 |
if minetest.is_protected(pos, player_name) then |
|
114 |
minetest.record_protection_violation(pos, player_name) |
731a82
|
115 |
return |
S |
116 |
end |
0f6bdb
|
117 |
local node_name = minetest.get_node(pos).name |
S |
118 |
local def = wrench.registered_nodes[node_name] |
731a82
|
119 |
if not def then |
S |
120 |
return |
|
121 |
end |
|
122 |
|
0f6bdb
|
123 |
local stack_pickup = ItemStack(get_pickup_name(node_name)) |
731a82
|
124 |
local player_inv = placer:get_inventory() |
0f6bdb
|
125 |
if not player_inv:room_for_item("main", stack_pickup) then |
731a82
|
126 |
return |
S |
127 |
end |
3b7695
|
128 |
local meta = minetest.get_meta(pos) |
395089
|
129 |
if def.owned and not minetest.check_player_privs(placer, "protection_bypass") then |
d5c554
|
130 |
local owner = meta:get_string("owner") |
9167d4
|
131 |
if owner and owner ~= player_name then |
D |
132 |
minetest.log("action", player_name.. |
|
133 |
" tried to pick up an owned node belonging to ".. |
d5c554
|
134 |
owner.." at ".. |
3b7695
|
135 |
minetest.pos_to_string(pos)) |
731a82
|
136 |
return |
21c96a
|
137 |
end |
M |
138 |
end |
731a82
|
139 |
|
0f6bdb
|
140 |
-- Do the actual pickup: |
731a82
|
141 |
local metadata = {} |
0f6bdb
|
142 |
metadata.name = node_name |
c5a2f0
|
143 |
metadata.version = LATEST_SERIALIZATION_VERSION |
S |
144 |
|
0f6bdb
|
145 |
-- Serialize inventory lists + items |
3b7695
|
146 |
local inv = meta:get_inventory() |
731a82
|
147 |
local lists = {} |
S |
148 |
for _, listname in pairs(def.lists or {}) do |
|
149 |
local list = inv:get_list(listname) |
|
150 |
for i, stack in pairs(list) do |
|
151 |
list[i] = stack:to_string() |
|
152 |
end |
|
153 |
lists[listname] = list |
21c96a
|
154 |
end |
731a82
|
155 |
metadata.lists = lists |
9167d4
|
156 |
|
0f6bdb
|
157 |
-- Serialize node metadata fields |
S |
158 |
local item_meta = stack_pickup:get_meta() |
9167d4
|
159 |
metadata.metas = {} |
0f6bdb
|
160 |
for key, meta_type in pairs(def.metas or {}) do |
731a82
|
161 |
if meta_type == wrench.META_TYPE_INT then |
0f6bdb
|
162 |
metadata.metas[key] = meta:get_int(key) |
731a82
|
163 |
elseif meta_type == wrench.META_TYPE_FLOAT then |
0f6bdb
|
164 |
metadata.metas[key] = meta:get_float(key) |
731a82
|
165 |
elseif meta_type == wrench.META_TYPE_STRING then |
0f6bdb
|
166 |
metadata.metas[key] = meta:get_string(key) |
3b7695
|
167 |
end |
M |
168 |
end |
9167d4
|
169 |
|
D |
170 |
item_meta:set_string("data", minetest.serialize(metadata)) |
731a82
|
171 |
minetest.remove_node(pos) |
S |
172 |
itemstack:add_wear(65535 / 20) |
0f6bdb
|
173 |
player_inv:add_item("main", stack_pickup) |
21c96a
|
174 |
return itemstack |
M |
175 |
end, |
3b32bf
|
176 |
}) |