Add metrics combinator entity, GUI, and related functionality; enhance power and production stats tracking
Greatly improved train trip perfomance by culling table after sending Fixed formatting in many places
This commit is contained in:
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"Lua.workspace.userThirdParty": [
|
"Lua.workspace.userThirdParty": [
|
||||||
"c:\\Users\\jangr\\AppData\\Roaming\\Code\\User\\workspaceStorage\\6d87f11bcadf77c8bf3a32c6545bb9a5\\justarandomgeek.factoriomod-debug\\sumneko-3rd"
|
"c:\\Users\\jangr\\AppData\\Roaming\\Code\\User\\workspaceStorage\\7cc4b07e291c43ff9c178f1dad6e0f26\\justarandomgeek.factoriomod-debug\\sumneko-3rd"
|
||||||
],
|
],
|
||||||
"Lua.workspace.checkThirdParty": "ApplyInMemory",
|
"Lua.workspace.checkThirdParty": "ApplyInMemory",
|
||||||
"factorio.versions": [
|
"factorio.versions": [
|
||||||
|
|||||||
240
control.lua
240
control.lua
@@ -5,6 +5,7 @@ require("research-stats")
|
|||||||
require("power-stats")
|
require("power-stats")
|
||||||
require("logistic-network-stats")
|
require("logistic-network-stats")
|
||||||
require("train-stats")
|
require("train-stats")
|
||||||
|
require("metrics-combinator")
|
||||||
|
|
||||||
tickInterval = tonumber(settings.global["factorio-metrics-exporter-tick-interval"].value) or 300
|
tickInterval = tonumber(settings.global["factorio-metrics-exporter-tick-interval"].value) or 300
|
||||||
udpAddress = 52555
|
udpAddress = 52555
|
||||||
@@ -13,9 +14,11 @@ sendIndex = 0
|
|||||||
serverIndex = 0
|
serverIndex = 0
|
||||||
scannedGrids = false
|
scannedGrids = false
|
||||||
scannedLabs = false
|
scannedLabs = false
|
||||||
|
scannedGenerators = false
|
||||||
autotrainGroupName = ""
|
autotrainGroupName = ""
|
||||||
autotrainDepotName = ""
|
autotrainDepotName = ""
|
||||||
|
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
enableMod = false,
|
enableMod = false,
|
||||||
enablePlayers = false,
|
enablePlayers = false,
|
||||||
@@ -31,7 +34,7 @@ options = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
script.on_init(function ()
|
script.on_init(function()
|
||||||
storage.electricGrids = {}
|
storage.electricGrids = {}
|
||||||
storage.researchedTechnologies = {}
|
storage.researchedTechnologies = {}
|
||||||
storage.playerDeathCount = {}
|
storage.playerDeathCount = {}
|
||||||
@@ -46,9 +49,19 @@ script.on_init(function ()
|
|||||||
storage.deconstructedEntities = {}
|
storage.deconstructedEntities = {}
|
||||||
storage.trainStats = {}
|
storage.trainStats = {}
|
||||||
storage.networkCache = {}
|
storage.networkCache = {}
|
||||||
|
---@type LuaEntity[]
|
||||||
|
storage.powerGenerators = {}
|
||||||
---@type LuaTrain[]
|
---@type LuaTrain[]
|
||||||
storage.trains = {}
|
storage.trains = {}
|
||||||
|
storage.powerStats = {}
|
||||||
|
|
||||||
|
storage.cargoStats = {}
|
||||||
|
|
||||||
|
storage.metrics = {}
|
||||||
|
storage.cliffsDestroyed = 0
|
||||||
|
|
||||||
|
storage.nuclearReactorDeaths = 0
|
||||||
|
|
||||||
|
|
||||||
storage.scannedGrids = false
|
storage.scannedGrids = false
|
||||||
storage.scannedLabs = false
|
storage.scannedLabs = false
|
||||||
@@ -67,14 +80,12 @@ script.on_init(function ()
|
|||||||
options.enableTrainTrips = settings.global["factorio-metrics-exporter-export_train_trips"].value
|
options.enableTrainTrips = settings.global["factorio-metrics-exporter-export_train_trips"].value
|
||||||
autotrainGroupName = settings.global["factorio-metrics-exporter-autotrain_group_name"].value
|
autotrainGroupName = settings.global["factorio-metrics-exporter-autotrain_group_name"].value
|
||||||
autotrainDepotName = settings.global["factorio-metrics-exporter-autotrain_depot_name"].value
|
autotrainDepotName = settings.global["factorio-metrics-exporter-autotrain_depot_name"].value
|
||||||
|
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
script.on_load(function ()
|
script.on_load(function()
|
||||||
log("factorio-metrics-exporter: on_load")
|
log("factorio-metrics-exporter: on_load")
|
||||||
log("tickInterval: "..tickInterval)
|
log("tickInterval: " .. tickInterval)
|
||||||
log("udpAddress: "..udpAddress)
|
log("udpAddress: " .. udpAddress)
|
||||||
|
|
||||||
options.enableMod = settings.global["factorio-metrics-exporter-enable"].value
|
options.enableMod = settings.global["factorio-metrics-exporter-enable"].value
|
||||||
options.enableProduction = settings.global["factorio-metrics-exporter-export_production_stats"].value
|
options.enableProduction = settings.global["factorio-metrics-exporter-export_production_stats"].value
|
||||||
@@ -105,21 +116,29 @@ script.on_configuration_changed(function()
|
|||||||
storage.scannedLabs = storage.scannedLabs or false
|
storage.scannedLabs = storage.scannedLabs or false
|
||||||
storage.playerDeathCause = storage.playerDeathCause or {}
|
storage.playerDeathCause = storage.playerDeathCause or {}
|
||||||
storage.constructedEntites = storage.constructedEntites or {}
|
storage.constructedEntites = storage.constructedEntites or {}
|
||||||
storage.deconstructedEntities = storage.deconstructedEntities or{}
|
storage.deconstructedEntities = storage.deconstructedEntities or {}
|
||||||
storage.networkCache = storage.networkCache or {}
|
storage.networkCache = storage.networkCache or {}
|
||||||
storage.trains = storage.trains or {}
|
storage.trains = storage.trains or {}
|
||||||
---@type table<uint, trainStat>
|
---@type table<uint, trainStat>
|
||||||
storage.trainStats = storage.trainStats or {}
|
storage.trainStats = storage.trainStats or {}
|
||||||
|
---@type LuaEntity[]
|
||||||
|
storage.powerGenerators = storage.powerGenerators or {}
|
||||||
|
storage.powerStats = storage.powerStats or {}
|
||||||
|
storage.metrics = storage.metrics or {}
|
||||||
|
storage.cargoStats = storage.cargoStats or {}
|
||||||
|
storage.nuclearReactorDeaths = storage.nuclearReactorDeaths or 0
|
||||||
|
storage.cliffsDestroyed = storage.cliffsDestroyed or 0
|
||||||
ScanNetworks()
|
ScanNetworks()
|
||||||
ScanLabs()
|
ScanLabs()
|
||||||
ScanTrains()
|
ScanTrains()
|
||||||
|
ScanGenerators()
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
script.on_event(defines.events.on_runtime_mod_setting_changed, function(event)
|
script.on_event(defines.events.on_runtime_mod_setting_changed, function(event)
|
||||||
log("Mod setting changed: "..event.setting)
|
log("Mod setting changed: " .. event.setting)
|
||||||
if event.setting == "factorio-metrics-exporter-tick-interval" then
|
if event.setting == "factorio-metrics-exporter-tick-interval" then
|
||||||
tickInterval = settings.global["factorio-metrics-exporter-tick-interval"].value
|
tickInterval = settings.global["factorio-metrics-exporter-tick-interval"].value
|
||||||
end
|
end
|
||||||
@@ -163,13 +182,12 @@ script.on_event(defines.events.on_runtime_mod_setting_changed, function(event)
|
|||||||
if event.setting == "factorio-metrics-exporter-autotrain_depot_name" then
|
if event.setting == "factorio-metrics-exporter-autotrain_depot_name" then
|
||||||
autotrainDepotName = settings.global["factorio-metrics-exporter-autotrain_depot_name"].value
|
autotrainDepotName = settings.global["factorio-metrics-exporter-autotrain_depot_name"].value
|
||||||
end
|
end
|
||||||
if event.setting == "factorio-metrics-exporter-autotrain_group_name" then
|
if event.setting == "factorio-metrics-exporter-autotrain_group_name" then
|
||||||
autotrainGroupName = settings.global["factorio-metrics-exporter-autotrain_group_name"].value
|
autotrainGroupName = settings.global["factorio-metrics-exporter-autotrain_group_name"].value
|
||||||
end
|
end
|
||||||
if event.setting == "factorio-metrics-exporter-export_train_trips" then
|
if event.setting == "factorio-metrics-exporter-export_train_trips" then
|
||||||
options.enableTrainTrips = settings.global["factorio-metrics-exporter-export_train_trips"].value
|
options.enableTrainTrips = settings.global["factorio-metrics-exporter-export_train_trips"].value
|
||||||
end
|
end
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
@@ -182,55 +200,56 @@ script.on_event(defines.events.on_player_died, function(event)
|
|||||||
local victim_index = event.player_index
|
local victim_index = event.player_index
|
||||||
local killerName = killer.name
|
local killerName = killer.name
|
||||||
local victimName = game.players[victim_index].name
|
local victimName = game.players[victim_index].name
|
||||||
log(("Player ID %d:%s killed player ID %d:%s"):format(killer_index,killerName,victim_index,victimName))
|
log(("Player ID %d:%s killed player ID %d:%s"):format(killer_index, killerName, victim_index, victimName))
|
||||||
|
|
||||||
storage.playerKillCount[killer_index] =
|
storage.playerKillCount[killer_index] =
|
||||||
storage.playerKillCount[killer_index] or {}
|
storage.playerKillCount[killer_index] or {}
|
||||||
|
|
||||||
storage.playerKillCount[killer_index][victim_index] =
|
storage.playerKillCount[killer_index][victim_index] =
|
||||||
(storage.playerKillCount[killer_index][victim_index] or 0) + 1
|
(storage.playerKillCount[killer_index][victim_index] or 0) + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--Log cause of player death
|
--Log cause of player death
|
||||||
if event.cause and event.cause.type then
|
if event.cause and event.cause.name then
|
||||||
storage.playerDeathCause[event.player_index] =
|
storage.playerDeathCause[event.player_index] =
|
||||||
storage.playerDeathCause[event.player_index] or {}
|
storage.playerDeathCause[event.player_index] or {}
|
||||||
|
|
||||||
storage.playerDeathCause[event.player_index][event.cause.type] =
|
storage.playerDeathCause[event.player_index][event.cause.name] =
|
||||||
(storage.playerDeathCause[event.player_index][event.cause.type] or 0) + 1
|
(storage.playerDeathCause[event.player_index][event.cause.name] or 0) + 1
|
||||||
|
|
||||||
log(("Player %s died from type %s"):format(game.players[event.player_index].name,event.cause.type))
|
|
||||||
|
|
||||||
|
log(("Player %s died from type %s"):format(game.players[event.player_index].name, event.cause.name))
|
||||||
end
|
end
|
||||||
--Log player death count
|
--Log player death count
|
||||||
storage.playerDeathCount[event.player_index] = (storage.playerDeathCount[event.player_index] or 0) + 1
|
storage.playerDeathCount[event.player_index] = (storage.playerDeathCount[event.player_index] or 0) + 1
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function SendGameStats()
|
function SendGameStats()
|
||||||
if options.enablePlayers then
|
if options.enablePlayers then
|
||||||
local returnParts = {}
|
local returnParts = {}
|
||||||
GetMods()
|
GetMods()
|
||||||
returnParts[#returnParts+1] = GetMapSeed()
|
returnParts[#returnParts + 1] = GetMapSeed()
|
||||||
returnParts[#returnParts+1] = GetRocketsLaunched()
|
returnParts[#returnParts + 1] = GetEvolution()
|
||||||
returnParts[#returnParts+1] = GetPlayerTime()
|
returnParts[#returnParts + 1] = GetRocketsLaunched()
|
||||||
returnParts[#returnParts+1] = GetPlayerDeaths()
|
returnParts[#returnParts + 1] = GetTotalPlayTime()
|
||||||
returnParts[#returnParts+1] = GetPlayerDeathCauses()
|
returnParts[#returnParts + 1] = GetPlayerTime()
|
||||||
returnParts[#returnParts+1] = GetPlayerKills()
|
returnParts[#returnParts + 1] = GetPlayerDeaths()
|
||||||
returnParts[#returnParts+1] = GetPlayerEntityStats()
|
returnParts[#returnParts + 1] = GetPlayerDeathCauses()
|
||||||
helpers.send_udp(udpAddress, table.concat(returnParts, "\n"), serverIndex)
|
returnParts[#returnParts + 1] = GetPlayerKills()
|
||||||
|
returnParts[#returnParts + 1] = GetPlayerEntityStats()
|
||||||
|
helpers.send_udp(udpAddress, table.concat(returnParts, "\n"), serverIndex)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function SendAll(event)
|
function SendAll(event)
|
||||||
|
if (isInitialized == false) then
|
||||||
if(isInitialized == false) then
|
|
||||||
if game.is_multiplayer() then
|
if game.is_multiplayer() then
|
||||||
serverIndex = 0
|
serverIndex = 0
|
||||||
log("Loaded game as mulitplayer")
|
log("Loaded game as mulitplayer")
|
||||||
else
|
else
|
||||||
log("Loaded game as singleplayer")
|
log("Loaded game as singleplayer")
|
||||||
serverIndex = 1
|
serverIndex = 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
isInitialized = true
|
isInitialized = true
|
||||||
@@ -241,22 +260,30 @@ function SendAll(event)
|
|||||||
scannedGrids = true
|
scannedGrids = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if scannedGenerators == false then
|
||||||
|
storage.powerGenerators = {}
|
||||||
|
ScanGenerators()
|
||||||
|
scannedGenerators = true
|
||||||
|
end
|
||||||
|
|
||||||
if scannedLabs == false then
|
if scannedLabs == false then
|
||||||
ScanLabs()
|
ScanLabs()
|
||||||
scannedLabs = true
|
scannedLabs = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if options.enableMod==true then
|
if options.enableMod == true then
|
||||||
|
local interval = math.max(1, math.floor(tickInterval / 10))
|
||||||
local interval = math.max(1, math.floor(tickInterval / 10))
|
if event.tick % interval ~= 0 then return end
|
||||||
if event.tick % interval ~= 0 then return end
|
|
||||||
sendIndex = (sendIndex % 10) + 1
|
sendIndex = (sendIndex % 10) + 1
|
||||||
if sendIndex == 1 then SendProductionStats() end
|
if sendIndex == 1 then SendProductionStats() end
|
||||||
if sendIndex == 2 then SendPollutionStats() end
|
if sendIndex == 2 then SendPollutionStats() end
|
||||||
if sendIndex == 3 then SendKillStats() end
|
if sendIndex == 3 then SendKillStats() end
|
||||||
if sendIndex == 4 then SendFluidProductionStats() end
|
if sendIndex == 4 then SendFluidProductionStats() end
|
||||||
if sendIndex == 5 then SendBuildStats() end
|
if sendIndex == 5 then SendBuildStats() end
|
||||||
if sendIndex == 6 then SendResearchStats() end
|
if sendIndex == 6 then
|
||||||
|
SendResearchStats()
|
||||||
|
SendCombinatorMetrics()
|
||||||
|
end
|
||||||
if sendIndex == 7 then SendLogisticStats() end
|
if sendIndex == 7 then SendLogisticStats() end
|
||||||
if sendIndex == 8 then SendPowerStats() end
|
if sendIndex == 8 then SendPowerStats() end
|
||||||
if sendIndex == 9 then SendGameStats() end
|
if sendIndex == 9 then SendGameStats() end
|
||||||
@@ -272,24 +299,41 @@ function UpdateStorage(event)
|
|||||||
if event.entity.type == "electric-pole" then
|
if event.entity.type == "electric-pole" then
|
||||||
AddPowerPole(event)
|
AddPowerPole(event)
|
||||||
end
|
end
|
||||||
|
if event.entity.type == "generator"
|
||||||
|
or event.entity.type == "fusion-generator"
|
||||||
|
or event.entity.type == "solar-panel" then
|
||||||
|
AddGenerator(event)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function RemoveStorage(event)
|
function RemoveStorage(event)
|
||||||
if not event then return end
|
if not event then return end
|
||||||
if event.entity.type =="lab" then
|
if event.entity.type == "lab" then
|
||||||
RemoveLab(event)
|
RemoveLab(event)
|
||||||
end
|
end
|
||||||
if event.entity.type == "electric-pole" then
|
if event.entity.type == "electric-pole" then
|
||||||
RemovePowerPole(event)
|
RemovePowerPole(event)
|
||||||
end
|
end
|
||||||
|
if event.entity.type == "generator"
|
||||||
|
or event.entity.type == "fusion-generator"
|
||||||
|
or event.entity.type == "solar-panel" then
|
||||||
|
RemoveGenerator(event)
|
||||||
|
end
|
||||||
|
|
||||||
--log(event.entity.name)
|
--log(event.entity.name)
|
||||||
if event.entity.name == "crash-site-spaceship" then
|
if event.entity.name == "crash-site-spaceship" then
|
||||||
--log(event.name)
|
--log(event.name)
|
||||||
if event.name == defines.events.on_player_mined_entity then
|
if event.name == defines.events.on_player_mined_entity then
|
||||||
--log("in ban call")
|
--log("in ban call")
|
||||||
if settings.global["factorio-metrics-exporter-enable_denkmalschutz"].value == true then
|
if settings.global["factorio-metrics-exporter-enable_denkmalschutz"].value == true then
|
||||||
game.ban_player(event.player_index,"You violated the rules of DENKMALSCHUTZ!!!")
|
game.ban_player(event.player_index, "You violated the rules of DENKMALSCHUTZ!!!")
|
||||||
end
|
game.kick_player(event.player_index, "")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if event.name == defines.events.on_robot_mined_entity then
|
||||||
|
if event.entity.last_user then
|
||||||
|
game.ban_player(event.entity.last_user.index, "You violated the rules of DENKMALSCHUTZ!!!")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -300,68 +344,91 @@ function CreateEntity(event)
|
|||||||
|
|
||||||
--Event is PlayerPlaced
|
--Event is PlayerPlaced
|
||||||
if event.name == defines.events.on_built_entity then
|
if event.name == defines.events.on_built_entity then
|
||||||
if event.entity.name ~= "entity-ghost" then
|
if event.entity.name ~= "entity-ghost"
|
||||||
|
and event.entity.name ~= "tile-ghost"
|
||||||
|
and event.entity.name ~= "deconstructible_tile_proxy" then
|
||||||
storage.constructedEntites[event.player_index] = storage.constructedEntites[event.player_index] or {}
|
storage.constructedEntites[event.player_index] = storage.constructedEntites[event.player_index] or {}
|
||||||
storage.constructedEntites[event.player_index][event.entity.name] = (storage.constructedEntites[event.player_index][event.entity.name] or 0) + 1
|
storage.constructedEntites[event.player_index][event.entity.name] = (storage.constructedEntites[event.player_index][event.entity.name] or 0) +
|
||||||
|
1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--Event is RobotPlaced
|
--Event is RobotPlaced
|
||||||
if event.name == defines.events.on_robot_built_entity then
|
if event.name == defines.events.on_robot_built_entity then
|
||||||
if event.entity.name ~= "entity-ghost" then
|
if event.entity.name ~= "entity-ghost"
|
||||||
|
and event.entity.name ~= "tile-ghost"
|
||||||
|
and event.entity.name ~= "deconstructible_tile_proxy" then
|
||||||
if event.entity.last_user then
|
if event.entity.last_user then
|
||||||
local lastUser = event.entity.last_user.index
|
local lastUser = event.entity.last_user.index
|
||||||
storage.constructedEntites[lastUser] = storage.constructedEntites[lastUser] or {}
|
storage.constructedEntites[lastUser] = storage.constructedEntites[lastUser] or {}
|
||||||
storage.constructedEntites[lastUser][event.entity.name] = (storage.constructedEntites[lastUser][event.entity.name] or 0) + 1
|
storage.constructedEntites[lastUser][event.entity.name] = (storage.constructedEntites[lastUser][event.entity.name] or 0) +
|
||||||
|
1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--Event is spaceplatform build
|
--Event is spaceplatform build
|
||||||
if event.name == defines.events.on_space_platform_built_entity then
|
if event.name == defines.events.on_space_platform_built_entity then
|
||||||
if event.entity.name ~= "entity-ghost" then
|
if event.entity.name ~= "entity-ghost"
|
||||||
if event.entity.last_user then
|
and event.entity.name ~= "tile-ghost"
|
||||||
local lastUser = event.entity.last_user.index
|
and event.entity.name ~= "deconstructible_tile_proxy" then
|
||||||
storage.constructedEntites[lastUser] = storage.constructedEntites[lastUser] or {}
|
if event.entity.last_user then
|
||||||
storage.constructedEntites[lastUser][event.entity.name] = (storage.constructedEntites[lastUser][event.entity.name] or 0) + 1
|
local lastUser = event.entity.last_user.index
|
||||||
|
storage.constructedEntites[lastUser] = storage.constructedEntites[lastUser] or {}
|
||||||
|
storage.constructedEntites[lastUser][event.entity.name] = (storage.constructedEntites[lastUser][event.entity.name] or 0) +
|
||||||
|
1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
UpdateStorage(event)
|
UpdateStorage(event)
|
||||||
|
CreateMetricsEntry(event)
|
||||||
end
|
end
|
||||||
|
|
||||||
function RemoveEntity(event)
|
function RemoveEntity(event)
|
||||||
if event.name == defines.events.on_player_mined_entity then
|
if event.name == defines.events.on_player_mined_entity then
|
||||||
storage.deconstructedEntities[event.player_index] = storage.deconstructedEntities[event.player_index] or {}
|
if event.entity.name ~= "entity-ghost"
|
||||||
storage.deconstructedEntities[event.player_index][event.entity.name] = (storage.deconstructedEntities[event.player_index][event.entity.name] or 0) + 1
|
and event.entity.name ~= "tile-ghost"
|
||||||
|
and event.entity.name ~= "deconstructible_tile_proxy" then
|
||||||
|
storage.deconstructedEntities[event.player_index] = storage.deconstructedEntities[event.player_index] or {}
|
||||||
|
storage.deconstructedEntities[event.player_index][event.entity.name] = (storage.deconstructedEntities[event.player_index][event.entity.name] or 0) +
|
||||||
|
1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if event.name == defines.events.on_robot_mined_entity then
|
if event.name == defines.events.on_robot_mined_entity then
|
||||||
if event.entity.name ~= "entity-ghost" then
|
if event.entity.name ~= "entity-ghost"
|
||||||
|
and event.entity.name ~= "tile-ghost"
|
||||||
|
and event.entity.name ~= "deconstructible_tile_proxy" then
|
||||||
if event.entity.last_user then
|
if event.entity.last_user then
|
||||||
local lastUser = event.entity.last_user.index
|
local lastUser = event.entity.last_user.index
|
||||||
storage.deconstructedEntities[lastUser] = storage.deconstructedEntities[lastUser] or {}
|
storage.deconstructedEntities[lastUser] = storage.deconstructedEntities[lastUser] or {}
|
||||||
storage.deconstructedEntities[lastUser][event.entity.name] = (storage.deconstructedEntities[lastUser][event.entity.name] or 0) + 1
|
storage.deconstructedEntities[lastUser][event.entity.name] = (storage.deconstructedEntities[lastUser][event.entity.name] or 0) +
|
||||||
end
|
1
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if event.name == defines.events.on_space_platform_mined_entity then
|
if event.name == defines.events.on_space_platform_mined_entity then
|
||||||
if event.entity.name ~= "entity-ghost" then
|
if event.entity.name ~= "entity-ghost"
|
||||||
|
and event.entity.name ~= "tile-ghost"
|
||||||
|
and event.entity.name ~= "deconstructible_tile_proxy" then
|
||||||
if event.entity.last_user then
|
if event.entity.last_user then
|
||||||
local lastUser = event.entity.last_user.index
|
local lastUser = event.entity.last_user.index
|
||||||
storage.deconstructedEntities[lastUser] = storage.deconstructedEntities[lastUser] or {}
|
storage.deconstructedEntities[lastUser] = storage.deconstructedEntities[lastUser] or {}
|
||||||
storage.deconstructedEntities[lastUser][event.entity.name] = (storage.deconstructedEntities[lastUser][event.entity.name] or 0) + 1
|
storage.deconstructedEntities[lastUser][event.entity.name] = (storage.deconstructedEntities[lastUser][event.entity.name] or 0) +
|
||||||
|
1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if event.name == defines.events.on_entity_died then
|
if event.name == defines.events.on_entity_died then
|
||||||
end
|
end
|
||||||
|
CheckReactor(event)
|
||||||
RemoveStorage(event)
|
RemoveStorage(event)
|
||||||
|
onMetricsCombinatorDied(event)
|
||||||
|
onMetricsCombinatorMined(event)
|
||||||
end
|
end
|
||||||
|
|
||||||
script.on_event(defines.events.on_tick, SendAll)
|
script.on_event(defines.events.on_tick, SendAll)
|
||||||
@@ -373,11 +440,20 @@ script.on_event(defines.events.on_tick, SendAll)
|
|||||||
--script.on_event(defines.events.on_robot_mined_entity,RemoveStorage,{{filter = "type", type = "electric-pole"},{filter ="type", type="lab"},{filter = "type", type="container"}})
|
--script.on_event(defines.events.on_robot_mined_entity,RemoveStorage,{{filter = "type", type = "electric-pole"},{filter ="type", type="lab"},{filter = "type", type="container"}})
|
||||||
--script.on_event(defines.events.on_entity_died,RemoveStorage,{{filter = "type", type = "electric-pole"},{filter ="type", type="lab"},{filter = "type", type="container"}})
|
--script.on_event(defines.events.on_entity_died,RemoveStorage,{{filter = "type", type = "electric-pole"},{filter ="type", type="lab"},{filter = "type", type="container"}})
|
||||||
|
|
||||||
script.on_event(defines.events.on_built_entity,CreateEntity)
|
script.on_event(defines.events.on_built_entity, CreateEntity)
|
||||||
script.on_event(defines.events.on_robot_built_entity,CreateEntity)
|
script.on_event(defines.events.on_robot_built_entity, CreateEntity)
|
||||||
script.on_event(defines.events.on_space_platform_built_entity,CreateEntity)
|
script.on_event(defines.events.on_space_platform_built_entity, CreateEntity)
|
||||||
script.on_event(defines.events.on_player_mined_entity,RemoveEntity)
|
script.on_event(defines.events.on_player_mined_entity, RemoveEntity)
|
||||||
script.on_event(defines.events.on_robot_mined_entity,RemoveEntity)
|
script.on_event(defines.events.on_robot_mined_entity, RemoveEntity)
|
||||||
script.on_event(defines.events.on_space_platform_mined_entity,RemoveEntity)
|
script.on_event(defines.events.on_space_platform_mined_entity, RemoveEntity)
|
||||||
script.on_event(defines.events.on_entity_died,RemoveEntity)
|
script.on_event(defines.events.on_entity_died, RemoveEntity)
|
||||||
script.on_event(defines.events.on_train_changed_state,onTrainStateChange)
|
script.on_event(defines.events.on_train_changed_state, onTrainStateChange)
|
||||||
|
|
||||||
|
script.on_event(defines.events.on_gui_checked_state_changed, onGuiCheckedState)
|
||||||
|
script.on_event(defines.events.on_gui_opened, onGuiOpened)
|
||||||
|
script.on_event(defines.events.on_gui_click, onGuiClick)
|
||||||
|
script.on_event(defines.events.on_gui_closed, onClosedCombinatorGui)
|
||||||
|
script.on_event(defines.events.on_gui_text_changed, onGuiTextChanged)
|
||||||
|
|
||||||
|
script.on_event(defines.events.on_cargo_pod_delivered_cargo, onCargoDelivered)
|
||||||
|
script.on_event(defines.events.on_rocket_launched, onCargoDelivered)
|
||||||
|
|||||||
55
data.lua
55
data.lua
@@ -0,0 +1,55 @@
|
|||||||
|
-- ENTITY
|
||||||
|
local entity = table.deepcopy(data.raw["constant-combinator"]["constant-combinator"])
|
||||||
|
|
||||||
|
entity.name = "metrics-combinator"
|
||||||
|
entity.minable = {
|
||||||
|
mining_time = 0.1,
|
||||||
|
result = "metrics-combinator"
|
||||||
|
}
|
||||||
|
entity.allow_copy_paste = true
|
||||||
|
entity.icon = "__base__/graphics/icons/constant-combinator.png"
|
||||||
|
entity.icon_size = 64
|
||||||
|
--entity.operable = false
|
||||||
|
entity.flags = { "get-by-unit-number", "placeable-neutral", "placeable-player" }
|
||||||
|
|
||||||
|
-- ITEM
|
||||||
|
local item = {
|
||||||
|
type = "item",
|
||||||
|
name = "metrics-combinator",
|
||||||
|
icon = "__base__/graphics/icons/constant-combinator.png",
|
||||||
|
icon_size = 64,
|
||||||
|
subgroup = "circuit-network",
|
||||||
|
order = "c[combinators]-c[metrics-combinator]",
|
||||||
|
place_result = "metrics-combinator",
|
||||||
|
stack_size = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
-- RECIPE (sichtbar von Spielstart)
|
||||||
|
local recipe = {
|
||||||
|
type = "recipe",
|
||||||
|
name = "metrics-combinator",
|
||||||
|
enabled = true,
|
||||||
|
allow_quality = true,
|
||||||
|
|
||||||
|
ingredients = {
|
||||||
|
{
|
||||||
|
type = "item",
|
||||||
|
name = "electronic-circuit",
|
||||||
|
amount = 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
results = {
|
||||||
|
{
|
||||||
|
type = "item",
|
||||||
|
name = "metrics-combinator",
|
||||||
|
amount = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data:extend({
|
||||||
|
entity,
|
||||||
|
item,
|
||||||
|
recipe
|
||||||
|
})
|
||||||
|
|||||||
@@ -2,93 +2,111 @@
|
|||||||
function GetMods()
|
function GetMods()
|
||||||
local mods = script.active_mods
|
local mods = script.active_mods
|
||||||
local modstring = "---mod-info---\n"
|
local modstring = "---mod-info---\n"
|
||||||
for k,v in pairs(mods) do
|
for k, v in pairs(mods) do
|
||||||
modstring = modstring .. ("%s:%s\n"):format(k,v)
|
modstring = modstring .. ("%s:%s\n"):format(k, v)
|
||||||
end
|
end
|
||||||
helpers.send_udp(udpAddress, modstring,serverIndex)
|
helpers.send_udp(udpAddress, modstring, serverIndex)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetPlayerColors()
|
function GetPlayerColors()
|
||||||
local colorParts = {}
|
local colorParts = {}
|
||||||
colorParts[#colorParts+1] = "---player-colors---\n"
|
colorParts[#colorParts + 1] = "---player-colors---\n"
|
||||||
for index, player in pairs(game.players) do
|
for index, player in pairs(game.players) do
|
||||||
local colorSettings = player.color
|
local colorSettings = player.color
|
||||||
colorParts[#colorParts+1] = ("%d:%s:%d:%d:%d:%d"):format(index,player.name,colorSettings.r,colorSettings.g,colorSettings.b,colorSettings.a)
|
colorParts[#colorParts + 1] = ("%d:%s:%d:%d:%d:%d"):format(index, player.name, colorSettings.r, colorSettings.g,
|
||||||
|
colorSettings.b, colorSettings.a)
|
||||||
end
|
end
|
||||||
return table.concat(colorParts,"\n")
|
return table.concat(colorParts, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function GetPlayerKills()
|
function GetPlayerKills()
|
||||||
local killParts = {}
|
local killParts = {}
|
||||||
killParts[#killParts+1] = "---player-kills---\n"
|
killParts[#killParts + 1] = "---player-kills---\n"
|
||||||
for killerIndex, victims in pairs(storage.playerKillCount) do
|
for killerIndex, victims in pairs(storage.playerKillCount) do
|
||||||
for victimIndex, kills in pairs(victims) do
|
for victimIndex, kills in pairs(victims) do
|
||||||
local killerName = game.players[killerIndex].name
|
local killerName = game.players[killerIndex].name
|
||||||
local victimName = game.players[victimIndex].name
|
local victimName = game.players[victimIndex].name
|
||||||
killParts[#killParts+1] = ("%s:%s:%s:%s:%d"):format(killerName,killerIndex,victimName,victimIndex,kills)
|
killParts[#killParts + 1] = ("%s:%s:%s:%s:%d"):format(killerName, killerIndex, victimName, victimIndex, kills)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return table.concat(killParts,"\n")
|
return table.concat(killParts, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetPlayerEntityStats()
|
function GetPlayerEntityStats()
|
||||||
local entityParts = {}
|
local entityParts = {}
|
||||||
entityParts[#entityParts+1] = "---player-build-stats---"
|
entityParts[#entityParts + 1] = "---player-build-stats---"
|
||||||
for playerIndex, items in pairs(storage.constructedEntites) do
|
for playerIndex, items in pairs(storage.constructedEntites) do
|
||||||
local playerName = game.players[playerIndex].name
|
local playerName = game.players[playerIndex].name
|
||||||
for itemName, itemCount in pairs(items) do
|
for itemName, itemCount in pairs(items) do
|
||||||
entityParts[#entityParts+1] = ("%s:%s:constructed:%s:%s"):format(playerIndex,playerName,itemName,itemCount)
|
entityParts[#entityParts + 1] = ("%s:%s:constructed:%s:%s"):format(playerIndex, playerName, itemName, itemCount)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for playerIndex, items in pairs(storage.deconstructedEntities) do
|
for playerIndex, items in pairs(storage.deconstructedEntities) do
|
||||||
local playerName = game.players[playerIndex].name
|
local playerName = game.players[playerIndex].name
|
||||||
for itemName, itemCount in pairs(items) do
|
for itemName, itemCount in pairs(items) do
|
||||||
entityParts[#entityParts+1] = ("%s:%s:deconstructed:%s:%s"):format(playerIndex,playerName,itemName,itemCount)
|
entityParts[#entityParts + 1] = ("%s:%s:deconstructed:%s:%s"):format(playerIndex, playerName, itemName, itemCount)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return table.concat(entityParts,"\n")
|
return table.concat(entityParts, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetMapSeed()
|
function GetMapSeed()
|
||||||
return("---map-seed---\n%d"):format(game.surfaces["nauvis"].map_gen_settings.seed)
|
return ("---map-seed---\n%d"):format(game.surfaces["nauvis"].map_gen_settings.seed)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetRocketsLaunched()
|
function GetRocketsLaunched()
|
||||||
return("---rocket-launches---\n%d"):format(game.forces["player"].rockets_launched)
|
return ("---rocket-launches---\n%d"):format(game.forces["player"].rockets_launched)
|
||||||
end
|
end
|
||||||
|
|
||||||
---Concats all player online times into a single string
|
---Concats all player online times into a single string
|
||||||
---Takes all players that ever visited the server into account
|
---Takes all players that ever visited the server into account
|
||||||
---@return string
|
---@return string
|
||||||
function GetPlayerTime()
|
function GetPlayerTime()
|
||||||
local timeParts = {}
|
local timeParts = {}
|
||||||
timeParts[#timeParts+1] = "---player-times---\n"
|
timeParts[#timeParts + 1] = "---player-times---\n"
|
||||||
for _,player in pairs(game.players) do
|
for _, player in pairs(game.players) do
|
||||||
timeParts[#timeParts+1] = ("%s:%d:%d"):format(player.name, player.index, player.online_time)
|
timeParts[#timeParts + 1] = ("%s:%d:%d"):format(player.name, player.index, player.online_time)
|
||||||
end
|
end
|
||||||
return table.concat(timeParts, "\n")
|
return table.concat(timeParts, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---comment
|
---comment
|
||||||
---@return string
|
---@return string
|
||||||
function GetPlayerDeaths()
|
function GetPlayerDeaths()
|
||||||
local deathParts = {}
|
local deathParts = {}
|
||||||
deathParts[#deathParts+1] = "---player-deaths---\n"
|
deathParts[#deathParts + 1] = "---player-deaths---\n"
|
||||||
for _,player in pairs(game.players) do
|
for _, player in pairs(game.players) do
|
||||||
deathParts[#deathParts+1] = ("%s:%d:%d"):format(player.name, player.index, storage.playerDeathCount[player.index]or 0)
|
deathParts[#deathParts + 1] = ("%s:%d:%d"):format(player.name, player.index,
|
||||||
end
|
storage.playerDeathCount[player.index] or 0)
|
||||||
return table.concat(deathParts, "\n")
|
end
|
||||||
|
return table.concat(deathParts, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetPlayerDeathCauses()
|
function GetPlayerDeathCauses()
|
||||||
local deathParts = {}
|
local deathParts = {}
|
||||||
deathParts[#deathParts+1] = "---player-death-cause---\n"
|
deathParts[#deathParts + 1] = "---player-death-cause---\n"
|
||||||
for playerIndex,deathCauses in pairs(storage.playerDeathCause) do
|
for playerIndex, deathCauses in pairs(storage.playerDeathCause) do
|
||||||
for causeName, causeCount in pairs(deathCauses) do
|
for causeName, causeCount in pairs(deathCauses) do
|
||||||
deathParts[#deathParts+1] = ("%s:%d:%s:%d"):format(game.players[playerIndex].name,playerIndex,causeName,causeCount)
|
deathParts[#deathParts + 1] = ("%s:%d:%s:%d"):format(game.players[playerIndex].name, playerIndex, causeName,
|
||||||
|
causeCount)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return table.concat(deathParts,"\n")
|
return table.concat(deathParts, "\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
function GetTotalPlayTime()
|
||||||
|
return ("---game-time---\n%d:%d"):format(game.tick, game.ticks_played)
|
||||||
|
end
|
||||||
|
|
||||||
|
function CheckReactor(event)
|
||||||
|
if not event and not event.entity then return end
|
||||||
|
if event.entity.name == "nuclear-reactor" then
|
||||||
|
if event.entity.temperature >= 900 then
|
||||||
|
storage.nuclearReactorDeaths = (storage.nuclearReactorDeaths or 0) + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function GetReactorExplosions()
|
||||||
|
return "---reactor-explosion---\n" .. (storage.nuclearReactorDeaths or 0)
|
||||||
end
|
end
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "factorio-metrics-exporter",
|
"name": "factorio-metrics-exporter",
|
||||||
"version": "0.2.6",
|
"version": "0.3.0",
|
||||||
"title": "Prometheus Metrics Exporter",
|
"title": "Prometheus Metrics Exporter",
|
||||||
"author": "Jan Grießhaber",
|
"author": "Jan Grießhaber",
|
||||||
"contact": "jan@griesshaber.systems",
|
"contact": "jan@griesshaber.systems",
|
||||||
|
|||||||
175
metrics-combinator.lua
Normal file
175
metrics-combinator.lua
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
local function getMetricsStorageData(entity)
|
||||||
|
local unit = entity.unit_number
|
||||||
|
storage.metrics[unit] = storage.metrics[unit] or {
|
||||||
|
name = "",
|
||||||
|
enabled = false,
|
||||||
|
}
|
||||||
|
return storage.metrics[unit]
|
||||||
|
end
|
||||||
|
|
||||||
|
function CreateMetricsEntry(event)
|
||||||
|
if event.entity.name == "metrics-combinator"
|
||||||
|
and event.entity.valid then
|
||||||
|
---@type LuaEntity
|
||||||
|
local entity = event.entity
|
||||||
|
storage.metrics[entity.unit_number] = storage.metrics[entity.unit_number] or {
|
||||||
|
name = "",
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function open_metrics_gui(player, entity)
|
||||||
|
if player.gui.screen.metrics_frame then
|
||||||
|
player.gui.screen.metrics_frame.destroy()
|
||||||
|
end
|
||||||
|
|
||||||
|
local frame = player.gui.screen.add {
|
||||||
|
type = "frame",
|
||||||
|
name = "metrics_frame",
|
||||||
|
direction = "vertical"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Titelzeile mit Close-Button
|
||||||
|
local titlebar = frame.add {
|
||||||
|
type = "flow",
|
||||||
|
direction = "horizontal"
|
||||||
|
}
|
||||||
|
|
||||||
|
titlebar.drag_target = frame
|
||||||
|
|
||||||
|
titlebar.add {
|
||||||
|
type = "label",
|
||||||
|
caption = "Metrics Combinator",
|
||||||
|
style = "frame_title"
|
||||||
|
}
|
||||||
|
|
||||||
|
local spacer = titlebar.add {
|
||||||
|
type = "empty-widget",
|
||||||
|
style = "draggable_space_header",
|
||||||
|
}
|
||||||
|
spacer.style.horizontally_stretchable = true
|
||||||
|
spacer.drag_target = frame
|
||||||
|
|
||||||
|
titlebar.add {
|
||||||
|
type = "sprite-button",
|
||||||
|
name = "metrics_close",
|
||||||
|
sprite = "utility/close",
|
||||||
|
style = "frame_action_button"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Inhalt
|
||||||
|
frame.add {
|
||||||
|
type = "textfield",
|
||||||
|
name = "metrics_name",
|
||||||
|
text = storage.metrics[entity.unit_number].name
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.add {
|
||||||
|
type = "checkbox",
|
||||||
|
name = "metrics_enabled",
|
||||||
|
caption = "Enabled",
|
||||||
|
state = storage.metrics[entity.unit_number].enabled
|
||||||
|
}
|
||||||
|
|
||||||
|
frame.force_auto_center()
|
||||||
|
frame.tags = { entity_unit_number = entity.unit_number }
|
||||||
|
player.opened = frame
|
||||||
|
end
|
||||||
|
|
||||||
|
function onGuiClick(event)
|
||||||
|
if event.element.name ~= "metrics_close" then return end
|
||||||
|
|
||||||
|
local player = game.get_player(event.player_index)
|
||||||
|
if not player then return end
|
||||||
|
if player.gui.screen.metrics_frame then
|
||||||
|
player.gui.screen.metrics_frame.destroy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function onGuiOpened(event)
|
||||||
|
if event.gui_type ~= defines.gui_type.entity then return end
|
||||||
|
if not (event.entity and event.entity.valid and event.entity.name == "metrics-combinator") then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local player = game.get_player(event.player_index)
|
||||||
|
|
||||||
|
-- SCHLÜSSELZEILE: Engine-GUI sofort schließen
|
||||||
|
player.opened = nil
|
||||||
|
|
||||||
|
open_metrics_gui(player, event.entity)
|
||||||
|
end
|
||||||
|
|
||||||
|
function onClosedCombinatorGui(event)
|
||||||
|
if event.element and event.element.name == "metrics_frame" then
|
||||||
|
event.element.destroy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function onGuiTextChanged(event)
|
||||||
|
if event.element.name ~= "metrics_name" then return end
|
||||||
|
|
||||||
|
local player = game.get_player(event.player_index)
|
||||||
|
if not player then return end
|
||||||
|
local entity = player.opened
|
||||||
|
if not (entity and entity.valid) then return end
|
||||||
|
|
||||||
|
local data = getMetricsStorageData(game.get_entity_by_unit_number(entity.tags.entity_unit_number))
|
||||||
|
data.name = event.text
|
||||||
|
end
|
||||||
|
|
||||||
|
function onGuiCheckedState(event)
|
||||||
|
if event.element.name ~= "metrics_enabled" then return end
|
||||||
|
|
||||||
|
local player = game.get_player(event.player_index)
|
||||||
|
if not player then return end
|
||||||
|
local frame = player.opened
|
||||||
|
if not (frame and frame.valid) then return end
|
||||||
|
|
||||||
|
|
||||||
|
local data = getMetricsStorageData(game.get_entity_by_unit_number(frame.tags.entity_unit_number))
|
||||||
|
data.enabled = event.element.state
|
||||||
|
|
||||||
|
-- optional: echtes Abschalten
|
||||||
|
--frame.active = data.enabled
|
||||||
|
end
|
||||||
|
|
||||||
|
function onMetricsCombinatorDied(event)
|
||||||
|
if event.entity.name ~= "metrics-combinator" then return end
|
||||||
|
storage.metrics[event.entity.unit_number] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function onMetricsCombinatorMined(event)
|
||||||
|
if event.entity.name ~= "metrics-combinator" then return end
|
||||||
|
storage.metrics[event.entity.unit_number] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function SendCombinatorMetrics()
|
||||||
|
local netParts = {}
|
||||||
|
netParts[#netParts + 1] = "---circuit-stats---\n"
|
||||||
|
for unitNumber, combinatorFlags in pairs(storage.metrics) do
|
||||||
|
if combinatorFlags.enabled then
|
||||||
|
local entity = game.get_entity_by_unit_number(unitNumber)
|
||||||
|
if entity and entity.valid then
|
||||||
|
---@type LuaCircuitNetwork?
|
||||||
|
local redNet = entity.get_circuit_network(defines.wire_connector_id.circuit_red)
|
||||||
|
---@type LuaCircuitNetwork?
|
||||||
|
local greenNet = entity.get_circuit_network(defines.wire_connector_id.circuit_green)
|
||||||
|
if redNet then
|
||||||
|
for _, signal in pairs(redNet.signals) do
|
||||||
|
netParts[#netParts + 1] = ("%s:red:%s:%d"):format(combinatorFlags.name,
|
||||||
|
signal.signal.name .. signal.signal.quality.name, signal.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if greenNet then
|
||||||
|
for _, signal in pairs(greenNet.signals) do
|
||||||
|
netParts[#netParts + 1] = ("%s:green:%s:%d"):format(combinatorFlags.name,
|
||||||
|
signal.signal.name .. signal.signal.quality.name, signal.count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
helpers.send_udp(udpAddress, table.concat(netParts, "\n"), serverIndex)
|
||||||
|
end
|
||||||
@@ -1,53 +1,66 @@
|
|||||||
function SendPollutionStats()
|
function SendPollutionStats()
|
||||||
if options.enablePollution then
|
if options.enablePollution then
|
||||||
local pollutionParts = {}
|
local pollutionParts = {}
|
||||||
pollutionParts[#pollutionParts+1] = "---pollution-stats---\n"
|
pollutionParts[#pollutionParts + 1] = "---pollution-stats---\n"
|
||||||
for _,surface in pairs(game.surfaces) do
|
for _, surface in pairs(game.surfaces) do
|
||||||
local surface_name = surface.name
|
local surface_name = surface.name
|
||||||
|
|
||||||
local pollution_input = game.surfaces[surface_name].pollution_statistics.input_counts
|
local pollution_input = game.surfaces[surface_name].pollution_statistics.input_counts
|
||||||
local pollution_output = game.surfaces[surface_name].pollution_statistics.output_counts
|
local pollution_output = game.surfaces[surface_name].pollution_statistics.output_counts
|
||||||
|
|
||||||
if surface.platform ~= nil then
|
if surface.platform ~= nil then
|
||||||
surface_name = surface.platform.name
|
surface_name = surface.platform.name
|
||||||
|
end
|
||||||
|
|
||||||
|
for name, stat in pairs(pollution_input) do
|
||||||
|
pollutionParts[#pollutionParts + 1] = ("%s:in:%s:%d"):format(surface_name, name, stat)
|
||||||
|
end
|
||||||
|
|
||||||
|
for name, stat in pairs(pollution_output) do
|
||||||
|
pollutionParts[#pollutionParts + 1] = ("%s:out:%s:%d"):format(surface_name, name, stat)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
helpers.send_udp(udpAddress, table.concat(pollutionParts, "\n"), serverIndex)
|
||||||
for name, stat in pairs(pollution_input) do
|
|
||||||
pollutionParts[#pollutionParts+1] = ("%s:in:%s:%d"):format(surface_name,name, stat)
|
|
||||||
end
|
|
||||||
|
|
||||||
for name, stat in pairs(pollution_output) do
|
|
||||||
pollutionParts[#pollutionParts+1] = ("%s:out:%s:%d"):format(surface_name,name, stat)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
helpers.send_udp(udpAddress, table.concat(pollutionParts,"\n"),serverIndex)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function SendKillStats()
|
function SendKillStats()
|
||||||
if options.enableKills then
|
if options.enableKills then
|
||||||
local killParts = {}
|
local killParts = {}
|
||||||
killParts[#killParts+1] = "---kill-stats---\n"
|
killParts[#killParts + 1] = "---kill-stats---\n"
|
||||||
for _,surface in pairs(game.surfaces) do
|
for _, surface in pairs(game.surfaces) do
|
||||||
local surface_name = surface.name
|
local surface_name = surface.name
|
||||||
|
|
||||||
local kill_input = game.forces["player"].get_kill_count_statistics(surface_name).input_counts
|
local kill_input = game.forces["player"].get_kill_count_statistics(surface_name).input_counts
|
||||||
local kill_output = game.forces["player"].get_kill_count_statistics(surface_name).output_counts
|
local kill_output = game.forces["player"].get_kill_count_statistics(surface_name).output_counts
|
||||||
|
|
||||||
if surface.platform ~= nil then
|
if surface.platform ~= nil then
|
||||||
surface_name = surface.platform.name
|
surface_name = surface.platform.name
|
||||||
|
end
|
||||||
|
|
||||||
|
for name, stat in pairs(kill_input) do
|
||||||
|
killParts[#killParts + 1] = ("%s:in:%s:%d"):format(surface_name, name, stat)
|
||||||
|
end
|
||||||
|
|
||||||
|
for name, stat in pairs(kill_output) do
|
||||||
|
killParts[#killParts + 1] = ("%s:out:%s:%d"):format(surface_name, name, stat)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
helpers.send_udp(udpAddress, table.concat(killParts, "\n"), serverIndex)
|
||||||
for name, stat in pairs(kill_input) do
|
|
||||||
killParts[#killParts+1] = ("%s:in:%s:%d"):format(surface_name,name, stat)
|
|
||||||
end
|
|
||||||
|
|
||||||
for name, stat in pairs(kill_output) do
|
|
||||||
killParts[#killParts+1] = ("%s:out:%s:%d"):format(surface_name,name, stat)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
helpers.send_udp(udpAddress, table.concat(killParts,"\n"),serverIndex)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function GetEvolution()
|
||||||
|
local evolutionParts = {}
|
||||||
|
local playerForce = game.forces["player"]
|
||||||
|
evolutionParts[#evolutionParts + 1] = "---evolution-stats---\n"
|
||||||
|
for _, surface in pairs(game.surfaces) do
|
||||||
|
evolutionParts[#evolutionParts + 1] = ("%s:%d:%d:%d:%d"):format(
|
||||||
|
surface.name,
|
||||||
|
playerForce.get_evolution_factor(surface),
|
||||||
|
playerForce.get_evolution_factor_by_pollution(surface),
|
||||||
|
playerForce.get_evolution_factor_by_time(surface),
|
||||||
|
playerForce.get_evolution_factor_by_killing_spawners(surface))
|
||||||
|
end
|
||||||
|
return table.concat(evolutionParts, "\n")
|
||||||
end
|
end
|
||||||
134
power-stats.lua
134
power-stats.lua
@@ -41,7 +41,7 @@ function ScanNetworks()
|
|||||||
storage.networkCache = {}
|
storage.networkCache = {}
|
||||||
|
|
||||||
for _, surface in pairs(game.surfaces) do
|
for _, surface in pairs(game.surfaces) do
|
||||||
for _, pole in pairs(surface.find_entities_filtered{type = "electric-pole"}) do
|
for _, pole in pairs(surface.find_entities_filtered { type = "electric-pole" }) do
|
||||||
if pole.valid and pole.electric_network_id then
|
if pole.valid and pole.electric_network_id then
|
||||||
storage.representativePoles[pole.unit_number] = pole
|
storage.representativePoles[pole.unit_number] = pole
|
||||||
storage.networkCache[pole.electric_network_id] = pole
|
storage.networkCache[pole.electric_network_id] = pole
|
||||||
@@ -50,25 +50,143 @@ function ScanNetworks()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
solarBase = 60
|
||||||
|
steamBase = 900
|
||||||
|
turbineBase = 5820
|
||||||
|
fusionBase = 50000
|
||||||
|
|
||||||
|
|
||||||
|
function AddGenerator(event)
|
||||||
|
if event then
|
||||||
|
if event.entity then
|
||||||
|
---@type LuaEntity
|
||||||
|
local entity = event.entity
|
||||||
|
if entity.type == "solar-panel" then
|
||||||
|
storage.powerStats["solar"][entity.surface.name] = (storage.powerStats["solar"][entity.surface.name] or 0) +
|
||||||
|
(solarBase * entity.quality.default_multiplier * entity.surface.solar_power_multiplier)
|
||||||
|
end
|
||||||
|
if entity.type == "fusion-generator" then
|
||||||
|
storage.powerStats["fusion"][entity.surface.name] = (storage.powerStats["fusion"][entity.surface.name] or 0) +
|
||||||
|
(fusionBase * entity.quality.default_multiplier)
|
||||||
|
end
|
||||||
|
if entity.name == "steam-engine" then
|
||||||
|
storage.powerStats["steam"][entity.surface.name] = (storage.powerStats["steam"][entity.surface.name] or 0) +
|
||||||
|
(steamBase * entity.quality.default_multiplier)
|
||||||
|
end
|
||||||
|
if entity.name == "steam-turbine" then
|
||||||
|
storage.powerStats["turbine"][entity.surface.name] = (storage.powerStats["turbine"][entity.surface.name] or 0) +
|
||||||
|
(turbineBase * entity.quality.default_multiplier)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function RemoveGenerator(event)
|
||||||
|
if event then
|
||||||
|
if event.entity then
|
||||||
|
---@type LuaEntity
|
||||||
|
local entity = event.entity
|
||||||
|
if entity.type == "solar-panel" then
|
||||||
|
storage.powerStats["solar"][entity.surface.name] = (storage.powerStats["solar"][entity.surface.name] or 0) -
|
||||||
|
(solarBase * entity.quality.default_multiplier * entity.surface.solar_power_multiplier)
|
||||||
|
end
|
||||||
|
if entity.type == "fusion-generator" then
|
||||||
|
storage.powerStats["fusion"][entity.surface.name] = (storage.powerStats["fusion"][entity.surface.name] or 0) -
|
||||||
|
(fusionBase * entity.quality.default_multiplier)
|
||||||
|
end
|
||||||
|
if entity.name == "steam-engine" then
|
||||||
|
storage.powerStats["steam"][entity.surface.name] = (storage.powerStats["steam"][entity.surface.name] or 0) -
|
||||||
|
(steamBase * entity.quality.default_multiplier)
|
||||||
|
end
|
||||||
|
if entity.name == "steam-turbine" then
|
||||||
|
storage.powerStats["turbine"][entity.surface.name] = (storage.powerStats["turbine"][entity.surface.name] or 0) -
|
||||||
|
(turbineBase * entity.quality.default_multiplier)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function ScanGenerators()
|
||||||
|
storage.powerGenerators = {}
|
||||||
|
for _, surface in pairs(game.surfaces) do
|
||||||
|
for _, generator in pairs(surface.find_entities_filtered({ filter = type, type = { "generator", "fusion-generator", "solar-panel" } })) do
|
||||||
|
storage.powerGenerators[generator.unit_number] = generator
|
||||||
|
end
|
||||||
|
end
|
||||||
|
PopulateStats()
|
||||||
|
end
|
||||||
|
|
||||||
|
function PopulateStats()
|
||||||
|
local solar = {}
|
||||||
|
local steam = {}
|
||||||
|
local turbine = {}
|
||||||
|
local fusion = {}
|
||||||
|
|
||||||
|
for _, generator in pairs(storage.powerGenerators) do
|
||||||
|
local surface = generator.surface
|
||||||
|
if generator.type == "solar-panel" then
|
||||||
|
local surfaceSolarFactor = surface.solar_power_multiplier
|
||||||
|
solar[surface.name] = (solar[surface.name] or 0) +
|
||||||
|
(solarBase * generator.quality.default_multiplier * surfaceSolarFactor)
|
||||||
|
end
|
||||||
|
if generator.type == "fusion-generator" then
|
||||||
|
fusion[surface.name] = (fusion[surface.name] or 0) + (fusionBase * generator.quality.default_multiplier)
|
||||||
|
end
|
||||||
|
if generator.name == "steam-engine" then
|
||||||
|
steam[surface.name] = (steam[surface.name] or 0) + (steamBase * generator.quality.default_multiplier)
|
||||||
|
end
|
||||||
|
if generator.name == "steam-turbine" then
|
||||||
|
turbine[surface.name] = (turbine[surface.name] or 0) + (turbineBase * generator.quality.default_multiplier)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
storage.powerStats["solar"] = solar
|
||||||
|
storage.powerStats["steam"] = steam
|
||||||
|
storage.powerStats["turbine"] = turbine
|
||||||
|
storage.powerStats["fusion"] = fusion
|
||||||
|
end
|
||||||
|
|
||||||
|
function GetPossiblePower()
|
||||||
|
local result = {}
|
||||||
|
result[#result + 1] = "---max-power---\n"
|
||||||
|
for _, surface in pairs(game.surfaces) do
|
||||||
|
result[#result + 1] = ("%s:%d:%d:%d:%d"):format(
|
||||||
|
surface.name,
|
||||||
|
storage.powerStats["solar"][surface.name] or 0,
|
||||||
|
storage.powerStats["steam"][surface.name] or 0,
|
||||||
|
storage.powerStats["turbine"][surface.name] or 0,
|
||||||
|
storage.powerStats["fusion"][surface.name] or 0
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return table.concat(result, "\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function SendPowerStats()
|
function SendPowerStats()
|
||||||
if options.enablePower then
|
if options.enablePower then
|
||||||
|
local possiblePower = GetPossiblePower()
|
||||||
local powerPart = {}
|
local powerPart = {}
|
||||||
powerPart[#powerPart+1] = "---power-stats---\n"
|
powerPart[#powerPart + 1] = "---power-stats---\n"
|
||||||
for _, pole in pairs(GetNetworks()) do
|
for _, pole in pairs(GetNetworks()) do
|
||||||
if pole.valid and pole.type == "electric-pole" then
|
if pole.valid and pole.type == "electric-pole" then
|
||||||
local input = pole.electric_network_statistics.input_counts
|
local input = pole.electric_network_statistics.input_counts
|
||||||
local output = pole.electric_network_statistics.output_counts
|
local output = pole.electric_network_statistics.output_counts
|
||||||
|
local capacity = pole.electric_network_statistics.storage_counts
|
||||||
local surfaceName = pole.surface.name
|
local surfaceName = pole.surface.name
|
||||||
for item,value in pairs(input) do
|
for item, value in pairs(input) do
|
||||||
powerPart[#powerPart+1] = ("%s:%d:in:%s:%d"):format(surfaceName, pole.electric_network_id, item, value)
|
powerPart[#powerPart + 1] = ("%s:%d:in:%s:%d"):format(surfaceName, pole.electric_network_id, item,
|
||||||
|
value)
|
||||||
end
|
end
|
||||||
for item, value in pairs(output) do
|
for item, value in pairs(output) do
|
||||||
powerPart[#powerPart+1] = ("%s:%d:out:%s:%d"):format(surfaceName,pole.electric_network_id, item, value)
|
powerPart[#powerPart + 1] = ("%s:%d:out:%s:%d"):format(surfaceName, pole.electric_network_id, item,
|
||||||
|
value)
|
||||||
|
end
|
||||||
|
for item, value in pairs(capacity) do
|
||||||
|
powerPart[#powerPart + 1] = ("%s:%d:capacity:%s:%d"):format(surfaceName, pole.electric_network_id,
|
||||||
|
item, value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
helpers.send_udp(udpAddress,table.concat(powerPart,"\n"),serverIndex)
|
powerPart[#powerPart + 1] = possiblePower
|
||||||
|
helpers.send_udp(udpAddress, table.concat(powerPart, "\n"), serverIndex)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,27 @@
|
|||||||
|
protos = {}
|
||||||
|
--Experimental function, not in use right now
|
||||||
|
function GetProductionWithQuality(surface)
|
||||||
|
|
||||||
|
log("StartQualProd"..surface.name)
|
||||||
|
local prodWithQualityParts = {}
|
||||||
|
local prodstat = game.forces["player"].get_item_production_statistics(surface)
|
||||||
|
for key, _ in pairs(prodstat.input_counts) do
|
||||||
|
for quality,_ in pairs(prototypes.quality) do
|
||||||
|
local count = prodstat.get_input_count({name=key,quality=quality})
|
||||||
|
if count > 0 then
|
||||||
|
prodWithQualityParts[#prodWithQualityParts+1] =
|
||||||
|
surface.name..":"..
|
||||||
|
key..":"..
|
||||||
|
quality..":"..
|
||||||
|
count
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
log("EndQualProd"..surface.name)
|
||||||
|
return table.concat(prodWithQualityParts,"\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function SendProductionStats()
|
function SendProductionStats()
|
||||||
if options.enableProduction then
|
if options.enableProduction then
|
||||||
local productionParts = {}
|
local productionParts = {}
|
||||||
@@ -5,6 +29,9 @@ function SendProductionStats()
|
|||||||
for _,surface in pairs(game.surfaces) do
|
for _,surface in pairs(game.surfaces) do
|
||||||
local surfaceName = surface.name
|
local surfaceName = surface.name
|
||||||
|
|
||||||
|
--TODO
|
||||||
|
--local test = GetProductionWithQuality(surface)
|
||||||
|
|
||||||
local inputStats = game.forces["player"].get_item_production_statistics(surfaceName).input_counts
|
local inputStats = game.forces["player"].get_item_production_statistics(surfaceName).input_counts
|
||||||
local outputStats = game.forces["player"].get_item_production_statistics(surfaceName).output_counts
|
local outputStats = game.forces["player"].get_item_production_statistics(surfaceName).output_counts
|
||||||
|
|
||||||
@@ -81,3 +108,12 @@ function SendBuildStats()
|
|||||||
helpers.send_udp(udpAddress, table.concat(buildParts, "\n"), serverIndex)
|
helpers.send_udp(udpAddress, table.concat(buildParts, "\n"), serverIndex)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function GetAllPrototypes()
|
||||||
|
for ID, _ in pairs(prototypes.item) do
|
||||||
|
for quality,_ in pairs(prototypes.quality) do
|
||||||
|
protos[#protos+1] = {name=ID,quality=quality}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ function ScanLabs()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function UpdateLabs(event)
|
function UpdateLabs(event)
|
||||||
local lab = event.entity
|
local lab = event.entity
|
||||||
if lab and lab.valid then
|
if lab and lab.valid then
|
||||||
@@ -28,8 +26,6 @@ function RemoveLab(event)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function GetEstimatedResearchTime()
|
function GetEstimatedResearchTime()
|
||||||
-- Base time in seconds for research
|
-- Base time in seconds for research
|
||||||
local playerForce = game.forces["player"]
|
local playerForce = game.forces["player"]
|
||||||
@@ -40,7 +36,8 @@ function GetEstimatedResearchTime()
|
|||||||
local researchName = currentResearch.name.."-"..currentResearch.level
|
local researchName = currentResearch.name.."-"..currentResearch.level
|
||||||
local researchTotalCost = currentResearch.research_unit_count * (currentResearch.research_unit_energy/60)
|
local researchTotalCost = currentResearch.research_unit_count * (currentResearch.research_unit_energy/60)
|
||||||
|
|
||||||
local totalSpeed = storage.totalResearchSpeed
|
--local totalSpeed = storage.totalResearchSpeed
|
||||||
|
local totalSpeed = GetCurrentResearchSpeed()
|
||||||
|
|
||||||
local remainingPercentage = 1-math.min(playerForce.research_progress,1)
|
local remainingPercentage = 1-math.min(playerForce.research_progress,1)
|
||||||
local remainingUnits = remainingPercentage*researchTotalCost
|
local remainingUnits = remainingPercentage*researchTotalCost
|
||||||
@@ -81,9 +78,18 @@ function UpdateLabInfos()
|
|||||||
storage.totalResearchSpeed = totalSpeed
|
storage.totalResearchSpeed = totalSpeed
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function GetCurrentResearchSpeed()
|
||||||
|
local totalResearch = 0
|
||||||
|
local playerForce = game.forces["player"]
|
||||||
|
if not playerForce then return end
|
||||||
|
for _,surface in pairs(game.surfaces) do
|
||||||
|
totalResearch = totalResearch + playerForce.get_item_production_statistics(surface).get_flow_count({name = "science", category = "input",precision_index = defines.flow_precision_index.five_seconds})
|
||||||
|
end
|
||||||
|
return totalResearch
|
||||||
|
end
|
||||||
|
|
||||||
function SendResearchStats()
|
function SendResearchStats()
|
||||||
if options.enableResearch == true then
|
if options.enableResearch == true then
|
||||||
UpdateLabInfos()
|
|
||||||
local researchTimeInfo = GetEstimatedResearchTime()
|
local researchTimeInfo = GetEstimatedResearchTime()
|
||||||
if researchTimeInfo then
|
if researchTimeInfo then
|
||||||
helpers.send_udp(udpAddress, researchTimeInfo, serverIndex)
|
helpers.send_udp(udpAddress, researchTimeInfo, serverIndex)
|
||||||
|
|||||||
225
train-stats.lua
225
train-stats.lua
@@ -1,6 +1,6 @@
|
|||||||
function ScanTrains()
|
function ScanTrains()
|
||||||
storage.trains = {}
|
storage.trains = {}
|
||||||
for _,train in pairs(game.train_manager.get_trains({})) do
|
for _, train in pairs(game.train_manager.get_trains({})) do
|
||||||
storage.trains[train.id] = train
|
storage.trains[train.id] = train
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -12,7 +12,7 @@ function GetTrainName(train)
|
|||||||
return train.locomotives.front_movers[1].backer_name or ""
|
return train.locomotives.front_movers[1].backer_name or ""
|
||||||
elseif train.locomotives.back_movers[1] then
|
elseif train.locomotives.back_movers[1] then
|
||||||
return train.locomotives.back_movers[1].backer_name or ""
|
return train.locomotives.back_movers[1].backer_name or ""
|
||||||
end
|
end
|
||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -20,70 +20,94 @@ function GetTrainsInDepot()
|
|||||||
local trainsInDepot = 0
|
local trainsInDepot = 0
|
||||||
for trainsID, train in pairs(storage.trains) do
|
for trainsID, train in pairs(storage.trains) do
|
||||||
if train.state == defines.train_state.wait_station
|
if train.state == defines.train_state.wait_station
|
||||||
and train.station and train.station.backer_name == autotrainDepotName then
|
and train.station and train.station.backer_name == autotrainDepotName then
|
||||||
trainsInDepot = trainsInDepot + 1
|
trainsInDepot = trainsInDepot + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local trainsInGroup = #game.train_manager.get_trains({group=autotrainGroupName})
|
local trainsInGroup = #game.train_manager.get_trains({ group = autotrainGroupName })
|
||||||
return ("---autotrain-stats---\n%d:%d"):format(trainsInDepot,trainsInGroup)
|
return ("---autotrain-stats---\n%d:%d"):format(trainsInDepot, trainsInGroup)
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetTrainPlayerKills()
|
function GetTrainPlayerKills()
|
||||||
local trainKills = {}
|
local trainKills = {}
|
||||||
trainKills[#trainKills+1] = "---train-player-kills---"
|
trainKills[#trainKills + 1] = "---train-player-kills---"
|
||||||
---@type LuaTrain
|
---@type LuaTrain
|
||||||
for _, train in pairs(storage.trains ) do
|
for _, train in pairs(storage.trains) do
|
||||||
for killedPlayerID,killedPlayerCount in pairs(train.killed_players) 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)
|
trainKills[#trainKills + 1] = ("%s:%s:%s:%s:%d"):format(train.id, GetTrainName(train), killedPlayerID,
|
||||||
|
game.players[killedPlayerID].name, killedPlayerCount)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return table.concat(trainKills,"\n")
|
return table.concat(trainKills, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function GetTrainTotalKills()
|
function GetTrainTotalKills()
|
||||||
local trainKills = {}
|
local trainKills = {}
|
||||||
trainKills[#trainKills+1] = "---train-total-kills---"
|
trainKills[#trainKills + 1] = "---train-total-kills---"
|
||||||
---@type LuaTrain
|
---@type LuaTrain
|
||||||
for _, train in pairs(storage.trains) do
|
for _, train in pairs(storage.trains) do
|
||||||
trainKills[#trainKills+1] = ("%s:%s:%d"):format(train.id,GetTrainName(train),train.kill_count)
|
trainKills[#trainKills + 1] = ("%s:%s:%d"):format(train.id, GetTrainName(train), train.kill_count)
|
||||||
end
|
end
|
||||||
return table.concat(trainKills,"\n")
|
return table.concat(trainKills, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--TODO: Seperate by surface
|
||||||
function GetTrainStates()
|
function GetTrainStates()
|
||||||
local trainsDriving = 0
|
local trainsWaiting = {}
|
||||||
local trainsWaiting = 0
|
local trainsDriving = {}
|
||||||
local trainsProblems = 0
|
local trainsManual = {}
|
||||||
local trainsManual = 0
|
local trainsProblems = {}
|
||||||
for _, train in pairs(storage.trains) do
|
for _, train in pairs(storage.trains) do
|
||||||
if train.state == defines.train_state.wait_station
|
local surfaceName
|
||||||
or train.state == defines.train_state.destination_full
|
if train.locomotives then
|
||||||
or train.state == defines.train_state.no_schedule
|
if train.locomotives.front_movers[1] then
|
||||||
then trainsWaiting = trainsWaiting + 1
|
surfaceName = train.locomotives.front_movers[1].surface.name
|
||||||
|
end
|
||||||
elseif train.state == defines.train_state.on_the_path
|
elseif train.locomotives.back_movers[1] then
|
||||||
or train.state == defines.train_state.arrive_signal
|
surfaceName = train.locomotives.back_movers[1].surface.name
|
||||||
or train.state == defines.train_state.arrive_station
|
end
|
||||||
or train.state == defines.train_state.wait_signal
|
if surfaceName then
|
||||||
then trainsDriving = trainsDriving + 1
|
if train.state == defines.train_state.wait_station
|
||||||
|
or train.state == defines.train_state.destination_full
|
||||||
elseif train.state == defines.train_state.manual_control
|
or train.state == defines.train_state.no_schedule
|
||||||
or train.state == defines.train_state.manual_control_stop
|
then
|
||||||
then trainsManual = trainsManual + 1
|
trainsWaiting[surfaceName] = (trainsWaiting[surfaceName] or 0) + 1
|
||||||
|
elseif train.state == defines.train_state.on_the_path
|
||||||
elseif train.state == defines.train_state.no_path
|
or train.state == defines.train_state.arrive_signal
|
||||||
then trainsProblems = trainsProblems + 1 end
|
or train.state == defines.train_state.arrive_station
|
||||||
|
or train.state == defines.train_state.wait_signal
|
||||||
|
then
|
||||||
|
trainsDriving[surfaceName] = (trainsDriving[surfaceName] or 0) + 1
|
||||||
|
elseif train.state == defines.train_state.manual_control
|
||||||
|
or train.state == defines.train_state.manual_control_stop
|
||||||
|
then
|
||||||
|
trainsManual[surfaceName] = (trainsManual[surfaceName] or 0) + 1
|
||||||
|
elseif train.state == defines.train_state.no_path
|
||||||
|
then
|
||||||
|
trainsProblems[surfaceName] = (trainsProblems[surfaceName] or 0) + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return ("---trains-states---\n%d:%d:%d:%d"):format(trainsDriving,trainsManual,trainsProblems,trainsWaiting)
|
local stateParts = {}
|
||||||
|
stateParts[#stateParts + 1] = "---trains-states---\n"
|
||||||
|
for _, surface in pairs(game.surfaces) do
|
||||||
|
local surfaceName = surface.name
|
||||||
|
stateParts[#stateParts + 1] = ("%s:%d:%d:%d:%d"):format(
|
||||||
|
surfaceName,
|
||||||
|
trainsDriving[surfaceName] or 0,
|
||||||
|
trainsManual[surfaceName] or 0,
|
||||||
|
trainsProblems[surfaceName] or 0,
|
||||||
|
trainsWaiting[surfaceName] or 0)
|
||||||
|
end
|
||||||
|
return table.concat(stateParts, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
---@class trainStat
|
---@class trainStat
|
||||||
trainStat = {
|
trainStat = {
|
||||||
trainID = 0,
|
trainID = 0,
|
||||||
trainName = "",
|
trainName = "",
|
||||||
lastInventory={},
|
lastInventory = {},
|
||||||
currentInventory={},
|
currentInventory = {},
|
||||||
lastState = 0,
|
lastState = 0,
|
||||||
lastStationUnitNumber = 0,
|
lastStationUnitNumber = 0,
|
||||||
currentStationUnitNumber = 0,
|
currentStationUnitNumber = 0,
|
||||||
@@ -95,18 +119,19 @@ trainStat = {
|
|||||||
trips = {}
|
trips = {}
|
||||||
}
|
}
|
||||||
---@class trip
|
---@class trip
|
||||||
trip = {
|
trip = {
|
||||||
startStation= {},
|
startStation = {},
|
||||||
endStation = {},
|
endStation = {},
|
||||||
timeTaken = 0
|
timeTaken = 0,
|
||||||
}
|
tick = 0
|
||||||
|
}
|
||||||
|
|
||||||
---@param inv table[]
|
---@param inv table[]
|
||||||
---@return table<string, table>
|
---@return table<string, table>
|
||||||
local function toLookup(inv)
|
local function toLookup(inv)
|
||||||
local t = {}
|
local t = {}
|
||||||
for _, item in ipairs(inv) do
|
for _, item in ipairs(inv) do
|
||||||
local key = item.name .. ":" .. (item.quality or 0) -- eindeutiger Key
|
local key = item.name .. ":" .. (item.quality or 0) -- eindeutiger Key
|
||||||
t[key] = item.count
|
t[key] = item.count
|
||||||
end
|
end
|
||||||
return t
|
return t
|
||||||
@@ -166,7 +191,6 @@ function onTrainStateChange(event)
|
|||||||
stat.trainName = GetTrainName(train)
|
stat.trainName = GetTrainName(train)
|
||||||
|
|
||||||
if event.train.state == defines.train_state.wait_station then
|
if event.train.state == defines.train_state.wait_station then
|
||||||
|
|
||||||
if not train.station then return end
|
if not train.station then return end
|
||||||
if train.station.unit_number == stat.lastStationUnitNumber then return end
|
if train.station.unit_number == stat.lastStationUnitNumber then return end
|
||||||
|
|
||||||
@@ -179,19 +203,21 @@ function onTrainStateChange(event)
|
|||||||
stat.currentArrivalTime = game.tick
|
stat.currentArrivalTime = game.tick
|
||||||
|
|
||||||
if stat.lastStationUnitNumber
|
if stat.lastStationUnitNumber
|
||||||
and stat.currentStationUnitNumber
|
and stat.currentStationUnitNumber
|
||||||
and (stat.lastStationUnitNumber ~= stat.currentStationUnitNumber) then
|
and (stat.lastStationUnitNumber ~= stat.currentStationUnitNumber) then
|
||||||
local tripIdentifier = tostring(stat.lastStationUnitNumber) .. tostring(stat.currentStationUnitNumber)
|
local tripIdentifier = tostring(stat.lastStationUnitNumber) .. tostring(stat.currentStationUnitNumber)
|
||||||
stat.trips[tripIdentifier] = {
|
stat.trips[tripIdentifier] = {
|
||||||
startStation = game.get_entity_by_unit_number(stat.lastStationUnitNumber),
|
startStation = game.get_entity_by_unit_number(stat.lastStationUnitNumber),
|
||||||
endStation = game.get_entity_by_unit_number(stat.currentStationUnitNumber),
|
endStation = game.get_entity_by_unit_number(stat.currentStationUnitNumber),
|
||||||
timeTaken = stat.currentArrivalTime-stat.lastArrivalTime}
|
timeTaken = stat.currentArrivalTime - stat.lastArrivalTime,
|
||||||
|
time = game.tick
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
if stat.currentInventory and stat.lastInventory then
|
if stat.currentInventory and stat.lastInventory then
|
||||||
--Get Total Cargo
|
--Get Total Cargo
|
||||||
for key, value in pairs(inventoryDiff(stat.lastInventory,stat.currentInventory)) do
|
for key, value in pairs(inventoryDiff(stat.lastInventory, stat.currentInventory)) do
|
||||||
stat.totalCargoCount = (stat.totalCargoCount or 0) + math.abs(value.delta)
|
stat.totalCargoCount = (stat.totalCargoCount or 0) + math.abs(value.delta)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -199,14 +225,15 @@ function onTrainStateChange(event)
|
|||||||
end
|
end
|
||||||
--log("inEvent")
|
--log("inEvent")
|
||||||
end
|
end
|
||||||
|
|
||||||
--Checks if trip is still valid by checking of st
|
--Checks if trip is still valid by checking of st
|
||||||
function isTripValid(trip,tripID,trainID)
|
function isTripValid(trip, tripID, trainID)
|
||||||
if trip.startStation == nil
|
if trip.startStation == nil
|
||||||
or trip.endStation==nil
|
or trip.endStation == nil
|
||||||
or trip.startStation.valid == false
|
or trip.startStation.valid == false
|
||||||
or trip.endStation.valid == false then
|
or trip.endStation.valid == false then
|
||||||
--One station is nil so we delete this trip
|
--One station is nil so we delete this trip
|
||||||
log("Deleting trip"..tripID)
|
log("Deleting trip" .. tripID)
|
||||||
storage.trainStats[trainID].trips[tripID] = nil
|
storage.trainStats[trainID].trips[tripID] = nil
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@@ -214,40 +241,55 @@ function isTripValid(trip,tripID,trainID)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function SortTrips()
|
||||||
|
for trainID, stat in pairs(storage.trainStats) do
|
||||||
|
table.sort(stat.trips, function(a, b)
|
||||||
|
return a.tick > b.tick
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function GetTrainTripStats()
|
function GetTrainTripStats()
|
||||||
|
--SortTrips()
|
||||||
local tripParts = {}
|
local tripParts = {}
|
||||||
local tripCount = 0
|
local tripCount = 0
|
||||||
tripParts[#tripParts+1] = "---train-trips---\n"
|
tripParts[#tripParts + 1] = "---train-trips---\n"
|
||||||
for trainID,stats in pairs(storage.trainStats) do
|
for trainID, stats in pairs(storage.trainStats) do
|
||||||
for tripIndex,trip in pairs(stats.trips or {}) do
|
for tripIndex, trip in pairs(stats.trips or {}) do
|
||||||
if isTripValid(trip,tripIndex,trainID) then
|
if isTripValid(trip, tripIndex, trainID) then
|
||||||
tripParts[#tripParts+1] =
|
tripParts[#tripParts + 1] =
|
||||||
("%d:%s:%s:%s:%d"):format(
|
("%d:%s:%s:%s:%s:%d"):format(
|
||||||
trainID,
|
trainID,
|
||||||
stats.trainName,
|
stats.trainName,
|
||||||
trip.startStation.backer_name,
|
trip.startStation.surface.name,
|
||||||
trip.endStation.backer_name,
|
trip.startStation.backer_name,
|
||||||
trip.timeTaken)
|
trip.endStation.backer_name,
|
||||||
tripCount = tripCount + 1
|
trip.timeTaken)
|
||||||
|
tripCount = tripCount + 1
|
||||||
end
|
end
|
||||||
|
--To clean up, we delete this trip now
|
||||||
|
stats.trips[tripIndex] = nil
|
||||||
end
|
end
|
||||||
if #tripParts > 400 then
|
if #tripParts > 400 then
|
||||||
log("Sending at "..tripCount.." trips")
|
log("Sending at " .. tripCount .. " trips")
|
||||||
helpers.send_udp(udpAddress,table.concat(tripParts,"\n"),serverIndex)
|
helpers.send_udp(udpAddress, table.concat(tripParts, "\n"), serverIndex)
|
||||||
tripParts = {}
|
tripParts = {}
|
||||||
|
tripParts[#tripParts + 1] = "---train-trips---\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
log("Counted "..tripCount.." trips")
|
--tripParts[#tripParts+1] = "--train-fin--"
|
||||||
|
helpers.send_udp(udpAddress, table.concat(tripParts, "\n"), serverIndex)
|
||||||
|
log("Counted " .. tripCount .. " trips")
|
||||||
--return table.concat(tripParts,"\n")
|
--return table.concat(tripParts,"\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
function GetTrainStatistics()
|
function GetTrainStatistics()
|
||||||
local trainParts = {}
|
local trainParts = {}
|
||||||
trainParts[#trainParts+1] = "---train-total-statistics---\n"
|
trainParts[#trainParts + 1] = "---train-total-statistics---\n"
|
||||||
for trainID, stat in pairs(storage.trainStats) do
|
for trainID, stat in pairs(storage.trainStats) do
|
||||||
trainParts[#trainParts+1] = ("%d:%s:%d"):format(trainID,stat.trainName,stat.totalCargoCount or 0)
|
trainParts[#trainParts + 1] = ("%d:%s:%d"):format(trainID, stat.trainName, stat.totalCargoCount or 0)
|
||||||
end
|
end
|
||||||
return table.concat(trainParts,"\n")
|
return table.concat(trainParts, "\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
---Purges stats for trains that no longer exist
|
---Purges stats for trains that no longer exist
|
||||||
@@ -270,21 +312,20 @@ function PurgeDeadTrainStats(trainID)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function SendTrainStats()
|
function SendTrainStats()
|
||||||
if options.enableTrains then
|
if options.enableTrains then
|
||||||
ScanTrains()
|
ScanTrains()
|
||||||
PurgeDeadTrainStats()
|
PurgeDeadTrainStats()
|
||||||
local returnParts = {}
|
local returnParts = {}
|
||||||
returnParts[#returnParts+1] = GetTrainPlayerKills()
|
returnParts[#returnParts + 1] = GetTrainPlayerKills()
|
||||||
returnParts[#returnParts+1] = GetTrainTotalKills()
|
returnParts[#returnParts + 1] = GetTrainTotalKills()
|
||||||
returnParts[#returnParts+1] = GetTrainStates()
|
returnParts[#returnParts + 1] = GetTrainStates()
|
||||||
returnParts[#returnParts+1] = GetTrainStatistics()
|
returnParts[#returnParts + 1] = GetTrainStatistics()
|
||||||
returnParts[#returnParts+1] = GetTrainsInDepot()
|
returnParts[#returnParts + 1] = GetTrainsInDepot()
|
||||||
if options.enableTrainTrips then
|
if options.enableTrainTrips then
|
||||||
GetTrainTripStats()
|
GetTrainTripStats()
|
||||||
end
|
end
|
||||||
log("Sending Train statistics")
|
log("Sending Train statistics")
|
||||||
helpers.send_udp(udpAddress,table.concat(returnParts,"\n"),serverIndex)
|
helpers.send_udp(udpAddress, table.concat(returnParts, "\n"), serverIndex)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Reference in New Issue
Block a user