134 lines
4.5 KiB
Lua

--- Functions for working with trains.
--- ```lua
--- local flib_train = require("__flib__/train")
--- ```
--- @class flib_train
local flib_train = {}
local table = table
--- Get the main locomotive in a given train.
--- @param train LuaTrain
--- @return LuaEntity? locomotive The primary locomotive entity or `nil` when no locomotive was found
function flib_train.get_main_locomotive(train)
if
train.valid
and train.locomotives
and (#train.locomotives.front_movers > 0 or #train.locomotives.back_movers > 0)
then
return train.locomotives.front_movers and train.locomotives.front_movers[1] or train.locomotives.back_movers[1]
end
end
--- Get the backer_name of the main locomotive in a given train.
--- @param train LuaTrain
--- @return string? backer_name The backer_name of the primary locomotive or `nil` when no locomotive was found
function flib_train.get_backer_name(train)
local loco = flib_train.get_main_locomotive(train)
return loco and loco.backer_name
end
--- Rotate a single carriage of a train.
--- @param entity LuaEntity
--- @return boolean rotated `true` when rotation was successful.
function flib_train.rotate_carriage(entity)
local disconnected_back = entity.disconnect_rolling_stock(defines.rail_direction.back)
local disconnected_front = entity.disconnect_rolling_stock(defines.rail_direction.front)
entity.rotate()
-- Only reconnect the side that was disconnected
local reconnected_front = disconnected_front
local reconnected_back = disconnected_back
if disconnected_back then
reconnected_back = entity.connect_rolling_stock(defines.rail_direction.front)
end
if disconnected_front then
reconnected_front = entity.connect_rolling_stock(defines.rail_direction.back)
end
if disconnected_front and not reconnected_front then
return false
end
if disconnected_back and not reconnected_back then
return false
end
return true
end
--- Create a string representing train composition, and return a count of locomotives and wagons in the train.
--- - `<L<`, `>L>`: Locomotives
--- - `C`: Cargo wagon
--- - `F`: Fluid wagon
--- - `A`: Artillery wagon
--- @param train LuaTrain
--- @return string? composition The composition string, or `nil` if the train was invalid.
--- @return TrainCompositionCounts?
function flib_train.get_composition_string(train)
if train and train.valid then
local carriages = train.carriages
local string_table = {}
local count_wagons, count_loco_front, count_loco_back, i = 0, 0, 0, 0
local locos_front = train.locomotives.front_movers
for _, carriage in pairs(carriages) do
i = i + 1
if carriage.type == "locomotive" then
local faces_forward = false
for _, loco in pairs(locos_front) do
if carriage.unit_number == loco.unit_number then
faces_forward = true
break
end
end
if faces_forward then
string_table[i] = "<L<"
count_loco_front = count_loco_front + 1
else
string_table[i] = ">L>"
count_loco_back = count_loco_back + 1
end
elseif carriage.type == "cargo-wagon" then
count_wagons = count_wagons + 1
string_table[i] = "C"
elseif carriage.type == "fluid-wagon" then
count_wagons = count_wagons + 1
string_table[i] = "F"
elseif carriage.type == "artillery-wagon" then
count_wagons = count_wagons + 1
string_table[i] = "A"
else
count_wagons = count_wagons + 1
string_table[i] = "?"
end
end
return table.concat(string_table),
{
total = i,
wagons = count_wagons,
front_movers = count_loco_front,
back_movers = count_loco_back,
}
end
end
--- Open train GUI for one player.
--- @param player_index number
--- @param train LuaTrain
--- @return boolean `true` if the GUI was opened.
function flib_train.open_gui(player_index, train)
if train and train.valid and game.players[player_index] then
local loco = flib_train.get_main_locomotive(train)
if loco and loco.valid then
game.players[player_index].opened = loco
return true
end
end
return false
end
return flib_train
--- @class TrainCompositionCounts
--- @field total number The total number of rolling stocks in the train.
--- @field wagons number The number of wagons in the train.
--- @field front_movers number The number of front-facing locomotives in the train.
--- @field back_movers number The number of back-facing locomotives in the train.