Route random hand reveals through PlayerActions

Keep command creation, dispatch and response handling in the game action
layer. HandMenu requests the typed operation and presents the count and
failure dialogs. Show the chosen recipient, distinguish the count action
from the immediate single-card reveal, and use the game window as parent.
This commit is contained in:
Bryce! 2026-11-03 16:36:54 -05:00
parent ccdee18db2
commit afe9bf77af
5 changed files with 59 additions and 28 deletions

View file

@ -6,6 +6,8 @@
#include "../player_graphics_item.h"
#include <QAction>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QInputDialog>
#include <QKeySequence>
#include <QList>
@ -24,8 +26,6 @@
#include <libcockatrice/game/player/player_manager.h>
#include <libcockatrice/game/zones/hand_zone_logic.h>
#include <libcockatrice/network/client/abstract/abstract_client.h>
#include <libcockatrice/protocol/pb/response.pb.h>
#include <libcockatrice/protocol/pending_command.h>
#include <libcockatrice/utility/zone_names.h>
class QWidget;
@ -33,6 +33,7 @@ class QWidget;
HandMenu::HandMenu(PlayerGraphicsItem *_player, QWidget *parent) : TearOffMenu(parent), player(_player)
{
auto *actions = player->getLogic()->getPlayerActions();
connect(actions, &PlayerActions::randomHandRevealFailed, this, &HandMenu::onRandomHandRevealFailed);
if (player->getLogic()->getPlayerInfo()->local || player->getLogic()->getPlayerInfo()->judge) {
aViewHand = new QAction(this);
@ -161,7 +162,7 @@ void HandMenu::retranslateUi()
mRevealRandomHandCard->setTitle(tr("Reveal r&andom card to..."));
aRevealRandomHandCardToAll->setText(tr("All players"));
mRevealRandomHandCards->setTitle(tr("Reveal random cards to..."));
mRevealRandomHandCards->setTitle(tr("Reveal a chosen number of random cards to..."));
aRevealRandomHandCardsToAll->setText(tr("All players"));
}
}
@ -253,15 +254,19 @@ void HandMenu::onRevealRandomHandCardTriggered()
void HandMenu::populateRevealRandomHandCardsMenuWithActivePlayers()
{
const bool hasCards = !player->getLogic()->getHandZone()->getCards().isEmpty();
mRevealRandomHandCards->clear();
aRevealRandomHandCardsToAll->setEnabled(hasCards);
mRevealRandomHandCards->addAction(aRevealRandomHandCardsToAll);
mRevealRandomHandCards->addSeparator();
for (auto *other : player->getLogic()->getGame()->getPlayerManager()->getPlayers()) {
const auto &players = player->getLogic()->getGame()->getPlayerManager()->getPlayers().values();
for (auto *other : players) {
if (other == player->getLogic()) {
continue;
}
auto *action = mRevealRandomHandCards->addAction(other->getPlayerInfo()->getName());
action->setData(other->getPlayerInfo()->getId());
action->setEnabled(hasCards);
connect(action, &QAction::triggered, this, &HandMenu::onRevealRandomHandCardsTriggered);
}
}
@ -280,36 +285,45 @@ void HandMenu::onRevealRandomHandCardsTriggered()
if (!client) {
return;
}
auto *dialog = new QInputDialog(this);
auto *dialog = new QInputDialog(dialogParent());
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setWindowTitle(tr("Reveal Random Hand Cards"));
dialog->setLabelText(tr("Number of distinct random cards to reveal:"));
dialog->setLabelText(tr("Number of distinct random cards to reveal to %1:").arg(action->text()));
dialog->setInputMode(QInputDialog::IntInput);
dialog->setIntRange(1, handSize);
dialog->setIntValue(qMin(2, handSize));
connect(this, &QObject::destroyed, dialog, &QDialog::reject);
connect(client, &QObject::destroyed, dialog, &QDialog::reject);
connect(actions, &QObject::destroyed, dialog, &QDialog::reject);
connect(dialog, &QDialog::accepted, this, [this, dialog, actions, client, targetId] {
connect(dialog, &QDialog::accepted, this, [dialog, actions, client, targetId] {
if (!actions || !client) {
return;
}
auto *pending = actions->prepareRandomHandReveal(targetId, dialog->intValue());
connect(pending, &PendingCommand::finished, this, [this, actions, client](const Response &response) {
if (!actions || !client || response.response_code() == Response::RespOk) {
return;
}
const QString text =
response.response_code() == Response::RespInvalidCommand
? tr("This server does not support revealing multiple random cards. No cards were revealed.")
: tr("The random reveal could not be completed. The hand or recipient may have changed.");
auto *message =
new QMessageBox(QMessageBox::Warning, tr("Reveal Random Hand Cards"), text, QMessageBox::Ok, this);
message->setAttribute(Qt::WA_DeleteOnClose);
connect(actions, &QObject::destroyed, message, &QDialog::reject);
connect(client, &QObject::destroyed, message, &QDialog::reject);
message->open();
});
actions->sendGameCommand(pending);
actions->actRevealRandomHandCards(targetId, dialog->intValue());
});
dialog->open();
}
QWidget *HandMenu::dialogParent() const
{
if (auto *view = player->scene() ? player->scene()->views().value(0) : nullptr) {
return view->window();
}
return nullptr;
}
void HandMenu::onRandomHandRevealFailed(bool unsupported)
{
const QString text =
unsupported ? tr("This server does not support revealing multiple random cards. No cards were revealed.")
: tr("The random reveal could not be completed. The hand or recipient may have changed.");
auto *message = new QMessageBox(QMessageBox::Warning, tr("Reveal Random Hand Cards"), text, QMessageBox::Ok,
dialogParent());
message->setAttribute(Qt::WA_DeleteOnClose);
connect(this, &QObject::destroyed, message, &QDialog::reject);
connect(player->getLogic()->getPlayerActions(), &QObject::destroyed, message, &QDialog::reject);
if (auto *client = player->getLogic()->getGame()->getClientForPlayer(player->getLogic()->getPlayerInfo()->getId())) {
connect(client, &QObject::destroyed, message, &QDialog::reject);
}
message->open();
}