From 78071ce0a3e4d58979e600109fbb18ed0763b297 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 25 Aug 2015 23:34:15 +0200 Subject: [PATCH] * Fixed a bug that order of triggered abilities of tokens were not shown to human player and the UI was locked (fixes #910). --- Mage.Common/src/mage/view/CardsView.java | 3 + .../java/mage/server/game/GameController.java | 3 +- .../mage/sets/tenthedition/VenerableMonk.java | 6 +- .../mage/sets/zendikar/RiteOfReplication.java | 9 ++- .../cards/replacement/DoublingSeasonTest.java | 61 ++++++++++++++++--- 5 files changed, 65 insertions(+), 17 deletions(-) diff --git a/Mage.Common/src/mage/view/CardsView.java b/Mage.Common/src/mage/view/CardsView.java index 4a7ee78da5..606918a3ee 100644 --- a/Mage.Common/src/mage/view/CardsView.java +++ b/Mage.Common/src/mage/view/CardsView.java @@ -89,6 +89,9 @@ public class CardsView extends LinkedHashMap { case EXILED: case GRAVEYARD: sourceObject = game.getCard(ability.getSourceId()); + if (sourceObject == null) { + sourceObject = game.getPermanent(ability.getSourceId()); + } isCard = true; break; case BATTLEFIELD: diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index 07ed9e64e9..5242a01961 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -846,7 +846,8 @@ public class GameController implements GameCallback { perform(playerId, new Command() { @Override public void execute(UUID playerId) { - getGameSession(playerId).target(question, new CardsView(abilities, game), null, required, options); + CardsView cardsView = new CardsView(abilities, game); + getGameSession(playerId).target(question, cardsView, null, required, options); } }); } diff --git a/Mage.Sets/src/mage/sets/tenthedition/VenerableMonk.java b/Mage.Sets/src/mage/sets/tenthedition/VenerableMonk.java index 5b46688a5c..34c8825469 100644 --- a/Mage.Sets/src/mage/sets/tenthedition/VenerableMonk.java +++ b/Mage.Sets/src/mage/sets/tenthedition/VenerableMonk.java @@ -28,12 +28,12 @@ package mage.sets.tenthedition; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Rarity; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Rarity; /** * @@ -50,6 +50,8 @@ public class VenerableMonk extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(2); + + // When Venerable Monk enters the battlefield, you gain 2 life. this.addAbility(new EntersBattlefieldTriggeredAbility(new GainLifeEffect(2))); } diff --git a/Mage.Sets/src/mage/sets/zendikar/RiteOfReplication.java b/Mage.Sets/src/mage/sets/zendikar/RiteOfReplication.java index 328c65228a..fd51ca2ee7 100644 --- a/Mage.Sets/src/mage/sets/zendikar/RiteOfReplication.java +++ b/Mage.Sets/src/mage/sets/zendikar/RiteOfReplication.java @@ -28,16 +28,16 @@ package mage.sets.zendikar; import java.util.UUID; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.condition.common.KickedCondition; import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.KickerAbility; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.game.permanent.token.EmptyToken; @@ -54,7 +54,6 @@ public class RiteOfReplication extends CardImpl { super(ownerId, 61, "Rite of Replication", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{2}{U}{U}"); this.expansionSetCode = "ZEN"; - // Kicker {5} this.addAbility(new KickerAbility("{5}")); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java index e1cb48a3b5..677561abbc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/DoublingSeasonTest.java @@ -7,17 +7,19 @@ import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; /** - * Doubling Season: - * If an effect would put one or more tokens onto the battlefield under your control, it puts twice that many of those tokens onto the battlefield instead. - * If an effect would place one or more counters on a permanent you control, it places twice that many of those counters on that permanent instead. + * Doubling Season: If an effect would put one or more tokens onto the + * battlefield under your control, it puts twice that many of those tokens onto + * the battlefield instead. If an effect would place one or more counters on a + * permanent you control, it places twice that many of those counters on that + * permanent instead. * * @author LevelX2 */ public class DoublingSeasonTest extends CardTestPlayerBase { /** - * Tests that instead of one spore counter there were two spore counters added to Pallid Mycoderm - * if Doubling Season is on the battlefield. + * Tests that instead of one spore counter there were two spore counters + * added to Pallid Mycoderm if Doubling Season is on the battlefield. */ @Test public void testDoubleSporeCounter() { @@ -35,8 +37,9 @@ public class DoublingSeasonTest extends CardTestPlayerBase { } /** - * Tests if 3 damage are prevented with Test of Faith and Doubling Season is on - * the battlefield, that 6 +1/+1 counters are added to the target creature. + * Tests if 3 damage are prevented with Test of Faith and Doubling Season is + * on the battlefield, that 6 +1/+1 counters are added to the target + * creature. */ @Test public void testDoubleP1P1Counter() { @@ -63,9 +66,10 @@ public class DoublingSeasonTest extends CardTestPlayerBase { assertPowerToughness(playerA, "Silvercoat Lion", 8, 8); } + /** - * Tests that 2 Saproling tokens are created instead of one if Doubling Season is on - * the battlefield. + * Tests that 2 Saproling tokens are created instead of one if Doubling + * Season is on the battlefield. */ @Test public void testDoubleTokens() { @@ -89,4 +93,43 @@ public class DoublingSeasonTest extends CardTestPlayerBase { } + /** + * Creatures with enter the battlefield triggers are causing a bug when + * multiple copies are made simultaneously (ie via Doubling Season + + * Kiki-Jiki, Mirror Breaker or Rite of Replication). After the tokens have + * entered the battlefield it asks their controller to choose the order that + * the triggered abilities on the stack but no window opens to select the + * triggers leaving no option to move the game forward (besides rollback and + * just not making the tokens). Several attempts with the different + * combinations make it *seem to be a general bug about duplicates entering + * at the same time and not related to the specific cards. + */ + @Test + public void testDoubleRiteOfReplication() { + /** + * If an effect would put one or more tokens onto the battlefield under + * your control, it puts twice that many of those tokens onto the + * battlefield instead. If an effect would place one or more counters on + * a permanent you control, it places twice that many of those counters + * on that permanent instead. + */ + + addCard(Zone.BATTLEFIELD, playerA, "Doubling Season"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 9); + + // Put a token that's a copy of target creature onto the battlefield. If Rite of Replication was kicked, put five of those tokens onto the battlefield instead. + addCard(Zone.HAND, playerA, "Rite of Replication"); + // When Venerable Monk enters the battlefield, you gain 2 life. + addCard(Zone.BATTLEFIELD, playerB, "Venerable Monk", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rite of Replication", "Venerable Monk"); + setChoice(playerA, "Yes"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 40); + assertPermanentCount(playerA, "Venerable Monk", 10); + + } }