From b91995eaf1962ba5202324943ff1a2de841b8ae6 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Thu, 4 Jan 2024 10:36:09 -0800 Subject: [PATCH] Fix _active machine handling. Manage time better by resource reservations. Autocrafting status is one per network, not one per server. Lengthing craft time of 81 doped wafers. --- modules/network/autocraft.lua | 67 +++++++++++++++++++---------- modules/storage/cmonitor.lua | 4 +- modules/storage/cterminal.lua | 6 +++ modules/storage/technic-interop.lua | 19 ++++++++ 4 files changed, 72 insertions(+), 24 deletions(-) diff --git a/modules/network/autocraft.lua b/modules/network/autocraft.lua index 0674a5b..bb9d4bc 100644 --- a/modules/network/autocraft.lua +++ b/modules/network/autocraft.lua @@ -46,7 +46,30 @@ function me.register_max(name, count) me.maximums[name] = count end +-- This reserves a machine for length seconds. This is used to +-- schedule machines and know when they are done processing a job. +-- The jobs run sequentially. A 10 second job followed by a 5 second +-- job will finish at 15 seconds, not 5 seconds. Return the new start +-- time. todo: this solves the end and the outputs, but not the +-- inputs. They can be overloaded and we might have to delay putting +-- things into the machine. +function me.reserve(net, pos, original_start, length) + if not net.pending then + net.pending = {} + net.pending.time = {} + end + if not net.pending.busy then + net.pending.busy = {} + end + local free_time = net.pending.busy[pos] or 0 + local start = math.max(free_time, original_start) + local ending = start + length + net.pending.busy[pos] = ending + return start +end +-- Testing: HV solar is realiable, big loans are screwy. +-- Building 2 MV batteries manages to miss a single LV battery, odd. local function build(net, cpos, inv, name, count, stack, sink, time) -- The autocrafters nor the machines can take really large amounts -- of things, help them out. @@ -78,6 +101,7 @@ local function build(net, cpos, inv, name, count, stack, sink, time) me.log("BUILD: count is "..count.." and stack size is "..stack:get_count(), "error") local dat = {} local second_output = nil + local main_action_time = count * pipeworks_craft_time + 1 if net.process and net.process[name] then dat.apos, dat.ipos = next(net.process[name]) dat.rinv = minetest.get_meta(dat.apos):get_inventory() @@ -85,6 +109,7 @@ local function build(net, cpos, inv, name, count, stack, sink, time) local inputs = me.find_by_output(name) local machine_name = minetest.get_node(dat.apos).name local typename = me.block_to_typename_map[machine_name] + me.log("Looking up "..(typename or "nil").." recipe for a "..(machine_name or nil), "error") dat.recip = me.get_recipe(typename, inputs) me.log("MACHINE: "..machine_name.." typename is "..typename.." and time is "..tostring(dat.recip.time), "error") dat.recip.input = inputs @@ -100,12 +125,12 @@ local function build(net, cpos, inv, name, count, stack, sink, time) local total = math.ceil(count/craft_count) -- crafting 4 carbon plates misses taking 1 carbin plate on output, make this bigger -- we'll try 1 for now, figure out right formula. 1 looks perfect - dat.recip.time = round((total+1)*dat.recip.time/speed) + main_action_time = round((total+2)*dat.recip.time/speed) + 1 -- 1 + 1 is a second too slow on the doped for 81., 2 +0 doesn't work, a second shy if second_output then second_output = ItemStack(second_output) second_output:set_count(second_output:get_count()*total) end - me.log("MACHINE: "..machine_name.." is speed "..speed.." and final time is "..dat.recip.time, "error") + me.log("MACHINE: "..machine_name.." is speed "..speed.." and final time is "..main_action_time, "error") elseif net.autocrafters[name] then -- fill all recipe slots, wait, grab all output slots -- "src" "dst" "recipe" "output" @@ -163,7 +188,9 @@ local function build(net, cpos, inv, name, count, stack, sink, time) end end local replace = true - local next_time = time + local next_time = me.reserve(net, dat.apos, time, main_action_time) + me.log("RESERVE: "..name.." stime "..time.." step "..main_action_time.." reserve "..next_time, "error") + -- local next_time = time me.log("PREP: pre count is "..count, "error") -- prepwork me.log("PREP: count is "..count, "error") @@ -186,7 +213,7 @@ local function build(net, cpos, inv, name, count, stack, sink, time) local grabbed = me.remove_item(net, inv, "main", istack) if grabbed then me.log("ac grabbed "..name, "error") - me.ac_status = me.ac_status .. "Grabbed "..count.." "..name..".\n" + net.ac_status = net.ac_status .. "Grabbed "..count.." "..name..".\n" local slot = inv:get_size("ac")+1 inv:set_size("ac", slot) inv:set_stack("ac", slot, grabbed) @@ -205,15 +232,15 @@ local function build(net, cpos, inv, name, count, stack, sink, time) else -- Try and autocraft it me.log("AC: recursive crafting "..count.." "..istack:get_count(), "error") - me.ac_status = me.ac_status .. "Need to craft "..count.." "..name..".\n" + net.ac_status = net.ac_status .. "Need to craft "..count.." "..name..".\n" local built, step_time = build(net, cpos, inv, name, count, istack, dat.isink, time) if built then hasit = true next_time = math.max(next_time, time + step_time) - me.ac_status = me.ac_status .. "Craft "..count.." "..name.." in "..step_time.." seconds.\n" + net.ac_status = net.ac_status .. "Craft "..count.." "..name.." in "..step_time.." seconds.\n" else me.log("can't craft "..istack:get_count().." "..istack:get_name(), "error") - me.ac_status = me.ac_status .. "Can't craft "..count.." "..name..".\n" + net.ac_status = net.ac_status .. "Can't craft "..count.." "..name..".\n" end end replace = replace and hasit @@ -234,10 +261,6 @@ local function build(net, cpos, inv, name, count, stack, sink, time) -- Existing items are already loaded. return end - local main_action_time = count * pipeworks_craft_time + 1 - if net.process and net.process[name] then - main_action_time = dat.recip.time + 1 - end local main_action = function() me.log("ACTION: prep for "..stack:get_name(), "error") prepwork() @@ -273,10 +296,7 @@ local function build(net, cpos, inv, name, count, stack, sink, time) timer:start(pipeworks_craft_time) end me.log("TIMER: registering timer for "..stack:get_name(), "error") - local action_time_step = count * pipeworks_craft_time + 1 - if net.process and net.process[name] then - action_time_step = dat.recip.time + 1 - end + local action_time_step = main_action_time local action = function(net) me.log("ACTION: post craft for "..stack:get_name(), "error") me.log("TIMER: moving "..stack:get_count().." "..stack:get_name(), "error") @@ -285,14 +305,14 @@ local function build(net, cpos, inv, name, count, stack, sink, time) if dst_stack:get_count() ~= stack:get_count() then me.log("wow, missing items that should have been crafted "..stack:get_name(), "error") -- me.log("saw "..dst_stack:get_count().." items instead of "..stack:get_count().." items", "error") - me.ac_status = me.ac_status .. "Missing "..(stack:get_count()-dst_stack:get_count()).." "..name..", only made "..dst_stack:get_count()..".\n" + net.ac_status = net.ac_status .. "Missing "..(stack:get_count()-dst_stack:get_count()).." "..name..", only made "..dst_stack:get_count()..".\n" end if not dst_stack:is_empty() then me.log("TIMER: inserting "..dst_stack:get_count().." "..dst_stack:get_name(), "error") local leftovers = sink(dst_stack) if leftovers and not leftovers:is_empty() then me.log("autocrafter overflow, backpressuring", "error") - me.ac_status = me.ac_status .. "Backpressure of "..name..".\n" + net.ac_status = net.ac_status .. "Backpressure of "..name..".\n" -- If any don't fit, back pressure on the crafter, we don't -- mean to do this, and want to chunk the crafting items smaller dat.rinv:add_item("dst", leftovers) @@ -309,7 +329,7 @@ local function build(net, cpos, inv, name, count, stack, sink, time) net:set_storage_space(true) if leftovers and not leftovers:is_empty() then me.log("autocrafter overflow, backpressuring", "error") - me.ac_status = me.ac_status .. "Backpressure of "..name..".\n" + net.ac_status = net.ac_status .. "Backpressure of "..name..".\n" -- If any don't fit, back pressure on the crafter, we don't -- mean to do this, and want to chunk the crafting items smaller dat.rinv:add_item("dst", leftovers) @@ -322,7 +342,7 @@ local function build(net, cpos, inv, name, count, stack, sink, time) local leftovers = me.insert_item(second, net, inv, "main") if leftovers and not leftovers:is_empty() then me.log("autocrafter overflow, backpressuring", "error") - me.ac_status = me.ac_status .. "Backpressure of "..name..".\n" + net.ac_status = net.ac_status .. "Backpressure of "..name..".\n" -- If any don't fit, back pressure on the crafter, we don't -- mean to do this, and want to chunk the crafting items smaller dat.rinv:add_item("dst", leftovers) @@ -411,7 +431,10 @@ function me.autocraft(autocrafterCache, cpos, net, linv, inv, count) end if net.autocrafters[name] or net.process[name] then me.log("using pipeworks autocrafter", "error") - me.ac_status = "using pipeworks autocrafter\n" + if not net.pending or not net.ac_status then + net.ac_status = "" + end + net.ac_status = net.ac_status .. "using pipeworks autocrafter\n" local sink = function(stack) local leftovers = me.insert_item(stack, net, inv, "main") net:set_storage_space(true) @@ -421,10 +444,10 @@ function me.autocraft(autocrafterCache, cpos, net, linv, inv, count) local built, step_time = build(net, cpos, inv, name, count*craft_count, stack, sink, start_time) if built then me.log("crafting "..stack:get_count().." "..stack:get_name().." in "..step_time.." seconds", "error") - me.ac_status = me.ac_status .. "Crafting "..(count*craft_count).." "..name.." in "..step_time.." seconds.\n" + net.ac_status = net.ac_status .. "Crafting "..(count*craft_count).." "..name.." in "..step_time.." seconds.\n" else me.log("can't craft "..stack:get_count().." "..stack:get_name(), "error") - me.ac_status = me.ac_status .. "Can't craft "..(count*craft_count).." "..name..".\n" + net.ac_status = net.ac_status .. "Can't craft "..(count*craft_count).." "..name..".\n" end return end diff --git a/modules/storage/cmonitor.lua b/modules/storage/cmonitor.lua index 5808ff1..0571552 100644 --- a/modules/storage/cmonitor.lua +++ b/modules/storage/cmonitor.lua @@ -38,7 +38,7 @@ local function chest_formspec(pos, start_id, listname, page_max, q) ]] local status = "The status of the crafter is: " .. ((net.pending and "running " .. #net.pending .. " steps\n") or "idle\n") - status = status .. (me.ac_status or "") + status = status .. (net.ac_status or "") buttons = [[ button[0.8,5.1;0.8,0.9;prev;<] button[2.65,5.1;0.8,0.9;next;>] @@ -250,7 +250,7 @@ me.register_node("cmonitor", { meta:set_string("formspec", chest_formspec(pos, page, inv_name, page_max)) elseif fields.clear then own_inv:set_size("search", 0) - ctrl_inv:set_size("ac", 16) + ctrl_inv:set_size("ac", 0) meta:set_int("page", 1) meta:set_string("inv_name", "ac") net.pending = nil diff --git a/modules/storage/cterminal.lua b/modules/storage/cterminal.lua index 54fb556..feca3c5 100644 --- a/modules/storage/cterminal.lua +++ b/modules/storage/cterminal.lua @@ -295,6 +295,12 @@ me.block_to_typename_map = { -- default wiring me.register_typename("default:furnace", "cooking") +-- These must be called after the true name of the machine is defined. +function me.register_machine_alias(alias, name) + me.block_to_typename_map[alias] = me.block_to_typename_map[name] + me.set_speed(alias, me.speed[name]) +end + function me.get_recipe(typename, inputs) return technic.get_recipe(typename, inputs) end diff --git a/modules/storage/technic-interop.lua b/modules/storage/technic-interop.lua index 93b77d0..dd8448c 100644 --- a/modules/storage/technic-interop.lua +++ b/modules/storage/technic-interop.lua @@ -100,6 +100,25 @@ me.register_typename("technic:hv_compressor", "compressing") me.register_typename("technic:mv_centrifuge", "separating") me.register_typename("technic:mv_freezer", "freezing") +-- We need active nodes defined as well, as the recipe system doesn't otherwise have +-- recipes for them. +me.register_machine_alias("technic:electric_furnace_active", "technic:electric_furnace") +me.register_machine_alias("technic:mv_electric_furnace_active", "technic:mv_electric_furnace") +me.register_machine_alias("technic:hv_electric_furnace_active", "technic:hv_electric_furnace") +me.register_machine_alias("technic:lv_grinder_active", "technic:lv_grinder") +me.register_machine_alias("technic:mv_grinder_active", "technic:mv_grinder") +me.register_machine_alias("technic:hv_grinder_active", "technic:hv_grinder") +me.register_machine_alias("technic:coal_alloy_furnace_active", "technic:coal_alloy_furnace") +me.register_machine_alias("technic:lv_alloy_furnace_active", "technic:lv_alloy_furnace") +me.register_machine_alias("technic:mv_alloy_furnace_active", "technic:mv_alloy_furnace") +me.register_machine_alias("technic:lv_extractor_active", "technic:lv_extractor") +me.register_machine_alias("technic:mv_extractor_active", "technic:mv_extractor") +me.register_machine_alias("technic:lv_compressor_active", "technic:lv_compressor") +me.register_machine_alias("technic:mv_compressor_active", "technic:mv_compressor") +me.register_machine_alias("technic:hv_compressor_active", "technic:hv_compressor") +me.register_machine_alias("technic:mv_centrifuge_active", "technic:mv_centrifuge") +me.register_machine_alias("technic:mv_freezer_active", "technic:mv_freezer") + -- ======================================================================== --