Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup deprecated metadata access for tools #233

Merged
merged 4 commits into from
Jun 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 35 additions & 15 deletions technic/helpers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,11 @@ assert(technic.pretty_num(0) == "0 ")
assert(technic.pretty_num(1234) == "1234 ")
assert(technic.pretty_num(123456789) == "123.5 M")


-- used to display power values
function technic.EU_string(num)
return technic.pretty_num(num) .. "EU"
end


--- Same as minetest.swap_node, but only changes name
-- and doesn't re-set if already set.
function technic.swap_node(pos, name)
Expand All @@ -64,19 +62,44 @@ function technic.swap_node(pos, name)
end
end

function technic.set_RE_charge(stack, charge)
local wear_factor = stack:get_definition().technic_wear_factor
if wear_factor then
local wear = math.floor(charge * wear_factor + 0.5)
stack:set_wear(wear > 0 and 65536 - wear or 0)
else
minetest.log("error", "technic.set_RE_charge item not registered as power tool: "..stack:get_name())
end
end

--- Fully charge RE chargeable item.
-- Must be defined early to reference in item definitions.
function technic.refill_RE_charge(stack)
local max_charge = technic.power_tools[stack:get_name()]
if not max_charge then return stack end
technic.set_RE_wear(stack, max_charge, max_charge)
local meta = minetest.deserialize(stack:get_metadata()) or {}
meta.charge = max_charge
stack:set_metadata(minetest.serialize(meta))
return stack
function technic.get_RE_charge(stack)
local wear_factor = stack:get_definition().technic_wear_factor
if wear_factor then
local wear = stack:get_wear()
return math.floor((wear > 0 and 65536 - wear or 0) / wear_factor + 0.5)
end
minetest.log("warning", "technic.get_RE_charge item not registered as power tool: "..stack:get_name())
return 0
end

function technic.use_RE_charge(stack, amount)
if technic.creative_mode or amount <= 0 then
-- Do not check charge in creative mode or when trying to use zero amount
return true
end
local charge = technic.get_RE_charge(stack)
if charge < amount then
-- Not enough energy available
return false
end
-- Ensure that at least single point is always added to wear when using tool
local wear_factor = stack:get_definition().technic_wear_factor
local wear = stack:get_wear()
wear = math.max(math.floor(wear + 1.5), math.floor(amount * wear_factor + wear + 0.5))
stack:set_wear(wear > 65535 and 0 or wear)
-- Charge used successfully
return true
end

-- If the node is loaded, returns it. If it isn't loaded, load it and return nil.
function technic.get_or_load_node(pos)
Expand All @@ -87,15 +110,13 @@ function technic.get_or_load_node(pos)
return nil
end


technic.tube_inject_item = pipeworks.tube_inject_item or function(pos, start_pos, velocity, item)
local tubed = pipeworks.tube_item(vector.new(pos), item)
tubed:get_luaentity().start_pos = vector.new(start_pos)
tubed:set_velocity(velocity)
tubed:set_acceleration(vector.new(0, 0, 0))
end


--- Iterates over the node positions along the specified ray.
-- The returned positions will not include the starting position.
function technic.trace_node_ray(pos, dir, range)
Expand Down Expand Up @@ -143,7 +164,6 @@ function technic.trace_node_ray(pos, dir, range)
end, vector.round(pos)
end


--- Like trace_node_ray, but includes extra positions close to the ray.
function technic.trace_node_ray_fat(pos, dir, range)
local x_step = dir.x > 0 and 1 or -1
Expand Down
10 changes: 7 additions & 3 deletions technic/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
local load_start = os.clock()

technic = rawget(_G, "technic") or {}
technic.plus = true
S-S-X marked this conversation as resolved.
Show resolved Hide resolved
technic.creative_mode = minetest.settings:get_bool("creative_mode")

local modpath = minetest.get_modpath("technic")
Expand All @@ -23,15 +24,18 @@ dofile(modpath.."/max_lag.lua")
-- Helper functions
dofile(modpath.."/helpers.lua")

-- Register functions
dofile(modpath.."/register.lua")

-- Compatibility shims for tools
dofile(modpath.."/machines/compat/tools.lua")
S-S-X marked this conversation as resolved.
Show resolved Hide resolved

-- Items
dofile(modpath.."/items.lua")

-- Craft recipes for items
dofile(modpath.."/crafts.lua")

-- Register functions
dofile(modpath.."/register.lua")

-- Radiation
dofile(modpath.."/radiation.lua")

Expand Down
33 changes: 6 additions & 27 deletions technic/items.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,55 +21,34 @@ minetest.register_craftitem( "technic:diamond_drill_head", {
inventory_image = "technic_diamond_drill_head.png",
})

minetest.register_tool("technic:blue_energy_crystal", {
technic.register_power_tool("technic:blue_energy_crystal", {
description = S("Blue Energy Crystal"),
inventory_image = minetest.inventorycube(
"technic_diamond_block_blue.png",
"technic_diamond_block_blue.png",
"technic_diamond_block_blue.png"),
groups = { disable_repair = 1 },
wear_represents = "technic_RE_charge",
on_refill = technic.refill_RE_charge,
tool_capabilities = {
max_drop_level = 0,
groupcaps = {
fleshy = {times={}, uses=10000, maxlevel=0}
}
}
max_charge = 450000,
})

minetest.register_tool("technic:green_energy_crystal", {
technic.register_power_tool("technic:green_energy_crystal", {
description = S("Green Energy Crystal"),
inventory_image = minetest.inventorycube(
"technic_diamond_block_green.png",
"technic_diamond_block_green.png",
"technic_diamond_block_green.png"),
groups = { disable_repair = 1 },
wear_represents = "technic_RE_charge",
on_refill = technic.refill_RE_charge,
tool_capabilities = {
max_drop_level = 0,
groupcaps = {
fleshy = {times={}, uses=10000, maxlevel=0}
}
}
max_charge = 150000,
})

minetest.register_tool("technic:red_energy_crystal", {
technic.register_power_tool("technic:red_energy_crystal", {
description = S("Red Energy Crystal"),
inventory_image = minetest.inventorycube(
"technic_diamond_block_red.png",
"technic_diamond_block_red.png",
"technic_diamond_block_red.png"),
groups = { disable_repair = 1 },
wear_represents = "technic_RE_charge",
on_refill = technic.refill_RE_charge,
tool_capabilities = {
max_drop_level = 0,
groupcaps = {
fleshy = {times={}, uses=10000, maxlevel=0}
}
}
max_charge = 50000,
})

minetest.register_craftitem("technic:copper_coil", {
Expand Down
81 changes: 80 additions & 1 deletion technic/machines/compat/digtron.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,65 @@
--
-- Compatibility hacks for digtron to work well with technic plus new network system
-- Compatibility hacks for digtron to work well with new Technic Plus network and power tools
--
-- More information:
-- https://github.com/mt-mods/technic/issues/100
-- https://github.com/mt-mods/technic/issues/233
--
-- Disable some luacheck warnings to allow having original formatting here
-- luacheck: no max line length
-- luacheck: globals digtron

-- Only relevant sections modified, you can directly compare this with upstream function defined in util.lua
local node_inventory_table = {type="node"}
local function tap_batteries(battery_positions, target, test)
if (battery_positions == nil) then
return 0
end

local current_burned = 0
-- 1 coal block is 370 PU
-- 1 coal lump is 40 PU
-- An RE battery holds 10000 EU of charge
-- local power_ratio = 100 -- How much charge equals 1 unit of PU from coal
-- setting Moved to digtron.config.power_ratio

for k, location in pairs(battery_positions) do
if current_burned > target then
break
end
node_inventory_table.pos = location.pos
local inv = minetest.get_inventory(node_inventory_table)
local invlist = inv:get_list("batteries")

if (invlist == nil) then -- This check shouldn't be needed, it's yet another guard against https://github.com/minetest/minetest/issues/8067
break
end

for i, itemstack in pairs(invlist) do
local charge = technic.get_RE_charge(itemstack)
local power_available = math.floor(charge / digtron.config.power_ratio)
if power_available ~= 0 then
local actual_burned = power_available -- we just take all we have from the battery, since they aren't stackable
-- don't bother recording the items if we're just testing, nothing is actually being removed.
if test ~= true then
-- since we are taking everything, the wear and charge can both be set to 0
technic.set_RE_charge(itemstack, 0)
end
current_burned = current_burned + actual_burned
end

if current_burned > target then
break
end
end

if test ~= true then
-- only update the list if we're doing this for real.
inv:set_list("batteries", invlist)
end
end
return current_burned
end

local function power_connector_compat()
local digtron_technic_run = minetest.registered_nodes["digtron:power_connector"].technic_run
Expand All @@ -23,8 +79,31 @@ local function power_connector_compat()
})
end

local function battery_holder_compat()
-- Override battery holder
local tube = minetest.registered_nodes["digtron:battery_holder"].tube
tube.can_insert = function(pos, node, stack, direction)
if technic.get_RE_charge(stack) > 0 then
local inv = minetest.get_meta(pos):get_inventory()
return inv:room_for_item("batteries", stack)
end
return false
end
minetest.override_item("digtron:battery_holder",{
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
return (listname == "batteries" and technic.get_RE_charge(stack) > 0) and stack:get_count() or 0
end,
tube = tube,
})
-- Override digtron.tap_batteries
digtron.tap_batteries = tap_batteries
end

minetest.register_on_mods_loaded(function()
if minetest.registered_nodes["digtron:power_connector"] then
power_connector_compat()
end
if minetest.registered_nodes["digtron:battery_holder"] then
battery_holder_compat()
end
end)
40 changes: 40 additions & 0 deletions technic/machines/compat/tools.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

-- This wont give full compatibility but allows using old style technic.register_power_tool tool registration function.
-- Tools still have to read charge value using technic.get_RE_charge, allows easier compatibility with official Technic
-- mod for some tools: a lot less changes required for compatibility but tool will keep some unnecessary meatadata.
--
-- To make tool fully compatible replace minetest.register_tool with technic.register_power_tool and add `max_charge`
-- field for tool definition. Fields `wear_represents` and `on_refill` can also be removed if using defaults.
--
local register_power_tool = technic.register_power_tool
function technic.register_power_tool(itemname, itemdef)
if type(itemdef) == "number" then
minetest.log("warning", "Deprecated technic.register_power_tool use. Setting max_charge for "..itemname)
technic.power_tools[itemname] = itemdef
minetest.register_on_mods_loaded(function()
minetest.log("warning", "Deprecated technic.register_power_tool use. Ensuring fields for "..itemname)
local redef = minetest.registered_items[itemname]
if redef and redef.wear_represents == "technic_RE_charge" and not redef.on_refill then
-- Override power tools that called register_power_tool but do not have on_refill function defined
local max_charge = itemdef
minetest.override_item(itemname, {
on_refill = function(stack)
technic.set_RE_charge(stack, max_charge)
return stack
end,
technic_max_charge = max_charge,
technic_wear_factor = 65535 / max_charge,
})
minetest.log("warning", "Updated on_refill and max_charge for "..itemname)
end
end)
else
return register_power_tool(itemname, itemdef)
end
end

-- Alias set set_RE_wear, many tools calls this to set wear value which is also handled by set_RE_charge
function technic.set_RE_wear(stack, charge)
minetest.log("warning", "Use of deprecated function technic.set_RE_wear with stack: "..stack:get_name())
technic.set_RE_charge(stack, charge)
end
Loading