mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2025-12-12 07:40:30 -08:00
Addresses crash scenario where too many cards were being loaded in a game.
- Too many iterations that fill up the server's memory trying to (1) render the deck hash and (2) building up a string of the deck contents
This commit is contained in:
@@ -334,12 +334,14 @@ void DeckViewScene::rebuildTree()
|
|||||||
{
|
{
|
||||||
clearContents();
|
clearContents();
|
||||||
|
|
||||||
if (!deck)
|
if (!deck) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int cardsRenderedAlready = 0;
|
||||||
InnerDecklistNode *listRoot = deck->getRoot();
|
InnerDecklistNode *listRoot = deck->getRoot();
|
||||||
for (int i = 0; i < listRoot->size(); i++) {
|
for (const auto innerDecklistNode : *listRoot) {
|
||||||
InnerDecklistNode *currentZone = dynamic_cast<InnerDecklistNode *>(listRoot->at(i));
|
auto *currentZone = dynamic_cast<InnerDecklistNode *>(innerDecklistNode);
|
||||||
|
|
||||||
DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0);
|
DeckViewCardContainer *container = cardContainers.value(currentZone->getName(), 0);
|
||||||
if (!container) {
|
if (!container) {
|
||||||
@@ -349,12 +351,15 @@ void DeckViewScene::rebuildTree()
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < currentZone->size(); j++) {
|
for (int j = 0; j < currentZone->size(); j++) {
|
||||||
DecklistCardNode *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
|
auto *currentCard = dynamic_cast<DecklistCardNode *>(currentZone->at(j));
|
||||||
if (!currentCard)
|
if (!currentCard)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (int k = 0; k < currentCard->getNumber(); ++k) {
|
for (int k = 0; k < currentCard->getNumber(); ++k) {
|
||||||
DeckViewCard *newCard = new DeckViewCard(currentCard->getName(), currentZone->getName(), container);
|
if (++cardsRenderedAlready >= MAX_CARDS_TO_RENDER) {
|
||||||
|
break; // We can't render anymore cards efficiently, evict early
|
||||||
|
}
|
||||||
|
auto *newCard = new DeckViewCard(currentCard->getName(), currentZone->getName(), container);
|
||||||
container->addCard(newCard);
|
container->addCard(newCard);
|
||||||
emit newCardAdded(newCard);
|
emit newCardAdded(newCard);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ signals:
|
|||||||
void sideboardPlanChanged();
|
void sideboardPlanChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr unsigned int MAX_CARDS_TO_RENDER = 300;
|
||||||
bool locked;
|
bool locked;
|
||||||
DeckList *deck;
|
DeckList *deck;
|
||||||
QMap<QString, DeckViewCardContainer *> cardContainers;
|
QMap<QString, DeckViewCardContainer *> cardContainers;
|
||||||
|
|||||||
@@ -804,13 +804,18 @@ void DeckList::updateDeckHash()
|
|||||||
hashZones << DECK_ZONE_MAIN << DECK_ZONE_SIDE; // Zones in deck to be included in hashing process
|
hashZones << DECK_ZONE_MAIN << DECK_ZONE_SIDE; // Zones in deck to be included in hashing process
|
||||||
optionalZones << DECK_ZONE_TOKENS; // Optional zones in deck not included in hashing process
|
optionalZones << DECK_ZONE_TOKENS; // Optional zones in deck not included in hashing process
|
||||||
|
|
||||||
for (int i = 0; i < root->size(); i++) {
|
unsigned int cardsHashedAlready = 0;
|
||||||
auto *node = dynamic_cast<InnerDecklistNode *>(root->at(i));
|
for (auto innerDecklistNode : *root) {
|
||||||
|
auto *node = dynamic_cast<InnerDecklistNode *>(innerDecklistNode);
|
||||||
for (int j = 0; j < node->size(); j++) {
|
for (int j = 0; j < node->size(); j++) {
|
||||||
if (hashZones.contains(node->getName())) // Mainboard or Sideboard
|
if (hashZones.contains(node->getName())) // Mainboard or Sideboard
|
||||||
{
|
{
|
||||||
auto *card = dynamic_cast<DecklistCardNode *>(node->at(j));
|
auto *card = dynamic_cast<DecklistCardNode *>(node->at(j));
|
||||||
for (int k = 0; k < card->getNumber(); ++k) {
|
for (int k = 0; k < card->getNumber(); ++k) {
|
||||||
|
if (++cardsHashedAlready >= MAX_CARDS_TO_HASH) {
|
||||||
|
cardList.clear();
|
||||||
|
break; // We can't efficiently calculate a hash with a larger number
|
||||||
|
}
|
||||||
cardList.append((node->getName() == DECK_ZONE_SIDE ? "SB:" : "") + card->getName().toLower());
|
cardList.append((node->getName() == DECK_ZONE_SIDE ? "SB:" : "") + card->getName().toLower());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,6 +173,7 @@ class DeckList : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
|
static constexpr unsigned int MAX_CARDS_TO_HASH = 100000;
|
||||||
QString name, comments;
|
QString name, comments;
|
||||||
QString deckHash;
|
QString deckHash;
|
||||||
QMap<QString, SideboardPlan *> sideboardPlans;
|
QMap<QString, SideboardPlan *> sideboardPlans;
|
||||||
|
|||||||
Reference in New Issue
Block a user