mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-14 07:24:52 +09:00
Sync the page shown on each quick bar row (#1202)
* Sync the page shown on each quick bar row player_sync restored the content of the quick bar slots but not which page each row shows, which every save keeps per player on its own. After switching servers the rows could show other pages, and with them another set of slots. Fixes #1201 Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JyNnVzRW4jPWaoWTxCyhM7 * Sync every quick bar slot when the pages are wider than 10 From Factorio 2.1 a quick bar page is as wide as the player set it, up to 100 slots. Only the first 100 slots were synced, so with wider pages the later pages kept the content of the destination, and restoring the page shown on a row could show those. --------- Co-authored-by: ILLISIS <jayson.harris01@gmail.com> Co-authored-by: Claude Fable 5.2 <noreply@anthropic.com> Co-authored-by: Danielv123 <danielv@danielv.no>
This commit is contained in:
5 files changed
+43
-4
No files matched your search
@@ -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`.
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -23,6 +23,7 @@ export type IpcPlayerData = {
|
||||
character?: any,
|
||||
inventories?: any,
|
||||
quick_bar?: any,
|
||||
quick_bar_pages?: number[],
|
||||
hotbar?: Record<string, string>,
|
||||
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),
|
||||
|
||||
@@ -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<string, QuickBarSlotEncoded>?
|
||||
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<string, table>?
|
||||
--- @field hotbar table<string, string>?
|
||||
--- @field quick_bar table<string, QuickBarSlotEncoded>?
|
||||
--- @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
|
||||
|
||||
@@ -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 } }],
|
||||
|
||||
Reference in new issue
Block a user