function ScanTrains() storage.trains = {} for _,train in pairs(game.train_manager.get_trains({})) do storage.trains[train.id] = train end 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] = ("%d%s%s%d"):format(train.id,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] = ("%d:%d"):format(train.id,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 defines.train_state.destination_full or defines.train_state.no_schedule then trainsWaiting = trainsWaiting + 1 end if train.state == defines.train_state.on_the_path or defines.train_state.arrive_signal or defines.train_state.wait_signal then trainsDriving = trainsDriving + 1 end if train.state == defines.train_state.manual_control or defines.train_state.manual_control_stop then trainsManual = trainsManual + 1 end if 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 = { lastInventory={}, currentInventory={}, lastState = 0, lastStationUnitNumber = 0, currentStationUnitNumber = 0, totalCargoCount = 0, totalCargo = {}, lastArrivalTime = 0, currentArrivalTime = 0 } ---@param inv table[] ---@return 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 {} if event.train.state == defines.train_state.wait_station then 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.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) + value.delta end storage.trainStats[trainID] = stat end end log("inEvent") end function GetTrainStatistics() local trainParts = {} trainParts[#trainParts+1] = "---train-total-statistics---\n" for trainID, stat in pairs(storage.trainStats) do trainParts[#trainParts+1] = ("%d:%d"):format(trainID,stat.totalCargoCount) end return table.concat(trainParts,"\n") end function SendTrainStats() ScanTrains() local returnParts = {} returnParts[#returnParts+1] = GetTrainPlayerKills() returnParts[#returnParts+1] = GetTrainTotalKills() returnParts[#returnParts+1] = GetTrainStates() returnParts[#returnParts+1] = GetTrainStatistics() helpers.send_udp(udpAddress,table.concat(returnParts,"\n"),serverIndex) end