diff --git a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java index a1444d0a2a3..c07902f9a4c 100644 --- a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java +++ b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java @@ -54,7 +54,6 @@ import forge.interfaces.IGuiBase; import forge.item.PaperCard; import forge.match.input.InputQueue; import forge.model.FModel; -import forge.player.GamePlayerUtil; import forge.screens.deckeditor.CDeckEditorUI; import forge.screens.deckeditor.controllers.CEditorQuestCardShop; import forge.screens.match.CMatchUI; @@ -286,7 +285,7 @@ public class GuiDesktop implements IGuiBase { @Override public void updatePlayerControl() { - CMatchUI.SINGLETON_INSTANCE.initHandViews(GamePlayerUtil.getGuiPlayer()); + CMatchUI.SINGLETON_INSTANCE.initHandViews(); SLayoutIO.loadLayout(null); VMatchUI.SINGLETON_INSTANCE.populate(); for (VHand h : VMatchUI.SINGLETON_INSTANCE.getHands()) { diff --git a/forge-gui-desktop/src/main/java/forge/control/FControl.java b/forge-gui-desktop/src/main/java/forge/control/FControl.java index 19c1488e242..3c2211969e6 100644 --- a/forge-gui-desktop/src/main/java/forge/control/FControl.java +++ b/forge-gui-desktop/src/main/java/forge/control/FControl.java @@ -27,6 +27,8 @@ import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Set; @@ -75,11 +77,6 @@ import forge.quest.io.QuestDataIO; import forge.screens.deckeditor.CDeckEditorUI; import forge.screens.match.CMatchUI; import forge.screens.match.VMatchUI; -import forge.screens.match.controllers.CDock; -import forge.screens.match.controllers.CLog; -import forge.screens.match.controllers.CPlayers; -import forge.screens.match.controllers.CStack; -import forge.screens.match.views.VAntes; import forge.screens.match.views.VField; import forge.sound.MusicPlaylist; import forge.sound.SoundSystem; @@ -88,7 +85,6 @@ import forge.toolbox.FSkin; import forge.toolbox.special.PhaseIndicator; import forge.view.FFrame; import forge.view.FView; -import forge.view.IGameView; import forge.view.LocalGameView; import forge.view.PlayerView; import forge.view.WatchLocalGame; @@ -104,13 +100,14 @@ import forge.view.WatchLocalGame; public enum FControl implements KeyEventDispatcher { instance; + private Game game; + private List gameViews = new ArrayList(); private ForgeMenu forgeMenu; private List shortcuts; private JLayeredPane display; private FScreen currentScreen; private boolean altKeyLastDown; private CloseAction closeAction; - private PlayerView localPlayer; public static enum CloseAction { NONE, @@ -170,12 +167,12 @@ public enum FControl implements KeyEventDispatcher { } public CloseAction getCloseAction() { - return this.closeAction; + return closeAction; } public void setCloseAction(CloseAction closeAction0) { - if (this.closeAction == closeAction0) { return; } - this.closeAction = closeAction0; + if (closeAction == closeAction0) { return; } + closeAction = closeAction0; Singletons.getView().getNavigationBar().updateBtnCloseTooltip(); final ForgePreferences prefs = FModel.getPreferences(); @@ -186,10 +183,10 @@ public enum FControl implements KeyEventDispatcher { public boolean canExitForge(boolean forRestart) { String action = (forRestart ? "Restart" : "Exit"); String userPrompt = "Are you sure you wish to " + (forRestart ? "restart" : "exit") + " Forge?"; - if (this.gameView != null) { + if (game != null) { userPrompt = "A game is currently active. " + userPrompt; } - if (!FOptionPane.showConfirmDialog(userPrompt, action + " Forge", action, "Cancel", this.gameView == null)) { //default Yes if no game active + if (!FOptionPane.showConfirmDialog(userPrompt, action + " Forge", action, "Cancel", game == null)) { //default Yes if no game active return false; } if (!CDeckEditorUI.SINGLETON_INSTANCE.canSwitchAway(true)) { @@ -212,14 +209,14 @@ public enum FControl implements KeyEventDispatcher { // Preloads skin components (using progress bar). FSkin.loadFull(true); - this.soundSystem = new SoundSystem(GuiBase.getInterface()); + soundSystem = new SoundSystem(GuiBase.getInterface()); - this.shortcuts = KeyboardShortcuts.attachKeyboardShortcuts(); - this.display = FView.SINGLETON_INSTANCE.getLpnDocument(); + shortcuts = KeyboardShortcuts.attachKeyboardShortcuts(); + display = FView.SINGLETON_INSTANCE.getLpnDocument(); final ForgePreferences prefs = FModel.getPreferences(); - this.closeAction = CloseAction.valueOf(prefs.getPref(FPref.UI_CLOSE_ACTION)); + closeAction = CloseAction.valueOf(prefs.getPref(FPref.UI_CLOSE_ACTION)); FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("About to load current quest."); // Preload quest data if present @@ -267,14 +264,14 @@ public enum FControl implements KeyEventDispatcher { } public ForgeMenu getForgeMenu() { - if (this.forgeMenu == null) { - this.forgeMenu = new ForgeMenu(); + if (forgeMenu == null) { + forgeMenu = new ForgeMenu(); } - return this.forgeMenu; + return forgeMenu; } public FScreen getCurrentScreen() { - return this.currentScreen; + return currentScreen; } /** @@ -286,14 +283,14 @@ public enum FControl implements KeyEventDispatcher { public boolean setCurrentScreen(FScreen screen, boolean previousScreenClosed) { //TODO: Uncomment the line below if this function stops being used to refresh //the current screen in some places (such as Continue and Restart in the match screen) - //if (this.currentScreen == screen) { return; } + //if (currentScreen == screen) { return; } //give previous screen a chance to perform special switch handling and/or cancel switching away from screen - if (this.currentScreen != screen && !Singletons.getView().getNavigationBar().canSwitch(screen)) { + if (currentScreen != screen && !Singletons.getView().getNavigationBar().canSwitch(screen)) { return false; } - if (this.currentScreen == FScreen.MATCH_SCREEN) { //hide targeting overlay and reset image if was on match screen + if (currentScreen == FScreen.MATCH_SCREEN) { //hide targeting overlay and reset image if was on match screen SOverlayUtils.hideTargetingOverlay(); if (isMatchBackgroundImageVisible()) { FView.SINGLETON_INSTANCE.getPnlInsets().setForegroundImage(new ImageIcon()); @@ -304,7 +301,7 @@ public enum FControl implements KeyEventDispatcher { SOverlayUtils.hideOverlay(); ImageCache.clear(); //reduce memory usage by clearing image cache when switching screens - this.currentScreen = screen; + currentScreen = screen; //load layout for new current screen try { @@ -335,14 +332,14 @@ public enum FControl implements KeyEventDispatcher { } public boolean ensureScreenActive(FScreen screen) { - if (this.currentScreen == screen) { return true; } + if (currentScreen == screen) { return true; } return setCurrentScreen(screen); } /** @return List A list of attached keyboard shortcut descriptions and properties. */ public List getShortcuts() { - return this.shortcuts; + return shortcuts; } /** Remove all children from a specified layer. */ @@ -374,17 +371,6 @@ public enum FControl implements KeyEventDispatcher { return soundSystem; } - private Game game; - private IGameView gameView; - - public IGameView getGameView() { - return this.gameView; - } - - public PlayerView getLocalPlayer() { - return localPlayer; - } - public final void stopGame() { List pp = new ArrayList(); for (Player p : game.getPlayers()) { @@ -410,7 +396,7 @@ public enum FControl implements KeyEventDispatcher { } else { game.isGameOver(); // this is synchronized method - it's used to make Game-0 thread see changes made here - inputQueue.onGameOver(false); //release any waiting input, effectively passing priority + getInputQueue().onGameOver(false); //release any waiting input, effectively passing priority } if (playbackControl != null) { @@ -418,74 +404,148 @@ public enum FControl implements KeyEventDispatcher { } } - private InputQueue inputQueue; + public Player getCurrentPlayer() { + if (game == null) { return null; } + + // try current priority + Player currentPriority = game.getPhaseHandler().getPriorityPlayer(); + if (null != currentPriority && currentPriority.getLobbyPlayer() == getGuiPlayer()) { + return currentPriority; + } + + // otherwise find just any player, belonging to this lobbyplayer + for (Player p : game.getPlayers()) { + if (p.getLobbyPlayer() == getGuiPlayer()) { + return p; + } + } + + return null; + } + + public LocalGameView getGameView() { + return getGameView(getCurrentPlayer()); + } + public LocalGameView getGameView(Player player) { + switch (gameViews.size()) { + case 1: + return gameViews.get(0); + case 0: + return null; + default: + if (player != null && player.getController() instanceof PlayerControllerHuman) { + return ((PlayerControllerHuman)player.getController()).getGameView(); + } + return gameViews.get(0); + } + } + public InputQueue getInputQueue() { - return inputQueue; + LocalGameView gameView = getGameView(); + if (gameView != null) { + return gameView.getInputQueue(); + } + return null; } public final void startGameInSameMatch() { - this.startGameWithUi(this.game.getMatch()); + startGameWithUi(game.getMatch()); } public final void startGameAndClearMatch() { - if (this.game != null) { - this.game.getMatch().clearGamesPlayed(); + if (game != null) { + game.getMatch().clearGamesPlayed(); } startGameInSameMatch(); } public final void startGameWithUi(final Match match) { - if (this.gameView != null) { - this.setCurrentScreen(FScreen.MATCH_SCREEN); + if (game != null) { + setCurrentScreen(FScreen.MATCH_SCREEN); SOverlayUtils.hideOverlay(); FOptionPane.showMessageDialog("Cannot start a new game while another game is already in progress."); return; //TODO: See if it's possible to run multiple games at once without crashing } + setPlayerName(match.getPlayers()); - this.game = match.createGame(); - inputQueue = new InputQueue(game); - boolean anyPlayerIsAi = false; - for (final Player p : game.getPlayers()) { - if (p.getLobbyPlayer() instanceof LobbyPlayerAi) { - anyPlayerIsAi = true; - break; + getSoundSystem().setBackgroundMusic(MusicPlaylist.MATCH); + + game = match.createGame(); + + if (game.getRules().getGameType() == GameType.Quest) { + QuestController qc = FModel.getQuest(); + // Reset new list when the Match round starts, not when each game starts + if (game.getMatch().getPlayedGames().isEmpty()) { + qc.getCards().resetNewList(); } + game.subscribeToEvents(qc); // this one listens to player's mulligans ATM } - final LobbyPlayer me = getGuiPlayer(); - for (final Player p : game.getPlayers()) { - if (p.getLobbyPlayer().equals(me)) { + game.subscribeToEvents(getSoundSystem()); + + final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(","); + + // Instantiate all required field slots (user at 0) + final List sortedPlayers = new ArrayList(game.getRegisteredPlayers()); + Collections.sort(sortedPlayers, new Comparator() { + @Override + public int compare(Player p1, Player p2) { + int v1 = p1.getController() instanceof PlayerControllerHuman ? 0 : 1; + int v2 = p2.getController() instanceof PlayerControllerHuman ? 0 : 1; + return Integer.compare(v1, v2); + } + }); + + gameViews.clear(); + + int i = 0; + int avatarIndex = 0; + int humanCount = 0; + for (Player p : sortedPlayers) { + if (i < indices.length) { + avatarIndex = Integer.parseInt(indices[i]); + i++; + } + p.getLobbyPlayer().setAvatarIndex(avatarIndex); + + if (p.getController() instanceof PlayerControllerHuman) { final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController(); - this.gameView = controller.getGameView(); - this.fcVisitor = new FControlGameEventHandler(GuiBase.getInterface(), controller.getGameView()); - break; + LocalGameView gameView = controller.getGameView(); + game.subscribeToEvents(new FControlGameEventHandler(GuiBase.getInterface(), gameView)); + gameViews.add(gameView); + humanCount++; } } - if (!anyPlayerIsAi) { - // If there are no AI's, allow all players to see all cards (hotseat - // mode). - for (final Player p : game.getPlayers()) { - if (p.getController() instanceof PlayerControllerHuman) { - final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController(); - controller.setMayLookAtAllCards(true); - } + if (humanCount == 0) { //watch game but do not participate + LocalGameView gameView = new WatchLocalGame(game, GuiBase.getInterface()); + game.subscribeToEvents(new FControlGameEventHandler(GuiBase.getInterface(), gameView)); + gameViews.add(gameView); + } + else if (humanCount == sortedPlayers.size()) { + //if there are no AI's, allow all players to see all cards (hotseat mode). + for (Player p : sortedPlayers) { + ((PlayerControllerHuman) p.getController()).setMayLookAtAllCards(true); } } - boolean openAllHands = !anyPlayerIsAi; - if (this.gameView == null) { - // Watch game but do not participate - openAllHands = true; - final LocalGameView gameView = new WatchLocalGame(game, inputQueue); - this.gameView = gameView; - this.fcVisitor = new FControlGameEventHandler(GuiBase.getInterface(), gameView); - this.playbackControl = new FControlGamePlayback(GuiBase.getInterface(), gameView); - this.playbackControl.setGame(game); - this.game.subscribeToEvents(playbackControl); + List sortedPlayerViews = new ArrayList(); + for (Player p : sortedPlayers) { + sortedPlayerViews.add(getGameView().getPlayerView(p)); } + CMatchUI.SINGLETON_INSTANCE.initMatch(sortedPlayerViews, humanCount != 1); - attachToGame(this.gameView, openAllHands); + actuateMatchPreferences(); + + setCurrentScreen(FScreen.MATCH_SCREEN); + SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc()); + + // per player observers were set in CMatchUI.SINGLETON_INSTANCE.initMatch + //Set Field shown to current player. + if (humanCount > 0) { + final VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(sortedPlayerViews.get(0)); + SDisplayUtil.showTab(nextField); + } // It's important to run match in a different thread to allow GUI inputs to be invoked from inside game. // Game is set on pause while gui player takes decisions @@ -499,64 +559,14 @@ public enum FControl implements KeyEventDispatcher { } public final void endCurrentGame() { - if (this.gameView == null) { return; } + if (game == null) { return; } Singletons.getView().getNavigationBar().closeTab(FScreen.MATCH_SCREEN); - this.gameView = null; + game = null; } - private FControlGameEventHandler fcVisitor; private FControlGamePlayback playbackControl; - private void attachToGame(final IGameView game0, final boolean openAllHands) { - if (game0.getGameType().equals(GameType.Quest)) { - QuestController qc = FModel.getQuest(); - // Reset new list when the Match round starts, not when each game starts - if (game0.isFirstGameInMatch()) { - qc.getCards().resetNewList(); - } - game0.subscribeToEvents(qc); // this one listens to player's mulligans ATM - } - - game0.subscribeToEvents(Singletons.getControl().getSoundSystem()); - - //switch back to match screen music - Singletons.getControl().getSoundSystem().setBackgroundMusic(MusicPlaylist.MATCH); - - final LobbyPlayer humanLobbyPlayer = getGuiPlayer(); - // The UI controls should use these game data as models - final List players = game0.getPlayers(); - CMatchUI.SINGLETON_INSTANCE.initMatch(game0, players, humanLobbyPlayer, openAllHands); - - localPlayer = null; - for (final PlayerView p : players) { - if (p.getLobbyPlayer() == humanLobbyPlayer) { - localPlayer = p; - break; - } - } - - CDock.SINGLETON_INSTANCE.setModel(game0); - CStack.SINGLETON_INSTANCE.setModel(game0, localPlayer); - CPlayers.SINGLETON_INSTANCE.setModel(game0); - CLog.SINGLETON_INSTANCE.setModel(game0); - - actuateMatchPreferences(); - VAntes.SINGLETON_INSTANCE.setModel(players); - - setCurrentScreen(FScreen.MATCH_SCREEN); - SDisplayUtil.showTab(EDocID.REPORT_LOG.getDoc()); - - // Listen to DuelOutcome event to show ViewWinLose - game0.subscribeToEvents(fcVisitor); - - // per player observers were set in CMatchUI.SINGLETON_INSTANCE.initMatch - //Set Field shown to current player. - if (localPlayer != null) { - final VField nextField = CMatchUI.SINGLETON_INSTANCE.getFieldViewFor(localPlayer); - SDisplayUtil.showTab(nextField); - } - } /* (non-Javadoc) * @see java.awt.KeyEventDispatcher#dispatchKeyEvent(java.awt.event.KeyEvent) diff --git a/forge-gui-desktop/src/main/java/forge/control/KeyboardShortcuts.java b/forge-gui-desktop/src/main/java/forge/control/KeyboardShortcuts.java index 32cd1aa5da8..df258bd655b 100644 --- a/forge-gui-desktop/src/main/java/forge/control/KeyboardShortcuts.java +++ b/forge-gui-desktop/src/main/java/forge/control/KeyboardShortcuts.java @@ -115,7 +115,7 @@ public class KeyboardShortcuts { @Override public void actionPerformed(final ActionEvent e) { if (Singletons.getControl().getCurrentScreen() != FScreen.MATCH_SCREEN) { return; } - CDock.SINGLETON_INSTANCE.alphaStrike(); + Singletons.getControl().getGameView().alphaStrike(); } }; 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 2a6f6b3bec2..c67cc2c3bb1 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 @@ -27,7 +27,6 @@ import javax.swing.JMenu; import org.apache.commons.lang3.tuple.Pair; -import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.eventbus.EventBus; @@ -53,6 +52,7 @@ import forge.gui.framework.SDisplayUtil; import forge.item.InventoryItem; import forge.menus.IMenuProvider; import forge.model.FModel; +import forge.player.LobbyPlayerHuman; import forge.properties.ForgePreferences.FPref; import forge.quest.QuestDraftUtils; import forge.screens.match.controllers.CAntes; @@ -73,7 +73,6 @@ import forge.toolbox.special.PhaseLabel; import forge.view.CardView; import forge.view.CombatView; import forge.view.GameEntityView; -import forge.view.IGameView; import forge.view.PlayerView; import forge.view.ViewUtil; import forge.view.arcane.CardPanel; @@ -90,7 +89,6 @@ import forge.view.arcane.PlayArea; public enum CMatchUI implements ICDoc, IMenuProvider { SINGLETON_INSTANCE; - private IGameView game; private List sortedPlayers; private VMatchUI view; private boolean allHands; @@ -123,17 +121,14 @@ public enum CMatchUI implements ICDoc, IMenuProvider { /** * Instantiates at a match. */ - public void initMatch(final IGameView game, final List players, final LobbyPlayer localPlayer, final boolean allHands) { - this.game = game; - this.allHands = allHands; + public void initMatch(final List sortedPlayers0, final boolean allHands0) { + sortedPlayers = sortedPlayers0; + allHands = allHands0; view = VMatchUI.SINGLETON_INSTANCE; // TODO fix for use with multiplayer final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(","); - // Instantiate all required field slots (user at 0) - sortedPlayers = shiftPlayersPlaceLocalFirst(players, localPlayer); - final List fields = new ArrayList(); final List commands = new ArrayList(); @@ -141,7 +136,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { for (final PlayerView p : sortedPlayers) { // A field must be initialized after it's instantiated, to update player info. // No player, no init. - VField f = new VField(EDocID.Fields[i], p, localPlayer); + VField f = new VField(EDocID.Fields[i], p); VCommand c = new VCommand(EDocID.Commands[i], p); fields.add(f); commands.add(c); @@ -157,20 +152,17 @@ public enum CMatchUI implements ICDoc, IMenuProvider { view.setCommandViews(commands); view.setFieldViews(fields); - VPlayers.SINGLETON_INSTANCE.init(players); + VPlayers.SINGLETON_INSTANCE.init(sortedPlayers0); - initHandViews(localPlayer, allHands); + initHandViews(); } - public void initHandViews(final LobbyPlayer localPlayer) { - this.initHandViews(localPlayer, this.allHands); - } - public void initHandViews(final LobbyPlayer localPlayer, final boolean allHands) { + public void initHandViews() { final List hands = new ArrayList(); int i = 0; for (final PlayerView p : sortedPlayers) { - if (allHands || p.getLobbyPlayer().equals(localPlayer) || ViewUtil.mayViewAny(p.getHandCards())) { + if (allHands || p.getLobbyPlayer() instanceof LobbyPlayerHuman || ViewUtil.mayViewAny(p.getHandCards())) { VHand newHand = new VHand(EDocID.Hands[i], p); newHand.getLayoutControl().initialize(); hands.add(newHand); @@ -181,22 +173,6 @@ public enum CMatchUI implements ICDoc, IMenuProvider { view.setHandViews(hands); } - private List shiftPlayersPlaceLocalFirst(final List players, final LobbyPlayer localPlayer) { - // get an arranged list so that the first local player is at index 0 - final List sortedPlayers = Lists.newArrayList(players); - int ixFirstHuman = -1; - for (int i = 0; i < players.size(); i++) { - if (sortedPlayers.get(i).getLobbyPlayer() == localPlayer) { - ixFirstHuman = i; - break; - } - } - if (ixFirstHuman > 0) { - sortedPlayers.add(0, sortedPlayers.remove(ixFirstHuman)); - } - return sortedPlayers; - } - /** * Resets all phase buttons in all fields to "inactive", so highlight won't * be drawn on them. "Enabled" state remains the same. @@ -299,7 +275,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider { } public void showCombat(final CombatView combat) { - if (combat != null && combat.getNumAttackers() > 0 && game.peekStack() == null) { + if (combat != null && combat.getNumAttackers() > 0 && Singletons.getControl().getGameView().peekStack() == null) { if (selectedDocBeforeCombat == null) { IVDoc combatDoc = EDocID.REPORT_COMBAT.getDoc(); if (combatDoc.getParentCell() != null) { diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java index db86f5ddfee..82012b4255f 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDock.java @@ -40,7 +40,6 @@ import forge.toolbox.FSkin; import forge.toolbox.SaveOpenDialog; import forge.toolbox.SaveOpenDialog.Filetypes; import forge.view.FView; -import forge.view.IGameView; /** * Controls the dock panel in the match UI. @@ -52,11 +51,6 @@ public enum CDock implements ICDoc { SINGLETON_INSTANCE; private int arcState; - private IGameView game; - - public void setModel(final IGameView game0) { - game = game0; - } /** * End turn. @@ -156,33 +150,6 @@ public enum CDock implements ICDoc { //FModel.SINGLETON_INSTANCE.getPreferences().save(); } - /** Attack with everyone. */ - public void alphaStrike() { - game.alphaStrike(); - /* TODO: rewrite this! - final Player p = this.findAffectedPlayer(); - final Combat combat = FControl.instance.getObservedGame().getCombat(); - if (this.game.isCombatDeclareAttackers()) { - List defenders = p.getOpponents(); - - for (Card c : CardLists.filter(p.getCardsIn(ZoneType.Battlefield), Presets.CREATURES)) { - if (combat.isAttacking(c)) - continue; - - for(Player defender : defenders) - if( CombatUtil.canAttack(c, defender, combat)) { - combat.addAttacker(c, defender); - break; - } - } - //human.updateObservers(); - - // TODO Is this redrawing immediately? - FView.SINGLETON_INSTANCE.getFrame().repaint(); - } - */ - } - /** Toggle targeting overlay painting. */ public void toggleTargeting() { arcState++; @@ -271,7 +238,7 @@ public enum CDock implements ICDoc { VDock.SINGLETON_INSTANCE.getBtnAlphaStrike().setCommand(new UiCommand() { @Override public void run() { - alphaStrike(); + Singletons.getControl().getGameView().alphaStrike(); } }); VDock.SINGLETON_INSTANCE.getBtnTargeting().setCommand(new UiCommand() { diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CField.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CField.java index 536f2bfdd3f..5caf7196a94 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CField.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CField.java @@ -23,7 +23,6 @@ import java.awt.event.MouseListener; import com.google.common.base.Function; -import forge.LobbyPlayer; import forge.Singletons; import forge.UiCommand; import forge.game.zone.ZoneType; @@ -41,8 +40,6 @@ import forge.view.PlayerView; public class CField implements ICDoc { // The one who owns cards on this side of table private final PlayerView player; - // Tho one who looks at screen and 'performs actions' - private final LobbyPlayer viewer; private final VField view; private boolean initializedAlready = false; @@ -60,9 +57,8 @@ public class CField implements ICDoc { * @param v0   {@link forge.screens.match.views.VField} * @param playerViewer */ - public CField(final PlayerView player0, final VField v0, LobbyPlayer playerViewer) { + public CField(final PlayerView player0, final VField v0) { this.player = player0; - this.viewer = playerViewer; this.view = v0; final ZoneAction handAction = new ZoneAction(player, ZoneType.Hand, MatchConstants.HUMANHAND); @@ -74,7 +70,7 @@ public class CField implements ICDoc { @Override protected void doAction(final CardView c) { // activate cards only via your own flashback button - if (player.getLobbyPlayer() != CField.this.viewer) { + if (player.getLobbyPlayer() != Singletons.getControl().getGuiPlayer()) { return; } @@ -88,7 +84,7 @@ public class CField implements ICDoc { Function manaAction = new Function() { public Void apply(Byte colorCode) { - if (CField.this.player.getLobbyPlayer() == CField.this.viewer) { + if (CField.this.player.getLobbyPlayer() == Singletons.getControl().getGuiPlayer()) { Singletons.getControl().getGameView().useMana(colorCode.byteValue()); } return null; diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CLog.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CLog.java index 2dfe34c1a07..406b740f9a3 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CLog.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CLog.java @@ -5,8 +5,6 @@ import forge.UiCommand; import forge.FThreads; import forge.gui.framework.ICDoc; import forge.screens.match.views.VLog; -import forge.view.IGameView; - import java.util.Observable; import java.util.Observer; @@ -20,8 +18,6 @@ public enum CLog implements ICDoc, Observer { /** */ SINGLETON_INSTANCE; - private IGameView model; - /* (non-Javadoc) * @see forge.gui.framework.ICDoc#getCommandOnSelect() */ @@ -41,19 +37,10 @@ public enum CLog implements ICDoc, Observer { private final Runnable r = new Runnable() { @Override public void run() { - VLog.SINGLETON_INSTANCE.updateConsole(model); + VLog.SINGLETON_INSTANCE.updateConsole(); } }; - /** - * TODO: Write javadoc for this method. - * @param game0 - */ - public void setModel(final IGameView game0) { - model = game0; - model.addLogObserver(this); - } - /* (non-Javadoc) * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPlayers.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPlayers.java index 28a964f1134..b5f36c75ba9 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPlayers.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CPlayers.java @@ -3,7 +3,6 @@ package forge.screens.match.controllers; import forge.UiCommand; import forge.gui.framework.ICDoc; import forge.screens.match.views.VPlayers; -import forge.view.IGameView; /** * Controls the combat panel in the match UI. @@ -14,7 +13,6 @@ import forge.view.IGameView; public enum CPlayers implements ICDoc { /** */ SINGLETON_INSTANCE; - private IGameView game; /* (non-Javadoc) * @see forge.gui.framework.ICDoc#getCommandOnSelect() @@ -36,11 +34,6 @@ public enum CPlayers implements ICDoc { */ @Override public void update() { - VPlayers.SINGLETON_INSTANCE.update(game); + VPlayers.SINGLETON_INSTANCE.update(); } - - public void setModel(IGameView game) { - this.game = game; - } - } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CStack.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CStack.java index 2d2c50f0100..421527ead53 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CStack.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CStack.java @@ -5,8 +5,6 @@ import forge.gui.framework.EDocID; import forge.gui.framework.ICDoc; import forge.gui.framework.SDisplayUtil; import forge.screens.match.views.VStack; -import forge.view.IGameView; -import forge.view.PlayerView; /** * Controls the combat panel in the match UI. @@ -18,9 +16,6 @@ public enum CStack implements ICDoc { /** */ SINGLETON_INSTANCE; - private IGameView model; - private PlayerView localPlayer; - /* (non-Javadoc) * @see forge.gui.framework.ICDoc#getCommandOnSelect() */ @@ -39,12 +34,6 @@ public enum CStack implements ICDoc { @Override public void update() { SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc()); - VStack.SINGLETON_INSTANCE.updateStack(model, localPlayer); + VStack.SINGLETON_INSTANCE.updateStack(); } - - public void setModel(final IGameView game0, final PlayerView localPlayer) { - model = game0; - this.localPlayer = localPlayer; - } - } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java b/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java index 73d4aeeb133..d0518a45c50 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/menus/GameMenu.java @@ -119,7 +119,7 @@ public final class GameMenu { return new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - controller.alphaStrike(); + Singletons.getControl().getGameView().alphaStrike(); } }; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VAntes.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VAntes.java index cc89346a1f3..2cd928552cf 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VAntes.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VAntes.java @@ -18,7 +18,6 @@ package forge.screens.match.views; import java.awt.Dimension; -import java.util.List; import java.util.SortedSet; import java.util.TreeSet; @@ -26,6 +25,7 @@ import javax.swing.JPanel; import javax.swing.SwingConstants; import net.miginfocom.swing.MigLayout; +import forge.Singletons; import forge.gui.CardPicturePanel; import forge.gui.WrapLayout; import forge.gui.framework.DragCell; @@ -55,7 +55,6 @@ public enum VAntes implements IVDoc { private final FScrollPane scroller = new FScrollPane(pnl, false); private final SortedSet allAntes = new TreeSet(); - private Iterable players; //========== Constructor private VAntes() { pnl.setLayout(new WrapLayout()); @@ -72,9 +71,8 @@ public enum VAntes implements IVDoc { parentCell.getBody().setLayout(new MigLayout("insets 0, gap 0")); parentCell.getBody().add(scroller, "w 100%!, h 100%!"); } - - public final void setModel(final List players) { - this.players = players; + + public final void setModel() { update(); } @@ -122,7 +120,7 @@ public enum VAntes implements IVDoc { allAntes.clear(); pnl.removeAll(); - for (final PlayerView p : players) { + for (final PlayerView p : Singletons.getControl().getGameView().getPlayers()) { for (final CardView c : p.getAnteCards()) { final AntePanel pnlTemp = new AntePanel(c); allAntes.add(pnlTemp); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java index 9dd552b4e20..58accc375d4 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VField.java @@ -28,7 +28,6 @@ import javax.swing.border.Border; import javax.swing.border.LineBorder; import net.miginfocom.swing.MigLayout; -import forge.LobbyPlayer; import forge.game.zone.ZoneType; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; @@ -84,7 +83,7 @@ public class VField implements IVDoc { * @param p   {@link forge.game.player.Player} * @param id0   {@link forge.gui.framework.EDocID} */ - public VField(final EDocID id0, final PlayerView p, final LobbyPlayer playerViewer) { + public VField(final EDocID id0, final PlayerView p) { this.docID = id0; id0.setDoc(this); @@ -98,7 +97,7 @@ public class VField implements IVDoc { // (haven't looked into it too deeply). Doublestrike 12-04-12 tabletop = new PlayArea(scroller, id0 == EDocID.FIELD_1, player, ZoneType.Battlefield); - control = new CField(player, this, playerViewer); + control = new CField(player, this); avatarArea.setOpaque(false); avatarArea.setBackground(FSkin.getColor(FSkin.Colors.CLR_HOVER)); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VLog.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VLog.java index 62e6674d1ae..5fbf11f2d5b 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VLog.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VLog.java @@ -25,6 +25,7 @@ import net.miginfocom.swing.MigLayout; import com.google.common.collect.Lists; +import forge.Singletons; import forge.game.GameLogEntry; import forge.game.GameLogEntryType; import forge.gui.framework.DragCell; @@ -38,6 +39,7 @@ import forge.screens.match.controllers.CLog; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinFont; import forge.view.IGameView; +import forge.view.LocalGameView; /** * Assembles Swing components of game log report. @@ -124,8 +126,9 @@ public enum VLog implements IVDoc { *

* @param model contains list of log entries. */ - public void updateConsole(final IGameView model) { + public void updateConsole() { if (isGameLogConsoleVisible()) { + LocalGameView model = Singletons.getControl().getGameView(); resetDisplayIfNewGame(model); displayNewGameLogEntries(model); // Important : refreshLayout() needs to be called every update. diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VPlayers.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VPlayers.java index 966318b576c..58c60cde189 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VPlayers.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VPlayers.java @@ -28,6 +28,7 @@ import javax.swing.ScrollPaneConstants; import com.google.common.collect.Lists; import net.miginfocom.swing.MigLayout; +import forge.Singletons; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; @@ -39,7 +40,6 @@ import forge.toolbox.FScrollPanel; import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedLabel; import forge.view.CardView; -import forge.view.IGameView; import forge.view.PlayerView; /** @@ -142,10 +142,10 @@ public enum VPlayers implements IVDoc { //========== Observer update methods /** @param game {@link forge.game.player.Player} */ - public void update(final IGameView game) { + public void update() { // No need to update if this panel isn't showing if (parentCell == null || !this.equals(parentCell.getSelected())) { return; } - boolean isCommander = game.isCommander(); + boolean isCommander = Singletons.getControl().getGameView().isCommander(); for(final Entry rr : infoLBLs.entrySet()) { PlayerView p0 = rr.getKey(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java index be611ff2278..518568b6650 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VStack.java @@ -36,8 +36,10 @@ import javax.swing.border.EmptyBorder; import net.miginfocom.swing.MigLayout; import forge.ImageCache; +import forge.Singletons; import forge.card.CardDetailUtil; import forge.card.CardDetailUtil.DetailColors; +import forge.game.player.Player; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; @@ -51,7 +53,7 @@ import forge.toolbox.FSkin; import forge.toolbox.FSkin.SkinnedTextArea; import forge.view.CardView; import forge.view.IGameView; -import forge.view.PlayerView; +import forge.view.LocalGameView; import forge.view.StackItemView; import forge.view.arcane.CardPanel; @@ -132,9 +134,10 @@ public enum VStack implements IVDoc { //========== Observer update methods /** - * @param model + * @param models * @param viewer */ - public void updateStack(final IGameView model, final PlayerView localPlayer) { + public void updateStack() { + final LocalGameView model = Singletons.getControl().getGameView(); final List items = model.getStack(); tab.setText("Stack : " + items.size()); @@ -145,7 +148,7 @@ public enum VStack implements IVDoc { boolean isFirst = true; for (final StackItemView item : items) { - final StackInstanceTextArea tar = new StackInstanceTextArea(model, item, localPlayer); + final StackInstanceTextArea tar = new StackInstanceTextArea(model, item); scroller.add(tar, "pushx, growx" + (isFirst ? "" : ", gaptop 2px")); @@ -175,9 +178,10 @@ public enum VStack implements IVDoc { private final CardView sourceCard; - public StackInstanceTextArea(final IGameView game, final StackItemView item, final PlayerView localPlayer) { + public StackInstanceTextArea(final IGameView game, final StackItemView item) { sourceCard = item.getSource(); + final Player localPlayer = Singletons.getControl().getCurrentPlayer(); final String txt = (item.isOptionalTrigger() && item.getActivatingPlayer().equals(localPlayer) ? "(OPTIONAL) " : "") + item.getText(); @@ -302,7 +306,7 @@ public enum VStack implements IVDoc { add(jmiAlwaysNo); } - public void setStackInstance(final IGameView game, final StackItemView item, final PlayerView localPlayer) { + public void setStackInstance(final IGameView game, final StackItemView item, final Player localPlayer) { this.game = game; this.item = item; triggerID = Integer.valueOf(item.getSourceTrigger()); diff --git a/forge-gui-mobile/src/forge/GuiMobile.java b/forge-gui-mobile/src/forge/GuiMobile.java index 793904ac923..f5b10efcc15 100644 --- a/forge-gui-mobile/src/forge/GuiMobile.java +++ b/forge-gui-mobile/src/forge/GuiMobile.java @@ -239,12 +239,12 @@ public class GuiMobile implements IGuiBase { @Override public IButton getBtnOK() { - return FControl.getView().getPrompt().getBtnOk(); + return FControl.getView().getActivePrompt().getBtnOk(); } @Override public IButton getBtnCancel() { - return FControl.getView().getPrompt().getBtnCancel(); + return FControl.getView().getActivePrompt().getBtnCancel(); } @Override diff --git a/forge-gui-mobile/src/forge/screens/match/FControl.java b/forge-gui-mobile/src/forge/screens/match/FControl.java index a0518d6e86e..0618ab008bd 100644 --- a/forge-gui-mobile/src/forge/screens/match/FControl.java +++ b/forge-gui-mobile/src/forge/screens/match/FControl.java @@ -6,6 +6,8 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.EnumMap; import java.util.HashMap; import java.util.HashSet; @@ -23,7 +25,6 @@ import forge.Forge; import forge.Graphics; import forge.GuiBase; import forge.LobbyPlayer; -import forge.ai.LobbyPlayerAi; import forge.assets.FImage; import forge.assets.FSkin; import forge.assets.FTextureRegionImage; @@ -71,7 +72,6 @@ import forge.view.CardView; import forge.view.CardView.CardStateView; import forge.view.CombatView; import forge.view.GameEntityView; -import forge.view.IGameView; import forge.view.LocalGameView; import forge.view.PlayerView; import forge.view.WatchLocalGame; @@ -80,13 +80,10 @@ public class FControl { private FControl() { } //don't allow creating instance private static Game game; - private static IGameView gameView; + private static List gameViews = new ArrayList(); private static MatchScreen view; - private static InputQueue inputQueue; private static final EventBus uiEvents; - private static boolean gameHasHumanPlayer; private static final MatchUiEventVisitor visitor = new MatchUiEventVisitor(); - private static FControlGameEventHandler fcVisitor; private static FControlGamePlayback playbackControl; private static final Map avatarImages = new HashMap(); @@ -147,30 +144,63 @@ public class FControl { game.subscribeToEvents(qc); // this one listens to player's mulligans ATM } - inputQueue = new InputQueue(game); - game.subscribeToEvents(Forge.getSoundSystem()); - Player humanLobbyPlayer = game.getRegisteredPlayers().get(0); - // The UI controls should use these game data as models - initMatch(game.getRegisteredPlayers(), humanLobbyPlayer); + final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(","); - actuateMatchPreferences(); + // Instantiate all required field slots (user at 0) + final List sortedPlayers = new ArrayList(game.getRegisteredPlayers()); + Collections.sort(sortedPlayers, new Comparator() { + @Override + public int compare(Player p1, Player p2) { + int v1 = p1.getController() instanceof PlayerControllerHuman ? 0 : 1; + int v2 = p2.getController() instanceof PlayerControllerHuman ? 0 : 1; + return Integer.compare(v1, v2); + } + }); - // Listen to DuelOutcome event to show ViewWinLose - game.subscribeToEvents(fcVisitor); + gameViews.clear(); + List playerPanels = new ArrayList(); - // Add playback controls to match if needed - gameHasHumanPlayer = false; - boolean gameHasAiPlayer = false; - for (Player p : game.getPlayers()) { - if (p.getController().getLobbyPlayer() == getGuiPlayer()) { - gameHasHumanPlayer = true; - } else if (p.getLobbyPlayer() instanceof LobbyPlayerAi) { - gameHasAiPlayer = true; + int i = 0; + int avatarIndex = 0; + int humanCount = 0; + for (Player p : sortedPlayers) { + if (i < indices.length) { + avatarIndex = Integer.parseInt(indices[i]); + i++; + } + p.getLobbyPlayer().setAvatarIndex(avatarIndex); + + if (p.getController() instanceof PlayerControllerHuman) { + final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController(); + LocalGameView gameView = controller.getGameView(); + game.subscribeToEvents(new FControlGameEventHandler(GuiBase.getInterface(), gameView)); + gameViews.add(gameView); + humanCount++; } } - if (!gameHasHumanPlayer) { + + if (humanCount == 0) { //watch game but do not participate + LocalGameView gameView = new WatchLocalGame(game, GuiBase.getInterface()); + game.subscribeToEvents(new FControlGameEventHandler(GuiBase.getInterface(), gameView)); + gameViews.add(gameView); + } + else if (humanCount == sortedPlayers.size()) { + //if there are no AI's, allow all players to see all cards (hotseat mode). + for (Player p : sortedPlayers) { + ((PlayerControllerHuman) p.getController()).setMayLookAtAllCards(true); + } + } + + for (Player p : sortedPlayers) { + playerPanels.add(new VPlayerPanel(getGameView(p).getPlayerView(p), humanCount == 0 || p.getController() instanceof PlayerControllerHuman)); + } + view = new MatchScreen(playerPanels); + + if (humanCount == 0) { + playbackControl = new FControlGamePlayback(GuiBase.getInterface(), getGameView()); + playbackControl.setGame(game); game.subscribeToEvents(playbackControl); //add special object that pauses game if screen touched @@ -189,16 +219,7 @@ public class FControl { }); } - if (!gameHasAiPlayer) { - // If there are no AI's, allow all players to see all cards (hotseat - // mode). - for (final Player p : game.getPlayers()) { - if (p.getController() instanceof PlayerControllerHuman) { - final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController(); - controller.setMayLookAtAllCards(true); - } - } - } + actuateMatchPreferences(); Forge.openScreen(view); @@ -216,8 +237,21 @@ public class FControl { return game; } - public static IGameView getGameView() { - return gameView; + public static LocalGameView getGameView() { + return getGameView(getCurrentPlayer()); + } + public static LocalGameView getGameView(Player player) { + switch (gameViews.size()) { + case 1: + return gameViews.get(0); + case 0: + return null; + default: + if (player != null && player.getController() instanceof PlayerControllerHuman) { + return ((PlayerControllerHuman)player.getController()).getGameView(); + } + return gameViews.get(0); + } } public static MatchScreen getView() { @@ -225,7 +259,11 @@ public class FControl { } public static InputQueue getInputQueue() { - return inputQueue; + LocalGameView gameView = getGameView(); + if (gameView != null) { + return gameView.getInputQueue(); + } + return null; } public static boolean stopAtPhase(final PlayerView turn, final PhaseType phase) { @@ -234,69 +272,7 @@ public class FControl { } public static void endCurrentTurn() { - gameView.passPriorityUntilEndOfTurn(); - } - - public static void initMatch(final List players, Player localPlayer) { - final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(","); - - // Instantiate all required field slots (user at 0) - final List sortedPlayers = shiftPlayersPlaceLocalFirst(players, localPlayer); - - List playerPanels = new ArrayList(); - - int i = 0; - int avatarIndex = 0; - for (Player p : sortedPlayers) { - if (i < indices.length) { - avatarIndex = Integer.parseInt(indices[i]); - i++; - } - p.getLobbyPlayer().setAvatarIndex(avatarIndex); - } - - final LocalGameView localGameView; - final boolean isWatchingGame; - if (localPlayer.getController() instanceof PlayerControllerHuman) { - final PlayerControllerHuman controller = (PlayerControllerHuman) localPlayer.getController(); - localGameView = controller.getGameView(); - gameView = localGameView; - fcVisitor = new FControlGameEventHandler(GuiBase.getInterface(), localGameView); - isWatchingGame = false; - } else { - // Watch game but do not participate - localGameView = new WatchLocalGame(game, inputQueue); - gameView = localGameView; - fcVisitor = new FControlGameEventHandler(GuiBase.getInterface(), localGameView); - isWatchingGame = true; - } - - for (Player p : sortedPlayers) { - playerPanels.add(new VPlayerPanel(localGameView.getPlayerView(p))); - } - view = new MatchScreen(localGameView, localGameView.getPlayerView(localPlayer), playerPanels); - - if (isWatchingGame) { - playbackControl = new FControlGamePlayback(GuiBase.getInterface(), localGameView); - playbackControl.setGame(game); - game.subscribeToEvents(playbackControl); - } - } - - private static List shiftPlayersPlaceLocalFirst(final List players, Player localPlayer) { - // get an arranged list so that the first local player is at index 0 - List sortedPlayers = new ArrayList(players); - int ixFirstHuman = -1; - for (int i = 0; i < players.size(); i++) { - if (sortedPlayers.get(i) == localPlayer) { - ixFirstHuman = i; - break; - } - } - if (ixFirstHuman > 0) { - sortedPlayers.add(0, sortedPlayers.remove(ixFirstHuman)); - } - return sortedPlayers; + getGameView().passPriorityUntilEndOfTurn(); } public static void resetAllPhaseButtons() { @@ -306,7 +282,10 @@ public class FControl { } public static void showMessage(final String s0) { - view.getPrompt().setMessage(s0); + view.getActivePrompt().setMessage(s0); + } + public static void showMessage(final PlayerView playerView, final String s0) { + view.getPrompt(playerView).setMessage(s0); } public static VPlayerPanel getPlayerPanel(final PlayerView playerView) { @@ -333,6 +312,8 @@ public class FControl { } public static Player getCurrentPlayer() { + if (game == null) { return null; } + // try current priority Player currentPriority = game.getPhaseHandler().getPriorityPlayer(); if (null != currentPriority && currentPriority.getLobbyPlayer() == getGuiPlayer()) { @@ -350,7 +331,7 @@ public class FControl { } public static void alphaStrike() { - gameView.alphaStrike(); + getGameView().alphaStrike(); } public static void showCombat(CombatView combat) { @@ -537,7 +518,7 @@ public class FControl { } else { game.isGameOver(); // this is synchronized method - it's used to make Game-0 thread see changes made here - inputQueue.onGameOver(false); //release any waiting input, effectively passing priority + getInputQueue().onGameOver(false); //release any waiting input, effectively passing priority } if (playbackControl != null) { @@ -556,6 +537,7 @@ public class FControl { public static void pause() { Forge.getSoundSystem().pause(); //pause playback if needed + InputQueue inputQueue = getInputQueue(); if (inputQueue != null && inputQueue.getInput() instanceof InputPlaybackControl) { ((InputPlaybackControl)inputQueue.getInput()).pause(); } diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index 7fcd92d3af6..3390e953b8a 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -14,6 +14,7 @@ import com.google.common.collect.Maps; import forge.Forge; import forge.menu.FMenuBar; import forge.model.FModel; +import forge.player.LobbyPlayerHuman; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.screens.FScreen; @@ -34,7 +35,6 @@ import forge.animation.AbilityEffect; import forge.assets.FSkinColor; import forge.assets.FSkinTexture; import forge.assets.FSkinColor.Colors; -import forge.game.zone.ZoneType; import forge.toolbox.FEvent; import forge.toolbox.FEvent.FEventHandler; import forge.toolbox.FScrollPane; @@ -42,52 +42,72 @@ import forge.util.Callback; import forge.view.CardView; import forge.view.CombatView; import forge.view.GameEntityView; -import forge.view.IGameView; import forge.view.PlayerView; public class MatchScreen extends FScreen { public static FSkinColor BORDER_COLOR = FSkinColor.get(Colors.CLR_BORDERS); - private final IGameView gameView; private final Map playerPanels = Maps.newHashMap(); - private final VPrompt prompt; private final VLog log; private final VStack stack; private final VDevMenu devMenu; private final FieldScroller scroller; + private final VPrompt bottomPlayerPrompt, topPlayerPrompt; private VPlayerPanel bottomPlayerPanel, topPlayerPanel; private AbilityEffect activeEffect; - public MatchScreen(final IGameView game, PlayerView localPlayer, List playerPanels0) { + public MatchScreen(List playerPanels0) { super(new FMenuBar()); - this.gameView = game; scroller = add(new FieldScroller()); + + int humanCount = 0; for (VPlayerPanel playerPanel : playerPanels0) { playerPanels.put(playerPanel.getPlayer(), scroller.add(playerPanel)); + if (playerPanel.getPlayer().getLobbyPlayer() instanceof LobbyPlayerHuman) { + humanCount++; + } } bottomPlayerPanel = playerPanels0.get(0); topPlayerPanel = playerPanels0.get(1); topPlayerPanel.setFlipped(true); - bottomPlayerPanel.setSelectedZone(ZoneType.Hand); - prompt = add(new VPrompt("", "", + bottomPlayerPrompt = add(new VPrompt("", "", new FEventHandler() { @Override public void handleEvent(FEvent e) { - game.selectButtonOk(); + FControl.getGameView().selectButtonOk(); } }, new FEventHandler() { @Override public void handleEvent(FEvent e) { - game.selectButtonCancel(); + FControl.getGameView().selectButtonCancel(); } })); - log = new VLog(game); + if (humanCount > 1) { //show top prompt if multiple human players + topPlayerPrompt = add(new VPrompt("", "", + new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + FControl.getGameView().selectButtonOk(); + } + }, + new FEventHandler() { + @Override + public void handleEvent(FEvent e) { + FControl.getGameView().selectButtonCancel(); + } + })); + } + else { + topPlayerPrompt = null; + } + + log = new VLog(); log.setDropDownContainer(this); - stack = new VStack(game, localPlayer); + stack = new VStack(); stack.setDropDownContainer(this); devMenu = new VDevMenu(); devMenu.setDropDownContainer(this); @@ -96,7 +116,7 @@ public class MatchScreen extends FScreen { players.setDropDownContainer(this); FMenuBar menuBar = (FMenuBar)getHeader(); - menuBar.addTab("Game", new VGameMenu(game)); + menuBar.addTab("Game", new VGameMenu()); menuBar.addTab("Players (" + playerPanels.size() + ")", players); menuBar.addTab("Log", log); menuBar.addTab("Dev", devMenu); @@ -109,6 +129,20 @@ public class MatchScreen extends FScreen { devMenu.getMenuTab().setVisible(ForgePreferences.DEV_MODE); } + public VPrompt getActivePrompt() { + if (topPlayerPrompt != null && topPlayerPanel.getPlayer().equals(FControl.getCurrentPlayer())) { + return topPlayerPrompt; + } + return bottomPlayerPrompt; + } + + public VPrompt getPrompt(PlayerView playerView) { + if (topPlayerPrompt == null || bottomPlayerPanel.getPlayer() == playerView) { + return bottomPlayerPrompt; + } + return topPlayerPrompt; + } + public VLog getLog() { return log; } @@ -117,10 +151,6 @@ public class MatchScreen extends FScreen { return stack; } - public VPrompt getPrompt() { - return prompt; - } - public VPlayerPanel getTopPlayerPanel() { return topPlayerPanel; } @@ -142,8 +172,12 @@ public class MatchScreen extends FScreen { @Override protected void doLayout(float startY, float width, float height) { + if (topPlayerPrompt != null) { + bottomPlayerPrompt.setBounds(0, startY, width, VPrompt.HEIGHT); + startY += VPrompt.HEIGHT; + } scroller.setBounds(0, startY, width, height - VPrompt.HEIGHT - startY); - prompt.setBounds(0, height - VPrompt.HEIGHT, width, VPrompt.HEIGHT); + bottomPlayerPrompt.setBounds(0, height - VPrompt.HEIGHT, width, VPrompt.HEIGHT); } @Override @@ -162,7 +196,7 @@ public class MatchScreen extends FScreen { } //draw arrows for combat - final CombatView combat = gameView.getCombat(); + final CombatView combat = FControl.getGameView().getCombat(); if (combat != null) { for (final CardView attacker : combat.getAttackers()) { //connect each attacker with planeswalker it's attacking if applicable @@ -190,12 +224,12 @@ public class MatchScreen extends FScreen { switch (keyCode) { case Keys.ENTER: case Keys.SPACE: - if (prompt.getBtnOk().trigger()) { //trigger OK on Enter or Space + if (getActivePrompt().getBtnOk().trigger()) { //trigger OK on Enter or Space return true; } - return prompt.getBtnCancel().trigger(); //trigger Cancel if can't trigger OK + return getActivePrompt().getBtnCancel().trigger(); //trigger Cancel if can't trigger OK case Keys.ESCAPE: - return prompt.getBtnCancel().trigger(); //otherwise trigger Cancel + return getActivePrompt().getBtnCancel().trigger(); //otherwise trigger Cancel case Keys.BACK: return true; //suppress Back button so it's not bumped when trying to press OK or Cancel buttons case Keys.A: //alpha strike on Ctrl+A @@ -218,7 +252,7 @@ public class MatchScreen extends FScreen { break; case Keys.Z: //undo on Ctrl+Z if (KeyInputAdapter.isCtrlKeyDown()) { - gameView.tryUndoLastAction(); + FControl.getGameView().tryUndoLastAction(); return true; } break; diff --git a/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java b/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java index 6df096659a7..cc883ff78d7 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VGameMenu.java @@ -14,13 +14,9 @@ import forge.screens.match.FControl; import forge.screens.settings.SettingsScreen; import forge.toolbox.FEvent; import forge.toolbox.FEvent.FEventHandler; -import forge.view.IGameView; public class VGameMenu extends FDropDownMenu { - private final IGameView gameView; - - public VGameMenu(IGameView gameView0) { - gameView = gameView0; + public VGameMenu() { } @Override @@ -71,7 +67,7 @@ public class VGameMenu extends FDropDownMenu { //if re-enabling auto-yields, auto-yield to current ability on stack if applicable SpellAbility ability = game.getStack().peekAbility(); if (ability != null && ability.isAbility() && localPlayer.getController().shouldAutoYield(ability.toUnsuppressedString())) { - gameView.passPriority(); + FControl.getGameView().passPriority(); } } } diff --git a/forge-gui-mobile/src/forge/screens/match/views/VLog.java b/forge-gui-mobile/src/forge/screens/match/views/VLog.java index fa4ee83e87c..aba2c6f6904 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VLog.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VLog.java @@ -14,9 +14,9 @@ import forge.game.GameLogEntryType; import forge.menu.FDropDown; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; +import forge.screens.match.FControl; import forge.toolbox.FDisplayObject; import forge.util.Utils; -import forge.view.IGameView; public class VLog extends FDropDown { private static final float PADDING = Utils.scale(5); @@ -25,10 +25,7 @@ public class VLog extends FDropDown { private static final FSkinColor ROW_COLOR = ALT_ROW_COLOR.darker(); private static final FSkinColor FORE_COLOR = FSkinColor.get(Colors.CLR_TEXT); - private final IGameView gameView; - - public VLog(IGameView log0) { - gameView = log0; + public VLog() { } @Override @@ -48,7 +45,7 @@ public class VLog extends FDropDown { clear(); GameLogEntryType logVerbosityFilter = GameLogEntryType.valueOf(FModel.getPreferences().getPref(FPref.DEV_LOG_ENTRY_TYPE)); - List logEntrys = gameView.getLogEntries(logVerbosityFilter); + List logEntrys = FControl.getGameView().getLogEntries(logVerbosityFilter); LogEntryDisplay logEntryDisplay; float width = maxWidth - getMenuTab().getScreenPosition().x; //stretch from tab to edge of screen diff --git a/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java b/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java index 6f6306771b9..612a283a509 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VPlayerPanel.java @@ -44,9 +44,10 @@ public class VPlayerPanel extends FContainer { private final List tabs = new ArrayList(); private InfoTab selectedTab; - public VPlayerPanel(PlayerView player0) { + public VPlayerPanel(PlayerView player0, boolean showHand) { player = player0; phaseIndicator = add(new VPhaseIndicator()); + field = add(new VField(player)); avatar = add(new VAvatar(player)); lblLife = add(new LifeLabel()); @@ -65,6 +66,10 @@ public class VPlayerPanel extends FContainer { addZoneDisplay(ZoneType.Exile, FSkinImage.EXILE); commandZone = add(new CommandZoneDisplay(player)); + + if (showHand) { + setSelectedZone(ZoneType.Hand); + } } public PlayerView getPlayer() { diff --git a/forge-gui-mobile/src/forge/screens/match/views/VStack.java b/forge-gui-mobile/src/forge/screens/match/views/VStack.java index ff12564825d..ffcc794a1cb 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VStack.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VStack.java @@ -19,6 +19,7 @@ import forge.card.CardDetailUtil; import forge.card.CardRenderer; import forge.card.CardZoom; import forge.card.CardDetailUtil.DetailColors; +import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.menu.FCheckBoxMenuItem; import forge.menu.FDropDown; @@ -47,17 +48,13 @@ public class VStack extends FDropDown { private static final float ALPHA_COMPOSITE = 0.5f; private static final TextRenderer textRenderer = new TextRenderer(true); - private final IGameView gameView; - private final PlayerView localPlayer; private StackInstanceDisplay activeItem; private StackItemView activeStackInstance; private Map playersWithValidTargets; private int stackSize; - public VStack(IGameView gameView0, PlayerView localPlayer0) { - gameView = gameView0; - localPlayer = localPlayer0; + public VStack() { } @Override @@ -93,7 +90,7 @@ public class VStack extends FDropDown { activeStackInstance = null; //reset before updating stack restoreOldZones(); - final List stack = gameView.getStack(); + final List stack = FControl.getGameView().getStack(); if (stackSize != stack.size()) { int oldStackSize = stackSize; stackSize = stack.size(); @@ -124,7 +121,7 @@ public class VStack extends FDropDown { float totalWidth = maxWidth - FControl.getView().getTopPlayerPanel().getTabs().iterator().next().getRight(); //keep avatar, life total, and hand tab visible to left of stack float width = totalWidth - 2 * MARGINS; - final List stack = gameView.getStack(); + final List stack = FControl.getGameView().getStack(); if (stack.isEmpty()) { //show label if stack empty FLabel label = add(new FLabel.Builder().text("[Empty]").font(FONT).align(HAlignment.CENTER).build()); @@ -204,7 +201,7 @@ public class VStack extends FDropDown { text = stackInstance.getText(); if (stackInstance.isOptionalTrigger() && - stackInstance0.getActivatingPlayer().getLobbyPlayer().equals(localPlayer)) { + stackInstance0.getActivatingPlayer().equals(FControl.getCurrentPlayer())) { text = "(OPTIONAL) " + text; } @@ -227,11 +224,14 @@ public class VStack extends FDropDown { VStack.this.updateSizeAndPosition(); return true; } - if (localPlayer != null) { //don't show menu if tapping on art + Player player = FControl.getCurrentPlayer(); + if (player != null) { //don't show menu if tapping on art if (stackInstance.isAbility()) { FPopupMenu menu = new FPopupMenu() { @Override protected void buildMenu() { + final IGameView gameView = FControl.getGameView(); + final Player player = FControl.getCurrentPlayer(); final String key = stackInstance.getKey(); final boolean autoYield = gameView.shouldAutoYield(key); addItem(new FCheckBoxMenuItem("Auto-Yield", autoYield, @@ -245,7 +245,7 @@ public class VStack extends FDropDown { } } })); - if (stackInstance.isOptionalTrigger() && stackInstance.getActivatingPlayer() == localPlayer) { + if (stackInstance.isOptionalTrigger() && stackInstance.getActivatingPlayer().equals(player)) { final int triggerID = stackInstance.getSourceTrigger(); addItem(new FCheckBoxMenuItem("Always Yes", gameView.shouldAlwaysAcceptTrigger(triggerID), diff --git a/forge-gui/src/main/java/forge/match/input/InputProxy.java b/forge-gui/src/main/java/forge/match/input/InputProxy.java index 66a013d44cb..4ed0a013414 100644 --- a/forge-gui/src/main/java/forge/match/input/InputProxy.java +++ b/forge-gui/src/main/java/forge/match/input/InputProxy.java @@ -22,12 +22,10 @@ import java.util.Observer; import java.util.concurrent.atomic.AtomicReference; import forge.FThreads; -import forge.game.Game; import forge.interfaces.IGuiBase; -import forge.player.PlayerControllerHuman; import forge.util.ITriggerEvent; -import forge.util.gui.SOptionPane; import forge.view.CardView; +import forge.view.LocalGameView; import forge.view.PlayerView; import forge.view.SpellAbilityView; @@ -43,48 +41,21 @@ public class InputProxy implements Observer { /** The input. */ private AtomicReference input = new AtomicReference(); - private final Game game; + private final LocalGameView gameView; // private static final boolean DEBUG_INPUT = true; // false; - private final PlayerControllerHuman controller; - public InputProxy(final PlayerControllerHuman controller, final Game game) { - this.controller = controller; - this.game = game; + public InputProxy(final LocalGameView gameView0) { + this.gameView = gameView0; } private IGuiBase getGui() { - return this.controller.getGui(); - } - - public boolean passPriority() { - return passPriority(false); - } - public boolean passPriorityUntilEndOfTurn() { - return passPriority(true); - } - private boolean passPriority(final boolean passUntilEndOfTurn) { - final Input inp = getInput(); - if (inp instanceof InputPassPriority) { - if (passUntilEndOfTurn) { - controller.autoPassUntilEndOfTurn(); - } - inp.selectButtonOK(); - return true; - } - - FThreads.invokeInEdtNowOrLater(getGui(), new Runnable() { - @Override - public void run() { - SOptionPane.showMessageDialog(getGui(), "Cannot pass priority at this time."); - } - }); - return false; + return this.gameView.getGui(); } @Override public final void update(final Observable observable, final Object obj) { - final Input nextInput = getGui().getInputQueue().getActualInput(game); + final Input nextInput = gameView.getInputQueue().getActualInput(gameView); /* if(DEBUG_INPUT) System.out.printf("%s ... \t%s on %s, \tstack = %s%n", FThreads.debugGetStackTraceItem(6, true), nextInput == null ? "null" : nextInput.getClass().getSimpleName(), @@ -137,7 +108,7 @@ public class InputProxy implements Observer { public final void selectPlayer(final PlayerView player, final ITriggerEvent triggerEvent) { final Input inp = getInput(); if (inp != null) { - inp.selectPlayer(controller.getPlayer(player), triggerEvent); + inp.selectPlayer(gameView.getPlayer(player), triggerEvent); } } @@ -153,7 +124,7 @@ public class InputProxy implements Observer { public final boolean selectCard(final CardView cardView, final ITriggerEvent triggerEvent) { final Input inp = getInput(); if (inp != null) { - return inp.selectCard(controller.getCard(cardView), triggerEvent); + return inp.selectCard(gameView.getCard(cardView), triggerEvent); } return false; } @@ -161,7 +132,7 @@ public class InputProxy implements Observer { public final void selectAbility(final SpellAbilityView ab) { final Input inp = getInput(); if (inp != null) { - inp.selectAbility(controller.getSpellAbility(ab)); + inp.selectAbility(gameView.getSpellAbility(ab)); } } @@ -180,7 +151,7 @@ public class InputProxy implements Observer { } /** @return {@link forge.gui.InputProxy.InputBase} */ - private Input getInput() { + public Input getInput() { return this.input.get(); } } diff --git a/forge-gui/src/main/java/forge/match/input/InputQueue.java b/forge-gui/src/main/java/forge/match/input/InputQueue.java index fd24b86dc59..6873c861009 100644 --- a/forge-gui/src/main/java/forge/match/input/InputQueue.java +++ b/forge-gui/src/main/java/forge/match/input/InputQueue.java @@ -22,8 +22,7 @@ import java.util.concurrent.BlockingDeque; import java.util.concurrent.LinkedBlockingDeque; import forge.game.Game; -import forge.game.player.Player; -import forge.player.PlayerControllerHuman; +import forge.view.IGameView; /** *

@@ -37,22 +36,18 @@ public class InputQueue extends Observable { private final BlockingDeque inputStack = new LinkedBlockingDeque(); private final InputLockUI inputLock; - public InputQueue(final Game game) { + public InputQueue(final Game game, final InputProxy inputProxy) { inputLock = new InputLockUI(game, this); - for (final Player p : game.getPlayers()) { - if (p.getController() instanceof PlayerControllerHuman) { - this.addObserver(((PlayerControllerHuman) p.getController()).getInputProxy()); - } - } + addObserver(inputProxy); } public final void updateObservers() { - this.setChanged(); - this.notifyObservers(); + setChanged(); + notifyObservers(); } public final Input getInput() { - return inputStack.isEmpty() ? null : this.inputStack.peek(); + return inputStack.isEmpty() ? null : inputStack.peek(); } public final void removeInput(Input inp) { @@ -71,9 +66,9 @@ public class InputQueue extends Observable { * * @return a {@link forge.gui.input.InputBase} object. */ - public final Input getActualInput(final Game game) { + public final Input getActualInput(final IGameView gameView) { Input topMost = inputStack.peek(); // incoming input to Control - if (topMost != null && !game.isGameOver()) { + if (topMost != null && !gameView.isGameOver()) { return topMost; } return inputLock; @@ -85,10 +80,10 @@ public class InputQueue extends Observable { } public void setInput(final InputSynchronized input) { - this.inputStack.push(input); + inputStack.push(input); inputLock.setGui(input.getGui()); syncPoint(); - this.updateObservers(); + updateObservers(); } public void syncPoint() { diff --git a/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java b/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java index ab7af5241cc..9c011f393d3 100644 --- a/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java +++ b/forge-gui/src/main/java/forge/match/input/InputSyncronizedBase.java @@ -29,7 +29,6 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn cdlDone.countDown(); } - public void showAndWait() { getGui().getInputQueue().setInput(this); awaitLatchRelease(); diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index 85d70f13dfa..93b0583ec96 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -31,6 +31,7 @@ import com.google.common.collect.Maps; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; +import forge.FThreads; import forge.LobbyPlayer; import forge.achievement.AchievementCollection; import forge.card.CardCharacteristicName; @@ -118,9 +119,6 @@ import forge.view.StackItemView; * Handles phase skips for now. */ public class PlayerControllerHuman extends PlayerController { - - private IGuiBase gui; - private final InputProxy inputProxy; private final GameView gameView; /** * Cards this player may look at right now, for example when searching a @@ -131,9 +129,7 @@ public class PlayerControllerHuman extends PlayerController { public PlayerControllerHuman(final Game game0, final Player p, final LobbyPlayer lp, final IGuiBase gui) { super(game0, p, lp); - this.gui = gui; - this.inputProxy = new InputProxy(this, game0); - this.gameView = new GameView(game0); + this.gameView = new GameView(game0, gui); // aggressively cache a view for each player (also caches cards) for (final Player player : game.getRegisteredPlayers()) { @@ -142,11 +138,11 @@ public class PlayerControllerHuman extends PlayerController { } public IGuiBase getGui() { - return gui; + return gameView.getGui(); } public InputProxy getInputProxy() { - return inputProxy; + return gameView.getInputProxy(); } public LocalGameView getGameView() { @@ -1334,8 +1330,8 @@ public class PlayerControllerHuman extends PlayerController { * What follows are the View methods. */ private class GameView extends LocalGameView { - public GameView(Game game) { - super(game); + public GameView(Game game0, IGuiBase gui0) { + super(game0, gui0); } @Override @@ -1395,12 +1391,29 @@ public class PlayerControllerHuman extends PlayerController { @Override public boolean passPriority() { - return getInputProxy().passPriority(); + return passPriority(false); } - @Override public boolean passPriorityUntilEndOfTurn() { - return getInputProxy().passPriorityUntilEndOfTurn(); + return passPriority(true); + } + private boolean passPriority(final boolean passUntilEndOfTurn) { + final Input inp = gameView.getInputProxy().getInput(); + if (inp instanceof InputPassPriority) { + if (passUntilEndOfTurn) { + autoPassUntilEndOfTurn(); + } + inp.selectButtonOK(); + return true; + } + + FThreads.invokeInEdtNowOrLater(getGui(), new Runnable() { + @Override + public void run() { + SOptionPane.showMessageDialog(getGui(), "Cannot pass priority at this time."); + } + }); + return false; } @Override @@ -1472,11 +1485,11 @@ public class PlayerControllerHuman extends PlayerController { @Override public boolean getDisableAutoYields() { - return this.getGame().getDisableAutoYields(); + return game.getDisableAutoYields(); } @Override public void setDisableAutoYields(final boolean b) { - this.getGame().setDisableAutoYields(b); + game.setDisableAutoYields(b); } @Override diff --git a/forge-gui/src/main/java/forge/view/LocalGameView.java b/forge-gui/src/main/java/forge/view/LocalGameView.java index f5fbae0940c..6ed232e3448 100644 --- a/forge-gui/src/main/java/forge/view/LocalGameView.java +++ b/forge-gui/src/main/java/forge/view/LocalGameView.java @@ -27,16 +27,37 @@ import forge.game.player.RegisteredPlayer; import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbilityStackInstance; import forge.game.zone.ZoneType; +import forge.interfaces.IGuiBase; +import forge.match.input.InputProxy; +import forge.match.input.InputQueue; public abstract class LocalGameView implements IGameView { + protected final Game game; + protected final IGuiBase gui; + protected final InputQueue inputQueue; + protected final InputProxy inputProxy; - private final Game game; - public LocalGameView(final Game game) { - this.game = game; + public LocalGameView(Game game0, IGuiBase gui0) { + game = game0; + gui = gui0; + inputProxy = new InputProxy(this); + inputQueue = new InputQueue(game, inputProxy); } - protected final Game getGame() { - return this.game; + public final Game getGame() { + return game; + } + + public final IGuiBase getGui() { + return gui; + } + + public final InputQueue getInputQueue() { + return inputQueue; + } + + public InputProxy getInputProxy() { + return inputProxy; } /** Cache of players. */ @@ -60,17 +81,17 @@ public abstract class LocalGameView implements IGameView { */ @Override public GameType getGameType() { - return this.game.getMatch().getRules().getGameType(); + return game.getMatch().getRules().getGameType(); } @Override public int getTurnNumber() { - return this.game.getPhaseHandler().getTurn(); + return game.getPhaseHandler().getTurn(); } @Override public boolean isCommandZoneNeeded() { - return this.game.getMatch().getRules().getGameType().isCommandZoneNeeded(); + return game.getMatch().getRules().getGameType().isCommandZoneNeeded(); } @Override @@ -93,37 +114,37 @@ public abstract class LocalGameView implements IGameView { */ @Override public boolean isFirstGameInMatch() { - return this.game.getMatch().getPlayedGames().isEmpty(); + return game.getMatch().getPlayedGames().isEmpty(); } @Override public boolean isMatchOver() { - return this.game.getMatch().isMatchOver(); + return game.getMatch().isMatchOver(); } @Override public int getNumGamesInMatch() { - return this.game.getMatch().getRules().getGamesPerMatch(); + return game.getMatch().getRules().getGamesPerMatch(); } @Override public int getNumPlayedGamesInMatch() { - return this.game.getMatch().getPlayedGames().size(); + return game.getMatch().getPlayedGames().size(); } @Override public Iterable getOutcomesOfMatch() { - return Iterables.unmodifiableIterable(this.game.getMatch().getPlayedGames()); + return Iterables.unmodifiableIterable(game.getMatch().getPlayedGames()); } @Override public boolean isMatchWonBy(final LobbyPlayer p) { - return this.game.getMatch().isWonBy(p); + return game.getMatch().isWonBy(p); } @Override public int getGamesWonBy(final LobbyPlayer p) { - return this.game.getMatch().getGamesWonBy(p); + return game.getMatch().getGamesWonBy(p); } @Override @@ -133,7 +154,7 @@ public abstract class LocalGameView implements IGameView { @Override public Deck getDeck(final LobbyPlayer player) { - for (final RegisteredPlayer rp : this.game.getMatch().getPlayers()) { + for (final RegisteredPlayer rp : game.getMatch().getPlayers()) { if (rp.getPlayer().equals(player)) { return rp.getDeck(); } diff --git a/forge-gui/src/main/java/forge/view/WatchLocalGame.java b/forge-gui/src/main/java/forge/view/WatchLocalGame.java index ad8f73add58..f17814d4855 100644 --- a/forge-gui/src/main/java/forge/view/WatchLocalGame.java +++ b/forge-gui/src/main/java/forge/view/WatchLocalGame.java @@ -5,6 +5,7 @@ package forge.view; import forge.game.Game; import forge.game.card.Card; +import forge.interfaces.IGuiBase; import forge.match.input.Input; import forge.match.input.InputPlaybackControl; import forge.match.input.InputQueue; @@ -16,9 +17,6 @@ import forge.util.ITriggerEvent; * */ public class WatchLocalGame extends LocalGameView { - - private final InputQueue inputQueue; - /** * @param game * the @{link Game} to attach to. @@ -26,9 +24,8 @@ public class WatchLocalGame extends LocalGameView { * the {@link InputQueue} of the game to enable playback * controls, or {@code null} to disallow them. */ - public WatchLocalGame(final Game game, final InputQueue inputQueue) { - super(game); - this.inputQueue = inputQueue; + public WatchLocalGame(Game game0, IGuiBase gui0) { + super(game0, gui0); } @Override