From 4b9de96a6b80dbbda13f5db68a2b5e9fa448272d Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Wed, 3 Feb 2021 14:23:50 +0400 Subject: [PATCH] Test framework: added support to put mdf cards on battlefield by cheats or unit tests; --- .../client/dialog/TestCardRenderDialog.java | 35 +++++++------ .../test/serverside/base/MageTestBase.java | 10 ++-- .../serverside/base/MageTestPlayerBase.java | 24 +++++---- .../base/impl/CardTestPlayerAPIImpl.java | 9 ++-- .../performance/SerializationTest.java | 10 +++- .../mage/game/permanent/PermanentCard.java | 23 ++++++++- Mage/src/main/java/mage/util/CardUtil.java | 49 +++++++++++++------ 7 files changed, 111 insertions(+), 49 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/dialog/TestCardRenderDialog.java b/Mage.Client/src/main/java/mage/client/dialog/TestCardRenderDialog.java index 977f8ea9cdb..f79e91956c2 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/TestCardRenderDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/TestCardRenderDialog.java @@ -15,10 +15,8 @@ import mage.cards.repository.ExpansionRepository; import mage.client.MageFrame; import mage.client.cards.BigCard; import mage.client.themes.ThemeType; -import mage.client.util.ClientEventType; +import mage.client.util.*; import mage.client.util.Event; -import mage.client.util.GUISizeHelper; -import mage.client.util.Listener; import mage.constants.MultiplayerAttackOption; import mage.constants.RangeOfInfluence; import mage.constants.Zone; @@ -33,6 +31,7 @@ import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; import mage.players.Player; import mage.players.StubPlayer; +import mage.util.CardUtil; import mage.util.RandomUtil; import mage.view.*; import org.apache.log4j.Logger; @@ -107,16 +106,19 @@ public class TestCardRenderDialog extends MageDialog { ExpansionInfo setInfo = ExpansionRepository.instance.getSetByCode(code); CardSetInfo testSet = new CardSetInfo(cardInfo.getName(), setInfo.getCode(), cardNumber, cardInfo.getRarity(), new CardGraphicInfo(cardInfo.getFrameStyle(), cardInfo.usesVariousArt())); - Card card = CardImpl.createCard(cardInfo.getClassName(), testSet); - if (extraAbilities != null) { - extraAbilities.forEach(ability -> card.addAbility(ability)); - } + Card newCard = CardImpl.createCard(cardInfo.getClassName(), testSet); Set cardsList = new HashSet<>(); - cardsList.add(card); + cardsList.add(newCard); game.loadCards(cardsList, controllerId); - PermanentCard perm = new PermanentCard(card, controllerId, game); + Card permCard = CardUtil.getDefaultCardSideForBattlefield(newCard); + + if (extraAbilities != null) { + extraAbilities.forEach(ability -> permCard.addAbility(ability)); + } + + PermanentCard perm = new PermanentCard(permCard, controllerId, game); if (damage > 0) perm.damage(damage, controllerId, null, game); if (power > 0) perm.getPower().setValue(power); if (toughness > 0) perm.getToughness().setValue(toughness); @@ -125,8 +127,7 @@ public class TestCardRenderDialog extends MageDialog { if (perm.isTransformable()) { perm.setTransformed(true); } - PermanentView cardView = new PermanentView(perm, card, controllerId, game); - //cardView.setInViewerOnly(true); + PermanentView cardView = new PermanentView(perm, permCard, controllerId, game); return cardView; } @@ -136,13 +137,15 @@ public class TestCardRenderDialog extends MageDialog { ExpansionInfo setInfo = ExpansionRepository.instance.getSetByCode(code); CardSetInfo testSet = new CardSetInfo(cardInfo.getName(), setInfo.getCode(), cardNumber, cardInfo.getRarity(), new CardGraphicInfo(cardInfo.getFrameStyle(), cardInfo.usesVariousArt())); - Card card = CardImpl.createCard(cardInfo.getClassName(), testSet); + Card newCard = CardImpl.createCard(cardInfo.getClassName(), testSet); Set cardsList = new HashSet<>(); - cardsList.add(card); + cardsList.add(newCard); game.loadCards(cardsList, controllerId); - PermanentCard perm = new PermanentCard(card, controllerId, game); + Card permCard = CardUtil.getDefaultCardSideForBattlefield(newCard); + + PermanentCard perm = new PermanentCard(permCard, controllerId, game); perm.setFaceDown(true, game); perm.setMorphed(isMorphed); perm.setManifested(isManifested); @@ -151,7 +154,7 @@ public class TestCardRenderDialog extends MageDialog { if (perm.isTransformable()) { perm.setTransformed(true); } - PermanentView cardView = new PermanentView(perm, card, controllerId, game); + PermanentView cardView = new PermanentView(perm, permCard, controllerId, game); cardView.setInViewerOnly(false); // must false for face down return cardView; } @@ -293,6 +296,8 @@ public class TestCardRenderDialog extends MageDialog { cardViews.add(createHandCard(game, playerYou.getId(), "DKA", "140")); // Huntmaster of the Fells, transforms cardViews.add(createPermanentCard(game, playerYou.getId(), "MB1", "401", 1, 1, 0, false, additionalIcons)); // Hinterland Drake cardViews.add(createPermanentCard(game, playerYou.getId(), "MB1", "1441", 1, 1, 0, true, additionalIcons)); // Kathari Remnant + cardViews.add(createPermanentCard(game, playerYou.getId(), "KHM", "50", 1, 1, 0, true, additionalIcons)); // Cosima, God of the Voyage + //*/ diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java index 6e1eb646b87..8fa74432277 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java @@ -21,6 +21,7 @@ import mage.server.util.ConfigWrapper; import mage.server.util.PluginClassLoader; import mage.server.util.config.GamePlugin; import mage.server.util.config.Plugin; +import mage.util.CardUtil; import mage.util.Copier; import org.apache.log4j.Level; import org.apache.log4j.Logger; @@ -247,14 +248,15 @@ public abstract class MageTestBase { } else { for (int i = 0; i < amount; i++) { CardInfo cardInfo = CardRepository.instance.findCard(cardName); - Card card = cardInfo != null ? cardInfo.getCard() : null; - if (card != null) { + Card newCard = cardInfo != null ? cardInfo.getCard() : null; + if (newCard != null) { if (gameZone == Zone.BATTLEFIELD) { - PermanentCard p = new PermanentCard(card, null, currentGame); + Card permCard = CardUtil.getDefaultCardSideForBattlefield(newCard); + PermanentCard p = new PermanentCard(permCard, null, currentGame); p.setTapped(tapped); perms.add(p); } else { - cards.add(card); + cards.add(newCard); } } else { logger.fatal("Couldn't find a card: " + cardName); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java index 46f26fe5126..1ed6be9e9cd 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java @@ -33,6 +33,7 @@ import mage.server.util.PluginClassLoader; import mage.server.util.config.GamePlugin; import mage.server.util.config.Plugin; import mage.target.common.TargetAnyTarget; +import mage.util.CardUtil; import mage.util.Copier; import org.apache.log4j.Level; import org.apache.log4j.Logger; @@ -250,14 +251,15 @@ public abstract class MageTestPlayerBase { } else { for (int i = 0; i < amount; i++) { CardInfo cardInfo = CardRepository.instance.findCard(cardName); - Card card = cardInfo != null ? cardInfo.getCard() : null; - if (card != null) { + Card newCard = cardInfo != null ? cardInfo.getCard() : null; + if (newCard != null) { if (gameZone == Zone.BATTLEFIELD) { - PermanentCard p = new PermanentCard(card, null, currentGame); + Card permCard = CardUtil.getDefaultCardSideForBattlefield(newCard); + PermanentCard p = new PermanentCard(permCard, null, currentGame); p.setTapped(tapped); perms.add(p); } else { - cards.add(card); + cards.add(newCard); } } else { logger.fatal("Couldn't find a card: " + cardName); @@ -404,23 +406,25 @@ public abstract class MageTestPlayerBase { CustomTestCard.addAdditionalSubtypes(customName, additionalSubTypes); CardSetInfo testSet = new CardSetInfo(customName, "custom", "123", Rarity.COMMON); - PermanentCard card = new PermanentCard(new CustomTestCard(controllerPlayer.getId(), testSet, cardType, spellCost), controllerPlayer.getId(), currentGame); + Card newCard = new CustomTestCard(controllerPlayer.getId(), testSet, cardType, spellCost); + Card permCard = CardUtil.getDefaultCardSideForBattlefield(newCard); + PermanentCard permanent = new PermanentCard(permCard, controllerPlayer.getId(), currentGame); switch (putAtZone) { case BATTLEFIELD: - getBattlefieldCards(controllerPlayer).add(card); + getBattlefieldCards(controllerPlayer).add(permanent); break; case GRAVEYARD: - getGraveCards(controllerPlayer).add(card); + getGraveCards(controllerPlayer).add(newCard); break; case HAND: - getHandCards(controllerPlayer).add(card); + getHandCards(controllerPlayer).add(newCard); break; case LIBRARY: - getLibraryCards(controllerPlayer).add(card); + getLibraryCards(controllerPlayer).add(newCard); break; case COMMAND: - getCommandCards(controllerPlayer).add(card); + getCommandCards(controllerPlayer).add(newCard); break; default: Assert.fail("Unsupported zone: " + putAtZone); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index 20e6d2f2a55..8b7cd2895b1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -655,11 +655,14 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement if (gameZone == Zone.BATTLEFIELD) { for (int i = 0; i < count; i++) { CardInfo cardInfo = CardRepository.instance.findCard(cardName); - Card card = cardInfo != null ? cardInfo.getCard() : null; - if (card == null) { + Card newCard = cardInfo != null ? cardInfo.getCard() : null; + if (newCard == null) { throw new IllegalArgumentException("[TEST] Couldn't find a card: " + cardName); } - PermanentCard p = new PermanentCard(card.copy(), player.getId(), currentGame); + + Card permCard = CardUtil.getDefaultCardSideForBattlefield(newCard); + + PermanentCard p = new PermanentCard(permCard, player.getId(), currentGame); p.setTapped(tapped); getBattlefieldCards(player).add(p); diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/performance/SerializationTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/performance/SerializationTest.java index de21c8e3836..75f77d6bff6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/performance/SerializationTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/performance/SerializationTest.java @@ -1,6 +1,7 @@ package org.mage.test.serverside.performance; import mage.abilities.keyword.InfectAbility; +import mage.cards.Card; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.constants.PhaseStep; @@ -11,6 +12,7 @@ import mage.game.mulligan.LondonMulligan; import mage.game.permanent.PermanentCard; import mage.game.permanent.PermanentImpl; import mage.remote.traffic.ZippedObjectImpl; +import mage.util.CardUtil; import mage.utils.CompressUtil; import org.junit.Assert; import org.junit.Test; @@ -24,7 +26,9 @@ public class SerializationTest extends CardTestPlayerBase { @Test public void test_PermanentImpl_Simple() { CardInfo cardInfo = CardRepository.instance.findCard("Balduvian Bears"); - PermanentImpl permanent = new PermanentCard(cardInfo.getCard(), playerA.getId(), currentGame); + Card newCard = cardInfo.getCard(); + Card permCard = CardUtil.getDefaultCardSideForBattlefield(newCard); + PermanentImpl permanent = new PermanentCard(permCard, playerA.getId(), currentGame); currentGame.addPermanent(permanent, 0); Object compressed = CompressUtil.compress(permanent); @@ -36,7 +40,9 @@ public class SerializationTest extends CardTestPlayerBase { @Test public void test_PermanentImpl_MarkedDamageInfo() { CardInfo cardInfo = CardRepository.instance.findCard("Balduvian Bears"); - PermanentImpl permanent = new PermanentCard(cardInfo.getCard(), playerA.getId(), currentGame); + Card newCard = cardInfo.getCard(); + Card permCard = CardUtil.getDefaultCardSideForBattlefield(newCard); + PermanentImpl permanent = new PermanentCard(permCard, playerA.getId(), currentGame); currentGame.addPermanent(permanent, 0); // mark damage from infected ability diff --git a/Mage/src/main/java/mage/game/permanent/PermanentCard.java b/Mage/src/main/java/mage/game/permanent/PermanentCard.java index 9952b2a2552..3366c8784e6 100644 --- a/Mage/src/main/java/mage/game/permanent/PermanentCard.java +++ b/Mage/src/main/java/mage/game/permanent/PermanentCard.java @@ -8,15 +8,20 @@ import mage.abilities.costs.mana.ManaCosts; import mage.abilities.keyword.TransformAbility; import mage.cards.Card; import mage.cards.LevelerCard; +import mage.cards.ModalDoubleFacesCard; +import mage.cards.SplitCard; +import mage.constants.SpellAbilityType; import mage.game.Game; import mage.game.events.ZoneChangeEvent; -import mage.util.CardUtil; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import java.util.UUID; /** + * Static permanent on the battlefield. There are possible multiple permanents per one card, + * so be carefull for targets (ids are different) and ZCC (zcc is static for permanent). + * * @author BetaSteward_at_googlemail.com */ @SupportedSourceVersion(SourceVersion.RELEASE_8) @@ -31,6 +36,22 @@ public class PermanentCard extends PermanentImpl { public PermanentCard(Card card, UUID controllerId, Game game) { super(card.getId(), card.getOwnerId(), controllerId, card.getName()); + // usage check: you must put to play only real card's part + // if you use it in test code then call CardUtil.getDefaultCardSideForBattlefield for default side + // it's a basic check and still allows to create permanent from instant or sorcery + boolean goodForBattlefield = true; + if (card instanceof ModalDoubleFacesCard) { + goodForBattlefield = false; + } else if (card instanceof SplitCard) { + // fused spells allowed (it uses main card) + if (card.getSpellAbility() != null && !card.getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)) { + goodForBattlefield = false; + } + } + if (!goodForBattlefield) { + throw new IllegalArgumentException("ERROR, can't create permanent card from split or mdf: " + card.getName()); + } + this.card = card; this.zoneChangeCounter = card.getZoneChangeCounter(game); // local value already set to the raised number init(card, game); diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 5a4894e005e..74f777ec55e 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -15,10 +15,7 @@ import mage.abilities.effects.common.asthought.CanPlayCardControllerEffect; import mage.abilities.effects.common.asthought.YouMaySpendManaAsAnyColorToCastTargetEffect; import mage.abilities.hint.Hint; import mage.abilities.hint.HintUtils; -import mage.cards.Card; -import mage.cards.MeldCard; -import mage.cards.ModalDoubleFacesCard; -import mage.cards.SplitCard; +import mage.cards.*; import mage.constants.*; import mage.filter.Filter; import mage.filter.predicate.mageobject.NamePredicate; @@ -896,33 +893,36 @@ public final class CardUtil { /** * Put card to battlefield without resolve (for cheats and tests only) * - * @param source must be non null (if you need it empty then use fakeSourceAbility) + * @param source must be non null (if you need it empty then use fakeSourceAbility) * @param game - * @param card + * @param newCard * @param player */ - public static void putCardOntoBattlefieldWithEffects(Ability source, Game game, Card card, Player player) { + public static void putCardOntoBattlefieldWithEffects(Ability source, Game game, Card newCard, Player player) { // same logic as ZonesHandler->maybeRemoveFromSourceZone + // workaround to put real permanent from one side (example: you call mdf card by cheats) + Card permCard = getDefaultCardSideForBattlefield(newCard); + // prepare card and permanent - card.setZone(Zone.BATTLEFIELD, game); - card.setOwnerId(player.getId()); + permCard.setZone(Zone.BATTLEFIELD, game); + permCard.setOwnerId(player.getId()); PermanentCard permanent; - if (card instanceof MeldCard) { - permanent = new PermanentMeld(card, player.getId(), game); + if (permCard instanceof MeldCard) { + permanent = new PermanentMeld(permCard, player.getId(), game); } else { - permanent = new PermanentCard(card, player.getId(), game); + permanent = new PermanentCard(permCard, player.getId(), game); } // put onto battlefield with possible counters game.getPermanentsEntering().put(permanent.getId(), permanent); - card.checkForCountersToAdd(permanent, source, game); + permCard.checkForCountersToAdd(permanent, source, game); permanent.entersBattlefield(source, game, Zone.OUTSIDE, false); game.addPermanent(permanent, game.getState().getNextPermanentOrderNumber()); game.getPermanentsEntering().remove(permanent.getId()); // workaround for special tapped status from test framework's command (addCard) - if (card instanceof PermanentCard && ((PermanentCard) card).isTapped()) { + if (permCard instanceof PermanentCard && ((PermanentCard) permCard).isTapped()) { permanent.setTapped(true); } @@ -938,6 +938,27 @@ public final class CardUtil { } } + /** + * Choose default card's part to put on battlefield (for cheats and tests only) + * + * @param card + * @return + */ + public static Card getDefaultCardSideForBattlefield(Card card) { + // chose left side all time + Card permCard; + if (card instanceof SplitCard) { + permCard = card; + } else if (card instanceof AdventureCard) { + permCard = card; + } else if (card instanceof ModalDoubleFacesCard) { + permCard = ((ModalDoubleFacesCard) card).getLeftHalfCard(); + } else { + permCard = card; + } + return permCard; + } + /** * Return card name for same name searching *