mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-05 01:23:24 -08:00
[Client] Tell the user when their playmat art is blocked (#7533)
* [Client] Tell the user when their playmat art is blocked A server DENY rule silently drops banned playmat art: SetPlaymat fails with no handler and DeckSelect strips the mat while answering RespOk. Surface both cases with the same critical message box the banner card art flow uses. DeckSelect strips are detected by comparing the requested mat, passed via PendingCommand extraData, against the server-echoed deck. Notices dedupe per card and reset on success. * [Client] Gate playmat blocked notice on RespFunctionNotAllowed per review Only SetPlaymat with RespFunctionNotAllowed signals a card art DENY rule. Older servers answer RespInvalidCommand and strip the mat from DeckSelect, so drop the DeckSelect comparison to avoid false blacklisted popups on pre-playmat servers. --------- Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de> Co-authored-by: BruebachL <bruebachl@users.noreply.github.com>
This commit is contained in:
parent
b11b096828
commit
711386574d
2 changed files with 27 additions and 3 deletions
|
|
@ -354,6 +354,19 @@ void DeckViewContainer::resolveAndSendPlaymat()
|
|||
pp->set_vertical_offset(resolved.params.verticalOffset);
|
||||
pp->set_zoom(resolved.params.zoom);
|
||||
PendingCommand *playmatPend = parentGame->getGame()->getGameEventHandler()->prepareGameCommand(playmatCmd);
|
||||
const QString sentName = resolved.card.name;
|
||||
connect(playmatPend, &PendingCommand::finished, this, [this, sentName](const Response &r) {
|
||||
// Only RespFunctionNotAllowed signals a card art DENY rule. Older servers that predate
|
||||
// playmats answer RespInvalidCommand and strip the mat from DeckSelect, which must stay silent.
|
||||
if (r.response_code() == Response::RespFunctionNotAllowed) {
|
||||
if (!sentName.isEmpty()) {
|
||||
notifyPlaymatBlacklisted(
|
||||
sentName, tr("The selected playmat card is blacklisted on this server, so it was not applied."));
|
||||
}
|
||||
} else if (r.response_code() == Response::RespOk && !sentName.isEmpty()) {
|
||||
lastBlacklistedPlaymatNotice.clear();
|
||||
}
|
||||
});
|
||||
parentGame->getGame()->getGameEventHandler()->sendGameCommand(playmatPend, playerId);
|
||||
}
|
||||
|
||||
|
|
@ -412,6 +425,15 @@ void DeckViewContainer::deckSelectFinished(const Response &r)
|
|||
switchToDeckLoadedView();
|
||||
}
|
||||
|
||||
void DeckViewContainer::notifyPlaymatBlacklisted(const QString &cardName, const QString &message)
|
||||
{
|
||||
if (cardName.isEmpty() || cardName == lastBlacklistedPlaymatNotice) {
|
||||
return;
|
||||
}
|
||||
lastBlacklistedPlaymatNotice = cardName;
|
||||
QMessageBox::critical(this, tr("Error"), message);
|
||||
}
|
||||
|
||||
void DeckViewContainer::readyStart()
|
||||
{
|
||||
sendReadyStartCommand(!readyStartButton->getState());
|
||||
|
|
|
|||
|
|
@ -60,12 +60,14 @@ private:
|
|||
VisualDeckStorageWidget *visualDeckStorageWidget;
|
||||
TabGame *parentGame;
|
||||
int playerId;
|
||||
int playmatRotationIndex = 0; ///< Per-match cursor for round-robin playmat mode.
|
||||
DeckList currentDeck; ///< Cached deck for live settings re-resolution.
|
||||
PlaymatInfo lastResolvedPlaymat; ///< Tracks last sent playmat to avoid repeats in random mode.
|
||||
int playmatRotationIndex = 0; ///< Per-match cursor for round-robin playmat mode.
|
||||
DeckList currentDeck; ///< Cached deck for live settings re-resolution.
|
||||
PlaymatInfo lastResolvedPlaymat; ///< Tracks last sent playmat to avoid repeats in random mode.
|
||||
QString lastBlacklistedPlaymatNotice; ///< Card name already reported as blacklisted, to avoid repeat popups.
|
||||
|
||||
void tryCreateVisualDeckStorageWidget();
|
||||
void sendReadyStartCommand(bool ready);
|
||||
void notifyPlaymatBlacklisted(const QString &cardName, const QString &message);
|
||||
private slots:
|
||||
void switchToDeckSelectView();
|
||||
void switchToDeckLoadedView();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue