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>
60 lines
2.0 KiB
TypeScript
60 lines
2.0 KiB
TypeScript
import type { InstancePluginContext } from "@clusterio/host";
|
|
import * as messages from "./messages.js";
|
|
|
|
/** Sent by the lua side with what each player gained since the last update. */
|
|
export type IpcStatisticsUpdate = {
|
|
players: { name: string, stats: Record<string, number> }[],
|
|
};
|
|
|
|
/**
|
|
* Forwards the statistics gained in game to the controller, and hands the
|
|
* totals of a player to lua when they join, see module/control.lua.
|
|
*/
|
|
export default async function (context: InstancePluginContext) {
|
|
const { instance, plugin, logger } = context;
|
|
|
|
async function luaCall(code: string) {
|
|
await instance.sendRcon(`/sc ${code}`, true);
|
|
}
|
|
|
|
async function luaSendTotals(record: messages.PlayerStatistics) {
|
|
const json = JSON.stringify({ name: record.id, stats: record.stats });
|
|
// Pick a long bracket the json does not contain
|
|
let level = "=";
|
|
while (json.includes(`]${level}]`)) {
|
|
level += "=";
|
|
}
|
|
await luaCall(`exp_player_statistics.receive_totals(helpers.json_to_table[${level}[${json}]${level}])`);
|
|
}
|
|
|
|
instance.server.handle("exp_player_statistics:update", async (event: IpcStatisticsUpdate) => {
|
|
instance.sendTo("controller", new messages.StatisticsUpdateEvent(
|
|
event.players.map(player => new messages.StatisticsDelta(player.name, player.stats)),
|
|
));
|
|
});
|
|
|
|
instance.hooks.playerEvent.attach(plugin.name, async event => {
|
|
if (event.type !== "join") {
|
|
return;
|
|
}
|
|
try {
|
|
const record = await instance.sendTo("controller", new messages.StatisticsGetRequest(event.name));
|
|
if (instance.status === "running") {
|
|
await luaSendTotals(record);
|
|
}
|
|
} catch (err: any) {
|
|
logger.warn(`Failed to send the statistics of ${event.name}: ${err.message}`);
|
|
}
|
|
});
|
|
|
|
// Anything still unsent at start came from a save made before the last
|
|
// update was sent, so it is dropped rather than counted twice
|
|
instance.hooks.start.attach(plugin.name, async () => {
|
|
await luaCall("exp_player_statistics.discard_unsent()");
|
|
});
|
|
|
|
instance.hooks.stop.attach(plugin.name, async () => {
|
|
await luaCall("exp_player_statistics.send_all()");
|
|
});
|
|
}
|