mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-11-12 07:54:52 +09:00
clusterio#1129 replaced DatastoreProvider.bootstrap with async factories and Instance now takes its FactorioServer in the constructor, so the instance tests pass their server stub there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
63 lines
2.4 KiB
TypeScript
63 lines
2.4 KiB
TypeScript
import type { ControllerPluginContext } from "@clusterio/controller";
|
|
import * as lib from "@clusterio/lib";
|
|
import * as messages from "./messages.js";
|
|
import * as path from "node:path";
|
|
|
|
/** Keeps the statistics totals of every player, instances send what was gained since their last update. */
|
|
export default async function (context: ControllerPluginContext) {
|
|
const { controller, plugin } = context;
|
|
const databaseDirectory = controller.config.get("controller.database_directory");
|
|
const players = await lib.SubscribableDatastore.fromProvider(new lib.JsonIdDatastoreProvider(
|
|
path.join(databaseDirectory, "exp_player_statistics", "players.json"),
|
|
messages.PlayerStatistics.fromJSON.bind(messages.PlayerStatistics),
|
|
));
|
|
|
|
function addDeltas(deltas: messages.StatisticsDelta[]) {
|
|
const changed = new Map<string, messages.PlayerStatistics>();
|
|
for (const delta of deltas) {
|
|
const record = changed.get(delta.name)
|
|
?? players.getMutable(delta.name)
|
|
?? new messages.PlayerStatistics(delta.name);
|
|
for (const [name, value] of Object.entries(delta.stats)) {
|
|
if (Number.isFinite(value) && value !== 0) {
|
|
record.stats[name] = (record.stats[name] ?? 0) + value;
|
|
}
|
|
}
|
|
changed.set(record.id, record);
|
|
}
|
|
if (changed.size) {
|
|
players.setMany([...changed.values()]);
|
|
}
|
|
}
|
|
|
|
players.on("update", updates => {
|
|
controller.subscriptions.broadcast(new messages.PlayerStatisticsUpdatedEvent(updates));
|
|
});
|
|
|
|
controller.subscriptions.handle(messages.PlayerStatisticsUpdatedEvent, async request => {
|
|
const updates = [...players.values()].filter(player => player.updatedAtMs > request.lastRequestTimeMs);
|
|
return updates.length ? new messages.PlayerStatisticsUpdatedEvent(updates) : null;
|
|
});
|
|
|
|
controller.handle(messages.StatisticsUpdateEvent, async (event: messages.StatisticsUpdateEvent) => {
|
|
addDeltas(event.deltas);
|
|
});
|
|
|
|
controller.handle(messages.StatisticsGetRequest, async (request: messages.StatisticsGetRequest) => {
|
|
const record = players.get(request.name);
|
|
return new messages.PlayerStatistics(request.name, {
|
|
...record?.stats,
|
|
...messages.userStatistics(controller.users.getByName(request.name), record?.stats),
|
|
}, record?.updatedAtMs);
|
|
});
|
|
|
|
controller.handle(messages.StatisticsListRequest, async () => [...players.values()]);
|
|
|
|
controller.hooks.save.attach(plugin.name, async () => {
|
|
await players.save();
|
|
});
|
|
controller.hooks.shutdown.attach(plugin.name, async () => {
|
|
await players.save();
|
|
});
|
|
}
|