diff --git a/TODO b/TODO index 03b6a8a..1cb3fbb 100644 --- a/TODO +++ b/TODO @@ -7,3 +7,5 @@ space elevator compat railloader compat major bug with copy-paste when the operation is changed by blueprint but it gets copied to the old settings before it's checked for update catch inserter rotation +trains of capacity greater than the stations current contents can be dispatched + diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index f7db7ad..a687159 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -35,3 +35,10 @@ Version: 0.4.2 Date: 2022-11-22 Features: - Bugfix with station warmup time +--------------------------------------------------------------------------------------------------- +Version: 0.4.3 +Date: 2022-11-24 + Features: + - Added a stuck train alert + - Improved localization + - Fixed Bug with fluid cargo not being detected by depots diff --git a/cybersyn/info.json b/cybersyn/info.json index 048d289..7274d32 100644 --- a/cybersyn/info.json +++ b/cybersyn/info.json @@ -1,6 +1,6 @@ { "name": "cybersyn", - "version": "0.4.2", + "version": "0.4.3", "title": "Project Cybersyn", "author": "Mami", "factorio_version": "1.1", diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index 1c064f4..0ce4490 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -1,14 +1,16 @@ [mod-setting-name] -cybersyn-ticks-per-second=Dispatcher updates per second +cybersyn-ticks-per-second=Central planning updates per second cybersyn-request-threshold=Default requester threshold cybersyn-network-flag=Default network flags -cybersyn-warmup-time=Station warmup time +cybersyn-warmup-time=Station warmup time (sec) +cybersyn-stuck-train-time=Stuck train timeout (sec) [mod-setting-description] -cybersyn-ticks-per-second=How many times per second the dispather should check for new deliveries. Deliveries are made one at a time per update. This value will be rounded up to a divisor of 60. -cybersyn-request-threshold=The default request threshold when a request threshold signal is not given to a station. Huge values will prevent stations from taking requests from the network unless an explicit threshold is set. +cybersyn-ticks-per-second=How many times per second the central planner should update the state of the network and schedule deliveries. Only one deliveries can be made per update. This value will be rounded up to a divisor of 60. +cybersyn-request-threshold=The default request threshold when a request threshold signal is not given to a station. When a station receives a negative item signal that surpasses its request threshold, so long as any station exists with a positive signal greater than the request threshold, a delivery of that item will be scheduled between the two stations. cybersyn-network-flag=The default set of networks a station will service when no network signal is given to a station. This integer is interpretted bit-wise to give 32 possible network flags to choose from. -cybersyn-warmup-time=How many seconds a cybernetic combinator will wait before connecting to the Cybersyn network. A grace period to modify or correct the circuit network before trains start dispatching to a newly blueprinted station. +cybersyn-warmup-time=How many seconds a cybernetic combinator will wait before connecting to the Cybersyn network. This is a grace period to modify or correct the circuit network before trains start dispatching to a newly blueprinted station. +cybersyn-stuck-train-time=After this many seconds from a train's dispatch, an alert will be sent to let you know a train is probably stuck and has not completed its delivery. The player will likely have to debug their network to get the train unstuck. [item-name] cybersyn-combinator=Cybernetic combinator @@ -40,6 +42,7 @@ missing-trains=No trains available to make a delivery from __2__ to __1__ lost-train=A train from depot __1__ has become lost 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 [cybersyn-gui] combinator-title=Cybernetic combinator diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 0492d3d..5fd46f9 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -215,6 +215,7 @@ local function send_train_between(map_data, r_station_id, p_station_id, depot, p train.p_station_id = p_station_id train.r_station_id = r_station_id train.manifest = manifest + train.last_manifest_tick = map_data.total_ticks train.entity.schedule = create_manifest_schedule(train.depot_name, p_station.entity_stop, r_station.entity_stop, manifest) set_comb2(map_data, p_station) @@ -227,6 +228,18 @@ local function send_train_between(map_data, r_station_id, p_station_id, depot, p end end +---@param map_data MapData +---@param mod_settings CybersynModSettings +local function tick_poll_train(map_data, mod_settings) + local tick_data = map_data.tick_data + --NOTE: the following has undefined behavior if last_train is deleted, this should be ok since the following doesn't care how inconsistent our access pattern is + local train_id, train = next(map_data.trains, tick_data.last_train) + tick_data.last_train = train_id + + if train and train.manifest and train.last_manifest_tick + mod_settings.stuck_train_time*mod_settings.tps < map_data.total_ticks then + send_stuck_train_alert(train.entity, train.depot_name) + end +end ---@param map_data MapData ---@param mod_settings CybersynModSettings local function tick_poll_station(map_data, mod_settings) @@ -467,7 +480,7 @@ function tick(map_data, mod_settings) for i, id in pairs(map_data.warmup_station_ids) do local station = map_data.stations[id] if station then - if station.last_delivery_tick + mod_settings.warmup_time*mod_settings.tps <= map_data.total_ticks then + if station.last_delivery_tick + mod_settings.warmup_time*mod_settings.tps < map_data.total_ticks then map_data.active_station_ids[#map_data.active_station_ids + 1] = id map_data.warmup_station_ids[i] = nil end @@ -475,6 +488,7 @@ function tick(map_data, mod_settings) map_data.warmup_station_ids[i] = nil end end + tick_poll_train(map_data, mod_settings) end if map_data.tick_state == STATE_POLL_STATIONS then diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 0752077..6eca48d 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -266,3 +266,20 @@ function send_nonempty_train_in_depot_alert(train) end end 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) + 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) + end + end +end diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 60a4c63..a97228d 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -56,6 +56,7 @@ ---@field public p_station_id uint ---@field public r_station_id uint ---@field public manifest Manifest +---@field public last_manifest_tick int ---@field public has_filtered_wagon boolean ---@field public depot_id uint? ---@field public depot_name string @@ -78,6 +79,7 @@ ---@field public r_threshold int ---@field public network_flag int ---@field public warmup_time int +---@field public stuck_train_time int ---@type CybersynModSettings mod_settings = {} diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index 19534b0..c729ebe 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -558,6 +558,8 @@ end ---@param train_entity LuaTrain local function on_train_arrives_depot(map_data, depot_id, train_entity) local contents = train_entity.get_contents() + local fluid_contents = train_entity.get_fluid_contents() + local is_train_empty = next(contents) == nil and next(fluid_contents) == nil local train_id = train_entity.id local train = map_data.trains[train_id] if train then @@ -576,15 +578,15 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) train.status = STATUS_D add_available_train(map_data, depot_id, train_id) end - if next(contents) ~= nil then + if is_train_empty then + train_entity.schedule = create_depot_schedule(train.depot_name) + else --train still has cargo train_entity.schedule = nil remove_train(map_data, train, train_id) send_nonempty_train_in_depot_alert(train_entity) - else - train_entity.schedule = create_depot_schedule(train.depot_name) end - elseif next(contents) == nil then + elseif is_train_empty then train = { status = STATUS_D, entity = train_entity, @@ -593,6 +595,7 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) fluid_capacity = 0, p_station_id = 0, r_station_id = 0, + last_manifest_tick = map_data.total_ticks, manifest = nil, } update_train_layout(map_data, train) @@ -602,6 +605,7 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity) local schedule = create_depot_schedule(train.depot_name) train_entity.schedule = schedule else + train_entity.schedule = nil send_nonempty_train_in_depot_alert(train_entity) end end @@ -836,6 +840,7 @@ local function on_settings_changed(event) mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]] mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]] mod_settings.warmup_time = settings.global["cybersyn-warmup-time"].value--[[@as int]] + mod_settings.stuck_train_time = settings.global["cybersyn-stuck-train-time"].value--[[@as int]] if event.setting == "cybersyn-ticks-per-second" then local nth_tick = math.ceil(60/mod_settings.tps); flib_event.on_nth_tick(nil) @@ -866,6 +871,7 @@ local function main() mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]] mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]] mod_settings.warmup_time = settings.global["cybersyn-warmup-time"].value--[[@as int]] + mod_settings.stuck_train_time = settings.global["cybersyn-stuck-train-time"].value--[[@as int]] --NOTE: There is a concern that it is possible to build or destroy important entities without one of these events being triggered, in which case the mod will have undefined behavior flib_event.register(defines.events.on_built_entity, on_built, filter_built) diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index db32a3e..32caeff 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -75,6 +75,19 @@ local migrations_table = { } end end, + ["0.4.3"] = function() + ---@type MapData + local map_data = global + map_data.tick_state = STATE_INIT + for id, station in pairs(map_data.stations) do + set_station_from_comb_state(station) + station.allow_all_trains = nil + end + for id, train in pairs(map_data.trains) do + train.last_manifest_tick = map_data.total_ticks + end + mod_settings.stuck_train_time = settings.global["cybersyn-stuck-train-time"].value--[[@as int]] + end, } ---@param data ConfigurationChangedData diff --git a/cybersyn/settings.lua b/cybersyn/settings.lua index e60fd94..3f4e315 100644 --- a/cybersyn/settings.lua +++ b/cybersyn/settings.lua @@ -36,4 +36,13 @@ data:extend({ minimum_value = 0, maximum_value = 2147483647, }, + { + type = "int-setting", + name = "cybersyn-stuck-train-time", + order = "ad", + setting_type = "runtime-global", + default_value = 600, + minimum_value = 0, + maximum_value = 2147483647, + }, })