yl_api_nodestages/internal.lua
2024-07-02 15:03:49 +02:00

136 lines
4.1 KiB
Lua

-- The functions and variables in this file are only for use in the mod itself.
-- Those that do real work should be local and wrapped in public functions
local function log(text)
local logmessage = yl_api_food.t("log_prefix", yl_api_food.modname, text)
if yl_api_food.settings.debug then minetest.log("action", logmessage) end
return logmessage
end
function yl_api_food.log(text) return log(text) end
local function remove_timer(pos)
local t = minetest.get_node_timer(pos)
t:stop()
end
function yl_api_food.remove_timer(pos) return remove_timer(pos) end
function yl_api_food.on_destruct(pos) return remove_timer(pos) end
local function on_construct(pos)
local node = minetest.get_node(pos)
local nodename = node.name
local stage = minetest.registered_nodes[nodename]._stage
local duration = stage.duration or 0
local node_definition = minetest.registered_nodes[nodename]
-- node functions
if ((minetest.registered_nodes[nodename] == nil) or
-- Only add a nodetimer if the node does not yet have one
(minetest.registered_nodes[nodename].on_timer)) then
node_definition.on_timer = function(tpos, elapsed)
yl_api_food.on_timer(tpos, elapsed, stage.duration)
end
end
if (duration > 0) then
local current_duration = duration
local t = minetest.get_node_timer(pos)
t:start(current_duration)
end
end
function yl_api_food.on_construct(pos) return on_construct(pos) end
local function get_next_stage(next_stages)
local sum = 0
for _, stage_chance in pairs(next_stages) do sum = sum + stage_chance[2] end
local dice = math.random(sum)
for _, stage_chance in pairs(next_stages) do
dice = dice - stage_chance[2]
if dice <= 0 then return stage_chance[1] end
end
-- should never return this
return yl_api_food.error
end
local function on_timer(pos, elapsed)
local node = minetest.get_node(pos)
local stage = minetest.registered_nodes[node.name]._stage
local target_nodename
local timer = 0
local duration
if (stage == nil) or (stage.next_stages == nil) then
minetest.get_node_timer(pos):stop()
return
end
repeat
duration = stage.duration
timer = timer + duration
target_nodename = get_next_stage(stage.next_stages)
-- Last stage most often does not have a _stage
stage = minetest.registered_nodes[target_nodename] and
minetest.registered_nodes[target_nodename]._stage or nil
until ((timer >= elapsed) or (stage == nil) or (stage.duration == 0))
if ((target_nodename == nil) or
(minetest.registered_nodes[target_nodename] == nil)) then return end
minetest.set_node(pos, {name = target_nodename})
local remaining = timer - elapsed
if (stage and stage.duration and (remaining > 0)) then
local nodetimer = minetest.get_node_timer(pos)
nodetimer:set(stage.duration, remaining)
end
end
function yl_api_food.on_timer(pos, elapsed) return on_timer(pos, elapsed) end
function yl_api_food.is_valid(stages)
-- TODO: Implement stages validation once we know how stages look like
return true
end
-- Preparation for random duration
function calc_duration(duration)
assert(duration ~= nil, "TODO: ERROR")
local d_min, d_max
-- table
if type(duration) == "table" then
assert(((#duration >= 1) and (#duration <= 2)), "TODO: ERROR")
if #duration == 1 then
d_min = duration[1]
d_max = duration[1]
else
d_min = math.min(duration[1], duration[2])
d_max = math.max(duration[1], duration[2])
end
elseif type(duration) == "number" then
d_min = duration
d_max = duration
elseif type(duration) == "string" then
d_min = tonumber(duration)
d_max = tonumber(duration)
else
return yl_api_food.error
end
assert((d_min >= 0) and (d_max >= 0) and ((d_max >= d_min)), "TODO: ERROR")
return {min = d_min, max = d_max}
end
function yl_api_food.calc_duration(duration) return calc_duration(duration) end