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>
This commit is contained in:
bbassieandClaude Opus 5.5 committed 2026-10-17 18:52:29 +00:00
1 parent f67097257b
commit 004fb13f1c
2 files changed
+11 -3

No files matched your search

+6 -3
View File
@@ -9,6 +9,9 @@ type SerializedItem = {
e?: string,
};
// Factorio serializes an empty table as {}
type SerializedInventory = { i?: SerializedItem[] | Record<string, SerializedItem> };
export type ItemSummary = {
name: string,
quality?: string,
@@ -22,10 +25,10 @@ export type InventorySummary = {
items: ItemSummary[],
};
export function summarizeInventory(inventory: { i?: SerializedItem[] }): ItemSummary[] {
export function summarizeInventory(inventory: SerializedInventory): ItemSummary[] {
let items: ItemSummary[] = [];
let stacks = new Map<string, ItemSummary>();
for (let entry of inventory.i ?? []) {
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++) {
@@ -51,6 +54,6 @@ export function summarizeInventory(inventory: { i?: SerializedItem[] }): ItemSum
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[] }) })
([name, inventory]) => ({ name, items: summarizeInventory(inventory as SerializedInventory) })
);
}
+5
View File
@@ -65,6 +65,7 @@ describe("player_sync plugin", function() {
});
it("should handle empty inventories", function() {
assert.deepEqual(summarizeInventory({}), []);
assert.deepEqual(summarizeInventory(JSON.parse('{"i":{}}')), []);
assert.deepEqual(
summarizeInventory({ i: [{ n: "wood" }] }),
[{ name: "wood", quality: undefined, count: 0 }],
@@ -88,6 +89,10 @@ describe("player_sync plugin", function() {
{ name: "main", items: [{ name: "stone", quality: undefined, count: 1 }] },
]);
});
it("should handle empty serialized inventories", function() {
const data = JSON.parse('{"generation":1,"name":"player","character":{"inventories":{"armor":{"i":{}}}}}');
assert.deepEqual(summarizePlayerInventories(data), [{ name: "armor", items: [] }]);
});
it("should handle missing inventories", function() {
assert.deepEqual(summarizePlayerInventories(playerData("player", 1)), []);
assert.deepEqual(summarizePlayerInventories(playerData("player", 1, { character: {} })), []);