added train timeout

This commit is contained in:
Monica Moniot
2022-11-24 17:38:32 -05:00
parent 35a0994ae3
commit fe202642e7
10 changed files with 84 additions and 11 deletions

2
TODO
View File

@@ -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

View File

@@ -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

View File

@@ -1,6 +1,6 @@
{
"name": "cybersyn",
"version": "0.4.2",
"version": "0.4.3",
"title": "Project Cybersyn",
"author": "Mami",
"factorio_version": "1.1",

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 = {}

View File

@@ -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)

View File

@@ -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

View File

@@ -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,
},
})