From c076f4925f7cc2bf7d752c2f8870e1745733f81f Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Tue, 7 Jan 2025 12:26:30 +0400 Subject: [PATCH] Turn under control reworked: - game: added support for human games (cards like Emrakul, the Promised End, #12878); - game: added support of 720.1. to reset control in the turn beginning instead cleanup step (related to #12115); - game: added game logs for priorities in cleanup step; - game: fixed game freezes and wrong skip settings usages (related to #12878); - gui: added playable and choose-able marks for controlling player's cards and permanents, including switched hands; - gui: added controlling player name in all choice dialogs; - info: control of computer players is it not yet supported; --- .../main/java/mage/client/game/GamePanel.java | 32 ++++++++++++ .../src/mage/player/human/HumanPlayer.java | 50 ++++++++----------- .../java/mage/server/game/GameController.java | 8 +-- .../mage/server/game/GameSessionPlayer.java | 11 ++-- .../mage/test/load/LoadCallbackClient.java | 23 ++++----- ...OfTurnStepPostDelayedTriggeredAbility.java | 42 ---------------- Mage/src/main/java/mage/game/Game.java | 6 +++ Mage/src/main/java/mage/game/GameImpl.java | 46 +++++++++++------ .../java/mage/game/turn/BeginningPhase.java | 2 - .../main/java/mage/game/turn/CleanupStep.java | 26 +++++++--- .../main/java/mage/game/turn/EndPhase.java | 11 ++-- Mage/src/main/java/mage/game/turn/Step.java | 6 +++ Mage/src/main/java/mage/game/turn/Turn.java | 31 +++++++++++- Mage/src/main/java/mage/players/Player.java | 2 +- .../main/java/mage/players/PlayerImpl.java | 8 +-- Mage/src/main/java/mage/util/CardUtil.java | 5 +- Mage/src/main/java/mage/util/GameLog.java | 4 -- 17 files changed, 175 insertions(+), 138 deletions(-) delete mode 100644 Mage/src/main/java/mage/abilities/common/delayed/AtTheEndOfTurnStepPostDelayedTriggeredAbility.java diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index 7ee3f1ebccbe..56d4e666592e 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -30,8 +30,10 @@ import mage.game.events.PlayerQueryEvent; import mage.players.PlayableObjectStats; import mage.players.PlayableObjectsList; +import mage.util.CardUtil; import mage.util.DebugUtil; import mage.util.MultiAmountMessage; +import mage.util.StreamUtils; import mage.view.*; import org.apache.log4j.Logger; import org.mage.plugins.card.utils.impl.ImageManagerImpl; @@ -53,6 +55,7 @@ import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import static mage.client.dialog.PreferencesDialog.*; import static mage.constants.PlayerAction.*; @@ -1810,6 +1813,7 @@ private void prepareSelectableView() { // hand if (needZone == Zone.HAND || needZone == Zone.ALL) { + // my hand for (CardView card : lastGameData.game.getMyHand().values()) { if (needSelectable.contains(card.getId())) { card.setChoosable(true); @@ -1821,6 +1825,34 @@ private void prepareSelectableView() { card.setPlayableStats(needPlayable.getStats(card.getId())); } } + + // opponent hands (switching by GUI's button with my hand) + List list = lastGameData.game.getOpponentHands().values().stream().flatMap(s -> s.values().stream()).collect(Collectors.toList()); + for (SimpleCardView card : list) { + if (needSelectable.contains(card.getId())) { + card.setChoosable(true); + } + if (needChosen.contains(card.getId())) { + card.setSelected(true); + } + if (needPlayable.containsObject(card.getId())) { + card.setPlayableStats(needPlayable.getStats(card.getId())); + } + } + + // watched hands (switching by GUI's button with my hand) + list = lastGameData.game.getWatchedHands().values().stream().flatMap(s -> s.values().stream()).collect(Collectors.toList()); + for (SimpleCardView card : list) { + if (needSelectable.contains(card.getId())) { + card.setChoosable(true); + } + if (needChosen.contains(card.getId())) { + card.setSelected(true); + } + if (needPlayable.containsObject(card.getId())) { + card.setPlayableStats(needPlayable.getStats(card.getId())); + } + } } // stack 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 815472067543..f55dcf7b402a 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 @@ -37,6 +37,7 @@ import mage.players.Player; import mage.players.PlayerImpl; import mage.players.PlayerList; +import mage.players.net.UserData; import mage.target.Target; import mage.target.TargetAmount; import mage.target.TargetCard; @@ -93,7 +94,7 @@ public class HumanPlayer extends PlayerImpl { // * - GAME thread: open response for income command and wait (go to sleep by response.wait) // * - CALL thread: on closed response - waiting open status of player's response object (if it's too long then cancel the answer) // * - CALL thread: on opened response - save answer to player's response object and notify GAME thread about it by response.notifyAll - // * - GAME thread: on nofify from response - check new answer value and process it (if it bad then repeat and wait the next one); + // * - GAME thread: on notify from response - check new answer value and process it (if it bad then repeat and wait the next one); private transient Boolean responseOpenedForAnswer = false; // GAME thread waiting new answer private transient long responseLastWaitingThreadId = 0; private final transient PlayerResponse response = new PlayerResponse(); @@ -1159,25 +1160,27 @@ public boolean priority(Game game) { // TODO: change pass and other states like passedUntilStackResolved for controlling player, not for "this" // TODO: check and change all "this" to controling player calls, many bugs with hand, mana, skips - https://github.com/magefree/mage/issues/2088 // TODO: use controlling player in all choose dialogs (and canRespond too, what's with take control of player AI?!) + UserData controllingUserData = this.userData; if (canRespond()) { - HumanPlayer controllingPlayer = this; - if (isGameUnderControl()) { // TODO: must be ! to get real controlling player + if (!isGameUnderControl()) { Player player = game.getPlayer(getTurnControlledBy()); if (player instanceof HumanPlayer) { - controllingPlayer = (HumanPlayer) player; + controllingUserData = player.getUserData(); + } else { + // TODO: add computer opponent here?! } } // TODO: check that all skips and stops used from real controlling player // like holdingPriority (is it a bug here?) if (getJustActivatedType() != null && !holdingPriority) { - if (controllingPlayer.getUserData().isPassPriorityCast() + if (controllingUserData.isPassPriorityCast() && getJustActivatedType() == AbilityType.SPELL) { setJustActivatedType(null); pass(game); return false; } - if (controllingPlayer.getUserData().isPassPriorityActivation() + if (controllingUserData.isPassPriorityActivation() && getJustActivatedType().isNonManaActivatedAbility()) { setJustActivatedType(null); pass(game); @@ -1252,7 +1255,7 @@ && getJustActivatedType().isNonManaActivatedAbility()) { // it's main step if (!skippedAtLeastOnce || (!playerId.equals(game.getActivePlayerId()) - && !controllingPlayer.getUserData().getUserSkipPrioritySteps().isStopOnAllMainPhases())) { + && !controllingUserData.getUserSkipPrioritySteps().isStopOnAllMainPhases())) { skippedAtLeastOnce = true; if (passWithManaPoolCheck(game)) { return false; @@ -1274,8 +1277,7 @@ && getJustActivatedType().isNonManaActivatedAbility()) { // it's end of turn step if (!skippedAtLeastOnce || (playerId.equals(game.getActivePlayerId()) - && !controllingPlayer - .getUserData() + && !controllingUserData .getUserSkipPrioritySteps() .isStopOnAllEndPhases())) { skippedAtLeastOnce = true; @@ -1295,7 +1297,7 @@ && getJustActivatedType().isNonManaActivatedAbility()) { } if (!dontCheckPassStep - && checkPassStep(game, controllingPlayer)) { + && checkPassStep(game, controllingUserData)) { if (passWithManaPoolCheck(game)) { return false; } @@ -1308,8 +1310,7 @@ && checkPassStep(game, controllingPlayer)) { if (passedUntilStackResolved) { if (haveNewObjectsOnStack && (playerId.equals(game.getActivePlayerId()) - && controllingPlayer - .getUserData() + && controllingUserData .getUserSkipPrioritySteps() .isStopOnStackNewObjects())) { // new objects on stack -- disable "pass until stack resolved" @@ -1433,17 +1434,17 @@ private UUID getFixedResponseUUID(Game game) { return response.getUUID(); } - private boolean checkPassStep(Game game, HumanPlayer controllingPlayer) { + private boolean checkPassStep(Game game, UserData controllingUserData) { try { if (playerId.equals(game.getActivePlayerId())) { - return !controllingPlayer.getUserData().getUserSkipPrioritySteps().getYourTurn().isPhaseStepSet(game.getTurnStepType()); + return !controllingUserData.getUserSkipPrioritySteps().getYourTurn().isPhaseStepSet(game.getTurnStepType()); } else { - return !controllingPlayer.getUserData().getUserSkipPrioritySteps().getOpponentTurn().isPhaseStepSet(game.getTurnStepType()); + return !controllingUserData.getUserSkipPrioritySteps().getOpponentTurn().isPhaseStepSet(game.getTurnStepType()); } } catch (NullPointerException ex) { - if (controllingPlayer.getUserData() != null) { - if (controllingPlayer.getUserData().getUserSkipPrioritySteps() != null) { + if (controllingUserData != null) { + if (controllingUserData.getUserSkipPrioritySteps() != null) { if (game.getStep() != null) { if (game.getTurnStepType() == null) { logger.error("game.getTurnStepType() == null"); @@ -2929,19 +2930,8 @@ private void setTriggerAutoOrder(PlayerAction playerAction, Game game, Object da protected boolean passWithManaPoolCheck(Game game) { if (userData.confirmEmptyManaPool() && game.getStack().isEmpty() && getManaPool().count() > 0 && getManaPool().canLostManaOnEmpty()) { - String activePlayerText; - if (game.isActivePlayer(playerId)) { - activePlayerText = "Your turn"; - } else { - activePlayerText = game.getPlayer(game.getActivePlayerId()).getName() + "'s turn"; - } - String priorityPlayerText = ""; - if (!isGameUnderControl()) { - priorityPlayerText = " / priority " + game.getPlayer(game.getPriorityPlayerId()).getName(); - } - // TODO: chooseUse and other dialogs must be under controlling player - if (!chooseUse(Outcome.Detriment, GameLog.getPlayerConfirmColoredText("You still have mana in your mana pool and it will be lose. Pass anyway?") - + GameLog.getSmallSecondLineText(activePlayerText + " / " + game.getTurnStepType().toString() + priorityPlayerText), null, game)) { + String message = GameLog.getPlayerConfirmColoredText("You still have mana in your mana pool and it will be lose. Pass anyway?"); + if (!chooseUse(Outcome.Detriment, message, null, game)) { sendPlayerAction(PlayerAction.PASS_PRIORITY_CANCEL_ALL_ACTIONS, game, null); return false; } 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 2a768f4ebd9e..868c161ae341 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -906,14 +906,14 @@ private synchronized void multiAmount(UUID playerId, final List getGameSession(playerId1).getMultiAmount(messages, min, max, options)); } - private void informOthers(UUID playerId) { + private void informOthers(UUID waitingPlayerId) { StringBuilder message = new StringBuilder(); if (game.getStep() != null) { message.append(game.getTurnStepType().toString()).append(" - "); } - message.append("Waiting for ").append(game.getPlayer(playerId).getLogName()); + message.append("Waiting for ").append(game.getPlayer(waitingPlayerId).getLogName()); for (final Entry entry : getGameSessionsMap().entrySet()) { - if (!entry.getKey().equals(playerId)) { + if (!entry.getKey().equals(waitingPlayerId)) { entry.getValue().inform(message.toString()); } } @@ -1030,7 +1030,7 @@ private void perform(UUID playerId, Command command, boolean informOthers) { // TODO: if watcher disconnects then game freezes with active timer, must be fix for such use case // same for another player (can be fixed by super-duper connection) if (informOthers) { - informOthers(playerId); + informOthers(realPlayerController.getId()); } } 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 790d85d31dbc..b4b7bd6c7c38 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java @@ -212,13 +212,14 @@ public static GameView prepareGameView(Game game, UUID playerId, UUID userId) { // game view calculation can take some time and can be called from non-game thread, // so use copy for thread save (protection from ConcurrentModificationException) Game sourceGame = game.copy(); + GameView gameView = new GameView(sourceGame.getState(), sourceGame, playerId, null); + // playable info (if opponent under control then show opponent's playable) Player player = sourceGame.getPlayer(playerId); // null for watcher - GameView gameView = new GameView(sourceGame.getState(), sourceGame, playerId, null); - if (player != null) { - if (gameView.getPriorityPlayerName().equals(player.getName())) { - gameView.setCanPlayObjects(player.getPlayableObjects(sourceGame, Zone.ALL)); - } + Player priorityPlayer = sourceGame.getPlayer(sourceGame.getPriorityPlayerId()); + Player controllingPlayer = priorityPlayer == null ? null : sourceGame.getPlayer(priorityPlayer.getTurnControlledBy()); + if (controllingPlayer != null && player == controllingPlayer) { + gameView.setCanPlayObjects(priorityPlayer.getPlayableObjects(sourceGame, Zone.ALL)); } processControlledPlayers(sourceGame, player, gameView); diff --git a/Mage.Tests/src/test/java/org/mage/test/load/LoadCallbackClient.java b/Mage.Tests/src/test/java/org/mage/test/load/LoadCallbackClient.java index f37ff6f5aac6..e69ee664e214 100644 --- a/Mage.Tests/src/test/java/org/mage/test/load/LoadCallbackClient.java +++ b/Mage.Tests/src/test/java/org/mage/test/load/LoadCallbackClient.java @@ -104,18 +104,17 @@ public void onCallback(ClientCallback callback) { GameClientMessage message = (GameClientMessage) callback.getData(); this.gameView = message.getGameView(); log.info(getLogStartInfo() + " target: " + message.getMessage()); - switch (message.getMessage()) { - case "Select a starting player": - session.sendPlayerUUID(gameId, playerId); - return; - case "Select a card to discard": - log.info(getLogStartInfo() + "hand size: " + gameView.getMyHand().size()); - SimpleCardView card = gameView.getMyHand().values().iterator().next(); - session.sendPlayerUUID(gameId, card.getId()); - return; - default: - log.error(getLogStartInfo() + "unknown GAME_TARGET message: " + message.toString()); - return; + if (message.getMessage().startsWith("Select a starting player")) { + session.sendPlayerUUID(gameId, playerId); + return; + } else if (message.getMessage().startsWith("Select a card to discard")) { + log.info(getLogStartInfo() + "hand size: " + gameView.getMyHand().size()); + SimpleCardView card = gameView.getMyHand().values().iterator().next(); + session.sendPlayerUUID(gameId, card.getId()); + return; + } else { + log.error(getLogStartInfo() + "unknown GAME_TARGET message: " + message.toString()); + return; } } diff --git a/Mage/src/main/java/mage/abilities/common/delayed/AtTheEndOfTurnStepPostDelayedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/AtTheEndOfTurnStepPostDelayedTriggeredAbility.java deleted file mode 100644 index d0078125fa32..000000000000 --- a/Mage/src/main/java/mage/abilities/common/delayed/AtTheEndOfTurnStepPostDelayedTriggeredAbility.java +++ /dev/null @@ -1,42 +0,0 @@ - -package mage.abilities.common.delayed; - -import mage.abilities.DelayedTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.game.Game; -import mage.game.events.GameEvent; - -/** - * @author nantuko - */ -public class AtTheEndOfTurnStepPostDelayedTriggeredAbility extends DelayedTriggeredAbility { - - public AtTheEndOfTurnStepPostDelayedTriggeredAbility(Effect effect) { - this(effect, false); - } - - public AtTheEndOfTurnStepPostDelayedTriggeredAbility(Effect effect, boolean usesStack) { - super(effect); - this.usesStack = usesStack; - setTriggerPhrase("At end of turn "); - } - - public AtTheEndOfTurnStepPostDelayedTriggeredAbility(AtTheEndOfTurnStepPostDelayedTriggeredAbility ability) { - super(ability); - } - - @Override - public AtTheEndOfTurnStepPostDelayedTriggeredAbility copy() { - return new AtTheEndOfTurnStepPostDelayedTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.END_TURN_STEP_POST; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - return true; - } -} diff --git a/Mage/src/main/java/mage/game/Game.java b/Mage/src/main/java/mage/game/Game.java index c6d8c2b0aa07..0dd53c256e20 100644 --- a/Mage/src/main/java/mage/game/Game.java +++ b/Mage/src/main/java/mage/game/Game.java @@ -550,6 +550,12 @@ default boolean isOpponent(Player player, UUID playerToCheckId) { @Deprecated // TODO: must research usage and remove it from all non engine code (example: Bestow ability, ProcessActions must be used instead) boolean checkStateAndTriggered(); + /** + * Play priority by all players + * + * @param activePlayerId starting priority player + * @param resuming false to reset passed priority and ask it again + */ void playPriority(UUID activePlayerId, boolean resuming); void resetControlAfterSpellResolve(UUID topId); diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index 66ea48734b64..dc2cb22fbaa8 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -2987,21 +2987,35 @@ public synchronized void firePriorityEvent(UUID playerId) { } String message; if (this.canPlaySorcery(playerId)) { - message = "Play spells and abilities."; + message = "Play spells and abilities"; } else { - message = "Play instants and activated abilities."; + message = "Play instants and activated abilities"; } - playerQueryEventSource.select(playerId, message); + + message += getControllingPlayerHint(playerId); + + Player player = this.getPlayer(playerId); + playerQueryEventSource.select(player.getTurnControlledBy(), message); getState().clearLookedAt(); getState().clearRevealed(); } + private String getControllingPlayerHint(UUID playerId) { + Player player = this.getPlayer(playerId); + Player controllingPlayer = this.getPlayer(player.getTurnControlledBy()); + if (player != controllingPlayer) { + return " (as " + player.getLogName() + ")"; + } else { + return ""; + } + } + @Override public synchronized void fireSelectEvent(UUID playerId, String message) { if (simulation) { return; } - playerQueryEventSource.select(playerId, message); + playerQueryEventSource.select(playerId, message + getControllingPlayerHint(playerId)); } @Override @@ -3009,7 +3023,7 @@ public synchronized void fireSelectEvent(UUID playerId, String message, Map mo if (simulation) { return; } - playerQueryEventSource.chooseMode(playerId, message, modes); + playerQueryEventSource.chooseMode(playerId, message + getControllingPlayerHint(playerId), modes); } @Override @@ -3066,7 +3080,7 @@ public void fireSelectTargetEvent(UUID playerId, MessageToClient message, Set abilities) { - playerQueryEventSource.target(playerId, message, abilities); + playerQueryEventSource.target(playerId, message + getControllingPlayerHint(playerId), abilities); } @Override @@ -3095,7 +3109,7 @@ public void fireSelectTargetEvent(UUID playerId, String message, List if (simulation) { return; } - playerQueryEventSource.target(playerId, message, perms, required); + playerQueryEventSource.target(playerId, message + getControllingPlayerHint(playerId), perms, required); } @Override @@ -3103,7 +3117,7 @@ public void fireGetAmountEvent(UUID playerId, String message, int min, int max) if (simulation) { return; } - playerQueryEventSource.amount(playerId, message, min, max); + playerQueryEventSource.amount(playerId, message + getControllingPlayerHint(playerId), min, max); } @Override @@ -3128,7 +3142,7 @@ public void fireChoosePileEvent(UUID playerId, String message, List { + if (player.isInGame() && !player.isGameUnderControl()) { + Player controllingPlayer = game.getPlayer(player.getTurnControlledBy()); + if (player != controllingPlayer && controllingPlayer != null) { + game.informPlayers(controllingPlayer.getLogName() + " lost control over " + player.getLogName()); + } + player.setGameUnderYourControl(true); + } + }); + + // add new under control TurnMod newControllerMod = game.getState().getTurnMods().useNextNewController(activePlayerId); if (newControllerMod != null && !newControllerMod.getNewControllerId().equals(activePlayerId)) { + // set player under new control // game logs added in child's call (controlPlayersTurn) game.getPlayer(newControllerMod.getNewControllerId()).controlPlayersTurn(game, activePlayerId, newControllerMod.getInfo()); } diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index 257f6443dc74..3f3073986d28 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -366,7 +366,7 @@ default boolean isComputer() { boolean isGameUnderControl(); /** - * Returns false in case you don't control the game. + * False in case you don't control the game. *

* Note: For effects like "You control target player during that player's * next turn". diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 4492b47d95a8..87e0bac88753 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -7,7 +7,6 @@ import mage.abilities.common.PassAbility; import mage.abilities.common.PlayLandAsCommanderAbility; import mage.abilities.common.WhileSearchingPlayFromLibraryAbility; -import mage.abilities.common.delayed.AtTheEndOfTurnStepPostDelayedTriggeredAbility; import mage.abilities.costs.*; import mage.abilities.costs.mana.AlternateManaPaymentAbility; import mage.abilities.costs.mana.ManaCost; @@ -15,7 +14,6 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.RestrictionUntapNotMoreThanEffect; -import mage.abilities.effects.common.LoseControlOnOtherPlayersControllerEffect; import mage.abilities.keyword.*; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.ManaOptions; @@ -609,11 +607,7 @@ public void controlPlayersTurn(Game game, UUID playerUnderControlId, String info if (!playerUnderControl.hasLeft() && !playerUnderControl.hasLost()) { playerUnderControl.setGameUnderYourControl(false); } - DelayedTriggeredAbility ability = new AtTheEndOfTurnStepPostDelayedTriggeredAbility( - new LoseControlOnOtherPlayersControllerEffect(this.getLogName(), playerUnderControl.getLogName())); - ability.setSourceId(getId()); - ability.setControllerId(getId()); - game.addDelayedTriggeredAbility(ability, null); + // control will reset on start of the turn } } diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 609861d1f915..d77bdca4a6ad 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -2127,9 +2127,10 @@ public static String getTurnInfo(GameState gameState) { return null; } - // not started game + // T0 - for not started game + // T2 - for starting of the turn if (gameState.getTurn().getStep() == null) { - return "T0"; + return "T" + gameState.getTurnNum(); } // normal game diff --git a/Mage/src/main/java/mage/util/GameLog.java b/Mage/src/main/java/mage/util/GameLog.java index 4e12e9fe55d8..b2a6bae3b274 100644 --- a/Mage/src/main/java/mage/util/GameLog.java +++ b/Mage/src/main/java/mage/util/GameLog.java @@ -160,10 +160,6 @@ public static String getPlayerConfirmColoredText(String name) { return "" + name + ""; } - public static String getSmallSecondLineText(String text) { - return "

" + text + "
"; - } - private static String getColorName(ObjectColor objectColor) { if (objectColor.isMulticolored()) { return LOG_COLOR_MULTI;