Skip to content

Commit 166da3e

Browse files
authored
Wrench rewrite (#247)
1 parent b283cc6 commit 166da3e

12 files changed

+416
-265
lines changed

wrench/api.lua

Lines changed: 0 additions & 38 deletions
This file was deleted.

wrench/functions.lua

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
2+
local S = rawget(_G, "intllib") and intllib.Getter() or function(s) return s end
3+
4+
local SERIALIZATION_VERSION = 1
5+
6+
local errors = {
7+
owned = S("Cannot pickup node. Owned by %s."),
8+
full_inv = S("Not enough room in inventory to pickup node."),
9+
bad_item = S("Cannot pickup node containing %s."),
10+
nested = S("Cannot pickup node. Nesting inventories is not allowed."),
11+
metadata = S("Cannot pickup node. Node contains too much metadata."),
12+
}
13+
14+
local function get_stored_metadata(itemstack)
15+
local meta = itemstack:get_meta()
16+
local data = meta:get("data") or meta:get("")
17+
data = minetest.deserialize(data)
18+
if not data or not data.version or not data.name then
19+
return
20+
end
21+
return data
22+
end
23+
24+
local function get_description(def, pos, meta, node, player)
25+
local t = type(def.description)
26+
if t == "string" then
27+
return def.description
28+
elseif t == "function" then
29+
local desc = def.description(pos, meta, node, player)
30+
if desc then
31+
return desc
32+
end
33+
end
34+
return S("%s with items"):format(minetest.registered_nodes[node.name].description)
35+
end
36+
37+
function wrench.pickup_node(pos, player)
38+
local node = minetest.get_node(pos)
39+
local def = wrench.registered_nodes[node.name]
40+
if not def then
41+
return
42+
end
43+
local meta = minetest.get_meta(pos)
44+
if def.owned and not minetest.check_player_privs(player, "protection_bypass") then
45+
local owner = meta:get_string("owner")
46+
if owner ~= "" and owner ~= player:get_player_name() then
47+
return false, errors.owned:format(owner)
48+
end
49+
end
50+
local data = {
51+
name = node.name,
52+
version = SERIALIZATION_VERSION,
53+
lists = {},
54+
metas = {},
55+
}
56+
local inv = meta:get_inventory()
57+
for _, listname in pairs(def.lists or {}) do
58+
local list = inv:get_list(listname)
59+
for i, stack in pairs(list) do
60+
if wrench.blacklisted_items[stack:get_name()] then
61+
local desc = stack:get_definition().description
62+
return false, errors.bad_item:format(desc)
63+
end
64+
local sdata = get_stored_metadata(stack)
65+
if sdata and sdata.lists and next(sdata.lists) ~= nil then
66+
return false, errors.nested
67+
end
68+
list[i] = stack:to_string()
69+
end
70+
data.lists[listname] = list
71+
end
72+
for name, meta_type in pairs(def.metas or {}) do
73+
if meta_type == wrench.META_TYPE_FLOAT then
74+
data.metas[name] = meta:get_float(name)
75+
elseif meta_type == wrench.META_TYPE_STRING then
76+
data.metas[name] = meta:get_string(name)
77+
elseif meta_type == wrench.META_TYPE_INT then
78+
data.metas[name] = meta:get_int(name)
79+
end
80+
end
81+
local stack = ItemStack(node.name)
82+
local item_meta = stack:get_meta()
83+
item_meta:set_string("data", minetest.serialize(data))
84+
item_meta:set_string("description", get_description(def, pos, meta, node, player))
85+
if #stack:to_string() > 65000 then
86+
return false, errors.metadata
87+
end
88+
local player_inv = player:get_inventory()
89+
if not player_inv:room_for_item("main", stack) then
90+
return false, errors.full_inv
91+
end
92+
player_inv:add_item("main", stack)
93+
minetest.remove_node(pos)
94+
return true
95+
end
96+
97+
function wrench.restore_node(pos, player, stack)
98+
if not stack then
99+
return
100+
end
101+
local data = get_stored_metadata(stack)
102+
if not data then
103+
return
104+
end
105+
local def = wrench.registered_nodes[data.name]
106+
if not def then
107+
return
108+
end
109+
local meta = minetest.get_meta(pos)
110+
local inv = meta:get_inventory()
111+
for listname, list in pairs(data.lists) do
112+
inv:set_list(listname, list)
113+
end
114+
for name, value in pairs(data.metas) do
115+
local meta_type = def.metas and def.metas[name]
116+
if meta_type == wrench.META_TYPE_INT then
117+
meta:set_int(name, value)
118+
elseif meta_type == wrench.META_TYPE_FLOAT then
119+
meta:set_float(name, value)
120+
elseif meta_type == wrench.META_TYPE_STRING then
121+
meta:set_string(name, value)
122+
end
123+
end
124+
if def.after_place then
125+
def.after_place(pos, player, stack)
126+
end
127+
return true
128+
end

0 commit comments

Comments
 (0)