mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-13 15:14:52 +09:00
Admins had no way to look at or fix the player data the controller stores when a sync went wrong. The web page now lists every stored entry with its generation, size and the instance holding the lock, and opens a drawer per player with an inventory summary, JSON export and import, delete and lock release. The same operations are exposed as clusterioctl player-sync commands. Import bumps the generation past the stored one so instances holding an older copy download the new data on the next join. Import and delete are refused while an instance holds the lock, since its upload on leave would undo the change. A new player_sync.inventory.modify permission gates the write operations. Closes #1003 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
57 lines
1.5 KiB
TypeScript
57 lines
1.5 KiB
TypeScript
import type { IpcPlayerData } from "./messages.js";
|
|
|
|
// See packages/host/modules/clusterio/serialize.lua for the item stack format
|
|
type SerializedItem = {
|
|
n?: string,
|
|
c?: number,
|
|
q?: string,
|
|
r?: number,
|
|
e?: string,
|
|
};
|
|
|
|
export type ItemSummary = {
|
|
name: string,
|
|
quality?: string,
|
|
count: number,
|
|
/** Length of the export string for blueprints and other exportable items */
|
|
exportSize?: number,
|
|
};
|
|
|
|
export type InventorySummary = {
|
|
name: string,
|
|
items: ItemSummary[],
|
|
};
|
|
|
|
export function summarizeInventory(inventory: { i?: SerializedItem[] }): ItemSummary[] {
|
|
let items: ItemSummary[] = [];
|
|
let stacks = new Map<string, ItemSummary>();
|
|
for (let entry of inventory.i ?? []) {
|
|
let repeat = (entry.r ?? 0) + 1;
|
|
if (entry.e !== undefined) {
|
|
for (let i = 0; i < repeat; i++) {
|
|
items.push({ name: "exported item", count: 1, exportSize: entry.e.length });
|
|
}
|
|
continue;
|
|
}
|
|
if (entry.n === undefined) {
|
|
continue;
|
|
}
|
|
let key = `${entry.n}\0${entry.q ?? ""}`;
|
|
let stack = stacks.get(key);
|
|
if (!stack) {
|
|
stack = { name: entry.n, quality: entry.q, count: 0 };
|
|
stacks.set(key, stack);
|
|
items.push(stack);
|
|
}
|
|
stack.count += (entry.c ?? 0) * repeat;
|
|
}
|
|
return items;
|
|
}
|
|
|
|
export function summarizePlayerInventories(playerData: IpcPlayerData): InventorySummary[] {
|
|
let inventories = playerData.character?.inventories ?? playerData.inventories ?? {};
|
|
return Object.entries(inventories).map(
|
|
([name, inventory]) => ({ name, items: summarizeInventory(inventory as { i?: SerializedItem[] }) })
|
|
);
|
|
}
|