diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java index 27c99df3cf0..269d55b91ed 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/CMatchUI.java @@ -244,7 +244,6 @@ public final class CMatchUI private void initMatch(final FCollectionView sortedPlayers, final Collection myPlayers) { this.sortedPlayers = sortedPlayers; - this.setLocalPlayers(myPlayers); allHands = sortedPlayers.size() == getLocalPlayerCount(); final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(","); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/ControlWinLose.java b/forge-gui-desktop/src/main/java/forge/screens/match/ControlWinLose.java index 95e7fc47afb..f5d77366e87 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/ControlWinLose.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/ControlWinLose.java @@ -59,31 +59,26 @@ public class ControlWinLose { /** Action performed when "continue" button is pressed in default win/lose UI. */ public void actionOnContinue() { - SOverlayUtils.hideOverlay(); - saveOptions(); - for (final IGameController controller : matchUI.getGameControllers()) { - controller.nextGameDecision(NextGameDecision.CONTINUE); - } + nextGameAction(NextGameDecision.CONTINUE); } /** Action performed when "restart" button is pressed in default win/lose UI. */ public void actionOnRestart() { - SOverlayUtils.hideOverlay(); - saveOptions(); - for (final IGameController controller : matchUI.getGameControllers()) { - controller.nextGameDecision(NextGameDecision.NEW); - } + nextGameAction(NextGameDecision.NEW); } /** Action performed when "quit" button is pressed in default win/lose UI. */ public void actionOnQuit() { - // Reset other stuff - saveOptions(); - for (final IGameController controller : matchUI.getGameControllers()) { - controller.nextGameDecision(NextGameDecision.QUIT); - } + nextGameAction(NextGameDecision.QUIT); Singletons.getControl().setCurrentScreen(FScreen.HOME_SCREEN); + } + + private void nextGameAction(final NextGameDecision decision) { SOverlayUtils.hideOverlay(); + saveOptions(); + for (final IGameController controller : matchUI.getOriginalGameControllers()) { + controller.nextGameDecision(decision); + } } /** diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index 5e7bc2bde52..7e266c63521 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -110,7 +110,6 @@ public class MatchController extends AbstractGuiGame { @Override public void openView(final TrackableCollection myPlayers) { - setLocalPlayers(myPlayers); final boolean noHumans = !hasLocalPlayers(); final FCollectionView allPlayers = getGameView().getPlayers(); diff --git a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java index 7ed97b7835e..54917bfaad8 100644 --- a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java +++ b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java @@ -235,9 +235,15 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { if (ev.player.getGame().isGameOver()) { return null; } + + final PlayerControllerHuman newController; if (ev.newController instanceof PlayerControllerHuman) { - matchController.setGameController(PlayerView.get(ev.player), (PlayerControllerHuman) ev.newController); + newController = (PlayerControllerHuman) ev.newController; + } else { + newController = null; } + matchController.setGameController(PlayerView.get(ev.player), newController); + needPlayerControlUpdate = true; return processEvent(); } diff --git a/forge-gui/src/main/java/forge/interfaces/IGuiGame.java b/forge-gui/src/main/java/forge/interfaces/IGuiGame.java index 493e96388a0..3c627dca488 100644 --- a/forge-gui/src/main/java/forge/interfaces/IGuiGame.java +++ b/forge-gui/src/main/java/forge/interfaces/IGuiGame.java @@ -25,7 +25,9 @@ import forge.util.ITriggerEvent; public interface IGuiGame { void setGameView(GameView gameView); + void setOriginalGameController(PlayerView view, IGameController gameController); void setGameController(PlayerView player, IGameController gameController); + void setSpectator(IGameController spectator); void openView(TrackableCollection myPlayers); void afterGameEnd(); void showCombat(); diff --git a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java index 45add1adabc..54f2b22c8f6 100644 --- a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java +++ b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java @@ -5,6 +5,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.Timer; import java.util.TimerTask; @@ -27,37 +28,24 @@ import forge.game.player.PlayerView; import forge.interfaces.IGameController; import forge.interfaces.IGuiGame; import forge.interfaces.IMayViewCards; -import forge.util.FCollection; -import forge.util.FCollectionView; public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { - private FCollection localPlayers = new FCollection(); private PlayerView currentPlayer = null; - - protected final void setLocalPlayers(final Collection myPlayers) { - this.localPlayers = myPlayers == null ? new FCollection() : new FCollection(myPlayers); - this.currentPlayer = Iterables.getFirst(this.localPlayers, null); - this.autoPassUntilEndOfTurn.retainAll(myPlayers); - } - private void addLocalPlayer(final PlayerView player) { - this.localPlayers.add(player); - } - private void removeLocalPlayer(final PlayerView player) { - this.localPlayers.remove(player); - this.autoPassUntilEndOfTurn.remove(player); - } + private IGameController spectator = null; + private final Map gameControllers = Maps.newHashMap(); + private final Map originalGameControllers = Maps.newHashMap(); public final boolean hasLocalPlayers() { - return !localPlayers.isEmpty(); + return !gameControllers.isEmpty(); } - public final FCollectionView getLocalPlayers() { - return localPlayers; + public final Set getLocalPlayers() { + return gameControllers.keySet(); } public final int getLocalPlayerCount() { - return localPlayers.size(); + return gameControllers.size(); } public final boolean isLocalPlayer(final PlayerView player) { - return localPlayers.contains(player); + return gameControllers.containsKey(player); } public final PlayerView getCurrentPlayer() { @@ -65,6 +53,9 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { } @Override public final void setCurrentPlayer(final PlayerView player) { + if (!gameControllers.containsKey(player)) { + throw new IllegalArgumentException(); + } this.currentPlayer = player; updateCurrentPlayer(player); } @@ -79,24 +70,54 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { this.gameView = gameView; } - private final Map gameControllers = Maps.newHashMap(); public final IGameController getGameController() { - return gameControllers.get(getCurrentPlayer()); + return getGameController(getCurrentPlayer()); } - public final IGameController getGameController(final PlayerView p0) { - return gameControllers.get(p0); + public final IGameController getGameController(final PlayerView player) { + if (player == null) { + return spectator; + } + return gameControllers.get(player); } - public final Collection getGameControllers() { - return gameControllers.values(); + + public final Collection getOriginalGameControllers() { + return originalGameControllers.values(); } + + @Override + public void setOriginalGameController(final PlayerView player, final IGameController gameController) { + if (player == null || gameController == null) { + throw new IllegalArgumentException(); + } + originalGameControllers.put(player, gameController); + gameControllers.put(player, gameController); + } + @Override public void setGameController(final PlayerView player, final IGameController gameController) { - this.gameControllers.put(player, gameController); - if (gameController == null) { - addLocalPlayer(player); - } else { - removeLocalPlayer(player); + if (player == null) { + throw new IllegalArgumentException(); } + if (gameController == null) { + if (originalGameControllers.containsKey(player)) { + gameControllers.put(player, originalGameControllers.get(player)); + } else { + gameControllers.remove(player); + autoPassUntilEndOfTurn.remove(player); + final PlayerView currentPlayer = getCurrentPlayer(); + if (Objects.equals(player, currentPlayer)) { + // set current player to a value known to be legal + setCurrentPlayer(Iterables.getFirst(gameControllers.keySet(), null)); + } + } + } else { + this.gameControllers.put(player, gameController); + } + } + + @Override + public void setSpectator(final IGameController spectator) { + this.spectator = spectator; } @Override @@ -177,8 +198,8 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { } if (hasLocalPlayers()) { if (showConfirmDialog("This will concede the current game and you will lose.\n\nConcede anyway?", "Concede Game?", "Concede", "Cancel")) { - for (final IGameController c : getGameControllers()) { - // Concede each player on this Gui + for (final IGameController c : getOriginalGameControllers()) { + // Concede each player on this Gui (except mind-controlled players) c.concede(); } } @@ -204,9 +225,6 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { updateButtons(owner, "OK", "Cancel", okEnabled, cancelEnabled, focusOk); } - @Override - public abstract void updateButtons(PlayerView owner, String label1, String label2, boolean enable1, boolean enable2, boolean focus1); - // Auto-yield and other input-related code private final Set autoPassUntilEndOfTurn = Sets.newHashSet(); diff --git a/forge-gui/src/main/java/forge/match/HostedMatch.java b/forge-gui/src/main/java/forge/match/HostedMatch.java index dbf7c30cce1..e511f224798 100644 --- a/forge-gui/src/main/java/forge/match/HostedMatch.java +++ b/forge-gui/src/main/java/forge/match/HostedMatch.java @@ -169,7 +169,7 @@ public class HostedMatch { final IGuiGame gui = guis.get(p.getRegisteredPlayer()); humanController.setGui(gui); gui.setGameView(gameView); - gui.setGameController(p.getView(), humanController); + gui.setOriginalGameController(p.getView(), humanController); game.subscribeToEvents(new FControlGameEventHandler(humanController)); playersPerGui.add(gui, p.getView()); @@ -189,7 +189,7 @@ public class HostedMatch { final PlayerControllerHuman humanController = new WatchLocalGame(game, new LobbyPlayerHuman("Spectator"), gui); game.subscribeToEvents(new FControlGameEventHandler(humanController)); humanControllers.add(humanController); - gui.setGameController(null, humanController); + gui.setSpectator(humanController); gui.openView(null); } @@ -230,12 +230,11 @@ public class HostedMatch { } } }); - } public void registerSpectator(final IGuiGame gui) { final PlayerControllerHuman humanController = new WatchLocalGame(game, null, gui); - gui.setGameController(null, humanController); + gui.setSpectator(humanController); gui.openView(null); game.subscribeToEvents(new FControlGameEventHandler(humanController));