mirror of
https://github.com/Xevion/project-cybersyn.git
synced 2025-12-08 12:08:09 -06:00
added a refueler
This commit is contained in:
@@ -117,4 +117,5 @@ Date: 2022-12-5
|
||||
Features:
|
||||
- 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 refueler stations
|
||||
- Slightly more permissive allow-list logic
|
||||
- Fixed a crash relating to wagon control combinators on request stations
|
||||
|
||||
@@ -3,8 +3,9 @@
|
||||
require("scripts.constants")
|
||||
require("scripts.global")
|
||||
require("scripts.factorio-api")
|
||||
require("scripts.central-planning")
|
||||
require("scripts.layout")
|
||||
require("scripts.central-planning")
|
||||
require("scripts.train-events")
|
||||
require("scripts.gui")
|
||||
require("scripts.migrations")
|
||||
require("scripts.main")
|
||||
|
||||
@@ -175,7 +175,7 @@ function send_train_between(map_data, r_station_id, p_station_id, train_id, prim
|
||||
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_D_TO_P
|
||||
train.status = STATUS_TO_P
|
||||
train.p_station_id = p_station_id
|
||||
train.r_station_id = r_station_id
|
||||
train.manifest = manifest
|
||||
|
||||
@@ -20,6 +20,7 @@ OPERATION_PRIMARY_IO_ACTIVE = "<<"
|
||||
OPERATION_SECONDARY_IO = "%"
|
||||
OPERATION_DEPOT = "+"
|
||||
OPERATION_WAGON_MANIFEST = "-"
|
||||
OPERATION_REFUELER = ">>"
|
||||
|
||||
NETWORK_SIGNAL_DEFAULT = {name="signal-A", type="virtual"}
|
||||
INACTIVITY_TIME = 100
|
||||
@@ -29,11 +30,14 @@ DELTA = 1/2048
|
||||
DEPOT_PRIORITY_MULT = 2048
|
||||
|
||||
STATUS_D = 0
|
||||
STATUS_D_TO_P = 1
|
||||
STATUS_TO_P = 1
|
||||
STATUS_P = 2
|
||||
STATUS_P_TO_R = 3
|
||||
STATUS_TO_R = 3
|
||||
STATUS_R = 4
|
||||
STATUS_R_TO_D = 5
|
||||
STATUS_TO_D = 5
|
||||
STATUS_TO_D_BYPASS = 6
|
||||
STATUS_TO_F = 7
|
||||
STATUS_F = 8
|
||||
STATUS_CUSTOM = 256 --this status and any status greater than it can be used by other mods (I've reserved the lower integers for myself in case I want to add more statuses)
|
||||
|
||||
LONGEST_INSERTER_REACH = 2
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
--By Mami
|
||||
local get_distance = require("__flib__.misc").get_distance
|
||||
local abs = math.abs
|
||||
local floor = math.floor
|
||||
local table_insert = table.insert
|
||||
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
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
@@ -130,7 +133,7 @@ function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, m
|
||||
local t_surface_i = t_surface.index
|
||||
local p_surface_i = p_surface.index
|
||||
local r_surface_i = r_surface.index
|
||||
if t_surface_i == p_surface_i and p_surface_i == r_surface_i then
|
||||
if t_surface_i == p_surface_i and p_surface_i == r_surface_i and d_surface_i == t_surface_i then
|
||||
train.schedule = {current = start_at_depot and 1 or 2, records = {
|
||||
create_inactivity_order(depot_name),
|
||||
create_direct_to_station_order(p_stop),
|
||||
@@ -159,7 +162,9 @@ function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, m
|
||||
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
|
||||
if t_surface_i == r_surface_i then
|
||||
records[#records + 1] = create_direct_to_station_order(r_stop)
|
||||
elseif 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
|
||||
end
|
||||
@@ -190,6 +195,46 @@ function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, m
|
||||
return true
|
||||
end
|
||||
|
||||
---@param train LuaTrain
|
||||
---@param stop LuaEntity
|
||||
function add_refueler_schedule(train, stop)
|
||||
local schedule = train.schedule or {current = 1, records = {}}
|
||||
local i = schedule.current
|
||||
|
||||
local t_surface = train.front_stock.surface
|
||||
local f_surface = stop.surface
|
||||
local t_surface_i = t_surface.index
|
||||
local f_surface_i = f_surface.index
|
||||
if t_surface_i == f_surface_i then
|
||||
table_insert(schedule.records, i, create_direct_to_station_order(stop))
|
||||
i = i + 1
|
||||
table_insert(schedule.records, i, create_inactivity_order(stop.backer_name))
|
||||
|
||||
train.schedule = schedule
|
||||
elseif IS_SE_PRESENT then
|
||||
local t_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = t_surface_i})
|
||||
local other_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = f_surface})
|
||||
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)
|
||||
local cur_order = schedule.records[i]
|
||||
local is_elevator_in_orders_already = cur_order and cur_order.station == elevator_name..(is_train_in_orbit and SE_ELEVATOR_ORBIT_SUFFIX or SE_ELEVATOR_PLANET_SUFFIX)
|
||||
if not is_elevator_in_orders_already then
|
||||
table_insert(schedule.records, i, se_create_elevator_order(elevator_name, is_train_in_orbit))
|
||||
end
|
||||
i = i + 1
|
||||
is_train_in_orbit = not is_train_in_orbit
|
||||
table_insert(schedule.records, i, create_inactivity_order(stop.backer_name))
|
||||
i = i + 1
|
||||
if not is_elevator_in_orders_already then
|
||||
table_insert(schedule.records, i, se_create_elevator_order(elevator_name, is_train_in_orbit))
|
||||
i = i + 1
|
||||
is_train_in_orbit = not is_train_in_orbit
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
--[[combinators]]--
|
||||
@@ -253,6 +298,34 @@ 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 mod_settings CybersynModSettings
|
||||
---@param refueler Refueler
|
||||
function set_refueler_from_comb(mod_settings, refueler)
|
||||
--NOTE: this does nothing to update currently active deliveries
|
||||
local params = get_comb_params(refueler.entity_comb)
|
||||
local bits = params.second_constant or 0
|
||||
local signal = params.first_signal
|
||||
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 not signals then return end
|
||||
for k, v in pairs(signals) do
|
||||
local item_name = v.signal.name
|
||||
local item_count = v.count
|
||||
if item_name then
|
||||
if item_name == SIGNAL_PRIORITY then
|
||||
refueler.priority = item_count
|
||||
end
|
||||
if item_name == refueler.network_name then
|
||||
refueler.network_flag = item_count
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
function update_display(map_data, station)
|
||||
@@ -320,9 +393,6 @@ function set_combinator_output(map_data, comb, signals)
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
---@param station Station
|
||||
function get_signals(station)
|
||||
--NOTE: the combinator must be valid, but checking for valid every time is too slow
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
---@field public active_station_ids uint[]
|
||||
---@field public warmup_station_ids uint[]
|
||||
---@field public depots {[uint]: Depot}
|
||||
---@field public refuelers {[uint]: Refueler}
|
||||
---@field public trains {[uint]: Train}
|
||||
---@field public available_trains {[string]: {[uint]: true?}} --{[network_name]: {[train_id]: depot_id}}
|
||||
---@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 layouts {[uint]: (0|1|2)[]}
|
||||
---@field public layout_train_count {[uint]: int}
|
||||
---@field public tick_state uint
|
||||
@@ -29,6 +31,7 @@
|
||||
---@field public deliveries_total int
|
||||
---@field public last_delivery_tick int
|
||||
---@field public priority int --transient
|
||||
---@field public item_priority int? --transient
|
||||
---@field public r_threshold int >= 0 --transient
|
||||
---@field public locked_slots int >= 0 --transient
|
||||
---@field public network_name string?
|
||||
@@ -38,7 +41,8 @@
|
||||
---@field public accepted_layouts {[uint]: true?}
|
||||
---@field public layout_pattern (0|1|2|3)[]?
|
||||
---@field public tick_signals {[uint]: Signal}? --transient
|
||||
---@field public p_count_or_r_threshold_per_item {[string]: int} --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
|
||||
|
||||
---@class Depot
|
||||
@@ -46,15 +50,26 @@
|
||||
---@field public entity_comb LuaEntity
|
||||
---@field public available_train_id uint?--train_id
|
||||
|
||||
---@class Refueler
|
||||
---@field public entity_stop LuaEntity
|
||||
---@field public entity_comb LuaEntity
|
||||
---@field public trains_total int
|
||||
---@field public accepted_layouts {[uint]: true?}
|
||||
---@field public layout_pattern (0|1|2|3)[]?
|
||||
---@field public allows_all_trains boolean
|
||||
---@field public priority int
|
||||
---@field public network_name string?
|
||||
---@field public network_flag int
|
||||
|
||||
---@class Train
|
||||
---@field public entity LuaTrain --should only be invalid if se_is_being_teleported is true
|
||||
---@field public layout_id uint
|
||||
---@field public item_slot_capacity int
|
||||
---@field public fluid_capacity int
|
||||
---@field public status int
|
||||
---@field public p_station_id uint
|
||||
---@field public r_station_id uint
|
||||
---@field public manifest Manifest
|
||||
---@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 true?
|
||||
---@field public is_available true?
|
||||
@@ -63,6 +78,7 @@
|
||||
---@field public network_name string? --can only be nil when the train is parked at a depot
|
||||
---@field public network_flag int
|
||||
---@field public priority int
|
||||
---@field public refueler_id uint?
|
||||
---@field public se_depot_surface_i uint --se only
|
||||
---@field public se_is_being_teleported true? --se only
|
||||
---@field public se_awaiting_removal any? --se only
|
||||
|
||||
@@ -30,11 +30,11 @@ end
|
||||
|
||||
---@param layout_pattern (0|1|2|3)[]
|
||||
---@param layout (0|1|2)[]
|
||||
function is_layout_accepted(layout_pattern, layout)
|
||||
function is_refuel_layout_accepted(layout_pattern, layout)
|
||||
local valid = true
|
||||
for i, v in ipairs(layout) do
|
||||
local p = layout_pattern[i] or 0
|
||||
if (v == 0 and p == 2) or (v == 1 and (p == 0 or p == 2)) or (v == 2 and (p == 0 or p == 1)) then
|
||||
if (v == 1 and (p == 1 or p == 3)) or (v == 2 and (p == 2 or p == 3)) then
|
||||
valid = false
|
||||
break
|
||||
end
|
||||
@@ -42,7 +42,28 @@ function is_layout_accepted(layout_pattern, layout)
|
||||
if valid or not layout[0] then return valid end
|
||||
for i, v in irpairs(layout) do
|
||||
local p = layout_pattern[i] or 0
|
||||
if (v == 0 and p == 2) or (v == 1 and (p == 0 or p == 2)) or (v == 2 and (p == 0 or p == 1)) then
|
||||
if (v == 1 and (p == 1 or p == 3)) or (v == 2 and (p == 2 or p == 3)) then
|
||||
valid = false
|
||||
break
|
||||
end
|
||||
end
|
||||
return valid
|
||||
end
|
||||
---@param layout_pattern (0|1|2|3)[]
|
||||
---@param layout (0|1|2)[]
|
||||
function is_layout_accepted(layout_pattern, layout)
|
||||
local valid = true
|
||||
for i, v in ipairs(layout) do
|
||||
local p = layout_pattern[i] or 0
|
||||
if (v == 1 and not (p == 1 or p == 3)) or (v == 2 and not (p == 2 or p == 3)) then
|
||||
valid = false
|
||||
break
|
||||
end
|
||||
end
|
||||
if valid or not layout[0] then return valid end
|
||||
for i, v in irpairs(layout) do
|
||||
local p = layout_pattern[i] or 0
|
||||
if (v == 1 and not (p == 1 or p == 3)) or (v == 2 and not (p == 2 or p == 3)) then
|
||||
valid = false
|
||||
break
|
||||
end
|
||||
@@ -142,7 +163,7 @@ end
|
||||
function set_p_wagon_combs(map_data, station, train)
|
||||
if not station.wagon_combs or not next(station.wagon_combs) then return end
|
||||
local carriages = train.entity.carriages
|
||||
local manifest = train.manifest
|
||||
local manifest = train.manifest--[[@as Manifest]]
|
||||
|
||||
local is_reversed = get_train_direction(station.entity_stop, train.entity)
|
||||
|
||||
@@ -325,57 +346,58 @@ end
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
---@param stop Station|Refueler
|
||||
---@param is_station_or_refueler boolean
|
||||
---@param forbidden_entity LuaEntity?
|
||||
function reset_station_layout(map_data, station, forbidden_entity)
|
||||
function reset_stop_layout(map_data, stop, is_station_or_refueler, forbidden_entity)
|
||||
--NOTE: station must be in auto mode
|
||||
local station_rail = station.entity_stop.connected_rail
|
||||
if station_rail == nil then
|
||||
local stop_rail = stop.entity_stop.connected_rail
|
||||
if stop_rail == nil then
|
||||
--cannot accept deliveries
|
||||
station.layout_pattern = nil
|
||||
station.accepted_layouts = {}
|
||||
stop.layout_pattern = nil
|
||||
stop.accepted_layouts = {}
|
||||
return
|
||||
end
|
||||
local rail_direction_from_station
|
||||
if station.entity_stop.connected_rail_direction == defines.rail_direction.front then
|
||||
rail_direction_from_station = defines.rail_direction.back
|
||||
local rail_direction_from_stop
|
||||
if stop.entity_stop.connected_rail_direction == defines.rail_direction.front then
|
||||
rail_direction_from_stop = defines.rail_direction.back
|
||||
else
|
||||
rail_direction_from_station = defines.rail_direction.front
|
||||
rail_direction_from_stop = defines.rail_direction.front
|
||||
end
|
||||
local station_direction = station.entity_stop.direction
|
||||
local surface = station.entity_stop.surface
|
||||
local middle_x = station_rail.position.x
|
||||
local middle_y = station_rail.position.y
|
||||
local stop_direction = stop.entity_stop.direction
|
||||
local surface = stop.entity_stop.surface
|
||||
local middle_x = stop_rail.position.x
|
||||
local middle_y = stop_rail.position.y
|
||||
local reach = LONGEST_INSERTER_REACH + 1
|
||||
local search_area
|
||||
local area_delta
|
||||
local is_ver
|
||||
if station_direction == defines.direction.north then
|
||||
if stop_direction == defines.direction.north then
|
||||
search_area = {left_top = {x = middle_x - reach, y = middle_y}, right_bottom = {x = middle_x + reach, y = middle_y + 6}}
|
||||
area_delta = {x = 0, y = 7}
|
||||
is_ver = true
|
||||
elseif station_direction == defines.direction.east then
|
||||
elseif stop_direction == defines.direction.east then
|
||||
search_area = {left_top = {y = middle_y - reach, x = middle_x - 6}, right_bottom = {y = middle_y + reach, x = middle_x}}
|
||||
area_delta = {x = -7, y = 0}
|
||||
is_ver = false
|
||||
elseif station_direction == defines.direction.south then
|
||||
elseif stop_direction == defines.direction.south then
|
||||
search_area = {left_top = {x = middle_x - reach, y = middle_y - 6}, right_bottom = {x = middle_x + reach, y = middle_y}}
|
||||
area_delta = {x = 0, y = -7}
|
||||
is_ver = true
|
||||
elseif station_direction == defines.direction.west then
|
||||
elseif stop_direction == defines.direction.west then
|
||||
search_area = {left_top = {y = middle_y - reach, x = middle_x}, right_bottom = {y = middle_y + reach, x = middle_x + 6}}
|
||||
area_delta = {x = 7, y = 0}
|
||||
is_ver = false
|
||||
else
|
||||
assert(false, "cybersyn: invalid station direction")
|
||||
assert(false, "cybersyn: invalid stop direction")
|
||||
end
|
||||
local length = 2
|
||||
local pre_rail = station_rail
|
||||
local pre_rail = stop_rail
|
||||
local layout_pattern = {0}
|
||||
local type_filter = {"inserter", "pump", "arithmetic-combinator"}
|
||||
local wagon_number = 0
|
||||
for i = 1, 112 do
|
||||
local rail, rail_direction, rail_connection_direction = pre_rail.get_connected_rail({rail_direction = rail_direction_from_station, rail_connection_direction = defines.rail_connection_direction.straight})
|
||||
local rail, rail_direction, rail_connection_direction = pre_rail.get_connected_rail({rail_direction = rail_direction_from_stop, rail_connection_direction = defines.rail_connection_direction.straight})
|
||||
if not rail or rail_connection_direction ~= defines.rail_connection_direction.straight or not rail.valid then
|
||||
is_break = true
|
||||
break
|
||||
@@ -426,7 +448,7 @@ function reset_station_layout(map_data, station, forbidden_entity)
|
||||
supports_fluid = true
|
||||
end
|
||||
end
|
||||
elseif entity.name == COMBINATOR_NAME then
|
||||
elseif entity.name == COMBINATOR_NAME and is_station_or_refueler then
|
||||
local param = map_data.to_comb_params[entity.unit_number]
|
||||
if param.operation == OPERATION_WAGON_MANIFEST then
|
||||
local pos = entity.position
|
||||
@@ -437,10 +459,10 @@ function reset_station_layout(map_data, station, forbidden_entity)
|
||||
is_there = middle_y - 2.1 <= pos.y and pos.y <= middle_y + 2.1
|
||||
end
|
||||
if is_there then
|
||||
if not station.wagon_combs then
|
||||
station.wagon_combs = {}
|
||||
if not stop.wagon_combs then
|
||||
stop.wagon_combs = {}
|
||||
end
|
||||
station.wagon_combs[wagon_number] = entity
|
||||
stop.wagon_combs[wagon_number] = entity
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -461,18 +483,19 @@ function reset_station_layout(map_data, station, forbidden_entity)
|
||||
search_area = area.move(search_area, area_delta)
|
||||
end
|
||||
end
|
||||
station.layout_pattern = layout_pattern
|
||||
stop.layout_pattern = layout_pattern
|
||||
for id, layout in pairs(map_data.layouts) do
|
||||
station.accepted_layouts[id] = is_layout_accepted(layout_pattern, layout) or nil
|
||||
stop.accepted_layouts[id] = is_layout_accepted(layout_pattern, layout) or nil
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
---@param stop Station|Refueler
|
||||
---@param is_station_or_refueler boolean
|
||||
---@param forbidden_entity LuaEntity?
|
||||
function update_station_if_auto(map_data, station, forbidden_entity)
|
||||
if not station.allows_all_trains then
|
||||
reset_station_layout(map_data, station, forbidden_entity)
|
||||
function update_stop_if_auto(map_data, stop, is_station_or_refueler, forbidden_entity)
|
||||
if not stop.allows_all_trains then
|
||||
reset_stop_layout(map_data, stop, is_station_or_refueler, forbidden_entity)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -480,7 +503,7 @@ end
|
||||
---@param rail LuaEntity
|
||||
---@param forbidden_entity LuaEntity?
|
||||
---@param force boolean?
|
||||
function update_station_from_rail(map_data, rail, forbidden_entity, force)
|
||||
function update_stop_from_rail(map_data, rail, forbidden_entity, force)
|
||||
--NOTE: is this a correct way to figure out the direction?
|
||||
---@type defines.rail_direction
|
||||
local rail_direction = defines.rail_direction.back
|
||||
@@ -494,12 +517,18 @@ function update_station_from_rail(map_data, rail, forbidden_entity, force)
|
||||
return
|
||||
end
|
||||
if entity.name == "train-stop" then
|
||||
local station = map_data.stations[entity.unit_number]
|
||||
if station then
|
||||
local id = entity.unit_number
|
||||
local is_station = true
|
||||
local stop = map_data.stations[id]
|
||||
if not stop then
|
||||
stop = map_data.refuelers[id]
|
||||
is_station = false
|
||||
end
|
||||
if stop then
|
||||
if force then
|
||||
reset_station_layout(map_data, station, forbidden_entity)
|
||||
else
|
||||
update_station_if_auto(map_data, station, forbidden_entity)
|
||||
reset_stop_layout(map_data, stop, is_station, forbidden_entity)
|
||||
elseif not stop.allows_all_trains then
|
||||
reset_stop_layout(map_data, stop, is_station, forbidden_entity)
|
||||
end
|
||||
end
|
||||
return
|
||||
@@ -516,15 +545,15 @@ end
|
||||
---@param map_data MapData
|
||||
---@param pump LuaEntity
|
||||
---@param forbidden_entity LuaEntity?
|
||||
function update_station_from_pump(map_data, pump, forbidden_entity)
|
||||
function update_stop_from_pump(map_data, pump, forbidden_entity)
|
||||
if pump.pump_rail_target then
|
||||
update_station_from_rail(map_data, pump.pump_rail_target, forbidden_entity)
|
||||
update_stop_from_rail(map_data, pump.pump_rail_target, forbidden_entity)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param inserter LuaEntity
|
||||
---@param forbidden_entity LuaEntity?
|
||||
function update_station_from_inserter(map_data, inserter, forbidden_entity)
|
||||
function update_stop_from_inserter(map_data, inserter, forbidden_entity)
|
||||
local surface = inserter.surface
|
||||
|
||||
--NOTE: we don't use find_entity solely for miniloader compat
|
||||
@@ -534,7 +563,7 @@ function update_station_from_inserter(map_data, inserter, forbidden_entity)
|
||||
radius = 1,
|
||||
})
|
||||
if rails[1] then
|
||||
update_station_from_rail(map_data, rails[1], forbidden_entity)
|
||||
update_stop_from_rail(map_data, rails[1], forbidden_entity)
|
||||
end
|
||||
rails = surface.find_entities_filtered({
|
||||
type = "straight-rail",
|
||||
@@ -542,6 +571,6 @@ function update_station_from_inserter(map_data, inserter, forbidden_entity)
|
||||
radius = 1,
|
||||
})
|
||||
if rails[1] then
|
||||
update_station_from_rail(map_data, rails[1], forbidden_entity)
|
||||
update_stop_from_rail(map_data, rails[1], forbidden_entity)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,138 +4,6 @@ local ceil = math.ceil
|
||||
local table_insert = table.insert
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
---@param manifest Manifest
|
||||
---@param sign int?
|
||||
local function set_comb1(map_data, station, manifest, sign)
|
||||
local comb = station.entity_comb1
|
||||
if comb.valid then
|
||||
if manifest then
|
||||
local signals = {}
|
||||
for i, item in ipairs(manifest) do
|
||||
signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = sign*item.count}
|
||||
end
|
||||
set_combinator_output(map_data, comb, signals)
|
||||
else
|
||||
set_combinator_output(map_data, comb, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function on_failed_delivery(map_data, train_id, train)
|
||||
--NOTE: must either change this train's status or remove it after this call
|
||||
local p_station_id = train.p_station_id
|
||||
local r_station_id = train.r_station_id
|
||||
local manifest = train.manifest
|
||||
local is_p_in_progress = train.status == STATUS_D_TO_P or train.status == STATUS_P
|
||||
local is_r_in_progress = is_p_in_progress or train.status == STATUS_P_TO_R or train.status == STATUS_R
|
||||
if is_p_in_progress then
|
||||
local station = map_data.stations[p_station_id]
|
||||
remove_manifest(map_data, station, manifest, 1)
|
||||
if train.status == STATUS_P then
|
||||
set_comb1(map_data, station, nil)
|
||||
unset_wagon_combs(map_data, station)
|
||||
end
|
||||
end
|
||||
if is_r_in_progress then
|
||||
local station = map_data.stations[r_station_id]
|
||||
remove_manifest(map_data, station, manifest, -1)
|
||||
if train.status == STATUS_R then
|
||||
set_comb1(map_data, station, nil)
|
||||
unset_wagon_combs(map_data, station)
|
||||
end
|
||||
end
|
||||
train.r_station_id = 0
|
||||
train.p_station_id = 0
|
||||
train.manifest = nil
|
||||
interface_raise_train_failed_delivery(train_id, is_p_in_progress, p_station_id, is_r_in_progress, r_station_id, manifest)
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function add_available_train(map_data, train_id, train)
|
||||
local network_name = train.network_name
|
||||
if network_name then
|
||||
local network = map_data.available_trains[network_name]
|
||||
if not network then
|
||||
network = {}
|
||||
map_data.available_trains[network_name] = network
|
||||
end
|
||||
network[train_id] = true
|
||||
train.is_available = true
|
||||
interface_raise_train_available(train_id)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param mod_settings CybersynModSettings
|
||||
---@param depot_id uint
|
||||
---@param depot Depot
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot)
|
||||
local comb = depot.entity_comb
|
||||
local network_name = get_comb_network_name(comb)
|
||||
if network_name then
|
||||
local network = map_data.available_trains[network_name]
|
||||
if not network then
|
||||
network = {}
|
||||
map_data.available_trains[network_name] = network
|
||||
end
|
||||
network[train_id] = true
|
||||
train.is_available = true
|
||||
end
|
||||
depot.available_train_id = train_id
|
||||
train.status = STATUS_D
|
||||
train.parked_at_depot_id = depot_id
|
||||
train.depot_name = depot.entity_stop.backer_name
|
||||
train.se_depot_surface_i = depot.entity_stop.surface.index
|
||||
train.network_name = network_name
|
||||
train.network_flag = mod_settings.network_flag
|
||||
train.priority = 0
|
||||
if network_name then
|
||||
local signals = comb.get_merged_signals(defines.circuit_connector_id.combinator_input)
|
||||
if signals then
|
||||
for k, v in pairs(signals) do
|
||||
local item_name = v.signal.name
|
||||
local item_count = v.count
|
||||
if item_name then
|
||||
if item_name == SIGNAL_PRIORITY then
|
||||
train.priority = item_count
|
||||
end
|
||||
if item_name == network_name then
|
||||
train.network_flag = item_count
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
interface_raise_train_available(train_id)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function remove_available_train(map_data, train_id, train)
|
||||
---@type uint
|
||||
if train.is_available and train.network_name then
|
||||
local network = map_data.available_trains[train.network_name--[[@as string]]]
|
||||
if network then
|
||||
network[train_id] = nil
|
||||
if next(network) == nil then
|
||||
map_data.available_trains[train.network_name] = nil
|
||||
end
|
||||
end
|
||||
train.is_available = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
---@param comb LuaEntity
|
||||
@@ -152,8 +20,9 @@ local function on_depot_built(map_data, stop, comb)
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param depot_id uint
|
||||
---@param depot Depot
|
||||
local function on_depot_broken(map_data, depot)
|
||||
local function on_depot_broken(map_data, depot_id, depot)
|
||||
local train_id = depot.available_train_id
|
||||
if train_id then
|
||||
local train = map_data.trains[train_id]
|
||||
@@ -161,11 +30,62 @@ local function on_depot_broken(map_data, depot)
|
||||
send_lost_train_alert(train.entity, depot.entity_stop.backer_name)
|
||||
remove_train(map_data, train_id, train)
|
||||
end
|
||||
local depot_id = depot.entity_stop.unit_number--[[@as uint]]
|
||||
map_data.depots[depot_id] = nil
|
||||
interface_raise_depot_removed(depot_id, depot)
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
---@param comb LuaEntity
|
||||
local function on_refueler_built(map_data, stop, comb)
|
||||
--NOTE: only place where new Depot
|
||||
local refueler = {
|
||||
entity_stop = stop,
|
||||
entity_comb = comb,
|
||||
trains_total = 0,
|
||||
accepted_layouts = {},
|
||||
layout_pattern = {},
|
||||
--allows_all_trains = set_refueler_from_comb,
|
||||
--priority = set_refueler_from_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
|
||||
update_stop_if_auto(map_data, refueler, false)
|
||||
interface_raise_refueler_created(depot_id)
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param refueler_id uint
|
||||
---@param refueler Refueler
|
||||
local function on_refueler_broken(map_data, refueler_id, refueler)
|
||||
if refueler.trains_total > 0 then
|
||||
--search for trains coming to the destroyed refueler
|
||||
for train_id, train in pairs(map_data.trains) do
|
||||
local is_f = train.refueler_id == refueler_id
|
||||
if is_f then
|
||||
if not train.se_is_being_teleported then
|
||||
remove_train(map_data, train_id, train)
|
||||
lock_train(train.entity)
|
||||
send_lost_train_alert(train.entity, train.depot_name)
|
||||
else
|
||||
train.se_awaiting_removal = train_id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if refueler.network_name then
|
||||
local network = map_data.to_refueler[refueler.network_name]
|
||||
network[refueler_id] = nil
|
||||
if next(network) == nil then
|
||||
map_data.to_refueler[refueler.network_name] = nil
|
||||
end
|
||||
end
|
||||
map_data.stations[refueler_id] = nil
|
||||
interface_raise_refueler_removed(refueler_id, refueler)
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
---@param comb1 LuaEntity
|
||||
@@ -201,7 +121,7 @@ local function on_station_built(map_data, stop, comb1, comb2)
|
||||
map_data.stations[id] = station
|
||||
map_data.warmup_station_ids[#map_data.warmup_station_ids + 1] = id
|
||||
|
||||
update_station_if_auto(map_data, station, nil)
|
||||
update_stop_if_auto(map_data, station, true)
|
||||
interface_raise_station_created(id)
|
||||
end
|
||||
---@param map_data MapData
|
||||
@@ -215,8 +135,8 @@ local function on_station_broken(map_data, station_id, station)
|
||||
local is_p = train.p_station_id == station_id
|
||||
if is_p or is_r then
|
||||
|
||||
local is_p_in_progress = train.status == STATUS_D_TO_P or train.status == STATUS_P
|
||||
local is_r_in_progress = is_p_in_progress or train.status == STATUS_P_TO_R or train.status == STATUS_R
|
||||
local is_p_in_progress = train.status == STATUS_TO_P or train.status == STATUS_P
|
||||
local is_r_in_progress = is_p_in_progress or train.status == STATUS_TO_R or train.status == STATUS_R
|
||||
if (is_p and is_p_in_progress) or (is_r and is_r_in_progress) then
|
||||
--train is attempting delivery to a stop that was destroyed, stop it
|
||||
on_failed_delivery(map_data, train_id, train)
|
||||
@@ -331,41 +251,37 @@ local function on_combinator_built(map_data, comb)
|
||||
|
||||
if op == OPERATION_WAGON_MANIFEST then
|
||||
if rail then
|
||||
update_station_from_rail(map_data, rail, nil, true)
|
||||
update_stop_from_rail(map_data, rail, nil, true)
|
||||
end
|
||||
elseif op == OPERATION_DEPOT then
|
||||
if stop then
|
||||
local station = map_data.stations[stop.unit_number]
|
||||
---@type Depot
|
||||
local depot = map_data.depots[stop.unit_number]
|
||||
if depot or station then
|
||||
--NOTE: repeated combinators are ignored
|
||||
else
|
||||
elseif stop then
|
||||
local id = stop.unit_number--[[@as uint]]
|
||||
local station = map_data.stations[id]
|
||||
local depot = map_data.depots[id]
|
||||
local refueler = map_data.refuelers[id]
|
||||
if op == OPERATION_DEPOT then
|
||||
if refueler then
|
||||
on_refueler_broken(map_data, id, refueler)
|
||||
end
|
||||
if not station and not depot then
|
||||
on_depot_built(map_data, stop, comb)
|
||||
end
|
||||
elseif op == OPERATION_REFUELER then
|
||||
if not station and not depot and not refueler then
|
||||
on_depot_built(map_data, stop, comb)
|
||||
end
|
||||
elseif op == OPERATION_SECONDARY_IO then
|
||||
if stop then
|
||||
local station = map_data.stations[stop.unit_number]
|
||||
if station and not station.entity_comb2 then
|
||||
station.entity_comb2 = comb
|
||||
end
|
||||
end
|
||||
elseif op == OPERATION_PRIMARY_IO then
|
||||
if stop then
|
||||
local station = map_data.stations[stop.unit_number]
|
||||
if station then
|
||||
--NOTE: repeated combinators are ignored
|
||||
else
|
||||
local depot = map_data.depots[stop.unit_number]
|
||||
if depot then
|
||||
on_depot_broken(map_data, depot)
|
||||
if refueler then
|
||||
on_refueler_broken(map_data, id, refueler)
|
||||
end
|
||||
--no station or depot
|
||||
--add station
|
||||
|
||||
if depot then
|
||||
on_depot_broken(map_data, id, depot)
|
||||
end
|
||||
if not station then
|
||||
local comb2 = search_for_station_combinator(map_data, stop, OPERATION_SECONDARY_IO, comb)
|
||||
|
||||
on_station_built(map_data, stop, comb, comb2)
|
||||
end
|
||||
end
|
||||
@@ -378,20 +294,42 @@ 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 station = map_data.stations[stop.unit_number]
|
||||
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_id = stop.unit_number
|
||||
local depot = map_data.depots[depot_id]
|
||||
if depot and depot.entity_comb == comb then
|
||||
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, depot_id, depot)
|
||||
add_available_train_to_depot(map_data, mod_settings, train_id, train, id, depot)
|
||||
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]
|
||||
network[id] = nil
|
||||
if next(network) == nil then
|
||||
map_data.to_refueler[refueler.network_name] = nil
|
||||
end
|
||||
end
|
||||
refueler.network_name = network_name
|
||||
if network_name then
|
||||
local network = map_data.to_refueler[network_name]
|
||||
if network == nil then
|
||||
network = {}
|
||||
map_data.to_refueler[network_name] = network
|
||||
end
|
||||
network[id] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -407,33 +345,27 @@ function on_combinator_broken(map_data, comb)
|
||||
local stop = map_data.to_stop[comb_id]
|
||||
|
||||
if stop and stop.valid then
|
||||
local station = map_data.stations[stop.unit_number]
|
||||
local id = stop.unit_number--[[@as uint]]
|
||||
local station = map_data.stations[id]
|
||||
if station then
|
||||
if station.entity_comb1 == comb then
|
||||
local comb1 = search_for_station_combinator(map_data, stop, OPERATION_PRIMARY_IO, comb)
|
||||
if comb1 then
|
||||
station.entity_comb1 = comb1
|
||||
set_station_from_comb_state(station)
|
||||
update_station_if_auto(map_data, station)
|
||||
else
|
||||
on_station_broken(map_data, stop.unit_number, station)
|
||||
local depot_comb = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, comb)
|
||||
if depot_comb then
|
||||
on_depot_built(map_data, stop, depot_comb)
|
||||
end
|
||||
end
|
||||
on_station_broken(map_data, id, station)
|
||||
on_stop_built(map_data, stop, comb)
|
||||
elseif station.entity_comb2 == comb then
|
||||
station.entity_comb2 = search_for_station_combinator(map_data, stop, OPERATION_SECONDARY_IO, comb)
|
||||
end
|
||||
else
|
||||
local depot = map_data.depots[stop.unit_number]
|
||||
if depot and depot.entity_comb == comb then
|
||||
--NOTE: this will disrupt deliveries in progress that where dispatched from this station in a minor way
|
||||
local depot_comb = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, comb)
|
||||
if depot_comb then
|
||||
depot.entity_comb = depot_comb
|
||||
local depot = map_data.depots[id]
|
||||
if depot then
|
||||
if depot.entity_comb == comb then
|
||||
on_depot_broken(map_data, id, depot)
|
||||
on_stop_built(map_data, stop, comb)
|
||||
end
|
||||
else
|
||||
on_depot_broken(map_data, depot)
|
||||
local refueler = map_data.refuelers[id]
|
||||
if refueler and refueler.entity_comb == comb then
|
||||
on_refueler_broken(map_data, id, depot)
|
||||
on_stop_built(map_data, stop, comb)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -451,8 +383,7 @@ end
|
||||
---@param map_data MapData
|
||||
---@param comb LuaEntity
|
||||
function combinator_update(map_data, comb)
|
||||
---@type uint
|
||||
local unit_number = comb.unit_number
|
||||
local unit_number = comb.unit_number--[[@as uint]]
|
||||
local control = get_comb_control(comb)
|
||||
local params = control.parameters
|
||||
local old_params = map_data.to_comb_params[unit_number]
|
||||
@@ -480,18 +411,24 @@ function combinator_update(map_data, comb)
|
||||
end
|
||||
if params.second_constant ~= old_params.second_constant then
|
||||
has_changed = true
|
||||
local stop = global.to_stop[comb.unit_number]
|
||||
local stop = map_data.to_stop[comb.unit_number]
|
||||
if stop then
|
||||
local station = global.stations[stop.unit_number]
|
||||
local id = stop.unit_number
|
||||
local station = map_data.stations[id]
|
||||
if station then
|
||||
local bits = params.second_constant
|
||||
local is_pr_state = floor(bits/2)%3
|
||||
station.is_p = is_pr_state == 0 or is_pr_state == 1
|
||||
station.is_r = is_pr_state == 0 or is_pr_state == 2
|
||||
local allows_all_trains = bits%2 == 1
|
||||
if station.allows_all_trains ~= allows_all_trains then
|
||||
station.allows_all_trains = allows_all_trains
|
||||
update_station_if_auto(map_data, station)
|
||||
local pre = station.allows_all_trains
|
||||
set_station_from_comb_state(station)
|
||||
if station.allows_all_trains ~= pre then
|
||||
update_stop_if_auto(map_data, station, true)
|
||||
end
|
||||
else
|
||||
local refueler = map_data.refuelers[id]
|
||||
if refueler then
|
||||
local pre = refueler.allows_all_trains
|
||||
set_refueler_from_comb(mod_settings, refueler)
|
||||
if refueler.allows_all_trains ~= pre then
|
||||
update_stop_if_auto(map_data, refueler, false)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -504,7 +441,8 @@ end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
local function on_stop_built(map_data, stop)
|
||||
---@param comb_forbidden LuaEntity?
|
||||
function on_stop_built(map_data, stop, comb_forbidden)
|
||||
local pos_x = stop.position.x
|
||||
local pos_y = stop.position.y
|
||||
|
||||
@@ -515,9 +453,10 @@ local function on_stop_built(map_data, stop)
|
||||
local comb2 = nil
|
||||
local comb1 = nil
|
||||
local depot_comb = nil
|
||||
local refueler_comb = nil
|
||||
local entities = stop.surface.find_entities(search_area)
|
||||
for _, entity in pairs(entities) do
|
||||
if entity.valid and entity.name == COMBINATOR_NAME and map_data.to_stop[entity.unit_number] == nil then
|
||||
if entity.valid and entity ~= comb_forbidden and entity.name == COMBINATOR_NAME and map_data.to_stop[entity.unit_number] == nil then
|
||||
map_data.to_stop[entity.unit_number] = stop
|
||||
local param = get_comb_params(entity)
|
||||
local op = param.operation
|
||||
@@ -527,6 +466,8 @@ local function on_stop_built(map_data, stop)
|
||||
comb2 = entity
|
||||
elseif op == OPERATION_DEPOT then
|
||||
depot_comb = entity
|
||||
elseif op == OPERATION_REFUELER then
|
||||
refueler_comb = entity
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -534,6 +475,8 @@ local function on_stop_built(map_data, stop)
|
||||
on_station_built(map_data, stop, comb1, comb2)
|
||||
elseif depot_comb then
|
||||
on_depot_built(map_data, stop, depot_comb)
|
||||
elseif refueler_comb then
|
||||
on_refueler_built(map_data, stop, refueler_comb)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
@@ -553,20 +496,26 @@ local function on_stop_broken(map_data, stop)
|
||||
end
|
||||
end
|
||||
|
||||
local station = map_data.stations[stop.unit_number]
|
||||
local id = stop.unit_number--[[@as uint]]
|
||||
local station = map_data.stations[id]
|
||||
if station then
|
||||
on_station_broken(map_data, stop.unit_number, station)
|
||||
on_station_broken(map_data, id, station)
|
||||
else
|
||||
local depot = map_data.depots[stop.unit_number]
|
||||
local depot = map_data.depots[id]
|
||||
if depot then
|
||||
on_depot_broken(map_data, depot)
|
||||
on_depot_broken(map_data, id, depot)
|
||||
else
|
||||
local refueler = map_data.refuelers[id]
|
||||
if refueler then
|
||||
on_refueler_broken(map_data, id, refueler)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
---@param old_name string
|
||||
local function on_station_rename(map_data, stop, old_name)
|
||||
local function on_stop_rename(map_data, stop, old_name)
|
||||
--search for trains coming to the renamed station
|
||||
local station_id = stop.unit_number--[[@as uint]]
|
||||
local station = map_data.stations[station_id]
|
||||
@@ -575,8 +524,8 @@ local function on_station_rename(map_data, stop, old_name)
|
||||
local is_p = train.p_station_id == station_id
|
||||
local is_r = train.r_station_id == station_id
|
||||
if is_p or is_r then
|
||||
local is_p_in_progress = train.status == STATUS_D_TO_P or train.status == STATUS_P
|
||||
local is_r_in_progress = is_p_in_progress or train.status == STATUS_P_TO_R or train.status == STATUS_R
|
||||
local is_p_in_progress = train.status == STATUS_TO_P or train.status == STATUS_P
|
||||
local is_r_in_progress = is_p_in_progress or train.status == STATUS_TO_R or train.status == STATUS_R
|
||||
if is_r and is_r_in_progress then
|
||||
local r_station = map_data.stations[train.r_station_id]
|
||||
if not train.se_is_being_teleported then
|
||||
@@ -618,209 +567,6 @@ local function find_and_add_all_stations_from_nothing(map_data)
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param depot_id uint
|
||||
---@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
|
||||
if train.manifest then
|
||||
if train.status == STATUS_R_TO_D then
|
||||
--succeeded delivery
|
||||
train.p_station_id = 0
|
||||
train.r_station_id = 0
|
||||
train.manifest = nil
|
||||
elseif mod_settings.react_to_train_early_to_depot then
|
||||
on_failed_delivery(map_data, train_id, train)
|
||||
send_unexpected_train_alert(train.entity)
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
if is_train_empty then
|
||||
remove_available_train(map_data, train_id, train)
|
||||
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)
|
||||
else
|
||||
--train still has cargo
|
||||
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)
|
||||
end
|
||||
interface_raise_train_nonempty_in_depot(depot_id, train_entity, train_id)
|
||||
end
|
||||
elseif is_train_empty then
|
||||
--NOTE: only place where new Train
|
||||
train = {
|
||||
entity = train_entity,
|
||||
--layout_id = set_train_layout,
|
||||
--item_slot_capacity = set_train_layout,
|
||||
--fluid_capacity = set_train_layout,
|
||||
--status = add_available_train_to_depot,
|
||||
p_station_id = 0,
|
||||
r_station_id = 0,
|
||||
manifest = nil,
|
||||
last_manifest_tick = map_data.total_ticks,
|
||||
has_filtered_wagon = nil,
|
||||
--is_available = add_available_train_to_depot,
|
||||
--parked_at_depot_id = add_available_train_to_depot,
|
||||
--depot_name = add_available_train_to_depot,
|
||||
--network_name = add_available_train_to_depot,
|
||||
--network_flag = add_available_train_to_depot,
|
||||
--priority = add_available_train_to_depot,
|
||||
}
|
||||
set_train_layout(map_data, train)
|
||||
map_data.trains[train_id] = train
|
||||
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_created(train_id, depot_id)
|
||||
else
|
||||
if mod_settings.react_to_nonempty_train_in_depot then
|
||||
lock_train(train_entity)
|
||||
send_nonempty_train_in_depot_alert(train_entity)
|
||||
end
|
||||
interface_raise_train_nonempty_in_depot(depot_id, train_entity)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
local function on_train_arrives_buffer(map_data, stop, train_id, train)
|
||||
if train.manifest then
|
||||
---@type uint
|
||||
local station_id = stop.unit_number
|
||||
if train.status == STATUS_D_TO_P then
|
||||
if train.p_station_id == station_id then
|
||||
train.status = STATUS_P
|
||||
local station = map_data.stations[station_id]
|
||||
set_comb1(map_data, station, train.manifest, 1)
|
||||
set_p_wagon_combs(map_data, station, train)
|
||||
end
|
||||
elseif train.status == STATUS_P_TO_R then
|
||||
if train.r_station_id == station_id then
|
||||
train.status = STATUS_R
|
||||
local station = map_data.stations[station_id]
|
||||
set_comb1(map_data, station, train.manifest, -1)
|
||||
set_r_wagon_combs(map_data, station, train)
|
||||
end
|
||||
elseif train.status == STATUS_P and train.p_station_id == station_id then
|
||||
--this is player intervention that is considered valid
|
||||
elseif (train.status == STATUS_R or train.status == STATUS_R_TO_D) and train.r_station_id == station_id then
|
||||
--this is player intervention that is considered valid
|
||||
elseif mod_settings.react_to_train_at_incorrect_station then
|
||||
on_failed_delivery(map_data, train_id, train)
|
||||
remove_train(map_data, train_id, train)
|
||||
lock_train(train.entity)
|
||||
send_lost_train_alert(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_lost_train_alert(train.entity, train.depot_name)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param mod_settings CybersynModSettings
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
local function on_train_leaves_station(map_data, mod_settings, train_id, train)
|
||||
if train.manifest then
|
||||
if train.status == STATUS_P then
|
||||
train.status = STATUS_P_TO_R
|
||||
local station = map_data.stations[train.p_station_id]
|
||||
remove_manifest(map_data, station, train.manifest, 1)
|
||||
set_comb1(map_data, station, nil)
|
||||
unset_wagon_combs(map_data, station)
|
||||
if train.has_filtered_wagon then
|
||||
train.has_filtered_wagon = nil
|
||||
for carriage_i, carriage in ipairs(train.entity.cargo_wagons) do
|
||||
local inv = carriage.get_inventory(defines.inventory.cargo_wagon)
|
||||
if inv and inv.is_filtered() then
|
||||
---@type uint
|
||||
for i = 1, #inv do
|
||||
inv.set_filter(i, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
interface_raise_train_completed_provide(train_id)
|
||||
elseif train.status == STATUS_R then
|
||||
train.status = STATUS_R_TO_D
|
||||
local station = map_data.stations[train.r_station_id]
|
||||
remove_manifest(map_data, station, train.manifest, -1)
|
||||
set_comb1(map_data, station, nil)
|
||||
unset_wagon_combs(map_data, station)
|
||||
--add to available trains for depot bypass
|
||||
local fuel_fill = 0
|
||||
local total_slots = 0
|
||||
for k, v in pairs(train.entity.locomotives) do
|
||||
if v[1] then
|
||||
local inv = v[1].get_fuel_inventory()
|
||||
if inv then
|
||||
local inv_size = #inv
|
||||
total_slots = total_slots + inv_size
|
||||
for i = 1, inv_size do
|
||||
local item = inv[i--[[@as uint]]]
|
||||
local count = item.count
|
||||
if count > 0 then
|
||||
fuel_fill = fuel_fill + count/get_stack_size(map_data, item.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if total_slots == 0 then
|
||||
--if total_slots == 0 it's probably a modded electric train
|
||||
if mod_settings.depot_bypass_threshold < 1 then
|
||||
add_available_train(map_data, train_id, train)
|
||||
end
|
||||
elseif fuel_fill/total_slots > mod_settings.depot_bypass_threshold then
|
||||
add_available_train(map_data, train_id, train)
|
||||
end
|
||||
interface_raise_train_completed_request(train_id)
|
||||
end
|
||||
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]]]
|
||||
remove_train(map_data, train_id, train)
|
||||
send_lost_train_alert(train.entity, depot.entity_stop.backer_name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
local function on_train_broken(map_data, train_id, train)
|
||||
--NOTE: train.entity is only absent if the train is climbing a space elevator as of 0.5.0
|
||||
if not train.se_is_being_teleported then
|
||||
if train.manifest then
|
||||
on_failed_delivery(map_data, train_id, train)
|
||||
end
|
||||
remove_train(map_data, train_id, train)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param pre_train_id uint
|
||||
local function on_train_modified(map_data, pre_train_id)
|
||||
local train = map_data.trains[pre_train_id]
|
||||
--NOTE: train.entity is only absent if the train is climbing a space elevator as of 0.5.0
|
||||
if train and not train.se_is_being_teleported then
|
||||
if train.manifest then
|
||||
on_failed_delivery(map_data, pre_train_id, train)
|
||||
end
|
||||
remove_train(map_data, pre_train_id, train)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function on_built(event)
|
||||
local entity = event.entity or event.created_entity
|
||||
@@ -831,11 +577,11 @@ local function on_built(event)
|
||||
elseif entity.name == COMBINATOR_NAME then
|
||||
on_combinator_built(global, entity)
|
||||
elseif entity.type == "inserter" then
|
||||
update_station_from_inserter(global, entity)
|
||||
update_stop_from_inserter(global, entity)
|
||||
elseif entity.type == "pump" then
|
||||
update_station_from_pump(global, entity)
|
||||
update_stop_from_pump(global, entity)
|
||||
elseif entity.type == "straight-rail" then
|
||||
update_station_from_rail(global, entity)
|
||||
update_stop_from_rail(global, entity)
|
||||
end
|
||||
end
|
||||
local function on_broken(event)
|
||||
@@ -847,11 +593,11 @@ local function on_broken(event)
|
||||
elseif entity.name == COMBINATOR_NAME then
|
||||
on_combinator_broken(global, entity)
|
||||
elseif entity.type == "inserter" then
|
||||
update_station_from_inserter(global, entity, entity)
|
||||
update_stop_from_inserter(global, entity, entity)
|
||||
elseif entity.type == "pump" then
|
||||
update_station_from_pump(global, entity, entity)
|
||||
update_stop_from_pump(global, entity, entity)
|
||||
elseif entity.type == "straight-rail" then
|
||||
update_station_from_rail(global, entity, nil)
|
||||
update_stop_from_rail(global, entity, nil)
|
||||
elseif entity.train then
|
||||
local train_id = entity.train.id
|
||||
local train = global.trains[train_id]
|
||||
@@ -865,47 +611,7 @@ local function on_rotate(event)
|
||||
if not entity or not entity.valid then return end
|
||||
|
||||
if entity.type == "inserter" then
|
||||
update_station_from_inserter(global, entity)
|
||||
end
|
||||
end
|
||||
local function on_rename(event)
|
||||
if event.entity.name == "train-stop" then
|
||||
on_station_rename(global, event.entity, event.old_name)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_train_built(event)
|
||||
local train_e = event.train
|
||||
if event.old_train_id_1 then
|
||||
on_train_modified(global, event.old_train_id_1)
|
||||
end
|
||||
if event.old_train_id_2 then
|
||||
on_train_modified(global, event.old_train_id_2)
|
||||
end
|
||||
end
|
||||
local 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
|
||||
local train = global.trains[train_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
|
||||
if global.stations[stop.unit_number] then
|
||||
if train then
|
||||
on_train_arrives_buffer(global, stop, train_id, train)
|
||||
end
|
||||
else
|
||||
local depot_id = stop.unit_number--[[@as uint]]
|
||||
if global.depots[depot_id] then
|
||||
on_train_arrives_depot(global, depot_id, train_e)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif event.old_state == defines.train_state.wait_station then
|
||||
if train then
|
||||
on_train_leaves_station(global, mod_settings, train_id, train)
|
||||
end
|
||||
update_stop_from_inserter(global, entity)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -931,6 +637,12 @@ local function on_paste(event)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_rename(event)
|
||||
if event.entity.name == "train-stop" then
|
||||
on_stop_rename(global, event.entity, event.old_name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function on_settings_changed(event)
|
||||
mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value --[[@as double]]
|
||||
@@ -1016,10 +728,11 @@ local function setup_se_compat()
|
||||
train.se_awaiting_rename = nil
|
||||
end
|
||||
|
||||
if not (train.status == STATUS_D_TO_P or train.status == STATUS_P_TO_R) then return end
|
||||
if not (train.status == STATUS_TO_P or train.status == STATUS_TO_R) then return end
|
||||
|
||||
local schedule = train_entity.schedule
|
||||
if schedule then
|
||||
if train.status == STATUS_TO_P or train.status == STATUS_TO_R then
|
||||
local p_station = map_data.stations[train.p_station_id]
|
||||
local p_name = p_station.entity_stop.backer_name
|
||||
local p_surface_i = p_station.entity_stop.surface.index
|
||||
@@ -1039,6 +752,21 @@ local function setup_se_compat()
|
||||
i = i + 1
|
||||
end
|
||||
train_entity.schedule = schedule
|
||||
elseif train.status == STATUS_TO_F then
|
||||
local refueler = map_data.refuelers[train.refueler_id]
|
||||
local f_name = refueler.entity_stop.backer_name
|
||||
local f_surface_i = refueler.entity_stop.surface.index
|
||||
local records = schedule.records
|
||||
local i = schedule.current
|
||||
while i <= #records do
|
||||
if records[i].station == f_name and f_surface_i ~= old_surface_index then
|
||||
table_insert(records, i, create_direct_to_station_order(refueler.entity_stop))
|
||||
i = i + 1
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
train_entity.schedule = schedule
|
||||
end
|
||||
end
|
||||
interface_raise_train_teleported(new_id, old_id)
|
||||
end)
|
||||
|
||||
@@ -2,122 +2,6 @@ local flib_migration = require("__flib__.migration")
|
||||
|
||||
|
||||
local migrations_table = {
|
||||
["0.2.1"] = function()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
for id, station in pairs(map_data.stations) do
|
||||
station.p_threshold = nil
|
||||
end
|
||||
end,
|
||||
["0.3.0"] = function()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
map_data.warmup_station_ids = {}
|
||||
map_data.active_station_ids = map_data.all_station_ids
|
||||
map_data.all_station_ids = nil
|
||||
mod_settings.warmup_time = settings.global["cybersyn-warmup-time"].value--[[@as int]]
|
||||
end,
|
||||
["0.4.0"] = function()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
map_data.is_player_cursor_blueprint = {}
|
||||
map_data.to_comb_params = {}
|
||||
for id, comb in pairs(map_data.to_comb) do
|
||||
map_data.to_comb_params[id] = get_comb_params(comb)
|
||||
end
|
||||
end,
|
||||
["0.4.1"] = function()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
map_data.tick_state = STATE_INIT
|
||||
for id, station in pairs(map_data.stations) do
|
||||
station.allows_all_trains = station.allow_all_trains or station.allows_all_trains
|
||||
station.allow_all_trains = nil
|
||||
end
|
||||
end,
|
||||
["0.4.2"] = function()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
map_data.tick_state = STATE_INIT
|
||||
map_data.available_trains = map_data.trains_available
|
||||
for id, train in pairs(map_data.trains) do
|
||||
local depot = train.depot
|
||||
if depot then
|
||||
train.parked_at_depot_id = depot.entity_comb.unit_number
|
||||
train.network_name = depot.network_name
|
||||
train.network_flag = depot.network_flag
|
||||
train.priority = depot.priority
|
||||
else
|
||||
train.network_name = ""
|
||||
train.network_flag = 0
|
||||
train.priority = 0
|
||||
end
|
||||
end
|
||||
for id, depot in pairs(map_data.depots) do
|
||||
map_data.depots[id] = {
|
||||
entity_comb = depot.entity_comb,
|
||||
entity_stop = depot.entity_stop,
|
||||
available_train_id = depot.available_train,
|
||||
}
|
||||
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,
|
||||
["0.4.4"] = function()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
map_data.tick_state = STATE_INIT
|
||||
for id, layout in pairs(map_data.layouts) do
|
||||
local new_layout = {}
|
||||
local i = 1
|
||||
for c in string.gmatch(layout, ".") do
|
||||
if c == "N" then
|
||||
elseif c == "C" then
|
||||
new_layout[i] = 1
|
||||
elseif c == "F" then
|
||||
new_layout[i] = 2
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
map_data.layouts[id] = new_layout
|
||||
end
|
||||
end,
|
||||
["0.5.1"] = function()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
map_data.tick_state = STATE_INIT
|
||||
map_data.is_player_cursor_blueprint = nil
|
||||
for id, layout in pairs(map_data.layouts) do
|
||||
local new_layout = {}
|
||||
local max_i = 0
|
||||
for i, v in pairs(layout) do
|
||||
new_layout[i] = v
|
||||
if i > max_i then
|
||||
max_i = i
|
||||
end
|
||||
end
|
||||
for i = 1, max_i do
|
||||
if new_layout[i] == nil then
|
||||
new_layout[i] = 0
|
||||
end
|
||||
end
|
||||
map_data.layouts[id] = new_layout
|
||||
end
|
||||
for id, station in pairs(map_data.stations) do
|
||||
reset_station_layout(map_data, station)
|
||||
end
|
||||
end,
|
||||
["1.0.3"] = function()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
@@ -194,6 +78,7 @@ local migrations_table = {
|
||||
end
|
||||
end,
|
||||
}
|
||||
--STATUS_R_TO_D = 5
|
||||
|
||||
---@param data ConfigurationChangedData
|
||||
function on_config_changed(data)
|
||||
|
||||
@@ -330,21 +330,27 @@ end
|
||||
function interface.is_layout_accepted(layout_pattern, layout)
|
||||
return is_layout_accepted(layout_pattern, layout)
|
||||
end
|
||||
---@param station_id uint
|
||||
---@param stop_id uint
|
||||
---@param forbidden_entity LuaEntity?
|
||||
---@param force_update boolean?
|
||||
function interface.reset_station_layout(station_id, forbidden_entity, force_update)
|
||||
local station = global.stations[station_id]
|
||||
assert(station)
|
||||
if force_update or not station.allows_all_trains then
|
||||
reset_station_layout(global, station, forbidden_entity)
|
||||
function interface.reset_stop_layout(stop_id, forbidden_entity, force_update)
|
||||
local is_station = true
|
||||
---@type Refueler|Station
|
||||
local stop = global.stations[stop_id]
|
||||
if not stop then
|
||||
is_station = false
|
||||
stop = global.refuelers[stop_id]
|
||||
end
|
||||
assert(stop)
|
||||
if force_update or not stop.allows_all_trains then
|
||||
reset_stop_layout(global, stop, is_station, forbidden_entity)
|
||||
end
|
||||
end
|
||||
---@param rail LuaEntity
|
||||
---@param forbidden_entity LuaEntity?
|
||||
---@param force_update boolean?
|
||||
function interface.update_station_from_rail(rail, forbidden_entity, force_update)
|
||||
update_station_from_rail(global, rail, forbidden_entity, force_update)
|
||||
function interface.update_stop_from_rail(rail, forbidden_entity, force_update)
|
||||
update_stop_from_rail(global, rail, forbidden_entity, force_update)
|
||||
end
|
||||
|
||||
------------------------------------------------------------------
|
||||
|
||||
432
cybersyn/scripts/train-events.lua
Normal file
432
cybersyn/scripts/train-events.lua
Normal file
@@ -0,0 +1,432 @@
|
||||
--By Mami
|
||||
local INF = math.huge
|
||||
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
---@param manifest Manifest
|
||||
---@param sign int?
|
||||
local function set_comb1(map_data, station, manifest, sign)
|
||||
local comb = station.entity_comb1
|
||||
if comb.valid then
|
||||
if manifest then
|
||||
local signals = {}
|
||||
for i, item in ipairs(manifest) do
|
||||
signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = sign*item.count}
|
||||
end
|
||||
set_combinator_output(map_data, comb, signals)
|
||||
else
|
||||
set_combinator_output(map_data, comb, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function on_failed_delivery(map_data, train_id, train)
|
||||
--NOTE: must either change this train's status or remove it after this call
|
||||
local p_station_id = train.p_station_id--[[@as uint]]
|
||||
local r_station_id = train.r_station_id--[[@as uint]]
|
||||
local manifest = train.manifest--[[@as Manifest]]
|
||||
local is_p_in_progress = train.status == STATUS_TO_P or train.status == STATUS_P
|
||||
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
|
||||
local station = map_data.stations[p_station_id]
|
||||
remove_manifest(map_data, station, manifest, 1)
|
||||
if train.status == STATUS_P then
|
||||
set_comb1(map_data, station, nil)
|
||||
unset_wagon_combs(map_data, station)
|
||||
end
|
||||
end
|
||||
if is_r_in_progress then
|
||||
local station = map_data.stations[r_station_id]
|
||||
remove_manifest(map_data, station, manifest, -1)
|
||||
if train.status == STATUS_R then
|
||||
set_comb1(map_data, station, nil)
|
||||
unset_wagon_combs(map_data, station)
|
||||
end
|
||||
end
|
||||
train.r_station_id = nil
|
||||
train.p_station_id = nil
|
||||
train.manifest = nil
|
||||
interface_raise_train_failed_delivery(train_id, is_p_in_progress, p_station_id, is_r_in_progress, r_station_id, manifest)
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function add_available_train(map_data, train_id, train)
|
||||
local network_name = train.network_name
|
||||
if network_name then
|
||||
local network = map_data.available_trains[network_name]
|
||||
if not network then
|
||||
network = {}
|
||||
map_data.available_trains[network_name] = network
|
||||
end
|
||||
network[train_id] = true
|
||||
train.is_available = true
|
||||
interface_raise_train_available(train_id)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param mod_settings CybersynModSettings
|
||||
---@param depot_id uint
|
||||
---@param depot Depot
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot)
|
||||
local comb = depot.entity_comb
|
||||
local network_name = get_comb_network_name(comb)
|
||||
if network_name then
|
||||
local network = map_data.available_trains[network_name]
|
||||
if not network then
|
||||
network = {}
|
||||
map_data.available_trains[network_name] = network
|
||||
end
|
||||
network[train_id] = true
|
||||
train.is_available = true
|
||||
end
|
||||
depot.available_train_id = train_id
|
||||
train.status = STATUS_D
|
||||
train.parked_at_depot_id = depot_id
|
||||
train.depot_name = depot.entity_stop.backer_name
|
||||
train.se_depot_surface_i = depot.entity_stop.surface.index
|
||||
train.network_name = network_name
|
||||
train.network_flag = mod_settings.network_flag
|
||||
train.priority = 0
|
||||
if network_name then
|
||||
local signals = comb.get_merged_signals(defines.circuit_connector_id.combinator_input)
|
||||
if signals then
|
||||
for k, v in pairs(signals) do
|
||||
local item_name = v.signal.name
|
||||
local item_count = v.count
|
||||
if item_name then
|
||||
if item_name == SIGNAL_PRIORITY then
|
||||
train.priority = item_count
|
||||
end
|
||||
if item_name == network_name then
|
||||
train.network_flag = item_count
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
interface_raise_train_available(train_id)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function remove_available_train(map_data, train_id, train)
|
||||
---@type uint
|
||||
if train.is_available and train.network_name then
|
||||
local network = map_data.available_trains[train.network_name--[[@as string]]]
|
||||
if network then
|
||||
network[train_id] = nil
|
||||
if next(network) == nil then
|
||||
map_data.available_trains[train.network_name] = nil
|
||||
end
|
||||
end
|
||||
train.is_available = nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param depot_id uint
|
||||
---@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
|
||||
if train.status == STATUS_TO_D then
|
||||
elseif train.status == STATUS_TO_D_BYPASS then
|
||||
remove_available_train(map_data, train_id, train)
|
||||
elseif mod_settings.react_to_train_early_to_depot then
|
||||
if train.manifest then
|
||||
on_failed_delivery(map_data, train_id, train)
|
||||
end
|
||||
send_unexpected_train_alert(train.entity)
|
||||
else
|
||||
return
|
||||
end
|
||||
if is_train_empty then
|
||||
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)
|
||||
else
|
||||
--train still has cargo
|
||||
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)
|
||||
end
|
||||
interface_raise_train_nonempty_in_depot(depot_id, train_entity, train_id)
|
||||
end
|
||||
elseif is_train_empty then
|
||||
--NOTE: only place where new Train
|
||||
train = {
|
||||
entity = train_entity,
|
||||
--layout_id = set_train_layout,
|
||||
--item_slot_capacity = set_train_layout,
|
||||
--fluid_capacity = set_train_layout,
|
||||
--status = add_available_train_to_depot,
|
||||
p_station_id = 0,
|
||||
r_station_id = 0,
|
||||
manifest = nil,
|
||||
last_manifest_tick = map_data.total_ticks,
|
||||
has_filtered_wagon = nil,
|
||||
--is_available = add_available_train_to_depot,
|
||||
--parked_at_depot_id = add_available_train_to_depot,
|
||||
--depot_name = add_available_train_to_depot,
|
||||
--network_name = add_available_train_to_depot,
|
||||
--network_flag = add_available_train_to_depot,
|
||||
--priority = add_available_train_to_depot,
|
||||
}
|
||||
set_train_layout(map_data, train)
|
||||
map_data.trains[train_id] = train
|
||||
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_created(train_id, depot_id)
|
||||
else
|
||||
if mod_settings.react_to_nonempty_train_in_depot then
|
||||
lock_train(train_entity)
|
||||
send_nonempty_train_in_depot_alert(train_entity)
|
||||
end
|
||||
interface_raise_train_nonempty_in_depot(depot_id, train_entity)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param station_id uint
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
local function on_train_arrives_station(map_data, station_id, train_id, train)
|
||||
if train.manifest then
|
||||
---@type uint
|
||||
if train.status == STATUS_TO_P then
|
||||
if train.p_station_id == station_id then
|
||||
train.status = STATUS_P
|
||||
local station = map_data.stations[station_id]
|
||||
set_comb1(map_data, station, train.manifest, 1)
|
||||
set_p_wagon_combs(map_data, station, train)
|
||||
end
|
||||
elseif train.status == STATUS_TO_R then
|
||||
if train.r_station_id == station_id then
|
||||
train.status = STATUS_R
|
||||
local station = map_data.stations[station_id]
|
||||
set_comb1(map_data, station, train.manifest, -1)
|
||||
set_r_wagon_combs(map_data, station, train)
|
||||
end
|
||||
elseif train.status == STATUS_P and train.p_station_id == station_id then
|
||||
--this is player intervention that is considered valid
|
||||
elseif (train.status == STATUS_R or train.status == STATUS_TO_D or train.status == STATUS_TO_D_BYPASS) and train.r_station_id == station_id then
|
||||
--this is player intervention that is considered valid
|
||||
elseif mod_settings.react_to_train_at_incorrect_station then
|
||||
on_failed_delivery(map_data, train_id, train)
|
||||
remove_train(map_data, train_id, train)
|
||||
lock_train(train.entity)
|
||||
send_lost_train_alert(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_lost_train_alert(train.entity, train.depot_name)
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param refueler_id uint
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
local function on_train_arrives_refueler(map_data, refueler_id, train_id, train)
|
||||
if train.status == STATUS_TO_F then
|
||||
--local refueler = map_data.refuelers[refueler_id]
|
||||
train.status = STATUS_F
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param mod_settings CybersynModSettings
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
local function on_train_leaves_stop(map_data, mod_settings, train_id, train)
|
||||
if train.status == STATUS_P then
|
||||
train.status = STATUS_TO_R
|
||||
local station = map_data.stations[train.p_station_id]
|
||||
remove_manifest(map_data, station, train.manifest, 1)
|
||||
set_comb1(map_data, station, nil)
|
||||
unset_wagon_combs(map_data, station)
|
||||
if train.has_filtered_wagon then
|
||||
train.has_filtered_wagon = nil
|
||||
for carriage_i, carriage in ipairs(train.entity.cargo_wagons) do
|
||||
local inv = carriage.get_inventory(defines.inventory.cargo_wagon)
|
||||
if inv and inv.is_filtered() then
|
||||
---@type uint
|
||||
for i = 1, #inv do
|
||||
inv.set_filter(i, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
interface_raise_train_completed_provide(train_id)
|
||||
elseif train.status == STATUS_R then
|
||||
local station = map_data.stations[train.r_station_id]
|
||||
remove_manifest(map_data, station, train.manifest, -1)
|
||||
set_comb1(map_data, station, nil)
|
||||
unset_wagon_combs(map_data, station)
|
||||
--complete delivery
|
||||
train.p_station_id = nil
|
||||
train.r_station_id = nil
|
||||
train.manifest = nil
|
||||
--add to available trains for depot bypass
|
||||
local fuel_fill = 0
|
||||
local total_slots = 0
|
||||
for k, v in pairs(train.entity.locomotives) do
|
||||
if v[1] then
|
||||
local inv = v[1].get_fuel_inventory()
|
||||
if inv then
|
||||
local inv_size = #inv
|
||||
total_slots = total_slots + inv_size
|
||||
for i = 1, inv_size do
|
||||
local item = inv[i--[[@as uint]]]
|
||||
local count = item.count
|
||||
if count > 0 then
|
||||
fuel_fill = fuel_fill + count/get_stack_size(map_data, item.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if total_slots == 0 then
|
||||
--if total_slots == 0 it's probably a modded electric train
|
||||
if mod_settings.depot_bypass_threshold < 1 then
|
||||
train.status = STATUS_TO_D_BYPASS
|
||||
add_available_train(map_data, train_id, train)
|
||||
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)
|
||||
else
|
||||
local refuelers = map_data.to_refueler[train.network_name]
|
||||
if refuelers then
|
||||
local best_refueler_id = nil
|
||||
local best_dist = INF
|
||||
local best_prior = -INF
|
||||
for i, id in ipairs(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
|
||||
local accepted = false
|
||||
local dist = nil
|
||||
if refueler.priority == best_prior then
|
||||
dist = get_stop_dist(train.entity.front_stock, refueler.entity_stop)
|
||||
accepted = dist < best_dist
|
||||
end
|
||||
if accepted or refueler.priority > best_prior then
|
||||
best_refueler_id = id
|
||||
best_dist = dist or get_stop_dist(train.entity.front_stock, refueler.entity_stop)
|
||||
best_prior = refueler.priority
|
||||
end
|
||||
end
|
||||
end
|
||||
if best_refueler_id then
|
||||
train.status = STATUS_TO_F
|
||||
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)
|
||||
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)
|
||||
elseif train.status == STATUS_F then
|
||||
local refueler = map_data.refuelers[train.refueler_id]
|
||||
train.status = STATUS_TO_D_BYPASS
|
||||
train.refueler_id = nil
|
||||
refueler.trains_total = refueler.trains_total - 1
|
||||
add_available_train(map_data, train_id, train)
|
||||
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]]]
|
||||
remove_train(map_data, train_id, train)
|
||||
send_lost_train_alert(train.entity, depot.entity_stop.backer_name)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function on_train_broken(map_data, train_id, train)
|
||||
--NOTE: train.entity is only absent if the train is climbing a space elevator as of 0.5.0
|
||||
if not train.se_is_being_teleported then
|
||||
if train.manifest then
|
||||
on_failed_delivery(map_data, train_id, train)
|
||||
end
|
||||
remove_train(map_data, train_id, train)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param pre_train_id uint
|
||||
local function on_train_modified(map_data, pre_train_id)
|
||||
local train = map_data.trains[pre_train_id]
|
||||
--NOTE: train.entity is only absent if the train is climbing a space elevator as of 0.5.0
|
||||
if train and not train.se_is_being_teleported then
|
||||
if train.manifest then
|
||||
on_failed_delivery(map_data, pre_train_id, train)
|
||||
end
|
||||
remove_train(map_data, pre_train_id, train)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function on_train_built(event)
|
||||
local train_e = event.train
|
||||
if event.old_train_id_1 then
|
||||
on_train_modified(global, event.old_train_id_1)
|
||||
end
|
||||
if event.old_train_id_2 then
|
||||
on_train_modified(global, event.old_train_id_2)
|
||||
end
|
||||
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 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
|
||||
local id = stop.unit_number--[[@as uint]]
|
||||
if global.stations[id] then
|
||||
local train = global.trains[train_id]
|
||||
if train then
|
||||
on_train_arrives_station(global, id, train_id, train)
|
||||
end
|
||||
elseif global.depots[id] then
|
||||
on_train_arrives_depot(global, id, train_e)
|
||||
elseif global.refuelers[id] then
|
||||
local train = global.trains[train_id]
|
||||
if train then
|
||||
on_train_arrives_refueler(global, id, train_id, train)
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif event.old_state == defines.train_state.wait_station then
|
||||
local train = global.trains[train_id]
|
||||
if train then
|
||||
on_train_leaves_stop(global, mod_settings, train_id, train)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user