Files
factorio-clusterio/plugins/player_sync/player_data.ts
T
bbassieandClaude Opus 5.5 004fb13f1c Handle empty inventories serialized as objects
Factorio's table_to_json writes an empty inventory as {"i":{}}, which
made the summary throw for show and the web drawer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 18:52:29 +00:00

60 lines
1.6 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,
};
// Factorio serializes an empty table as {}
type SerializedInventory = { i?: SerializedItem[] | Record<string, SerializedItem> };
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: SerializedInventory): ItemSummary[] {
let items: ItemSummary[] = [];
let stacks = new Map<string, ItemSummary>();
for (let entry of Object.values(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 SerializedInventory) })
);
}