From aa1eb354efd02f548056eeebe5442d97fa71e92a Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 18 Aug 2015 17:20:04 +0200 Subject: [PATCH] * Removed some data from player restoring to fix unintended draws after a player concedes game (#1205) --- .../src/mage/player/ai/SimulatedPlayer2.java | 2 + .../mage/sets/fatereforged/OutpostSiege.java | 21 +++++----- .../sets/magicorigins/AbbotOfKeralKeep.java | 13 +++--- .../java/org/mage/test/player/TestPlayer.java | 10 +++++ Mage/src/mage/game/GameImpl.java | 1 + Mage/src/mage/players/Player.java | 7 ++-- Mage/src/mage/players/PlayerImpl.java | 40 ++++++++++++++----- 7 files changed, 65 insertions(+), 29 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java index 419a33a0b53..fce50c8ff20 100644 --- a/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java +++ b/Mage.Server.Plugins/Mage.Player.AI.MA/src/mage/player/ai/SimulatedPlayer2.java @@ -53,6 +53,7 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.StackAbility; import mage.players.Player; +import mage.players.net.UserData; import mage.target.Target; import org.apache.log4j.Logger; @@ -75,6 +76,7 @@ public class SimulatedPlayer2 extends ComputerPlayer { pass.setControllerId(playerId); this.isSimulatedPlayer = isSimulatedPlayer; this.suggested = suggested; + this.userData = UserData.getDefaultUserDataView(); } public SimulatedPlayer2(final SimulatedPlayer2 player) { diff --git a/Mage.Sets/src/mage/sets/fatereforged/OutpostSiege.java b/Mage.Sets/src/mage/sets/fatereforged/OutpostSiege.java index f49e7e15cc9..a2598cdb69a 100644 --- a/Mage.Sets/src/mage/sets/fatereforged/OutpostSiege.java +++ b/Mage.Sets/src/mage/sets/fatereforged/OutpostSiege.java @@ -50,6 +50,7 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreatureOrPlayer; import mage.target.targetpointer.FixedTarget; @@ -68,8 +69,8 @@ public class OutpostSiege extends CardImpl { this.expansionSetCode = "FRF"; // As Outpost Siege enters the battlefield, choose Khans or Dragons. - this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?","Khans", "Dragons"),null, true, - "As {this} enters the battlefield, choose Khans or Dragons.","")); + this.addAbility(new EntersBattlefieldAbility(new ChooseModeEffect("Khans or Dragons?", "Khans", "Dragons"), null, true, + "As {this} enters the battlefield, choose Khans or Dragons.", "")); // * Khans - At the beginning of your upkeep, exile the top card of your library. Until end of turn, you may play that card. this.addAbility(new ConditionalTriggeredAbility( @@ -80,10 +81,10 @@ public class OutpostSiege extends CardImpl { // * Dragons - Whenever a creature you control leaves the battlefield, Outpost Siege deals 1 damage to target creature or player. Ability ability2 = new ConditionalTriggeredAbility( new ZoneChangeAllTriggeredAbility(Zone.BATTLEFIELD, Zone.BATTLEFIELD, null, new DamageTargetEffect(1), - new FilterControlledCreaturePermanent(), "", false), + new FilterControlledCreaturePermanent(), "", false), new ModeChoiceSourceCondition("Dragons"), ruleTrigger2); - ability2.addTarget(new TargetCreatureOrPlayer()); + ability2.addTarget(new TargetCreatureOrPlayer()); this.addAbility(ability2); } @@ -117,13 +118,15 @@ class OutpostSiegeExileEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null && sourcePermanent != null) { Card card = controller.getLibrary().getFromTop(game); if (card != null) { - controller.moveCardToExileWithInfo(card, null, "", source.getSourceId(), game, Zone.LIBRARY, true); + String exileName = sourcePermanent.getIdName() + " ").toString(); - controller.moveCardToExileWithInfo(card, source.getSourceId(), exileName, source.getSourceId(), game, Zone.LIBRARY, true); + String exileName = sourcePermanent.getIdName() + " "; + controller.moveCardsToExile(card, source, game, true, source.getSourceId(), exileName); ContinuousEffect effect = new AbbotOfKeralKeepCastFromExileEffect(); - effect.setTargetPointer(new FixedTarget(card.getId())); + effect.setTargetPointer(new FixedTarget(card.getId(), card.getZoneChangeCounter(game))); game.addEffect(effect, source); } return true; @@ -139,7 +138,7 @@ class AbbotOfKeralKeepCastFromExileEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - return source.getControllerId().equals(affectedControllerId) && - objectId.equals(getTargetPointer().getFirst(game, source)); + return source.getControllerId().equals(affectedControllerId) + && objectId.equals(getTargetPointer().getFirst(game, source)); } } 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 7806999ead1..100ebafb3e1 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 @@ -1358,6 +1358,11 @@ public class TestPlayer implements Player { computerPlayer.resetPassed(); } + @Override + public void resetPlayerPassedActions() { + computerPlayer.resetPlayerPassedActions(); + } + @Override public void quit(Game game) { computerPlayer.quit(game); @@ -1701,6 +1706,11 @@ public class TestPlayer implements Player { return computerPlayer.moveCardToHandWithInfo(card, sourceId, game, withName); } + @Override + public boolean moveCardsToExile(Card card, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName) { + return computerPlayer.moveCardsToExile(card, source, game, withName, exileId, exileZoneName); + } + @Override public boolean moveCardsToExile(Set cards, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName) { return computerPlayer.moveCardsToExile(cards, source, game, withName, exileId, exileZoneName); diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 1705dba7ee8..e30b539ce25 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -2657,6 +2657,7 @@ public abstract class GameImpl implements Game, Serializable { for (Player playerObject : getPlayers().values()) { if (playerObject.isHuman() && playerObject.isInGame()) { playerObject.abort(); + playerObject.resetPlayerPassedActions(); } } fireUpdatePlayersEvent(); diff --git a/Mage/src/mage/players/Player.java b/Mage/src/mage/players/Player.java index 4d450a9d58a..80c17cce2c8 100644 --- a/Mage/src/mage/players/Player.java +++ b/Mage/src/mage/players/Player.java @@ -179,6 +179,8 @@ public interface Player extends MageItem, Copyable { void resetPassed(); + void resetPlayerPassedActions(); + boolean getPassedTurn(); boolean getPassedUntilEndOfTurn(); @@ -620,13 +622,12 @@ public interface Player extends MageItem, Copyable { */ boolean moveCards(Cards cards, Zone fromZone, Zone toZone, Ability source, Game game); -// boolean moveCards(Cards cards, Zone fromZone, Zone toZone, Ability source, Game game, boolean withName); boolean moveCards(Card card, Zone fromZone, Zone toZone, Ability source, Game game); -// boolean moveCards(Card card, Zone fromZone, Zone toZone, Ability source, Game game, boolean withName); boolean moveCards(Set cards, Zone fromZone, Zone toZone, Ability source, Game game); - // boolean moveCards(Set cards, Zone fromZone, Zone toZone, Ability source, Game game, boolean withName); + boolean moveCardsToExile(Card card, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName); + boolean moveCardsToExile(Set cards, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName); /** diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index 5998477bbec..8eb7b8bed84 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -330,9 +330,21 @@ public abstract class PlayerImpl implements Player, Serializable { this.name = player.getName(); this.human = player.isHuman(); this.life = player.getLife(); - this.wins = player.hasWon(); - this.loses = player.hasLost(); + // Don't restore more global states. If restored they are probably cause for unintended draws (https://github.com/magefree/mage/issues/1205). +// this.wins = player.hasWon(); +// this.loses = player.hasLost(); +// this.left = player.hasLeft(); +// this.quit = player.hasQuit(); + // Makes no sense to restore +// this.passed = player.isPassed(); +// this.priorityTimeLeft = player.getPriorityTimeLeft(); +// this.idleTimeout = player.hasIdleTimeout(); +// this.timerTimeout = player.hasTimerTimeout(); + // can't change so no need to restore +// this.isTestMode = player.isTestMode(); + // This is meta data and should'nt be restored by rollback +// this.userData = player.getUserData(); this.library = player.getLibrary().copy(); this.sideboard = player.getSideboard().copy(); this.hand = player.getHand().copy(); @@ -349,10 +361,6 @@ public abstract class PlayerImpl implements Player, Serializable { this.manaPool = player.getManaPool().copy(); this.turns = player.getTurns(); - this.left = player.hasLeft(); - this.quit = player.hasQuit(); - this.timerTimeout = player.hasTimerTimeout(); - this.idleTimeout = player.hasIdleTimeout(); this.range = player.getRange(); this.canGainLife = player.isCanGainLife(); this.canLoseLife = player.isCanLoseLife(); @@ -361,7 +369,6 @@ public abstract class PlayerImpl implements Player, Serializable { this.inRange.clear(); this.inRange.addAll(player.getInRange()); - this.userData = player.getUserData(); this.canPayLifeCost = player.canPayLifeCost(); this.canPaySacrificeCost = player.canPaySacrificeCost(); this.loseByZeroOrLessLife = player.canLoseByZeroOrLessLife(); @@ -371,12 +378,9 @@ public abstract class PlayerImpl implements Player, Serializable { this.topCardRevealed = player.isTopCardRevealed(); this.playersUnderYourControl.clear(); this.playersUnderYourControl.addAll(player.getPlayersUnderYourControl()); - this.isTestMode = player.isTestMode(); this.isGameUnderControl = player.isGameUnderControl(); this.turnController = player.getTurnControlledBy(); - this.passed = player.isPassed(); - this.priorityTimeLeft = player.getPriorityTimeLeft(); this.reachedNextTurnAfterLeaving = player.hasReachedNextTurnAfterLeaving(); this.castSourceIdWithAlternateMana = player.getCastSourceIdWithAlternateMana(); this.castSourceIdManaCosts = player.getCastSourceIdManaCosts(); @@ -1823,6 +1827,15 @@ public abstract class PlayerImpl implements Player, Serializable { this.passed = this.loses || this.hasLeft(); } + @Override + public void resetPlayerPassedActions() { + this.passedAllTurns = false; + this.passedTurn = false; + this.passedUntilEndOfTurn = false; + this.passedUntilNextMain = false; + this.passedUntilStackResolved = false; + } + @Override public void quit(Game game) { quit = true; @@ -2949,6 +2962,13 @@ public abstract class PlayerImpl implements Player, Serializable { } } + @Override + public boolean moveCardsToExile(Card card, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName) { + Set cards = new HashSet<>(); + cards.add(card); + return moveCardsToExile(cards, source, game, withName, exileId, exileZoneName); + } + @Override public boolean moveCardsToExile(Set cards, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName) { if (cards.isEmpty()) {