262 lines
8.6 KiB
Lua
262 lines
8.6 KiB
Lua
function ScanTrains()
|
|
storage.trains = {}
|
|
for _,train in pairs(game.train_manager.get_trains({})) do
|
|
storage.trains[train.id] = train
|
|
end
|
|
end
|
|
|
|
---comment Get the first locomotive in the front, if non, in the back, if none empty string
|
|
---@param train LuaTrain
|
|
function GetTrainName(train)
|
|
if train.locomotives.front_movers[1] then
|
|
return train.locomotives.front_movers[1].backer_name or ""
|
|
elseif train.locomotives.back_movers[1] then
|
|
return train.locomotives.back_movers[1].backer_name or ""
|
|
end
|
|
return ""
|
|
end
|
|
|
|
function GetTrainsInDepot()
|
|
local trainsInDepot = 0
|
|
for trainsID, train in pairs(storage.trains) do
|
|
if train.state == defines.train_state.wait_station
|
|
and train.station and train.station.backer_name == autotrainDepotName then
|
|
trainsInDepot = trainsInDepot + 1
|
|
end
|
|
end
|
|
local trainsInGroup = #game.train_manager.get_trains({group=autotrainGroupName})
|
|
return ("---autotrain-stats---\n%d:%d"):format(trainsInDepot,trainsInGroup)
|
|
end
|
|
|
|
function GetTrainPlayerKills()
|
|
local trainKills = {}
|
|
trainKills[#trainKills+1] = "---train-player-kills---"
|
|
---@type LuaTrain
|
|
for _, train in pairs(storage.trains ) do
|
|
for killedPlayerID,killedPlayerCount in pairs(train.killed_players) do
|
|
trainKills[#trainKills+1] = ("%s:%s:%s:%s:%d"):format(train.id,GetTrainName(train),killedPlayerID,game.players[killedPlayerID].name,killedPlayerCount)
|
|
end
|
|
end
|
|
return table.concat(trainKills,"\n")
|
|
end
|
|
|
|
|
|
function GetTrainTotalKills()
|
|
local trainKills = {}
|
|
trainKills[#trainKills+1] = "---train-total-kills---"
|
|
---@type LuaTrain
|
|
for _, train in pairs(storage.trains) do
|
|
trainKills[#trainKills+1] = ("%s:%s:%d"):format(train.id,GetTrainName(train),train.kill_count)
|
|
end
|
|
return table.concat(trainKills,"\n")
|
|
end
|
|
|
|
function GetTrainStates()
|
|
local trainsDriving = 0
|
|
local trainsWaiting = 0
|
|
local trainsProblems = 0
|
|
local trainsManual = 0
|
|
for _, train in pairs(storage.trains) do
|
|
if train.state == defines.train_state.wait_station
|
|
or train.state == defines.train_state.destination_full
|
|
or train.state == defines.train_state.no_schedule
|
|
then trainsWaiting = trainsWaiting + 1
|
|
|
|
elseif train.state == defines.train_state.on_the_path
|
|
or train.state == defines.train_state.arrive_signal
|
|
or train.state == defines.train_state.arrive_station
|
|
or train.state == defines.train_state.wait_signal
|
|
then trainsDriving = trainsDriving + 1
|
|
|
|
elseif train.state == defines.train_state.manual_control
|
|
or train.state == defines.train_state.manual_control_stop
|
|
then trainsManual = trainsManual + 1
|
|
|
|
elseif train.state == defines.train_state.no_path
|
|
then trainsProblems = trainsProblems + 1 end
|
|
end
|
|
return ("---trains-states---\n%d:%d:%d:%d"):format(trainsDriving,trainsManual,trainsProblems,trainsWaiting)
|
|
end
|
|
|
|
---@class trainStat
|
|
trainStat = {
|
|
trainID = 0,
|
|
trainName = "",
|
|
lastInventory={},
|
|
currentInventory={},
|
|
lastState = 0,
|
|
lastStationUnitNumber = 0,
|
|
currentStationUnitNumber = 0,
|
|
totalCargoCount = 0,
|
|
totalCargo = {},
|
|
lastArrivalTime = 0,
|
|
currentArrivalTime = 0,
|
|
---@type trip
|
|
trips = {}
|
|
}
|
|
---@class trip
|
|
trip = {
|
|
startStation= {},
|
|
endStation = {},
|
|
timeTaken = 0
|
|
}
|
|
|
|
---@param inv table[]
|
|
---@return table<string, table>
|
|
local function toLookup(inv)
|
|
local t = {}
|
|
for _, item in ipairs(inv) do
|
|
local key = item.name .. ":" .. (item.quality or 0) -- eindeutiger Key
|
|
t[key] = item.count
|
|
end
|
|
return t
|
|
end
|
|
|
|
---@param oldInv table[]
|
|
---@param newInv table[]
|
|
---@return table[]
|
|
local function inventoryDiff(oldInv, newInv)
|
|
local oldLookup = toLookup(oldInv)
|
|
local newLookup = toLookup(newInv)
|
|
local diff = {}
|
|
|
|
-- Items, die neu hinzugekommen oder verändert wurden
|
|
for key, newCount in pairs(newLookup) do
|
|
local oldCount = oldLookup[key] or 0
|
|
if newCount ~= oldCount then
|
|
local name, quality = key:match("([^:]+):([^:]+)")
|
|
table.insert(diff, {
|
|
name = name,
|
|
quality = tonumber(quality),
|
|
oldCount = oldCount,
|
|
newCount = newCount,
|
|
delta = newCount - oldCount
|
|
})
|
|
end
|
|
end
|
|
|
|
-- Items, die komplett entfernt wurden
|
|
for key, oldCount in pairs(oldLookup) do
|
|
if newLookup[key] == nil then
|
|
local name, quality = key:match("([^:]+):([^:]+)")
|
|
table.insert(diff, {
|
|
name = name,
|
|
quality = tonumber(quality),
|
|
oldCount = oldCount,
|
|
newCount = 0,
|
|
delta = -oldCount
|
|
})
|
|
end
|
|
end
|
|
|
|
return diff
|
|
end
|
|
|
|
|
|
function onTrainStateChange(event)
|
|
-- Train arrived at station, so we store current data
|
|
---@type LuaTrain
|
|
local train = event.train
|
|
|
|
local trainID = train.id
|
|
---@type trainStat
|
|
local stat = storage.trainStats[trainID] or {}
|
|
stat.trips = stat.trips or {}
|
|
stat.trainID = trainID
|
|
stat.trainName = GetTrainName(train)
|
|
|
|
if event.train.state == defines.train_state.wait_station then
|
|
|
|
if train.station.unit_number == stat.lastStationUnitNumber then return end
|
|
|
|
stat.lastStationUnitNumber = stat.currentStationUnitNumber
|
|
stat.lastInventory = stat.currentInventory
|
|
stat.lastArrivalTime = stat.currentArrivalTime
|
|
|
|
stat.currentStationUnitNumber = train.station.unit_number
|
|
stat.currentInventory = train.get_contents()
|
|
stat.currentArrivalTime = game.tick
|
|
|
|
if stat.lastStationUnitNumber
|
|
and stat.currentStationUnitNumber
|
|
and (stat.lastStationUnitNumber ~= stat.currentStationUnitNumber) then
|
|
local tripIdentifier = tostring(stat.lastStationUnitNumber) .. tostring(stat.currentStationUnitNumber)
|
|
stat.trips[tripIdentifier] = {
|
|
startStation = game.get_entity_by_unit_number(stat.lastStationUnitNumber),
|
|
endStation = game.get_entity_by_unit_number(stat.currentStationUnitNumber),
|
|
timeTaken = stat.currentArrivalTime-stat.lastArrivalTime}
|
|
end
|
|
|
|
if stat.currentInventory and stat.lastInventory then
|
|
--Get Total Cargo
|
|
for key, value in pairs(inventoryDiff(stat.lastInventory,stat.currentInventory)) do
|
|
stat.totalCargoCount = (stat.totalCargoCount or 0) + math.abs(value.delta)
|
|
end
|
|
end
|
|
|
|
storage.trainStats[trainID] = stat
|
|
end
|
|
--log("inEvent")
|
|
end
|
|
|
|
function GetTrainTripStats()
|
|
local tripParts = {}
|
|
tripParts[#tripParts+1] = "---train-trips---\n"
|
|
for trainID,stats in pairs(storage.trainStats) do
|
|
for _,trip in pairs(stats.trips or {}) do
|
|
tripParts[#tripParts+1] =
|
|
("%d:%s:%s:%s:%d"):format(
|
|
trainID,
|
|
stats.trainName,
|
|
trip.startStation.backer_name,
|
|
trip.endStation.backer_name,
|
|
trip.timeTaken)
|
|
end
|
|
end
|
|
return table.concat(tripParts,"\n")
|
|
end
|
|
|
|
function GetTrainStatistics()
|
|
local trainParts = {}
|
|
trainParts[#trainParts+1] = "---train-total-statistics---\n"
|
|
for trainID, stat in pairs(storage.trainStats) do
|
|
trainParts[#trainParts+1] = ("%d:%s:%d"):format(trainID,stat.trainName,stat.totalCargoCount or 0)
|
|
end
|
|
return table.concat(trainParts,"\n")
|
|
end
|
|
|
|
---Purges stats for trains that no longer exist
|
|
---@param trainID integer|nil If provided, purges only that train. If nil, purges all dead trains.
|
|
function PurgeDeadTrainStats(trainID)
|
|
if trainID then
|
|
-- Purge a specific train if it doesn't exist
|
|
if not storage.trains[trainID] then
|
|
storage.trainStats[trainID] = nil
|
|
return true
|
|
end
|
|
else
|
|
-- Purge all trains not in storage.trains
|
|
for statTrainID in pairs(storage.trainStats) do
|
|
if not storage.trains[statTrainID] then
|
|
storage.trainStats[statTrainID] = nil
|
|
end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
function SendTrainStats()
|
|
if options.enableTrains then
|
|
ScanTrains()
|
|
PurgeDeadTrainStats()
|
|
local returnParts = {}
|
|
returnParts[#returnParts+1] = GetTrainPlayerKills()
|
|
returnParts[#returnParts+1] = GetTrainTotalKills()
|
|
returnParts[#returnParts+1] = GetTrainStates()
|
|
returnParts[#returnParts+1] = GetTrainStatistics()
|
|
returnParts[#returnParts+1] = GetTrainsInDepot()
|
|
returnParts[#returnParts+1] = GetTrainTripStats()
|
|
helpers.send_udp(udpAddress,table.concat(returnParts,"\n"),serverIndex)
|
|
end
|
|
end |