diff --git a/internal_nodefunctions.lua b/internal_nodefunctions.lua new file mode 100644 index 0000000..a9ee95b --- /dev/null +++ b/internal_nodefunctions.lua @@ -0,0 +1,102 @@ +local function remove_timer(pos) + local t = minetest.get_node_timer(pos) + t:stop() +end + +function yl_api_nodestages.remove_timer(pos) return remove_timer(pos) end + +function yl_api_nodestages.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 + + if (duration > 0) then + local current_duration = duration + local t = minetest.get_node_timer(pos) + t:start(current_duration) + end +end + +function yl_api_nodestages.on_construct(pos) return on_construct(pos) end + +local function get_target_nodename(node, pos, 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 + if (minetest.registered_nodes[stage_chance[1]] == nil) then + minetest.log("warning", + yl_api_nodestages.t( + "target_nodestage_does_not_exist", + dump(stage_chance[1]), dump(node.name), + dump(pos))) + return nil + elseif ((stage_chance[3] ~= nil) and + (type(stage_chance[3].can_set) == "function") and + (stage_chance[3].can_set(pos) == false)) then + return node.name + else + return stage_chance[1] + end + end + end + + -- should never return this + return yl_api_nodestages.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) or (stage.duration == nil)) then + yl_api_nodestages.remove_timer(pos) + return + end + + repeat + duration = stage.duration + timer = timer + duration + target_nodename = get_target_nodename(node, pos, stage.next_stages) + + if (target_nodename == yl_api_nodestages.error) then + -- Thing kaputt, stop it. + minetest.log("error", yl_api_nodestages.t("undefined_state_abort")) + yl_api_nodestages.remove_timer(pos) + return + end + + if (target_nodename == nil) then + -- Fallback to last known target_nodename + target_nodename = stage.stage_name + break + else + -- Last stage most often does not have a _stage + stage = minetest.registered_nodes[target_nodename] and + minetest.registered_nodes[target_nodename]._stage or nil + end + until ((timer >= elapsed) or (stage == nil) or (stage.duration == 0) or (stage.duration == nil)) + + if (node.name == target_nodename) then + return true 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_nodestages.on_timer(pos, elapsed) return on_timer(pos, elapsed) end diff --git a/internal_validation.lua b/internal_validation.lua new file mode 100644 index 0000000..df61266 --- /dev/null +++ b/internal_validation.lua @@ -0,0 +1,74 @@ +-- Validation +-- + +function get_valid_copy_of_stage(stage) + if (type(stage) ~= "table") then return false, t("stage_not_table") end + + local stage = table.copy(stage) + + if (yl_api_nodestages.is_valid_stage(stage) == false) then + return false, t("stage_not_valid") + end + + return true, stage + +end + +function yl_api_nodestages.get_valid_copy_of_stage(stage) + return get_valid_copy_of_stage(stage) +end + +local function is_valid_stage(stage) + + if (stage == nil) then return false, t("node_does_not_have_stage") end + + if (type(stage) ~= "table") then return false, t("stage_not_table") end + + + + return true -- TODO: Implement validation +end + +function yl_api_nodestages.is_valid_stage(stage) + return is_valid_stage(stage) +end + +function yl_api_nodestages.is_valid(stages) + + local good, bad, total = 0, 0, 0 + local reasons = {} + + for _, stage in ipairs(stages) do + total = total + 1 + local success, message = is_valid_stage(stage) + if (success == true) then + good = good + 1 + else + bad = bad + 1 + table.insert(reasons, message) + end + end + + if (bad == 0) then + minetest.log("action", + "[MOD] yl_api_nodestages : bad = " .. tostring(bad) .. + ", good = " .. tostring(good) .. ", total = " .. + tostring(total)) + return true, good, bad, total, reasons + else + minetest.log("warning", + "[MOD] yl_api_nodestages : bad = " .. tostring(bad) .. + ", good = " .. tostring(good) .. ", total = " .. + tostring(total)) + return false, good, bad, total, reasons + end +end + +function yl_api_nodestages.validate_all_stages() + local stages = {} + for _, def in pairs(minetest.registered_nodes) do + local stage = def._stage + table.insert(stages, stage) + end + return yl_api_nodestages.is_valid(stages) +end