From b8394803cf9fa61801ff537bc904f2dae228b163 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Thu, 22 Dec 2022 20:02:04 -0500 Subject: [PATCH 01/26] refactored planning algorithm --- TODO | 2 + cybersyn/changelog.txt | 6 + cybersyn/scripts/central-planning.lua | 236 +++++++++++++++----------- 3 files changed, 141 insertions(+), 103 deletions(-) diff --git a/TODO b/TODO index 18675b7..56d378f 100644 --- a/TODO +++ b/TODO @@ -11,6 +11,8 @@ major: add in game guide move to an event based algorithm models & art + Leave the train in automatic mode for at least a tick so that I can implement a memory cell to make an alert + Make the alert persistent instead of going away after 10 seconds minor: railloader compat diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index 5c8f108..e2d921a 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -1,4 +1,10 @@ --------------------------------------------------------------------------------------------------- +Version: 1.1.8 +Date: 2022-12-22 + Changes: + - Fixed depot priority + - A train's distance from the provide station is now prioritized over train cargo capacity +--------------------------------------------------------------------------------------------------- Version: 1.1.7 Date: 2022-12-17 Changes: diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 87ab317..93a77fe 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -36,58 +36,6 @@ end ---@param min_slots_to_move int local function get_valid_train(map_data, r_station_id, p_station_id, item_type, min_slots_to_move) --NOTE: this code is the critical section for amortized run-time optimization - local r_station = map_data.stations[r_station_id] - local p_station = map_data.stations[p_station_id] - ---@type string - local network_name = p_station.network_name - - local p_to_r_dist = get_stop_dist(p_station.entity_stop, r_station.entity_stop) - local netand = band(p_station.network_flag, r_station.network_flag) - if p_to_r_dist == INF or netand == 0 then - return nil, INF - end - - ---@type uint? - local best_train = nil - local best_capacity = 0 - local best_dist = INF - local valid_train_exists = false - - local is_fluid = item_type == "fluid" - local trains = map_data.available_trains[network_name] - if trains then - for train_id, _ in pairs(trains) do - local train = map_data.trains[train_id] - local layout_id = train.layout_id - --check cargo capabilities - --check layout validity for both stations - local capacity = (is_fluid and train.fluid_capacity) or train.item_slot_capacity - if - capacity >= min_slots_to_move and - btest(netand, train.network_flag) and - (r_station.allows_all_trains or r_station.accepted_layouts[layout_id]) and - (p_station.allows_all_trains or p_station.accepted_layouts[layout_id]) and - not train.se_is_being_teleported - then - valid_train_exists = true - --check if exists valid path - --check if path is shortest so we prioritize locality - local t_to_p_dist = get_stop_dist(train.entity.front_stock, p_station.entity_stop) - DEPOT_PRIORITY_MULT*train.priority - - if capacity > best_capacity or (capacity == best_capacity and t_to_p_dist < best_dist) then - best_capacity = capacity - best_dist = t_to_p_dist - best_train = train_id - end - end - end - end - - if valid_train_exists then - return best_train, best_dist + p_to_r_dist - else - return nil, p_to_r_dist - end end @@ -290,31 +238,44 @@ local function tick_dispatch(map_data, mod_settings) while true do local r_station_i = nil local r_threshold = nil - local best_prior = -INF - local best_lru = INF + local best_r_prior = -INF + local best_timestamp = INF for i, id in ipairs(r_stations) do local station = stations[id] --NOTE: the station at r_station_id could have been deleted and reregistered since last poll, this check here prevents it from being processed for a delivery in that case - if station and station.deliveries_total < station.entity_stop.trains_limit then - local item_threshold = station.item_thresholds and station.item_thresholds[item_name] or nil - local threshold = station.r_threshold - local prior = station.priority - if item_threshold then - threshold = item_threshold - if station.item_priority then - prior = station.item_priority--[[@as int]] - end - end - if threshold <= max_threshold and (prior > best_prior or (prior == best_prior and station.last_delivery_tick < best_lru)) then - r_station_i = i - r_threshold = threshold - best_prior = prior - best_lru = station.last_delivery_tick + if not station or station.deliveries_total >= station.entity_stop.trains_limit then + goto continue + end + + local threshold = station.r_threshold + local prior = station.priority + local item_threshold = station.item_thresholds and station.item_thresholds[item_name] or nil + if item_threshold then + threshold = item_threshold + if station.item_priority then + prior = station.item_priority--[[@as int]] end end + if threshold > max_threshold then + goto continue + end + + if prior < best_r_prior then + goto continue + end + + if prior == best_r_prior and station.last_delivery_tick > best_timestamp then + goto continue + end + + r_station_i = i + r_threshold = threshold + best_r_prior = prior + best_timestamp = station.last_delivery_tick + ::continue:: end if not r_station_i then - for i, id in ipairs(r_stations) do + for _, id in ipairs(r_stations) do local station = stations[id] if station and station.display_state%2 == 0 then station.display_state = station.display_state + 1 @@ -326,51 +287,120 @@ local function tick_dispatch(map_data, mod_settings) local r_station_id = r_stations[r_station_i] local r_station = stations[r_station_id] + ---@type string + local network_name = r_station.network_name + local trains = map_data.available_trains[network_name] + local is_fluid = item_type == "fluid" + --no train exists with layout accepted by both provide and request stations + local a_p_exists = false + local a_train_exists = false + local a_train_has_capacity = false + local a_train_has_r_layout = false max_threshold = 0 - local best_i = 0 - local best_train = nil + ---@type uint? + local best_p_i = nil + local best_train_id = nil + local best_p_prior = -INF local best_dist = INF - local best_prior = -INF - local can_be_serviced = false + --if no available trains in the network, skip search for j, p_station_id in ipairs(p_stations) do local p_station = stations[p_station_id] - if p_station and p_station.deliveries_total < p_station.entity_stop.trains_limit then - local effective_count = p_station.item_p_counts[item_name] - if effective_count >= r_threshold then - local item_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] or nil - local prior = p_station.priority - if item_threshold and p_station.item_priority then - prior = p_station.item_priority--[[@as int]] + if not p_station or p_station.deliveries_total >= p_station.entity_stop.trains_limit then + goto p_continue + end + local netand = band(p_station.network_flag, r_station.network_flag) + if netand == 0 then + goto p_continue + end + local effective_count = p_station.item_p_counts[item_name] + max_threshold = max(max_threshold, effective_count) + if effective_count < r_threshold then + goto p_continue + end + a_p_exists = true + local p_prior = p_station.priority + if p_station.item_thresholds and p_station.item_thresholds[item_name] and p_station.item_priority then + p_prior = p_station.item_priority--[[@as int]] + end + if p_prior < best_p_prior then + goto p_continue + end + ---------------------------------------------------------------- + -- check for valid train + ---------------------------------------------------------------- + local slot_threshold = is_fluid and r_threshold or ceil(r_threshold/get_stack_size(map_data, item_name)) + + ---@type uint? + local best_p_train_id = nil + local best_t_prior = -INF + local best_t_to_p_dist = INF + if trains then + for train_id, _ in pairs(trains) do + local train = map_data.trains[train_id] + if not btest(netand, train.network_flag) or train.se_is_being_teleported then + goto train_continue end - local slot_threshold = item_type == "fluid" and r_threshold or ceil(r_threshold/get_stack_size(map_data, item_name)) - local train, d = get_valid_train(map_data, r_station_id, p_station_id, item_type, slot_threshold) - if prior > best_prior or (prior == best_prior and d < best_dist) then - if train then - best_i = j - best_dist = d - best_train = train - best_prior = prior - can_be_serviced = true - elseif d < INF then - best_i = j - can_be_serviced = true - end + a_train_exists = true + --check cargo capabilities + local capacity = (is_fluid and train.fluid_capacity) or train.item_slot_capacity + if capacity < slot_threshold then + --no train with high enough capacity is available + goto train_continue end - end - if effective_count > max_threshold then - max_threshold = effective_count + a_train_has_capacity = true + --check layout validity for both stations + local layout_id = train.layout_id + if not (r_station.allows_all_trains or r_station.accepted_layouts[layout_id]) then + goto train_continue + end + a_train_has_r_layout = true + if not (p_station.allows_all_trains or p_station.accepted_layouts[layout_id]) then + goto train_continue + end + if train.priority < best_t_prior then + goto train_continue + end + --check if path is shortest so we prioritize locality + local t_to_p_dist = get_stop_dist(train.entity.front_stock, p_station.entity_stop) - DEPOT_PRIORITY_MULT*train.priority + + if train.priority == best_t_prior and t_to_p_dist > best_t_to_p_dist then + goto train_continue + end + best_p_train_id = train_id + best_t_prior = train.priority + best_t_to_p_dist = t_to_p_dist + ::train_continue:: end end + if not best_p_train_id then + goto p_continue + end + local best_p_dist = best_t_to_p_dist + get_stop_dist(p_station.entity_stop, r_station.entity_stop) + if p_prior == best_p_prior and best_p_dist > best_dist then + goto p_continue + end + best_p_i = j--[[@as uint]] + best_train_id = best_p_train_id + best_p_prior = p_prior + best_dist = best_p_dist + ::p_continue:: end - if best_train then - local p_station_id = table_remove(p_stations, best_i) - local manifest = create_manifest(map_data, r_station_id, p_station_id, best_train, item_name) - create_delivery(map_data, r_station_id, p_station_id, best_train, manifest) + + if best_train_id then + local p_station_id = table_remove(p_stations, best_p_i) + local manifest = create_manifest(map_data, r_station_id, p_station_id, best_train_id, item_name) + create_delivery(map_data, r_station_id, p_station_id, best_train_id, manifest) return false else - if can_be_serviced and mod_settings.missing_train_alert_enabled then - send_missing_train_alert(r_station.entity_stop, stations[p_stations[best_i]].entity_stop) + if a_train_has_r_layout then + send_no_train_p_layout_alert(r_station.entity_stop, r_station.entity_stop) + elseif a_train_has_capacity then + send_no_train_r_layout_alert(r_station.entity_stop, r_station.entity_stop) + elseif a_train_exists then + send_no_train_capacity_alert(r_station.entity_stop, r_station.entity_stop) + elseif a_p_exists then + send_missing_train_alert(r_station.entity_stop, r_station.entity_stop) end if r_station.display_state%2 == 0 then r_station.display_state = r_station.display_state + 1 From 4b415de86ad8ae4241047dccc8e2e44afe32097d Mon Sep 17 00:00:00 2001 From: mamoniot Date: Thu, 22 Dec 2022 20:02:15 -0500 Subject: [PATCH 02/26] refactored planning algorithm --- cybersyn/scripts/central-planning.lua | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 93a77fe..c8a0747 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -29,16 +29,6 @@ function remove_manifest(map_data, station, manifest, sign) end end ----@param map_data MapData ----@param r_station_id uint ----@param p_station_id uint ----@param item_type string ----@param min_slots_to_move int -local function get_valid_train(map_data, r_station_id, p_station_id, item_type, min_slots_to_move) - --NOTE: this code is the critical section for amortized run-time optimization -end - - ---@param map_data MapData ---@param r_station_id uint ---@param p_station_id uint From 4d6b4997d9126016de3ef399b4966e3f4fba158e Mon Sep 17 00:00:00 2001 From: mamoniot Date: Thu, 22 Dec 2022 21:43:12 -0500 Subject: [PATCH 03/26] added provide threshold override --- TODO | 4 +- cybersyn/changelog.txt | 23 ++---- cybersyn/locale/en/base.cfg | 9 ++- cybersyn/scripts/central-planning.lua | 105 ++++++++++++++++---------- cybersyn/scripts/factorio-api.lua | 52 +++++++++---- cybersyn/scripts/main.lua | 8 +- cybersyn/scripts/remote-interface.lua | 18 ++--- cybersyn/scripts/train-events.lua | 10 +-- 8 files changed, 136 insertions(+), 93 deletions(-) diff --git a/TODO b/TODO index 56d378f..d1bccb1 100644 --- a/TODO +++ b/TODO @@ -5,12 +5,12 @@ bugs: major: debug output - more detailed missing train alerts - implement provide station priority locking add request threshold provide override add in game guide move to an event based algorithm models & art + add stack threshold setting + allow "any" signal for network unions Leave the train in automatic mode for at least a tick so that I can implement a memory cell to make an alert Make the alert persistent instead of going away after 10 seconds diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index e2d921a..3686b4a 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -3,7 +3,10 @@ Version: 1.1.8 Date: 2022-12-22 Changes: - Fixed depot priority - - A train's distance from the provide station is now prioritized over train cargo capacity + - Prioritized a train's distance from the provide station over train cargo capacity + - Forced provide stations to wait until they can service the highest priority request station + - Added more detailed missing train alerts + - Provide stations now override request thresholds with the per-item thresholds set by their station info combinator --------------------------------------------------------------------------------------------------- Version: 1.1.7 Date: 2022-12-17 @@ -38,7 +41,7 @@ Date: 2022-12-8 Version: 1.1.0 Date: 2022-12-8 Changes: - - Added the ability to use the priority signal as input to optional station control so one can override priority on items with optional station control thresholds + - Added the ability to use the priority signal as input to station info combinators so one can override priority on items with station info combinators thresholds - Added refueler stations - Slightly more permissive allow-list logic - Made non-backwards compatible improvements and bugfixes to the modding interface @@ -50,20 +53,8 @@ Date: 2022-12-3 Changes: - Fixed a bug with SE compat preventing players from joining multiplayer games --------------------------------------------------------------------------------------------------- -Version: 1.0.8 -Date: 2022-12-2 - Changes: - - Fixed a bug with combinator displays not updating correctly - - Improved combinator display performance - - Added a modding interface ---------------------------------------------------------------------------------------------------- -Version: 1.0.7 -Date: 2022-12-1 - Changes: - - Fixed a crash relating to depot bypass through space elevators ---------------------------------------------------------------------------------------------------- -Version: 1.0.6 -Date: 2022-11-30 +Version: 1.0.8optional station +optional station Changes: - Added depot bypass - Increased inactivity time so burner inserters are fast enough to trigger it diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index c076410..3c9d32c 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -1,7 +1,7 @@ [mod-setting-name] cybersyn-ticks-per-second=Central planning updates per second cybersyn-update-rate=Central planning update rate -cybersyn-request-threshold=Default requester threshold +cybersyn-request-threshold=Default request threshold cybersyn-network-flag=Default network mask cybersyn-fuel-threshold=Fuel threshold cybersyn-depot-bypass-enabled=Depot bypass enabled @@ -43,7 +43,6 @@ cybersyn-request-threshold=Request threshold cybersyn-locked-slots=Locked slots per cargo wagon [cybersyn-messages] -missing-trains=Could not find a train to make a delivery from __2__ to __1__ nonempty-train=A train is being held in the depot because it still has cargo unexpected-train=A train has unexpectedly returned to the depot before completing its delivery stuck-train=A train from depot __1__ is stuck @@ -52,6 +51,10 @@ depot-broken=A train from depot __1__ is lost because its depot was broken. refueler-broken=A train from depot __1__ is lost because its refueler was broken. station-broken=A train from depot __1__ is lost because one of its delivery stations was broken. train-at-incorrect=A train from depot __1__ is lost; it parked at a station it was not scheduled to delivered to. +missing-train=Could not find any train on the correct network to make a delivery from __2__ to __1__ +no-train-has-capacity=Could not find a train with large enough cargo capacity to make a delivery from __2__ to __1__ +no-train-matches-r-layout=Could not find a train on the allow-list of __1__ to make a delivery +no-train-matches-p-layout=Could not find a train on the allow-list of __2__ to make a delivery to __1__ [cybersyn-gui] combinator-title=Cybernetic combinator @@ -62,7 +65,7 @@ refueler=Fuel loader comb2=Station info wagon-manifest=Wagon info network=Network -network-tooltip=A signal is used to identify which network this combinator is a member of. Trains will only be dispatched from depots to provide and request stations if they are all identified with the same signal. +network-tooltip=A signal is used to identify which network this combinator is a member of. Trains will only be dispatched from depots to provider and requester stations if they are all identified with the same signal. auto-tooltip=When checked trains in the network are automatically added to the allow-list if every wagon of the train is able to be loaded or unloaded by this station. When unchecked the allow-list is not used and all trains are allowed to park here. auto-description=Automatic train allow-list switch-provide=Provide only diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index c8a0747..f84a790 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -117,7 +117,8 @@ function create_manifest(map_data, r_station_id, p_station_id, train_id, primary local r_threshold = r_station.item_thresholds and r_station.item_thresholds[item_name] or r_station.r_threshold local p_effective_item_count = p_station.item_p_counts[item_name] --could be an item that is not present at the station - if p_effective_item_count and p_effective_item_count >= r_threshold then + local override_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] + if p_effective_item_count and p_effective_item_count >= (override_threshold or r_threshold) then local item = {name = item_name, type = item_type, count = min(-r_effective_item_count, p_effective_item_count)} if item_name == primary_item_name then manifest[#manifest + 1] = manifest[1] @@ -224,7 +225,6 @@ local function tick_dispatch(map_data, mod_settings) end end end - local max_threshold = INF while true do local r_station_i = nil local r_threshold = nil @@ -246,10 +246,6 @@ local function tick_dispatch(map_data, mod_settings) prior = station.item_priority--[[@as int]] end end - if threshold > max_threshold then - goto continue - end - if prior < best_r_prior then goto continue end @@ -282,39 +278,31 @@ local function tick_dispatch(map_data, mod_settings) local trains = map_data.available_trains[network_name] local is_fluid = item_type == "fluid" --no train exists with layout accepted by both provide and request stations - local a_p_exists = false - local a_train_exists = false - local a_train_has_capacity = false - local a_train_has_r_layout = false + local correctness = 0 + local closest_to_correct_p_station = nil - max_threshold = 0 ---@type uint? - local best_p_i = nil + local p_station_i = nil local best_train_id = nil local best_p_prior = -INF local best_dist = INF --if no available trains in the network, skip search - for j, p_station_id in ipairs(p_stations) do + ---@type uint + local j = 1 + while j <= #p_stations do + local p_station_id = p_stations[j] local p_station = stations[p_station_id] if not p_station or p_station.deliveries_total >= p_station.entity_stop.trains_limit then goto p_continue end + local netand = band(p_station.network_flag, r_station.network_flag) if netand == 0 then goto p_continue end - local effective_count = p_station.item_p_counts[item_name] - max_threshold = max(max_threshold, effective_count) - if effective_count < r_threshold then - goto p_continue - end - a_p_exists = true - local p_prior = p_station.priority - if p_station.item_thresholds and p_station.item_thresholds[item_name] and p_station.item_priority then - p_prior = p_station.item_priority--[[@as int]] - end - if p_prior < best_p_prior then - goto p_continue + if correctness < 1 then + correctness = 1 + closest_to_correct_p_station = p_station end ---------------------------------------------------------------- -- check for valid train @@ -331,23 +319,40 @@ local function tick_dispatch(map_data, mod_settings) if not btest(netand, train.network_flag) or train.se_is_being_teleported then goto train_continue end - a_train_exists = true + if correctness < 2 then + correctness = 2 + closest_to_correct_p_station = p_station + end + --check cargo capabilities local capacity = (is_fluid and train.fluid_capacity) or train.item_slot_capacity if capacity < slot_threshold then --no train with high enough capacity is available goto train_continue end - a_train_has_capacity = true + if correctness < 3 then + correctness = 3 + closest_to_correct_p_station = p_station + end + --check layout validity for both stations local layout_id = train.layout_id if not (r_station.allows_all_trains or r_station.accepted_layouts[layout_id]) then goto train_continue end - a_train_has_r_layout = true + if correctness < 4 then + correctness = 4 + closest_to_correct_p_station = p_station + end + if not (p_station.allows_all_trains or p_station.accepted_layouts[layout_id]) then goto train_continue end + if correctness < 5 then + correctness = 5 + closest_to_correct_p_station = p_station + end + if train.priority < best_t_prior then goto train_continue end @@ -357,6 +362,7 @@ local function tick_dispatch(map_data, mod_settings) if train.priority == best_t_prior and t_to_p_dist > best_t_to_p_dist then goto train_continue end + best_p_train_id = train_id best_t_prior = train.priority best_t_to_p_dist = t_to_p_dist @@ -366,31 +372,52 @@ local function tick_dispatch(map_data, mod_settings) if not best_p_train_id then goto p_continue end + + local effective_count = p_station.item_p_counts[item_name] + local override_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] + if effective_count < (override_threshold or r_threshold) then + --this p station should have serviced the current r station, lock it so it can't serve any others + --this will lock stations even when the r station manages to find a p station, this not a problem because all stations will be unlocked before it could be an issue + table_remove(p_stations, j) + goto p_continue_remove + end + + local p_prior = p_station.priority + if override_threshold and p_station.item_priority then + p_prior = p_station.item_priority--[[@as int]] + end + if p_prior < best_p_prior then + goto p_continue + end + local best_p_dist = best_t_to_p_dist + get_stop_dist(p_station.entity_stop, r_station.entity_stop) if p_prior == best_p_prior and best_p_dist > best_dist then goto p_continue end - best_p_i = j--[[@as uint]] + + p_station_i = j best_train_id = best_p_train_id best_p_prior = p_prior best_dist = best_p_dist ::p_continue:: + j = j + 1 + ::p_continue_remove:: end if best_train_id then - local p_station_id = table_remove(p_stations, best_p_i) + local p_station_id = table_remove(p_stations, p_station_i) local manifest = create_manifest(map_data, r_station_id, p_station_id, best_train_id, item_name) create_delivery(map_data, r_station_id, p_station_id, best_train_id, manifest) return false else - if a_train_has_r_layout then - send_no_train_p_layout_alert(r_station.entity_stop, r_station.entity_stop) - elseif a_train_has_capacity then - send_no_train_r_layout_alert(r_station.entity_stop, r_station.entity_stop) - elseif a_train_exists then - send_no_train_capacity_alert(r_station.entity_stop, r_station.entity_stop) - elseif a_p_exists then - send_missing_train_alert(r_station.entity_stop, r_station.entity_stop) + if correctness == 1 then + send_alert_missing_train(r_station.entity_stop, closest_to_correct_p_station.entity_stop) + elseif correctness == 2 then + send_alert_no_train_has_capacity(r_station.entity_stop, closest_to_correct_p_station.entity_stop) + elseif correctness == 3 then + send_alert_no_train_matches_r_layout(r_station.entity_stop, closest_to_correct_p_station.entity_stop) + elseif correctness == 4 then + send_alert_no_train_matches_p_layout(r_station.entity_stop, closest_to_correct_p_station.entity_stop) end if r_station.display_state%2 == 0 then r_station.display_state = r_station.display_state + 1 @@ -540,7 +567,7 @@ local function tick_poll_train(map_data, mod_settings) if train and train.manifest and not train.se_is_being_teleported and train.last_manifest_tick + mod_settings.stuck_train_time*mod_settings.tps < map_data.total_ticks then if mod_settings.stuck_train_alert_enabled then - send_stuck_train_alert(train.entity, train.depot_name) + send_alert_stuck_train(train.entity, train.depot_name) end interface_raise_train_stuck(train_id) end diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index a982a0f..06102e3 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -198,7 +198,7 @@ function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, m create_unloading_order(r_stop), }} lock_train(train) - send_cannot_path_between_surfaces_alert(train, depot_name) + send_alert_cannot_path_between_surfaces(train, depot_name) return true end @@ -252,7 +252,7 @@ function add_refueler_schedule(train, stop, depot_name) --create an order that probably cannot be fulfilled and alert the player table_insert(schedule.records, i, create_inactivity_order(stop.backer_name)) lock_train(train) - send_cannot_path_between_surfaces_alert(train, depot_name) + send_alert_cannot_path_between_surfaces(train, depot_name) train.schedule = schedule end @@ -473,55 +473,77 @@ local function send_alert_with_sound(train, icon, message) end end end - -local send_missing_train_alert_for_stop_icon = {name = MISSING_TRAIN_NAME, type = "fluid"} +local send_alert_about_missing_train_icon = {name = MISSING_TRAIN_NAME, type = "fluid"} ---@param r_stop LuaEntity ---@param p_stop LuaEntity -function send_missing_train_alert(r_stop, p_stop) +---@param message string +function send_alert_about_missing_train(r_stop, p_stop, message) for _, player in pairs(r_stop.force.players) do player.add_custom_alert( r_stop, - send_missing_train_alert_for_stop_icon, - {"cybersyn-messages.missing-trains", r_stop.backer_name, p_stop.backer_name}, + send_alert_about_missing_train_icon, + {message, r_stop.backer_name, p_stop.backer_name}, true) end end + +---@param r_stop LuaEntity +---@param p_stop LuaEntity +function send_alert_missing_train(r_stop, p_stop) + send_alert_about_missing_train(r_stop, p_stop, "cybersyn-messages.missing-train") +end +---@param r_stop LuaEntity +---@param p_stop LuaEntity +function send_alert_no_train_has_capacity(r_stop, p_stop) + send_alert_about_missing_train(r_stop, p_stop, "cybersyn-messages.no-train-has-capacity") +end +---@param r_stop LuaEntity +---@param p_stop LuaEntity +function send_alert_no_train_matches_r_layout(r_stop, p_stop) + send_alert_about_missing_train(r_stop, p_stop, "cybersyn-messages.no-train-matches-r-layout") +end +---@param r_stop LuaEntity +---@param p_stop LuaEntity +function send_alert_no_train_matches_p_layout(r_stop, p_stop) + send_alert_about_missing_train(r_stop, p_stop, "cybersyn-messages.no-train-matches-p-layout") +end + local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} ---@param train LuaTrain ---@param depot_name string -function send_cannot_path_between_surfaces_alert(train, depot_name) +function send_alert_cannot_path_between_surfaces(train, depot_name) send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.cannot-path-between-surfaces", depot_name}) end ---@param train LuaTrain ---@param depot_name string -function send_depot_of_train_broken_alert(train, depot_name) +function send_alert_depot_of_train_broken(train, depot_name) send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.depot-broken", depot_name}) end ---@param train LuaTrain ---@param depot_name string -function send_refueler_of_train_broken_alert(train, depot_name) +function send_alert_refueler_of_train_broken(train, depot_name) send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.refueler-broken", depot_name}) end ---@param train LuaTrain ---@param depot_name string -function send_station_of_train_broken_alert(train, depot_name) +function send_alert_station_of_train_broken(train, depot_name) send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.station-broken", depot_name}) end ---@param train LuaTrain ---@param depot_name string -function send_train_at_incorrect_station_alert(train, depot_name) +function send_alert_train_at_incorrect_station(train, depot_name) send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.train-at-incorrect", depot_name}) end local send_nonempty_train_in_depot_alert_icon = {name = NONEMPTY_TRAIN_NAME, type = "fluid"} ---@param train LuaTrain -function send_nonempty_train_in_depot_alert(train) +function send_alert_nonempty_train_in_depot(train) send_alert_with_sound(train, send_nonempty_train_in_depot_alert_icon, {"cybersyn-messages.nonempty-train"}) end ---@param train LuaTrain -function send_unexpected_train_alert(train) +function send_alert_unexpected_train(train) local loco = train.front_stock or train.back_stock if loco then for _, player in pairs(loco.force.players) do @@ -536,7 +558,7 @@ end local send_stuck_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} ---@param train LuaTrain ---@param depot_name string -function send_stuck_train_alert(train, depot_name) +function send_alert_stuck_train(train, depot_name) local loco = train.front_stock or train.back_stock if loco then for _, player in pairs(loco.force.players) do diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index 79261fb..f996204 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -27,7 +27,7 @@ local function on_depot_broken(map_data, depot_id, depot) if train_id then local train = map_data.trains[train_id] lock_train(train.entity) - send_depot_of_train_broken_alert(train.entity, depot.entity_stop.backer_name) + send_alert_depot_of_train_broken(train.entity, depot.entity_stop.backer_name) remove_train(map_data, train_id, train) end map_data.depots[depot_id] = nil @@ -76,7 +76,7 @@ local function on_refueler_broken(map_data, refueler_id, refueler) if not train.se_is_being_teleported then remove_train(map_data, train_id, train) lock_train(train.entity) - send_refueler_of_train_broken_alert(train.entity, train.depot_name) + send_alert_refueler_of_train_broken(train.entity, train.depot_name) else train.se_awaiting_removal = train_id end @@ -151,7 +151,7 @@ local function on_station_broken(map_data, station_id, station) if not train.se_is_being_teleported then remove_train(map_data, train_id, train) lock_train(train.entity) - send_station_of_train_broken_alert(train.entity, train.depot_name) + send_alert_station_of_train_broken(train.entity, train.depot_name) else train.se_awaiting_removal = train_id end @@ -752,7 +752,7 @@ local function setup_se_compat() if train.se_awaiting_removal then remove_train(map_data, train.se_awaiting_removal, train) lock_train(train.entity) - send_station_of_train_broken_alert(train.entity, train.depot_name) + send_alert_station_of_train_broken(train.entity, train.depot_name) return elseif train.se_awaiting_rename then rename_manifest_schedule(train.entity, train.se_awaiting_rename[1], train.se_awaiting_rename[2]) diff --git a/cybersyn/scripts/remote-interface.lua b/cybersyn/scripts/remote-interface.lua index 7828d2e..04863ac 100644 --- a/cybersyn/scripts/remote-interface.lua +++ b/cybersyn/scripts/remote-interface.lua @@ -347,15 +347,15 @@ interface.add_refueler_schedule = add_refueler_schedule --[[alerts]] ------------------------------------------------------------------ -interface.send_missing_train_alert = send_missing_train_alert -interface.send_unexpected_train_alert = send_unexpected_train_alert -interface.send_nonempty_train_in_depot_alert = send_nonempty_train_in_depot_alert -interface.send_stuck_train_alert = send_stuck_train_alert -interface.send_cannot_path_between_surfaces_alert = send_cannot_path_between_surfaces_alert -interface.send_depot_of_train_broken_alert = send_depot_of_train_broken_alert -interface.send_refueler_of_train_broken_alert = send_refueler_of_train_broken_alert -interface.send_station_of_train_broken_alert = send_station_of_train_broken_alert -interface.send_train_at_incorrect_station_alert = send_train_at_incorrect_station_alert +interface.send_alert_missing_train = send_alert_missing_train +interface.send_alert_unexpected_train = send_alert_unexpected_train +interface.send_alert_nonempty_train_in_depot = send_alert_nonempty_train_in_depot +interface.send_alert_stuck_train = send_alert_stuck_train +interface.send_alert_cannot_path_between_surfaces = send_alert_cannot_path_between_surfaces +interface.send_alert_depot_of_train_broken = send_alert_depot_of_train_broken +interface.send_alert_refueler_of_train_broken = send_alert_refueler_of_train_broken +interface.send_alert_station_of_train_broken = send_alert_station_of_train_broken +interface.send_alert_train_at_incorrect_station = send_alert_train_at_incorrect_station remote.add_interface("cybersyn", interface) diff --git a/cybersyn/scripts/train-events.lua b/cybersyn/scripts/train-events.lua index 815a6ef..d78d478 100644 --- a/cybersyn/scripts/train-events.lua +++ b/cybersyn/scripts/train-events.lua @@ -155,7 +155,7 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) if train.manifest then on_failed_delivery(map_data, train_id, train) end - send_unexpected_train_alert(train.entity) + send_alert_unexpected_train(train.entity) else return end @@ -169,7 +169,7 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) if mod_settings.react_to_nonempty_train_in_depot then lock_train(train_entity) remove_train(map_data, train_id, train) - send_nonempty_train_in_depot_alert(train_entity) + send_alert_nonempty_train_in_depot(train_entity) end interface_raise_train_nonempty_in_depot(depot_id, train_entity, train_id) end @@ -202,7 +202,7 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) else if mod_settings.react_to_nonempty_train_in_depot then lock_train(train_entity) - send_nonempty_train_in_depot_alert(train_entity) + send_alert_nonempty_train_in_depot(train_entity) end interface_raise_train_nonempty_in_depot(depot_id, train_entity) end @@ -238,12 +238,12 @@ local function on_train_arrives_station(map_data, station_id, train_id, train) on_failed_delivery(map_data, train_id, train) remove_train(map_data, train_id, train) lock_train(train.entity) - send_train_at_incorrect_station_alert(train.entity, train.depot_name) + send_alert_train_at_incorrect_station(train.entity, train.depot_name) end elseif mod_settings.react_to_train_at_incorrect_station then --train is lost somehow, probably from player intervention remove_train(map_data, train_id, train) - send_train_at_incorrect_station_alert(train.entity, train.depot_name) + send_alert_train_at_incorrect_station(train.entity, train.depot_name) end end From 3c80fd0df23b3a022f1e2a4407d473924144df62 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Thu, 22 Dec 2022 23:25:03 -0500 Subject: [PATCH 04/26] improved alerts --- TODO | 3 - cybersyn/changelog.txt | 5 +- cybersyn/scripts/central-planning.lua | 11 +- cybersyn/scripts/constants.lua | 1 + cybersyn/scripts/factorio-api.lua | 183 +++++++++++++++++--------- cybersyn/scripts/global.lua | 1 + cybersyn/scripts/train-events.lua | 21 ++- 7 files changed, 147 insertions(+), 78 deletions(-) diff --git a/TODO b/TODO index d1bccb1..5e2b603 100644 --- a/TODO +++ b/TODO @@ -5,14 +5,11 @@ bugs: major: debug output - add request threshold provide override add in game guide move to an event based algorithm models & art add stack threshold setting allow "any" signal for network unions - Leave the train in automatic mode for at least a tick so that I can implement a memory cell to make an alert - Make the alert persistent instead of going away after 10 seconds minor: railloader compat diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index 3686b4a..f43521b 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -7,6 +7,8 @@ Date: 2022-12-22 - Forced provide stations to wait until they can service the highest priority request station - Added more detailed missing train alerts - Provide stations now override request thresholds with the per-item thresholds set by their station info combinator + - Nonempty trains in depot are no longer put in manual mode, instead they are forced to park at the depot + - Made several alerts persistent --------------------------------------------------------------------------------------------------- Version: 1.1.7 Date: 2022-12-17 @@ -53,8 +55,7 @@ Date: 2022-12-3 Changes: - Fixed a bug with SE compat preventing players from joining multiplayer games --------------------------------------------------------------------------------------------------- -Version: 1.0.8optional station -optional station +Version: 1.0.8 Changes: - Added depot bypass - Increased inactivity time so burner inserters are fast enough to trigger it diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index f84a790..d640a6e 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -49,7 +49,7 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes train.parked_at_depot_id = nil end --NOTE: we assume that the train is not being teleported at this time - if set_manifest_schedule(train.entity, train.depot_name, train.se_depot_surface_i, p_station.entity_stop, r_station.entity_stop, manifest, depot_id ~= nil) then + if set_manifest_schedule(map_data, train.entity, train.depot_name, train.se_depot_surface_i, p_station.entity_stop, r_station.entity_stop, manifest, depot_id ~= nil) then local old_status = train.status train.status = STATUS_TO_P train.p_station_id = p_station_id @@ -567,7 +567,7 @@ local function tick_poll_train(map_data, mod_settings) if train and train.manifest and not train.se_is_being_teleported and train.last_manifest_tick + mod_settings.stuck_train_time*mod_settings.tps < map_data.total_ticks then if mod_settings.stuck_train_alert_enabled then - send_alert_stuck_train(train.entity, train.depot_name) + send_alert_stuck_train(map_data, train.entity) end interface_raise_train_stuck(train_id) end @@ -587,6 +587,13 @@ end ---@param mod_settings CybersynModSettings function tick(map_data, mod_settings) map_data.total_ticks = map_data.total_ticks + 1 + + if map_data.active_alerts then + if map_data.total_ticks%(10*mod_settings.tps) < 1 then + process_active_alerts(map_data) + end + end + if map_data.tick_state == STATE_INIT then map_data.economy.all_p_stations = {} map_data.economy.all_r_stations = {} diff --git a/cybersyn/scripts/constants.lua b/cybersyn/scripts/constants.lua index ee5eeb8..2d15ffd 100644 --- a/cybersyn/scripts/constants.lua +++ b/cybersyn/scripts/constants.lua @@ -24,6 +24,7 @@ MODE_REFUELER = ">>" NETWORK_SIGNAL_DEFAULT = {name="signal-A", type="virtual"} INACTIVITY_TIME = 100 +LOCK_TRAIN_TIME = 60*60*60*24*7 DELTA = 1/2048 diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 06102e3..8fb9a1c 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -93,6 +93,26 @@ end function lock_train(train) train.manual_mode = true end +---@param train LuaTrain +function lock_train_to_depot(train) + local schedule = train.schedule + if schedule then + local record = schedule.records[schedule.current] + if record then + local wait = record.wait_conditions + if wait and wait[1] then + wait[1].ticks = LOCK_TRAIN_TIME + else + record.wait_conditions = {{type = "inactivity", compare_type = "and", ticks = LOCK_TRAIN_TIME}} + end + train.schedule = schedule + else + train.manual_mode = true + end + else + train.manual_mode = true + end +end ---@param train LuaTrain ---@param stop LuaEntity @@ -114,6 +134,7 @@ end function se_create_elevator_order(elevator_name, is_train_in_orbit) return {station = elevator_name..(is_train_in_orbit and SE_ELEVATOR_ORBIT_SUFFIX or SE_ELEVATOR_PLANET_SUFFIX)} end +---@param map_data MapData ---@param train LuaTrain ---@param depot_name string ---@param d_surface_i int @@ -121,7 +142,7 @@ end ---@param r_stop LuaEntity ---@param manifest Manifest ---@param start_at_depot boolean? -function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, manifest, start_at_depot) +function set_manifest_schedule(map_data, train, depot_name, d_surface_i, p_stop, r_stop, manifest, start_at_depot) --NOTE: can only return false if start_at_depot is false, it should be incredibly rare that this function returns false local old_schedule if not start_at_depot then @@ -137,13 +158,16 @@ function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, m local is_r_on_t = t_surface_i == r_surface_i local is_d_on_t = t_surface_i == d_surface_i if is_p_on_t and is_r_on_t and is_d_on_t then - train.schedule = {current = start_at_depot and 1 or 2--[[@as uint]], records = { - create_inactivity_order(depot_name), - create_direct_to_station_order(p_stop), - create_loading_order(p_stop, manifest), - create_direct_to_station_order(r_stop), - create_unloading_order(r_stop), - }} + train.schedule = { + current = start_at_depot and 1 or 2--[[@as uint]], + records = { + create_inactivity_order(depot_name), + create_direct_to_station_order(p_stop), + create_loading_order(p_stop, manifest), + create_direct_to_station_order(r_stop), + create_unloading_order(r_stop), + } + } if old_schedule and not train.has_path then train.schedule = old_schedule return false @@ -198,14 +222,14 @@ function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, m create_unloading_order(r_stop), }} lock_train(train) - send_alert_cannot_path_between_surfaces(train, depot_name) + send_alert_cannot_path_between_surfaces(map_data, train) return true end +---@param map_data MapData ---@param train LuaTrain ---@param stop LuaEntity ----@param depot_name string -function add_refueler_schedule(train, stop, depot_name) +function add_refueler_schedule(map_data, train, stop) local schedule = train.schedule or {current = 1, records = {}} local i = schedule.current if i == 1 then @@ -252,8 +276,8 @@ function add_refueler_schedule(train, stop, depot_name) --create an order that probably cannot be fulfilled and alert the player table_insert(schedule.records, i, create_inactivity_order(stop.backer_name)) lock_train(train) - send_alert_cannot_path_between_surfaces(train, depot_name) train.schedule = schedule + send_alert_cannot_path_between_surfaces(map_data, train) end @@ -459,15 +483,15 @@ end ---@param train LuaTrain ---@param icon {} ----@param message {} -local function send_alert_with_sound(train, icon, message) +---@param message string +local function send_alert_for_train(train, icon, message) local loco = train.front_stock or train.back_stock if loco then for _, player in pairs(loco.force.players) do player.add_custom_alert( loco, icon, - message, + {message}, true) player.play_sound({path = ALERT_SOUND}) end @@ -487,6 +511,16 @@ function send_alert_about_missing_train(r_stop, p_stop, message) end end +---@param train LuaTrain +function send_alert_sounds(train) + local loco = train.front_stock or train.back_stock + if loco then + for _, player in pairs(loco.force.players) do + player.play_sound({path = ALERT_SOUND}) + end + end +end + ---@param r_stop LuaEntity ---@param p_stop LuaEntity @@ -509,64 +543,85 @@ function send_alert_no_train_matches_p_layout(r_stop, p_stop) send_alert_about_missing_train(r_stop, p_stop, "cybersyn-messages.no-train-matches-p-layout") end -local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} + +local send_stuck_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} +---@param map_data MapData ---@param train LuaTrain ----@param depot_name string -function send_alert_cannot_path_between_surfaces(train, depot_name) - send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.cannot-path-between-surfaces", depot_name}) -end ----@param train LuaTrain ----@param depot_name string -function send_alert_depot_of_train_broken(train, depot_name) - send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.depot-broken", depot_name}) -end ----@param train LuaTrain ----@param depot_name string -function send_alert_refueler_of_train_broken(train, depot_name) - send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.refueler-broken", depot_name}) -end ----@param train LuaTrain ----@param depot_name string -function send_alert_station_of_train_broken(train, depot_name) - send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.station-broken", depot_name}) -end ----@param train LuaTrain ----@param depot_name string -function send_alert_train_at_incorrect_station(train, depot_name) - send_alert_with_sound(train, send_lost_train_alert_icon, {"cybersyn-messages.train-at-incorrect", depot_name}) +function send_alert_stuck_train(map_data, train) + send_alert_for_train(train, send_stuck_train_alert_icon, "cybersyn-messages.stuck-train") + map_data.active_alerts = map_data.active_alerts or {} + map_data.active_alerts[train] = 1 end local send_nonempty_train_in_depot_alert_icon = {name = NONEMPTY_TRAIN_NAME, type = "fluid"} +---@param map_data MapData ---@param train LuaTrain -function send_alert_nonempty_train_in_depot(train) - send_alert_with_sound(train, send_nonempty_train_in_depot_alert_icon, {"cybersyn-messages.nonempty-train"}) +function send_alert_nonempty_train_in_depot(map_data, train) + send_alert_for_train(train, send_nonempty_train_in_depot_alert_icon, "cybersyn-messages.nonempty-train") + map_data.active_alerts = map_data.active_alerts or {} + map_data.active_alerts[train] = 2 +end + +local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} +---@param map_data MapData +---@param train LuaTrain +function send_alert_depot_of_train_broken(map_data, train) + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.depot-broken") + map_data.active_alerts = map_data.active_alerts or {} + map_data.active_alerts[train] = 3 +end +---@param map_data MapData +---@param train LuaTrain +function send_alert_station_of_train_broken(map_data, train) + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.station-broken") + map_data.active_alerts = map_data.active_alerts or {} + map_data.active_alerts[train] = 4 +end +---@param map_data MapData +---@param train LuaTrain +function send_alert_refueler_of_train_broken(map_data, train) + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.refueler-broken") + map_data.active_alerts = map_data.active_alerts or {} + map_data.active_alerts[train] = 5 +end +---@param map_data MapData +---@param train LuaTrain +function send_alert_train_at_incorrect_station(map_data, train) + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.train-at-incorrect") + map_data.active_alerts = map_data.active_alerts or {} + map_data.active_alerts[train] = 6 +end +---@param map_data MapData +---@param train LuaTrain +function send_alert_cannot_path_between_surfaces(map_data, train) + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.cannot-path-between-surfaces") + map_data.active_alerts = map_data.active_alerts or {} + map_data.active_alerts[train] = 7 end ---@param train LuaTrain function send_alert_unexpected_train(train) - local loco = train.front_stock or train.back_stock - if loco then - for _, player in pairs(loco.force.players) do - player.add_custom_alert( - loco, - send_lost_train_alert_icon, - {"cybersyn-messages.unexpected-train"}, - true) - end - end -end -local send_stuck_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} ----@param train LuaTrain ----@param depot_name string -function send_alert_stuck_train(train, depot_name) - local loco = train.front_stock or train.back_stock - if loco then - for _, player in pairs(loco.force.players) do - player.add_custom_alert( - loco, - send_stuck_train_alert_icon, - {"cybersyn-messages.stuck-train", depot_name}, - true) + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.unexpected-train") +end + + +---@param map_data MapData +function process_active_alerts(map_data) + for train, id in pairs(map_data.active_alerts) do + if id == 1 then + send_alert_for_train(train, send_stuck_train_alert_icon, "cybersyn-messages.stuck-train") + elseif id == 2 then + send_alert_for_train(train, send_nonempty_train_in_depot_alert_icon, "cybersyn-messages.nonempty-train") + elseif id == 3 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.depot-broken") + elseif id == 4 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.station-broken") + elseif id == 5 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.refueler-broken") + elseif id == 6 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.train-at-incorrect") + elseif id == 7 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.cannot-path-between-surfaces") end end end diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index a9be46c..2acf3c7 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -19,6 +19,7 @@ ---@field public tick_state uint ---@field public tick_data {} ---@field public economy Economy +---@field public active_alerts {[LuaTrain]: int}? ---@field public se_tele_old_id {[string]: uint} ---@class Station diff --git a/cybersyn/scripts/train-events.lua b/cybersyn/scripts/train-events.lua index d78d478..a4141a3 100644 --- a/cybersyn/scripts/train-events.lua +++ b/cybersyn/scripts/train-events.lua @@ -167,9 +167,9 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) else --train still has cargo if mod_settings.react_to_nonempty_train_in_depot then - lock_train(train_entity) + lock_train_to_depot(train_entity) remove_train(map_data, train_id, train) - send_alert_nonempty_train_in_depot(train_entity) + send_alert_nonempty_train_in_depot(map_data, train_entity) end interface_raise_train_nonempty_in_depot(depot_id, train_entity, train_id) end @@ -201,8 +201,7 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) interface_raise_train_created(train_id, depot_id) else if mod_settings.react_to_nonempty_train_in_depot then - lock_train(train_entity) - send_alert_nonempty_train_in_depot(train_entity) + send_alert_nonempty_train_in_depot(map_data, train_entity) end interface_raise_train_nonempty_in_depot(depot_id, train_entity) end @@ -238,12 +237,12 @@ local function on_train_arrives_station(map_data, station_id, train_id, train) on_failed_delivery(map_data, train_id, train) remove_train(map_data, train_id, train) lock_train(train.entity) - send_alert_train_at_incorrect_station(train.entity, train.depot_name) + send_alert_train_at_incorrect_station(map_data, train.entity) end elseif mod_settings.react_to_train_at_incorrect_station then --train is lost somehow, probably from player intervention remove_train(map_data, train_id, train) - send_alert_train_at_incorrect_station(train.entity, train.depot_name) + send_alert_train_at_incorrect_station(map_data, train.entity) end end @@ -350,7 +349,7 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train) train.refueler_id = best_refueler_id local refueler = map_data.refuelers[best_refueler_id] refueler.trains_total = refueler.trains_total + 1 - add_refueler_schedule(train.entity, refueler.entity_stop, train.depot_name) + add_refueler_schedule(map_data, train.entity, refueler.entity_stop) interface_raise_train_status_changed(train_id, STATUS_R, STATUS_TO_F) return end @@ -417,6 +416,14 @@ end function on_train_changed(event) local train_e = event.train--[[@as LuaTrain]] if not train_e.valid then return end + + if global.active_alerts and global.active_alerts[train_e] then + global.active_alerts[train_e] = nil + if next(global.active_alerts) == nil then + global.active_alerts = nil + end + end + local train_id = train_e.id if train_e.state == defines.train_state.wait_station then local stop = train_e.station From be849acb437b8b056e0af4cbb4357f641dc60f3b Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 08:52:55 -0500 Subject: [PATCH 05/26] added an "everything" network --- TODO | 1 - cybersyn/changelog.txt | 1 + cybersyn/scripts/central-planning.lua | 77 ++++++++++++----- cybersyn/scripts/constants.lua | 1 + cybersyn/scripts/factorio-api.lua | 52 ++++++++++-- cybersyn/scripts/global.lua | 8 +- cybersyn/scripts/gui.lua | 11 ++- cybersyn/scripts/log.lua | 9 ++ cybersyn/scripts/main.lua | 117 +++++++++++--------------- cybersyn/scripts/train-events.lua | 7 +- 10 files changed, 181 insertions(+), 103 deletions(-) create mode 100644 cybersyn/scripts/log.lua diff --git a/TODO b/TODO index 5e2b603..186f80e 100644 --- a/TODO +++ b/TODO @@ -9,7 +9,6 @@ major: move to an event based algorithm models & art add stack threshold setting - allow "any" signal for network unions minor: railloader compat diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index f43521b..06db779 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -9,6 +9,7 @@ Date: 2022-12-22 - Provide stations now override request thresholds with the per-item thresholds set by their station info combinator - Nonempty trains in depot are no longer put in manual mode, instead they are forced to park at the depot - Made several alerts persistent + - Allowed station and fuel combinators to be set to network id "everything", for each virtual signal they recieve as input, the stop is added to that network and its signal strength is used as the network mask --------------------------------------------------------------------------------------------------- Version: 1.1.7 Date: 2022-12-17 diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index d640a6e..09da855 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -9,6 +9,7 @@ local band = bit32.band local table_remove = table.remove local random = math.random + ---@param map_data MapData ---@param station Station ---@param manifest Manifest @@ -188,6 +189,7 @@ local function tick_dispatch(map_data, mod_settings) local p_stations local item_name local item_type + local item_network_name while true do local size = #all_names if size == 0 then @@ -198,7 +200,7 @@ local function tick_dispatch(map_data, mod_settings) --randomizing the ordering should only matter if we run out of available trains local name_i = size <= 2 and 2 or 2*random(size/2) - local item_network_name = all_names[name_i - 1]--[[@as string]] + item_network_name = all_names[name_i - 1]--[[@as string]] local signal = all_names[name_i]--[[@as SignalID]] --swap remove @@ -274,7 +276,13 @@ local function tick_dispatch(map_data, mod_settings) local r_station_id = r_stations[r_station_i] local r_station = stations[r_station_id] ---@type string - local network_name = r_station.network_name + local network_name + if r_station.network_name == NETWORK_ANY then + --TODO: here + _, _, network_name = string.find(item_network_name, "(^.*):") + else + network_name = r_station.network_name + end local trains = map_data.available_trains[network_name] local is_fluid = item_type == "fluid" --no train exists with layout accepted by both provide and request stations @@ -296,7 +304,9 @@ local function tick_dispatch(map_data, mod_settings) goto p_continue end - local netand = band(p_station.network_flag, r_station.network_flag) + local p_flag = p_station.network_name == NETWORK_ANY and (p_station.network_flag[item_name] or 0) or p_station.network_flag + local r_flag = r_station.network_name == NETWORK_ANY and (r_station.network_flag[item_name] or 0) or r_station.network_flag + local netand = band(p_flag, r_flag) if netand == 0 then goto p_continue end @@ -462,7 +472,11 @@ local function tick_poll_station(map_data, mod_settings) station.priority = 0 station.item_priority = nil station.locked_slots = 0 - station.network_flag = mod_settings.network_flag + if station.network_name == NETWORK_ANY then + station.network_flag = {} + else + station.network_flag = mod_settings.network_flag + end local comb1_signals, comb2_signals = get_signals(station) station.tick_signals = comb1_signals station.item_p_counts = {} @@ -500,6 +514,8 @@ local function tick_poll_station(map_data, mod_settings) station.r_threshold = abs(item_count) elseif item_name == LOCKED_SLOTS then station.locked_slots = max(item_count, 0) + elseif station.network_name == NETWORK_ANY then + station.network_flag[item_name] = item_count end comb1_signals[k] = nil end @@ -524,27 +540,43 @@ local function tick_poll_station(map_data, mod_settings) if -effective_item_count >= r_threshold and -item_count >= r_threshold then is_not_requesting = false is_requesting_nothing = false - local item_network_name = station.network_name..":"..item_name - local stations = all_r_stations[item_network_name] - if stations == nil then - stations = {} - all_r_stations[item_network_name] = stations - all_names[#all_names + 1] = item_network_name - all_names[#all_names + 1] = v.signal + local f, a + if station.network_name == NETWORK_ANY then + f, a = pairs(station.network_flag--[[@as {[string]: int}]]) + else + f, a = once, station.network_name + end + for network_name, _ in f, a do + local item_network_name = network_name..":"..item_name + local stations = all_r_stations[item_network_name] + if stations == nil then + stations = {} + all_r_stations[item_network_name] = stations + all_names[#all_names + 1] = item_network_name + all_names[#all_names + 1] = v.signal + end + stations[#stations + 1] = station_id end - stations[#stations + 1] = station_id end end if is_not_requesting then if station.is_p and effective_item_count > 0 and item_count > 0 then - local item_network_name = station.network_name..":"..item_name - local stations = all_p_stations[item_network_name] - if stations == nil then - stations = {} - all_p_stations[item_network_name] = stations + local f, a + if station.network_name == NETWORK_ANY then + f, a = pairs(station.network_flag--[[@as {[string]: int}]]) + else + f, a = once, station.network_name + end + for network_name, _ in f, a do + local item_network_name = network_name..":"..item_name + local stations = all_p_stations[item_network_name] + if stations == nil then + stations = {} + all_p_stations[item_network_name] = stations + end + stations[#stations + 1] = station_id + station.item_p_counts[item_name] = effective_item_count end - stations[#stations + 1] = station_id - station.item_p_counts[item_name] = effective_item_count else comb1_signals[k] = nil end @@ -589,7 +621,7 @@ function tick(map_data, mod_settings) map_data.total_ticks = map_data.total_ticks + 1 if map_data.active_alerts then - if map_data.total_ticks%(10*mod_settings.tps) < 1 then + if map_data.total_ticks%(9*mod_settings.tps) < 1 then process_active_alerts(map_data) end end @@ -613,9 +645,8 @@ function tick(map_data, mod_settings) interface_raise_tick_init() tick_poll_train(map_data, mod_settings) tick_poll_comb(map_data) - end - - if map_data.tick_state == STATE_POLL_STATIONS then + return + elseif map_data.tick_state == STATE_POLL_STATIONS then for i = 1, mod_settings.update_rate do if tick_poll_station(map_data, mod_settings) then break end end diff --git a/cybersyn/scripts/constants.lua b/cybersyn/scripts/constants.lua index 2d15ffd..ee51318 100644 --- a/cybersyn/scripts/constants.lua +++ b/cybersyn/scripts/constants.lua @@ -23,6 +23,7 @@ MODE_WAGON_MANIFEST = "-" MODE_REFUELER = ">>" NETWORK_SIGNAL_DEFAULT = {name="signal-A", type="virtual"} +NETWORK_ANY = "signal-everything" INACTIVITY_TIME = 100 LOCK_TRAIN_TIME = 60*60*60*24*7 diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 8fb9a1c..b79c5ad 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -345,32 +345,74 @@ function set_station_from_comb_state(station) station.is_p = is_pr_state == 0 or is_pr_state == 1 station.is_r = is_pr_state == 0 or is_pr_state == 2 end +---@param map_data MapData ---@param mod_settings CybersynModSettings ----@param refueler Refueler -function set_refueler_from_comb(mod_settings, refueler) +---@param id uint +function set_refueler_from_comb(map_data, mod_settings, id) --NOTE: this does nothing to update currently active deliveries + local refueler = map_data.refuelers[id] local params = get_comb_params(refueler.entity_comb) local bits = params.second_constant or 0 local signal = params.first_signal + + local f, a + if refueler.network_name == NETWORK_ANY then + f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) + else + f, a = once, refueler.network_name + end + for network_name, _ in f, a do + local network = map_data.to_refuelers[network_name] + if network then + network[id] = nil + if next(network) == nil then + map_data.to_refuelers[network_name] = nil + end + end + end + refueler.network_name = signal and signal.name or nil refueler.allows_all_trains = bits%2 == 1 local signals = refueler.entity_comb.get_merged_signals(DEFINES_COMBINATOR_INPUT) refueler.priority = 0 - refueler.network_flag = mod_settings.network_flag + if refueler.network_name == NETWORK_ANY then + refueler.network_flag = {} + else + refueler.network_flag = mod_settings.network_flag + end if not signals then return end for k, v in pairs(signals) do local item_name = v.signal.name + local item_type = v.signal.type local item_count = v.count if item_name then - if item_name == SIGNAL_PRIORITY then - refueler.priority = item_count + if item_type == "virtual" then + if item_name == SIGNAL_PRIORITY then + refueler.priority = item_count + elseif refueler.network_name == NETWORK_ANY then + refueler.network_flag[item_name] = item_count + end end if item_name == refueler.network_name then refueler.network_flag = item_count end end end + + if refueler.network_name == NETWORK_ANY then + f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) + else + f, a = once, refueler.network_name + end + for network_name, _ in f, a do + local network = map_data.to_refuelers[network_name] + if not network then + network = {} + map_data.to_refuelers[network_name] = network + end + network[id] = true + end end ---@param map_data MapData diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 2acf3c7..843c2db 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -36,7 +36,7 @@ ---@field public r_threshold int >= 0 --transient ---@field public locked_slots int >= 0 --transient ---@field public network_name string? ----@field public network_flag int --transient +---@field public network_flag int|{[string]: int} --transient ---@field public wagon_combs {[int]: LuaEntity}?--NOTE: allowed to be invalid entities or combinators with the wrong operation, these must be checked and lazy deleted when found ---@field public deliveries {[string]: int} ---@field public accepted_layouts {[uint]: true?} @@ -151,3 +151,9 @@ function init_global() global.se_tele_old_id = {} end end + +---@param v string +---@param h string? +function once(v, h) + return not h and v or nil--[[@as string|nil]] +end diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 58607b8..60fe7dc 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -192,10 +192,17 @@ function register_gui_actions() local comb = global.to_comb[msg[2]] if not comb or not comb.valid then return end + local param = get_comb_params(comb) + local signal = element.elem_value if signal and (signal.name == "signal-everything" or signal.name == "signal-anything" or signal.name == "signal-each") then - signal = nil - element.elem_value = nil + if param.operation == MODE_PRIMARY_IO or param.operation == MODE_PRIMARY_IO_ACTIVE or param.operation == MODE_PRIMARY_IO_FAILED_REQUEST or param.operation == MODE_REFUELER then + signal.name = NETWORK_ANY + element.elem_value.name = NETWORK_ANY + else + signal = nil + element.elem_value = nil + end end set_comb_network_name(comb, signal) diff --git a/cybersyn/scripts/log.lua b/cybersyn/scripts/log.lua new file mode 100644 index 0000000..36acc00 --- /dev/null +++ b/cybersyn/scripts/log.lua @@ -0,0 +1,9 @@ + + + + +function log_dispatch(network_name, r_stop, p_stop) +end + +function log_refuel(network_name, refuel_stop) +end diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index f996204..fcb211d 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -27,7 +27,7 @@ local function on_depot_broken(map_data, depot_id, depot) if train_id then local train = map_data.trains[train_id] lock_train(train.entity) - send_alert_depot_of_train_broken(train.entity, depot.entity_stop.backer_name) + send_alert_depot_of_train_broken(map_data, train.entity) remove_train(map_data, train_id, train) end map_data.depots[depot_id] = nil @@ -50,18 +50,10 @@ local function on_refueler_built(map_data, stop, comb) --network_name = set_refueler_from_comb, --network_flag = set_refueler_from_comb, } - set_refueler_from_comb(mod_settings, refueler) local id = stop.unit_number--[[@as uint]] map_data.refuelers[id] = refueler + set_refueler_from_comb(map_data, mod_settings, id) update_stop_if_auto(map_data, refueler, false) - if refueler.network_name then - local network = map_data.to_refuelers[refueler.network_name] - if not network then - network = {} - map_data.to_refuelers[refueler.network_name] = network - end - network[id] = true - end interface_raise_refueler_created(id) end ---@param map_data MapData @@ -76,18 +68,26 @@ local function on_refueler_broken(map_data, refueler_id, refueler) if not train.se_is_being_teleported then remove_train(map_data, train_id, train) lock_train(train.entity) - send_alert_refueler_of_train_broken(train.entity, train.depot_name) + send_alert_refueler_of_train_broken(map_data, train.entity) else train.se_awaiting_removal = train_id end end end end - if refueler.network_name then - local network = map_data.to_refuelers[refueler.network_name] - network[refueler_id] = nil - if next(network) == nil then - map_data.to_refuelers[refueler.network_name] = nil + local f, a + if refueler.network_name == NETWORK_ANY then + f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) + else + f, a = once, refueler.network_name + end + for network_name, _ in f, a do + local network = map_data.to_refuelers[network_name] + if network then + network[refueler_id] = nil + if next(network) == nil then + map_data.to_refuelers[network_name] = nil + end end end map_data.refuelers[refueler_id] = nil @@ -151,7 +151,7 @@ local function on_station_broken(map_data, station_id, station) if not train.se_is_being_teleported then remove_train(map_data, train_id, train) lock_train(train.entity) - send_alert_station_of_train_broken(train.entity, train.depot_name) + send_alert_station_of_train_broken(map_data, train.entity) else train.se_awaiting_removal = train_id end @@ -297,55 +297,6 @@ local function on_combinator_built(map_data, comb) end ---@param map_data MapData ---@param comb LuaEntity ----@param network_name string? -function on_combinator_network_updated(map_data, comb, network_name) - local stop = map_data.to_stop[comb.unit_number] - - if stop and stop.valid then - local id = stop.unit_number - local station = map_data.stations[id] - if station then - if station.entity_comb1 == comb then - station.network_name = network_name - end - else - local depot = map_data.depots[id] - if depot then - if depot.entity_comb == comb then - local train_id = depot.available_train_id - if train_id then - local train = map_data.trains[train_id] - remove_available_train(map_data, train_id, train) - add_available_train_to_depot(map_data, mod_settings, train_id, train, id, depot) - interface_raise_train_status_changed(train_id, STATUS_D, STATUS_D) - end - end - else - local refueler = map_data.refuelers[id] - if refueler and refueler.entity_comb == comb then - if refueler.network_name then - local network = map_data.to_refuelers[refueler.network_name] - network[id] = nil - if next(network) == nil then - map_data.to_refuelers[refueler.network_name] = nil - end - end - refueler.network_name = network_name - if network_name then - local network = map_data.to_refuelers[network_name] - if not network then - network = {} - map_data.to_refuelers[network_name] = network - end - network[id] = true - end - end - end - end - end -end ----@param map_data MapData ----@param comb LuaEntity function on_combinator_broken(map_data, comb) --NOTE: we do not check for wagon manifest combinators and update their stations, it is assumed they will be lazy deleted later ---@type uint @@ -441,7 +392,35 @@ function combinator_update(map_data, comb, reset_display) local old_network = old_signal and old_signal.name or nil if new_network ~= old_network then has_changed = true - on_combinator_network_updated(map_data, comb, new_network) + + local stop = map_data.to_stop[comb.unit_number] + if stop and stop.valid then + id = stop.unit_number + station = map_data.stations[id] + if station then + if station.entity_comb1 == comb then + station.network_name = new_network + end + else + local depot = map_data.depots[id] + if depot then + if depot.entity_comb == comb then + local train_id = depot.available_train_id + if train_id then + local train = map_data.trains[train_id] + remove_available_train(map_data, train_id, train) + add_available_train_to_depot(map_data, mod_settings, train_id, train, id, depot) + interface_raise_train_status_changed(train_id, STATUS_D, STATUS_D) + end + end + else + local refueler = map_data.refuelers[id] + if refueler and refueler.entity_comb == comb then + set_refueler_from_comb(map_data, mod_settings, id) + end + end + end + end end if params.second_constant ~= old_params.second_constant then has_changed = true @@ -455,7 +434,7 @@ function combinator_update(map_data, comb, reset_display) local refueler = map_data.refuelers[id] if refueler then local pre = refueler.allows_all_trains - set_refueler_from_comb(mod_settings, refueler) + set_refueler_from_comb(map_data, mod_settings, id) if refueler.allows_all_trains ~= pre then update_stop_if_auto(map_data, refueler, false) end @@ -752,7 +731,7 @@ local function setup_se_compat() if train.se_awaiting_removal then remove_train(map_data, train.se_awaiting_removal, train) lock_train(train.entity) - send_alert_station_of_train_broken(train.entity, train.depot_name) + send_alert_station_of_train_broken(map_data, train.entity) return elseif train.se_awaiting_rename then rename_manifest_schedule(train.entity, train.se_awaiting_rename[1], train.se_awaiting_rename[2]) diff --git a/cybersyn/scripts/train-events.lua b/cybersyn/scripts/train-events.lua index a4141a3..c2da022 100644 --- a/cybersyn/scripts/train-events.lua +++ b/cybersyn/scripts/train-events.lua @@ -1,6 +1,7 @@ --By Mami local min = math.min local INF = math.huge +local btest = bit32.btest ---@param map_data MapData ---@param station Station @@ -329,8 +330,10 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train) local best_prior = -INF for id, _ in pairs(refuelers) do local refueler = map_data.refuelers[id] - set_refueler_from_comb(mod_settings, refueler) - if bit32.btest(train.network_flag, refueler.network_flag) and (refueler.allows_all_trains or refueler.accepted_layouts[train.layout_id]) and refueler.trains_total < refueler.entity_stop.trains_limit then + set_refueler_from_comb(map_data, mod_settings, id) + + local refueler_network_flag = refueler.network_name == NETWORK_ANY and refueler.network_flag[train.network_name] or refueler.network_flag + if btest(train.network_flag, refueler_network_flag) and (refueler.allows_all_trains or refueler.accepted_layouts[train.layout_id]) and refueler.trains_total < refueler.entity_stop.trains_limit then local accepted = false local dist = nil if refueler.priority == best_prior then From 2a5b4543d43375ccbbb8a80f8551f9a46653a301 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 10:11:04 -0500 Subject: [PATCH 06/26] added stack thresholds --- TODO | 6 +- cybersyn/changelog.txt | 1 + cybersyn/locale/en/base.cfg | 6 +- cybersyn/scripts/central-planning.lua | 22 ++++- cybersyn/scripts/factorio-api.lua | 124 +++++++++++++++----------- cybersyn/scripts/global.lua | 11 +-- cybersyn/scripts/gui.lua | 98 ++++++++++---------- cybersyn/scripts/migrations.lua | 18 ++++ 8 files changed, 175 insertions(+), 111 deletions(-) diff --git a/TODO b/TODO index 186f80e..ce9a2c0 100644 --- a/TODO +++ b/TODO @@ -1,18 +1,18 @@ bugs: - fix crash in sumbitted massively modded world + fix crash in submitted massively modded world check for bugs in new player's submitted world find se bug https://mods.factorio.com/mod/cybersyn/discussion/639d1ea26f00ecfa7b048da0 + https://mods.factorio.com/mod/cybersyn/discussion/63a52e54be4341bccc0446f8 major: debug output add in game guide move to an event based algorithm models & art - add stack threshold setting minor: railloader compat - request stack threshold + refuelers set to everything should check for new signals close gui when the combinator is destroyed do not play close sound when a different gui is opened gui can desync if settings are changed outside of it while it is open diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index 06db779..14da236 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -10,6 +10,7 @@ Date: 2022-12-22 - Nonempty trains in depot are no longer put in manual mode, instead they are forced to park at the depot - Made several alerts persistent - Allowed station and fuel combinators to be set to network id "everything", for each virtual signal they recieve as input, the stop is added to that network and its signal strength is used as the network mask + - Added the ability to specify per-station whether request thresholds represent total items or total stacks --------------------------------------------------------------------------------------------------- Version: 1.1.7 Date: 2022-12-17 diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index 3c9d32c..f00585b 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -66,8 +66,10 @@ comb2=Station info wagon-manifest=Wagon info network=Network network-tooltip=A signal is used to identify which network this combinator is a member of. Trains will only be dispatched from depots to provider and requester stations if they are all identified with the same signal. -auto-tooltip=When checked trains in the network are automatically added to the allow-list if every wagon of the train is able to be loaded or unloaded by this station. When unchecked the allow-list is not used and all trains are allowed to park here. -auto-description=Automatic train allow-list +allow-list-description=Automatic train allow-list +allow-list-tooltip=When checked trains in the network are automatically added to the allow-list if every wagon of the train is able to be loaded or unloaded by this station. When unchecked the allow-list is not used and all trains are allowed to park here. +is-stack-description=Enable stack thresholds +is-stack-tooltip=When checked all request thresholds for this station are interpretted as a count of item stacks rather than a count of total items. Fluid thresholds are unaffected. switch-provide=Provide only switch-request=Request only switch-provide-tooltip=Lock this station to only provide items to the network. By default it both requests and provides. diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 09da855..40d3870 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -116,9 +116,15 @@ function create_manifest(map_data, r_station_id, p_station_id, train_id, primary local r_effective_item_count = r_item_count + (r_station.deliveries[item_name] or 0) if r_effective_item_count < 0 and r_item_count < 0 then local r_threshold = r_station.item_thresholds and r_station.item_thresholds[item_name] or r_station.r_threshold + if r_station.is_stack and item_type == "item" then + r_threshold = r_threshold*get_stack_size(map_data, item_name) + end local p_effective_item_count = p_station.item_p_counts[item_name] --could be an item that is not present at the station local override_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] + if override_threshold and p_station.is_stack and item_type == "item" then + override_threshold = override_threshold*get_stack_size(map_data, item_name) + end if p_effective_item_count and p_effective_item_count >= (override_threshold or r_threshold) then local item = {name = item_name, type = item_type, count = min(-r_effective_item_count, p_effective_item_count)} if item_name == primary_item_name then @@ -317,7 +323,13 @@ local function tick_dispatch(map_data, mod_settings) ---------------------------------------------------------------- -- check for valid train ---------------------------------------------------------------- - local slot_threshold = is_fluid and r_threshold or ceil(r_threshold/get_stack_size(map_data, item_name)) + local slot_threshold + if r_station.is_stack and item_type == "item" then + slot_threshold = r_threshold + r_threshold = r_threshold*get_stack_size(map_data, item_name) + else + slot_threshold = is_fluid and r_threshold or ceil(r_threshold/get_stack_size(map_data, item_name)) + end ---@type uint? local best_p_train_id = nil @@ -385,6 +397,9 @@ local function tick_dispatch(map_data, mod_settings) local effective_count = p_station.item_p_counts[item_name] local override_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] + if override_threshold and p_station.is_stack and item_type == "item" then + override_threshold = override_threshold*get_stack_size(map_data, item_name) + end if effective_count < (override_threshold or r_threshold) then --this p station should have serviced the current r station, lock it so it can't serve any others --this will lock stations even when the r station manages to find a p station, this not a problem because all stations will be unlocked before it could be an issue @@ -531,12 +546,16 @@ local function tick_poll_station(map_data, mod_settings) for k, v in pairs(comb1_signals) do ---@type string local item_name = v.signal.name + local item_type = v.signal.type local item_count = v.count local effective_item_count = item_count + (station.deliveries[item_name] or 0) local is_not_requesting = true if station.is_r then local r_threshold = station.item_thresholds and station.item_thresholds[item_name] or station.r_threshold + if station.is_stack and item_type == "item" then + r_threshold = r_threshold*get_stack_size(map_data, item_name) + end if -effective_item_count >= r_threshold and -item_count >= r_threshold then is_not_requesting = false is_requesting_nothing = false @@ -645,7 +664,6 @@ function tick(map_data, mod_settings) interface_raise_tick_init() tick_poll_train(map_data, mod_settings) tick_poll_comb(map_data) - return elseif map_data.tick_state == STATE_POLL_STATIONS then for i = 1, mod_settings.update_rate do if tick_poll_station(map_data, mod_settings) then break end diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index b79c5ad..0849e82 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -296,55 +296,12 @@ function get_comb_params(comb) return comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] end ---@param comb LuaEntity -function get_comb_gui_settings(comb) - local params = get_comb_params(comb) - local op = params.operation - - local selected_index = 0 - local switch_state = "none" - local bits = params.second_constant or 0 - local allows_all_trains = bits%2 == 1 - local is_pr_state = floor(bits/2)%3 - if is_pr_state == 0 then - switch_state = "none" - elseif is_pr_state == 1 then - switch_state = "left" - elseif is_pr_state == 2 then - switch_state = "right" - end - - if op == MODE_PRIMARY_IO or op == MODE_PRIMARY_IO_ACTIVE or op == MODE_PRIMARY_IO_FAILED_REQUEST then - selected_index = 1 - elseif op == MODE_DEPOT then - selected_index = 2 - elseif op == MODE_REFUELER then - selected_index = 3 - elseif op == MODE_SECONDARY_IO then - selected_index = 4 - elseif op == MODE_WAGON_MANIFEST then - selected_index = 5 - end - return selected_index, params.first_signal, not allows_all_trains, switch_state -end ----@param comb LuaEntity function get_comb_network_name(comb) local params = get_comb_params(comb) local signal = params.first_signal return signal and signal.name or nil end ----@param station Station -function set_station_from_comb_state(station) - --NOTE: this does nothing to update currently active deliveries - local params = get_comb_params(station.entity_comb1) - local bits = params.second_constant or 0 - local is_pr_state = floor(bits/2)%3 - local signal = params.first_signal - station.network_name = signal and signal.name or nil - station.allows_all_trains = bits%2 == 1 - station.is_p = is_pr_state == 0 or is_pr_state == 1 - station.is_r = is_pr_state == 0 or is_pr_state == 2 -end ---@param map_data MapData ---@param mod_settings CybersynModSettings ---@param id uint @@ -372,7 +329,7 @@ function set_refueler_from_comb(map_data, mod_settings, id) end refueler.network_name = signal and signal.name or nil - refueler.allows_all_trains = bits%2 == 1 + refueler.allows_all_trains = (bits%2 == 1) or nil local signals = refueler.entity_comb.get_merged_signals(DEFINES_COMBINATOR_INPUT) refueler.priority = 0 @@ -435,14 +392,56 @@ function update_display(map_data, station) end end end + + +---@param station Station +function set_station_from_comb_state(station) + --NOTE: this does nothing to update currently active deliveries + local params = get_comb_params(station.entity_comb1) + local signal = params.first_signal + + local bits = params.second_constant or 0 + local is_pr_state = bit32.extract(bits, 0, 2) + local allows_all_trains = bit32.extract(bits, 2) > 0 + local is_stack = bit32.extract(bits, 3) > 0 + + station.network_name = signal and signal.name or nil + station.allows_all_trains = allows_all_trains + station.is_stack = is_stack + station.is_p = (is_pr_state == 0 or is_pr_state == 1) or nil + station.is_r = (is_pr_state == 0 or is_pr_state == 2) or nil +end ---@param comb LuaEntity ----@param allows_all_trains boolean -function set_comb_allows_all_trains(comb, allows_all_trains) - local control = get_comb_control(comb) - local param = control.parameters - local bits = param.second_constant or 0 - param.second_constant = (bits - bits%2) + (allows_all_trains and 1 or 0) - control.parameters = param +function get_comb_gui_settings(comb) + local params = get_comb_params(comb) + local op = params.operation + + local selected_index = 0 + local switch_state = "none" + local bits = params.second_constant or 0 + local is_pr_state = bit32.extract(bits, 0, 2) + local allows_all_trains = bit32.extract(bits, 2) > 0 + local is_stack = bit32.extract(bits, 3) > 0 + if is_pr_state == 0 then + switch_state = "none" + elseif is_pr_state == 1 then + switch_state = "left" + elseif is_pr_state == 2 then + switch_state = "right" + end + + if op == MODE_PRIMARY_IO or op == MODE_PRIMARY_IO_ACTIVE or op == MODE_PRIMARY_IO_FAILED_REQUEST then + selected_index = 1 + elseif op == MODE_DEPOT then + selected_index = 2 + elseif op == MODE_REFUELER then + selected_index = 3 + elseif op == MODE_SECONDARY_IO then + selected_index = 4 + elseif op == MODE_WAGON_MANIFEST then + selected_index = 5 + end + return selected_index, params.first_signal, switch_state, not allows_all_trains, is_stack end ---@param comb LuaEntity ---@param is_pr_state 0|1|2 @@ -450,7 +449,28 @@ function set_comb_is_pr_state(comb, is_pr_state) local control = get_comb_control(comb) local param = control.parameters local bits = param.second_constant or 0 - param.second_constant = (bits%2) + (2*is_pr_state) + + param.second_constant = bit32.replace(bits, is_pr_state, 0, 2) + control.parameters = param +end +---@param comb LuaEntity +---@param allows_all_trains boolean +function set_comb_allows_all_trains(comb, allows_all_trains) + local control = get_comb_control(comb) + local param = control.parameters + local bits = param.second_constant or 0 + + param.second_constant = bit32.replace(bits, allows_all_trains and 1 or 0, 2) + control.parameters = param +end +---@param comb LuaEntity +---@param is_stack boolean +function set_comb_is_stack(comb, is_stack) + local control = get_comb_control(comb) + local param = control.parameters + local bits = param.second_constant or 0 + + param.second_constant = bit32.replace(bits, is_stack and 1 or 0, 3) control.parameters = param end ---@param comb LuaEntity diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 843c2db..1b192b6 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -26,9 +26,10 @@ ---@field public entity_stop LuaEntity ---@field public entity_comb1 LuaEntity ---@field public entity_comb2 LuaEntity? ----@field public is_p boolean ----@field public is_r boolean ----@field public allows_all_trains boolean +---@field public is_p true? +---@field public is_r true? +---@field public is_stack true? +---@field public allows_all_trains true? ---@field public deliveries_total int ---@field public last_delivery_tick int ---@field public priority int --transient @@ -58,10 +59,10 @@ ---@field public accepted_layouts {[uint]: true?} ---@field public layout_pattern (0|1|2|3)[]? ---@field public wagon_combs {[int]: LuaEntity}?--NOTE: allowed to be invalid entities or combinators with the wrong operation, these must be checked and lazy deleted when found ----@field public allows_all_trains boolean +---@field public allows_all_trains true? ---@field public priority int ---@field public network_name string? ----@field public network_flag int +---@field public network_flag int|{[string]: int} ---@class Train ---@field public entity LuaTrain --should only be invalid if se_is_being_teleported is true diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 60fe7dc..773efaf 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -26,13 +26,34 @@ STATUS_NAMES[defines.entity_status.disabled_by_script] = "entity-status.disabled STATUS_NAMES[defines.entity_status.marked_for_deconstruction] = "entity-status.marked-for-deconstruction" STATUS_NAMES_DEFAULT = "entity-status.disabled" +---@param main_window LuaGuiElement +---@param selected_index int +local function set_visibility(main_window, selected_index) + local uses_network = selected_index == 1 or selected_index == 2 or selected_index == 3 + local uses_allow_list = selected_index == 1 or selected_index == 3 + local is_station = selected_index == 1 + + local vflow = main_window.frame.vflow--[[@as LuaGuiElement]] + local top_flow = vflow.top--[[@as LuaGuiElement]] + local bottom_flow = vflow.bottom--[[@as LuaGuiElement]] + local right_flow = bottom_flow.right--[[@as LuaGuiElement]] + + top_flow.is_pr_switch.visible = is_station + vflow.network_label.visible = uses_network + bottom_flow.network.visible = uses_network + right_flow.allow_list.visible = uses_allow_list + right_flow.allow_list_label.visible = uses_allow_list + right_flow.is_stack.visible = is_station + right_flow.is_stack_label.visible = is_station +end + ---@param comb LuaEntity ---@param player LuaPlayer function gui_opened(comb, player) combinator_update(global, comb, true) local rootgui = player.gui.screen - local selected_index, signal, check, switch_state = get_comb_gui_settings(comb) + local selected_index, signal, switch_state, allow_list, is_stack = get_comb_gui_settings(comb) local window = flib_gui.build(rootgui, { {type="frame", direction="vertical", ref={"main_window"}, name=COMBINATOR_NAME, children={ @@ -44,8 +65,8 @@ function gui_opened(comb, player) on_click = {"close", comb.unit_number} }} }}, - {type="frame", style="inside_shallow_frame_with_padding", style_mods={padding=12}, children={ - {type="flow", direction="vertical", style_mods={horizontal_align="left"}, children={ + {type="frame", name="frame", style="inside_shallow_frame_with_padding", style_mods={padding=12}, children={ + {type="flow", name="vflow", direction="vertical", style_mods={horizontal_align="left"}, children={ --status {type="flow", style="status_flow", direction="horizontal", style_mods={vertical_align="center", horizontally_stretchable=true, bottom_padding=4}, children={ {type="sprite", sprite=STATUS_SPRITES[comb.status] or STATUS_SPRITES_DEFAULT, style="status_image", ref={"status_icon"}, style_mods={stretch_image_to_widget_size=true}}, @@ -67,8 +88,8 @@ function gui_opened(comb, player) {"cybersyn-gui.comb2"}, {"cybersyn-gui.wagon-manifest"}, }}, - {type="switch", name="switch", ref={"switch"}, allow_none_state=true, switch_state=switch_state, left_label_caption={"cybersyn-gui.switch-provide"}, right_label_caption={"cybersyn-gui.switch-request"}, left_label_tooltip={"cybersyn-gui.switch-provide-tooltip"}, right_label_tooltip={"cybersyn-gui.switch-request-tooltip"}, actions={ - on_switch_state_changed={"switch", comb.unit_number} + {type="switch", name="is_pr_switch", ref={"is_pr_switch"}, allow_none_state=true, switch_state=switch_state, left_label_caption={"cybersyn-gui.switch-provide"}, right_label_caption={"cybersyn-gui.switch-request"}, left_label_tooltip={"cybersyn-gui.switch-provide-tooltip"}, right_label_tooltip={"cybersyn-gui.switch-request-tooltip"}, actions={ + on_switch_state_changed={"is_pr_switch", comb.unit_number} }} }}, ---choose-elem-button @@ -78,10 +99,16 @@ function gui_opened(comb, player) {type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", ref={"network"}, elem_type="signal", tooltip={"cybersyn-gui.network-tooltip"}, signal=signal, style_mods={bottom_margin=1, right_margin=6}, actions={ on_elem_changed={"choose-elem-button", comb.unit_number} }}, - {type="checkbox", name="radio_button", ref={"radio_button"}, state=check, tooltip={"cybersyn-gui.auto-tooltip"}, actions={ - on_checked_state_changed={"radio_button", comb.unit_number} - }}, - {type="label", name="radio_label", style_mods={left_padding=3}, ref={"radio_label"}, caption={"cybersyn-gui.auto-description"}}, + {type="flow", name="right", direction="vertical", style_mods={horizontal_align="left"}, children={ + {type="checkbox", name="allow_list", ref={"allow_list"}, state=allow_list, tooltip={"cybersyn-gui.allow-list-tooltip"}, actions={ + on_checked_state_changed={"allow_list", comb.unit_number} + }}, + {type="label", name="allow_list_label", style_mods={left_padding=3}, ref={"allow_list_label"}, caption={"cybersyn-gui.allow-list-description"}}, + {type="checkbox", name="is_stack", ref={"is_stack"}, state=is_stack, tooltip={"cybersyn-gui.is-stack-tooltip"}, actions={ + on_checked_state_changed={"is_stack", comb.unit_number} + }}, + {type="label", name="is_stack_label", style_mods={left_padding=3}, ref={"is_stack_label"}, caption={"cybersyn-gui.is-stack-description"}}, + }} }} }} }} @@ -91,14 +118,8 @@ function gui_opened(comb, player) window.preview.entity = comb window.titlebar.drag_target = window.main_window window.main_window.force_auto_center() - local uses_network = selected_index == 1 or selected_index == 2 or selected_index == 3 - local uses_allow_list = selected_index == 1 or selected_index == 3 - window.network.visible = uses_network - window.network_label.visible = uses_network - window.radio_button.visible = uses_allow_list - window.radio_label.visible = uses_allow_list - window.switch.visible = selected_index == 1 + set_visibility(window.main_window, selected_index) player.opened = window.main_window end @@ -142,45 +163,18 @@ function register_gui_actions() local comb = global.to_comb[msg[2]] if not comb or not comb.valid then return end - local top_flow = element.parent - local all_flow = top_flow.parent - local bottom_flow = all_flow.bottom - local param + set_visibility(rootgui[COMBINATOR_NAME], element.selected_index) + if element.selected_index == 1 then set_comb_operation(comb, MODE_PRIMARY_IO) - top_flow["switch"].visible = true - all_flow["network_label"].visible = true - bottom_flow["network"].visible = true - bottom_flow["radio_button"].visible = true - bottom_flow["radio_label"].visible = true elseif element.selected_index == 2 then set_comb_operation(comb, MODE_DEPOT) - top_flow["switch"].visible = false - all_flow["network_label"].visible = true - bottom_flow["network"].visible = true - bottom_flow["radio_button"].visible = false - bottom_flow["radio_label"].visible = false elseif element.selected_index == 3 then set_comb_operation(comb, MODE_REFUELER) - top_flow["switch"].visible = false - all_flow["network_label"].visible = true - bottom_flow["network"].visible = true - bottom_flow["radio_button"].visible = true - bottom_flow["radio_label"].visible = true elseif element.selected_index == 4 then set_comb_operation(comb, MODE_SECONDARY_IO) - top_flow["switch"].visible = false - all_flow["network_label"].visible = false - bottom_flow["network"].visible = false - bottom_flow["radio_button"].visible = false - bottom_flow["radio_label"].visible = false elseif element.selected_index == 5 then set_comb_operation(comb, MODE_WAGON_MANIFEST) - top_flow["switch"].visible = false - all_flow["network_label"].visible = false - bottom_flow["network"].visible = false - bottom_flow["radio_button"].visible = false - bottom_flow["radio_label"].visible = false else return end @@ -207,7 +201,7 @@ function register_gui_actions() set_comb_network_name(comb, signal) combinator_update(global, comb) - elseif msg[1] == "radio_button" then + elseif msg[1] == "allow_list" then local element = event.element if not element then return end local comb = global.to_comb[msg[2]] @@ -217,7 +211,17 @@ function register_gui_actions() set_comb_allows_all_trains(comb, allows_all_trains) combinator_update(global, comb) - elseif msg[1] == "switch" then + elseif msg[1] == "is_stack" then + local element = event.element + if not element then return end + local comb = global.to_comb[msg[2]] + if not comb or not comb.valid then return end + + local is_stack = element.state + set_comb_is_stack(comb, is_stack) + + combinator_update(global, comb) + elseif msg[1] == "is_pr_switch" then local element = event.element if not element then return end local comb = global.to_comb[msg[2]] diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index bb6e7a0..d9b3951 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -114,6 +114,24 @@ local migrations_table = { end end end, + ["1.1.8"] = function() + ---@type MapData + local map_data = global + map_data.tick_state = STATE_INIT + map_data.tick_data = {} + for k, comb in pairs(map_data.to_comb) do + local control = get_comb_control(comb) + local params = control.parameters + local bits = params.second_constant or 0 + local allows_all_trains = bits%2 + local is_pr_state = math.floor(bits/2)%3 + + local new_bits = bit32.bor(is_pr_state, allows_all_trains*4) + params.second_constant = new_bits + + control.parameters = params + end + end, } --STATUS_R_TO_D = 5 From 13eefd8f1614f382adc5cbe6e40507bc3f2c0f81 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 10:22:08 -0500 Subject: [PATCH 07/26] improved refueler everything logic --- TODO | 1 - cybersyn/scripts/central-planning.lua | 21 +++++++++------ cybersyn/scripts/constants.lua | 2 +- cybersyn/scripts/factorio-api.lua | 39 +++++++++++++++------------ cybersyn/scripts/global.lua | 2 ++ cybersyn/scripts/gui.lua | 4 +-- cybersyn/scripts/main.lua | 3 ++- cybersyn/scripts/migrations.lua | 3 +++ cybersyn/scripts/train-events.lua | 2 +- 9 files changed, 46 insertions(+), 31 deletions(-) diff --git a/TODO b/TODO index ce9a2c0..aa08128 100644 --- a/TODO +++ b/TODO @@ -12,7 +12,6 @@ major: minor: railloader compat - refuelers set to everything should check for new signals close gui when the combinator is destroyed do not play close sound when a different gui is opened gui can desync if settings are changed outside of it while it is open diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 40d3870..bc43d0e 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -283,7 +283,7 @@ local function tick_dispatch(map_data, mod_settings) local r_station = stations[r_station_id] ---@type string local network_name - if r_station.network_name == NETWORK_ANY then + if r_station.network_name == NETWORK_EVERY then --TODO: here _, _, network_name = string.find(item_network_name, "(^.*):") else @@ -310,8 +310,8 @@ local function tick_dispatch(map_data, mod_settings) goto p_continue end - local p_flag = p_station.network_name == NETWORK_ANY and (p_station.network_flag[item_name] or 0) or p_station.network_flag - local r_flag = r_station.network_name == NETWORK_ANY and (r_station.network_flag[item_name] or 0) or r_station.network_flag + local p_flag = p_station.network_name == NETWORK_EVERY and (p_station.network_flag[item_name] or 0) or p_station.network_flag + local r_flag = r_station.network_name == NETWORK_EVERY and (r_station.network_flag[item_name] or 0) or r_station.network_flag local netand = band(p_flag, r_flag) if netand == 0 then goto p_continue @@ -487,7 +487,7 @@ local function tick_poll_station(map_data, mod_settings) station.priority = 0 station.item_priority = nil station.locked_slots = 0 - if station.network_name == NETWORK_ANY then + if station.network_name == NETWORK_EVERY then station.network_flag = {} else station.network_flag = mod_settings.network_flag @@ -529,7 +529,7 @@ local function tick_poll_station(map_data, mod_settings) station.r_threshold = abs(item_count) elseif item_name == LOCKED_SLOTS then station.locked_slots = max(item_count, 0) - elseif station.network_name == NETWORK_ANY then + elseif station.network_name == NETWORK_EVERY then station.network_flag[item_name] = item_count end comb1_signals[k] = nil @@ -560,7 +560,7 @@ local function tick_poll_station(map_data, mod_settings) is_not_requesting = false is_requesting_nothing = false local f, a - if station.network_name == NETWORK_ANY then + if station.network_name == NETWORK_EVERY then f, a = pairs(station.network_flag--[[@as {[string]: int}]]) else f, a = once, station.network_name @@ -581,7 +581,7 @@ local function tick_poll_station(map_data, mod_settings) if is_not_requesting then if station.is_p and effective_item_count > 0 and item_count > 0 then local f, a - if station.network_name == NETWORK_ANY then + if station.network_name == NETWORK_EVERY then f, a = pairs(station.network_flag--[[@as {[string]: int}]]) else f, a = once, station.network_name @@ -624,15 +624,20 @@ local function tick_poll_train(map_data, mod_settings) end end ---@param map_data MapData -local function tick_poll_comb(map_data) +local function tick_poll_comb(map_data, mod_settings) local tick_data = map_data.tick_data --NOTE: the following has undefined behavior if last_comb is deleted local comb_id, comb = next(map_data.to_comb, tick_data.last_comb) tick_data.last_comb = comb_id + local refueler_id, _ = next(map_data.everything_refuelers, tick_data.last_refueler) + tick_data.last_refueler = refueler_id if comb and comb.valid then combinator_update(map_data, comb, true) end + if refueler_id then + set_refueler_from_comb(map_data, mod_settings, refueler_id) + end end ---@param map_data MapData ---@param mod_settings CybersynModSettings diff --git a/cybersyn/scripts/constants.lua b/cybersyn/scripts/constants.lua index ee51318..50f750a 100644 --- a/cybersyn/scripts/constants.lua +++ b/cybersyn/scripts/constants.lua @@ -23,7 +23,7 @@ MODE_WAGON_MANIFEST = "-" MODE_REFUELER = ">>" NETWORK_SIGNAL_DEFAULT = {name="signal-A", type="virtual"} -NETWORK_ANY = "signal-everything" +NETWORK_EVERY = "signal-everything" INACTIVITY_TIME = 100 LOCK_TRAIN_TIME = 60*60*60*24*7 diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 0849e82..ce939ef 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -1,7 +1,9 @@ --By Mami local get_distance = require("__flib__.misc").get_distance -local floor = math.floor local table_insert = table.insert +local bit_extract = bit32.extract +local bit_replace = bit32.replace + local DEFINES_WORKING = defines.entity_status.working local DEFINES_LOW_POWER = defines.entity_status.low_power local DEFINES_COMBINATOR_INPUT = defines.circuit_connector_id.combinator_input @@ -313,7 +315,7 @@ function set_refueler_from_comb(map_data, mod_settings, id) local signal = params.first_signal local f, a - if refueler.network_name == NETWORK_ANY then + if refueler.network_name == NETWORK_EVERY then f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) else f, a = once, refueler.network_name @@ -329,15 +331,18 @@ function set_refueler_from_comb(map_data, mod_settings, id) end refueler.network_name = signal and signal.name or nil - refueler.allows_all_trains = (bits%2 == 1) or nil - - local signals = refueler.entity_comb.get_merged_signals(DEFINES_COMBINATOR_INPUT) + refueler.allows_all_trains = bit_extract(bits, 2) > 0 refueler.priority = 0 - if refueler.network_name == NETWORK_ANY then + + if refueler.network_name == NETWORK_EVERY then + map_data.everything_refuelers[id] = true refueler.network_flag = {} else + map_data.everything_refuelers[id] = nil refueler.network_flag = mod_settings.network_flag end + + local signals = refueler.entity_comb.get_merged_signals(DEFINES_COMBINATOR_INPUT) if not signals then return end for k, v in pairs(signals) do local item_name = v.signal.name @@ -347,7 +352,7 @@ function set_refueler_from_comb(map_data, mod_settings, id) if item_type == "virtual" then if item_name == SIGNAL_PRIORITY then refueler.priority = item_count - elseif refueler.network_name == NETWORK_ANY then + elseif refueler.network_name == NETWORK_EVERY then refueler.network_flag[item_name] = item_count end end @@ -357,7 +362,7 @@ function set_refueler_from_comb(map_data, mod_settings, id) end end - if refueler.network_name == NETWORK_ANY then + if refueler.network_name == NETWORK_EVERY then f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) else f, a = once, refueler.network_name @@ -401,9 +406,9 @@ function set_station_from_comb_state(station) local signal = params.first_signal local bits = params.second_constant or 0 - local is_pr_state = bit32.extract(bits, 0, 2) - local allows_all_trains = bit32.extract(bits, 2) > 0 - local is_stack = bit32.extract(bits, 3) > 0 + local is_pr_state = bit_extract(bits, 0, 2) + local allows_all_trains = bit_extract(bits, 2) > 0 + local is_stack = bit_extract(bits, 3) > 0 station.network_name = signal and signal.name or nil station.allows_all_trains = allows_all_trains @@ -419,9 +424,9 @@ function get_comb_gui_settings(comb) local selected_index = 0 local switch_state = "none" local bits = params.second_constant or 0 - local is_pr_state = bit32.extract(bits, 0, 2) - local allows_all_trains = bit32.extract(bits, 2) > 0 - local is_stack = bit32.extract(bits, 3) > 0 + local is_pr_state = bit_extract(bits, 0, 2) + local allows_all_trains = bit_extract(bits, 2) > 0 + local is_stack = bit_extract(bits, 3) > 0 if is_pr_state == 0 then switch_state = "none" elseif is_pr_state == 1 then @@ -450,7 +455,7 @@ function set_comb_is_pr_state(comb, is_pr_state) local param = control.parameters local bits = param.second_constant or 0 - param.second_constant = bit32.replace(bits, is_pr_state, 0, 2) + param.second_constant = bit_replace(bits, is_pr_state, 0, 2) control.parameters = param end ---@param comb LuaEntity @@ -460,7 +465,7 @@ function set_comb_allows_all_trains(comb, allows_all_trains) local param = control.parameters local bits = param.second_constant or 0 - param.second_constant = bit32.replace(bits, allows_all_trains and 1 or 0, 2) + param.second_constant = bit_replace(bits, allows_all_trains and 1 or 0, 2) control.parameters = param end ---@param comb LuaEntity @@ -470,7 +475,7 @@ function set_comb_is_stack(comb, is_stack) local param = control.parameters local bits = param.second_constant or 0 - param.second_constant = bit32.replace(bits, is_stack and 1 or 0, 3) + param.second_constant = bit_replace(bits, is_stack and 1 or 0, 3) control.parameters = param end ---@param comb LuaEntity diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 1b192b6..3a8d442 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -19,6 +19,7 @@ ---@field public tick_state uint ---@field public tick_data {} ---@field public economy Economy +---@field public everything_refuelers {[uint]: true} ---@field public active_alerts {[LuaTrain]: int}? ---@field public se_tele_old_id {[string]: uint} @@ -146,6 +147,7 @@ function init_global() global.layout_top_id = 1 global.refuelers = {} global.to_refuelers = {} + global.everything_refuelers = {} IS_SE_PRESENT = remote.interfaces["space-exploration"] ~= nil if IS_SE_PRESENT then diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 773efaf..ccc9bf2 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -191,8 +191,8 @@ function register_gui_actions() local signal = element.elem_value if signal and (signal.name == "signal-everything" or signal.name == "signal-anything" or signal.name == "signal-each") then if param.operation == MODE_PRIMARY_IO or param.operation == MODE_PRIMARY_IO_ACTIVE or param.operation == MODE_PRIMARY_IO_FAILED_REQUEST or param.operation == MODE_REFUELER then - signal.name = NETWORK_ANY - element.elem_value.name = NETWORK_ANY + signal.name = NETWORK_EVERY + element.elem_value.name = NETWORK_EVERY else signal = nil element.elem_value = nil diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index fcb211d..7cf274a 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -76,7 +76,7 @@ local function on_refueler_broken(map_data, refueler_id, refueler) end end local f, a - if refueler.network_name == NETWORK_ANY then + if refueler.network_name == NETWORK_EVERY then f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) else f, a = once, refueler.network_name @@ -90,6 +90,7 @@ local function on_refueler_broken(map_data, refueler_id, refueler) end end end + map_data.everything_refuelers[refueler_id] = nil map_data.refuelers[refueler_id] = nil interface_raise_refueler_removed(refueler_id, refueler) end diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index d9b3951..9e66fad 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -119,6 +119,9 @@ local migrations_table = { local map_data = global map_data.tick_state = STATE_INIT map_data.tick_data = {} + + map_data.everything_refuelers = {} + for k, comb in pairs(map_data.to_comb) do local control = get_comb_control(comb) local params = control.parameters diff --git a/cybersyn/scripts/train-events.lua b/cybersyn/scripts/train-events.lua index c2da022..76c38ab 100644 --- a/cybersyn/scripts/train-events.lua +++ b/cybersyn/scripts/train-events.lua @@ -332,7 +332,7 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train) local refueler = map_data.refuelers[id] set_refueler_from_comb(map_data, mod_settings, id) - local refueler_network_flag = refueler.network_name == NETWORK_ANY and refueler.network_flag[train.network_name] or refueler.network_flag + local refueler_network_flag = refueler.network_name == NETWORK_EVERY and refueler.network_flag[train.network_name] or refueler.network_flag if btest(train.network_flag, refueler_network_flag) and (refueler.allows_all_trains or refueler.accepted_layouts[train.layout_id]) and refueler.trains_total < refueler.entity_stop.trains_limit then local accepted = false local dist = nil From eb2feeaa3e5403d2dae97a8cc54a922099a237c0 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 10:53:12 -0500 Subject: [PATCH 08/26] cleared compilation errors --- cybersyn/control.lua | 2 +- cybersyn/scripts/central-planning.lua | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/cybersyn/control.lua b/cybersyn/control.lua index f3580ad..9ea0476 100644 --- a/cybersyn/control.lua +++ b/cybersyn/control.lua @@ -1,5 +1,5 @@ --By Mami - +-- at line 310 jumps into the scope of local 'p_flag' require("scripts.constants") require("scripts.global") require("scripts.factorio-api") diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index bc43d0e..6f50ec5 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -304,15 +304,17 @@ local function tick_dispatch(map_data, mod_settings) ---@type uint local j = 1 while j <= #p_stations do + local p_flag, r_flag, netand, slot_threshold, best_p_train_id, best_t_prior, best_t_to_p_dist, effective_count, override_threshold, p_prior, best_p_dist + local p_station_id = p_stations[j] local p_station = stations[p_station_id] if not p_station or p_station.deliveries_total >= p_station.entity_stop.trains_limit then goto p_continue end - local p_flag = p_station.network_name == NETWORK_EVERY and (p_station.network_flag[item_name] or 0) or p_station.network_flag - local r_flag = r_station.network_name == NETWORK_EVERY and (r_station.network_flag[item_name] or 0) or r_station.network_flag - local netand = band(p_flag, r_flag) + p_flag = p_station.network_name == NETWORK_EVERY and (p_station.network_flag[item_name] or 0) or p_station.network_flag + r_flag = r_station.network_name == NETWORK_EVERY and (r_station.network_flag[item_name] or 0) or r_station.network_flag + netand = band(p_flag, r_flag) if netand == 0 then goto p_continue end @@ -323,7 +325,6 @@ local function tick_dispatch(map_data, mod_settings) ---------------------------------------------------------------- -- check for valid train ---------------------------------------------------------------- - local slot_threshold if r_station.is_stack and item_type == "item" then slot_threshold = r_threshold r_threshold = r_threshold*get_stack_size(map_data, item_name) @@ -332,9 +333,9 @@ local function tick_dispatch(map_data, mod_settings) end ---@type uint? - local best_p_train_id = nil - local best_t_prior = -INF - local best_t_to_p_dist = INF + best_p_train_id = nil + best_t_prior = -INF + best_t_to_p_dist = INF if trains then for train_id, _ in pairs(trains) do local train = map_data.trains[train_id] @@ -395,8 +396,8 @@ local function tick_dispatch(map_data, mod_settings) goto p_continue end - local effective_count = p_station.item_p_counts[item_name] - local override_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] + effective_count = p_station.item_p_counts[item_name] + override_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] if override_threshold and p_station.is_stack and item_type == "item" then override_threshold = override_threshold*get_stack_size(map_data, item_name) end @@ -407,7 +408,7 @@ local function tick_dispatch(map_data, mod_settings) goto p_continue_remove end - local p_prior = p_station.priority + p_prior = p_station.priority if override_threshold and p_station.item_priority then p_prior = p_station.item_priority--[[@as int]] end @@ -415,7 +416,7 @@ local function tick_dispatch(map_data, mod_settings) goto p_continue end - local best_p_dist = best_t_to_p_dist + get_stop_dist(p_station.entity_stop, r_station.entity_stop) + best_p_dist = best_t_to_p_dist + get_stop_dist(p_station.entity_stop, r_station.entity_stop) if p_prior == best_p_prior and best_p_dist > best_dist then goto p_continue end From aebdd6b037f6469b30012ab0583afae23458ee6a Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 11:03:34 -0500 Subject: [PATCH 09/26] fixed gui --- cybersyn/scripts/gui.lua | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index ccc9bf2..6edc7f3 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -42,9 +42,9 @@ local function set_visibility(main_window, selected_index) vflow.network_label.visible = uses_network bottom_flow.network.visible = uses_network right_flow.allow_list.visible = uses_allow_list - right_flow.allow_list_label.visible = uses_allow_list + --right_flow.allow_list_label.visible = uses_allow_list right_flow.is_stack.visible = is_station - right_flow.is_stack_label.visible = is_station + --right_flow.is_stack_label.visible = is_station end ---@param comb LuaEntity @@ -100,14 +100,18 @@ function gui_opened(comb, player) on_elem_changed={"choose-elem-button", comb.unit_number} }}, {type="flow", name="right", direction="vertical", style_mods={horizontal_align="left"}, children={ - {type="checkbox", name="allow_list", ref={"allow_list"}, state=allow_list, tooltip={"cybersyn-gui.allow-list-tooltip"}, actions={ - on_checked_state_changed={"allow_list", comb.unit_number} + {type="flow", name="allow_list", direction="horizontal", style_mods={vertical_align="center"}, children={ + {type="checkbox", name="allow_list", ref={"allow_list"}, state=allow_list, tooltip={"cybersyn-gui.allow-list-tooltip"}, actions={ + on_checked_state_changed={"allow_list", comb.unit_number} + }}, + {type="label", name="allow_list_label", style_mods={left_padding=3}, ref={"allow_list_label"}, caption={"cybersyn-gui.allow-list-description"}}, }}, - {type="label", name="allow_list_label", style_mods={left_padding=3}, ref={"allow_list_label"}, caption={"cybersyn-gui.allow-list-description"}}, - {type="checkbox", name="is_stack", ref={"is_stack"}, state=is_stack, tooltip={"cybersyn-gui.is-stack-tooltip"}, actions={ - on_checked_state_changed={"is_stack", comb.unit_number} + {type="flow", name="is_stack", direction="horizontal", style_mods={vertical_align="center"}, children={ + {type="checkbox", name="is_stack", ref={"is_stack"}, state=is_stack, tooltip={"cybersyn-gui.is-stack-tooltip"}, actions={ + on_checked_state_changed={"is_stack", comb.unit_number} + }}, + {type="label", name="is_stack_label", style_mods={left_padding=3}, ref={"is_stack_label"}, caption={"cybersyn-gui.is-stack-description"}}, }}, - {type="label", name="is_stack_label", style_mods={left_padding=3}, ref={"is_stack_label"}, caption={"cybersyn-gui.is-stack-description"}}, }} }} }} From b3a40f87cba75105ce7e0f4e83c325130027b0c3 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 14:43:22 -0500 Subject: [PATCH 10/26] added a display state for provide lock --- .luarc.json | 1 + cybersyn/changelog.txt | 2 +- cybersyn/scripts/central-planning.lua | 29 +++++++---- cybersyn/scripts/factorio-api.lua | 70 +++++++++++++++------------ cybersyn/scripts/global.lua | 2 +- cybersyn/scripts/gui.lua | 4 +- cybersyn/scripts/migrations.lua | 3 ++ 7 files changed, 65 insertions(+), 46 deletions(-) diff --git a/.luarc.json b/.luarc.json index 7b1d9ce..d672eb8 100644 --- a/.luarc.json +++ b/.luarc.json @@ -26,6 +26,7 @@ "Lua.runtime.special": { "__object_name": "type" }, + "Lua.workspace.checkThirdParty": false, "Lua.workspace.library": [ "~/.steam/steam/steamapps/common/Factorio/data", "~/.steam/steam/steamapps/common/Factorio/data/core/lualib", diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index 14da236..fd9c78d 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -3,7 +3,7 @@ Version: 1.1.8 Date: 2022-12-22 Changes: - Fixed depot priority - - Prioritized a train's distance from the provide station over train cargo capacity + - Prioritized a train's distance from the provide station over the train's cargo capacity - Forced provide stations to wait until they can service the highest priority request station - Added more detailed missing train alerts - Provide stations now override request thresholds with the per-item thresholds set by their station info combinator diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 6f50ec5..012c8c2 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -24,8 +24,8 @@ function remove_manifest(map_data, station, manifest, sign) end set_comb2(map_data, station) station.deliveries_total = station.deliveries_total - 1 - if station.deliveries_total == 0 and station.display_state >= 2 then - station.display_state = station.display_state - 2 + if station.deliveries_total == 0 and band(station.display_state, 4) > 0 then + station.display_state = station.display_state - 4 update_display(map_data, station) end end @@ -81,12 +81,12 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes set_comb2(map_data, p_station) set_comb2(map_data, r_station) - if p_station.display_state < 2 then - p_station.display_state = 2 + if band(p_station.display_state, 4) == 0 then + p_station.display_state = p_station.display_state + 4 update_display(map_data, p_station) end - if r_station.display_state < 2 then - r_station.display_state = 2 + if band(r_station.display_state, 4) == 0 then + r_station.display_state = r_station.display_state + 4 update_display(map_data, r_station) end interface_raise_train_status_changed(train_id, old_status, STATUS_TO_P) @@ -225,7 +225,7 @@ local function tick_dispatch(map_data, mod_settings) else for i, id in ipairs(r_stations) do local station = stations[id] - if station and station.display_state%2 == 0 then + if station and band(station.display_state, 1) == 0 then station.display_state = station.display_state + 1 update_display(map_data, station) end @@ -271,7 +271,7 @@ local function tick_dispatch(map_data, mod_settings) if not r_station_i then for _, id in ipairs(r_stations) do local station = stations[id] - if station and station.display_state%2 == 0 then + if station and band(station.display_state, 1) == 0 then station.display_state = station.display_state + 1 update_display(map_data, station) end @@ -405,7 +405,16 @@ local function tick_dispatch(map_data, mod_settings) --this p station should have serviced the current r station, lock it so it can't serve any others --this will lock stations even when the r station manages to find a p station, this not a problem because all stations will be unlocked before it could be an issue table_remove(p_stations, j) + if band(p_station.display_state, 2) == 0 then + p_station.display_state = p_station.display_state + 2 + update_display(map_data, p_station) + end goto p_continue_remove + else + if band(p_station.display_state, 2) == 1 then + p_station.display_state = p_station.display_state - 2 + update_display(map_data, p_station) + end end p_prior = p_station.priority @@ -445,7 +454,7 @@ local function tick_dispatch(map_data, mod_settings) elseif correctness == 4 then send_alert_no_train_matches_p_layout(r_station.entity_stop, closest_to_correct_p_station.entity_stop) end - if r_station.display_state%2 == 0 then + if band(r_station.display_state, 1) == 0 then r_station.display_state = r_station.display_state + 1 update_display(map_data, r_station) end @@ -602,7 +611,7 @@ local function tick_poll_station(map_data, mod_settings) end end end - if is_requesting_nothing and station.display_state%2 == 1 then + if is_requesting_nothing and band(station.display_state, 1) == 1 then station.display_state = station.display_state - 1 update_display(map_data, station) end diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index ce939ef..1ebce55 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -313,22 +313,7 @@ function set_refueler_from_comb(map_data, mod_settings, id) local params = get_comb_params(refueler.entity_comb) local bits = params.second_constant or 0 local signal = params.first_signal - - local f, a - if refueler.network_name == NETWORK_EVERY then - f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) - else - f, a = once, refueler.network_name - end - for network_name, _ in f, a do - local network = map_data.to_refuelers[network_name] - if network then - network[id] = nil - if next(network) == nil then - map_data.to_refuelers[network_name] = nil - end - end - end + local old_network = refueler.network_name refueler.network_name = signal and signal.name or nil refueler.allows_all_trains = bit_extract(bits, 2) > 0 @@ -343,29 +328,50 @@ function set_refueler_from_comb(map_data, mod_settings, id) end local signals = refueler.entity_comb.get_merged_signals(DEFINES_COMBINATOR_INPUT) - if not signals then return end - for k, v in pairs(signals) do - local item_name = v.signal.name - local item_type = v.signal.type - local item_count = v.count - if item_name then - if item_type == "virtual" then - if item_name == SIGNAL_PRIORITY then - refueler.priority = item_count - elseif refueler.network_name == NETWORK_EVERY then - refueler.network_flag[item_name] = item_count + if signals then + for k, v in pairs(signals) do + local item_name = v.signal.name + local item_type = v.signal.type + local item_count = v.count + if item_name then + if item_type == "virtual" then + if item_name == SIGNAL_PRIORITY then + refueler.priority = item_count + elseif refueler.network_name == NETWORK_EVERY then + refueler.network_flag[item_name] = item_count + end + end + if item_name == refueler.network_name then + refueler.network_flag = item_count end end - if item_name == refueler.network_name then - refueler.network_flag = item_count + end + end + + local f, a + if old_network == NETWORK_EVERY then + f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) + elseif old_network ~= refueler.network_name then + f, a = once, old_network + else + f, a = once, nil + end + for network_name, _ in f, a do + local network = map_data.to_refuelers[network_name] + if network then + network[id] = nil + if next(network) == nil then + map_data.to_refuelers[network_name] = nil end end end if refueler.network_name == NETWORK_EVERY then f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) - else + elseif old_network ~= refueler.network_name then f, a = once, refueler.network_name + else + f, a = once, nil end for network_name, _ in f, a do local network = map_data.to_refuelers[network_name] @@ -386,9 +392,9 @@ function update_display(map_data, station) local params = control.parameters --NOTE: the following check can cause a bug where the display desyncs if the player changes the operation of the combinator and then changes it back before the mod can notice, however removing it causes a bug where the user's change is overwritten and ignored. Everything's bad we need an event to catch copy-paste by blueprint. if params.operation == MODE_PRIMARY_IO or params.operation == MODE_PRIMARY_IO_ACTIVE or params.operation == MODE_PRIMARY_IO_FAILED_REQUEST then - if station.display_state >= 2 then + if station.display_state >= 4 then params.operation = MODE_PRIMARY_IO_ACTIVE - elseif station.display_state == 1 then + elseif station.display_state >= 1 then params.operation = MODE_PRIMARY_IO_FAILED_REQUEST else params.operation = MODE_PRIMARY_IO diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 3a8d442..69597c5 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -46,7 +46,7 @@ ---@field public tick_signals {[uint]: Signal}? --transient ---@field public item_p_counts {[string]: int} --transient ---@field public item_thresholds {[string]: int}? --transient ----@field public display_state 0|1|2|3 --low bit is if this station's request has failed, high bit is if a train is heading to this station +---@field public display_state int ---@class Depot ---@field public entity_stop LuaEntity diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 6edc7f3..753f260 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -95,11 +95,11 @@ function gui_opened(comb, player) ---choose-elem-button {type="line", style_mods={top_padding=10}}, {type="label", name="network_label", ref={"network_label"}, style="heading_3_label", caption={"cybersyn-gui.network"}, style_mods={top_padding=8}}, - {type="flow", name="bottom", direction="horizontal", style_mods={vertical_align="center"}, children={ + {type="flow", name="bottom", direction="horizontal", style_mods={vertical_align="center", top_margin=0, top_padding=0}, children={ {type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", ref={"network"}, elem_type="signal", tooltip={"cybersyn-gui.network-tooltip"}, signal=signal, style_mods={bottom_margin=1, right_margin=6}, actions={ on_elem_changed={"choose-elem-button", comb.unit_number} }}, - {type="flow", name="right", direction="vertical", style_mods={horizontal_align="left"}, children={ + {type="flow", name="right", direction="vertical", style_mods={horizontal_align="left", top_margin=0, top_padding=0}, children={ {type="flow", name="allow_list", direction="horizontal", style_mods={vertical_align="center"}, children={ {type="checkbox", name="allow_list", ref={"allow_list"}, state=allow_list, tooltip={"cybersyn-gui.allow-list-tooltip"}, actions={ on_checked_state_changed={"allow_list", comb.unit_number} diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index 9e66fad..7329a30 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -134,6 +134,9 @@ local migrations_table = { control.parameters = params end + for id, station in pairs(map_data.stations) do + station.display_state = (station.display_state >= 2 and 4) + station.display_state%2 + end end, } --STATUS_R_TO_D = 5 From 8f993dd1ca88a244ee55347f2b91957408c466bd Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 15:45:29 -0500 Subject: [PATCH 11/26] fixed every stations --- cybersyn/changelog.txt | 10 ++--- cybersyn/locale/en/base.cfg | 2 +- cybersyn/scripts/central-planning.lua | 54 +++++++++++++++++++-------- 3 files changed, 44 insertions(+), 22 deletions(-) diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index fd9c78d..3f0af66 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -2,15 +2,15 @@ Version: 1.1.8 Date: 2022-12-22 Changes: - - Fixed depot priority - - Prioritized a train's distance from the provide station over the train's cargo capacity - Forced provide stations to wait until they can service the highest priority request station - - Added more detailed missing train alerts - Provide stations now override request thresholds with the per-item thresholds set by their station info combinator - - Nonempty trains in depot are no longer put in manual mode, instead they are forced to park at the depot - - Made several alerts persistent - Allowed station and fuel combinators to be set to network id "everything", for each virtual signal they recieve as input, the stop is added to that network and its signal strength is used as the network mask - Added the ability to specify per-station whether request thresholds represent total items or total stacks + - Prioritized a train's distance from the provide station over the train's cargo capacity + - Added more detailed missing train alerts + - Nonempty trains in depot are no longer put in manual mode, instead they are forced to park at the depot + - Made several alerts persistent + - Fixed bug with depot priority not working --------------------------------------------------------------------------------------------------- Version: 1.1.7 Date: 2022-12-17 diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index f00585b..0d0f195 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -52,7 +52,7 @@ refueler-broken=A train from depot __1__ is lost because its refueler was broken station-broken=A train from depot __1__ is lost because one of its delivery stations was broken. train-at-incorrect=A train from depot __1__ is lost; it parked at a station it was not scheduled to delivered to. missing-train=Could not find any train on the correct network to make a delivery from __2__ to __1__ -no-train-has-capacity=Could not find a train with large enough cargo capacity to make a delivery from __2__ to __1__ +no-train-has-capacity=Could not find a train with enough cargo capacity to make a delivery from __2__ to __1__ no-train-matches-r-layout=Could not find a train on the allow-list of __1__ to make a delivery no-train-matches-p-layout=Could not find a train on the allow-list of __2__ to make a delivery to __1__ diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 012c8c2..bf4f4c8 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -40,8 +40,6 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes local r_station = map_data.stations[r_station_id] local p_station = map_data.stations[p_station_id] local train = map_data.trains[train_id] - ---@type string - local network_name = r_station.network_name remove_available_train(map_data, train_id, train) local depot_id = train.parked_at_depot_id @@ -64,17 +62,38 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes r_station.deliveries_total = r_station.deliveries_total + 1 p_station.deliveries_total = p_station.deliveries_total + 1 + local r_is_every = r_station.network_name == NETWORK_EVERY + local p_is_every = p_station.network_name == NETWORK_EVERY for item_i, item in ipairs(manifest) do assert(item.count > 0, "main.lua error, transfer amount was not positive") r_station.deliveries[item.name] = (r_station.deliveries[item.name] or 0) + item.count p_station.deliveries[item.name] = (p_station.deliveries[item.name] or 0) - item.count - if item_i > 1 then + if item_i > 1 or r_is_every or p_is_every then + local f, a + if r_is_every then + f, a = pairs(r_station.network_flag--[[@as {[string]: int}]]) + if p_is_every then + for network_name, _ in f, a do + local item_network_name = network_name..":"..item.name + economy.all_r_stations[item_network_name] = nil + economy.all_p_stations[item_network_name] = nil + end + f, a = pairs(p_station.network_flag--[[@as {[string]: int}]]) + end + elseif p_is_every then + f, a = pairs(p_station.network_flag--[[@as {[string]: int}]]) + else + f, a = once, r_station.network_name + end --prevent deliveries from being processed for these items until their stations are re-polled - local item_network_name = network_name..":"..item.name - economy.all_r_stations[item_network_name] = nil - economy.all_p_stations[item_network_name] = nil + --if we don't wait until they are repolled a duplicate delivery might be generated for stations that share inventories + for network_name, _ in f, a do + local item_network_name = network_name..":"..item.name + economy.all_r_stations[item_network_name] = nil + economy.all_p_stations[item_network_name] = nil + end end end @@ -82,11 +101,11 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes set_comb2(map_data, r_station) if band(p_station.display_state, 4) == 0 then - p_station.display_state = p_station.display_state + 4 + p_station.display_state = 4 update_display(map_data, p_station) end if band(r_station.display_state, 4) == 0 then - r_station.display_state = r_station.display_state + 4 + r_station.display_state = 4 update_display(map_data, r_station) end interface_raise_train_status_changed(train_id, old_status, STATUS_TO_P) @@ -295,6 +314,16 @@ local function tick_dispatch(map_data, mod_settings) local correctness = 0 local closest_to_correct_p_station = nil + local slot_threshold + if is_fluid then + slot_threshold = r_threshold + elseif r_station.is_stack then + slot_threshold = r_threshold + r_threshold = r_threshold*get_stack_size(map_data, item_name) + else + slot_threshold = ceil(r_threshold/get_stack_size(map_data, item_name)) + end + ---@type uint? local p_station_i = nil local best_train_id = nil @@ -304,7 +333,7 @@ local function tick_dispatch(map_data, mod_settings) ---@type uint local j = 1 while j <= #p_stations do - local p_flag, r_flag, netand, slot_threshold, best_p_train_id, best_t_prior, best_t_to_p_dist, effective_count, override_threshold, p_prior, best_p_dist + local p_flag, r_flag, netand, best_p_train_id, best_t_prior, best_t_to_p_dist, effective_count, override_threshold, p_prior, best_p_dist local p_station_id = p_stations[j] local p_station = stations[p_station_id] @@ -325,13 +354,6 @@ local function tick_dispatch(map_data, mod_settings) ---------------------------------------------------------------- -- check for valid train ---------------------------------------------------------------- - if r_station.is_stack and item_type == "item" then - slot_threshold = r_threshold - r_threshold = r_threshold*get_stack_size(map_data, item_name) - else - slot_threshold = is_fluid and r_threshold or ceil(r_threshold/get_stack_size(map_data, item_name)) - end - ---@type uint? best_p_train_id = nil best_t_prior = -INF From a4694742f878bc87223b97c2b40a40f83e7bbfd0 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 17:06:52 -0500 Subject: [PATCH 12/26] fixed display bug --- cybersyn/scripts/central-planning.lua | 59 ++++++++++++++------------- cybersyn/scripts/factorio-api.lua | 10 ++--- cybersyn/scripts/gui.lua | 6 +-- cybersyn/scripts/main.lua | 10 ++--- cybersyn/scripts/migrations.lua | 2 +- 5 files changed, 45 insertions(+), 42 deletions(-) diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index bf4f4c8..1a9a83e 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -24,8 +24,8 @@ function remove_manifest(map_data, station, manifest, sign) end set_comb2(map_data, station) station.deliveries_total = station.deliveries_total - 1 - if station.deliveries_total == 0 and band(station.display_state, 4) > 0 then - station.display_state = station.display_state - 4 + if station.deliveries_total == 0 and band(station.display_state, 1) > 0 then + station.display_state = station.display_state - 1 update_display(map_data, station) end end @@ -100,14 +100,11 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes set_comb2(map_data, p_station) set_comb2(map_data, r_station) - if band(p_station.display_state, 4) == 0 then - p_station.display_state = 4 - update_display(map_data, p_station) - end - if band(r_station.display_state, 4) == 0 then - r_station.display_state = 4 - update_display(map_data, r_station) - end + p_station.display_state = 1 + update_display(map_data, p_station) + r_station.display_state = 1 + update_display(map_data, r_station) + interface_raise_train_status_changed(train_id, old_status, STATUS_TO_P) else interface_raise_train_dispatch_failed(train_id) @@ -244,8 +241,8 @@ local function tick_dispatch(map_data, mod_settings) else for i, id in ipairs(r_stations) do local station = stations[id] - if station and band(station.display_state, 1) == 0 then - station.display_state = station.display_state + 1 + if station and band(station.display_state, 2) == 0 then + station.display_state = station.display_state + 2 update_display(map_data, station) end end @@ -290,8 +287,8 @@ local function tick_dispatch(map_data, mod_settings) if not r_station_i then for _, id in ipairs(r_stations) do local station = stations[id] - if station and band(station.display_state, 1) == 0 then - station.display_state = station.display_state + 1 + if station and band(station.display_state, 2) == 0 then + station.display_state = station.display_state + 2 update_display(map_data, station) end end @@ -303,7 +300,6 @@ local function tick_dispatch(map_data, mod_settings) ---@type string local network_name if r_station.network_name == NETWORK_EVERY then - --TODO: here _, _, network_name = string.find(item_network_name, "(^.*):") else network_name = r_station.network_name @@ -420,23 +416,18 @@ local function tick_dispatch(map_data, mod_settings) effective_count = p_station.item_p_counts[item_name] override_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] - if override_threshold and p_station.is_stack and item_type == "item" then + if override_threshold and p_station.is_stack and not is_fluid then override_threshold = override_threshold*get_stack_size(map_data, item_name) end if effective_count < (override_threshold or r_threshold) then --this p station should have serviced the current r station, lock it so it can't serve any others --this will lock stations even when the r station manages to find a p station, this not a problem because all stations will be unlocked before it could be an issue table_remove(p_stations, j) - if band(p_station.display_state, 2) == 0 then - p_station.display_state = p_station.display_state + 2 + if band(p_station.display_state, 4) == 0 then + p_station.display_state = p_station.display_state + 4 update_display(map_data, p_station) end goto p_continue_remove - else - if band(p_station.display_state, 2) == 1 then - p_station.display_state = p_station.display_state - 2 - update_display(map_data, p_station) - end end p_prior = p_station.priority @@ -476,8 +467,8 @@ local function tick_dispatch(map_data, mod_settings) elseif correctness == 4 then send_alert_no_train_matches_p_layout(r_station.entity_stop, closest_to_correct_p_station.entity_stop) end - if band(r_station.display_state, 1) == 0 then - r_station.display_state = r_station.display_state + 1 + if band(r_station.display_state, 2) == 0 then + r_station.display_state = r_station.display_state + 2 update_display(map_data, r_station) end end @@ -633,9 +624,21 @@ local function tick_poll_station(map_data, mod_settings) end end end - if is_requesting_nothing and band(station.display_state, 1) == 1 then - station.display_state = station.display_state - 1 - update_display(map_data, station) + if station.display_state > 1 then + if is_requesting_nothing and band(station.display_state, 2) == 1 then + station.display_state = station.display_state - 2 + update_display(map_data, station) + end + if band(station.display_state, 8) == 1 then + if band(station.display_state, 4) == 1 then + station.display_state = station.display_state - 4 + else + station.display_state = station.display_state - 8 + update_display(map_data, station) + end + elseif band(station.display_state, 4) == 1 then + station.display_state = station.display_state + 4 + end end end return false diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 1ebce55..0db7739 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -392,12 +392,12 @@ function update_display(map_data, station) local params = control.parameters --NOTE: the following check can cause a bug where the display desyncs if the player changes the operation of the combinator and then changes it back before the mod can notice, however removing it causes a bug where the user's change is overwritten and ignored. Everything's bad we need an event to catch copy-paste by blueprint. if params.operation == MODE_PRIMARY_IO or params.operation == MODE_PRIMARY_IO_ACTIVE or params.operation == MODE_PRIMARY_IO_FAILED_REQUEST then - if station.display_state >= 4 then - params.operation = MODE_PRIMARY_IO_ACTIVE - elseif station.display_state >= 1 then - params.operation = MODE_PRIMARY_IO_FAILED_REQUEST - else + if station.display_state == 0 then params.operation = MODE_PRIMARY_IO + elseif station.display_state%2 == 1 then + params.operation = MODE_PRIMARY_IO_ACTIVE + else + params.operation = MODE_PRIMARY_IO_FAILED_REQUEST end control.parameters = params end diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 753f260..08feb67 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -65,7 +65,7 @@ function gui_opened(comb, player) on_click = {"close", comb.unit_number} }} }}, - {type="frame", name="frame", style="inside_shallow_frame_with_padding", style_mods={padding=12}, children={ + {type="frame", name="frame", style="inside_shallow_frame_with_padding", style_mods={padding=12, bottom_padding=10}, children={ {type="flow", name="vflow", direction="vertical", style_mods={horizontal_align="left"}, children={ --status {type="flow", style="status_flow", direction="horizontal", style_mods={vertical_align="center", horizontally_stretchable=true, bottom_padding=4}, children={ @@ -95,11 +95,11 @@ function gui_opened(comb, player) ---choose-elem-button {type="line", style_mods={top_padding=10}}, {type="label", name="network_label", ref={"network_label"}, style="heading_3_label", caption={"cybersyn-gui.network"}, style_mods={top_padding=8}}, - {type="flow", name="bottom", direction="horizontal", style_mods={vertical_align="center", top_margin=0, top_padding=0}, children={ + {type="flow", name="bottom", direction="horizontal", style_mods={vertical_align="center"}, children={ {type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", ref={"network"}, elem_type="signal", tooltip={"cybersyn-gui.network-tooltip"}, signal=signal, style_mods={bottom_margin=1, right_margin=6}, actions={ on_elem_changed={"choose-elem-button", comb.unit_number} }}, - {type="flow", name="right", direction="vertical", style_mods={horizontal_align="left", top_margin=0, top_padding=0}, children={ + {type="flow", name="right", direction="vertical", style_mods={horizontal_align="left"}, children={ {type="flow", name="allow_list", direction="horizontal", style_mods={vertical_align="center"}, children={ {type="checkbox", name="allow_list", ref={"allow_list"}, state=allow_list, tooltip={"cybersyn-gui.allow-list-tooltip"}, actions={ on_checked_state_changed={"allow_list", comb.unit_number} diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index 7cf274a..edf7211 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -363,12 +363,12 @@ function combinator_update(map_data, comb, reset_display) station = map_data.stations[id] if should_reset and station and station.entity_comb1 == comb then --make sure only MODE_PRIMARY_IO gets stored on map_data.to_comb_params - if station.display_state >= 2 then - params.operation = MODE_PRIMARY_IO_ACTIVE - elseif station.display_state == 1 then - params.operation = MODE_PRIMARY_IO_FAILED_REQUEST - else + if station.display_state == 0 then params.operation = MODE_PRIMARY_IO + elseif station.display_state%2 == 1 then + params.operation = MODE_PRIMARY_IO_ACTIVE + else + params.operation = MODE_PRIMARY_IO_FAILED_REQUEST end control.parameters = params should_reset = false diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index 7329a30..e765c02 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -135,7 +135,7 @@ local migrations_table = { control.parameters = params end for id, station in pairs(map_data.stations) do - station.display_state = (station.display_state >= 2 and 4) + station.display_state%2 + station.display_state = (station.display_state >= 2 and 1) + (station.display_state%2)*2 end end, } From 9282c092675e280fd6f782af2aece409201513a5 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 17:29:53 -0500 Subject: [PATCH 13/26] fixed display bug --- cybersyn/changelog.txt | 2 +- cybersyn/scripts/central-planning.lua | 56 +++++++++++++-------------- cybersyn/scripts/constants.lua | 2 +- cybersyn/scripts/factorio-api.lua | 12 +++--- cybersyn/scripts/global.lua | 4 +- cybersyn/scripts/gui.lua | 6 +-- cybersyn/scripts/main.lua | 4 +- cybersyn/scripts/migrations.lua | 2 +- cybersyn/scripts/train-events.lua | 2 +- 9 files changed, 45 insertions(+), 45 deletions(-) diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index 3f0af66..6463d78 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -4,7 +4,7 @@ Date: 2022-12-22 Changes: - Forced provide stations to wait until they can service the highest priority request station - Provide stations now override request thresholds with the per-item thresholds set by their station info combinator - - Allowed station and fuel combinators to be set to network id "everything", for each virtual signal they recieve as input, the stop is added to that network and its signal strength is used as the network mask + - Allowed station and fuel combinators to be set to network id "each", for each virtual signal they recieve as input, the stop is added to that network and its signal strength is used as the network mask - Added the ability to specify per-station whether request thresholds represent total items or total stacks - Prioritized a train's distance from the provide station over the train's cargo capacity - Added more detailed missing train alerts diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 1a9a83e..654fa58 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -62,19 +62,19 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes r_station.deliveries_total = r_station.deliveries_total + 1 p_station.deliveries_total = p_station.deliveries_total + 1 - local r_is_every = r_station.network_name == NETWORK_EVERY - local p_is_every = p_station.network_name == NETWORK_EVERY + local r_is_each = r_station.network_name == NETWORK_EACH + local p_is_each = p_station.network_name == NETWORK_EACH for item_i, item in ipairs(manifest) do assert(item.count > 0, "main.lua error, transfer amount was not positive") r_station.deliveries[item.name] = (r_station.deliveries[item.name] or 0) + item.count p_station.deliveries[item.name] = (p_station.deliveries[item.name] or 0) - item.count - if item_i > 1 or r_is_every or p_is_every then + if item_i > 1 or r_is_each or p_is_each then local f, a - if r_is_every then + if r_is_each then f, a = pairs(r_station.network_flag--[[@as {[string]: int}]]) - if p_is_every then + if p_is_each then for network_name, _ in f, a do local item_network_name = network_name..":"..item.name economy.all_r_stations[item_network_name] = nil @@ -82,7 +82,7 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes end f, a = pairs(p_station.network_flag--[[@as {[string]: int}]]) end - elseif p_is_every then + elseif p_is_each then f, a = pairs(p_station.network_flag--[[@as {[string]: int}]]) else f, a = once, r_station.network_name @@ -299,7 +299,7 @@ local function tick_dispatch(map_data, mod_settings) local r_station = stations[r_station_id] ---@type string local network_name - if r_station.network_name == NETWORK_EVERY then + if r_station.network_name == NETWORK_EACH then _, _, network_name = string.find(item_network_name, "(^.*):") else network_name = r_station.network_name @@ -337,8 +337,8 @@ local function tick_dispatch(map_data, mod_settings) goto p_continue end - p_flag = p_station.network_name == NETWORK_EVERY and (p_station.network_flag[item_name] or 0) or p_station.network_flag - r_flag = r_station.network_name == NETWORK_EVERY and (r_station.network_flag[item_name] or 0) or r_station.network_flag + p_flag = p_station.network_name == NETWORK_EACH and (p_station.network_flag[item_name] or 0) or p_station.network_flag + r_flag = r_station.network_name == NETWORK_EACH and (r_station.network_flag[item_name] or 0) or r_station.network_flag netand = band(p_flag, r_flag) if netand == 0 then goto p_continue @@ -510,7 +510,7 @@ local function tick_poll_station(map_data, mod_settings) station.priority = 0 station.item_priority = nil station.locked_slots = 0 - if station.network_name == NETWORK_EVERY then + if station.network_name == NETWORK_EACH then station.network_flag = {} else station.network_flag = mod_settings.network_flag @@ -519,6 +519,7 @@ local function tick_poll_station(map_data, mod_settings) station.tick_signals = comb1_signals station.item_p_counts = {} + local is_requesting_nothing = true if comb1_signals then if comb2_signals then station.item_thresholds = {} @@ -552,7 +553,7 @@ local function tick_poll_station(map_data, mod_settings) station.r_threshold = abs(item_count) elseif item_name == LOCKED_SLOTS then station.locked_slots = max(item_count, 0) - elseif station.network_name == NETWORK_EVERY then + elseif station.network_name == NETWORK_EACH then station.network_flag[item_name] = item_count end comb1_signals[k] = nil @@ -565,7 +566,6 @@ local function tick_poll_station(map_data, mod_settings) comb1_signals[k] = nil end end - local is_requesting_nothing = true for k, v in pairs(comb1_signals) do ---@type string local item_name = v.signal.name @@ -583,7 +583,7 @@ local function tick_poll_station(map_data, mod_settings) is_not_requesting = false is_requesting_nothing = false local f, a - if station.network_name == NETWORK_EVERY then + if station.network_name == NETWORK_EACH then f, a = pairs(station.network_flag--[[@as {[string]: int}]]) else f, a = once, station.network_name @@ -604,7 +604,7 @@ local function tick_poll_station(map_data, mod_settings) if is_not_requesting then if station.is_p and effective_item_count > 0 and item_count > 0 then local f, a - if station.network_name == NETWORK_EVERY then + if station.network_name == NETWORK_EACH then f, a = pairs(station.network_flag--[[@as {[string]: int}]]) else f, a = once, station.network_name @@ -624,21 +624,21 @@ local function tick_poll_station(map_data, mod_settings) end end end - if station.display_state > 1 then - if is_requesting_nothing and band(station.display_state, 2) == 1 then - station.display_state = station.display_state - 2 + end + if station.display_state > 1 then + if is_requesting_nothing and band(station.display_state, 2) > 0 then + station.display_state = station.display_state - 2 + update_display(map_data, station) + end + if band(station.display_state, 8) > 0 then + if band(station.display_state, 4) > 0 then + station.display_state = station.display_state - 4 + else + station.display_state = station.display_state - 8 update_display(map_data, station) end - if band(station.display_state, 8) == 1 then - if band(station.display_state, 4) == 1 then - station.display_state = station.display_state - 4 - else - station.display_state = station.display_state - 8 - update_display(map_data, station) - end - elseif band(station.display_state, 4) == 1 then - station.display_state = station.display_state + 4 - end + elseif band(station.display_state, 4) > 0 then + station.display_state = station.display_state + 4 end end return false @@ -664,7 +664,7 @@ local function tick_poll_comb(map_data, mod_settings) --NOTE: the following has undefined behavior if last_comb is deleted local comb_id, comb = next(map_data.to_comb, tick_data.last_comb) tick_data.last_comb = comb_id - local refueler_id, _ = next(map_data.everything_refuelers, tick_data.last_refueler) + local refueler_id, _ = next(map_data.each_refuelers, tick_data.last_refueler) tick_data.last_refueler = refueler_id if comb and comb.valid then diff --git a/cybersyn/scripts/constants.lua b/cybersyn/scripts/constants.lua index 50f750a..1fa7d7a 100644 --- a/cybersyn/scripts/constants.lua +++ b/cybersyn/scripts/constants.lua @@ -23,7 +23,7 @@ MODE_WAGON_MANIFEST = "-" MODE_REFUELER = ">>" NETWORK_SIGNAL_DEFAULT = {name="signal-A", type="virtual"} -NETWORK_EVERY = "signal-everything" +NETWORK_EACH = "signal-each" INACTIVITY_TIME = 100 LOCK_TRAIN_TIME = 60*60*60*24*7 diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 0db7739..ee2303a 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -319,11 +319,11 @@ function set_refueler_from_comb(map_data, mod_settings, id) refueler.allows_all_trains = bit_extract(bits, 2) > 0 refueler.priority = 0 - if refueler.network_name == NETWORK_EVERY then - map_data.everything_refuelers[id] = true + if refueler.network_name == NETWORK_EACH then + map_data.each_refuelers[id] = true refueler.network_flag = {} else - map_data.everything_refuelers[id] = nil + map_data.each_refuelers[id] = nil refueler.network_flag = mod_settings.network_flag end @@ -337,7 +337,7 @@ function set_refueler_from_comb(map_data, mod_settings, id) if item_type == "virtual" then if item_name == SIGNAL_PRIORITY then refueler.priority = item_count - elseif refueler.network_name == NETWORK_EVERY then + elseif refueler.network_name == NETWORK_EACH then refueler.network_flag[item_name] = item_count end end @@ -349,7 +349,7 @@ function set_refueler_from_comb(map_data, mod_settings, id) end local f, a - if old_network == NETWORK_EVERY then + if old_network == NETWORK_EACH then f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) elseif old_network ~= refueler.network_name then f, a = once, old_network @@ -366,7 +366,7 @@ function set_refueler_from_comb(map_data, mod_settings, id) end end - if refueler.network_name == NETWORK_EVERY then + if refueler.network_name == NETWORK_EACH then f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) elseif old_network ~= refueler.network_name then f, a = once, refueler.network_name diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 69597c5..5f75577 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -19,7 +19,7 @@ ---@field public tick_state uint ---@field public tick_data {} ---@field public economy Economy ----@field public everything_refuelers {[uint]: true} +---@field public each_refuelers {[uint]: true} ---@field public active_alerts {[LuaTrain]: int}? ---@field public se_tele_old_id {[string]: uint} @@ -147,7 +147,7 @@ function init_global() global.layout_top_id = 1 global.refuelers = {} global.to_refuelers = {} - global.everything_refuelers = {} + global.each_refuelers = {} IS_SE_PRESENT = remote.interfaces["space-exploration"] ~= nil if IS_SE_PRESENT then diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 08feb67..e2f1d94 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -96,7 +96,7 @@ function gui_opened(comb, player) {type="line", style_mods={top_padding=10}}, {type="label", name="network_label", ref={"network_label"}, style="heading_3_label", caption={"cybersyn-gui.network"}, style_mods={top_padding=8}}, {type="flow", name="bottom", direction="horizontal", style_mods={vertical_align="center"}, children={ - {type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", ref={"network"}, elem_type="signal", tooltip={"cybersyn-gui.network-tooltip"}, signal=signal, style_mods={bottom_margin=1, right_margin=6}, actions={ + {type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", ref={"network"}, elem_type="signal", tooltip={"cybersyn-gui.network-tooltip"}, signal=signal, style_mods={bottom_margin=1, right_margin=6, top_margin=2}, actions={ on_elem_changed={"choose-elem-button", comb.unit_number} }}, {type="flow", name="right", direction="vertical", style_mods={horizontal_align="left"}, children={ @@ -195,8 +195,8 @@ function register_gui_actions() local signal = element.elem_value if signal and (signal.name == "signal-everything" or signal.name == "signal-anything" or signal.name == "signal-each") then if param.operation == MODE_PRIMARY_IO or param.operation == MODE_PRIMARY_IO_ACTIVE or param.operation == MODE_PRIMARY_IO_FAILED_REQUEST or param.operation == MODE_REFUELER then - signal.name = NETWORK_EVERY - element.elem_value.name = NETWORK_EVERY + signal.name = NETWORK_EACH + element.elem_value.name = NETWORK_EACH else signal = nil element.elem_value = nil diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index edf7211..1456ee7 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -76,7 +76,7 @@ local function on_refueler_broken(map_data, refueler_id, refueler) end end local f, a - if refueler.network_name == NETWORK_EVERY then + if refueler.network_name == NETWORK_EACH then f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) else f, a = once, refueler.network_name @@ -90,7 +90,7 @@ local function on_refueler_broken(map_data, refueler_id, refueler) end end end - map_data.everything_refuelers[refueler_id] = nil + map_data.each_refuelers[refueler_id] = nil map_data.refuelers[refueler_id] = nil interface_raise_refueler_removed(refueler_id, refueler) end diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index e765c02..793d67e 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -120,7 +120,7 @@ local migrations_table = { map_data.tick_state = STATE_INIT map_data.tick_data = {} - map_data.everything_refuelers = {} + map_data.each_refuelers = {} for k, comb in pairs(map_data.to_comb) do local control = get_comb_control(comb) diff --git a/cybersyn/scripts/train-events.lua b/cybersyn/scripts/train-events.lua index 76c38ab..e5b85ba 100644 --- a/cybersyn/scripts/train-events.lua +++ b/cybersyn/scripts/train-events.lua @@ -332,7 +332,7 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train) local refueler = map_data.refuelers[id] set_refueler_from_comb(map_data, mod_settings, id) - local refueler_network_flag = refueler.network_name == NETWORK_EVERY and refueler.network_flag[train.network_name] or refueler.network_flag + local refueler_network_flag = refueler.network_name == NETWORK_EACH and refueler.network_flag[train.network_name] or refueler.network_flag if btest(train.network_flag, refueler_network_flag) and (refueler.allows_all_trains or refueler.accepted_layouts[train.layout_id]) and refueler.trains_total < refueler.entity_stop.trains_limit then local accepted = false local dist = nil From 33cd647042fa87a90a0e99b637397aed7c1dbaf6 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 18:52:44 -0500 Subject: [PATCH 14/26] fixed multiple issues --- cybersyn/changelog.txt | 4 +- cybersyn/info.json | 2 +- cybersyn/locale/en/base.cfg | 12 +++--- cybersyn/scripts/central-planning.lua | 8 ++-- cybersyn/scripts/factorio-api.lua | 57 ++++++++++++++++----------- cybersyn/scripts/global.lua | 2 +- cybersyn/scripts/gui.lua | 5 +-- cybersyn/scripts/migrations.lua | 2 +- cybersyn/scripts/train-events.lua | 8 ++-- 9 files changed, 55 insertions(+), 45 deletions(-) diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index 6463d78..00818f9 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -1,6 +1,6 @@ --------------------------------------------------------------------------------------------------- -Version: 1.1.8 -Date: 2022-12-22 +Version: 1.2.0 +Date: 2022-12-23 Changes: - Forced provide stations to wait until they can service the highest priority request station - Provide stations now override request thresholds with the per-item thresholds set by their station info combinator diff --git a/cybersyn/info.json b/cybersyn/info.json index ac57f6b..c3f06d2 100644 --- a/cybersyn/info.json +++ b/cybersyn/info.json @@ -1,6 +1,6 @@ { "name": "cybersyn", - "version": "1.1.7", + "version": "1.2.0", "title": "Project Cybersyn", "author": "Mami", "factorio_version": "1.1", diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index 0d0f195..a6ab8a2 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -45,12 +45,12 @@ cybersyn-locked-slots=Locked slots per cargo wagon [cybersyn-messages] nonempty-train=A train is being held in the depot because it still has cargo unexpected-train=A train has unexpectedly returned to the depot before completing its delivery -stuck-train=A train from depot __1__ is stuck -cannot-path-between-surfaces=A train from depot __1__ is attempting to make a delivery between two unconnected surfaces, perhaps put them on separate networks -depot-broken=A train from depot __1__ is lost because its depot was broken. -refueler-broken=A train from depot __1__ is lost because its refueler was broken. -station-broken=A train from depot __1__ is lost because one of its delivery stations was broken. -train-at-incorrect=A train from depot __1__ is lost; it parked at a station it was not scheduled to delivered to. +stuck-train=A train is stuck +cannot-path-between-surfaces=A train is attempting to make a delivery between two unconnected surfaces, perhaps put them on separate networks +depot-broken=A train is lost because its depot was broken +refueler-broken=A train is lost because its fuel loader was broken +station-broken=A train is lost because one of its delivery stations was broken +train-at-incorrect=A train parked at a station it was not scheduled to delivered to missing-train=Could not find any train on the correct network to make a delivery from __2__ to __1__ no-train-has-capacity=Could not find a train with enough cargo capacity to make a delivery from __2__ to __1__ no-train-matches-r-layout=Could not find a train on the allow-list of __1__ to make a delivery diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 654fa58..88b6714 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -300,7 +300,7 @@ local function tick_dispatch(map_data, mod_settings) ---@type string local network_name if r_station.network_name == NETWORK_EACH then - _, _, network_name = string.find(item_network_name, "(^.*):") + _, _, network_name = string.find(item_network_name, "^(.*):") else network_name = r_station.network_name end @@ -337,8 +337,8 @@ local function tick_dispatch(map_data, mod_settings) goto p_continue end - p_flag = p_station.network_name == NETWORK_EACH and (p_station.network_flag[item_name] or 0) or p_station.network_flag - r_flag = r_station.network_name == NETWORK_EACH and (r_station.network_flag[item_name] or 0) or r_station.network_flag + p_flag = p_station.network_name == NETWORK_EACH and (p_station.network_flag[network_name] or 0) or p_station.network_flag + r_flag = r_station.network_name == NETWORK_EACH and (r_station.network_flag[network_name] or 0) or r_station.network_flag netand = band(p_flag, r_flag) if netand == 0 then goto p_continue @@ -680,7 +680,7 @@ function tick(map_data, mod_settings) map_data.total_ticks = map_data.total_ticks + 1 if map_data.active_alerts then - if map_data.total_ticks%(9*mod_settings.tps) < 1 then + if map_data.total_ticks%(10*mod_settings.tps) < 1 then process_active_alerts(map_data) end end diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index ee2303a..7e9ff56 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -566,7 +566,6 @@ local function send_alert_for_train(train, icon, message) icon, {message}, true) - player.play_sound({path = ALERT_SOUND}) end end end @@ -623,7 +622,7 @@ local send_stuck_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} function send_alert_stuck_train(map_data, train) send_alert_for_train(train, send_stuck_train_alert_icon, "cybersyn-messages.stuck-train") map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train] = 1 + map_data.active_alerts[train.id] = {train, 1} end local send_nonempty_train_in_depot_alert_icon = {name = NONEMPTY_TRAIN_NAME, type = "fluid"} @@ -631,8 +630,9 @@ local send_nonempty_train_in_depot_alert_icon = {name = NONEMPTY_TRAIN_NAME, typ ---@param train LuaTrain function send_alert_nonempty_train_in_depot(map_data, train) send_alert_for_train(train, send_nonempty_train_in_depot_alert_icon, "cybersyn-messages.nonempty-train") + send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train] = 2 + map_data.active_alerts[train.id] = {train, 2} end local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} @@ -640,36 +640,41 @@ local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} ---@param train LuaTrain function send_alert_depot_of_train_broken(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.depot-broken") + send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train] = 3 + map_data.active_alerts[train.id] = {train, 3} end ---@param map_data MapData ---@param train LuaTrain function send_alert_station_of_train_broken(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.station-broken") + send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train] = 4 + map_data.active_alerts[train.id] = {train, 4} end ---@param map_data MapData ---@param train LuaTrain function send_alert_refueler_of_train_broken(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.refueler-broken") + send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train] = 5 + map_data.active_alerts[train.id] = {train, 5} end ---@param map_data MapData ---@param train LuaTrain function send_alert_train_at_incorrect_station(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.train-at-incorrect") + send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train] = 6 + map_data.active_alerts[train.id] = {train, 6} end ---@param map_data MapData ---@param train LuaTrain function send_alert_cannot_path_between_surfaces(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.cannot-path-between-surfaces") + send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train] = 7 + map_data.active_alerts[train.id] = {train, 7} end ---@param train LuaTrain @@ -680,21 +685,27 @@ end ---@param map_data MapData function process_active_alerts(map_data) - for train, id in pairs(map_data.active_alerts) do - if id == 1 then - send_alert_for_train(train, send_stuck_train_alert_icon, "cybersyn-messages.stuck-train") - elseif id == 2 then - send_alert_for_train(train, send_nonempty_train_in_depot_alert_icon, "cybersyn-messages.nonempty-train") - elseif id == 3 then - send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.depot-broken") - elseif id == 4 then - send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.station-broken") - elseif id == 5 then - send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.refueler-broken") - elseif id == 6 then - send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.train-at-incorrect") - elseif id == 7 then - send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.cannot-path-between-surfaces") + for train_id, data in pairs(map_data.active_alerts) do + local train = data[1] + if train.valid then + local id = data[2] + if id == 1 then + send_alert_for_train(train, send_stuck_train_alert_icon, "cybersyn-messages.stuck-train") + elseif id == 2 then + send_alert_for_train(train, send_nonempty_train_in_depot_alert_icon, "cybersyn-messages.nonempty-train") + elseif id == 3 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.depot-broken") + elseif id == 4 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.station-broken") + elseif id == 5 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.refueler-broken") + elseif id == 6 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.train-at-incorrect") + elseif id == 7 then + send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.cannot-path-between-surfaces") + end + else + map_data.active_alerts[train_id] = nil end end end diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 5f75577..a267061 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -20,7 +20,7 @@ ---@field public tick_data {} ---@field public economy Economy ---@field public each_refuelers {[uint]: true} ----@field public active_alerts {[LuaTrain]: int}? +---@field public active_alerts {[uint]: {[1]: LuaTrain, [2]: int}}? ---@field public se_tele_old_id {[string]: uint} ---@class Station diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index e2f1d94..1fd1cb9 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -65,7 +65,7 @@ function gui_opened(comb, player) on_click = {"close", comb.unit_number} }} }}, - {type="frame", name="frame", style="inside_shallow_frame_with_padding", style_mods={padding=12, bottom_padding=10}, children={ + {type="frame", name="frame", style="inside_shallow_frame_with_padding", style_mods={padding=12, bottom_padding=9}, children={ {type="flow", name="vflow", direction="vertical", style_mods={horizontal_align="left"}, children={ --status {type="flow", style="status_flow", direction="horizontal", style_mods={vertical_align="center", horizontally_stretchable=true, bottom_padding=4}, children={ @@ -196,11 +196,10 @@ function register_gui_actions() if signal and (signal.name == "signal-everything" or signal.name == "signal-anything" or signal.name == "signal-each") then if param.operation == MODE_PRIMARY_IO or param.operation == MODE_PRIMARY_IO_ACTIVE or param.operation == MODE_PRIMARY_IO_FAILED_REQUEST or param.operation == MODE_REFUELER then signal.name = NETWORK_EACH - element.elem_value.name = NETWORK_EACH else signal = nil - element.elem_value = nil end + element.elem_value = signal end set_comb_network_name(comb, signal) diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index 793d67e..4507bff 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -114,7 +114,7 @@ local migrations_table = { end end end, - ["1.1.8"] = function() + ["1.2.0"] = function() ---@type MapData local map_data = global map_data.tick_state = STATE_INIT diff --git a/cybersyn/scripts/train-events.lua b/cybersyn/scripts/train-events.lua index e5b85ba..1141834 100644 --- a/cybersyn/scripts/train-events.lua +++ b/cybersyn/scripts/train-events.lua @@ -332,7 +332,7 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train) local refueler = map_data.refuelers[id] set_refueler_from_comb(map_data, mod_settings, id) - local refueler_network_flag = refueler.network_name == NETWORK_EACH and refueler.network_flag[train.network_name] or refueler.network_flag + local refueler_network_flag = refueler.network_name == NETWORK_EACH and (refueler.network_flag[train.network_name] or 0) or refueler.network_flag if btest(train.network_flag, refueler_network_flag) and (refueler.allows_all_trains or refueler.accepted_layouts[train.layout_id]) and refueler.trains_total < refueler.entity_stop.trains_limit then local accepted = false local dist = nil @@ -419,15 +419,15 @@ end function on_train_changed(event) local train_e = event.train--[[@as LuaTrain]] if not train_e.valid then return end + local train_id = train_e.id - if global.active_alerts and global.active_alerts[train_e] then - global.active_alerts[train_e] = nil + if global.active_alerts and global.active_alerts[train_id] then + global.active_alerts[train_id] = nil if next(global.active_alerts) == nil then global.active_alerts = nil end end - local train_id = train_e.id if train_e.state == defines.train_state.wait_station then local stop = train_e.station if stop and stop.valid and stop.name == "train-stop" then From 253ee7cbe0df426b5b124dfddeb848a60e616cb3 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 19:04:52 -0500 Subject: [PATCH 15/26] fixed persistent alerts --- cybersyn/scripts/factorio-api.lua | 14 +++++++------- cybersyn/scripts/train-events.lua | 15 +++++++++++---- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 7e9ff56..70477c5 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -622,7 +622,7 @@ local send_stuck_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} function send_alert_stuck_train(map_data, train) send_alert_for_train(train, send_stuck_train_alert_icon, "cybersyn-messages.stuck-train") map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train.id] = {train, 1} + map_data.active_alerts[train.id] = {train, 1, map_data.total_ticks} end local send_nonempty_train_in_depot_alert_icon = {name = NONEMPTY_TRAIN_NAME, type = "fluid"} @@ -632,7 +632,7 @@ function send_alert_nonempty_train_in_depot(map_data, train) send_alert_for_train(train, send_nonempty_train_in_depot_alert_icon, "cybersyn-messages.nonempty-train") send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train.id] = {train, 2} + map_data.active_alerts[train.id] = {train, 2, map_data.total_ticks} end local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} @@ -642,7 +642,7 @@ function send_alert_depot_of_train_broken(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.depot-broken") send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train.id] = {train, 3} + map_data.active_alerts[train.id] = {train, 3, map_data.total_ticks} end ---@param map_data MapData ---@param train LuaTrain @@ -650,7 +650,7 @@ function send_alert_station_of_train_broken(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.station-broken") send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train.id] = {train, 4} + map_data.active_alerts[train.id] = {train, 4, map_data.total_ticks} end ---@param map_data MapData ---@param train LuaTrain @@ -658,7 +658,7 @@ function send_alert_refueler_of_train_broken(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.refueler-broken") send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train.id] = {train, 5} + map_data.active_alerts[train.id] = {train, 5, map_data.total_ticks} end ---@param map_data MapData ---@param train LuaTrain @@ -666,7 +666,7 @@ function send_alert_train_at_incorrect_station(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.train-at-incorrect") send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train.id] = {train, 6} + map_data.active_alerts[train.id] = {train, 6, map_data.total_ticks} end ---@param map_data MapData ---@param train LuaTrain @@ -674,7 +674,7 @@ function send_alert_cannot_path_between_surfaces(map_data, train) send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.cannot-path-between-surfaces") send_alert_sounds(train) map_data.active_alerts = map_data.active_alerts or {} - map_data.active_alerts[train.id] = {train, 7} + map_data.active_alerts[train.id] = {train, 7, map_data.total_ticks} end ---@param train LuaTrain diff --git a/cybersyn/scripts/train-events.lua b/cybersyn/scripts/train-events.lua index 1141834..113bb20 100644 --- a/cybersyn/scripts/train-events.lua +++ b/cybersyn/scripts/train-events.lua @@ -421,10 +421,17 @@ function on_train_changed(event) if not train_e.valid then return end local train_id = train_e.id - if global.active_alerts and global.active_alerts[train_id] then - global.active_alerts[train_id] = nil - if next(global.active_alerts) == nil then - global.active_alerts = nil + if global.active_alerts then + --remove the alert if the train is interacted with at all + local data = global.active_alerts[train_id] + if data then + --we need to wait for the train to come to a stop from being locked + if data[3] + 10*mod_settings.tps < global.total_ticks then + global.active_alerts[train_id] = nil + if next(global.active_alerts) == nil then + global.active_alerts = nil + end + end end end From dba8eef1d5a5ef2f914ff97536e493dc361f51fa Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 19:08:28 -0500 Subject: [PATCH 16/26] updated locale --- cybersyn/locale/en/base.cfg | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index a6ab8a2..9870edd 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -66,10 +66,10 @@ comb2=Station info wagon-manifest=Wagon info network=Network network-tooltip=A signal is used to identify which network this combinator is a member of. Trains will only be dispatched from depots to provider and requester stations if they are all identified with the same signal. -allow-list-description=Automatic train allow-list +allow-list-description=Automatic allow-list allow-list-tooltip=When checked trains in the network are automatically added to the allow-list if every wagon of the train is able to be loaded or unloaded by this station. When unchecked the allow-list is not used and all trains are allowed to park here. -is-stack-description=Enable stack thresholds -is-stack-tooltip=When checked all request thresholds for this station are interpretted as a count of item stacks rather than a count of total items. Fluid thresholds are unaffected. +is-stack-description=Stack thresholds +is-stack-tooltip=When checked all request thresholds for this station are interpretted as a count of item stacks rather than a count of total items. Thresholds for fluids are unaffected. switch-provide=Provide only switch-request=Request only switch-provide-tooltip=Lock this station to only provide items to the network. By default it both requests and provides. From 022ba834c765bd7ded4d442b007538bb11dfb383 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 20:10:24 -0500 Subject: [PATCH 17/26] fixed layout memory leak --- cybersyn/changelog.txt | 1 + cybersyn/scripts/layout.lua | 13 +++++++++++++ cybersyn/scripts/migrations.lua | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index 00818f9..d012120 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -11,6 +11,7 @@ Date: 2022-12-23 - Nonempty trains in depot are no longer put in manual mode, instead they are forced to park at the depot - Made several alerts persistent - Fixed bug with depot priority not working + - Fixed a memory leak relating to train layouts --------------------------------------------------------------------------------------------------- Version: 1.1.7 Date: 2022-12-17 diff --git a/cybersyn/scripts/layout.lua b/cybersyn/scripts/layout.lua index 30baf6b..a598350 100644 --- a/cybersyn/scripts/layout.lua +++ b/cybersyn/scripts/layout.lua @@ -87,6 +87,19 @@ function remove_train(map_data, train_id, train) depot.available_train_id = nil end remove_available_train(map_data, train_id, train) + + local layout_id = train.layout_id + local count = global.layout_train_count[layout_id] + if count <= 1 then + global.layout_train_count[layout_id] = nil + global.layouts[layout_id] = nil + for _, station in pairs(global.stations) do + station.accepted_layouts[layout_id] = nil + end + else + global.layout_train_count[layout_id] = count - 1 + end + map_data.trains[train_id] = nil interface_raise_train_removed(train_id, train) end diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index 4507bff..737448d 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -135,7 +135,20 @@ local migrations_table = { control.parameters = params end for id, station in pairs(map_data.stations) do - station.display_state = (station.display_state >= 2 and 1) + (station.display_state%2)*2 + station.display_state = (station.display_state >= 2 and 1 or 0) + (station.display_state%2)*2 + end + + map_data.layout_train_count = {} + for id, train in pairs(map_data.trains) do + map_data.layout_train_count[train.layout_id] = (map_data.layout_train_count[train.layout_id] or 0) + 1 + end + for layout_id, _ in pairs(map_data.layouts) do + if not map_data.layout_train_count[layout_id] then + map_data.layouts[layout_id] = nil + for id, station in pairs(map_data.stations) do + station.accepted_layouts[layout_id] = nil + end + end end end, } From 2a57d94e9d1847dffa8f67050c68a47c45f7d23d Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 20:13:36 -0500 Subject: [PATCH 18/26] fixed migration bug --- cybersyn/scripts/migrations.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index 737448d..e368c7b 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -13,7 +13,7 @@ local migrations_table = { local map_data = global map_data.tick_state = STATE_INIT map_data.tick_data = {} - for k, v in pairs(map_data.available_trains) do + for k, v in pairs(map_data.trains_available) do for id, _ in pairs(v) do local train = map_data.trains[id] train.is_available = true From c1d2a3dab9c88fec935175d8884ea36fb0f8e032 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 20:41:31 -0500 Subject: [PATCH 19/26] undid migrations edit --- cybersyn/scripts/migrations.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index e368c7b..737448d 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -13,7 +13,7 @@ local migrations_table = { local map_data = global map_data.tick_state = STATE_INIT map_data.tick_data = {} - for k, v in pairs(map_data.trains_available) do + for k, v in pairs(map_data.available_trains) do for id, _ in pairs(v) do local train = map_data.trains[id] train.is_available = true From 96baf62c39b78a04bbd548c54414d46b7aaacf17 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 20:48:20 -0500 Subject: [PATCH 20/26] improved SE compat --- TODO | 1 - cybersyn/changelog.txt | 2 ++ cybersyn/info.json | 2 +- cybersyn/scripts/global.lua | 4 ---- cybersyn/scripts/main.lua | 4 +--- cybersyn/scripts/migrations.lua | 1 + 6 files changed, 5 insertions(+), 9 deletions(-) diff --git a/TODO b/TODO index aa08128..01dcfc5 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,4 @@ bugs: - fix crash in submitted massively modded world check for bugs in new player's submitted world find se bug https://mods.factorio.com/mod/cybersyn/discussion/639d1ea26f00ecfa7b048da0 https://mods.factorio.com/mod/cybersyn/discussion/63a52e54be4341bccc0446f8 diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index d012120..e260049 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -12,6 +12,8 @@ Date: 2022-12-23 - Made several alerts persistent - Fixed bug with depot priority not working - Fixed a memory leak relating to train layouts + - Fixed a rare crash when building stations + - Slightly improved compat with SE thanks to a bugfix in 0.6.94 --------------------------------------------------------------------------------------------------- Version: 1.1.7 Date: 2022-12-17 diff --git a/cybersyn/info.json b/cybersyn/info.json index c3f06d2..aff5c6b 100644 --- a/cybersyn/info.json +++ b/cybersyn/info.json @@ -8,7 +8,7 @@ "dependencies": [ "base", "flib >= 0.6.0", - "? space-exploration >= 0.6.90", + "? space-exploration >= 0.6.94", "? miniloader", "? nullius", "? pypostprocessing" diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index a267061..5ddba18 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -21,7 +21,6 @@ ---@field public economy Economy ---@field public each_refuelers {[uint]: true} ---@field public active_alerts {[uint]: {[1]: LuaTrain, [2]: int}}? ----@field public se_tele_old_id {[string]: uint} ---@class Station ---@field public entity_stop LuaEntity @@ -150,9 +149,6 @@ function init_global() global.each_refuelers = {} IS_SE_PRESENT = remote.interfaces["space-exploration"] ~= nil - if IS_SE_PRESENT then - global.se_tele_old_id = {} - end end ---@param v string diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index 1456ee7..8a4f804 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -695,7 +695,6 @@ local function setup_se_compat() if not train then return end --NOTE: IMPORTANT, until se_on_train_teleport_finished_event is called map_data.trains[old_id] will reference an invalid train entity; our events have either been set up to account for this or should be impossible to trigger until teleportation is finished train.se_is_being_teleported = true - map_data.se_tele_old_id[train_unique_identifier] = old_id interface_raise_train_teleport_started(old_id) end) ---@param event {} @@ -711,8 +710,7 @@ local function setup_se_compat() --NOTE: event.old_train_id_1 from this event is useless, it's for one of the many transient trains SE spawns while teleporting the old train, only se_on_train_teleport_started_event returns the correct old train id --NOTE: please SE dev if you read this fix the issue where se_on_train_teleport_finished_event is returning the wrong old train id - local old_id = map_data.se_tele_old_id[train_unique_identifier] - map_data.se_tele_old_id[train_unique_identifier] = nil + local old_id = event.old_train_id_1 local train = map_data.trains[old_id] if not train then return end diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index 737448d..27bd7b3 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -121,6 +121,7 @@ local migrations_table = { map_data.tick_data = {} map_data.each_refuelers = {} + map_data.se_tele_old_id = nil for k, comb in pairs(map_data.to_comb) do local control = get_comb_control(comb) From 5adf211342ec6b4e226d7475e8b16442902f7e9e Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 21:02:56 -0500 Subject: [PATCH 21/26] added null check --- cybersyn/scripts/factorio-api.lua | 60 ++++++++++++++++--------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 70477c5..1488359 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -181,37 +181,39 @@ function set_manifest_schedule(map_data, train, depot_name, d_surface_i, p_stop, if (is_p_on_t or p_surface_i == other_surface_i) and (is_r_on_t or r_surface_i == other_surface_i) and (is_d_on_t or d_surface_i == other_surface_i) then local t_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = t_surface_i})--[[@as {}]] local other_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = other_surface_i})--[[@as {}]] - local is_train_in_orbit = other_zone.orbit_index == t_zone.index - if is_train_in_orbit or t_zone.orbit_index == other_zone.index then - local elevator_name = se_get_space_elevator_name(t_surface) - if elevator_name then - local records = {create_inactivity_order(depot_name)} - if t_surface_i == p_surface_i then - records[#records + 1] = create_direct_to_station_order(p_stop) - else - records[#records + 1] = se_create_elevator_order(elevator_name, is_train_in_orbit) - is_train_in_orbit = not is_train_in_orbit - end - records[#records + 1] = create_loading_order(p_stop, manifest) + if t_zone and other_zone then + local is_train_in_orbit = other_zone.orbit_index == t_zone.index + if is_train_in_orbit or t_zone.orbit_index == other_zone.index then + local elevator_name = se_get_space_elevator_name(t_surface) + if elevator_name then + local records = {create_inactivity_order(depot_name)} + if t_surface_i == p_surface_i then + records[#records + 1] = create_direct_to_station_order(p_stop) + else + records[#records + 1] = se_create_elevator_order(elevator_name, is_train_in_orbit) + is_train_in_orbit = not is_train_in_orbit + end + records[#records + 1] = create_loading_order(p_stop, manifest) - if p_surface_i ~= r_surface_i then - records[#records + 1] = se_create_elevator_order(elevator_name, is_train_in_orbit) - is_train_in_orbit = not is_train_in_orbit - elseif t_surface_i == r_surface_i then - records[#records + 1] = create_direct_to_station_order(r_stop) - end - records[#records + 1] = create_unloading_order(r_stop) - if r_surface_i ~= d_surface_i then - records[#records + 1] = se_create_elevator_order(elevator_name, is_train_in_orbit) - is_train_in_orbit = not is_train_in_orbit - end + if p_surface_i ~= r_surface_i then + records[#records + 1] = se_create_elevator_order(elevator_name, is_train_in_orbit) + is_train_in_orbit = not is_train_in_orbit + elseif t_surface_i == r_surface_i then + records[#records + 1] = create_direct_to_station_order(r_stop) + end + records[#records + 1] = create_unloading_order(r_stop) + if r_surface_i ~= d_surface_i then + records[#records + 1] = se_create_elevator_order(elevator_name, is_train_in_orbit) + is_train_in_orbit = not is_train_in_orbit + end - train.schedule = {current = start_at_depot and 1 or 2--[[@as uint]], records = records} - if old_schedule and not train.has_path then - train.schedule = old_schedule - return false - else - return true + train.schedule = {current = start_at_depot and 1 or 2--[[@as uint]], records = records} + if old_schedule and not train.has_path then + train.schedule = old_schedule + return false + else + return true + end end end end From dd8b0b234281768dd6b7ef03433ac9d0634ab7f2 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 21:21:03 -0500 Subject: [PATCH 22/26] fixed strange desync bug --- TODO | 2 -- cybersyn/changelog.txt | 1 + cybersyn/scripts/migrations.lua | 25 +++++-------------------- 3 files changed, 6 insertions(+), 22 deletions(-) diff --git a/TODO b/TODO index 01dcfc5..3656c83 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,4 @@ bugs: - check for bugs in new player's submitted world - find se bug https://mods.factorio.com/mod/cybersyn/discussion/639d1ea26f00ecfa7b048da0 https://mods.factorio.com/mod/cybersyn/discussion/63a52e54be4341bccc0446f8 major: diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index e260049..bd81c8f 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -13,6 +13,7 @@ Date: 2022-12-23 - Fixed bug with depot priority not working - Fixed a memory leak relating to train layouts - Fixed a rare crash when building stations + - Fixed a bug where automatic allow-list sometimes could not be turned off - Slightly improved compat with SE thanks to a bugfix in 0.6.94 --------------------------------------------------------------------------------------------------- Version: 1.1.7 diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index 27bd7b3..f922710 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -2,17 +2,9 @@ local flib_migration = require("__flib__.migration") local migrations_table = { - ["1.0.3"] = function() - ---@type MapData - local map_data = global - map_data.tick_state = STATE_INIT - map_data.tick_data = {} - end, ["1.0.6"] = function() ---@type MapData local map_data = global - map_data.tick_state = STATE_INIT - map_data.tick_data = {} for k, v in pairs(map_data.available_trains) do for id, _ in pairs(v) do local train = map_data.trains[id] @@ -29,8 +21,6 @@ local migrations_table = { ["1.0.7"] = function() ---@type MapData local map_data = global - map_data.tick_state = STATE_INIT - map_data.tick_data = {} map_data.available_trains = {} for id, v in pairs(map_data.trains) do v.parked_at_depot_id = v.depot_id @@ -53,8 +43,6 @@ local migrations_table = { ["1.0.8"] = function() ---@type MapData local map_data = global - map_data.tick_state = STATE_INIT - map_data.tick_data = {} for id, station in pairs(map_data.stations) do local params = get_comb_params(station.entity_comb1) if params.operation == MODE_PRIMARY_IO_FAILED_REQUEST then @@ -71,8 +59,6 @@ local migrations_table = { ["1.1.0"] = function() ---@type MapData local map_data = global - map_data.tick_state = STATE_INIT - map_data.tick_data = {} map_data.refuelers = {} map_data.to_refuelers = {} for id, station in pairs(map_data.stations) do @@ -98,16 +84,12 @@ local migrations_table = { ["1.1.2"] = function() ---@type MapData local map_data = global - map_data.tick_state = STATE_INIT - map_data.tick_data = {} map_data.refuelers = map_data.refuelers or {} map_data.to_refuelers = map_data.to_refuelers or {} end, ["1.1.3"] = function() ---@type MapData local map_data = global - map_data.tick_state = STATE_INIT - map_data.tick_data = {} for k, v in pairs(map_data.refuelers) do if not v.entity_comb.valid or not v.entity_stop.valid then map_data.refuelers[k] = nil @@ -117,8 +99,6 @@ local migrations_table = { ["1.2.0"] = function() ---@type MapData local map_data = global - map_data.tick_state = STATE_INIT - map_data.tick_data = {} map_data.each_refuelers = {} map_data.se_tele_old_id = nil @@ -137,6 +117,9 @@ local migrations_table = { end for id, station in pairs(map_data.stations) do station.display_state = (station.display_state >= 2 and 1 or 0) + (station.display_state%2)*2 + + set_station_from_comb_state(station) + update_stop_if_auto(map_data, station, true) end map_data.layout_train_count = {} @@ -157,6 +140,8 @@ local migrations_table = { ---@param data ConfigurationChangedData function on_config_changed(data) + global.tick_state = STATE_INIT + global.tick_data = {} flib_migration.on_config_changed(data, migrations_table) IS_SE_PRESENT = remote.interfaces["space-exploration"] ~= nil From 87f55f46314c25f9a0f529ecab5270ebb5dcc464 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 22:05:59 -0500 Subject: [PATCH 23/26] updated readme and fixed minor exploit --- README.md | 18 +++++++++++++----- TODO | 1 + cybersyn/scripts/gui.lua | 7 +++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f1b9a5b..124042f 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ If you like my work, consider supporting me on [ko-fi](https://ko-fi.com/lesbian ## Mod Details -This mod adds a single new entity to the game, the cybernetic combinator. This combinator can be in one of 5 different possible control modes. While each mode has a purpose, the only modes you have to use are primary station control and depot control. +This mod adds a single new entity to the game, the cybernetic combinator. This combinator can be in one of 5 different possible control modes. While each mode has a purpose, the only modes you are required to use are station mode and depot mode. ### Station mode @@ -91,7 +91,11 @@ Fuel loaders can automatically build allow-lists. When this option is enabled, t ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/science.png) -When placed adjacent to the train stop of an already existing Cybersyn station, this combinator will provide a second set of inputs and outputs that can be used to more precisely control this station. The combinator input allows for request thresholds to be set per-item. Any non-zero item signal given on the input circuit network will override the station's request thresholds for just that item. The output of the combinator gives the sum total of all item loading or unloading orders in progress for the station. The very tick a train is dispatched for a new order to the station, that order is added to the output of this combinator, and it is removed as soon as the train leaves the station. The primary use case for this is to prevent duplicate orders from being generated for stations that provide the same pool of items. Only one train can be dispatched per-tick per-item specifically to accommodate this. +When placed adjacent to the train stop of an already existing Cybersyn station, this combinator will provide a second set of inputs and outputs that can be used to more precisely control this station. The combinator input allows for request thresholds to be set per-item. Any non-zero item signal given on the input circuit network will override the station's request thresholds for just that item. When this is used on a provider station, if the station has more items than the input threshold, it will force the creation of a delivery for that item to the next available requester station. This effectively overrides the requester station's request threshold. This is useful for purging unwanted items from provider stations. + +If a station info combinator receives a "priority" signal as input, it will apply that priority to each item signal it is receiving as input. This allows you to specify up to 2 different priorities per-item on a single station. + +The output of the combinator gives the sum total of all item loading or unloading orders in progress for the station. The very tick a train is dispatched for a new order to the station, that order is added to the output of this combinator, and it is removed as soon as the train leaves the station. The primary use case for this is to prevent duplicate orders from being generated for stations that provide the same pool of items. Only one train can be dispatched per-tick per-item specifically to accommodate this. ### Wagon info mode @@ -103,15 +107,19 @@ When placed adjacent to the tracks of an already existing Cybersyn station, this ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/gui-network.png) -Stations and depots can be set to belong to a particular network by setting that network on the control combinator. By default all combinators belong to the "signal-A" network. By setting a different signal Id, the combinator will belong to that different network. Networks identified with different signal Ids do not share any trains or items; Orders will never be generated to transfer items between separate networks. +Stations, depots and fuel loaders can be set to belong to a particular network by setting that network on the control combinator. By default all combinators belong to the "signal-A" network. By setting a different signal Id, the combinator will belong to that different network. Networks identified with different signal Ids do not share any trains or items; Orders will never be generated to transfer items between separate networks. In addition, if the combinator receives as input a signal of the same Id as its network signal Id, then the value of this signal will be interpreted as a bitmask to give 32 "sub-networks" to choose from. Each station can belong to any set of sub-networks based on its mask. A delivery will only be made between two stations if any two bits match between the two masks, i.e. if `mask1 & mask2 > 0`. When a network Id is an item, that item will be ignored by stations, its signal will only ever be interpreted as the network mask. +Stations and fuel loader combinators allow their network to be set to the "each" virtual signal. When in this mode, each virtual signal given to them as input is interpretted as a network mask for that network Id. The station or fuel loader is thus made a part of that network with the specified network mask. This allows you to union together as many different networks as you would like. + ### Request threshold ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/virtual-signals.png) -If a primary station control combinator receives a request threshold signal as input, a request order for the station will only be generated if the station is requesting a number of items exceeding the request threshold. In addition, there must be a station in the network which is providing at least as many items as the request threshold, and there must be a train in the network that has cargo capacity exceeding the request threshold. Through this logic all generated orders must be for a number of items greater than or equal to the request threshold. By setting high thresholds, the traffic on your network can be greatly reduced, at the cost of needing to maintain larger item buffers at each station. There is no "provide threshold" in this mod because by design there is almost no need for one. If desired a provide threshold can be simulated with a single decider combinator. The request threshold signal sets the request threshold "per-station" whereas the optional station control combinator can set or override the threshold per-item as well. +If a station control combinator receives a request threshold signal as input, a request order for the station will only be generated if the station is requesting a number of items exceeding the request threshold. In addition, there must be a station in the network which is providing at least as many items as the request threshold, and there must be a train in the network that has cargo capacity exceeding the request threshold. Through this logic all generated orders must be for a number of items greater than or equal to the request threshold. By setting high thresholds, the traffic on your network can be greatly reduced, at the cost of needing to maintain larger item buffers at each station. There is no "provide threshold" in this mod because by design there is almost no need for one. If desired a provide threshold can be simulated with a single decider combinator. The request threshold signal sets the request threshold "per-station" whereas the optional station control combinator can set or override the threshold per-item as well. + +On station combinators their is a setting called "Stack thresholds". When set, any request threshold for this station will be multiplied by the stack size of any item it is being compared to. This applies to station info thresholds as well. Thus the request threshold can be specified based on total stack count rather than total item count. Fluids are unaffected by the "Stack thresholds" setting, they are always specified by total fluid count. ### Locked slots per cargo wagon @@ -119,7 +127,7 @@ After an order has been generated, enough items will be subtracted from that ord ### Priority -Orders will be generated first for stations, depots and fuel loaders which are receiving a higher priority signal than the others. If stations have the same priority, the least recently used requester station will be prioritized, and the provider station closest to the requester station will be prioritized. So in times of item shortage (front-pressure), round robin distribution will be used, and in times of item surplus (back-pressure), minimum travel distance distribution will be used. +Orders will be generated first for stations, depots and fuel loaders which are receiving a higher priority signal than the others. If stations have the same priority, the least recently used requester station will be prioritized, and the provider station closest to the requester station will be prioritized. So in times of item shortage (front-pressure), round robin distribution will be used, and in times of item surplus (back-pressure), minimum travel distance distribution will be used. Provider stations will be prevented from providing items to lower priority requester stations until the highest priority requester station is satisfied. If a combinator set to station info mode receives a priority signal, for each item signal input to the combinator, items of that type will have its priority overridden in addition to its request threshold. This effectively allows you to choose one of two possible priorities for each item that a station processes. diff --git a/TODO b/TODO index 3656c83..540d57c 100644 --- a/TODO +++ b/TODO @@ -8,6 +8,7 @@ major: models & art minor: + handle if signals are removed from the game during migration railloader compat close gui when the combinator is destroyed do not play close sound when a different gui is opened diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 1fd1cb9..018d86f 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -173,6 +173,13 @@ function register_gui_actions() set_comb_operation(comb, MODE_PRIMARY_IO) elseif element.selected_index == 2 then set_comb_operation(comb, MODE_DEPOT) + --prevent the use of the each signal with depots + local network = element.parent.parent.bottom.network + local signal = network.elem_value + if signal.name == NETWORK_EACH then + network.elem_value = nil + set_comb_network_name(comb, nil) + end elseif element.selected_index == 3 then set_comb_operation(comb, MODE_REFUELER) elseif element.selected_index == 4 then From de5f465910b10882eac9a23d97127aadb7061b5c Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 22:13:42 -0500 Subject: [PATCH 24/26] fixed inconsistent naming --- README.md | 22 +++++++++++----------- cybersyn/changelog.txt | 4 ++-- cybersyn/locale/en/base.cfg | 8 ++++---- cybersyn/scripts/constants.lua | 2 +- cybersyn/scripts/factorio-api.lua | 2 +- cybersyn/scripts/gui.lua | 2 +- cybersyn/scripts/layout.lua | 2 +- cybersyn/scripts/main.lua | 4 ++-- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 124042f..0b88d7b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Behold one of the most feature-rich and performant train logistics network mods Within Project Cybersyn, you can think of requester stations as requester chests, provider stations as passive provider chests, depots as roboports and trains as the logistics bots. There is a direct correspondence between the Cybersyn train network and Factorio's robot logistics network. -A bare minimum Cybersyn train network consists of 2 components: depots and stations. Both are created by placing a cybernetic combinator adjacent to a train stop. Select the "Control Mode" of the combinator to "Station" to create a station, and to "Depot" to create a depot. Create a basic train and order it to park at the depot you just created, it is now controlled by the Cybersyn network. Depots and stations can have any train stop name, names do not impact their function. The circuit network input of a station's cybernetic combinator determines what items that station will request or provide to the Cybersyn network. A positive item signal is interpreted as that station providing that item to the network; A negative item signal is interpreted as that station requesting that item from the network. +A bare minimum Cybersyn train network consists of 2 components: depots and stations. Both are created by placing a cybernetic combinator adjacent to a train stop. Select the "Mode" of the combinator to "Station" to create a station, and to "Depot" to create a depot. Create a basic train and order it to park at the depot you just created, it is now controlled by the Cybersyn network. Depots and stations can have any train stop name, names do not impact their function. The circuit network input of a station's cybernetic combinator determines what items that station will request or provide to the Cybersyn network. A positive item signal is interpreted as that station providing that item to the network; A negative item signal is interpreted as that station requesting that item from the network. ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/basic-provider.png) ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/basic-requester.png) @@ -63,7 +63,7 @@ If you like my work, consider supporting me on [ko-fi](https://ko-fi.com/lesbian ## Mod Details -This mod adds a single new entity to the game, the cybernetic combinator. This combinator can be in one of 5 different possible control modes. While each mode has a purpose, the only modes you are required to use are station mode and depot mode. +This mod adds a single new entity to the game, the cybernetic combinator. This combinator can be in one of 5 different possible modes. While each mode has a purpose, the only modes you are required to use are station mode and depot mode. ### Station mode @@ -79,7 +79,7 @@ Stations can be set to provide only or request only. By default stations can bot ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/big-depot.png) -When placed adjacent to a vanilla train stop, a Cybersyn depot is created. Any train which parks at this depot will automatically be added to the train network. Whenever a train order is generated, if this train has the cargo capacity to fulfill it, and is allow-listed by both stations, then it will automatically be dispatched to fulfill the order. When the order is completed, the train will return to any train stop with the same name as the depot it first parked in. This almost always means it returns to a Cybersyn depot where it will again await to fulfill a new order. To save on UPS the input of a depot control combinator is only read when a train parks at the depot; this is only relevant for networks which make extensive use of network masks on depots. +When placed adjacent to a vanilla train stop, a Cybersyn depot is created. Any train which parks at this depot will automatically be added to the train network. Whenever a train order is generated, if this train has the cargo capacity to fulfill it, and is allow-listed by both stations, then it will automatically be dispatched to fulfill the order. When the order is completed, the train will return to any train stop with the same name as the depot it first parked in. This almost always means it returns to a Cybersyn depot where it will again await to fulfill a new order. To save on UPS the input of a depot combinator is only read when a train parks at the depot; this is only relevant for networks which make extensive use of network masks on depots. ### Fuel loader mode @@ -87,17 +87,17 @@ When placed adjacent to a vanilla train stop, a Cybersyn fuel loader is created. Fuel loaders can automatically build allow-lists. When this option is enabled, trains will be prevented from parking at this station if one of their cargo wagons would be filled with fuel. -### Station info mode +### Station control mode ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/science.png) When placed adjacent to the train stop of an already existing Cybersyn station, this combinator will provide a second set of inputs and outputs that can be used to more precisely control this station. The combinator input allows for request thresholds to be set per-item. Any non-zero item signal given on the input circuit network will override the station's request thresholds for just that item. When this is used on a provider station, if the station has more items than the input threshold, it will force the creation of a delivery for that item to the next available requester station. This effectively overrides the requester station's request threshold. This is useful for purging unwanted items from provider stations. -If a station info combinator receives a "priority" signal as input, it will apply that priority to each item signal it is receiving as input. This allows you to specify up to 2 different priorities per-item on a single station. +If a station control combinator receives a "priority" signal as input, it will apply that priority to each item signal it is receiving as input. This allows you to specify up to 2 different priorities per-item on a single station. The output of the combinator gives the sum total of all item loading or unloading orders in progress for the station. The very tick a train is dispatched for a new order to the station, that order is added to the output of this combinator, and it is removed as soon as the train leaves the station. The primary use case for this is to prevent duplicate orders from being generated for stations that provide the same pool of items. Only one train can be dispatched per-tick per-item specifically to accommodate this. -### Wagon info mode +### Wagon control mode ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/filtered-slots.png) @@ -107,7 +107,7 @@ When placed adjacent to the tracks of an already existing Cybersyn station, this ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/gui-network.png) -Stations, depots and fuel loaders can be set to belong to a particular network by setting that network on the control combinator. By default all combinators belong to the "signal-A" network. By setting a different signal Id, the combinator will belong to that different network. Networks identified with different signal Ids do not share any trains or items; Orders will never be generated to transfer items between separate networks. +Stations, depots and fuel loaders can be set to belong to a particular network by setting that network on their combinator. By default all combinators belong to the "signal-A" network. By setting a different signal Id, the combinator will belong to that different network. Networks identified with different signal Ids do not share any trains or items; Orders will never be generated to transfer items between separate networks. In addition, if the combinator receives as input a signal of the same Id as its network signal Id, then the value of this signal will be interpreted as a bitmask to give 32 "sub-networks" to choose from. Each station can belong to any set of sub-networks based on its mask. A delivery will only be made between two stations if any two bits match between the two masks, i.e. if `mask1 & mask2 > 0`. When a network Id is an item, that item will be ignored by stations, its signal will only ever be interpreted as the network mask. @@ -117,19 +117,19 @@ Stations and fuel loader combinators allow their network to be set to the "each" ![Image](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/previews/virtual-signals.png) -If a station control combinator receives a request threshold signal as input, a request order for the station will only be generated if the station is requesting a number of items exceeding the request threshold. In addition, there must be a station in the network which is providing at least as many items as the request threshold, and there must be a train in the network that has cargo capacity exceeding the request threshold. Through this logic all generated orders must be for a number of items greater than or equal to the request threshold. By setting high thresholds, the traffic on your network can be greatly reduced, at the cost of needing to maintain larger item buffers at each station. There is no "provide threshold" in this mod because by design there is almost no need for one. If desired a provide threshold can be simulated with a single decider combinator. The request threshold signal sets the request threshold "per-station" whereas the optional station control combinator can set or override the threshold per-item as well. +If a station combinator receives a request threshold signal as input, a request order for the station will only be generated if the station is requesting a number of items exceeding the request threshold. In addition, there must be a station in the network which is providing at least as many items as the request threshold, and there must be a train in the network that has cargo capacity exceeding the request threshold. Through this logic all generated orders must be for a number of items greater than or equal to the request threshold. By setting high thresholds, the traffic on your network can be greatly reduced, at the cost of needing to maintain larger item buffers at each station. There is no "provide threshold" in this mod because by design there is almost no need for one. If desired a provide threshold can be simulated with a single decider combinator. The request threshold signal sets the request threshold "per-station" whereas the station control combinator can set or override the threshold per-item as well. -On station combinators their is a setting called "Stack thresholds". When set, any request threshold for this station will be multiplied by the stack size of any item it is being compared to. This applies to station info thresholds as well. Thus the request threshold can be specified based on total stack count rather than total item count. Fluids are unaffected by the "Stack thresholds" setting, they are always specified by total fluid count. +On station combinators their is a setting called "Stack thresholds". When set, any request threshold for this station will be multiplied by the stack size of any item it is being compared to. This applies to station control thresholds as well. Thus the request threshold can be specified based on total stack count rather than total item count. Fluids are unaffected by the "Stack thresholds" setting, they are always specified by total fluid count. ### Locked slots per cargo wagon -After an order has been generated, enough items will be subtracted from that order to ensure at least X number of slots in each cargo wagon can be left empty, where X is the "Locked slots per cargo wagon" signal being received by the station control combinator. It is necessary for multi-item stations to function. +After an order has been generated, enough items will be subtracted from that order to ensure at least X number of slots in each cargo wagon can be left empty, where X is the "Locked slots per cargo wagon" signal being received by the station combinator. It is necessary for multi-item stations to function. ### Priority Orders will be generated first for stations, depots and fuel loaders which are receiving a higher priority signal than the others. If stations have the same priority, the least recently used requester station will be prioritized, and the provider station closest to the requester station will be prioritized. So in times of item shortage (front-pressure), round robin distribution will be used, and in times of item surplus (back-pressure), minimum travel distance distribution will be used. Provider stations will be prevented from providing items to lower priority requester stations until the highest priority requester station is satisfied. -If a combinator set to station info mode receives a priority signal, for each item signal input to the combinator, items of that type will have its priority overridden in addition to its request threshold. This effectively allows you to choose one of two possible priorities for each item that a station processes. +If a combinator set to station control mode receives a priority signal, for each item signal input to the combinator, items of that type will have its priority overridden in addition to its request threshold. This effectively allows you to choose one of two possible priorities for each item that a station processes. ### Train limits diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index bd81c8f..74ad707 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -3,7 +3,7 @@ Version: 1.2.0 Date: 2022-12-23 Changes: - Forced provide stations to wait until they can service the highest priority request station - - Provide stations now override request thresholds with the per-item thresholds set by their station info combinator + - Provide stations now override request thresholds with the per-item thresholds set by their station control combinator - Allowed station and fuel combinators to be set to network id "each", for each virtual signal they recieve as input, the stop is added to that network and its signal strength is used as the network mask - Added the ability to specify per-station whether request thresholds represent total items or total stacks - Prioritized a train's distance from the provide station over the train's cargo capacity @@ -49,7 +49,7 @@ Date: 2022-12-8 Version: 1.1.0 Date: 2022-12-8 Changes: - - Added the ability to use the priority signal as input to station info combinators so one can override priority on items with station info combinators thresholds + - Added the ability to use the priority signal as input to station control combinators so one can override priority on items with station control combinators thresholds - Added refueler stations - Slightly more permissive allow-list logic - Made non-backwards compatible improvements and bugfixes to the modding interface diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index 9870edd..9346cd1 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -29,7 +29,7 @@ cybersyn-combinator=Cybernetic combinator cybersyn-combinator-output=Cybernetic combinator output [entity-description] -cybersyn-combinator=Has 4 different control modes. Primary control allows providing and requesting. Optional Control allows setting thresholds per-item and reading all in progress deliveries. Depot control allows parked trains to be added to the network. Wagon control allows for reading the desired contents of the adjacent wagon. +cybersyn-combinator=Has 5 different control modes. Station mode allows providing and requesting. Station control mode allows setting thresholds per-item and reading all in progress deliveries. Depot mode allows parked trains to be added to the network. Fuel loader mode allows refueling stations to be designated. Wagon control mode allows for reading the desired contents of the adjacent wagon. [technology-name] cybersyn-train-network=Cybersyn train network @@ -58,12 +58,12 @@ no-train-matches-p-layout=Could not find a train on the allow-list of __2__ to m [cybersyn-gui] combinator-title=Cybernetic combinator -operation=Control Mode +operation=Mode comb1=Station depot=Depot refueler=Fuel loader -comb2=Station info -wagon-manifest=Wagon info +comb2=Station control +wagon-manifest=Wagon control network=Network network-tooltip=A signal is used to identify which network this combinator is a member of. Trains will only be dispatched from depots to provider and requester stations if they are all identified with the same signal. allow-list-description=Automatic allow-list diff --git a/cybersyn/scripts/constants.lua b/cybersyn/scripts/constants.lua index 1fa7d7a..0d7307a 100644 --- a/cybersyn/scripts/constants.lua +++ b/cybersyn/scripts/constants.lua @@ -19,7 +19,7 @@ MODE_PRIMARY_IO_FAILED_REQUEST = "^" MODE_PRIMARY_IO_ACTIVE = "<<" MODE_SECONDARY_IO = "%" MODE_DEPOT = "+" -MODE_WAGON_MANIFEST = "-" +MODE_WAGON = "-" MODE_REFUELER = ">>" NETWORK_SIGNAL_DEFAULT = {name="signal-A", type="virtual"} diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 1488359..8593c35 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -451,7 +451,7 @@ function get_comb_gui_settings(comb) selected_index = 3 elseif op == MODE_SECONDARY_IO then selected_index = 4 - elseif op == MODE_WAGON_MANIFEST then + elseif op == MODE_WAGON then selected_index = 5 end return selected_index, params.first_signal, switch_state, not allows_all_trains, is_stack diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 018d86f..a75c2e7 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -185,7 +185,7 @@ function register_gui_actions() elseif element.selected_index == 4 then set_comb_operation(comb, MODE_SECONDARY_IO) elseif element.selected_index == 5 then - set_comb_operation(comb, MODE_WAGON_MANIFEST) + set_comb_operation(comb, MODE_WAGON) else return end diff --git a/cybersyn/scripts/layout.lua b/cybersyn/scripts/layout.lua index a598350..90c7b32 100644 --- a/cybersyn/scripts/layout.lua +++ b/cybersyn/scripts/layout.lua @@ -532,7 +532,7 @@ function reset_stop_layout(map_data, stop, is_station_or_refueler, forbidden_ent end elseif entity.name == COMBINATOR_NAME then local param = map_data.to_comb_params[entity.unit_number] - if param.operation == MODE_WAGON_MANIFEST then + if param.operation == MODE_WAGON then local pos = entity.position local is_there if is_ver then diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index 8a4f804..9983db6 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -247,7 +247,7 @@ local function on_combinator_built(map_data, comb) params.operation = op params.first_signal = NETWORK_SIGNAL_DEFAULT control.parameters = params - elseif op ~= MODE_PRIMARY_IO and op ~= MODE_SECONDARY_IO and op ~= MODE_DEPOT and op ~= MODE_REFUELER and op ~= MODE_WAGON_MANIFEST then + elseif op ~= MODE_PRIMARY_IO and op ~= MODE_SECONDARY_IO and op ~= MODE_DEPOT and op ~= MODE_REFUELER and op ~= MODE_WAGON then op = MODE_PRIMARY_IO params.operation = op control.parameters = params @@ -258,7 +258,7 @@ local function on_combinator_built(map_data, comb) map_data.to_output[comb.unit_number] = out map_data.to_stop[comb.unit_number] = stop - if op == MODE_WAGON_MANIFEST then + if op == MODE_WAGON then if rail then update_stop_from_rail(map_data, rail, nil, true) end From f8b5012d22927b96a5dfc2b44f9a7799dd9deb47 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 22:22:44 -0500 Subject: [PATCH 25/26] updated locale --- cybersyn/locale/en/base.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index 9346cd1..60614f8 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -29,7 +29,7 @@ cybersyn-combinator=Cybernetic combinator cybersyn-combinator-output=Cybernetic combinator output [entity-description] -cybersyn-combinator=Has 5 different control modes. Station mode allows providing and requesting. Station control mode allows setting thresholds per-item and reading all in progress deliveries. Depot mode allows parked trains to be added to the network. Fuel loader mode allows refueling stations to be designated. Wagon control mode allows for reading the desired contents of the adjacent wagon. +cybersyn-combinator=Has 5 different modes. However you only need station mode and depot mode to get started. [technology-name] cybersyn-train-network=Cybersyn train network From 7696bd39eee8f28d13c6702b6c99cc18ca0c12f3 Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 22:30:49 -0500 Subject: [PATCH 26/26] fixed typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0b88d7b..b6b133e 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ Stations and fuel loader combinators allow their network to be set to the "each" If a station combinator receives a request threshold signal as input, a request order for the station will only be generated if the station is requesting a number of items exceeding the request threshold. In addition, there must be a station in the network which is providing at least as many items as the request threshold, and there must be a train in the network that has cargo capacity exceeding the request threshold. Through this logic all generated orders must be for a number of items greater than or equal to the request threshold. By setting high thresholds, the traffic on your network can be greatly reduced, at the cost of needing to maintain larger item buffers at each station. There is no "provide threshold" in this mod because by design there is almost no need for one. If desired a provide threshold can be simulated with a single decider combinator. The request threshold signal sets the request threshold "per-station" whereas the station control combinator can set or override the threshold per-item as well. -On station combinators their is a setting called "Stack thresholds". When set, any request threshold for this station will be multiplied by the stack size of any item it is being compared to. This applies to station control thresholds as well. Thus the request threshold can be specified based on total stack count rather than total item count. Fluids are unaffected by the "Stack thresholds" setting, they are always specified by total fluid count. +On station combinators there is a setting called "Stack thresholds". When set, any request threshold for this station will be multiplied by the stack size of any item it is being compared to. This applies to station control thresholds as well. Thus the request threshold can be specified based on total stack count rather than total item count. Fluids are unaffected by the "Stack thresholds" setting, they are always specified by total fluid count. ### Locked slots per cargo wagon