Add option to share decklists on load. (#6029)

* Add option to share decklists on load.

Took 1 hour 58 minutes

Took 9 minutes


Took 39 minutes

* Lint.

Took 14 minutes


Took 2 minutes

* Stuffs

Took 39 minutes

Took 4 seconds

Took 43 minutes

* Process local player first.

Took 45 minutes

* Consider if the setting is set on the game info first.

Took 4 minutes

* Save an indent level.

Took 43 seconds

* Don't commit logging config.

Took 3 minutes

* Remove a debug print.

Took 10 seconds


Took 7 seconds

* Add another optional guard.

Took 5 minutes

* Hide the tab bar if only one (own deck) is visible.

Took 9 minutes

* Rename setting label for clarity

Took 2 minutes

* Capitalization.

Took 3 minutes

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2025-08-15 23:31:05 +02:00 committed by GitHub
parent 881243da6a
commit 09381575a7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 268 additions and 33 deletions

View file

@ -7,6 +7,7 @@
#include "../../game/cards/card_database.h"
#include "../../game/cards/card_database_manager.h"
#include "../../game/deckview/deck_view_container.h"
#include "../../game/deckview/tabbed_deck_view_container.h"
#include "../../game/game_scene.h"
#include "../../game/game_view.h"
#include "../../game/player/player.h"
@ -292,9 +293,9 @@ void TabGame::retranslateUi()
QMapIterator<int, Player *> i(players);
while (i.hasNext())
i.next().value()->retranslateUi();
QMapIterator<int, DeckViewContainer *> j(deckViewContainers);
QMapIterator<int, TabbedDeckViewContainer *> j(deckViewContainers);
while (j.hasNext())
j.next().value()->retranslateUi();
j.next().value()->playerDeckView->retranslateUi();
scene->retranslateUi();
}
@ -564,7 +565,7 @@ void TabGame::actCompleterChanged()
Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
{
bool local = ((clients.size() > 1) || (playerId == localPlayerId));
bool local = clients.size() > 1 || playerId == localPlayerId;
auto *newPlayer = new Player(info, playerId, local, judge, this);
connect(newPlayer, SIGNAL(openDeckEditor(const DeckLoader *)), this, SIGNAL(openDeckEditor(const DeckLoader *)));
QString newPlayerName = "@" + newPlayer->getName();
@ -582,8 +583,8 @@ Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
if (clients.size() == 1)
newPlayer->setShortcutsActive();
auto *deckView = new DeckViewContainer(playerId, this);
connect(deckView, &DeckViewContainer::newCardAdded, this, &TabGame::newCardAdded);
auto *deckView = new TabbedDeckViewContainer(playerId, this);
connect(deckView->playerDeckView, &DeckViewContainer::newCardAdded, this, &TabGame::newCardAdded);
deckViewContainers.insert(playerId, deckView);
deckViewContainerLayout->addWidget(deckView);
@ -591,8 +592,8 @@ Player *TabGame::addPlayer(int playerId, const ServerInfo_User &info)
QString deckPath = SettingsCache::instance().debug().getDeckPathForPlayer(newPlayer->getName());
if (!deckPath.isEmpty()) {
QTimer::singleShot(0, this, [deckView, deckPath] {
deckView->loadDeckFromFile(deckPath);
deckView->readyAndUpdate();
deckView->playerDeckView->loadDeckFromFile(deckPath);
deckView->playerDeckView->readyAndUpdate();
});
}
}
@ -777,11 +778,11 @@ void TabGame::startGame(bool _resuming)
{
currentPhase = -1;
QMapIterator<int, DeckViewContainer *> i(deckViewContainers);
QMapIterator<int, TabbedDeckViewContainer *> i(deckViewContainers);
while (i.hasNext()) {
i.next();
i.value()->setReadyStart(false);
i.value()->setVisualDeckStorageExists(false);
i.value()->playerDeckView->setReadyStart(false);
i.value()->playerDeckView->setVisualDeckStorageExists(false);
i.value()->hide();
}
@ -803,7 +804,7 @@ void TabGame::stopGame()
currentPhase = -1;
activePlayer = -1;
QMapIterator<int, DeckViewContainer *> i(deckViewContainers);
QMapIterator<int, TabbedDeckViewContainer *> i(deckViewContainers);
while (i.hasNext()) {
i.next();
i.value()->show();
@ -849,6 +850,44 @@ void TabGame::eventGameStateChanged(const Event_GameStateChanged &event,
const GameEventContext & /*context*/)
{
const int playerListSize = event.player_list_size();
// Always process the local player first so we have an established deckViewcontainer
for (int i = 0; i < playerListSize; ++i) {
const ServerInfo_Player &playerInfo = event.player_list(i);
const ServerInfo_PlayerProperties &prop = playerInfo.properties();
const int playerId = prop.player_id();
QString playerName = "@" + QString::fromStdString(prop.user_info().name());
if (sayEdit && !autocompleteUserList.contains(playerName)) {
autocompleteUserList << playerName;
sayEdit->setCompletionList(autocompleteUserList);
}
if (!prop.spectator()) {
Player *player = players.value(playerId, 0);
if (!player) {
if (clients.size() > 1 || playerId == localPlayerId) {
player = addPlayer(playerId, prop.user_info());
playerListWidget->addPlayer(prop);
player->processPlayerInfo(playerInfo);
if (player->getLocal()) {
TabbedDeckViewContainer *deckViewContainer = deckViewContainers.value(playerId);
if (playerInfo.has_deck_list()) {
DeckLoader newDeck(QString::fromStdString(playerInfo.deck_list()));
PictureLoader::cacheCardPixmaps(
CardDatabaseManager::getInstance()->getCards(newDeck.getCardRefList()));
deckViewContainer->playerDeckView->setDeck(newDeck);
player->setDeck(newDeck);
}
deckViewContainer->playerDeckView->setReadyStart(prop.ready_start());
deckViewContainer->playerDeckView->setSideboardLocked(prop.sideboard_locked());
}
}
}
}
}
// then process every non-local player.
for (int i = 0; i < playerListSize; ++i) {
const ServerInfo_Player &playerInfo = event.player_list(i);
const ServerInfo_PlayerProperties &prop = playerInfo.properties();
@ -870,17 +909,16 @@ void TabGame::eventGameStateChanged(const Event_GameStateChanged &event,
playerListWidget->addPlayer(prop);
}
player->processPlayerInfo(playerInfo);
if (player->getLocal()) {
DeckViewContainer *deckViewContainer = deckViewContainers.value(playerId);
if (playerInfo.has_deck_list()) {
DeckLoader newDeck(QString::fromStdString(playerInfo.deck_list()));
PictureLoader::cacheCardPixmaps(
CardDatabaseManager::getInstance()->getCards(newDeck.getCardRefList()));
deckViewContainer->setDeck(newDeck);
player->setDeck(newDeck);
}
deckViewContainer->setReadyStart(prop.ready_start());
deckViewContainer->setSideboardLocked(prop.sideboard_locked());
if (player->getLocal() || !gameInfo.share_decklists_on_load()) {
continue;
}
DeckList loader;
loader.loadFromString_Native(QString::fromStdString(playerInfo.deck_list()));
QMapIterator<int, TabbedDeckViewContainer *> i(deckViewContainers);
while (i.hasNext()) {
i.next();
i.value()->addOpponentDeckView(loader, playerId, player->getName());
}
}
}
@ -926,7 +964,7 @@ void TabGame::eventPlayerPropertiesChanged(const Event_PlayerPropertiesChanged &
case GameEventContext::READY_START: {
bool ready = prop.ready_start();
if (player->getLocal())
deckViewContainers.value(player->getId())->setReadyStart(ready);
deckViewContainers.value(player->getId())->playerDeckView->setReadyStart(ready);
if (ready)
messageLog->logReadyStart(player);
else
@ -957,11 +995,20 @@ void TabGame::eventPlayerPropertiesChanged(const Event_PlayerPropertiesChanged &
Context_DeckSelect deckSelect = context.GetExtension(Context_DeckSelect::ext);
messageLog->logDeckSelect(player, QString::fromStdString(deckSelect.deck_hash()),
deckSelect.sideboard_size());
if (gameInfo.share_decklists_on_load() && deckSelect.has_deck_list() && eventPlayerId != localPlayerId) {
DeckList loader;
loader.loadFromString_Native(QString::fromStdString(deckSelect.deck_list()));
QMapIterator<int, TabbedDeckViewContainer *> i(deckViewContainers);
while (i.hasNext()) {
i.next();
i.value()->addOpponentDeckView(loader, eventPlayerId, player->getName());
}
}
break;
}
case GameEventContext::SET_SIDEBOARD_LOCK: {
if (player->getLocal())
deckViewContainers.value(player->getId())->setSideboardLocked(prop.sideboard_locked());
deckViewContainers.value(player->getId())->playerDeckView->setSideboardLocked(prop.sideboard_locked());
messageLog->logSetSideboardLock(player, prop.sideboard_locked());
break;
}