added valid checking

This commit is contained in:
monica
2023-01-07 18:57:13 -05:00
committed by Monica Moniot
parent 2e0216a351
commit 1fc464055e
6 changed files with 241 additions and 169 deletions

View File

@@ -42,71 +42,93 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes
local train = map_data.trains[train_id] local train = map_data.trains[train_id]
local depot = map_data.depots[train.depot_id] local depot = map_data.depots[train.depot_id]
local is_at_depot = remove_available_train(map_data, train_id, train)
--NOTE: we assume that the train is not being teleported at this time if not train.entity.valid then
--NOTE: set_manifest_schedule is allowed to cancel the delivery at the last second if applying the schedule to the train makes it lost on_train_broken(map_data, train_id, train)
if set_manifest_schedule(map_data, train.entity, depot.entity_stop, not train.use_any_depot, p_station.entity_stop, p_station.enable_inactive, r_station.entity_stop, mod_settings.allow_cargo_in_depot and r_station.enable_inactive--[[@as boolean]], manifest, is_at_depot) then interface_raise_train_dispatch_failed(train_id)
local old_status = train.status return
train.status = STATUS_TO_P end
train.p_station_id = p_station_id if not depot.entity_stop.valid then
train.r_station_id = r_station_id on_depot_broken(map_data, train.depot_id, depot)
train.manifest = manifest interface_raise_train_dispatch_failed(train_id)
train.last_manifest_tick = map_data.total_ticks return
end
r_station.last_delivery_tick = map_data.total_ticks if not p_station.entity_stop.valid then
p_station.last_delivery_tick = map_data.total_ticks on_station_broken(map_data, p_station_id, p_station)
interface_raise_train_dispatch_failed(train_id)
r_station.deliveries_total = r_station.deliveries_total + 1 return
p_station.deliveries_total = p_station.deliveries_total + 1 end
if not r_station.entity_stop.valid then
local r_is_each = r_station.network_name == NETWORK_EACH on_station_broken(map_data, r_station_id, r_station)
local p_is_each = p_station.network_name == NETWORK_EACH interface_raise_train_dispatch_failed(train_id)
for item_i, item in ipairs(manifest) do return
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_each or p_is_each then
local f, a
if r_is_each then
f, a = pairs(r_station.network_flag--[[@as {[string]: int}]])
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
economy.all_p_stations[item_network_name] = nil
end
f, a = pairs(p_station.network_flag--[[@as {[string]: int}]])
end
elseif p_is_each 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
--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 end
set_comb2(map_data, p_station) local is_at_depot = remove_available_train(map_data, train_id, train)
set_comb2(map_data, r_station) --NOTE: we assume that the train is not being teleported at this time
--NOTE: set_manifest_schedule is allowed to cancel the delivery at the last second if applying the schedule to the train makes it lost and is_at_depot == false
local r_enable_inactive = mod_settings.allow_cargo_in_depot and r_station.enable_inactive--[[@as boolean]]
if set_manifest_schedule(map_data, train.entity, depot.entity_stop, not train.use_any_depot, p_station.entity_stop, p_station.enable_inactive, r_station.entity_stop, r_enable_inactive, manifest, is_at_depot) 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
p_station.display_state = 1 r_station.last_delivery_tick = map_data.total_ticks
update_display(map_data, p_station) p_station.last_delivery_tick = map_data.total_ticks
r_station.display_state = 1
update_display(map_data, r_station)
interface_raise_train_status_changed(train_id, old_status, STATUS_TO_P) r_station.deliveries_total = r_station.deliveries_total + 1
else p_station.deliveries_total = p_station.deliveries_total + 1
interface_raise_train_dispatch_failed(train_id)
end 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_each or p_is_each then
local f, a
if r_is_each then
f, a = pairs(r_station.network_flag--[[@as {[string]: int}]])
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
economy.all_p_stations[item_network_name] = nil
end
f, a = pairs(p_station.network_flag--[[@as {[string]: int}]])
end
elseif p_is_each 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
--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
set_comb2(map_data, p_station)
set_comb2(map_data, r_station)
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)
end
end end
---@param map_data MapData ---@param map_data MapData
---@param r_station_id uint ---@param r_station_id uint
@@ -255,7 +277,7 @@ local function tick_dispatch(map_data, mod_settings)
for i, id in ipairs(r_stations) do for i, id in ipairs(r_stations) do
local station = stations[id] 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 --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 not station or station.deliveries_total >= station.entity_stop.trains_limit then if not station or station.deliveries_total >= station.trains_limit then
goto continue goto continue
end end
@@ -331,7 +353,7 @@ local function tick_dispatch(map_data, mod_settings)
local p_station_id = p_stations[j] local p_station_id = p_stations[j]
local p_station = stations[p_station_id] local p_station = stations[p_station_id]
if not p_station or p_station.deliveries_total >= p_station.entity_stop.trains_limit then if not p_station or p_station.deliveries_total >= p_station.trains_limit then
goto p_continue goto p_continue
end end
@@ -403,7 +425,8 @@ local function tick_dispatch(map_data, mod_settings)
end end
--check if path is shortest so we prioritize locality --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 local t = get_any_train_entity(train.entity)
local t_to_p_dist = t and p_station.entity_stop.valid and (get_dist(t, p_station.entity_stop) - DEPOT_PRIORITY_MULT*train.priority) or INF
if capacity == best_capacity and t_to_p_dist > best_t_to_p_dist then if capacity == best_capacity and t_to_p_dist > best_t_to_p_dist then
goto train_continue goto train_continue
end end
@@ -443,7 +466,7 @@ local function tick_dispatch(map_data, mod_settings)
goto p_continue goto p_continue
end end
best_p_dist = best_t_to_p_dist + get_stop_dist(p_station.entity_stop, r_station.entity_stop) best_p_dist = p_station.entity_stop.valid and r_station.entity_stop.valid and (best_t_to_p_dist + get_dist(p_station.entity_stop, r_station.entity_stop)) or INF
if p_prior == best_p_prior and best_p_dist > best_dist then if p_prior == best_p_prior and best_p_dist > best_dist then
goto p_continue goto p_continue
end end
@@ -501,11 +524,7 @@ local function tick_poll_station(map_data, mod_settings)
station_id = map_data.active_station_ids[tick_data.i] station_id = map_data.active_station_ids[tick_data.i]
station = map_data.stations[station_id] station = map_data.stations[station_id]
if station then if station then
if station_id == 70487 then if station.network_name then
local i = 0
end
--NOTE: polling trains_limit here is expensive and not strictly necessary but using it to early out saves more ups
if station.network_name and station.deliveries_total < station.entity_stop.trains_limit then
break break
end end
else else
@@ -514,6 +533,12 @@ local function tick_poll_station(map_data, mod_settings)
tick_data.i = tick_data.i - 1 tick_data.i = tick_data.i - 1
end end
end end
if station.entity_stop.valid and station.entity_comb1.valid and (not station.entity_comb2 or station.entity_comb2.valid) then
station.trains_limit = station.entity_stop.trains_limit
else
on_station_broken(map_data, station_id, station)
return false
end
station.r_threshold = mod_settings.r_threshold station.r_threshold = mod_settings.r_threshold
station.priority = mod_settings.priority station.priority = mod_settings.priority
station.item_priority = nil station.item_priority = nil
@@ -673,13 +698,22 @@ function tick_poll_entities(map_data, mod_settings)
local refueler_id, _ = next(map_data.each_refuelers, tick_data.last_refueler) local refueler_id, _ = next(map_data.each_refuelers, tick_data.last_refueler)
tick_data.last_refueler = refueler_id tick_data.last_refueler = refueler_id
if refueler_id then if refueler_id then
set_refueler_from_comb(map_data, mod_settings, refueler_id) local refueler = map_data.refuelers[refueler_id]
if refueler.entity_stop.valid and refueler.entity_comb.valid then
set_refueler_from_comb(map_data, mod_settings, refueler_id, refueler)
else
on_refueler_broken(map_data, refueler_id, refueler)
end
end end
else else
local comb_id, comb = next(map_data.to_comb, tick_data.last_comb) local comb_id, comb = next(map_data.to_comb, tick_data.last_comb)
tick_data.last_comb = comb_id tick_data.last_comb = comb_id
if comb and comb.valid then if comb then
combinator_update(map_data, comb, true) if comb.valid then
combinator_update(map_data, comb, true)
else
map_data.to_comb[comb_id] = nil
end
end end
end end
end end
@@ -697,7 +731,11 @@ function tick_init(map_data, mod_settings)
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.active_station_ids[#map_data.active_station_ids + 1] = id
map_data.warmup_station_ids[i] = nil map_data.warmup_station_ids[i] = nil
combinator_update(map_data, station.entity_comb1) if station.entity_comb1.valid then
combinator_update(map_data, station.entity_comb1)
else
on_station_broken(map_data, id, station)
end
end end
else else
map_data.warmup_station_ids[i] = nil map_data.warmup_station_ids[i] = nil
@@ -708,9 +746,13 @@ function tick_init(map_data, mod_settings)
local station = map_data.stations[id] local station = map_data.stations[id]
if station then if station then
local pre = station.allows_all_trains local pre = station.allows_all_trains
set_station_from_comb(station) if station.entity_comb1.valid then
if station.allows_all_trains ~= pre then set_station_from_comb(station)
update_stop_if_auto(map_data, station, true) if station.allows_all_trains ~= pre then
update_stop_if_auto(map_data, station, true)
end
else
on_station_broken(map_data, id, station)
end end
end end
end end

View File

@@ -15,10 +15,10 @@ function get_stack_size(map_data, item_name)
return game.item_prototypes[item_name].stack_size return game.item_prototypes[item_name].stack_size
end end
---NOTE: does not check .valid
---@param entity0 LuaEntity ---@param entity0 LuaEntity
---@param entity1 LuaEntity ---@param entity1 LuaEntity
function get_stop_dist(entity0, entity1) function get_dist(entity0, entity1)
local surface0 = entity0.surface.index local surface0 = entity0.surface.index
local surface1 = entity1.surface.index local surface1 = entity1.surface.index
return (surface0 == surface1 and get_distance(entity0.position, entity1.position) or DIFFERENT_SURFACE_DISTANCE) return (surface0 == surface1 and get_distance(entity0.position, entity1.position) or DIFFERENT_SURFACE_DISTANCE)
@@ -41,7 +41,7 @@ end
---@param train LuaTrain ---@param train LuaTrain
function get_any_train_entity(train) function get_any_train_entity(train)
return train.front_stock or train.back_stock or train.carriages[1] return train.valid and (train.front_stock or train.back_stock or train.carriages[1]) or nil
end end
@@ -109,31 +109,37 @@ end
---@param train LuaTrain ---@param train LuaTrain
---@param depot_name string ---@param depot_name string
function set_depot_schedule(train, depot_name) function set_depot_schedule(train, depot_name)
train.schedule = {current = 1, records = {create_inactivity_order(depot_name)}} if train.valid then
train.schedule = {current = 1, records = {create_inactivity_order(depot_name)}}
end
end end
---@param train LuaTrain ---@param train LuaTrain
function lock_train(train) function lock_train(train)
train.manual_mode = true if train.valid then
train.manual_mode = true
end
end end
---@param train LuaTrain ---@param train LuaTrain
function lock_train_to_depot(train) function lock_train_to_depot(train)
local schedule = train.schedule if train.valid then
if schedule then local schedule = train.schedule
local record = schedule.records[schedule.current] if schedule then
if record then local record = schedule.records[schedule.current]
local wait = record.wait_conditions if record then
if wait and wait[1] then local wait = record.wait_conditions
wait[1].ticks = LOCK_TRAIN_TIME 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 else
record.wait_conditions = {{type = "inactivity", compare_type = "and", ticks = LOCK_TRAIN_TIME}} train.manual_mode = true
end end
train.schedule = schedule
else else
train.manual_mode = true train.manual_mode = true
end end
else
train.manual_mode = true
end end
end end
@@ -141,15 +147,17 @@ end
---@param stop LuaEntity ---@param stop LuaEntity
---@param old_name string ---@param old_name string
function rename_manifest_schedule(train, stop, old_name) function rename_manifest_schedule(train, stop, old_name)
local new_name = stop.backer_name if train.valid then
local schedule = train.schedule local new_name = stop.backer_name
if not schedule then return end local schedule = train.schedule
for i, record in ipairs(schedule.records) do if not schedule then return end
if record.station == old_name then for i, record in ipairs(schedule.records) do
record.station = new_name if record.station == old_name then
record.station = new_name
end
end end
train.schedule = schedule
end end
train.schedule = schedule
end end
---@param elevator_name string ---@param elevator_name string
@@ -157,6 +165,7 @@ end
function se_create_elevator_order(elevator_name, is_train_in_orbit) 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)} return {station = elevator_name..(is_train_in_orbit and SE_ELEVATOR_ORBIT_SUFFIX or SE_ELEVATOR_PLANET_SUFFIX)}
end end
---NOTE: does not check .valid
---@param map_data MapData ---@param map_data MapData
---@param train LuaTrain ---@param train LuaTrain
---@param depot_stop LuaEntity ---@param depot_stop LuaEntity
@@ -281,6 +290,7 @@ function set_manifest_schedule(map_data, train, depot_stop, same_depot, p_stop,
return true return true
end end
---NOTE: does not check .valid
---@param map_data MapData ---@param map_data MapData
---@param train LuaTrain ---@param train LuaTrain
---@param stop LuaEntity ---@param stop LuaEntity
@@ -355,14 +365,8 @@ end
function get_comb_params(comb) function get_comb_params(comb)
return comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] return comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
end 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
---NOTE: does not check .valid
---@param station Station ---@param station Station
function set_station_from_comb(station) function set_station_from_comb(station)
--NOTE: this does nothing to update currently active deliveries --NOTE: this does nothing to update currently active deliveries
@@ -387,6 +391,7 @@ function set_station_from_comb(station)
station.network_flag = {} station.network_flag = {}
end end
end end
---NOTE: does not check .valid
---@param mod_settings CybersynModSettings ---@param mod_settings CybersynModSettings
---@param train Train ---@param train Train
---@param comb LuaEntity ---@param comb LuaEntity
@@ -437,9 +442,9 @@ end
---@param map_data MapData ---@param map_data MapData
---@param mod_settings CybersynModSettings ---@param mod_settings CybersynModSettings
---@param id uint ---@param id uint
function set_refueler_from_comb(map_data, mod_settings, id) ---@param refueler Refueler
function set_refueler_from_comb(map_data, mod_settings, id, refueler)
--NOTE: this does nothing to update currently active deliveries --NOTE: this does nothing to update currently active deliveries
local refueler = map_data.refuelers[id]
local params = get_comb_params(refueler.entity_comb) local params = get_comb_params(refueler.entity_comb)
local bits = params.second_constant or 0 local bits = params.second_constant or 0
local signal = params.first_signal local signal = params.first_signal
@@ -620,7 +625,6 @@ end
---@param station Station ---@param station Station
function get_signals(station) function get_signals(station)
--NOTE: the combinator must be valid, but checking for valid every time is too slow
local comb1 = station.entity_comb1 local comb1 = station.entity_comb1
local status1 = comb1.status local status1 = comb1.status
---@type Signal[]? ---@type Signal[]?
@@ -693,7 +697,7 @@ end
---@param train LuaTrain ---@param train LuaTrain
function send_alert_sounds(train) function send_alert_sounds(train)
local loco = train.front_stock or train.back_stock local loco = get_any_train_entity(train)
if loco then if loco then
for _, player in pairs(loco.force.players) do for _, player in pairs(loco.force.players) do
player.play_sound({path = ALERT_SOUND}) player.play_sound({path = ALERT_SOUND})

View File

@@ -34,6 +34,7 @@
---@field public allows_all_trains true? ---@field public allows_all_trains true?
---@field public deliveries_total int ---@field public deliveries_total int
---@field public last_delivery_tick int ---@field public last_delivery_tick int
---@field public trains_limit int --transient
---@field public priority int --transient ---@field public priority int --transient
---@field public item_priority int? --transient ---@field public item_priority int? --transient
---@field public r_threshold int >= 0 --transient ---@field public r_threshold int >= 0 --transient

View File

@@ -596,14 +596,15 @@ function update_stop_from_rail(map_data, rail, forbidden_entity, force)
return return
end end
if entity.name == "train-stop" then if entity.name == "train-stop" then
local id = entity.unit_number local id = entity.unit_number--[[@as uint]]
local is_station = true local is_station = true
---@type Station|Refueler
local stop = map_data.stations[id] local stop = map_data.stations[id]
if not stop then if not stop then
stop = map_data.refuelers[id] stop = map_data.refuelers[id]
is_station = false is_station = false
end end
if stop then if stop and stop.entity_stop.valid then
if force then if force then
reset_stop_layout(map_data, stop, is_station, forbidden_entity) reset_stop_layout(map_data, stop, is_station, forbidden_entity)
elseif not stop.allows_all_trains then elseif not stop.allows_all_trains then

View File

@@ -21,17 +21,19 @@ end
---@param map_data MapData ---@param map_data MapData
---@param depot_id uint ---@param depot_id uint
---@param depot Depot ---@param depot Depot
local function on_depot_broken(map_data, depot_id, depot) function on_depot_broken(map_data, depot_id, depot)
for train_id, train in pairs(map_data.trains) do for train_id, train in pairs(map_data.trains) do
if train.depot_id == depot_id then if train.depot_id == depot_id then
if train.use_any_depot then if train.use_any_depot then
local e = get_any_train_entity(train.entity) local e = get_any_train_entity(train.entity)
local stops = e.force.get_train_stops({name = depot.entity_stop.backer_name, surface = e.surface}) if e then
for stop in rnext_consume, stops do local stops = e.force.get_train_stops({name = depot.entity_stop.backer_name, surface = e.surface})
local new_depot_id = stop.unit_number for stop in rnext_consume, stops do
if map_data.depots[new_depot_id] then local new_depot_id = stop.unit_number
train.depot_id = new_depot_id--[[@as uint]] if map_data.depots[new_depot_id] then
goto continue train.depot_id = new_depot_id--[[@as uint]]
goto continue
end
end end
end end
end end
@@ -63,14 +65,14 @@ local function on_refueler_built(map_data, stop, comb)
} }
local id = stop.unit_number--[[@as uint]] local id = stop.unit_number--[[@as uint]]
map_data.refuelers[id] = refueler map_data.refuelers[id] = refueler
set_refueler_from_comb(map_data, mod_settings, id) set_refueler_from_comb(map_data, mod_settings, id, refueler)
update_stop_if_auto(map_data, refueler, false) update_stop_if_auto(map_data, refueler, false)
interface_raise_refueler_created(id) interface_raise_refueler_created(id)
end end
---@param map_data MapData ---@param map_data MapData
---@param refueler_id uint ---@param refueler_id uint
---@param refueler Refueler ---@param refueler Refueler
local function on_refueler_broken(map_data, refueler_id, refueler) function on_refueler_broken(map_data, refueler_id, refueler)
if refueler.trains_total > 0 then if refueler.trains_total > 0 then
--search for trains coming to the destroyed refueler --search for trains coming to the destroyed refueler
for train_id, train in pairs(map_data.trains) do for train_id, train in pairs(map_data.trains) do
@@ -121,6 +123,7 @@ local function on_station_built(map_data, stop, comb1, comb2)
--allows_all_trains = set_station_from_comb, --allows_all_trains = set_station_from_comb,
deliveries_total = 0, deliveries_total = 0,
last_delivery_tick = map_data.total_ticks, last_delivery_tick = map_data.total_ticks,
trains_limit = math.huge,
priority = 0, priority = 0,
item_priotity = nil, item_priotity = nil,
r_threshold = 0, r_threshold = 0,
@@ -150,7 +153,7 @@ end
---@param map_data MapData ---@param map_data MapData
---@param station_id uint ---@param station_id uint
---@param station Station ---@param station Station
local function on_station_broken(map_data, station_id, station) function on_station_broken(map_data, station_id, station)
if station.deliveries_total > 0 then if station.deliveries_total > 0 then
--search for trains coming to the destroyed station --search for trains coming to the destroyed station
for train_id, train in pairs(map_data.trains) do for train_id, train in pairs(map_data.trains) do
@@ -430,7 +433,7 @@ function combinator_update(map_data, comb, reset_display)
else else
local refueler = map_data.refuelers[id] local refueler = map_data.refuelers[id]
if refueler and refueler.entity_comb == comb then if refueler and refueler.entity_comb == comb then
set_refueler_from_comb(map_data, mod_settings, id) set_refueler_from_comb(map_data, mod_settings, id, refueler)
end end
end end
end end
@@ -448,7 +451,7 @@ function combinator_update(map_data, comb, reset_display)
local refueler = map_data.refuelers[id] local refueler = map_data.refuelers[id]
if refueler then if refueler then
local pre = refueler.allows_all_trains local pre = refueler.allows_all_trains
set_refueler_from_comb(map_data, mod_settings, id) set_refueler_from_comb(map_data, mod_settings, id, refueler)
if refueler.allows_all_trains ~= pre then if refueler.allows_all_trains ~= pre then
update_stop_if_auto(map_data, refueler, false) update_stop_if_auto(map_data, refueler, false)
end end
@@ -757,19 +760,27 @@ local function setup_se_compat()
if schedule then if schedule then
if train.status == STATUS_TO_P then if train.status == STATUS_TO_P then
local stop = map_data.stations[train.p_station_id].entity_stop local stop = map_data.stations[train.p_station_id].entity_stop
se_add_direct_to_station_order(schedule, stop, old_surface_index) if stop.valid then
se_add_direct_to_station_order(schedule, stop, old_surface_index)
end
end end
if train.status == STATUS_TO_P or train.status == STATUS_TO_R then if train.status == STATUS_TO_P or train.status == STATUS_TO_R then
local stop = map_data.stations[train.r_station_id].entity_stop local stop = map_data.stations[train.r_station_id].entity_stop
se_add_direct_to_station_order(schedule, stop, old_surface_index) if stop.valid then
se_add_direct_to_station_order(schedule, stop, old_surface_index)
end
end end
if train.status == STATUS_TO_F then if train.status == STATUS_TO_F then
local stop = map_data.refuelers[train.refueler_id].entity_stop local stop = map_data.refuelers[train.refueler_id].entity_stop
se_add_direct_to_station_order(schedule, stop, old_surface_index) if stop.valid then
se_add_direct_to_station_order(schedule, stop, old_surface_index)
end
end end
if not train.use_any_depot then if not train.use_any_depot then
local depot = map_data.depots[train.depot_id] local stop = map_data.depots[train.depot_id].entity_stop
se_add_direct_to_station_order(schedule, depot.entity_stop, old_surface_index) if stop.valid then
se_add_direct_to_station_order(schedule, stop, old_surface_index)
end
end end
train_entity.schedule = schedule train_entity.schedule = schedule
end end

View File

@@ -34,18 +34,22 @@ function on_failed_delivery(map_data, train_id, train)
local is_r_in_progress = is_p_in_progress or train.status == STATUS_TO_R or train.status == STATUS_R local is_r_in_progress = is_p_in_progress or train.status == STATUS_TO_R or train.status == STATUS_R
if is_p_in_progress then if is_p_in_progress then
local station = map_data.stations[p_station_id] local station = map_data.stations[p_station_id]
remove_manifest(map_data, station, manifest, 1) if station.entity_comb1.valid and (not station.entity_comb2 or station.entity_comb2.valid) then
if train.status == STATUS_P then remove_manifest(map_data, station, manifest, 1)
set_comb1(map_data, station, nil) if train.status == STATUS_P then
unset_wagon_combs(map_data, station) set_comb1(map_data, station, nil)
unset_wagon_combs(map_data, station)
end
end end
end end
if is_r_in_progress then if is_r_in_progress then
local station = map_data.stations[r_station_id] local station = map_data.stations[r_station_id]
remove_manifest(map_data, station, manifest, -1) if station.entity_comb1.valid and (not station.entity_comb2 or station.entity_comb2.valid) then
if train.status == STATUS_R then remove_manifest(map_data, station, manifest, -1)
set_comb1(map_data, station, nil) if train.status == STATUS_R then
unset_wagon_combs(map_data, station) set_comb1(map_data, station, nil)
unset_wagon_combs(map_data, station)
end
end end
end end
if train.has_filtered_wagon then if train.has_filtered_wagon then
@@ -100,7 +104,9 @@ end
---@param train Train ---@param train Train
function add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot) function add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot)
local comb = depot.entity_comb local comb = depot.entity_comb
set_train_from_comb(mod_settings, train, comb) if comb.valid then
set_train_from_comb(mod_settings, train, comb)
end
depot.available_train_id = train_id depot.available_train_id = train_id
train.depot_id = depot_id train.depot_id = depot_id
train.status = STATUS_D train.status = STATUS_D
@@ -141,8 +147,9 @@ end
---@param map_data MapData ---@param map_data MapData
---@param depot_id uint ---@param depot_id uint
---@param depot Depot
---@param train_entity LuaTrain ---@param train_entity LuaTrain
local function on_train_arrives_depot(map_data, depot_id, train_entity) local function on_train_arrives_depot(map_data, depot_id, depot, train_entity)
local is_train_empty = next(train_entity.get_contents()) == nil and next(train_entity.get_fluid_contents()) == nil local is_train_empty = next(train_entity.get_contents()) == nil and next(train_entity.get_fluid_contents()) == nil
local train_id = train_entity.id local train_id = train_entity.id
local train = map_data.trains[train_id] local train = map_data.trains[train_id]
@@ -161,7 +168,6 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity)
end end
if is_train_empty or mod_settings.allow_cargo_in_depot then if is_train_empty or mod_settings.allow_cargo_in_depot then
local old_status = train.status local old_status = train.status
local depot = map_data.depots[depot_id]
add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot) add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot)
set_depot_schedule(train_entity, depot.entity_stop.backer_name) set_depot_schedule(train_entity, depot.entity_stop.backer_name)
interface_raise_train_status_changed(train_id, old_status, STATUS_D) interface_raise_train_status_changed(train_id, old_status, STATUS_D)
@@ -194,7 +200,6 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity)
}--[[@as Train]] }--[[@as Train]]
set_train_layout(map_data, train) set_train_layout(map_data, train)
map_data.trains[train_id] = train map_data.trains[train_id] = train
local depot = map_data.depots[depot_id]
add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot) add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot)
set_depot_schedule(train_entity, depot.entity_stop.backer_name) set_depot_schedule(train_entity, depot.entity_stop.backer_name)
@@ -208,20 +213,18 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity)
end end
end end
---@param map_data MapData ---@param map_data MapData
---@param station_id uint ---@param station Station
---@param train_id uint ---@param train_id uint
---@param train Train ---@param train Train
local function on_train_arrives_station(map_data, station_id, train_id, train) local function on_train_arrives_station(map_data, station, train_id, train)
---@type uint ---@type uint
if train.status == STATUS_TO_P then if train.status == STATUS_TO_P then
train.status = STATUS_P train.status = STATUS_P
local station = map_data.stations[station_id]
set_comb1(map_data, station, train.manifest, mod_settings.invert_sign and 1 or -1) set_comb1(map_data, station, train.manifest, mod_settings.invert_sign and 1 or -1)
set_p_wagon_combs(map_data, station, train) set_p_wagon_combs(map_data, station, train)
interface_raise_train_status_changed(train_id, STATUS_TO_P, STATUS_P) interface_raise_train_status_changed(train_id, STATUS_TO_P, STATUS_P)
elseif train.status == STATUS_TO_R then elseif train.status == STATUS_TO_R then
train.status = STATUS_R train.status = STATUS_R
local station = map_data.stations[station_id]
set_comb1(map_data, station, train.manifest, mod_settings.invert_sign and -1 or 1) set_comb1(map_data, station, train.manifest, mod_settings.invert_sign and -1 or 1)
set_r_wagon_combs(map_data, station, train) set_r_wagon_combs(map_data, station, train)
interface_raise_train_status_changed(train_id, STATUS_TO_R, STATUS_R) interface_raise_train_status_changed(train_id, STATUS_TO_R, STATUS_R)
@@ -229,12 +232,11 @@ local function on_train_arrives_station(map_data, station_id, train_id, train)
end end
---@param map_data MapData ---@param map_data MapData
---@param refueler_id uint ---@param refueler Refueler
---@param train_id uint ---@param train_id uint
---@param train Train ---@param train Train
local function on_train_arrives_refueler(map_data, refueler_id, train_id, train) local function on_train_arrives_refueler(map_data, refueler, train_id, train)
if train.status == STATUS_TO_F then if train.status == STATUS_TO_F then
local refueler = map_data.refuelers[refueler_id]
train.status = STATUS_F train.status = STATUS_F
set_refueler_combs(map_data, refueler, train) set_refueler_combs(map_data, refueler, train)
interface_raise_train_status_changed(train_id, STATUS_TO_F, STATUS_F) interface_raise_train_status_changed(train_id, STATUS_TO_F, STATUS_F)
@@ -319,21 +321,23 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train)
local best_prior = -INF local best_prior = -INF
for id, _ in pairs(refuelers) do for id, _ in pairs(refuelers) do
local refueler = map_data.refuelers[id] local refueler = map_data.refuelers[id]
set_refueler_from_comb(map_data, mod_settings, id) if not refueler.entity_stop.valid or not refueler.entity_comb.valid then
on_refueler_broken(map_data, id, refueler)
else
set_refueler_from_comb(map_data, mod_settings, id, refueler)
local refueler_network_flag = get_network_flag(refueler, network_name) local refueler_network_flag = get_network_flag(refueler, network_name)
local train_network_flag = get_network_flag(train, network_name) local train_network_flag = get_network_flag(train, network_name)
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 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 if refueler.priority >= best_prior then
local dist = nil local t = get_any_train_entity(train.entity)
if refueler.priority == best_prior then local dist = t and get_dist(t, refueler.entity_stop) or INF
dist = get_stop_dist(train.entity.front_stock, refueler.entity_stop) if refueler.priority > best_prior or dist < best_dist then
accepted = dist < best_dist best_refueler_id = id
end best_dist = dist
if accepted or refueler.priority > best_prior then best_prior = refueler.priority
best_refueler_id = id end
best_dist = dist or get_stop_dist(train.entity.front_stock, refueler.entity_stop) end
best_prior = refueler.priority
end end
end end
end end
@@ -358,7 +362,9 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train)
train.refueler_id = nil train.refueler_id = nil
refueler.trains_total = refueler.trains_total - 1 refueler.trains_total = refueler.trains_total - 1
unset_wagon_combs(map_data, refueler) unset_wagon_combs(map_data, refueler)
set_combinator_output(map_data, refueler.entity_comb, nil) if refueler.entity_comb.valid then
set_combinator_output(map_data, refueler.entity_comb, nil)
end
if not train.disable_bypass then if not train.disable_bypass then
train.status = STATUS_TO_D_BYPASS train.status = STATUS_TO_D_BYPASS
add_available_train(map_data, train_id, train) add_available_train(map_data, train_id, train)
@@ -427,8 +433,13 @@ function on_train_changed(event)
local stop = train_e.station local stop = train_e.station
if stop and stop.valid and stop.name == "train-stop" then if stop and stop.valid and stop.name == "train-stop" then
local id = stop.unit_number--[[@as uint]] local id = stop.unit_number--[[@as uint]]
if map_data.depots[id] then local depot = map_data.depots[id]
on_train_arrives_depot(map_data, id, train_e) if depot then
if depot.entity_comb.valid and depot.entity_stop.valid then
on_train_arrives_depot(map_data, id, depot, train_e)
else
on_depot_broken(map_data, id, depot)
end
end end
else else
local train = map_data.trains[train_id] local train = map_data.trains[train_id]
@@ -451,11 +462,13 @@ function on_train_changed(event)
station = map_data.refuelers[id] station = map_data.refuelers[id]
is_station = false is_station = false
end end
if id and station.entity_stop.connected_rail == rail then if id and station.entity_stop.valid and station.entity_stop.connected_rail == rail then
if is_station then if is_station then
on_train_arrives_station(map_data, id, train_id, train) if station.entity_comb1 and (not station.entity_comb2 or station.entity_comb2.valid) then
else on_train_arrives_station(map_data, station, train_id, train)
on_train_arrives_refueler(map_data, id, train_id, train) end
elseif station.entity_comb.valid then
on_train_arrives_refueler(map_data, station, train_id, train)
end end
end end
end end