From ebeae4865261e1749f83945f5be660f2f11b8b33 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Mon, 7 Sep 2026 08:21:44 +0200 Subject: [PATCH] [Game] Preserve hand card order when restoring connection (#7266) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a player restores connection to a game, the client rebuilds each zone from the cards the server sends in the game state. Non-coordinate zones (hand, piles, stack) report x == 0 on every card, so inserting each rebuilt card at that coordinate reversed the received order one card at a time. Append rebuilt cards in the order they arrive for zones without coordinates; coordinate-based zones (table) keep using x/y. Fixes #2759 Co-authored-by: Lukas BrĂ¼bach --- cockatrice/src/game/player/player_logic.cpp | 10 ++++++- .../card_zone_algorithms_test.cpp | 29 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/game/player/player_logic.cpp b/cockatrice/src/game/player/player_logic.cpp index 45ba09aac..143df5c57 100644 --- a/cockatrice/src/game/player/player_logic.cpp +++ b/cockatrice/src/game/player/player_logic.cpp @@ -175,7 +175,15 @@ void PlayerLogic::processPlayerInfo(const ServerInfo_Player &info) const ServerInfo_Card &cardInfo = zoneInfo.card_list(j); auto *card = new CardItem(this); card->processCardInfo(cardInfo); - zone->addCard(card, false, cardInfo.x(), cardInfo.y()); + // Zones without coordinates (hand, piles, stack) preserve the order + // they arrive in on the server in the positions of their cards list. + // The x coordinate of such cards is always 0, so inserting at it + // would reverse the list on reconnect. Append instead. + if (zoneInfo.with_coords()) { + zone->addCard(card, false, cardInfo.x(), cardInfo.y()); + } else { + zone->addCard(card, false, -1); + } } } if (zoneInfo.has_always_reveal_top_card()) { diff --git a/tests/card_zone_algorithms/card_zone_algorithms_test.cpp b/tests/card_zone_algorithms/card_zone_algorithms_test.cpp index cc098cae9..8fab42566 100644 --- a/tests/card_zone_algorithms/card_zone_algorithms_test.cpp +++ b/tests/card_zone_algorithms/card_zone_algorithms_test.cpp @@ -134,6 +134,35 @@ TEST_F(AddCardAlgorithmTest, MidListInsertionPreservesOrder) EXPECT_EQ(knownList.at(2), &b); } +// Reconnecting to a game rebuilds zones from a ServerInfo_Zone. Non-coordinate zones +// (hand, piles, stack) report x == 0 on every card, so inserting each rebuilt card at +// that index would reverse the received server order. Appending (-1) keeps it. +TEST_F(AddCardAlgorithmTest, RebuildInsertAtZeroReversesServerOrder) +{ + MockCard a, b, c; + CardZoneAlgorithms::addCardToList(knownList, &a, 0, false); + CardZoneAlgorithms::addCardToList(knownList, &b, 0, false); + CardZoneAlgorithms::addCardToList(knownList, &c, 0, false); + + EXPECT_EQ(knownList.size(), 3); + EXPECT_EQ(knownList.at(0), &c); + EXPECT_EQ(knownList.at(1), &b); + EXPECT_EQ(knownList.at(2), &a); +} + +TEST_F(AddCardAlgorithmTest, RebuildAppendPreservesServerOrder) +{ + MockCard a, b, c; + CardZoneAlgorithms::addCardToList(knownList, &a, -1, false); + CardZoneAlgorithms::addCardToList(knownList, &b, -1, false); + CardZoneAlgorithms::addCardToList(knownList, &c, -1, false); + + EXPECT_EQ(knownList.size(), 3); + EXPECT_EQ(knownList.at(0), &a); + EXPECT_EQ(knownList.at(1), &b); + EXPECT_EQ(knownList.at(2), &c); +} + TEST_F(AddCardAlgorithmTest, KeepAnnotationsFalsePassedThrough) { MockCard card;