Allow up to 100 dice to be rolled at a time (#5047)

* Allow up to 100 dice to be rolled at a time
- Fix #4276
This commit is contained in:
Zach H
2024-06-12 08:37:04 -04:00
committed by GitHub
parent c95cc1dd9d
commit ce8092318e
36 changed files with 184 additions and 58 deletions

View File

@@ -48,6 +48,7 @@ set(cockatrice_SOURCES
src/dlg_load_remote_deck.cpp
src/dlg_manage_sets.cpp
src/dlg_register.cpp
src/dlg_roll_dice.cpp
src/dlg_settings.cpp
src/dlg_tip_of_the_day.cpp
src/dlg_update.cpp

View File

@@ -1,7 +1,7 @@
#include "dlg_connect.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include "userconnection_information.h"
#include <QCheckBox>

View File

@@ -5,7 +5,7 @@
#include "decklist.h"
#include "main.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QCheckBox>
#include <QCloseEvent>

View File

@@ -3,8 +3,8 @@
#include "pb/serverinfo_game.pb.h"
#include "pending_command.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "tab_room.h"
#include "trice_limits.h"
#include <QApplication>
#include <QCheckBox>

View File

@@ -1,6 +1,6 @@
#include "dlg_edit_avatar.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QBuffer>
#include <QDebug>

View File

@@ -1,7 +1,7 @@
#include "dlg_edit_password.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QDialogButtonBox>
#include <QGridLayout>

View File

@@ -4,7 +4,7 @@
#include "carddatabasemodel.h"
#include "gettextwithmax.h"
#include "main.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QAction>
#include <QComboBox>

View File

@@ -1,7 +1,7 @@
#include "dlg_edit_user.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QDebug>
#include <QDialogButtonBox>

View File

@@ -1,7 +1,7 @@
#include "dlg_forgotpasswordchallenge.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QCheckBox>
#include <QDebug>

View File

@@ -1,7 +1,7 @@
#include "dlg_forgotpasswordrequest.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QCheckBox>
#include <QDebug>

View File

@@ -1,7 +1,7 @@
#include "dlg_forgotpasswordreset.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QCheckBox>
#include <QDebug>

View File

@@ -2,7 +2,7 @@
#include "pb/serverinfo_user.pb.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QCheckBox>
#include <QDebug>

View File

@@ -0,0 +1,52 @@
#include "dlg_roll_dice.h"
#include "trice_limits.h"
#include <QDialogButtonBox>
#include <QLabel>
#include <QSpinBox>
#include <QVBoxLayout>
#include <QWidget>
DlgRollDice::DlgRollDice(QWidget *parent) : QDialog(parent)
{
numberOfSidesLabel = new QLabel(tr("Number of sides:"));
numberOfSidesEdit = new QSpinBox(this);
numberOfSidesEdit->setValue(DEFAULT_NUMBER_SIDES_DIE);
numberOfSidesEdit->setRange(MINIMUM_DIE_SIDES, MAXIMUM_DIE_SIDES);
numberOfSidesEdit->setFocus();
numberOfSidesLabel->setBuddy(numberOfSidesEdit);
numberOfDiceLabel = new QLabel(tr("Number of dice:"));
numberOfDiceEdit = new QSpinBox(this);
numberOfDiceEdit->setValue(DEFAULT_NUMBER_DICE_TO_ROLL);
numberOfDiceEdit->setRange(MINIMUM_DICE_TO_ROLL, MAXIMUM_DICE_TO_ROLL);
numberOfDiceLabel->setBuddy(numberOfDiceEdit);
auto *grid = new QGridLayout;
grid->addWidget(numberOfSidesLabel, 0, 0);
grid->addWidget(numberOfSidesEdit, 0, 1);
grid->addWidget(numberOfDiceLabel, 1, 0);
grid->addWidget(numberOfDiceEdit, 1, 1);
buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto *mainLayout = new QVBoxLayout;
mainLayout->addItem(grid);
mainLayout->addWidget(buttonBox);
setLayout(mainLayout);
setWindowTitle(tr("Roll Dice"));
}
uint DlgRollDice::getDieSideCount() const
{
return numberOfSidesEdit->text().toUInt();
}
uint DlgRollDice::getDiceToRollCount() const
{
return numberOfDiceEdit->text().toUInt();
}

View File

@@ -0,0 +1,26 @@
#ifndef DLG_ROLL_DICE_H
#define DLG_ROLL_DICE_H
#include <QDialog>
#include <QDialogButtonBox>
#include <QLabel>
#include <QSpinBox>
class DlgRollDice : public QDialog
{
Q_OBJECT
static constexpr uint DEFAULT_NUMBER_SIDES_DIE = 20;
static constexpr uint DEFAULT_NUMBER_DICE_TO_ROLL = 1;
QLabel *numberOfSidesLabel, *numberOfDiceLabel;
QSpinBox *numberOfSidesEdit, *numberOfDiceEdit;
QDialogButtonBox *buttonBox;
public:
explicit DlgRollDice(QWidget *parent = nullptr);
[[nodiscard]] uint getDieSideCount() const;
[[nodiscard]] uint getDiceToRollCount() const;
};
#endif // DLG_ROLL_DICE_H

View File

@@ -2,7 +2,7 @@
#ifndef GETTEXTWITHMAX_H
#define GETTEXTWITHMAX_H
#include "stringsizes.h"
#include "trice_limits.h"
#include <QInputDialog>

View File

@@ -558,18 +558,39 @@ void MessageLogWidget::logReverseTurn(Player *player, bool reversed)
.arg(reversed ? tr("reversed") : tr("normal")));
}
void MessageLogWidget::logRollDie(Player *player, int sides, int roll)
void MessageLogWidget::logRollDie(Player *player, int sides, const QList<uint> &rolls)
{
if (sides == 2) {
QString coinOptions[2] = {tr("Heads") + " (1)", tr("Tails") + " (2)"};
appendHtmlServerMessage(tr("%1 flipped a coin. It landed as %2.")
.arg(sanitizeHtml(player->getName()))
.arg("<font class=\"blue\">" + coinOptions[roll - 1] + "</font>"));
if (rolls.length() == 1) {
const auto roll = rolls.at(0);
if (sides == 2) {
QString coinOptions[2] = {tr("Heads") + " (1)", tr("Tails") + " (2)"};
appendHtmlServerMessage(tr("%1 flipped a coin. It landed as %2.")
.arg(sanitizeHtml(player->getName()))
.arg("<font class=\"blue\">" + coinOptions[roll - 1] + "</font>"));
} else {
appendHtmlServerMessage(tr("%1 rolls a %2 with a %3-sided die.")
.arg(sanitizeHtml(player->getName()))
.arg("<font class=\"blue\">" + QString::number(roll) + "</font>")
.arg("<font class=\"blue\">" + QString::number(sides) + "</font>"));
}
} else {
appendHtmlServerMessage(tr("%1 rolls a %2 with a %3-sided die.")
.arg(sanitizeHtml(player->getName()))
.arg("<font class=\"blue\">" + QString::number(roll) + "</font>")
.arg("<font class=\"blue\">" + QString::number(sides) + "</font>"));
if (sides == 2) {
appendHtmlServerMessage(tr("%1 flips %2 coins. There are %3 heads and %4 tails.")
.arg(sanitizeHtml(player->getName()))
.arg("<font class=\"blue\">" + QString::number(rolls.length()) + "</font>")
.arg("<font class=\"blue\">" + QString::number(rolls.count(1)) + "</font>")
.arg("<font class=\"blue\">" + QString::number(rolls.count(2)) + "</font>"));
} else {
QStringList rollsStrings;
for (const auto &roll : rolls) {
rollsStrings.append(QString::number(roll));
}
appendHtmlServerMessage(tr("%1 rolls a %2-sided dice %3 times: %4.")
.arg(sanitizeHtml(player->getName()))
.arg("<font class=\"blue\">" + QString::number(sides) + "</font>")
.arg("<font class=\"blue\">" + QString::number(rolls.length()) + "</font>")
.arg("<font class=\"blue\">" + rollsStrings.join(", ") + "</font>"));
}
}
soundEngine->playSound("roll_dice");
}
@@ -796,7 +817,8 @@ void MessageLogWidget::connectToPlayer(Player *player)
connect(player, SIGNAL(logSay(Player *, QString)), this, SLOT(logSay(Player *, QString)));
connect(player, &Player::logShuffle, this, &MessageLogWidget::logShuffle);
connect(player, SIGNAL(logRollDie(Player *, int, int)), this, SLOT(logRollDie(Player *, int, int)));
connect(player, SIGNAL(logRollDie(Player *, int, const QList<uint> &)), this,
SLOT(logRollDie(Player *, int, const QList<uint> &)));
connect(player, SIGNAL(logCreateArrow(Player *, Player *, QString, Player *, QString, bool)), this,
SLOT(logCreateArrow(Player *, Player *, QString, Player *, QString, bool)));
connect(player, SIGNAL(logCreateToken(Player *, QString, QString)), this,

View File

@@ -79,7 +79,7 @@ public slots:
bool faceDown,
int amount);
void logReverseTurn(Player *player, bool reversed);
void logRollDie(Player *player, int sides, int roll);
void logRollDie(Player *player, int sides, const QList<uint> &rolls);
void logSay(Player *player, QString message);
void logSetActivePhase(int phase);
void logSetActivePlayer(Player *player);

View File

@@ -9,6 +9,7 @@
#include "counter_general.h"
#include "deck_loader.h"
#include "dlg_create_token.h"
#include "dlg_roll_dice.h"
#include "gamescene.h"
#include "gettextwithmax.h"
#include "handcounter.h"
@@ -57,10 +58,10 @@
#include "playertarget.h"
#include "settingscache.h"
#include "stackzone.h"
#include "stringsizes.h"
#include "tab_game.h"
#include "tablezone.h"
#include "thememanager.h"
#include "trice_limits.h"
#include "zoneviewwidget.h"
#include "zoneviewzone.h"
@@ -1601,15 +1602,15 @@ void Player::actUntapAll()
void Player::actRollDie()
{
bool ok;
int sides = QInputDialog::getInt(game, tr("Roll die"), tr("Number of sides:"), defaultNumberDieRoll, minDieRoll,
maxDieRoll, 1, &ok);
if (ok) {
defaultNumberDieRoll = sides;
Command_RollDie cmd;
cmd.set_sides(static_cast<google::protobuf::uint32>(sides));
sendGameCommand(cmd);
DlgRollDice dlg(game);
if (!dlg.exec()) {
return;
}
Command_RollDie cmd;
cmd.set_sides(dlg.getDieSideCount());
cmd.set_count(dlg.getDiceToRollCount());
sendGameCommand(cmd);
}
void Player::actCreateToken()
@@ -1962,7 +1963,21 @@ void Player::eventShuffle(const Event_Shuffle &event)
void Player::eventRollDie(const Event_RollDie &event)
{
emit logRollDie(this, event.sides(), event.value());
if (event.value()) {
// Backwards compatibility for old clients
emit logRollDie(this, static_cast<int>(event.sides()), {event.value()});
} else {
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QList<uint> rolls(event.values().begin(), event.values().end());
#else
QList<uint> rolls;
for (const auto &value : event.values()) {
rolls.append(value);
}
#endif
std::sort(rolls.begin(), rolls.end());
emit logRollDie(this, static_cast<int>(event.sides()), rolls);
}
}
void Player::eventCreateArrow(const Event_CreateArrow &event)

View File

@@ -114,7 +114,7 @@ signals:
// Log events
void logSay(Player *player, QString message);
void logShuffle(Player *player, CardZone *zone, int start, int end);
void logRollDie(Player *player, int sides, int roll);
void logRollDie(Player *player, int sides, const QList<uint> &rolls);
void logCreateArrow(Player *player,
Player *startPlayer,
QString startCard,
@@ -259,8 +259,6 @@ private:
int defaultNumberTopCardsToPlaceBelow = 1;
int defaultNumberBottomCards = 1;
int defaultNumberDieRoll = 20;
static constexpr int minDieRoll = 2;
static constexpr int maxDieRoll = 1000000;
QString lastTokenName, lastTokenColor, lastTokenPT, lastTokenAnnotation;
bool lastTokenDestroy;
int lastTokenTableRow;

View File

@@ -10,7 +10,7 @@
#include "pb/session_commands.pb.h"
#include "pending_command.h"
#include "soundengine.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include "userinfobox.h"
#include "userlist.h"

View File

@@ -2,7 +2,7 @@
#include "abstractclient.h"
#include "pb/admin_commands.pb.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QDialogButtonBox>
#include <QGridLayout>

View File

@@ -15,9 +15,9 @@
#include "pictureloader.h"
#include "pixmapgenerator.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "tab_supervisor.h"
#include "tappedout_interface.h"
#include "trice_limits.h"
#include <QAction>
#include <QApplication>

View File

@@ -52,8 +52,8 @@
#include "playerlistwidget.h"
#include "replay_timeline_widget.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "tab_supervisor.h"
#include "trice_limits.h"
#include "window_main.h"
#include "zoneviewwidget.h"
#include "zoneviewzone.h"

View File

@@ -6,7 +6,7 @@
#include "pb/moderator_commands.pb.h"
#include "pb/response_viewlog_history.pb.h"
#include "pending_command.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QCheckBox>
#include <QDialogButtonBox>

View File

@@ -10,7 +10,7 @@
#include "pending_command.h"
#include "settingscache.h"
#include "soundengine.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QApplication>
#include <QDebug>

View File

@@ -15,9 +15,9 @@
#include "pb/serverinfo_room.pb.h"
#include "pending_command.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "tab_account.h"
#include "tab_supervisor.h"
#include "trice_limits.h"
#include "userlist.h"
#include <QApplication>

View File

@@ -8,9 +8,9 @@
#include "pb/session_commands.pb.h"
#include "pending_command.h"
#include "pixmapgenerator.h"
#include "stringsizes.h"
#include "tab_account.h"
#include "tab_supervisor.h"
#include "trice_limits.h"
#include "user_context_menu.h"
#include <QApplication>

View File

@@ -1,6 +1,6 @@
#include "debug_pb_message.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QList>
#include <QString>

View File

@@ -5,4 +5,5 @@ message Command_RollDie {
optional Command_RollDie ext = 1005;
}
optional uint32 sides = 1;
optional uint32 count = 2;
}

View File

@@ -7,4 +7,5 @@ message Event_RollDie {
}
optional uint32 sides = 1;
optional uint32 value = 2;
repeated uint32 values = 3;
}

View File

@@ -79,7 +79,7 @@
#include "server_database_interface.h"
#include "server_game.h"
#include "server_room.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QDebug>
#include <algorithm>
@@ -1060,7 +1060,7 @@ Server_Player::cmdMulligan(const Command_Mulligan &cmd, ResponseContainer & /*rc
}
Response::ResponseCode
Server_Player::cmdRollDie(const Command_RollDie &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges)
Server_Player::cmdRollDie(const Command_RollDie &cmd, ResponseContainer & /*rc*/, GameEventStorage &ges) const
{
if (spectator) {
return Response::RespFunctionNotAllowed;
@@ -1069,9 +1069,15 @@ Server_Player::cmdRollDie(const Command_RollDie &cmd, ResponseContainer & /*rc*/
return Response::RespContextError;
}
const auto validatedSides = static_cast<int>(std::min(std::max(cmd.sides(), MINIMUM_DIE_SIDES), MAXIMUM_DIE_SIDES));
const auto validatedDiceToRoll =
static_cast<int>(std::min(std::max(cmd.count(), MINIMUM_DICE_TO_ROLL), MAXIMUM_DICE_TO_ROLL));
Event_RollDie event;
event.set_sides(cmd.sides());
event.set_value(rng->rand(1, cmd.sides()));
event.set_sides(validatedSides);
for (auto i = 0; i < validatedDiceToRoll; ++i) {
event.add_values(rng->rand(1, validatedSides));
}
ges.enqueueGameEvent(event, playerId);
return Response::RespOk;

View File

@@ -203,7 +203,7 @@ public:
Response::ResponseCode cmdGameSay(const Command_GameSay &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdShuffle(const Command_Shuffle &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdMulligan(const Command_Mulligan &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRollDie(const Command_RollDie &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdRollDie(const Command_RollDie &cmd, ResponseContainer &rc, GameEventStorage &ges) const;
Response::ResponseCode cmdDrawCards(const Command_DrawCards &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdUndoDraw(const Command_UndoDraw &cmd, ResponseContainer &rc, GameEventStorage &ges);
Response::ResponseCode cmdMoveCard(const Command_MoveCard &cmd, ResponseContainer &rc, GameEventStorage &ges);

View File

@@ -21,7 +21,7 @@
#include "server_game.h"
#include "server_player.h"
#include "server_room.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QDateTime>
#include <QDebug>

View File

@@ -11,7 +11,7 @@
#include "pb/serverinfo_room.pb.h"
#include "server_game.h"
#include "server_protocolhandler.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include <QDateTime>
#include <QDebug>

View File

@@ -1,6 +1,5 @@
// max sizes of strings used in the protocol
#ifndef STRINGSIZES_H
#define STRINGSIZES_H
#ifndef TRICE_LIMITS_H
#define TRICE_LIMITS_H
#include <QString>
@@ -11,6 +10,11 @@ constexpr int MAX_TEXT_LENGTH = 0xfff;
// max size for deck files and pictures
constexpr int MAX_FILE_LENGTH = 0xfffff; // about a megabyte
constexpr uint MINIMUM_DIE_SIDES = 2;
constexpr uint MAXIMUM_DIE_SIDES = 1000000;
constexpr uint MINIMUM_DICE_TO_ROLL = 1;
constexpr uint MAXIMUM_DICE_TO_ROLL = 100;
// optimized functions to get qstrings that are at most that long
static inline QString nameFromStdString(const std::string &_string)
{
@@ -25,4 +29,4 @@ static inline QString fileFromStdString(const std::string &_string)
return QString::fromUtf8(_string.data(), std::min(int(_string.size()), MAX_FILE_LENGTH));
}
#endif // STRINGSIZES_H
#endif // TRICE_LIMITS_H

View File

@@ -65,7 +65,7 @@
#include "server_response_containers.h"
#include "server_room.h"
#include "settingscache.h"
#include "stringsizes.h"
#include "trice_limits.h"
#include "version_string.h"
#include <QDateTime>