From 004fb13f1cb3105d640a929ef0845fa45da7e31d Mon Sep 17 00:00:00 2001 From: bbassie <17990055+bbassie@users.noreply.github.com> Date: Sat, 17 Oct 2026 15:32:20 +0000 Subject: [PATCH] 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 --- plugins/player_sync/player_data.ts | 9 ++++++--- plugins/player_sync/test/plugin.js | 5 +++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/plugins/player_sync/player_data.ts b/plugins/player_sync/player_data.ts index b4857ee5..1905b9c7 100644 --- a/plugins/player_sync/player_data.ts +++ b/plugins/player_sync/player_data.ts @@ -9,6 +9,9 @@ type SerializedItem = { e?: string, }; +// Factorio serializes an empty table as {} +type SerializedInventory = { i?: SerializedItem[] | Record }; + 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(); - 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) }) ); } diff --git a/plugins/player_sync/test/plugin.js b/plugins/player_sync/test/plugin.js index 56968025..be8442be 100644 --- a/plugins/player_sync/test/plugin.js +++ b/plugins/player_sync/test/plugin.js @@ -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: {} })), []);