mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-11-12 07:54:52 +09:00
The plugin is now exp_player_statistics (@expcluster/player-statistics), with the module, global, permission, route and database directory renamed to match. The exp-statistics locale section keeps its name. Every statistic is tracked unconditionally, so the enable flags are gone from config.lua. Playtime and JoinCount are no longer counted in game: clusterio already keeps online time and joins for each user, so the controller fills them in from the user when a player's totals are requested, and the web page does the same from the user list. They are not stored or adjusted by the plugin. The web table has a column picker, a multiple select with check boxes, Select all and Reset buttons, showing "N statistics selected". The choice is kept in local storage. The user page shows the statistics of the player in a grid like the core player stats. The readme statistics table drops its second title and uses the short time format. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
156 lines
5.1 KiB
Lua
156 lines
5.1 KiB
Lua
--[[-- ExpPlayerStatistics
|
|
Player statistics kept on the controller.
|
|
|
|
What each player gains is kept here as unsent until it is sent to the
|
|
controller, every 5 minutes and when the player leaves. Once sent it is added
|
|
to the totals the controller gave when the player joined, so get() is the
|
|
total across every server either way.
|
|
|
|
Updates which are lost are not sent again. Anything unsent when the server
|
|
starts is from a save made before it was sent, so it is dropped rather than
|
|
risk counting it twice.
|
|
|
|
local ExpPlayerStatistics = require("modules/exp_player_statistics")
|
|
|
|
ExpPlayerStatistics.increment(player, "Kills")
|
|
ExpPlayerStatistics.get(player, "Kills")
|
|
for _, name in ipairs(ExpPlayerStatistics.display_order) do end
|
|
]]
|
|
|
|
local clusterio_api = require("modules/clusterio/api")
|
|
local ExpUtil = require("modules/exp_util")
|
|
local Storage = require("modules/exp_util/storage")
|
|
local config = require("modules/exp_player_statistics/config")
|
|
|
|
local format_number = require("util").format_number
|
|
|
|
--- @alias ExpPlayerStatistics.Stats table<string, number>
|
|
|
|
--- @class ExpPlayerStatistics.Totals
|
|
--- @field name string
|
|
--- @field stats ExpPlayerStatistics.Stats
|
|
|
|
--- @class ExpPlayerStatistics
|
|
local ExpPlayerStatistics = {
|
|
config = config,
|
|
--- Statistics in the order they are shown
|
|
--- @type string[]
|
|
display_order = config.display_order,
|
|
--- Shown after the value
|
|
--- @type table<string, string>
|
|
units = { DistanceTravelled = " tiles" },
|
|
}
|
|
|
|
--- Measured in minutes and shown as a time
|
|
local time_statistics = { Playtime = true, AfkTime = true }
|
|
local long_time_format = ExpUtil.format_time_factory_locale{ format = "long", coefficient = 3600, hours = true, minutes = true }
|
|
local short_time_format = ExpUtil.format_time_factory_locale{ format = "short", coefficient = 3600, hours = true, minutes = true }
|
|
|
|
local unsent = {} --- @type table<string, ExpPlayerStatistics.Stats>
|
|
local totals = {} --- @type table<string, ExpPlayerStatistics.Stats>
|
|
Storage.register({ unsent, totals }, function(tbl)
|
|
unsent = tbl[1]
|
|
totals = tbl[2]
|
|
end)
|
|
|
|
--- Add to a statistic of a player
|
|
--- @param player LuaPlayer
|
|
--- @param statistic string
|
|
--- @param amount number? Defaults to 1
|
|
function ExpPlayerStatistics.increment(player, statistic, amount)
|
|
local name = player.name
|
|
local stats = unsent[name]
|
|
if not stats then
|
|
stats = {}
|
|
unsent[name] = stats
|
|
end
|
|
stats[statistic] = (stats[statistic] or 0) + (amount or 1)
|
|
end
|
|
|
|
--- Get the total of a statistic for a player, on every server
|
|
--- @param player LuaPlayer | string
|
|
--- @param statistic string
|
|
--- @return number
|
|
function ExpPlayerStatistics.get(player, statistic)
|
|
local name = type(player) == "string" and player or player.name
|
|
local received = totals[name]
|
|
local pending = unsent[name]
|
|
return (received and received[statistic] or 0) + (pending and pending[statistic] or 0)
|
|
end
|
|
|
|
--- Get the value of a statistic as it is shown to players
|
|
--- @param statistic string
|
|
--- @param value number
|
|
--- @param short boolean? Use the short time format
|
|
--- @return LocalisedString
|
|
function ExpPlayerStatistics.format(statistic, value, short)
|
|
if time_statistics[statistic] then
|
|
return short and short_time_format(value) or long_time_format(value)
|
|
end
|
|
return format_number(value, false)
|
|
end
|
|
|
|
--- Move the unsent statistics of a player into their totals
|
|
--- @param name string
|
|
--- @return ExpPlayerStatistics.Stats?
|
|
local function take_unsent(name)
|
|
local stats = unsent[name]
|
|
if not stats then return nil end
|
|
unsent[name] = nil
|
|
|
|
local received = totals[name]
|
|
if not received then
|
|
received = {}
|
|
totals[name] = received
|
|
end
|
|
for statistic, value in pairs(stats) do
|
|
received[statistic] = (received[statistic] or 0) + value
|
|
end
|
|
return stats
|
|
end
|
|
|
|
--- Send what a player gained to the controller
|
|
--- @param name string
|
|
function ExpPlayerStatistics.send(name)
|
|
local stats = take_unsent(name)
|
|
if stats then
|
|
clusterio_api.send_json("exp_player_statistics:update", { players = { { name = name, stats = stats } } })
|
|
end
|
|
end
|
|
|
|
--- Send what every player gained to the controller, in one update
|
|
function ExpPlayerStatistics.send_all()
|
|
local players, count = {}, 0
|
|
for name in pairs(unsent) do
|
|
count = count + 1
|
|
players[count] = { name = name, stats = take_unsent(name) }
|
|
end
|
|
if count > 0 then
|
|
clusterio_api.send_json("exp_player_statistics:update", { players = players })
|
|
end
|
|
end
|
|
|
|
--- Send what a player gained and forget them, called when they leave
|
|
--- @param name string
|
|
function ExpPlayerStatistics.send_and_forget(name)
|
|
ExpPlayerStatistics.send(name)
|
|
totals[name] = nil
|
|
end
|
|
|
|
--- Called by the instance plugin over rcon when the server starts
|
|
function ExpPlayerStatistics.discard_unsent()
|
|
for name in pairs(unsent) do
|
|
unsent[name] = nil
|
|
end
|
|
end
|
|
|
|
--- Called by the instance plugin over rcon when a player joins
|
|
--- @param payload ExpPlayerStatistics.Totals
|
|
function ExpPlayerStatistics.receive_totals(payload)
|
|
local player = game.get_player(payload.name)
|
|
if not player or not player.connected then return end
|
|
totals[payload.name] = payload.stats
|
|
end
|
|
|
|
return ExpPlayerStatistics
|