From dbe410871c40e3046f1e95a6d1ae95dabcfcf365 Mon Sep 17 00:00:00 2001 From: Ben Gardner Date: Sun, 12 Nov 2023 15:22:49 -0600 Subject: [PATCH] save off start of an idea --- src/GlobalState.lua | 111 +++++++++++++++++++++++++++++++++++++------ src/NetworkChest.lua | 8 ++-- src/constants.lua | 4 ++ 3 files changed, 105 insertions(+), 18 deletions(-) diff --git a/src/GlobalState.lua b/src/GlobalState.lua index 7192a94..4726019 100644 --- a/src/GlobalState.lua +++ b/src/GlobalState.lua @@ -19,18 +19,50 @@ function M.setup() M.inner_setup() end +--[[ +Service Queue Revamp. + +There is an array of queues. +The current queue is consumed until empty. Same 20-ish entities per tick. +Each queue is assigned a minimum amount of ticks that it occupies. (20 ?) +When a queue is empty, game.tick is compared against the deadline. If passed, then +the active queue index is incremented (and wrapped) and the deadline is reset. + +Entities are added to the service queue via a unit_number and priority. +The priority selects the relative queue to insert. + 0 = active + 1 + 1 = active + 2, etc + +The priority changes based on the type and whether anything was transferred. + + - Network Bulk Provider (empties everything from the chest) + * always max priority (longest time between services) + - Network Bulk Requester (one item, grabs as much as possible) + * always max priority (longest time between services) + - Network Chest + * priority goes down by 1 when serviced + * priority goes up by 1 when not serviced + - Network Tank + * priority goes down by 1 when serviced + * priority goes up by 1 when not serviced + - Vechicles + * Always max priority + - Logistics + * Always max priority +]] + function M.inner_setup() if global.mod == nil then global.mod = { rand = game.create_random_generator(), chests = {}, - scan_queue = Queue.new(), items = {}, } end - if global.mod.scan_queue_inactive == nil then - global.mod.scan_queue_inactive = Queue.new() + if global.mod.scan_queues == nil then + M.reset_queues() + global.mod.entity_priority = {} -- key=unum, val=priority end M.remove_old_ui() @@ -39,7 +71,7 @@ function M.inner_setup() end if global.mod.network_chest_has_been_placed == nil then - global.mod.network_chest_has_been_placed = (global.mod.scan_queue.size + global.mod.scan_queue_inactive.size) > 0 + global.mod.network_chest_has_been_placed = true -- (global.mod.scan_queue.size + global.mod.scan_queue_inactive.size) > 0 end if global.mod.fluids == nil then @@ -116,19 +148,25 @@ function M.inner_setup() end function M.reset_queues() - global.mod.scan_queue = Queue.new() - global.mod.scan_queue_inactive = Queue.new() + global.mod.scan_deadline = 0 -- keep doing nothing until past this tick + global.mod.scan_index = 1 -- working on the queue in this index + + global.mod.scan_queues = {} -- list of queues to process + for idx = 1, constants.QUEUE_COUNT do + global.mod.scan_queues[idx] = Queue.new() + end + for unum, _ in pairs(global.mod.chests) do - Queue.push(global.mod.scan_queue, unum) + M.queue_insert(unum, 1) end for unum, _ in pairs(global.mod.tanks) do - Queue.push(global.mod.scan_queue, unum) + M.queue_insert(unum, 2) end for unum, _ in pairs(global.mod.vehicles) do - Queue.push(global.mod.scan_queue, unum) + M.queue_insert(unum, 3) end for unum, _ in pairs(global.mod.logistic) do - Queue.push(global.mod.scan_queue, unum) + M.queue_insert(unum, 4) end end @@ -635,10 +673,11 @@ function M.get_ui_state(player_index) end M.UPDATE_STATUS = { - INVALID = 0, - UPDATED = 1, - NOT_UPDATED = 2, - ALREADY_UPDATED = 3, + INVALID = 0, -- causes the entity to be removed + UPDATED = -1, -- entity needed service + NOT_UPDATED = 1, -- entity did not need service + BULK = 1, -- bulk tranfser + ALREADY_UPDATED = 3, -- not used } function M.update_queue(update_entity) @@ -826,7 +865,49 @@ function M.update_queue_multi(update_entity) --Queue.swap_random_to_front(global.mod.scan_queue, global.mod.rand) end -M.update_queue = M.update_queue_dual +function M.queue_insert(unit_number, priority) + -- clamp priority to 0 .. QUEUE_COUNT-1 + priority = math.max(0, math.min(priority, constants.QUEUE_COUNT - 1)) + global.mod.entity_priority[unit_number] = priority + + -- q_idx is where to put it, Priority 0 => scan_index + 1 + -- scan_index is 1-based, so it would be scan_index-1+1+priority + local q_idx = 1 + (global.mod.scan_index + priority) % constants.QUEUE_COUNT + local q = globals.mod.scan_queues[q_idx] + Queue.push(q, unit_number) +end + +function M.update_queue_lists(update_entity) + local MAX_ENTITIES_TO_UPDATE = settings.global + ["item-network-number-of-entities-per-tick"] + .value + + local qs = global.mod.scan_queues + local q_idx = global.mod.scan_index + if q_idx < 1 or q_idx > #qs then + q_idx = 1 + end + local q = qs[q_idx] + + for _ = 1, MAX_ENTITIES_TO_UPDATE do + local unit_number = Queue.pop(q) + if unit_number == nil then + -- nothing to process in this queue. step to the next one if past the deadline + if game.tick > global.mod.scan_deadline then + global.mod.scan_deadline = game.tick + constants.QUEUE_TICKS + global.mod.scan_index = q_idx + 1 + end + return + end + + local pri = update_entity(unit_number, global.mod.entity_priority[unit_number] or 0) + if pri ~= nil then + M.queue_insert(unit_number, pri) + end + end +end + +M.update_queue = M.update_queue_lists function M.log_entity(title, entity) if entity ~= nil then diff --git a/src/NetworkChest.lua b/src/NetworkChest.lua index 40c78d6..1c7b476 100644 --- a/src/NetworkChest.lua +++ b/src/NetworkChest.lua @@ -1040,11 +1040,12 @@ local function update_tank_entity(unit_number, info) return update_tank(info) end -local function update_entity(unit_number) +local function update_entity(unit_number, priority) local info info = GlobalState.get_chest_info(unit_number) if info ~= nil then - return update_chest_entity(unit_number, info) + local status = update_chest_entity(unit_number, info) + if info. end info = GlobalState.get_tank_info(unit_number) @@ -1062,7 +1063,8 @@ local function update_entity(unit_number) return M.vehicle_update_entity(entity) end - return GlobalState.UPDATE_STATUS.INVALID + -- unknown/invalid unit_number + return nil end function M.update_queue() diff --git a/src/constants.lua b/src/constants.lua index 67d1c71..07b1c3a 100644 --- a/src/constants.lua +++ b/src/constants.lua @@ -8,4 +8,8 @@ M.MAX_TANK_SIZE = M.TANK_AREA * M.TANK_HEIGHT * 100 M.ALERT_TRANSFER_TICKS = 10 * 60 M.MAX_MISSING_TICKS = 5 * 60 +-- use an array of queues, each must take a minimum of QUEUE_TICKS to process. +M.QUEUE_COUNT = 10 +M.QUEUE_TICKS = 20 + return M