diff --git a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java index 0939c26eb6..dfa6bf947f 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java @@ -11,8 +11,8 @@ import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallbackMethod; import mage.players.Player; import mage.server.User; -import mage.server.managers.UserManager; import mage.server.managers.ManagerFactory; +import mage.server.managers.UserManager; import mage.view.*; import org.apache.log4j.Logger; @@ -195,6 +195,18 @@ public class GameSessionPlayer extends GameSessionWatcher { @Override public GameView getGameView() { + return prepareGameView(game, playerId, userId); + } + + /** + * Prepare client-server data. Can be used in real games or in unit tests + * + * @param game + * @param playerId + * @param userId can be null for tests + * @return + */ + public static GameView prepareGameView(Game game, UUID playerId, UUID userId) { Player player = game.getPlayer(playerId); GameView gameView = new GameView(game.getState(), game, playerId, null); gameView.setHand(new CardsView(game, player.getHand().getCards(game))); @@ -202,8 +214,8 @@ public class GameSessionPlayer extends GameSessionWatcher { gameView.setCanPlayObjects(player.getPlayableObjects(game, Zone.ALL)); } - processControlledPlayers(player, gameView); - processWatchedHands(userId, gameView); + processControlledPlayers(game, player, gameView); + processWatchedHands(game, userId, gameView); //TODO: should player who controls another player's turn be able to look at all these cards? List list = new ArrayList<>(); @@ -215,7 +227,7 @@ public class GameSessionPlayer extends GameSessionWatcher { return gameView; } - private void processControlledPlayers(Player player, GameView gameView) { + private static void processControlledPlayers(Game game, Player player, GameView gameView) { if (!player.getPlayersUnderYourControl().isEmpty()) { Map handCards = new HashMap<>(); for (UUID controlledPlayerId : player.getPlayersUnderYourControl()) { @@ -258,7 +270,7 @@ public class GameSessionPlayer extends GameSessionWatcher { if (ex.getCause() != null) { logger.debug("- Cause: " + (ex.getCause().getMessage() == null ? "null" : ex.getCause().getMessage()), ex); } else { - logger.debug("- ex: " + ex.toString(), ex); + logger.debug("- ex: " + ex, ex); } } else { logger.fatal("Game session game quit exception - null gameId:" + game.getId() + " playerId: " + playerId); diff --git a/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java b/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java index 6aafddbf67..4bcd69d57c 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionWatcher.java @@ -99,11 +99,11 @@ public class GameSessionWatcher { public GameView getGameView() { GameView gameView = new GameView(game.getState(), game, null, userId); - processWatchedHands(userId, gameView); + processWatchedHands(game, userId, gameView); return gameView; } - protected void processWatchedHands(UUID userId, GameView gameView) { + protected static void processWatchedHands(Game game, UUID userId, GameView gameView) { Map handCards = new HashMap<>(); for (Player player : game.getPlayers().values()) { if (player.hasUserPermissionToSeeHand(userId)) { diff --git a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java index 1f8d5988b8..38cef7431f 100644 --- a/Mage.Server/src/main/java/mage/server/util/SystemUtil.java +++ b/Mage.Server/src/main/java/mage/server/util/SystemUtil.java @@ -23,6 +23,7 @@ import mage.game.GameCommanderImpl; import mage.game.command.CommandObject; import mage.game.command.Plane; import mage.game.permanent.Permanent; +import mage.game.permanent.token.Token; import mage.players.Player; import mage.util.CardUtil; import mage.util.RandomUtil; @@ -267,8 +268,8 @@ public final class SystemUtil { public static void addCardsForTesting(Game game, String fileSource, Player feedbackPlayer) { // fake test ability for triggers and events - Ability fakeSourceAbility = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards")); - fakeSourceAbility.setControllerId(feedbackPlayer.getId()); + Ability fakeSourceAbilityTemplate = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards")); + fakeSourceAbilityTemplate.setControllerId(feedbackPlayer.getId()); try { String fileName = fileSource; @@ -496,9 +497,12 @@ public final class SystemUtil { // eg: token:Human:HippoToken:1 Class c = Class.forName("mage.game.permanent.token." + command.cardName); Constructor cons = c.getConstructor(); - Object token = cons.newInstance(); - if (token instanceof mage.game.permanent.token.Token) { - ((mage.game.permanent.token.Token) token).putOntoBattlefield(command.Amount, game, fakeSourceAbility, player.getId(), false, false); + Object obj = cons.newInstance(); + if (obj instanceof Token) { + Token token = (Token) obj; + Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy(); + fakeSourceAbility.setSourceId(token.getId()); + token.putOntoBattlefield(command.Amount, game, fakeSourceAbility, player.getId(), false, false); continue; } } else if ("emblem".equalsIgnoreCase(command.zone)) { @@ -518,6 +522,8 @@ public final class SystemUtil { } else if ("loyalty".equalsIgnoreCase(command.zone)) { for (Permanent perm : game.getBattlefield().getAllActivePermanents(player.getId())) { if (perm.getName().equals(command.cardName) && perm.getCardType(game).contains(CardType.PLANESWALKER)) { + Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy(); + fakeSourceAbility.setSourceId(perm.getId()); perm.addCounters(CounterType.LOYALTY.createInstance(command.Amount), fakeSourceAbility.getControllerId(), fakeSourceAbility, game); } } @@ -541,6 +547,8 @@ public final class SystemUtil { // move card from exile to stack for (Card card : cardsToLoad) { + Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy(); + fakeSourceAbility.setSourceId(card.getId()); putCardToZone(fakeSourceAbility, game, player, card, Zone.STACK); } @@ -616,6 +624,8 @@ public final class SystemUtil { } else { // as other card for (Card card : cardsToLoad) { + Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy(); + fakeSourceAbility.setSourceId(card.getId()); putCardToZone(fakeSourceAbility, game, player, card, gameZone); } } 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 533367ec58..2db1d1b67f 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 @@ -25,6 +25,7 @@ import mage.cards.repository.CardRepository; import mage.constants.*; import mage.filter.StaticFilters; import mage.game.Game; +import mage.game.match.Match; import mage.game.match.MatchType; import mage.game.permanent.PermanentCard; import mage.game.tournament.TournamentType; @@ -92,6 +93,8 @@ public abstract class MageTestPlayerBase { */ protected static Game currentGame = null; + protected static Match currentMatch = null; + /** * Player thats starts the game first. By default, it is ComputerA. */ 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 0e9e6a09ef..55b6d09d81 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 @@ -16,19 +16,19 @@ import mage.counters.CounterType; import mage.filter.Filter; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.NamePredicate; -import mage.game.ExileZone; -import mage.game.Game; -import mage.game.GameException; -import mage.game.GameOptions; +import mage.game.*; import mage.game.command.CommandObject; +import mage.game.match.MatchOptions; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentCard; import mage.player.ai.ComputerPlayer7; import mage.player.ai.ComputerPlayerMCTS; import mage.players.ManaPool; import mage.players.Player; +import mage.server.game.GameSessionPlayer; import mage.server.util.SystemUtil; import mage.util.CardUtil; +import mage.view.GameView; import org.junit.Assert; import org.junit.Before; import org.mage.test.player.PlayerAction; @@ -216,6 +216,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement currentGame = null; } + // prepare fake match (needs for testing some client-server code) + // always 4 seats + MatchOptions matchOptions = new MatchOptions("test match", "test game type", true, 4); + currentMatch = new FreeForAllMatch(matchOptions); currentGame = createNewGameAndPlayers(); activePlayer = playerA; @@ -267,6 +271,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement game.loadCards(deck.getCards(), player.getId()); game.loadCards(deck.getSideboard(), player.getId()); game.addPlayer(player, deck); + currentMatch.addPlayer(player, deck); // fake match return player; } @@ -2116,4 +2121,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement Assert.assertFalse(player.getName() + " has lost the game.", player.hasLost()); } + public GameView getGameView(Player player) { + // prepare client-server data for tests + return GameSessionPlayer.prepareGameView(currentGame, player.getId(), null); + } } 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 75f77d6bff..4234a680ca 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 @@ -7,13 +7,13 @@ import mage.cards.repository.CardRepository; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.CounterType; -import mage.game.Game; 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 mage.view.GameView; import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -76,9 +76,10 @@ public class SerializationTest extends CardTestPlayerBase { setStopAt(1, PhaseStep.END_TURN); execute(); - Object compressed = CompressUtil.compress(currentGame); + GameView gameView = getGameView(playerA); + Object compressed = CompressUtil.compress(gameView); Assert.assertTrue("Must be zip", compressed instanceof ZippedObjectImpl); - Game uncompressed = (Game) CompressUtil.decompress(compressed); - Assert.assertEquals("Must be same", 1, uncompressed.getBattlefield().getAllActivePermanents().size()); + GameView uncompressed = (GameView) CompressUtil.decompress(compressed); + Assert.assertEquals("Must be same", 1, uncompressed.getPlayers().get(0).getBattlefield().size()); } } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 57031170bd..e6b60b5d74 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -3185,8 +3185,8 @@ public abstract class GameImpl implements Game, Serializable { @Override public void cheat(UUID ownerId, List library, List hand, List battlefield, List graveyard, List command) { // fake test ability for triggers and events - Ability fakeSourceAbility = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards")); - fakeSourceAbility.setControllerId(ownerId); + Ability fakeSourceAbilityTemplate = new SimpleStaticAbility(Zone.OUTSIDE, new InfoEffect("adding testing cards")); + fakeSourceAbilityTemplate.setControllerId(ownerId); Player player = getPlayer(ownerId); if (player != null) { @@ -3221,6 +3221,8 @@ public abstract class GameImpl implements Game, Serializable { } for (PermanentCard permanentCard : battlefield) { + Ability fakeSourceAbility = fakeSourceAbilityTemplate.copy(); + fakeSourceAbility.setSourceId(permanentCard.getId()); CardUtil.putCardOntoBattlefieldWithEffects(fakeSourceAbility, this, permanentCard, player); }