improved the modding interface

This commit is contained in:
Monica Moniot
2022-12-08 11:14:24 -05:00
parent 2b632096b9
commit 66852924ee
10 changed files with 262 additions and 188 deletions

View File

@@ -119,3 +119,4 @@ Date: 2022-12-5
- Added refueler stations
- Slightly more permissive allow-list logic
- Fixed a crash relating to wagon control combinators on request stations
- Made non-backwards compatible improvements and bugfixes to the modding interface

View File

@@ -53,6 +53,7 @@ operation=Mode
comb1=Primary station control
comb2=Optional station control
depot=Depot control
refueler=Refueling 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 provide and request stations if they are all identified with the same signal.

View File

@@ -95,9 +95,8 @@ end
---@param r_station_id uint
---@param p_station_id uint
---@param train_id uint
---@param primary_item_name string?
function send_train_between(map_data, r_station_id, p_station_id, train_id, primary_item_name)
--trains and stations expected to be of the same network
---@param manifest Manifest
function create_delivery(map_data, r_station_id, p_station_id, train_id, manifest)
local economy = map_data.economy
local r_station = map_data.stations[r_station_id]
local p_station = map_data.stations[p_station_id]
@@ -105,6 +104,69 @@ function send_train_between(map_data, r_station_id, p_station_id, train_id, prim
---@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
if depot_id then
map_data.depots[depot_id].available_train_id = nil
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
local old_status = train.status
train.status = STATUS_TO_P
train.p_station_id = p_station_id
train.r_station_id = r_station_id
train.manifest = manifest
train.last_manifest_tick = map_data.total_ticks
r_station.last_delivery_tick = map_data.total_ticks
p_station.last_delivery_tick = map_data.total_ticks
r_station.deliveries_total = r_station.deliveries_total + 1
p_station.deliveries_total = p_station.deliveries_total + 1
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
--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
end
end
set_comb2(map_data, p_station)
set_comb2(map_data, r_station)
if p_station.display_state < 2 then
p_station.display_state = 2
update_display(map_data, p_station)
end
if r_station.display_state < 2 then
r_station.display_state = 2
update_display(map_data, r_station)
end
interface_raise_train_status_changed(train_id, old_status, STATUS_TO_P)
else
interface_raise_train_dispatch_failed(train_id)
end
end
---@param map_data MapData
---@param r_station_id uint
---@param p_station_id uint
---@param train_id uint
---@param primary_item_name string?
function create_manifest(map_data, r_station_id, p_station_id, train_id, primary_item_name)
--trains and stations expected to be of the same network
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 Manifest
local manifest = {}
for k, v in pairs(r_station.tick_signals) do
@@ -167,55 +229,7 @@ function send_train_between(map_data, r_station_id, p_station_id, train_id, prim
end
end
remove_available_train(map_data, train_id, train)
local depot_id = train.parked_at_depot_id
if depot_id then
map_data.depots[depot_id].available_train_id = nil
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
train.status = STATUS_TO_P
train.p_station_id = p_station_id
train.r_station_id = r_station_id
train.manifest = manifest
train.last_manifest_tick = map_data.total_ticks
r_station.last_delivery_tick = map_data.total_ticks
p_station.last_delivery_tick = map_data.total_ticks
r_station.deliveries_total = r_station.deliveries_total + 1
p_station.deliveries_total = p_station.deliveries_total + 1
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
--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
end
end
set_comb2(map_data, p_station)
set_comb2(map_data, r_station)
if p_station.display_state < 2 then
p_station.display_state = 2
update_display(map_data, p_station)
end
if r_station.display_state < 2 then
r_station.display_state = 2
update_display(map_data, r_station)
end
interface_raise_train_dispatched(train_id)
else
interface_raise_train_dispatch_failed(train_id)
end
return manifest
end
---@param map_data MapData
@@ -350,7 +364,9 @@ local function tick_dispatch(map_data, mod_settings)
end
end
if best_train then
send_train_between(map_data, r_station_id, table_remove(p_stations, best_i), best_train, item_name)
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)
return false
else
if can_be_serviced and mod_settings.missing_train_alert_enabled then

View File

@@ -274,8 +274,10 @@ function get_comb_gui_settings(comb)
selected_index = 2
elseif op == OPERATION_DEPOT then
selected_index = 3
elseif op == OPERATION_WAGON_MANIFEST then
elseif op == OPERATION_REFUELER then
selected_index = 4
elseif op == OPERATION_WAGON_MANIFEST then
selected_index = 5
end
return selected_index, params.first_signal, not allows_all_trains, switch_state
end

View File

@@ -13,7 +13,7 @@
---@field public refuelers {[uint]: Refueler}
---@field public trains {[uint]: Train}
---@field public available_trains {[string]: {[uint]: true?}} --{[network_name]: {[train_id]: true}}
---@field public to_refueler {[string]: {[uint]: true?}} --{[network_name]: {[refeuler_id]: true}}
---@field public to_refuelers {[string]: {[uint]: true?}} --{[network_name]: {[refeuler_id]: true}}
---@field public layouts {[uint]: (0|1|2)[]}
---@field public layout_train_count {[uint]: int}
---@field public tick_state uint
@@ -67,7 +67,7 @@
---@field public layout_id uint
---@field public item_slot_capacity int
---@field public fluid_capacity int
---@field public status int
---@field public status uint
---@field public p_station_id uint?
---@field public r_station_id uint?
---@field public manifest Manifest?
@@ -89,7 +89,7 @@
---@class ManifestEntry
---@field public type string
---@field public name string
---@field public count uint
---@field public count int
---@class Economy
---could contain invalid stations or stations with modified settings from when they were first appended

View File

@@ -62,6 +62,7 @@ function gui_opened(comb, player)
{"cybersyn-gui.comb1"},
{"cybersyn-gui.comb2"},
{"cybersyn-gui.depot"},
{"cybersyn-gui.refueler"},
{"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={
@@ -88,10 +89,12 @@ function gui_opened(comb, player)
window.preview.entity = comb
window.titlebar.drag_target = window.main_window
window.main_window.force_auto_center()
window.network.visible = selected_index == 1 or selected_index == 3
window.network_label.visible = selected_index == 1 or selected_index == 3
window.radio_button.visible = selected_index == 1
window.radio_label.visible = selected_index == 1
local uses_network = selected_index == 1 or selected_index == 3 or selected_index == 4
local uses_allow_list = selected_index == 1 or selected_index == 4
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
player.opened = window.main_window
@@ -163,6 +166,13 @@ function register_gui_actions()
bottom_flow["radio_button"].visible = false
bottom_flow["radio_label"].visible = false
elseif element.selected_index == 4 then
set_comb_operation(comb, OPERATION_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 == 5 then
set_comb_operation(comb, OPERATION_WAGON_MANIFEST)
top_flow["switch"].visible = false
all_flow["network_label"].visible = false

View File

@@ -54,7 +54,7 @@ local function on_refueler_built(map_data, stop, comb)
local id = stop.unit_number--[[@as uint]]
map_data.refuelers[id] = refueler
update_stop_if_auto(map_data, refueler, false)
interface_raise_refueler_created(depot_id)
interface_raise_refueler_created(id)
end
---@param map_data MapData
---@param refueler_id uint
@@ -76,10 +76,10 @@ local function on_refueler_broken(map_data, refueler_id, refueler)
end
end
if refueler.network_name then
local network = map_data.to_refueler[refueler.network_name]
local network = map_data.to_refuelers[refueler.network_name]
network[refueler_id] = nil
if next(network) == nil then
map_data.to_refueler[refueler.network_name] = nil
map_data.to_refuelers[refueler.network_name] = nil
end
end
map_data.stations[refueler_id] = nil
@@ -309,24 +309,25 @@ function on_combinator_network_updated(map_data, comb, network_name)
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_refueler[refueler.network_name]
local network = map_data.to_refuelers[refueler.network_name]
network[id] = nil
if next(network) == nil then
map_data.to_refueler[refueler.network_name] = nil
map_data.to_refuelers[refueler.network_name] = nil
end
end
refueler.network_name = network_name
if network_name then
local network = map_data.to_refueler[network_name]
local network = map_data.to_refuelers[network_name]
if network == nil then
network = {}
map_data.to_refueler[network_name] = network
map_data.to_refuelers[network_name] = network
end
network[id] = true
end

View File

@@ -73,9 +73,27 @@ local migrations_table = {
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
station.p_count_or_r_threshold_per_item = nil
end
local OLD_STATUS_R_TO_D = 5
local NEW_STATUS_TO_D = 5
local NEW_STATUS_TO_D_BYPASS = 6
for id, train in pairs(map_data.trains) do
if train.status == OLD_STATUS_R_TO_D then
train.manifest = nil
train.p_station_id = nil
train.r_station_id = nil
if train.is_available then
train.status = NEW_STATUS_TO_D_BYPASS
else
train.status = NEW_STATUS_TO_D
end
end
end
end,
}
--STATUS_R_TO_D = 5

View File

@@ -13,16 +13,15 @@ local on_station_created = nil
local on_station_removed = nil
local on_depot_created = nil
local on_depot_removed = nil
local on_refueler_created = nil
local on_refueler_removed = nil
local on_train_created = nil
local on_train_removed = nil
local on_train_available = nil
local on_train_nonempty_in_depot = nil
local on_train_dispatched = nil
local on_train_dispatch_failed = nil
local on_train_failed_delivery = nil
local on_train_completed_provide = nil
local on_train_completed_request = nil
local on_train_parked_at_depot = nil
local on_train_status_changed = nil
local on_train_stuck = nil
local on_train_teleport_started = nil
local on_train_teleported = nil
@@ -77,6 +76,25 @@ function interface_raise_depot_removed(old_depot_id, old_depot)
end
end
---@param refueler_id uint
function interface_raise_refueler_created(refueler_id)
if on_refueler_created then
raise_event(on_refueler_created, {
refueler_id = refueler_id,
})
end
end
---@param old_refueler_id uint
---@param old_refueler Refueler
function interface_raise_refueler_removed(old_refueler_id, old_refueler)
if on_refueler_removed then
raise_event(on_refueler_removed, {
old_refueler_id = old_refueler_id, --this id is now invalid
old_refueler = old_refueler, --this is the data that used to be stored at the old id
})
end
end
---@param train_id uint
---@param depot_id uint
function interface_raise_train_created(train_id, depot_id)
@@ -118,14 +136,6 @@ function interface_raise_train_nonempty_in_depot(depot_id, train_entity, train_i
end
end
---@param train_id uint
function interface_raise_train_dispatched(train_id)
if on_train_dispatched then
raise_event(on_train_dispatched, {
train_id = train_id,
})
end
end
---@param train_id uint
function interface_raise_train_dispatch_failed(train_id)
--this event is rare, it can only occur when a train is bypassing the depot and can't find a path to the provide station, that train is marked as unavailable but not dispatched
@@ -154,28 +164,14 @@ function interface_raise_train_failed_delivery(train_id, was_p_in_progress, p_st
end
end
---@param train_id uint
function interface_raise_train_completed_provide(train_id)
if on_train_completed_provide then
raise_event(on_train_completed_provide, {
---@param old_status uint
---@param new_status uint
function interface_raise_train_status_changed(train_id, old_status, new_status)
if on_train_status_changed then
raise_event(on_train_status_changed, {
train_id = train_id,
})
end
end
---@param train_id uint
function interface_raise_train_completed_request(train_id)
if on_train_completed_request then
raise_event(on_train_completed_request, {
train_id = train_id,
})
end
end
---@param train_id uint
---@param depot_id uint
function interface_raise_train_parked_at_depot(train_id, depot_id)
if on_train_parked_at_depot then
raise_event(on_train_parked_at_depot, {
train_id = train_id,
depot_id = depot_id,
old_status = old_status,
new_status = new_status,
})
end
end
@@ -240,6 +236,14 @@ function interface.get_on_depot_removed()
if not on_depot_removed then on_depot_removed = script_generate_event_name() end
return on_depot_removed
end
function interface.get_on_refueler_created()
if not on_refueler_created then on_refueler_created = script_generate_event_name() end
return on_refueler_created
end
function interface.get_on_refueler_removed()
if not on_refueler_removed then on_refueler_removed = script_generate_event_name() end
return on_refueler_removed
end
function interface.get_on_train_created()
if not on_train_created then on_train_created = script_generate_event_name() end
return on_train_created
@@ -256,10 +260,6 @@ function interface.get_on_train_nonempty_in_depot()
if not on_train_nonempty_in_depot then on_train_nonempty_in_depot = script_generate_event_name() end
return on_train_nonempty_in_depot
end
function interface.get_on_train_dispatched()
if not on_train_dispatched then on_train_dispatched = script_generate_event_name() end
return on_train_dispatched
end
function interface.get_on_train_dispatch_failed()
if not on_train_dispatch_failed then on_train_dispatch_failed = script_generate_event_name() end
return on_train_dispatch_failed
@@ -268,17 +268,9 @@ function interface.get_on_train_failed_delivery()
if not on_train_failed_delivery then on_train_failed_delivery = script_generate_event_name() end
return on_train_failed_delivery
end
function interface.get_on_train_completed_provide()
if not on_train_completed_provide then on_train_completed_provide = script_generate_event_name() end
return on_train_completed_provide
end
function interface.get_on_train_completed_request()
if not on_train_completed_request then on_train_completed_request = script_generate_event_name() end
return on_train_completed_request
end
function interface.get_on_train_parked_at_depot()
if not on_train_parked_at_depot then on_train_parked_at_depot = script_generate_event_name() end
return on_train_parked_at_depot
function interface.get_on_train_status_changed()
if not on_train_status_changed then on_train_status_changed = script_generate_event_name() end
return on_train_status_changed
end
function interface.get_on_train_stuck()
if not on_train_stuck then on_train_stuck = script_generate_event_name() end
@@ -298,11 +290,79 @@ function interface.get_on_tick_init()
end
------------------------------------------------------------------
--[[helper functions]]
------------------------------------------------------------------
--NOTE: the policy of cybersyn is to give modders access to as much of the raw data of the mod as possible. Factorio only allows me to return copies of the original data rather than the actual thing, which sucks. The unsafe api has some tools to help you bypass this limitation.
function interface.get_mod_settings()
return mod_settings
end
---@param key string
function interface.read_setting(key)
return mod_settings[key]
end
---@param ... string|int
function interface.read_global(...)
--this can read anything off of cybersyn's map_data
--so interface.read_global("trains", 31415, "manifest") == global.trains[31415].manifest (or nil if train 31415 does not exist)
--the second return value is how many parameters could be processed before a nil value was encountered (in the above example it's useful for telling apart global.trains[31415] == nil vs global.trains[31415].manifest == nil)
local base = global
local depth = 0
for i, v in ipairs({...}) do
depth = i
base = base[v]
if not base then break end
end
return base, depth
end
---@param id uint
function interface.get_station(id)
return global.stations[id]
end
---@param id uint
function interface.get_depot(id)
return global.depots[id]
end
---@param id uint
function interface.get_refueler(id)
return global.refuelers[id]
end
---@param id uint
function interface.get_train(id)
return global.trains[id]
end
---@param train_entity LuaTrain
function interface.get_train_id_from_luatrain(train_entity)
return train_entity.id
end
---@param stop LuaEntity
function interface.get_id_from_stop(stop)
return stop.unit_number
end
---@param comb LuaEntity
function interface.get_id_from_comb(comb)
local stop = global.to_stop[comb.unit_number]
if stop then
return stop.unit_number
end
end
------------------------------------------------------------------
--[[safe API]]
------------------------------------------------------------------
--NOTE: These functions can be called whenever however so long as their parameters have the correct types. Their ability to cause harm is extremely minimal.
---@param key string
---@param value any
function interface.write_setting(key, value)
--be careful that the value you write is of the correct type specified in global.lua
--these settings are not saved and have to be set on load and on init
mod_settings[key] = value
end
---@param comb LuaEntity
function interface.combinator_update(comb)
combinator_update(global, comb)
@@ -330,6 +390,11 @@ end
function interface.is_layout_accepted(layout_pattern, layout)
return is_layout_accepted(layout_pattern, layout)
end
---@param layout_pattern (0|1|2|3)[]
---@param layout (0|1|2)[]
function interface.is_refuel_layout_accepted(layout_pattern, layout)
return is_refuel_layout_accepted(layout_pattern, layout)
end
---@param stop_id uint
---@param forbidden_entity LuaEntity?
---@param force_update boolean?
@@ -358,14 +423,8 @@ end
------------------------------------------------------------------
--NOTE: The following functions can cause serious longterm damage to someone's world if they are given bad parameters. Please refer to global.lua for type information. Use caution.
---@param key string
---@param value any
function interface.write_setting(key, value)
--be careful that the value you write is of the correct type specified in global.lua
mod_settings[key] = value
end
---@param ... string|uint|any
---@param ... string|int
function interface.write_global(value, ...)
--this can write anything into cybersyn's map_data, please be very careful with anything you write, it can cause permanent damage
--so interface.read_global(nil, "trains", 31415, "manifest") will cause global.trains[31415].manifest = nil (or return false if train 31415 does not exist)
@@ -393,11 +452,19 @@ end
---@param r_station_id uint
---@param p_station_id uint
---@param train_id uint
---@param primary_item_name string?
function interface.create_new_delivery_between_stations(r_station_id, p_station_id, train_id, primary_item_name)
function interface.create_manifest(r_station_id, p_station_id, train_id)
local train = global.trains[train_id]
assert(global.stations[r_station_id] and global.stations[p_station_id] and train and train.is_available)
send_train_between(global, r_station_id, p_station_id, train_id, primary_item_name)
create_manifest(global, r_station_id, p_station_id, train_id)
end
---@param r_station_id uint
---@param p_station_id uint
---@param train_id uint
---@param manifest Manifest
function interface.create_delivery(r_station_id, p_station_id, train_id, manifest)
local train = global.trains[train_id]
assert(global.stations[r_station_id] and global.stations[p_station_id] and train and train.is_available and manifest)
create_delivery(global, r_station_id, p_station_id, train_id, manifest)
end
---@param train_id uint
function interface.fail_delivery(train_id)
@@ -453,6 +520,7 @@ interface.rename_manifest_schedule = rename_manifest_schedule
interface.se_get_space_elevator_name = se_get_space_elevator_name
interface.se_create_elevator_order = se_create_elevator_order
interface.set_manifest_schedule = set_manifest_schedule
interface.add_refueler_schedule = add_refueler_schedule
------------------------------------------------------------------
--[[alerts]]
@@ -464,58 +532,5 @@ 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
------------------------------------------------------------------
--[[helper functions]]
------------------------------------------------------------------
--NOTE: the policy of cybersyn is to give modders access to as much of the raw data of the mod as possible. Factorio only allows me to return copies of the original data rather than the actual thing, which sucks. The unsafe api has some tools to help you bypass this limitation.
function interface.get_mod_settings()
return mod_settings
end
---@param key string
function interface.read_setting(key)
return mod_settings[key]
end
---@param ... string|uint
function interface.read_global(...)
--this can read anything off of cybersyn's map_data
--so interface.read_global("trains", 31415, "manifest") == global.trains[31415].manifest (or nil if train 31415 does not exist)
local base = global
local depth = 0
for i, v in ipairs({...}) do
depth = i
base = base[v]
if not base then break end
end
return base, depth
end
---@param id uint
function interface.get_station(id)
return global.stations[id]
end
---@param id uint
function interface.get_depot(id)
return global.depots[id]
end
---@param id uint
function interface.get_train(id)
return global.trains[id]
end
---@param train_entity LuaTrain
function interface.get_train_id_from_luatrain(train_entity)
return train_entity.id
end
---@param stop LuaEntity
function interface.get_station_or_depot_id_from_stop(stop)
return stop.unit_number
end
---@param comb LuaEntity
function interface.get_station_or_depot_id_from_comb(comb)
local stop = global.to_stop[comb.unit_number]
if stop then
return stop.unit_number
end
end
remote.add_interface("cybersyn", interface)

View File

@@ -147,7 +147,8 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity)
local train = map_data.trains[train_id]
if train then
if train.status == STATUS_TO_D then
elseif train.status == STATUS_TO_D_BYPASS then
elseif train.status == STATUS_TO_D_BYPASS or train.status == STATUS_D then
--shouldn't be possible to get train.status == STATUS_D
remove_available_train(map_data, train_id, train)
elseif mod_settings.react_to_train_early_to_depot then
if train.manifest then
@@ -158,9 +159,10 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity)
return
end
if is_train_empty then
local old_status = train.status
add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, map_data.depots[depot_id])
set_depot_schedule(train_entity, train.depot_name)
interface_raise_train_parked_at_depot(train_id, depot_id)
interface_raise_train_status_changed(train_id, old_status, STATUS_D)
else
--train still has cargo
if mod_settings.react_to_nonempty_train_in_depot then
@@ -217,6 +219,7 @@ local function on_train_arrives_station(map_data, station_id, train_id, train)
local station = map_data.stations[station_id]
set_comb1(map_data, station, train.manifest, 1)
set_p_wagon_combs(map_data, station, train)
interface_raise_train_status_changed(train_id, STATUS_TO_P, STATUS_P)
end
elseif train.status == STATUS_TO_R then
if train.r_station_id == station_id then
@@ -224,6 +227,7 @@ local function on_train_arrives_station(map_data, station_id, train_id, train)
local station = map_data.stations[station_id]
set_comb1(map_data, station, train.manifest, -1)
set_r_wagon_combs(map_data, station, train)
interface_raise_train_status_changed(train_id, STATUS_TO_R, STATUS_R)
end
elseif train.status == STATUS_P and train.p_station_id == station_id then
--this is player intervention that is considered valid
@@ -251,6 +255,7 @@ local function on_train_arrives_refueler(map_data, refueler_id, train_id, train)
local refueler = map_data.refuelers[refueler_id]
train.status = STATUS_F
set_refueler_combs(map_data, refueler, train)
interface_raise_train_status_changed(train_id, STATUS_TO_F, STATUS_F)
end
end
@@ -277,7 +282,7 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train)
end
end
end
interface_raise_train_completed_provide(train_id)
interface_raise_train_status_changed(train_id, STATUS_P, STATUS_TO_R)
elseif train.status == STATUS_R then
local station = map_data.stations[train.r_station_id]
remove_manifest(map_data, station, train.manifest, -1)
@@ -311,12 +316,16 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train)
if mod_settings.depot_bypass_threshold < 1 then
train.status = STATUS_TO_D_BYPASS
add_available_train(map_data, train_id, train)
interface_raise_train_status_changed(train_id, STATUS_R, STATUS_TO_D_BYPASS)
return
end
elseif fuel_fill/total_slots > mod_settings.depot_bypass_threshold then
train.status = STATUS_TO_D_BYPASS
add_available_train(map_data, train_id, train)
interface_raise_train_status_changed(train_id, STATUS_R, STATUS_TO_D_BYPASS)
return
else
local refuelers = map_data.to_refueler[train.network_name]
local refuelers = map_data.to_refuelers[train.network_name]
if refuelers then
local best_refueler_id = nil
local best_dist = INF
@@ -344,14 +353,14 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train)
local refueler = map_data.refuelers[best_refueler_id]
refueler.trains_total = refueler.trains_total + 1
add_refueler_schedule(train.entity, refueler.entity_stop)
interface_raise_train_status_changed(train_id, STATUS_R, STATUS_TO_F)
return
end
end
end
if train.status == STATUS_R then
--the train has not qualified for depot bypass nor refueling
train.status = STATUS_TO_D
end
interface_raise_train_completed_request(train_id)
--the train has not qualified for depot bypass nor refueling
train.status = STATUS_TO_D
interface_raise_train_status_changed(train_id, STATUS_R, STATUS_TO_D)
elseif train.status == STATUS_F then
local refueler = map_data.refuelers[train.refueler_id]
train.status = STATUS_TO_D_BYPASS
@@ -360,6 +369,7 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train)
add_available_train(map_data, train_id, train)
unset_wagon_combs(map_data, refueler)
set_combinator_output(map_data, refueler.entity_comb, nil)
interface_raise_train_status_changed(train_id, STATUS_F, STATUS_TO_D_BYPASS)
elseif train.status == STATUS_D then
--The train is leaving the depot without a manifest, the player likely intervened
local depot = map_data.depots[train.parked_at_depot_id--[[@as uint]]]