finished wagon manifest

This commit is contained in:
Monica Moniot
2022-11-03 12:56:24 -04:00
parent 599978afb5
commit 89997e057f
7 changed files with 185 additions and 108 deletions

View File

@@ -1,6 +1,7 @@
finish wagon manifest
close gui when the combinator is destroyed
play close sound when gui is closed
improve localization
support space elevator
do hardcore testing
optimizations?
models & art

View File

@@ -35,7 +35,7 @@ cybersyn-request-threshold=Request threshold
cybersyn-locked-slots=Locked slots per cargo wagon
[cybersyn-messages]
missing-trains=No trains available to make a delivery from station __2__ to station __1__
missing-trains=No trains available to make a delivery from __2__ to __1__
lost-train=A train has become lost
nonempty-train=A train has parked in a depot while still containing items; it cannot be dispatched until it is empty

View File

@@ -74,33 +74,6 @@ local function get_signals(station)
end
end
---@param depot Depot
local function set_depot_signals(depot)
local comb = depot.entity_comb
if depot.network_name and comb.valid and (comb.status == defines.entity_status.working or comb.status == defines.entity_status.low_power) then
depot.priority = 0
depot.network_flag = 1
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
depot.priority = item_count
end
if item_name == depot.network_name then
depot.network_flag = item_count
end
end
end
end
else
depot.priority = 0
depot.network_flag = 0
end
end
---@param map_data MapData
---@param comb LuaEntity
---@param signals ConstantCombinatorParameters[]?
@@ -170,13 +143,6 @@ local function get_stop_dist(stop0, stop1)
end
---@param station Station
---@param layout_id uint
local function station_accepts_layout(station, layout_id)
return station.is_all or station.accepted_layouts[layout_id]
end
---@param map_data MapData
---@param r_station_id uint
@@ -195,38 +161,42 @@ local function get_valid_train(map_data, r_station_id, p_station_id, item_type)
return nil, INF
end
local best_train = nil
---@type Depot|nil
local best_depot = nil
local best_dist = INF
local valid_train_exists = false
local is_fluid = item_type == "fluid"
for depot_id, train_id in pairs(map_data.trains_available[network_name]) do
local depot = map_data.depots[depot_id]
local train = map_data.trains[train_id]
--check cargo capabilities
--check layout validity for both stations
if
depot.network_name == network_name and
btest(netand, depot.network_flag)
((is_fluid and train.fluid_capacity > 0) or (not is_fluid and train.item_slot_capacity > 0)) and
station_accepts_layout(r_station, train.layout_id) and
station_accepts_layout(p_station, train.layout_id)
then
valid_train_exists = true
--check if exists valid path
--check if path is shortest so we prioritize locality
local d_to_p_dist = get_stop_dist(depot.entity_stop, p_station.entity_stop) - DEPOT_PRIORITY_MULT*depot.priority
local trains = map_data.trains_available[network_name]
if trains then
for train_id, depot_id in pairs(trains) do
local depot = map_data.depots[depot_id]
local train = map_data.trains[train_id]
local layout_id = train.layout_id
--check cargo capabilities
--check layout validity for both stations
if
btest(netand, depot.network_flag) and
((is_fluid and train.fluid_capacity > 0) or (not is_fluid and train.item_slot_capacity > 0)) and
(r_station.is_all or r_station.accepted_layouts[layout_id]) and
(p_station.is_all or p_station.accepted_layouts[layout_id])
then
valid_train_exists = true
--check if exists valid path
--check if path is shortest so we prioritize locality
local d_to_p_dist = get_stop_dist(depot.entity_stop, p_station.entity_stop) - DEPOT_PRIORITY_MULT*depot.priority
local dist = d_to_p_dist
if dist < best_dist then
best_dist = dist
best_train = train
local dist = d_to_p_dist
if dist < best_dist then
best_dist = dist
best_depot = depot
end
end
end
end
if valid_train_exists then
return best_train, best_dist + p_to_r_dist
return best_depot, best_dist + p_to_r_dist
else
return nil, p_to_r_dist
end
@@ -236,13 +206,16 @@ end
---@param map_data MapData
---@param r_station_id uint
---@param p_station_id uint
---@param train Train
---@param depot Depot
---@param primary_item_name string
---@param economy Economy
local function send_train_between(map_data, r_station_id, p_station_id, train, primary_item_name, economy)
local function send_train_between(map_data, r_station_id, p_station_id, depot, primary_item_name, economy)
--trains and stations expected to be of the same network
local r_station = map_data.stations[r_station_id]
local p_station = map_data.stations[p_station_id]
local train = map_data.trains[depot.available_train]
---@type string
local network_name = depot.network_name
local requests = {}
local manifest = {}
@@ -333,7 +306,7 @@ local function send_train_between(map_data, r_station_id, p_station_id, train, p
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
local item_network_name = (r_station.network_name and item.name + ":" + r_station.network_name) or item.name
local item_network_name = network_name..":"..item.name
local r_stations = economy.r_stations_all[item_network_name]
local p_stations = economy.p_stations_all[item_network_name]
for i, id in ipairs(r_stations) do
@@ -350,7 +323,7 @@ local function send_train_between(map_data, r_station_id, p_station_id, train, p
end
end
map_data.trains_available[train.entity.id] = nil
remove_available_train(map_data, depot)
train.status = STATUS_D_TO_P
train.p_station_id = p_station_id
train.r_station_id = r_station_id
@@ -375,8 +348,33 @@ function tick(map_data, mod_settings)
local p_stations_all = economy.p_stations_all
local all_names = {}
for depot_id, _ in pairs(map_data.trains_available) do
set_depot_signals(map_data.depots[depot_id])
for _, network in pairs(map_data.trains_available) do
for _, depot_id in pairs(network) do
local depot = map_data.depots[depot_id]
local comb = depot.entity_comb
if depot.network_name and comb.valid and (comb.status == defines.entity_status.working or comb.status == defines.entity_status.low_power) then
depot.priority = 0
depot.network_flag = 1
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
depot.priority = item_count
end
if item_name == depot.network_name then
depot.network_flag = item_count
end
end
end
end
else
depot.priority = 0
depot.network_flag = 0
end
end
end
for station_id, station in pairs(stations) do
@@ -420,23 +418,23 @@ function tick(map_data, mod_settings)
local r_threshold, p_threshold = get_thresholds(map_data, station, v.signal)
if -effective_item_count >= r_threshold then
local item_network_name = item_name + ":" + station.network_name
local item_network_name = station.network_name..":"..item_name
if r_stations_all[item_network_name] == nil then
r_stations_all[item_network_name] = {}
p_stations_all[item_network_name] = {}
all_names[#all_names + 1] = item_network_name
all_names[#all_names + 1] = v.signal
end
table.insert(r_stations_all[item_name], station_id)
table.insert(r_stations_all[item_network_name], station_id)
elseif effective_item_count >= p_threshold then
local item_network_name = item_name + ":" + station.network_name
local item_network_name = station.network_name..":"..item_name
if r_stations_all[item_network_name] == nil then
r_stations_all[item_network_name] = {}
p_stations_all[item_network_name] = {}
all_names[#all_names + 1] = item_network_name
all_names[#all_names + 1] = v.signal
end
table.insert(p_stations_all[item_name], station_id)
table.insert(p_stations_all[item_network_name], station_id)
end
end
end
@@ -464,18 +462,18 @@ function tick(map_data, mod_settings)
local r_station_id = table.remove(r_stations, i)
local best = 0
local best_train = nil
local best_depot = nil
local best_dist = INF
local highest_prior = -INF
local could_have_been_serviced = false
for j, p_station_id in ipairs(p_stations) do
local train, d = get_valid_train(map_data, r_station_id, p_station_id, item_type)
local depot, d = get_valid_train(map_data, r_station_id, p_station_id, item_type)
local prior = stations[p_station_id].priority
if prior > highest_prior or (prior == highest_prior and d < best_dist) then
if train then
if depot then
best = j
best_dist = d
best_train = train
best_depot = depot
highest_prior = prior
elseif d < INF then
could_have_been_serviced = true
@@ -483,8 +481,8 @@ function tick(map_data, mod_settings)
end
end
end
if best_train then
send_train_between(map_data, r_station_id, p_stations[best], best_train, item_name, economy)
if best_depot then
send_train_between(map_data, r_station_id, p_stations[best], best_depot, item_name, economy)
elseif could_have_been_serviced then
send_missing_train_alert_for_stops(stations[r_station_id].entity_stop, stations[p_stations[best]].entity_stop)
end
@@ -496,7 +494,7 @@ function tick(map_data, mod_settings)
local p_station_id = table.remove(p_stations, j)
local best = 0
local best_train = nil
local best_depot = nil
local lowest_tick = INF
local highest_prior = -INF
local could_have_been_serviced = false
@@ -504,10 +502,10 @@ function tick(map_data, mod_settings)
local r_station = stations[r_station_id]
local prior = r_station.priority
if prior > highest_prior or (prior == highest_prior and r_station.last_delivery_tick < lowest_tick) then
local train, d = get_valid_train(map_data, r_station_id, p_station_id, item_type)
if train then
local depot, d = get_valid_train(map_data, r_station_id, p_station_id, item_type)
if depot then
best = i
best_train = train
best_depot = depot
lowest_tick = r_station.last_delivery_tick
highest_prior = prior
elseif d < INF then
@@ -516,8 +514,8 @@ function tick(map_data, mod_settings)
end
end
end
if best_train then
send_train_between(map_data, r_stations[best], p_station_id, best_train, item_name, economy)
if best_depot then
send_train_between(map_data, r_stations[best], p_station_id, best_depot, item_name, economy)
elseif could_have_been_serviced then
send_missing_train_alert_for_stops(stations[r_stations[best]].entity_stop, stations[p_station_id].entity_stop)
end

View File

@@ -8,7 +8,7 @@
---@field public stations {[uint]: Station}
---@field public depots {[uint]: Depot}
---@field public trains {[uint]: Train}
---@field public trains_available {[string]: {[uint]: uint}}
---@field public trains_available {[string]: {[uint]: uint}} --{[network_name]: {[train_id]: depot_id}}
---@field public layouts {[uint]: string}
---@field public layout_train_count {[uint]: int}
---@field public train_classes {[string]: TrainClass}
@@ -38,6 +38,7 @@
---@field public entity_comb LuaEntity
---@field public network_name string?
---@field public network_flag int --transient
---@field public available_train uint?
---@class Train
---@field public entity LuaTrain
@@ -45,6 +46,7 @@
---@field public item_slot_capacity int
---@field public fluid_capacity int
---@field public depot_name string
---@field public depot Depot?
---@field public status int
---@field public p_station_id uint
---@field public r_station_id uint

View File

@@ -75,7 +75,7 @@ local window = flib_gui.build(rootgui, {
}},
---choose-elem-button
{type="line", style_mods={top_padding=10}},
{type="label", name="network_label", style="heading_3_label", caption={"cybersyn-gui.network"}, style_mods={top_padding=7}},
{type="label", name="network_label", ref={"network_label"}, style="heading_3_label", caption={"cybersyn-gui.network"}, style_mods={top_padding=7}},
{type="flow", name="bottom", direction="horizontal", children={
{type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", ref={"network"}, elem_type="signal", signal=control.first_signal, style_mods={bottom_margin=2, right_margin=6}, actions={
on_elem_changed={"choose-elem-button", comb.unit_number}
@@ -94,6 +94,7 @@ local window = flib_gui.build(rootgui, {
window.titlebar.drag_target = window.main_window
window.main_window.force_auto_center()
window.network.visible = selected_index == 1 or selected_index == 3
window.network_label.visible = selected_index == 1 or selected_index == 3
window.radiobutton.visible = selected_index == 1
window.radiolabel.visible = selected_index == 1

View File

@@ -1,15 +1,16 @@
--By Mami
local area = require("__flib__.area")
local abs = math.abs
local function iterr(a, i)
i = i - 1
if i > 0 then
return i, a[i]
i = i + 1
if i <= #a then
return i, a[#a - i + 1]
end
end
local function irpairs(a)
return iterr, a, #a + 1
return iterr, a, 0
end
@@ -18,7 +19,10 @@ end
---@param train_id uint
function remove_train(map_data, train, train_id)
map_data.trains[train_id] = nil
map_data.trains_available[train_id] = nil
local depot = train.depot
if depot then
remove_available_train(map_data, depot)
end
local layout_id = train.layout_id
local count = map_data.layout_train_count[layout_id]
if count <= 1 then
@@ -89,10 +93,13 @@ end
---@param train LuaTrain
local function get_train_direction(stop, train)
local back_rail = train.back_rail
local stop_rail = stop.connected_rail
if back_rail and stop_rail and back_rail.unit_number == stop_rail.unit_number then
return true
if back_rail then
local back_pos = back_rail.position
local stop_pos = stop.position
if abs(back_pos.x - stop_pos.x) < 3 and abs(back_pos.y - stop_pos.y) < 3 then
return true
end
end
return false
@@ -238,7 +245,7 @@ function set_r_wagon_combs(map_data, station, train)
if stack.valid_for_read then
local i = #signals + 1
--TODO: does this work or do we need to aggregate signals?
signals[i] = {index = i, signal = {type = stack.type, name = stack.name}, count = stack.count}
signals[i] = {index = i, signal = {type = stack.type, name = stack.name}, count = -stack.count}
end
end
set_combinator_output(map_data, comb, signals)
@@ -248,7 +255,7 @@ function set_r_wagon_combs(map_data, station, train)
local inv = carriage.get_fluid_contents()
for fluid_name, count in pairs(inv) do
local i = #signals + 1
signals[i] = {index = i, signal = {type = "fluid", name = fluid_name}, count = math.floor(count)}
signals[i] = {index = i, signal = {type = "fluid", name = fluid_name}, count = -math.floor(count)}
end
set_combinator_output(map_data, comb, signals)
end

View File

@@ -29,6 +29,43 @@ local function on_failed_delivery(map_data, train)
end
---@param map_data MapData
---@param depot Depot
---@param train_id uint
local function add_available_train(map_data, depot, train_id)
if depot.network_name then
local network = map_data.trains_available[depot.network_name]
if not network then
network = {}
map_data.trains_available[depot.network_name] = network
end
network[train_id] = depot.entity_stop.unit_number
end
depot.available_train = train_id
local train = map_data.trains[train_id]
train.depot_name = depot.entity_stop.backer_name
train.depot = depot
end
---@param map_data MapData
---@param depot Depot
function remove_available_train(map_data, depot)
if depot.available_train then
if depot.network_name then
local network = map_data.trains_available[depot.network_name]
if network then
network[depot.available_train] = nil
if next(network) == nil then
map_data.trains_available[depot.network_name] = nil
end
end
end
local train = map_data.trains[depot.available_train]
train.depot = nil
depot.available_train = nil
end
end
---@param map_data MapData
---@param stop LuaEntity
---@param comb LuaEntity
@@ -43,6 +80,17 @@ local function on_depot_built(map_data, stop, comb, control)
map_data.depots[stop.unit_number] = depot
end
local function on_depot_broken(map_data, depot)
--remove train
if depot.available_train then
--NOTE: we could remove the schedule from this train
--local train = map_data.trains[depot.available_train]
map_data.trains[depot.available_train] = nil
remove_available_train(map_data, depot)
end
map_data.depots[depot.entity_stop.unit_number] = nil
end
---@param map_data MapData
---@param stop LuaEntity
---@param comb1 LuaEntity
@@ -225,6 +273,7 @@ local function on_combinator_built(map_data, comb)
end
---@param map_data MapData
---@param comb LuaEntity
---@param network_name string?
function on_combinator_network_updated(map_data, comb, network_name)
local stop = map_data.to_stop[comb.unit_number]
@@ -237,7 +286,12 @@ function on_combinator_network_updated(map_data, comb, network_name)
else
local depot = map_data.depots[stop.unit_number]
if depot.entity_comb == comb then
if depot.available_train then
remove_available_train(map_data, depot)
add_available_train(map_data, depot, depot.available_train)
end
depot.network_name = network_name
end
end
end
@@ -279,7 +333,7 @@ local function on_combinator_broken(map_data, comb)
depot.entity_comb = depot_comb
depot.network_name = control.first_signal and control.first_signal.name
else
map_data.depots[stop.unit_number] = nil
on_depot_broken(map_data, depot)
end
end
end
@@ -353,8 +407,12 @@ local function on_stop_broken(map_data, stop)
local station = map_data.stations[stop.unit_number]
if station then
on_station_broken(map_data, stop.unit_number, station)
else
local depot = map_data.depots[stop.unit_number]
if depot then
on_depot_broken(map_data, depot)
end
end
map_data.depots[stop.unit_number] = nil
end
---@param map_data MapData
---@param stop LuaEntity
@@ -379,6 +437,12 @@ local function on_station_rename(map_data, stop)
end
end
end
else
local depot = map_data.depots[station_id]
if depot and depot.available_train then
local train = map_data.trains[depot.available_train]
train.depot_name = stop.backer_name
end
end
end
@@ -395,42 +459,41 @@ local function find_and_add_all_stations_from_nothing(map_data)
end
end
---@param map_data MapData
---@param stop LuaEntity
---@param depot Depot
---@param train_entity LuaTrain
local function on_train_arrives_depot(map_data, stop, train_entity)
local function on_train_arrives_depot(map_data, depot, train_entity)
local contents = train_entity.get_contents()
local train = map_data.trains[train_entity.id]
local train_id = train_entity.id
local train = map_data.trains[train_id]
if train then
if train.manifest and train.status == STATUS_R_TO_D then
--succeeded delivery
train.p_station_id = 0
train.r_station_id = 0
train.manifest = nil
train.depot_name = train_entity.station.backer_name
train.status = STATUS_D
map_data.trains_available[stop.unit_number] = train_entity.id
add_available_train(map_data, depot, train_id)
else
if train.manifest then
on_failed_delivery(map_data, train)
send_lost_train_alert(train.entity)
end
train.depot_name = train_entity.station.backer_name
train.status = STATUS_D
map_data.trains_available[stop.unit_number] = train_entity.id
add_available_train(map_data, depot, train_id)
end
if next(contents) ~= nil then
--train still has cargo
train_entity.schedule = nil
remove_train(map_data, train, train_entity.id)
remove_train(map_data, train, train_id)
send_nonempty_train_in_depot_alert(train_entity)
else
train_entity.schedule = create_depot_schedule(train.depot_name)
end
elseif next(contents) == nil then
train = {
depot_name = train_entity.station.backer_name,
--depot_name = train_entity.station.backer_name,
--depot = depot,
status = STATUS_D,
entity = train_entity,
layout_id = 0,
@@ -441,8 +504,8 @@ local function on_train_arrives_depot(map_data, stop, train_entity)
manifest = nil,
}
update_train_layout(map_data, train)
map_data.trains[train_entity.id] = train
map_data.trains_available[stop.unit_number] = train_entity.id
map_data.trains[train_id] = train
add_available_train(map_data, depot, train_id)
local schedule = create_depot_schedule(train.depot_name)
train_entity.schedule = schedule
else
@@ -508,6 +571,8 @@ local function on_train_leaves_station(map_data, train)
set_combinator_output(map_data, station.entity_comb1, nil)
unset_wagon_combs(map_data, station)
end
elseif train.depot then
remove_available_train(map_data, train.depot)
end
end
@@ -605,8 +670,11 @@ local function on_train_changed(event)
if stop and stop.valid and stop.name == "train-stop" then
if global.stations[stop.unit_number] then
on_train_arrives_buffer(global, stop, train)
elseif global.depots[stop.unit_number] then
on_train_arrives_depot(global, stop, train_e)
else
local depot = global.depots[stop.unit_number]
if depot then
on_train_arrives_depot(global, depot, train_e)
end
end
end
elseif event.old_state == defines.train_state.wait_station then