Skip to content

Commit a08ba2b

Browse files
authored
Get rid of deprecated metadata (#628)
The deprecated metadata gets converted to a proper ItemStackMetaRef. All keys stay the same except for: - Cans that use `can_level` now, since they didn't store a serialized table in the metadata before. - `charge` which is now `technic:charge`, since any item (also from other mods) may have a technic charge which can cause compatibility problems. Backwards compatibility is kept but going back to older `technic` versions might result in misbehaving circuits.
1 parent 410e341 commit a08ba2b

11 files changed

+136
-98
lines changed

technic/helpers.lua

+14-3
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,26 @@ function technic.swap_node(pos, name)
6565
end
6666

6767

68+
--- Returns the meta of an item
69+
-- Gets overridden when legacy.lua is loaded
70+
function technic.get_stack_meta(itemstack)
71+
return itemstack:get_meta()
72+
end
73+
74+
--- Same as technic.get_stack_meta for cans
75+
function technic.get_stack_meta_cans(itemstack)
76+
return itemstack:get_meta()
77+
end
78+
79+
6880
--- Fully charge RE chargeable item.
6981
-- Must be defined early to reference in item definitions.
7082
function technic.refill_RE_charge(stack)
7183
local max_charge = technic.power_tools[stack:get_name()]
7284
if not max_charge then return stack end
85+
local meta = technic.get_stack_meta(stack)
86+
meta:set_int("technic:charge", max_charge)
7387
technic.set_RE_wear(stack, max_charge, max_charge)
74-
local meta = minetest.deserialize(stack:get_metadata()) or {}
75-
meta.charge = max_charge
76-
stack:set_metadata(minetest.serialize(meta))
7788
return stack
7889
end
7990

technic/legacy.lua

+37
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,40 @@ for i = 0, 64 do
3939
minetest.register_alias("technic:lv_cable"..i, "technic:lv_cable")
4040
end
4141

42+
-- Item meta
43+
44+
-- Meta keys that have changed
45+
technic.legacy_meta_keys = {
46+
["charge"] = "technic:charge",
47+
}
48+
49+
-- Converts legacy itemstack metadata string to itemstack meta and returns the ItemStackMetaRef
50+
function technic.get_stack_meta(itemstack)
51+
local meta = itemstack:get_meta()
52+
local legacy_string = meta:get("") -- Get deprecated metadata
53+
if legacy_string then
54+
local legacy_table = minetest.deserialize(legacy_string)
55+
if legacy_table then
56+
local table = meta:to_table()
57+
for k, v in pairs(legacy_table) do
58+
table.fields[technic.legacy_meta_keys[k] or k] = v
59+
end
60+
meta:from_table(table)
61+
end
62+
meta:set_string("", "") -- Remove deprecated metadata
63+
end
64+
return meta
65+
end
66+
67+
-- Same as technic.get_stack_meta for cans.
68+
-- (Cans didn't store a serialized table in the legacy metadata string, but just a number.)
69+
function technic.get_stack_meta_cans(itemstack)
70+
local meta = itemstack:get_meta()
71+
local legacy_string = meta:get("") -- Get deprecated metadata
72+
if legacy_string then
73+
meta:set_string("can_level", legacy_string)
74+
meta:set_string("", "") -- Remove deprecated metadata
75+
return meta
76+
end
77+
return meta
78+
end

technic/machines/register/battery_box.lua

+4-9
Original file line numberDiff line numberDiff line change
@@ -415,22 +415,17 @@ local function default_get_charge(itemstack)
415415
if not technic.power_tools[tool_name] then
416416
return 0, 0
417417
end
418-
-- Set meta data for the tool if it didn't do it itself
419-
local item_meta = minetest.deserialize(itemstack:get_metadata()) or {}
420-
if not item_meta.charge then
421-
item_meta.charge = 0
422-
end
423-
return item_meta.charge, technic.power_tools[tool_name]
418+
local item_meta = technic.get_stack_meta(itemstack)
419+
return item_meta:get_int("technic:charge"), technic.power_tools[tool_name]
424420
end
425421

426422
local function default_set_charge(itemstack, charge)
427423
local tool_name = itemstack:get_name()
428424
if technic.power_tools[tool_name] then
429425
technic.set_RE_wear(itemstack, charge, technic.power_tools[tool_name])
430426
end
431-
local item_meta = minetest.deserialize(itemstack:get_metadata()) or {}
432-
item_meta.charge = charge
433-
itemstack:set_metadata(minetest.serialize(item_meta))
427+
local item_meta = technic.get_stack_meta(itemstack)
428+
item_meta:set_int("technic:charge", charge)
434429
end
435430

436431
function technic.charge_tools(meta, batt_charge, charge_step)

technic/tools/cans.lua

+8-13
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,6 @@ local function set_can_wear(itemstack, level, max_level)
1212
itemstack:set_wear(temp)
1313
end
1414

15-
local function get_can_level(itemstack)
16-
if itemstack:get_metadata() == "" then
17-
return 0
18-
else
19-
return tonumber(itemstack:get_metadata())
20-
end
21-
end
22-
2315
function technic.register_can(d)
2416
local data = {}
2517
for k, v in pairs(d) do data[k] = v end
@@ -33,7 +25,8 @@ function technic.register_can(d)
3325
if pointed_thing.type ~= "node" then return end
3426
local node = minetest.get_node(pointed_thing.under)
3527
if node.name ~= data.liquid_source_name then return end
36-
local charge = get_can_level(itemstack)
28+
local meta = technic.get_stack_meta_cans(itemstack)
29+
local charge = meta:get_int("can_level")
3730
if charge == data.can_capacity then return end
3831
if minetest.is_protected(pointed_thing.under, user:get_player_name()) then
3932
minetest.log("action", user:get_player_name()..
@@ -44,7 +37,7 @@ function technic.register_can(d)
4437
end
4538
minetest.remove_node(pointed_thing.under)
4639
charge = charge + 1
47-
itemstack:set_metadata(tostring(charge))
40+
meta:set_int("can_level", charge)
4841
set_can_wear(itemstack, charge, data.can_capacity)
4942
return itemstack
5043
end,
@@ -63,7 +56,8 @@ function technic.register_can(d)
6356
-- Try to place node above the pointed source, or abort.
6457
if not def.buildable_to or node_name == data.liquid_source_name then return end
6558
end
66-
local charge = get_can_level(itemstack)
59+
local meta = technic.get_stack_meta_cans(itemstack)
60+
local charge = meta:get_int("can_level")
6761
if charge == 0 then return end
6862
if minetest.is_protected(pos, user:get_player_name()) then
6963
minetest.log("action", user:get_player_name()..
@@ -74,12 +68,13 @@ function technic.register_can(d)
7468
end
7569
minetest.set_node(pos, {name=data.liquid_source_name})
7670
charge = charge - 1
77-
itemstack:set_metadata(tostring(charge))
71+
meta:set_int("can_level", charge)
7872
set_can_wear(itemstack, charge, data.can_capacity)
7973
return itemstack
8074
end,
8175
on_refill = function(stack)
82-
stack:set_metadata(tostring(data.can_capacity))
76+
local meta = technic.get_stack_meta_cans(stack)
77+
meta:set_int("can_level", data.can_capacity)
8378
set_can_wear(stack, data.can_capacity, data.can_capacity)
8479
return stack
8580
end,

technic/tools/chainsaw.lua

+6-8
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,8 @@ minetest.register_tool("technic:chainsaw", {
313313
return itemstack
314314
end
315315

316-
local meta = minetest.deserialize(itemstack:get_metadata())
317-
if not meta or not meta.charge then
318-
return
319-
end
316+
local meta = technic.get_stack_meta(itemstack)
317+
local charge = meta:get_int("technic:charge")
320318

321319
local name = user:get_player_name()
322320
if minetest.is_protected(pointed_thing.under, name) then
@@ -326,14 +324,14 @@ minetest.register_tool("technic:chainsaw", {
326324

327325
-- Send current charge to digging function so that the
328326
-- chainsaw will stop after digging a number of nodes
329-
chainsaw_dig(user, pointed_thing.under, meta.charge)
330-
meta.charge = cutter.charge
327+
chainsaw_dig(user, pointed_thing.under, charge)
328+
charge = cutter.charge
331329

332330
cutter = {} -- Free RAM
333331

334332
if not technic.creative_mode then
335-
technic.set_RE_wear(itemstack, meta.charge, chainsaw_max_charge)
336-
itemstack:set_metadata(minetest.serialize(meta))
333+
meta:set_int("technic:charge", charge)
334+
technic.set_RE_wear(itemstack, charge, chainsaw_max_charge)
337335
end
338336
return itemstack
339337
end,

technic/tools/flashlight.lua

+6-5
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,13 @@ local function check_for_flashlight(player)
3838
local hotbar = inv:get_list("main")
3939
for i = 1, 8 do
4040
if hotbar[i]:get_name() == "technic:flashlight" then
41-
local meta = minetest.deserialize(hotbar[i]:get_metadata())
42-
if meta and meta.charge and meta.charge >= 2 then
41+
local meta = technic.get_stack_meta(hotbar[i])
42+
local charge = meta:get_int("technic:charge")
43+
if charge >= 2 then
4344
if not technic.creative_mode then
44-
meta.charge = meta.charge - 2;
45-
technic.set_RE_wear(hotbar[i], meta.charge, flashlight_max_charge)
46-
hotbar[i]:set_metadata(minetest.serialize(meta))
45+
charge = charge - 2;
46+
meta:set_int("technic:charge", charge)
47+
technic.set_RE_wear(hotbar[i], charge, flashlight_max_charge)
4748
inv:set_stack("main", i, hotbar[i])
4849
end
4950
return true

technic/tools/mining_drill.lua

+15-16
Original file line numberDiff line numberDiff line change
@@ -248,54 +248,53 @@ end
248248

249249
local function mining_drill_mkX_setmode(user, itemstack, drill_type, max_modes)
250250
local player_name = user:get_player_name()
251-
local meta = minetest.deserialize(itemstack:get_metadata()) or {}
251+
local meta = technic.get_stack_meta(itemstack)
252252

253-
if not meta["mode"] then
253+
if not meta:contains("mode") then
254254
minetest.chat_send_player(player_name,
255255
S("Use while sneaking to change Mining Drill Mk%d modes."):format(drill_type))
256256
end
257-
local mode = (meta["mode"] or 0) + 1
257+
local mode = meta:get_int("mode") + 1
258258
if mode > max_modes then mode = 1 end
259259

260260
minetest.chat_send_player(player_name,
261261
S("Mining Drill Mk%d Mode %d"):format(2, mode)..
262262
": "..mining_drill_mode_text[mode][1])
263263
itemstack:set_name(("technic:mining_drill_mk%d_%s"):format(drill_type, mode))
264-
meta["mode"] = mode
265-
itemstack:set_metadata(minetest.serialize(meta))
264+
meta:set_int("mode", mode)
266265
return itemstack
267266
end
268267

269268
local function mining_drill_mkX_handler(itemstack, user, pointed_thing, drill_type, max_modes)
270269
local keys = user:get_player_control()
271-
local meta = minetest.deserialize(itemstack:get_metadata()) or {}
270+
local meta = technic.get_stack_meta(itemstack)
272271

273272
-- Mode switching (if possible)
274273
if max_modes > 1 then
275-
if not meta.mode or keys.sneak then
274+
if not meta:contains("mode") or keys.sneak then
276275
return mining_drill_mkX_setmode(user, itemstack, drill_type, max_modes)
277276
end
278277
end
279278
if pointed_thing.type ~= "node" or not pos_is_pointable(pointed_thing.under) then
280279
return
281280
end
282-
if not meta.charge then
283-
return
284-
end
281+
282+
local charge = meta:get_int("technic:charge")
283+
local mode = meta:contains("mode") and meta:get_int("mode") or 1
285284

286285
-- Check whether the tool has enough charge
287-
local charge_to_take = cost_to_use(drill_type, meta.mode or 1)
288-
if meta.charge < charge_to_take then
286+
local charge_to_take = cost_to_use(drill_type, mode)
287+
if charge < charge_to_take then
289288
return
290289
end
291290

292291
-- Do the actual shoorting action
293292
local pos = minetest.get_pointed_thing_position(pointed_thing, false)
294-
drill_dig_it(pos, user, meta.mode or 1)
293+
drill_dig_it(pos, user, mode)
295294
if not technic.creative_mode then
296-
meta.charge = meta.charge - charge_to_take
297-
itemstack:set_metadata(minetest.serialize(meta))
298-
technic.set_RE_wear(itemstack, meta.charge, max_charge[drill_type])
295+
charge = charge - charge_to_take
296+
meta:set_int("technic:charge", charge)
297+
technic.set_RE_wear(itemstack, charge, max_charge[drill_type])
299298
end
300299
return itemstack
301300
end

technic/tools/mining_lasers.lua

+8-7
Original file line numberDiff line numberDiff line change
@@ -101,25 +101,26 @@ for _, m in pairs(mining_lasers_list) do
101101
wear_represents = "technic_RE_charge",
102102
on_refill = technic.refill_RE_charge,
103103
on_use = function(itemstack, user)
104-
local meta = minetest.deserialize(itemstack:get_metadata())
105-
if not meta or not meta.charge or meta.charge == 0 then
104+
local meta = technic.get_stack_meta(itemstack)
105+
local charge = meta:get_int("technic:charge")
106+
if charge == 0 then
106107
return
107108
end
108109

109110
local range = m[2]
110-
if meta.charge < m[4] then
111+
if charge < m[4] then
111112
if not allow_entire_discharging then
112113
return
113114
end
114115
-- If charge is too low, give the laser a shorter range
115-
range = range * meta.charge / m[4]
116+
range = range * charge / m[4]
116117
end
117118
laser_shoot(user, range, "technic_laser_beam_mk" .. m[1] .. ".png",
118119
"technic_laser_mk" .. m[1])
119120
if not technic.creative_mode then
120-
meta.charge = math.max(meta.charge - m[4], 0)
121-
technic.set_RE_wear(itemstack, meta.charge, m[3])
122-
itemstack:set_metadata(minetest.serialize(meta))
121+
charge = math.max(charge - m[4], 0)
122+
meta:set_int("technic:charge", charge)
123+
technic.set_RE_wear(itemstack, charge, m[3])
123124
end
124125
return itemstack
125126
end,

technic/tools/prospector.lua

+21-20
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ local S = technic.getter
22

33
technic.register_power_tool("technic:prospector", 300000)
44

5-
local function get_metadata(toolstack)
6-
local m = minetest.deserialize(toolstack:get_metadata())
7-
if not m then m = {} end
8-
if not m.charge then m.charge = 0 end
9-
if not m.target then m.target = "" end
10-
if not m.look_depth then m.look_depth = 7 end
11-
if not m.look_radius then m.look_radius = 1 end
12-
return m
5+
-- Helper function to consolidate ItemStackMetaRef access and initialize
6+
local function meta_to_table(meta)
7+
local t = {}
8+
local mt = meta:to_table()
9+
10+
t.charge = tonumber(mt.fields["technic:charge"]) or 0
11+
t.target = mt.fields.target or ""
12+
t.look_depth = tonumber(mt.fields.look_depth) or 7
13+
t.look_radius = tonumber(mt.fields.look_radius) or 1
14+
return t
1315
end
1416

1517
minetest.register_tool("technic:prospector", {
@@ -20,7 +22,8 @@ minetest.register_tool("technic:prospector", {
2022
on_use = function(toolstack, user, pointed_thing)
2123
if not user or not user:is_player() or user.is_fake_player then return end
2224
if pointed_thing.type ~= "node" then return end
23-
local toolmeta = get_metadata(toolstack)
25+
local meta = technic.get_stack_meta(toolstack)
26+
local toolmeta = meta_to_table(meta)
2427
local look_diameter = toolmeta.look_radius * 2 + 1
2528
local charge_to_take = toolmeta.look_depth * (toolmeta.look_depth + 1) * look_diameter * look_diameter
2629
if toolmeta.charge < charge_to_take then return end
@@ -30,7 +33,7 @@ minetest.register_tool("technic:prospector", {
3033
end
3134
if not technic.creative_mode then
3235
toolmeta.charge = toolmeta.charge - charge_to_take
33-
toolstack:set_metadata(minetest.serialize(toolmeta))
36+
meta:set_int("technic:charge", toolmeta.charge)
3437
technic.set_RE_wear(toolstack, toolmeta.charge, technic.power_tools[toolstack:get_name()])
3538
end
3639
-- What in the heaven's name is this evil sorcery ?
@@ -77,7 +80,8 @@ minetest.register_tool("technic:prospector", {
7780
end,
7881
on_place = function(toolstack, user, pointed_thing)
7982
if not user or not user:is_player() or user.is_fake_player then return end
80-
local toolmeta = get_metadata(toolstack)
83+
local meta = technic.get_stack_meta(toolstack)
84+
local toolmeta = meta_to_table(meta)
8185
local pointed
8286
if pointed_thing.type == "node" then
8387
local pname = minetest.get_node(pointed_thing.under).name
@@ -125,19 +129,16 @@ minetest.register_on_player_receive_fields(function(user, formname, fields)
125129
if not user or not user:is_player() or user.is_fake_player then return end
126130
local toolstack = user:get_wielded_item()
127131
if toolstack:get_name() ~= "technic:prospector" then return true end
128-
local toolmeta = get_metadata(toolstack)
132+
local meta = technic.get_stack_meta(toolstack)
129133
for field, value in pairs(fields) do
130134
if field:sub(1, 7) == "target_" then
131-
toolmeta.target = field:sub(8)
132-
end
133-
if field:sub(1, 12) == "look_radius_" then
134-
toolmeta.look_radius = field:sub(13)
135-
end
136-
if field:sub(1, 11) == "look_depth_" then
137-
toolmeta.look_depth = field:sub(12)
135+
meta:set_string("target", field:sub(8))
136+
elseif field:sub(1, 12) == "look_radius_" then
137+
meta:set_string("look_radius", field:sub(13))
138+
elseif field:sub(1, 11) == "look_depth_" then
139+
meta:set_string("look_depth", field:sub(12))
138140
end
139141
end
140-
toolstack:set_metadata(minetest.serialize(toolmeta))
141142
user:set_wielded_item(toolstack)
142143
return true
143144
end)

0 commit comments

Comments
 (0)