diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java index 5459acab7b0..33f70ceb3c6 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/ComputerPlayer6.java @@ -398,7 +398,10 @@ public class ComputerPlayer6 extends ComputerPlayer { } protected void resolve(SimulationNode2 node, int depth, Game game) { - StackObject stackObject = game.getStack().getFirst(); + StackObject stackObject = game.getStack().getFirstOrNull(); + if (stackObject == null) { + throw new IllegalStateException("Catch empty stack on resolve (something wrong with sim code)"); + } if (stackObject instanceof StackAbility) { // AI hint for search effects (calc all possible cards for best score) SearchEffect effect = getSearchEffect((StackAbility) stackObject); diff --git a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java index 6a0fbc550b8..0b3e78aa195 100644 --- a/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human/HumanPlayer.java @@ -638,8 +638,8 @@ public class HumanPlayer extends PlayerImpl { // Check check if the spell being paid for cares about the color of mana being paid // See: https://github.com/magefree/mage/issues/9070 boolean caresAboutManaColor = false; - if (!game.getStack().isEmpty() && game.getStack().getFirst() instanceof Spell) { - Spell spellBeingCast = (Spell) game.getStack().getFirst(); + if (game.getStack().getFirstOrNull() instanceof Spell) { + Spell spellBeingCast = (Spell) game.getStack().getFirstOrNull(); if (!spellBeingCast.isResolving() && spellBeingCast.getControllerId().equals(this.getId())) { CardImpl card = (CardImpl) game.getCard(spellBeingCast.getSourceId()); caresAboutManaColor = card.caresAboutManaColor(game); diff --git a/Mage.Sets/src/mage/cards/a/AstralDrift.java b/Mage.Sets/src/mage/cards/a/AstralDrift.java index e181fee3284..72c5956fbdd 100644 --- a/Mage.Sets/src/mage/cards/a/AstralDrift.java +++ b/Mage.Sets/src/mage/cards/a/AstralDrift.java @@ -68,10 +68,7 @@ class AstralDriftTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getState().getStack().isEmpty()) { - return false; - } - StackObject item = game.getState().getStack().getFirst(); + StackObject item = game.getState().getStack().getFirstOrNull(); if (!(item instanceof StackAbility && item.getStackAbility() instanceof CyclingAbility)) { return false; diff --git a/Mage.Sets/src/mage/cards/c/CobraTrap.java b/Mage.Sets/src/mage/cards/c/CobraTrap.java index 90ec0240ab8..99cd7e9cd7f 100644 --- a/Mage.Sets/src/mage/cards/c/CobraTrap.java +++ b/Mage.Sets/src/mage/cards/c/CobraTrap.java @@ -78,11 +78,9 @@ class CobraTrapWatcher extends Watcher { if (event.getType() == GameEvent.EventType.DESTROYED_PERMANENT) { Permanent perm = game.getPermanentOrLKIBattlefield(event.getTargetId()); // can regenerate or be indestructible if (perm != null && !perm.isCreature(game)) { - if (!game.getStack().isEmpty()) { - StackObject spell = game.getStack().getStackObject(event.getSourceId()); - if (spell != null && game.getOpponents(perm.getControllerId()).contains(spell.getControllerId())) { - players.add(perm.getControllerId()); - } + StackObject spell = game.getStack().getStackObject(event.getSourceId()); + if (spell != null && game.getOpponents(perm.getControllerId()).contains(spell.getControllerId())) { + players.add(perm.getControllerId()); } } } diff --git a/Mage.Sets/src/mage/cards/r/RainOfGore.java b/Mage.Sets/src/mage/cards/r/RainOfGore.java index dc769b3a515..32c46e62b10 100644 --- a/Mage.Sets/src/mage/cards/r/RainOfGore.java +++ b/Mage.Sets/src/mage/cards/r/RainOfGore.java @@ -1,7 +1,5 @@ - package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ReplacementEffectImpl; @@ -10,20 +8,20 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; -import mage.constants.Zone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.StackObject; import mage.players.Player; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class RainOfGore extends CardImpl { public RainOfGore(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{B}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{R}"); // If a spell or ability would cause its controller to gain life, that player loses that much life instead. @@ -71,13 +69,10 @@ class RainOfGoreEffect extends ReplacementEffectImpl { public boolean checksEventType(GameEvent event, Game game) { return event.getType() == GameEvent.EventType.GAIN_LIFE; } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (!game.getStack().isEmpty()) { - StackObject stackObject = game.getStack().getFirst(); - return stackObject.isControlledBy(event.getPlayerId()); - } - return false; + StackObject stackObject = game.getStack().getFirstOrNull(); + return stackObject != null && stackObject.isControlledBy(event.getPlayerId()); } } diff --git a/Mage.Sets/src/mage/cards/s/SoulSculptor.java b/Mage.Sets/src/mage/cards/s/SoulSculptor.java index d0ab23a7962..3e4a46d323d 100644 --- a/Mage.Sets/src/mage/cards/s/SoulSculptor.java +++ b/Mage.Sets/src/mage/cards/s/SoulSculptor.java @@ -120,13 +120,8 @@ enum SoulSculptorCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - if (!game.getStack().isEmpty()) { - StackObject stackObject = game.getStack().getFirst(); - if (stackObject != null) { - return !stackObject.getCardType(game).contains(CardType.CREATURE); - } - } - return true; + StackObject stackObject = game.getStack().getFirstOrNull(); + return stackObject != null && !stackObject.getCardType(game).contains(CardType.CREATURE); } @Override diff --git a/Mage.Sets/src/mage/cards/s/SoulfireGrandMaster.java b/Mage.Sets/src/mage/cards/s/SoulfireGrandMaster.java index b6e6f71b085..2f8db38d4a6 100644 --- a/Mage.Sets/src/mage/cards/s/SoulfireGrandMaster.java +++ b/Mage.Sets/src/mage/cards/s/SoulfireGrandMaster.java @@ -21,6 +21,7 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.game.stack.Spell; +import mage.game.stack.StackObject; import mage.players.Player; import java.util.UUID; @@ -94,18 +95,22 @@ class SoulfireGrandMasterCastFromHandReplacementEffect extends ReplacementEffect @Override public boolean replaceEvent(GameEvent event, Ability source, Game game) { - Spell spell = (Spell) game.getStack().getFirst(); - if (!spell.isCopy() && !spell.isCountered()) { - Card sourceCard = game.getCard(spellId); - if (sourceCard != null && Zone.STACK.equals(game.getState().getZone(spellId))) { - Player player = game.getPlayer(sourceCard.getOwnerId()); - if (player != null) { - player.moveCards(sourceCard, Zone.HAND, source, game); - discard(); - return true; + StackObject stackObject = game.getStack().getFirstOrNull(); + if (stackObject instanceof Spell) { + Spell spell = (Spell) stackObject; + if (!spell.isCopy() && !spell.isCountered()) { + Card sourceCard = game.getCard(spellId); + if (sourceCard != null && Zone.STACK.equals(game.getState().getZone(spellId))) { + Player player = game.getPlayer(sourceCard.getOwnerId()); + if (player != null) { + player.moveCards(sourceCard, Zone.HAND, source, game); + discard(); + return true; + } } } } + return false; } @@ -134,8 +139,8 @@ class SoulfireGrandMasterCastFromHandReplacementEffect extends ReplacementEffect if (zEvent.getFromZone() == Zone.STACK && zEvent.getToZone() == Zone.GRAVEYARD && event.getTargetId().equals(spellId)) { - if (game.getStack().getFirst() instanceof Spell) { - Card cardOfSpell = ((Spell) game.getStack().getFirst()).getCard(); + if (game.getStack().getFirstOrNull() instanceof Spell) { + Card cardOfSpell = ((Spell) game.getStack().getFirstOrNull()).getCard(); return cardOfSpell.getMainCard().getId().equals(spellId); } } diff --git a/Mage.Sets/src/mage/cards/t/TheTwelfthDoctor.java b/Mage.Sets/src/mage/cards/t/TheTwelfthDoctor.java index cea349b3b7e..b1359692b74 100644 --- a/Mage.Sets/src/mage/cards/t/TheTwelfthDoctor.java +++ b/Mage.Sets/src/mage/cards/t/TheTwelfthDoctor.java @@ -99,12 +99,10 @@ enum FirstSpellCastFromNotHandEachTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - if (game.getStack().isEmpty()) { - return false; - } TheTwelfthDoctorWatcher watcher = game.getState().getWatcher(TheTwelfthDoctorWatcher.class); - StackObject so = game.getStack().getFirst(); - return watcher != null + StackObject so = game.getStack().getFirstOrNull(); + return so != null + && watcher != null && TheTwelfthDoctorWatcher.checkSpell(so, game); } } diff --git a/Mage.Sets/src/mage/cards/v/ValiantRescuer.java b/Mage.Sets/src/mage/cards/v/ValiantRescuer.java index 6c1c956bf92..31a9b48f47c 100644 --- a/Mage.Sets/src/mage/cards/v/ValiantRescuer.java +++ b/Mage.Sets/src/mage/cards/v/ValiantRescuer.java @@ -74,12 +74,11 @@ class ValiantRescuerTriggeredAbility extends TriggeredAbilityImpl { ValiantRescuerWatcher watcher = game.getState().getWatcher(ValiantRescuerWatcher.class); if (watcher == null || !watcher.checkSpell(event.getPlayerId(), event.getSourceId()) - || game.getState().getStack().isEmpty() || !event.getPlayerId().equals(this.getControllerId()) || event.getSourceId().equals(this.getSourceId())) { return false; } - StackObject item = game.getState().getStack().getFirst(); + StackObject item = game.getState().getStack().getFirstOrNull(); return item instanceof StackAbility && item.getStackAbility() instanceof CyclingAbility; } @@ -106,11 +105,10 @@ class ValiantRescuerWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (event.getType() != GameEvent.EventType.ACTIVATED_ABILITY - || game.getState().getStack().isEmpty()) { + if (event.getType() != GameEvent.EventType.ACTIVATED_ABILITY) { return; } - StackObject item = game.getState().getStack().getFirst(); + StackObject item = game.getState().getStack().getFirstOrNull(); if (item instanceof StackAbility && item.getStackAbility() instanceof CyclingAbility) { playerMap.computeIfAbsent(event.getPlayerId(), u -> new HashMap<>()); diff --git a/Mage.Sets/src/mage/cards/w/WildMagicSorcerer.java b/Mage.Sets/src/mage/cards/w/WildMagicSorcerer.java index f91d13843b2..dc97b1e7937 100644 --- a/Mage.Sets/src/mage/cards/w/WildMagicSorcerer.java +++ b/Mage.Sets/src/mage/cards/w/WildMagicSorcerer.java @@ -2,7 +2,10 @@ package mage.cards.w; import mage.MageInt; import mage.MageObjectReference; +import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.Condition; +import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.keyword.CascadeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -11,14 +14,12 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.stack.Spell; import mage.game.stack.StackObject; +import mage.players.Player; import mage.watchers.Watcher; + import java.util.HashMap; import java.util.Map; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.condition.Condition; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.players.Player; /** * @author TheElk801 @@ -35,7 +36,7 @@ public final class WildMagicSorcerer extends CardImpl { // The first spell you cast from exile each turn has cascade. this.addAbility(new SimpleStaticAbility( - new WildMagicSorcererGainCascadeFirstSpellCastFromExileEffect()), + new WildMagicSorcererGainCascadeFirstSpellCastFromExileEffect()), new WildMagicSorcererWatcher()); } @@ -96,12 +97,10 @@ enum FirstSpellCastFromExileEachTurnCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - if (game.getStack().isEmpty()) { - return false; - } WildMagicSorcererWatcher watcher = game.getState().getWatcher(WildMagicSorcererWatcher.class); - StackObject so = game.getStack().getFirst(); - return watcher != null + StackObject so = game.getStack().getFirstOrNull(); + return so != null + && watcher != null && WildMagicSorcererWatcher.checkSpell(so, game); } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DisguiseTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DisguiseTest.java index 3ad59bf8d70..15afb526c3a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DisguiseTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DisguiseTest.java @@ -55,7 +55,7 @@ public class DisguiseTest extends CardTestPlayerBase { castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dog Walker using Disguise"); runCode("face up on stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { Assert.assertEquals("stack, server - can't find spell", 1, currentGame.getStack().size()); - SpellAbility spellAbility = (SpellAbility) currentGame.getStack().getFirst().getStackAbility(); + SpellAbility spellAbility = (SpellAbility) currentGame.getStack().getFirstOrNull().getStackAbility(); Assert.assertEquals("stack, server - can't find spell", "Cast Dog Walker using Disguise", spellAbility.getName()); CardView spellView = getGameView(playerA).getStack().values().stream().findFirst().orElse(null); Assert.assertNotNull("stack, client: can't find spell", spellView); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DisturbTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DisturbTest.java index 31c9ba2e104..9bc7356225d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DisturbTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DisturbTest.java @@ -40,7 +40,7 @@ public class DisturbTest extends CardTestPlayerBase { checkStackObject("on stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hook-Haunt Drifter using Disturb", 1); runCode("check stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { // Stack must contain another card side, so spell/card characteristics must be diff from main side (only mana value is same) - Spell spell = (Spell) game.getStack().getFirst(); + Spell spell = (Spell) game.getStack().getFirstOrNull(); Assert.assertEquals("Hook-Haunt Drifter", spell.getName()); Assert.assertEquals(1, spell.getCardType(game).size()); Assert.assertEquals(CardType.CREATURE, spell.getCardType(game).get(0)); @@ -91,7 +91,7 @@ public class DisturbTest extends CardTestPlayerBase { checkStackObject("on stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Waildrifter using Disturb", 1); runCode("check stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { // Stack must contain another card side, so spell/card characteristics must be diff from main side (only mana value is same) - Spell spell = (Spell) game.getStack().getFirst(); + Spell spell = (Spell) game.getStack().getFirstOrNull(); Assert.assertEquals("Waildrifter", spell.getName()); Assert.assertEquals(1, spell.getCardType(game).size()); Assert.assertEquals(CardType.CREATURE, spell.getCardType(game).get(0)); @@ -187,7 +187,7 @@ public class DisturbTest extends CardTestPlayerBase { // cast with disturb activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Hook-Haunt Drifter using Disturb"); runCode("check stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> { - Spell spell = (Spell) game.getStack().getFirst(); + Spell spell = (Spell) game.getStack().getFirstOrNull(); Assert.assertEquals("mana value must be from main side", 2, spell.getManaValue()); Assert.assertEquals("mana cost to pay must be modified", "{U}", spell.getSpellAbility().getManaCostsToPay().getText()); }); diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 7d322a5f17f..ecc88c66b35 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -334,11 +334,8 @@ public class TestPlayer implements Player { return true; } else if (groups[2].startsWith("spellOnTopOfStack=")) { String spellOnTopOFStack = groups[2].substring(18); - if (!game.getStack().isEmpty()) { - StackObject stackObject = game.getStack().getFirst(); - return stackObject != null && stackObject.getStackAbility().toString().contains(spellOnTopOFStack); - } - return false; + StackObject stackObject = game.getStack().getFirstOrNull(); + return stackObject != null && stackObject.getStackAbility().toString().contains(spellOnTopOFStack); } else if (groups[2].startsWith("manaInPool=")) { String manaInPool = groups[2].substring(11); int amountOfMana = Integer.parseInt(manaInPool); diff --git a/Mage/src/main/java/mage/abilities/SpecialAction.java b/Mage/src/main/java/mage/abilities/SpecialAction.java index ea17f671cc5..911e074c6e5 100644 --- a/Mage/src/main/java/mage/abilities/SpecialAction.java +++ b/Mage/src/main/java/mage/abilities/SpecialAction.java @@ -53,11 +53,9 @@ public abstract class SpecialAction extends ActivatedAbilityImpl { if (isManaAction()) { // limit play mana abilities by steps int currentStepOrder = 0; - if (!game.getStack().isEmpty()) { - StackObject stackObject = game.getStack().getFirst(); - if (stackObject instanceof Spell) { - currentStepOrder = ((Spell) stackObject).getCurrentActivatingManaAbilitiesStep().getStepOrder(); - } + StackObject stackObject = game.getStack().getFirstOrNull(); + if (stackObject instanceof Spell) { + currentStepOrder = ((Spell) stackObject).getCurrentActivatingManaAbilitiesStep().getStepOrder(); } if (currentStepOrder > manaAbility.useOnActivationManaAbilityStep().getStepOrder()) { return ActivationStatus.getFalse(); diff --git a/Mage/src/main/java/mage/abilities/common/CycleAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/CycleAllTriggeredAbility.java index 7621d355e6d..51762197c1b 100644 --- a/Mage/src/main/java/mage/abilities/common/CycleAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/CycleAllTriggeredAbility.java @@ -31,10 +31,7 @@ public class CycleAllTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getState().getStack().isEmpty()) { - return false; - } - StackObject item = game.getState().getStack().getFirst(); + StackObject item = game.getState().getStack().getFirstOrNull(); return item instanceof StackAbility && item.getStackAbility() instanceof CyclingAbility; } diff --git a/Mage/src/main/java/mage/abilities/common/CycleControllerTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/CycleControllerTriggeredAbility.java index ba2fe63e01e..3154476911a 100644 --- a/Mage/src/main/java/mage/abilities/common/CycleControllerTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/CycleControllerTriggeredAbility.java @@ -42,12 +42,11 @@ public class CycleControllerTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - if (game.getState().getStack().isEmpty() - || !event.getPlayerId().equals(this.getControllerId()) + if (!event.getPlayerId().equals(this.getControllerId()) || (event.getSourceId().equals(this.getSourceId()) && excludeSource)) { return false; } - StackObject item = game.getState().getStack().getFirst(); + StackObject item = game.getState().getStack().getFirstOrNull(); return item instanceof StackAbility && item.getStackAbility() instanceof CyclingAbility; } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SunburstCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SunburstCount.java index db83fe6837e..0303cfe132b 100644 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/SunburstCount.java +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/SunburstCount.java @@ -18,25 +18,24 @@ public enum SunburstCount implements DynamicValue { @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { int count = 0; - if (!game.getStack().isEmpty()) { - StackObject spell = game.getStack().getFirst(); - if (spell instanceof Spell && ((Spell) spell).getSourceId().equals(sourceAbility.getSourceId())) { - Mana mana = ((Spell) spell).getSpellAbility().getManaCostsToPay().getUsedManaToPay(); - if (mana.getBlack() > 0) { - count++; - } - if (mana.getBlue() > 0) { - count++; - } - if (mana.getGreen() > 0) { - count++; - } - if (mana.getRed() > 0) { - count++; - } - if (mana.getWhite() > 0) { - count++; - } + + StackObject spell = game.getStack().getFirstOrNull(); + if (spell instanceof Spell && spell.getSourceId().equals(sourceAbility.getSourceId())) { + Mana mana = ((Spell) spell).getSpellAbility().getManaCostsToPay().getUsedManaToPay(); + if (mana.getBlack() > 0) { + count++; + } + if (mana.getBlue() > 0) { + count++; + } + if (mana.getGreen() > 0) { + count++; + } + if (mana.getRed() > 0) { + count++; + } + if (mana.getWhite() > 0) { + count++; } } return count; diff --git a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java index 7db5097dcc8..0f9f25acc3a 100644 --- a/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java +++ b/Mage/src/main/java/mage/abilities/effects/ContinuousEffectImpl.java @@ -513,13 +513,10 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu // If the top card of your library changes while you’re casting a spell, playing a land, or activating an ability, // you can’t look at the new top card until you finish doing so. This means that if you cast the top card of // your library, you can’t look at the next one until you’re done paying for that spell. (2019-05-03) - if (!game.getStack().isEmpty()) { - StackObject stackObject = game.getStack().getFirst(); - return !(stackObject instanceof Spell) - || !Zone.LIBRARY.equals(((Spell) stackObject).getFromZone()) - || stackObject.getStackAbility().getManaCostsToPay().isPaid(); // mana payment finished - } - return true; + StackObject stackObject = game.getStack().getFirstOrNull(); + return !(stackObject instanceof Spell) + || !Zone.LIBRARY.equals(((Spell) stackObject).getFromZone()) + || stackObject.getStackAbility().getManaCostsToPay().isPaid(); // mana payment finished } @Override diff --git a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java index 9e9b2f9ead3..ce1a111e405 100644 --- a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java @@ -44,19 +44,16 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl public ActivationStatus canActivate(UUID playerId, Game game) { // check if player is in the process of playing spell costs and they are no longer allowed to use // activated mana abilities (e.g. because they started to use improvise or convoke) - if (!game.getStack().isEmpty()) { - StackObject stackObject = game.getStack().getFirst(); - if (stackObject instanceof Spell) { - switch (((Spell) stackObject).getCurrentActivatingManaAbilitiesStep()) { - case BEFORE: - case NORMAL: - break; - case AFTER: - return ActivationStatus.getFalse(); - } + StackObject stackObject = game.getStack().getFirstOrNull(); + if (stackObject instanceof Spell) { + switch (((Spell) stackObject).getCurrentActivatingManaAbilitiesStep()) { + case BEFORE: + case NORMAL: + break; + case AFTER: + return ActivationStatus.getFalse(); } } - return super.canActivate(playerId, game); } diff --git a/Mage/src/main/java/mage/game/stack/SpellStack.java b/Mage/src/main/java/mage/game/stack/SpellStack.java index 598c67c366e..149720cc740 100644 --- a/Mage/src/main/java/mage/game/stack/SpellStack.java +++ b/Mage/src/main/java/mage/game/stack/SpellStack.java @@ -51,6 +51,16 @@ public class SpellStack extends ArrayDeque { } } + @Override + @Deprecated // must use getFirstOrNull instead + public StackObject getFirst() { + return super.getFirst(); + } + + public StackObject getFirstOrNull() { + return this.isEmpty() ? null : this.getFirst(); + } + public boolean remove(StackObject object, Game game) { for (StackObject spell : this) { if (spell.getId().equals(object.getId())) {