From a26ed161c6762855275b02445050ad6c36a41b42 Mon Sep 17 00:00:00 2001 From: Monica Moniot Date: Thu, 1 Dec 2022 01:00:53 -0500 Subject: [PATCH] added depot bypass --- cybersyn/locale/en/base.cfg | 2 + cybersyn/scripts/central-planning.lua | 10 ++- cybersyn/scripts/factorio-api.lua | 5 +- cybersyn/scripts/global.lua | 1 + cybersyn/scripts/layout.lua | 6 +- cybersyn/scripts/main.lua | 115 +++++++++++++++----------- cybersyn/scripts/migrations.lua | 6 ++ cybersyn/settings.lua | 13 ++- 8 files changed, 102 insertions(+), 56 deletions(-) diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index b6b5de2..76aa0e1 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -3,6 +3,7 @@ cybersyn-ticks-per-second=Central planning updates per second cybersyn-update-rate=Central planning update rate cybersyn-request-threshold=Default requester threshold cybersyn-network-flag=Default network mask +cybersyn-depot-bypass-threshold=Depot bypass fuel threshold cybersyn-warmup-time=Station warmup time (sec) cybersyn-stuck-train-time=Stuck train timeout (sec) @@ -11,6 +12,7 @@ cybersyn-ticks-per-second=How many times per second the central planner should u cybersyn-update-rate=How many stations per tick can be polled at once or can have deliveries scheduled at once. Larger number allow the central planner to keep more up to date on the current state of the network, but at the cost of performance. cybersyn-request-threshold=The default request threshold when a request threshold signal is not given to a station. When a station receives a negative item signal that surpasses its request threshold, so long as any station exists with a positive signal greater than the request threshold, a delivery of that item will be scheduled between the two stations. cybersyn-network-flag=The default set of sub-networks a station will service when no network signal is given to a station. This integer is interpretted bit-wise to give 32 possible sub-networks to choose from. +cybersyn-depot-bypass-threshold=What percentage of the fuel inventory of the a train must be full to activate depot bypass. When a train qualifies for depot bypass, it may take a new order from the network before having to return to its depot, dramatically reducing travel time. If this is set to 1, depot bypass will be disabled. cybersyn-warmup-time=How many seconds a cybernetic combinator will wait before connecting to the Cybersyn network. This is a grace period to modify or correct the circuit network before trains start dispatching to a newly blueprinted station. cybersyn-stuck-train-time=After this many seconds from a train's dispatch, an alert will be sent to let you know a train is probably stuck and has not completed its delivery. The player will likely have to debug their network to get the train unstuck. diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 850a76c..6c5e736 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -191,13 +191,21 @@ local function send_train_between(map_data, r_station_id, p_station_id, train_id end remove_available_train(map_data, train_id, train) + local depot_id = train.depot_id + if depot_id then + map_data.depots[depot_id].available_train_id = nil + train.depot_id = nil + else + local test + end + train.status = STATUS_D_TO_P train.p_station_id = p_station_id train.r_station_id = r_station_id train.manifest = manifest train.last_manifest_tick = map_data.total_ticks - set_manifest_schedule(train.entity, train.depot_name, p_station.entity_stop, r_station.entity_stop, manifest) + set_manifest_schedule(train.entity, train.depot_name, p_station.entity_stop, r_station.entity_stop, manifest, depot_id ~= nil) set_comb2(map_data, p_station) set_comb2(map_data, r_station) if p_station.entity_comb1.valid then diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 116f0b6..58bc008 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -111,7 +111,8 @@ end ---@param p_stop LuaEntity ---@param r_stop LuaEntity ---@param manifest Manifest -function set_manifest_schedule(train, depot_name, p_stop, r_stop, manifest) +---@param start_at_depot boolean? +function set_manifest_schedule(train, depot_name, p_stop, r_stop, manifest, start_at_depot) --NOTE: train must be on same surface as depot_stop local d_surface = train.front_stock.surface local p_surface = p_stop.surface @@ -120,7 +121,7 @@ function set_manifest_schedule(train, depot_name, p_stop, r_stop, manifest) local p_surface_i = p_surface.index local r_surface_i = r_surface.index if d_surface_i == p_surface_i and p_surface_i == r_surface_i then - train.schedule = {current = 1, records = { + train.schedule = {current = start_at_depot and 1 or 2, records = { create_inactivity_order(depot_name), create_direct_to_station_order(p_stop), create_loading_order(p_stop, manifest), diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 3a25da6..a09d155 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -83,6 +83,7 @@ ---@field public network_flag int ---@field public warmup_time double ---@field public stuck_train_time double +---@field public depot_bypass_threshold double ---@type CybersynModSettings mod_settings = {} diff --git a/cybersyn/scripts/layout.lua b/cybersyn/scripts/layout.lua index 58b943c..fcdd3a4 100644 --- a/cybersyn/scripts/layout.lua +++ b/cybersyn/scripts/layout.lua @@ -52,15 +52,15 @@ local function is_layout_accepted(layout_pattern, layout) end ---@param map_data MapData ----@param train Train ---@param train_id uint -function remove_train(map_data, train, train_id) +---@param train Train +function remove_train(map_data, train_id, train) local parked_at_depot_id = train.depot_id if parked_at_depot_id then local depot = map_data.depots[parked_at_depot_id] - remove_available_train(map_data, parked_at_depot_id, train) depot.available_train_id = nil end + remove_available_train(map_data, train_id, train) local layout_id = train.layout_id local count = map_data.layout_train_count[layout_id] if count <= 1 then diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index c13c0a7..3c63ee0 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -147,9 +147,7 @@ local function on_depot_broken(map_data, depot) local train = map_data.trains[train_id] lock_train(train.entity) send_lost_train_alert(train.entity, depot.entity_stop.backer_name) - remove_available_train(map_data, train_id, train) - map_data.trains[train_id] = nil - depot.available_train_id = nil + remove_train(map_data, train_id, train) end map_data.depots[depot.entity_stop.unit_number] = nil end @@ -198,7 +196,7 @@ local function on_station_broken(map_data, station_id, station) --train is attempting delivery to a stop that was destroyed, stop it on_failed_delivery(map_data, train) if train.entity then - remove_train(map_data, train, train_id) + remove_train(map_data, train_id, train) lock_train(train.entity) send_lost_train_alert(train.entity, train.depot_name) else @@ -367,7 +365,6 @@ function on_combinator_network_updated(map_data, comb, network_name) if train_id then local train = map_data.trains[train_id] remove_available_train(map_data, train_id, train) - depot.available_train_id = nil add_available_train_to_depot(map_data, train_id, train, depot_id, depot) end end @@ -598,26 +595,25 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) local train_id = train_entity.id local train = map_data.trains[train_id] if train then - remove_available_train(map_data, train_id, train) - if train.manifest and train.status == STATUS_R_TO_D then - --succeeded delivery - train.p_station_id = 0 - train.r_station_id = 0 - train.manifest = nil - add_available_train_to_depot(map_data, train_id, train, depot_id, map_data.depots[depot_id]) - else - if train.manifest then + if train.manifest then + if train.status == STATUS_R_TO_D then + --succeeded delivery + train.p_station_id = 0 + train.r_station_id = 0 + train.manifest = nil + else on_failed_delivery(map_data, train) send_unexpected_train_alert(train.entity) end - add_available_train_to_depot(map_data, train_id, train, depot_id, map_data.depots[depot_id]) end if is_train_empty then + remove_available_train(map_data, train_id, train) + add_available_train_to_depot(map_data, train_id, train, depot_id, map_data.depots[depot_id]) set_depot_schedule(train_entity, train.depot_name) else --train still has cargo lock_train(train_entity) - remove_train(map_data, train, train_id) + remove_train(map_data, train_id, train) send_nonempty_train_in_depot_alert(train_entity) end elseif is_train_empty then @@ -644,8 +640,9 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) end ---@param map_data MapData ---@param stop LuaEntity +---@param train_id uint ---@param train Train -local function on_train_arrives_buffer(map_data, stop, train) +local function on_train_arrives_buffer(map_data, stop, train_id, train) if train.manifest then ---@type uint local station_id = stop.unit_number @@ -669,19 +666,20 @@ local function on_train_arrives_buffer(map_data, stop, train) --this player intervention that is considered valid else on_failed_delivery(map_data, train) - remove_train(map_data, train, train.entity.id) + remove_train(map_data, train_id, train) lock_train(train.entity) send_lost_train_alert(train.entity, train.depot_name) end else --train is lost somehow, probably from player intervention - remove_train(map_data, train, train.entity.id) + remove_train(map_data, train_id, train) end end ---@param map_data MapData +---@param mod_settings CybersynModSettings ---@param train_id uint ---@param train Train -local function on_train_leaves_station(map_data, train_id, train) +local function on_train_leaves_station(map_data, mod_settings, train_id, train) if train.manifest then if train.status == STATUS_P then train.status = STATUS_P_TO_R @@ -691,14 +689,12 @@ local function on_train_leaves_station(map_data, train_id, train) unset_wagon_combs(map_data, station) if train.has_filtered_wagon then train.has_filtered_wagon = false - for carriage_i, carriage in ipairs(train.entity.carriages) do - if carriage.type == "cargo-wagon" then - local inv = carriage.get_inventory(defines.inventory.cargo_wagon) - if inv and inv.is_filtered() then - ---@type uint - for i = 1, #inv do - inv.set_filter(i, nil) - end + for carriage_i, carriage in ipairs(train.entity.cargo_wagons) do + local inv = carriage.get_inventory(defines.inventory.cargo_wagon) + if inv and inv.is_filtered() then + ---@type uint + for i = 1, #inv do + inv.set_filter(i, nil) end end end @@ -709,41 +705,61 @@ local function on_train_leaves_station(map_data, train_id, train) remove_manifest(map_data, station, train.manifest, -1) set_comb1(map_data, station, nil) unset_wagon_combs(map_data, station) + --add to available trains for depot bypass + local fuel_fill = 0 + local total_slots = 0 + for k, v in pairs(train.entity.locomotives) do + if v[1] then + local inv = v[1].get_fuel_inventory() + if inv then + local inv_size = #inv + total_slots = total_slots + inv_size + for i = 1, inv_size do + local item = inv[i--[[@as uint]]] + local count = item.count + if count > 0 then + fuel_fill = fuel_fill + count/get_stack_size(map_data, item.name) + end + end + end + end + end + --if total_slots == 0 it's probably a modded electric train + if total_slots == 0 or fuel_fill/total_slots > mod_settings.depot_bypass_threshold then + add_available_train(map_data, train_id, train) + end end elseif train.status == STATUS_D then + --The train is leaving the depot without a manifest, the player likely intervened local depot = map_data.depots[train.depot_id--[[@as uint]]] - remove_available_train(map_data, train_id, train) - depot.available_train_id = nil + send_lost_train_alert(train.entity, depot.entity_stop.backer_name) + remove_train(map_data, train_id, train) end end ---@param map_data MapData +---@param train_id uint ---@param train Train -local function on_train_broken(map_data, train) +local function on_train_broken(map_data, train_id, train) --NOTE: train.entity is only absent if the train is climbing a space elevator as of 0.5.0 - if train.manifest and train.entity then - on_failed_delivery(map_data, train) - remove_train(map_data, train, train.entity.id) - if train.entity.valid then - lock_train(train.entity) + if train.entity then + if train.manifest then + on_failed_delivery(map_data, train) end + remove_train(map_data, train_id, train) end end ---@param map_data MapData ---@param pre_train_id uint ----@param train_entity LuaEntity -local function on_train_modified(map_data, pre_train_id, train_entity) +local function on_train_modified(map_data, pre_train_id) local train = map_data.trains[pre_train_id] --NOTE: train.entity is only absent if the train is climbing a space elevator as of 0.5.0 if train and train.entity then if train.manifest then on_failed_delivery(map_data, train) end - remove_train(map_data, train, pre_train_id) - if train.entity.valid then - lock_train(train.entity) - end + remove_train(map_data, pre_train_id, train) end end @@ -779,9 +795,10 @@ local function on_broken(event) elseif entity.type == "straight-rail" then update_station_from_rail(global, entity, nil) elseif entity.train then - local train = global.trains[entity.train.id] + local train_id = entity.train.id + local train = global.trains[train_id] if train then - on_train_broken(global, train) + on_train_broken(global, train_id, train) end end end @@ -802,10 +819,10 @@ end local function on_train_built(event) local train_e = event.train if event.old_train_id_1 then - on_train_modified(global, event.old_train_id_1, train_e) + on_train_modified(global, event.old_train_id_1) end if event.old_train_id_2 then - on_train_modified(global, event.old_train_id_2, train_e) + on_train_modified(global, event.old_train_id_2) end end local function on_train_changed(event) @@ -829,7 +846,7 @@ local function on_train_changed(event) end elseif event.old_state == defines.train_state.wait_station then if train then - on_train_leaves_station(global, train_id, train) + on_train_leaves_station(global, mod_settings, train_id, train) end end end @@ -862,6 +879,7 @@ local function on_settings_changed(event) mod_settings.update_rate = settings.global["cybersyn-update-rate"].value --[[@as int]] mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]] mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]] + mod_settings.depot_bypass_threshold = settings.global["cybersyn-depot-bypass-threshold"].value--[[@as double]] mod_settings.warmup_time = settings.global["cybersyn-warmup-time"].value--[[@as double]] mod_settings.stuck_train_time = settings.global["cybersyn-stuck-train-time"].value--[[@as double]] if event.setting == "cybersyn-ticks-per-second" then @@ -896,6 +914,7 @@ local function main() mod_settings.update_rate = settings.global["cybersyn-update-rate"].value --[[@as int]] mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]] mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]] + mod_settings.depot_bypass_threshold = settings.global["cybersyn-depot-bypass-threshold"].value--[[@as double]] mod_settings.warmup_time = settings.global["cybersyn-warmup-time"].value--[[@as double]] mod_settings.stuck_train_time = settings.global["cybersyn-stuck-train-time"].value--[[@as double]] @@ -980,7 +999,7 @@ local function main() train.entity = train_entity if train.se_awaiting_removal then - remove_train(map_data, train, train.se_awaiting_removal) + remove_train(map_data, train.se_awaiting_removal, train) lock_train(train.entity) send_lost_train_alert(train.entity, train.depot_name) return diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index 98eb7df..beb20ff 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -135,6 +135,12 @@ local migrations_table = { train.is_available = true end end + for k, v in pairs(map_data.trains) do + v.depot = nil + if not v.is_available then + v.depot_id = nil + end + end end, } diff --git a/cybersyn/settings.lua b/cybersyn/settings.lua index b90e60a..e8fef94 100644 --- a/cybersyn/settings.lua +++ b/cybersyn/settings.lua @@ -47,9 +47,18 @@ data:extend({ }, { type = "double-setting", - name = "cybersyn-warmup-time", + name = "cybersyn-depot-bypass-threshold", order = "ae", setting_type = "runtime-global", + default_value = .5, + minimum_value = 0, + maximum_value = 1, + }, + { + type = "double-setting", + name = "cybersyn-warmup-time", + order = "af", + setting_type = "runtime-global", default_value = 20, minimum_value = 0, maximum_value = 2147483647, @@ -57,7 +66,7 @@ data:extend({ { type = "double-setting", name = "cybersyn-stuck-train-time", - order = "af", + order = "ag", setting_type = "runtime-global", default_value = 600, minimum_value = 0,