diff --git a/plugins/player_sync/README.md b/plugins/player_sync/README.md index 5c663358..d148f834 100644 --- a/plugins/player_sync/README.md +++ b/plugins/player_sync/README.md @@ -170,7 +170,7 @@ Defaults to `true`. ### player_sync.sync_quick_bar -Sync the quick bar. +Sync the quick bar and the page shown on each of its rows. Defaults to `true`. diff --git a/plugins/player_sync/components.ts b/plugins/player_sync/components.ts index 1e1c1b03..133e039f 100644 --- a/plugins/player_sync/components.ts +++ b/plugins/player_sync/components.ts @@ -9,7 +9,7 @@ export const components = { // inventories holds the god inventory and the hidden ghost inventory inventories: ["character", "crafting_queue", "inventories"], logistics: ["personal_logistic_slots"], - quick_bar: ["quick_bar", "hotbar"], + quick_bar: ["quick_bar", "quick_bar_pages", "hotbar"], settings: ["flashlight", "shortcuts", "game_view_settings"], recipe_notifications: ["recipe_notifications"], } as const; diff --git a/plugins/player_sync/messages.ts b/plugins/player_sync/messages.ts index 5a92591d..a3a1ce9b 100644 --- a/plugins/player_sync/messages.ts +++ b/plugins/player_sync/messages.ts @@ -23,6 +23,7 @@ export type IpcPlayerData = { character?: any, inventories?: any, quick_bar?: any, + quick_bar_pages?: number[], hotbar?: Record, personal_logistic_slots?: any, crafting_queue?: any, @@ -181,6 +182,7 @@ const jsonImportedPlayerData = Type.Object({ character: Type.Optional(jsonCharacter), inventories: Type.Optional(jsonInventories), quick_bar: Type.Optional(Type.Record(Type.String(), jsonQuickBarSlot)), + quick_bar_pages: Type.Optional(Type.Array(Type.Integer({ minimum: 1, maximum: 10 }), { maxItems: 10 })), hotbar: Type.Optional(Type.Record(Type.String(), Type.String())), personal_logistic_slots: Type.Optional(jsonPersonalLogisticSlots), crafting_queue: Type.Optional(jsonCraftingQueue), diff --git a/plugins/player_sync/module/serialize.lua b/plugins/player_sync/module/serialize.lua index 71087c39..ee082e85 100644 --- a/plugins/player_sync/module/serialize.lua +++ b/plugins/player_sync/module/serialize.lua @@ -662,13 +662,20 @@ function serialize.deserialize_quick_bar_slot(entry, player) return entry --[[@as string]] end +--- Slots over all 10 quick bar pages, a page is as wide as the player set it from 2.1 and 10 slots before +--- @param player LuaPlayer +--- @return integer +local function quick_bar_slot_count(player) + return 10 * (v2_1_quick_bar_api and player.quick_bar_width or 10) +end + --- @param player LuaPlayer --- @return table? function serialize.serialize_quick_bar(player) local serialized local width = v2_1_quick_bar_api and player.quick_bar_width - for i = 1, 100 do + for i = 1, quick_bar_slot_count(player) do local slot if v2_1_quick_bar_api then @@ -699,7 +706,7 @@ function serialize.deserialize_quick_bar(player, serialized) -- previous server does not come back from this server's old copy serialized = serialized or {} local width = v2_1_quick_bar_api and player.quick_bar_width - for i = 1, 100 do + for i = 1, quick_bar_slot_count(player) do local entry = serialized[tostring(i)] local slot = entry ~= nil and serialize.deserialize_quick_bar_slot(entry, player) or nil if v2_1_quick_bar_api then @@ -713,6 +720,30 @@ function serialize.deserialize_quick_bar(player, serialized) end end +--- Quick bar page shown on each quick bar row of the screen, kept by every save on its own +--- @param player LuaPlayer +--- @return integer[]? +function serialize.serialize_quick_bar_pages(player) + local pages = {} + for screen = 1, 10 do + -- pcall: the number of rows the API knows is not documented for older versions + local ok, page = pcall(player.get_active_quick_bar_page, screen) + if not ok or not page then + break + end + pages[screen] = page + end + return pages[1] and pages or nil +end + +--- @param player LuaPlayer +--- @param pages integer[]? Absent in data from before pages were synced, the rows then stay as they are here +function serialize.deserialize_quick_bar_pages(player, pages) + for screen, page in ipairs(pages or {}) do + player.set_active_quick_bar_page(screen, page) + end +end + -- Crafting queue is a table with the following fields: -- crafting_queue -- ingredients @@ -977,6 +1008,7 @@ end --- @field inventories table? --- @field hotbar table? --- @field quick_bar table? +--- @field quick_bar_pages integer[]? Page shown on each quick bar row --- @field personal_logistic_slots table? --- @field crafting_queue table? --- @field recipe_notifications string? @@ -1181,6 +1213,7 @@ function serialize.serialize_player(player, failed_deserialization, components) -- Serialize quick bar if syncs(components, "quick_bar") then serialized.quick_bar = serialize.serialize_quick_bar(player) + serialized.quick_bar_pages = serialize.serialize_quick_bar_pages(player) end -- Serialize crafting queue @@ -1463,6 +1496,7 @@ function serialize.deserialize_player(player, serialized, components, local_cont -- Deserialize quick bar (named hotbar in old data) if syncs(components, "quick_bar") then serialize.deserialize_quick_bar(player, serialized.quick_bar or serialized.hotbar) + serialize.deserialize_quick_bar_pages(player, serialized.quick_bar_pages) end -- Deserialize recipe notifications diff --git a/plugins/player_sync/test/plugin.js b/plugins/player_sync/test/plugin.js index 77516d93..2bc67904 100644 --- a/plugins/player_sync/test/plugin.js +++ b/plugins/player_sync/test/plugin.js @@ -117,6 +117,7 @@ describe("player_sync plugin", function() { 3: { t: "i", n: "main", s: 4, b: [2] }, 4: { t: "r", p: [1], y: "blueprint" }, }, + quick_bar_pages: [2, 1, 3], crafting_queue: { crafting_queue: [{ recipe: "iron-gear-wheel", count: 5 }], crafting_queue_progress: 0.25, @@ -172,6 +173,8 @@ describe("player_sync plugin", function() { ["quick_bar", { 1: { t: "i", n: "main" } }], ["quick_bar", { 1: { t: "r", y: "blueprint" } }], ["quick_bar", { 1: 5 }], + ["quick_bar_pages", [0]], + ["quick_bar_pages", [11]], ["personal_logistic_slots", { enabled: true, sections: [] }], ["personal_logistic_slots", { enabled: true, trash_not_requested: false, sections: [{}] }], ["personal_logistic_slots", { 1: { min: 50 } }],