From adbe84c5407b46fc604b11b86cbdff03cd99308b Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Wed, 1 Jul 2020 13:48:22 +0400 Subject: [PATCH] Improved freeze checks and canRespond/isInGame usage --- .../src/mage/player/human/HumanPlayer.java | 2 +- .../java/mage/server/game/GameController.java | 2 +- Mage.Sets/src/mage/cards/c/CovetedJewel.java | 2 +- Mage.Sets/src/mage/cards/c/CruelFate.java | 13 ++----- Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java | 2 +- Mage.Sets/src/mage/cards/k/KarnLiberated.java | 9 +++-- .../src/mage/cards/k/KindleTheCarnage.java | 6 +-- .../src/mage/cards/n/NaturalBalance.java | 6 +-- .../src/mage/cards/s/ScourgeOfValkas.java | 3 +- Mage.Sets/src/mage/cards/s/SkySwallower.java | 9 ++--- .../src/mage/cards/s/SlaughterTheStrong.java | 3 +- Mage.Sets/src/mage/cards/u/UndyingFlames.java | 7 ++-- .../effects/common/DamageTargetEffect.java | 6 +-- .../continuous/GainControlTargetEffect.java | 11 ++---- Mage/src/main/java/mage/game/GameImpl.java | 8 ++-- .../java/mage/game/combat/CombatGroup.java | 37 +++++++------------ .../main/java/mage/players/PlayerList.java | 5 +++ 17 files changed, 54 insertions(+), 77 deletions(-) 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 e38c162e8d..c702e65dd7 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 @@ -1964,7 +1964,7 @@ public class HumanPlayer extends PlayerImpl { } waitForResponse(game); - if (response.getUUID() != null && isInGame()) { + if (response.getUUID() != null) { if (abilities.containsKey(response.getUUID())) { activateAbility(abilities.get(response.getUUID()), game); } 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 883df510da..e290eb3b73 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -326,7 +326,7 @@ public class GameController implements GameCallback { private void sendInfoAboutPlayersNotJoinedYetAndTryToFixIt() { // runs every 5 secs untill all players join for (Player player : game.getPlayers().values()) { - if (player.isInGame() && player.isHuman()) { + if (player.canRespond() && player.isHuman()) { Optional requestedUser = getUserByPlayerId(player.getId()); if (requestedUser.isPresent()) { User user = requestedUser.get(); diff --git a/Mage.Sets/src/mage/cards/c/CovetedJewel.java b/Mage.Sets/src/mage/cards/c/CovetedJewel.java index 0e068ed2a5..8f09a76266 100644 --- a/Mage.Sets/src/mage/cards/c/CovetedJewel.java +++ b/Mage.Sets/src/mage/cards/c/CovetedJewel.java @@ -123,7 +123,7 @@ class CovetedJewelControlEffect extends ContinuousEffectImpl { public boolean apply(Game game, Ability source) { Permanent permanent = game.getPermanent(source.getSourceId()); Player newControllingPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (permanent == null || newControllingPlayer == null || !newControllingPlayer.isInGame()) { + if (permanent == null || newControllingPlayer == null || !newControllingPlayer.canRespond()) { this.discard(); return false; } diff --git a/Mage.Sets/src/mage/cards/c/CruelFate.java b/Mage.Sets/src/mage/cards/c/CruelFate.java index b225636297..34e6ba82bf 100644 --- a/Mage.Sets/src/mage/cards/c/CruelFate.java +++ b/Mage.Sets/src/mage/cards/c/CruelFate.java @@ -1,14 +1,8 @@ - package mage.cards.c; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; @@ -18,8 +12,9 @@ import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author TheElk801 & L_J */ public final class CruelFate extends CardImpl { @@ -71,7 +66,7 @@ class CruelFateEffect extends OneShotEffect { // card to put into opponent's graveyard TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCard("card to put into target opponent's graveyard")); - if (targetOpponent.isInGame()) { + if (targetOpponent.canRespond()) { if (cards.size() > 1) { controller.choose(Outcome.Detriment, cards, target, game); Card card = cards.get(target.getFirstTarget(), game); diff --git a/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java b/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java index 563fb12b5c..86e8ba47bf 100644 --- a/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java +++ b/Mage.Sets/src/mage/cards/e/EyeOfTheStorm.java @@ -137,7 +137,7 @@ class EyeOfTheStormEffect1 extends OneShotEffect { } boolean continueCasting = true; - while (spellController.isInGame() && continueCasting) { + while (spellController.canRespond() && continueCasting) { continueCasting = copiedCards.size() > 1 && spellController.chooseUse(outcome, "Cast one of the copied cards without paying its mana cost?", source, game); Card cardToCopy; diff --git a/Mage.Sets/src/mage/cards/k/KarnLiberated.java b/Mage.Sets/src/mage/cards/k/KarnLiberated.java index 662cc84fa1..45a6c7b1aa 100644 --- a/Mage.Sets/src/mage/cards/k/KarnLiberated.java +++ b/Mage.Sets/src/mage/cards/k/KarnLiberated.java @@ -1,8 +1,5 @@ package mage.cards.k; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -26,6 +23,10 @@ import mage.target.TargetPlayer; import mage.target.common.TargetCardInHand; import mage.util.CardUtil; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + /** * @author bunchOfDevs */ @@ -100,7 +101,7 @@ class KarnLiberatedEffect extends OneShotEffect { game.getState().addCard(card); } for (Player player : game.getPlayers().values()) { - if (player.isInGame()) { // only players alive are in the restarted game + if (player.canRespond()) { // only players alive are in the restarted game player.getGraveyard().clear(); player.getHand().clear(); player.getLibrary().clear(); diff --git a/Mage.Sets/src/mage/cards/k/KindleTheCarnage.java b/Mage.Sets/src/mage/cards/k/KindleTheCarnage.java index 6e7b84b254..d1c3af51e2 100644 --- a/Mage.Sets/src/mage/cards/k/KindleTheCarnage.java +++ b/Mage.Sets/src/mage/cards/k/KindleTheCarnage.java @@ -1,7 +1,5 @@ - package mage.cards.k; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageAllEffect; @@ -15,8 +13,9 @@ import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class KindleTheCarnage extends CardImpl { @@ -62,7 +61,6 @@ class KindleTheCarnageEffect extends OneShotEffect { Cards hand = controller.getHand(); while (hand != null && hand.size() > 0 - && controller.isInGame() && controller.chooseUse(Outcome.AIDontUseIt, "Discard a card randomly from your hand?", source, game)) { Card discardedCard = controller.discardOne(true, source, game); if (discardedCard != null) { diff --git a/Mage.Sets/src/mage/cards/n/NaturalBalance.java b/Mage.Sets/src/mage/cards/n/NaturalBalance.java index 1dfc2c3bc2..7d9b4c3513 100644 --- a/Mage.Sets/src/mage/cards/n/NaturalBalance.java +++ b/Mage.Sets/src/mage/cards/n/NaturalBalance.java @@ -1,4 +1,3 @@ - package mage.cards.n; import mage.abilities.Ability; @@ -24,7 +23,6 @@ import java.util.List; import java.util.UUID; /** - * * @author Rene - bugisemail at gmail dot com */ public final class NaturalBalance extends CardImpl { @@ -100,9 +98,7 @@ public final class NaturalBalance extends CardImpl { } } for (Player player : toShuffle) { - if (player.isInGame()) { - player.shuffleLibrary(source, game); - } + player.shuffleLibrary(source, game); } return true; } diff --git a/Mage.Sets/src/mage/cards/s/ScourgeOfValkas.java b/Mage.Sets/src/mage/cards/s/ScourgeOfValkas.java index e6e7f1c6c7..27c638bd37 100644 --- a/Mage.Sets/src/mage/cards/s/ScourgeOfValkas.java +++ b/Mage.Sets/src/mage/cards/s/ScourgeOfValkas.java @@ -96,8 +96,7 @@ class ScourgeOfValkasDamageEffect extends OneShotEffect { permanent.damage(dragons, enteringDragon.getId(), game, false, true); } else { Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (player != null - && player.isInGame()) { + if (player != null) { player.damage(dragons, enteringDragon.getId(), game); } } diff --git a/Mage.Sets/src/mage/cards/s/SkySwallower.java b/Mage.Sets/src/mage/cards/s/SkySwallower.java index 0a6bafd472..68252b5138 100644 --- a/Mage.Sets/src/mage/cards/s/SkySwallower.java +++ b/Mage.Sets/src/mage/cards/s/SkySwallower.java @@ -1,7 +1,5 @@ - package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.Mode; @@ -17,15 +15,16 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetOpponent; +import java.util.UUID; + /** - * * @author ciaccona007 */ public final class SkySwallower extends CardImpl { public SkySwallower(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); - + this.subtype.add(SubType.LEVIATHAN); this.power = new MageInt(8); this.toughness = new MageInt(8); @@ -68,7 +67,7 @@ class GainControlAllPermanentsEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { Player targetPlayer = game.getPlayer(targetPointer.getFirst(game, source)); - if (targetPlayer != null && targetPlayer.isInGame()) { + if (targetPlayer != null) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, source.getControllerId(), game)) { if (permanent != null && !permanent.getId().equals(source.getSourceId())) { permanent.changeControllerId(targetPlayer.getId(), game); diff --git a/Mage.Sets/src/mage/cards/s/SlaughterTheStrong.java b/Mage.Sets/src/mage/cards/s/SlaughterTheStrong.java index b54b294cd1..c3832f3ceb 100644 --- a/Mage.Sets/src/mage/cards/s/SlaughterTheStrong.java +++ b/Mage.Sets/src/mage/cards/s/SlaughterTheStrong.java @@ -1,4 +1,3 @@ - package mage.cards.s; import mage.abilities.Ability; @@ -70,7 +69,7 @@ class SlaughterTheStrongEffect extends OneShotEffect { if (player != null) { boolean selectionDone = false; Set selectedCreatures = new HashSet<>(); - while (selectionDone == false && player.isInGame()) { + while (player.canRespond() && selectionDone == false) { int powerSum = 0; for (UUID creatureId : selectedCreatures) { Permanent creature = game.getPermanent(creatureId); diff --git a/Mage.Sets/src/mage/cards/u/UndyingFlames.java b/Mage.Sets/src/mage/cards/u/UndyingFlames.java index acbfe4a566..9f61def4f2 100644 --- a/Mage.Sets/src/mage/cards/u/UndyingFlames.java +++ b/Mage.Sets/src/mage/cards/u/UndyingFlames.java @@ -1,6 +1,5 @@ package mage.cards.u; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; @@ -15,10 +14,10 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author jeffwadsworth - * */ public final class UndyingFlames extends CardImpl { @@ -60,7 +59,7 @@ class UndyingFlamesEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - while (controller.getLibrary().hasCards() && controller.isInGame()) { + while (controller.canRespond() && controller.getLibrary().hasCards()) { Card card = controller.getLibrary().getFromTop(game); if (card != null) { controller.moveCards(card, Zone.EXILED, source, game); diff --git a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java index d4db66bb45..ea60a6e866 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DamageTargetEffect.java @@ -122,8 +122,7 @@ public class DamageTargetEffect extends OneShotEffect { permanent.damage(amount.calculate(game, source, this), source.getSourceId(), game, false, preventable); } Player player = game.getPlayer(targetId); - if (player != null - && player.isInGame()) { + if (player != null) { player.damage(amount.calculate(game, source, this), source.getSourceId(), game, false, preventable); } } @@ -136,8 +135,7 @@ public class DamageTargetEffect extends OneShotEffect { permanent.damage(amount.calculate(game, source, this), source.getSourceId(), game, false, preventable); } else { Player player = game.getPlayer(targetId); - if (player != null - && player.isInGame()) { + if (player != null) { player.damage(amount.calculate(game, source, this), source.getSourceId(), game, false, preventable); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java index c418dadd40..aee19ee2ba 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java @@ -1,6 +1,5 @@ package mage.abilities.effects.common.continuous; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.ActivatedAbility; import mage.abilities.Mode; @@ -16,8 +15,9 @@ import mage.players.Player; import mage.target.Target; import mage.util.CardUtil; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public class GainControlTargetEffect extends ContinuousEffectImpl { @@ -31,17 +31,15 @@ public class GainControlTargetEffect extends ContinuousEffectImpl { } /** - * * @param duration * @param fixedControl Controlling player is fixed even if the controller of - * the ability changes later + * the ability changes later */ public GainControlTargetEffect(Duration duration, boolean fixedControl) { this(duration, fixedControl, null); } /** - * * @param duration * @param controllingPlayerId Player that controls the target creature */ @@ -112,8 +110,7 @@ public class GainControlTargetEffect extends ContinuousEffectImpl { } } // no valid target exists and the controller is no longer in the game, effect can be discarded - if (!oneTargetStillExists - || !controller.isInGame()) { + if (!oneTargetStillExists || !controller.isInGame()) { discard(); } firstControlChange = false; diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 4bb34ae56a..a4ff70b008 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -982,7 +982,7 @@ public abstract class GameImpl implements Game, Serializable { targetPlayer.setTargetName("starting player"); if (choosingPlayerId != null) { choosingPlayer = this.getPlayer(choosingPlayerId); - if (choosingPlayer != null && !choosingPlayer.isInGame()) { + if (choosingPlayer != null && !choosingPlayer.canRespond()) { choosingPlayer = null; } } @@ -1007,7 +1007,7 @@ public abstract class GameImpl implements Game, Serializable { if (startingPlayerId == null) { // choose any available player as starting player for (Player player : state.getPlayers().values()) { - if (player.isInGame()) { + if (player.canRespond()) { startingPlayerId = player.getId(); break; } @@ -1161,7 +1161,7 @@ public abstract class GameImpl implements Game, Serializable { while (!hasEnded()) { playerId = players[RandomUtil.nextInt(players.length)]; Player player = getPlayer(playerId); - if (player != null && player.isInGame()) { + if (player != null && player.canRespond()) { fireInformEvent(state.getPlayer(playerId).getLogName() + " won the toss"); return player.getId(); } @@ -3281,7 +3281,7 @@ public abstract class GameImpl implements Game, Serializable { gameStatesRollBack.put(getTurnNum(), state.copy()); executingRollback = true; for (Player playerObject : getPlayers().values()) { - if (playerObject.isHuman() && playerObject.isInGame()) { + if (playerObject.isHuman() && playerObject.canRespond()) { playerObject.resetStoredBookmark(this); playerObject.abort(); playerObject.resetPlayerPassedActions(); diff --git a/Mage/src/main/java/mage/game/combat/CombatGroup.java b/Mage/src/main/java/mage/game/combat/CombatGroup.java index d3d5926822..616eebe772 100644 --- a/Mage/src/main/java/mage/game/combat/CombatGroup.java +++ b/Mage/src/main/java/mage/game/combat/CombatGroup.java @@ -1,17 +1,10 @@ - package mage.game.combat; import mage.abilities.Ability; import mage.abilities.common.ControllerAssignCombatDamageToBlockersAbility; import mage.abilities.common.ControllerDivideCombatDamageAbility; import mage.abilities.common.DamageAsThoughNotBlockedAbility; -import mage.abilities.keyword.BandingAbility; -import mage.abilities.keyword.BandsWithOtherAbility; -import mage.abilities.keyword.CantBlockAloneAbility; -import mage.abilities.keyword.DeathtouchAbility; -import mage.abilities.keyword.DoubleStrikeAbility; -import mage.abilities.keyword.FirstStrikeAbility; -import mage.abilities.keyword.TrampleAbility; +import mage.abilities.keyword.*; import mage.constants.AsThoughEffectType; import mage.constants.Outcome; import mage.filter.StaticFilters; @@ -27,7 +20,6 @@ import java.util.*; import java.util.stream.Stream; /** - * * @author BetaSteward_at_googlemail.com */ public class CombatGroup implements Serializable, Copyable { @@ -43,9 +35,9 @@ public class CombatGroup implements Serializable, Copyable { protected boolean defenderIsPlaneswalker; /** - * @param defenderId the player that controls the defending permanents + * @param defenderId the player that controls the defending permanents * @param defenderIsPlaneswalker is the defending permanent a planeswalker - * @param defendingPlayerId regular controller of the defending permanents + * @param defendingPlayerId regular controller of the defending permanents */ public CombatGroup(UUID defenderId, boolean defenderIsPlaneswalker, UUID defendingPlayerId) { this.defenderId = defenderId; @@ -174,7 +166,7 @@ public class CombatGroup implements Serializable, Copyable { Player player = game.getPlayer(defenderAssignsCombatDamage(game) ? defendingPlayerId : attacker.getControllerId()); if ((attacker.getAbilities().containsKey(DamageAsThoughNotBlockedAbility.getInstance().getId()) && player.chooseUse(Outcome.Damage, "Do you wish to assign damage for " - + attacker.getLogName() + " as though it weren't blocked?", null, game)) || + + attacker.getLogName() + " as though it weren't blocked?", null, game)) || game.getContinuousEffects().asThough(attacker.getId(), AsThoughEffectType.DAMAGE_NOT_BLOCKED , null, attacker.getControllerId(), game) != null) { // for handling creatures like Thorn Elemental @@ -227,7 +219,7 @@ public class CombatGroup implements Serializable, Copyable { * Determines if permanent can damage in current (First Strike or not) * combat damage step * - * @param perm Permanent to check + * @param perm Permanent to check * @param first First strike or common combat damage step * @return */ @@ -409,7 +401,7 @@ public class CombatGroup implements Serializable, Copyable { } if (damage > 0) { Player defendingPlayer = game.getPlayer(defendingPlayerId); - if (defendingPlayer.isInGame()) { + if (defendingPlayer != null) { defendingPlayer.damage(damage, attacker.getId(), game, true, true); } } @@ -466,9 +458,9 @@ public class CombatGroup implements Serializable, Copyable { * Damages attacking creatures by a creature that blocked several ones * Damages only attackers as blocker was damage in * {@link #singleBlockerDamage}. - * + *

* Handles abilities like "{this} an block any number of creatures.". - * + *

* Blocker damage for blockers blocking single creatures is handled in the * single/multi blocker methods, so this shouldn't be used anymore. * @@ -492,7 +484,7 @@ public class CombatGroup implements Serializable, Copyable { * Damages attacking creatures by a creature that blocked several ones * Damages only attackers as blocker was damage in either * {@link #singleBlockerDamage} or {@link #multiBlockerDamage}. - * + *

* Handles abilities like "{this} an block any number of creatures.". * * @param first @@ -552,7 +544,7 @@ public class CombatGroup implements Serializable, Copyable { } } else { Player defender = game.getPlayer(defenderId); - if (defender.isInGame()) { + if (defender != null) { defender.damage(amount, attacker.getId(), game, true, true); } } @@ -572,9 +564,8 @@ public class CombatGroup implements Serializable, Copyable { } /** - * * @param blockerId - * @param playerId controller of the blocking creature + * @param playerId controller of the blocking creature * @param game */ public void addBlocker(UUID blockerId, UUID playerId, Game game) { @@ -591,7 +582,7 @@ public class CombatGroup implements Serializable, Copyable { * event. * * @param blockerId - * @param playerId controller of the blocking creature + * @param playerId controller of the blocking creature * @param game */ public void addBlockerToGroup(UUID blockerId, UUID playerId, Game game) { @@ -645,7 +636,7 @@ public class CombatGroup implements Serializable, Copyable { attackerPerms.add(game.getPermanent(attackerId)); } UUID attackerId = player.chooseAttackerOrder(attackerPerms, game); - if (!player.isInGame()) { + if (attackerId == null) { break; } attackerOrder.add(attackerId); @@ -791,7 +782,7 @@ public class CombatGroup implements Serializable, Copyable { /** * There are effects, that set an attacker to be blocked. Therefore this * setter can be used. - * + *

* This method lacks a band check, use setBlocked(blocked, game) instead. * * @param blocked diff --git a/Mage/src/main/java/mage/players/PlayerList.java b/Mage/src/main/java/mage/players/PlayerList.java index f25b5a9a16..c01d4cfc3d 100644 --- a/Mage/src/main/java/mage/players/PlayerList.java +++ b/Mage/src/main/java/mage/players/PlayerList.java @@ -53,6 +53,7 @@ public class PlayerList extends CircularList { player.setReachedNextTurnAfterLeaving(true); } } + if (player.getId().equals(start)) { return null; } @@ -63,11 +64,15 @@ public class PlayerList extends CircularList { public Player getPrevious(Game game) { Player player; UUID start = this.get(); + if (start == null) { + return null; + } while (true) { player = game.getPlayer(super.getPrevious()); if (player.isInGame()) { break; } + if (player.getId().equals(start)) { return null; }