Start refactoring to make Human v. Human support better

This commit is contained in:
drdev
2014-09-23 11:22:36 +00:00
parent edf8c58754
commit 6a5cd5f39f
28 changed files with 434 additions and 503 deletions

View File

@@ -54,7 +54,6 @@ import forge.interfaces.IGuiBase;
import forge.item.PaperCard; import forge.item.PaperCard;
import forge.match.input.InputQueue; import forge.match.input.InputQueue;
import forge.model.FModel; import forge.model.FModel;
import forge.player.GamePlayerUtil;
import forge.screens.deckeditor.CDeckEditorUI; import forge.screens.deckeditor.CDeckEditorUI;
import forge.screens.deckeditor.controllers.CEditorQuestCardShop; import forge.screens.deckeditor.controllers.CEditorQuestCardShop;
import forge.screens.match.CMatchUI; import forge.screens.match.CMatchUI;
@@ -286,7 +285,7 @@ public class GuiDesktop implements IGuiBase {
@Override @Override
public void updatePlayerControl() { public void updatePlayerControl() {
CMatchUI.SINGLETON_INSTANCE.initHandViews(GamePlayerUtil.getGuiPlayer()); CMatchUI.SINGLETON_INSTANCE.initHandViews();
SLayoutIO.loadLayout(null); SLayoutIO.loadLayout(null);
VMatchUI.SINGLETON_INSTANCE.populate(); VMatchUI.SINGLETON_INSTANCE.populate();
for (VHand h : VMatchUI.SINGLETON_INSTANCE.getHands()) { for (VHand h : VMatchUI.SINGLETON_INSTANCE.getHands()) {

View File

@@ -27,6 +27,8 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -75,11 +77,6 @@ import forge.quest.io.QuestDataIO;
import forge.screens.deckeditor.CDeckEditorUI; import forge.screens.deckeditor.CDeckEditorUI;
import forge.screens.match.CMatchUI; import forge.screens.match.CMatchUI;
import forge.screens.match.VMatchUI; 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.screens.match.views.VField;
import forge.sound.MusicPlaylist; import forge.sound.MusicPlaylist;
import forge.sound.SoundSystem; import forge.sound.SoundSystem;
@@ -88,7 +85,6 @@ import forge.toolbox.FSkin;
import forge.toolbox.special.PhaseIndicator; import forge.toolbox.special.PhaseIndicator;
import forge.view.FFrame; import forge.view.FFrame;
import forge.view.FView; import forge.view.FView;
import forge.view.IGameView;
import forge.view.LocalGameView; import forge.view.LocalGameView;
import forge.view.PlayerView; import forge.view.PlayerView;
import forge.view.WatchLocalGame; import forge.view.WatchLocalGame;
@@ -104,13 +100,14 @@ import forge.view.WatchLocalGame;
public enum FControl implements KeyEventDispatcher { public enum FControl implements KeyEventDispatcher {
instance; instance;
private Game game;
private List<LocalGameView> gameViews = new ArrayList<LocalGameView>();
private ForgeMenu forgeMenu; private ForgeMenu forgeMenu;
private List<Shortcut> shortcuts; private List<Shortcut> shortcuts;
private JLayeredPane display; private JLayeredPane display;
private FScreen currentScreen; private FScreen currentScreen;
private boolean altKeyLastDown; private boolean altKeyLastDown;
private CloseAction closeAction; private CloseAction closeAction;
private PlayerView localPlayer;
public static enum CloseAction { public static enum CloseAction {
NONE, NONE,
@@ -170,12 +167,12 @@ public enum FControl implements KeyEventDispatcher {
} }
public CloseAction getCloseAction() { public CloseAction getCloseAction() {
return this.closeAction; return closeAction;
} }
public void setCloseAction(CloseAction closeAction0) { public void setCloseAction(CloseAction closeAction0) {
if (this.closeAction == closeAction0) { return; } if (closeAction == closeAction0) { return; }
this.closeAction = closeAction0; closeAction = closeAction0;
Singletons.getView().getNavigationBar().updateBtnCloseTooltip(); Singletons.getView().getNavigationBar().updateBtnCloseTooltip();
final ForgePreferences prefs = FModel.getPreferences(); final ForgePreferences prefs = FModel.getPreferences();
@@ -186,10 +183,10 @@ public enum FControl implements KeyEventDispatcher {
public boolean canExitForge(boolean forRestart) { public boolean canExitForge(boolean forRestart) {
String action = (forRestart ? "Restart" : "Exit"); String action = (forRestart ? "Restart" : "Exit");
String userPrompt = "Are you sure you wish to " + (forRestart ? "restart" : "exit") + " Forge?"; 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; 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; return false;
} }
if (!CDeckEditorUI.SINGLETON_INSTANCE.canSwitchAway(true)) { if (!CDeckEditorUI.SINGLETON_INSTANCE.canSwitchAway(true)) {
@@ -212,14 +209,14 @@ public enum FControl implements KeyEventDispatcher {
// Preloads skin components (using progress bar). // Preloads skin components (using progress bar).
FSkin.loadFull(true); FSkin.loadFull(true);
this.soundSystem = new SoundSystem(GuiBase.getInterface()); soundSystem = new SoundSystem(GuiBase.getInterface());
this.shortcuts = KeyboardShortcuts.attachKeyboardShortcuts(); shortcuts = KeyboardShortcuts.attachKeyboardShortcuts();
this.display = FView.SINGLETON_INSTANCE.getLpnDocument(); display = FView.SINGLETON_INSTANCE.getLpnDocument();
final ForgePreferences prefs = FModel.getPreferences(); 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."); FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("About to load current quest.");
// Preload quest data if present // Preload quest data if present
@@ -267,14 +264,14 @@ public enum FControl implements KeyEventDispatcher {
} }
public ForgeMenu getForgeMenu() { public ForgeMenu getForgeMenu() {
if (this.forgeMenu == null) { if (forgeMenu == null) {
this.forgeMenu = new ForgeMenu(); forgeMenu = new ForgeMenu();
} }
return this.forgeMenu; return forgeMenu;
} }
public FScreen getCurrentScreen() { public FScreen getCurrentScreen() {
return this.currentScreen; return currentScreen;
} }
/** /**
@@ -286,14 +283,14 @@ public enum FControl implements KeyEventDispatcher {
public boolean setCurrentScreen(FScreen screen, boolean previousScreenClosed) { public boolean setCurrentScreen(FScreen screen, boolean previousScreenClosed) {
//TODO: Uncomment the line below if this function stops being used to refresh //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) //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 //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; 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(); SOverlayUtils.hideTargetingOverlay();
if (isMatchBackgroundImageVisible()) { if (isMatchBackgroundImageVisible()) {
FView.SINGLETON_INSTANCE.getPnlInsets().setForegroundImage(new ImageIcon()); FView.SINGLETON_INSTANCE.getPnlInsets().setForegroundImage(new ImageIcon());
@@ -304,7 +301,7 @@ public enum FControl implements KeyEventDispatcher {
SOverlayUtils.hideOverlay(); SOverlayUtils.hideOverlay();
ImageCache.clear(); //reduce memory usage by clearing image cache when switching screens ImageCache.clear(); //reduce memory usage by clearing image cache when switching screens
this.currentScreen = screen; currentScreen = screen;
//load layout for new current screen //load layout for new current screen
try { try {
@@ -335,14 +332,14 @@ public enum FControl implements KeyEventDispatcher {
} }
public boolean ensureScreenActive(FScreen screen) { public boolean ensureScreenActive(FScreen screen) {
if (this.currentScreen == screen) { return true; } if (currentScreen == screen) { return true; }
return setCurrentScreen(screen); return setCurrentScreen(screen);
} }
/** @return List<Shortcut> A list of attached keyboard shortcut descriptions and properties. */ /** @return List<Shortcut> A list of attached keyboard shortcut descriptions and properties. */
public List<Shortcut> getShortcuts() { public List<Shortcut> getShortcuts() {
return this.shortcuts; return shortcuts;
} }
/** Remove all children from a specified layer. */ /** Remove all children from a specified layer. */
@@ -374,17 +371,6 @@ public enum FControl implements KeyEventDispatcher {
return soundSystem; return soundSystem;
} }
private Game game;
private IGameView gameView;
public IGameView getGameView() {
return this.gameView;
}
public PlayerView getLocalPlayer() {
return localPlayer;
}
public final void stopGame() { public final void stopGame() {
List<Player> pp = new ArrayList<Player>(); List<Player> pp = new ArrayList<Player>();
for (Player p : game.getPlayers()) { for (Player p : game.getPlayers()) {
@@ -410,7 +396,7 @@ public enum FControl implements KeyEventDispatcher {
} }
else { else {
game.isGameOver(); // this is synchronized method - it's used to make Game-0 thread see changes made here 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) { 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() { public InputQueue getInputQueue() {
return inputQueue; LocalGameView gameView = getGameView();
if (gameView != null) {
return gameView.getInputQueue();
}
return null;
} }
public final void startGameInSameMatch() { public final void startGameInSameMatch() {
this.startGameWithUi(this.game.getMatch()); startGameWithUi(game.getMatch());
} }
public final void startGameAndClearMatch() { public final void startGameAndClearMatch() {
if (this.game != null) { if (game != null) {
this.game.getMatch().clearGamesPlayed(); game.getMatch().clearGamesPlayed();
} }
startGameInSameMatch(); startGameInSameMatch();
} }
public final void startGameWithUi(final Match match) { public final void startGameWithUi(final Match match) {
if (this.gameView != null) { if (game != null) {
this.setCurrentScreen(FScreen.MATCH_SCREEN); setCurrentScreen(FScreen.MATCH_SCREEN);
SOverlayUtils.hideOverlay(); SOverlayUtils.hideOverlay();
FOptionPane.showMessageDialog("Cannot start a new game while another game is already in progress."); 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 return; //TODO: See if it's possible to run multiple games at once without crashing
} }
setPlayerName(match.getPlayers()); setPlayerName(match.getPlayers());
this.game = match.createGame();
inputQueue = new InputQueue(game);
boolean anyPlayerIsAi = false; getSoundSystem().setBackgroundMusic(MusicPlaylist.MATCH);
for (final Player p : game.getPlayers()) {
if (p.getLobbyPlayer() instanceof LobbyPlayerAi) { game = match.createGame();
anyPlayerIsAi = true;
break; 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(); game.subscribeToEvents(getSoundSystem());
for (final Player p : game.getPlayers()) {
if (p.getLobbyPlayer().equals(me)) { final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
// Instantiate all required field slots (user at 0)
final List<Player> sortedPlayers = new ArrayList<Player>(game.getRegisteredPlayers());
Collections.sort(sortedPlayers, new Comparator<Player>() {
@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(); final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController();
this.gameView = controller.getGameView(); LocalGameView gameView = controller.getGameView();
this.fcVisitor = new FControlGameEventHandler(GuiBase.getInterface(), controller.getGameView()); game.subscribeToEvents(new FControlGameEventHandler(GuiBase.getInterface(), gameView));
break; gameViews.add(gameView);
humanCount++;
} }
} }
if (!anyPlayerIsAi) { if (humanCount == 0) { //watch game but do not participate
// If there are no AI's, allow all players to see all cards (hotseat LocalGameView gameView = new WatchLocalGame(game, GuiBase.getInterface());
// mode). game.subscribeToEvents(new FControlGameEventHandler(GuiBase.getInterface(), gameView));
for (final Player p : game.getPlayers()) { gameViews.add(gameView);
if (p.getController() instanceof PlayerControllerHuman) { }
final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController(); else if (humanCount == sortedPlayers.size()) {
controller.setMayLookAtAllCards(true); //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; List<PlayerView> sortedPlayerViews = new ArrayList<PlayerView>();
if (this.gameView == null) { for (Player p : sortedPlayers) {
// Watch game but do not participate sortedPlayerViews.add(getGameView().getPlayerView(p));
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);
} }
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. // 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 // Game is set on pause while gui player takes decisions
@@ -499,64 +559,14 @@ public enum FControl implements KeyEventDispatcher {
} }
public final void endCurrentGame() { public final void endCurrentGame() {
if (this.gameView == null) { return; } if (game == null) { return; }
Singletons.getView().getNavigationBar().closeTab(FScreen.MATCH_SCREEN); Singletons.getView().getNavigationBar().closeTab(FScreen.MATCH_SCREEN);
this.gameView = null; game = null;
} }
private FControlGameEventHandler fcVisitor;
private FControlGamePlayback playbackControl; 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<PlayerView> 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) /* (non-Javadoc)
* @see java.awt.KeyEventDispatcher#dispatchKeyEvent(java.awt.event.KeyEvent) * @see java.awt.KeyEventDispatcher#dispatchKeyEvent(java.awt.event.KeyEvent)

View File

@@ -115,7 +115,7 @@ public class KeyboardShortcuts {
@Override @Override
public void actionPerformed(final ActionEvent e) { public void actionPerformed(final ActionEvent e) {
if (Singletons.getControl().getCurrentScreen() != FScreen.MATCH_SCREEN) { return; } if (Singletons.getControl().getCurrentScreen() != FScreen.MATCH_SCREEN) { return; }
CDock.SINGLETON_INSTANCE.alphaStrike(); Singletons.getControl().getGameView().alphaStrike();
} }
}; };

View File

@@ -27,7 +27,6 @@ import javax.swing.JMenu;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus; import com.google.common.eventbus.EventBus;
@@ -53,6 +52,7 @@ import forge.gui.framework.SDisplayUtil;
import forge.item.InventoryItem; import forge.item.InventoryItem;
import forge.menus.IMenuProvider; import forge.menus.IMenuProvider;
import forge.model.FModel; import forge.model.FModel;
import forge.player.LobbyPlayerHuman;
import forge.properties.ForgePreferences.FPref; import forge.properties.ForgePreferences.FPref;
import forge.quest.QuestDraftUtils; import forge.quest.QuestDraftUtils;
import forge.screens.match.controllers.CAntes; import forge.screens.match.controllers.CAntes;
@@ -73,7 +73,6 @@ import forge.toolbox.special.PhaseLabel;
import forge.view.CardView; import forge.view.CardView;
import forge.view.CombatView; import forge.view.CombatView;
import forge.view.GameEntityView; import forge.view.GameEntityView;
import forge.view.IGameView;
import forge.view.PlayerView; import forge.view.PlayerView;
import forge.view.ViewUtil; import forge.view.ViewUtil;
import forge.view.arcane.CardPanel; import forge.view.arcane.CardPanel;
@@ -90,7 +89,6 @@ import forge.view.arcane.PlayArea;
public enum CMatchUI implements ICDoc, IMenuProvider { public enum CMatchUI implements ICDoc, IMenuProvider {
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
private IGameView game;
private List<PlayerView> sortedPlayers; private List<PlayerView> sortedPlayers;
private VMatchUI view; private VMatchUI view;
private boolean allHands; private boolean allHands;
@@ -123,17 +121,14 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
/** /**
* Instantiates at a match. * Instantiates at a match.
*/ */
public void initMatch(final IGameView game, final List<PlayerView> players, final LobbyPlayer localPlayer, final boolean allHands) { public void initMatch(final List<PlayerView> sortedPlayers0, final boolean allHands0) {
this.game = game; sortedPlayers = sortedPlayers0;
this.allHands = allHands; allHands = allHands0;
view = VMatchUI.SINGLETON_INSTANCE; view = VMatchUI.SINGLETON_INSTANCE;
// TODO fix for use with multiplayer // TODO fix for use with multiplayer
final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(","); final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
// Instantiate all required field slots (user at 0)
sortedPlayers = shiftPlayersPlaceLocalFirst(players, localPlayer);
final List<VField> fields = new ArrayList<VField>(); final List<VField> fields = new ArrayList<VField>();
final List<VCommand> commands = new ArrayList<VCommand>(); final List<VCommand> commands = new ArrayList<VCommand>();
@@ -141,7 +136,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
for (final PlayerView p : sortedPlayers) { for (final PlayerView p : sortedPlayers) {
// A field must be initialized after it's instantiated, to update player info. // A field must be initialized after it's instantiated, to update player info.
// No player, no init. // 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); VCommand c = new VCommand(EDocID.Commands[i], p);
fields.add(f); fields.add(f);
commands.add(c); commands.add(c);
@@ -157,20 +152,17 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
view.setCommandViews(commands); view.setCommandViews(commands);
view.setFieldViews(fields); view.setFieldViews(fields);
VPlayers.SINGLETON_INSTANCE.init(players); VPlayers.SINGLETON_INSTANCE.init(sortedPlayers0);
initHandViews(localPlayer, allHands); initHandViews();
} }
public void initHandViews(final LobbyPlayer localPlayer) { public void initHandViews() {
this.initHandViews(localPlayer, this.allHands);
}
public void initHandViews(final LobbyPlayer localPlayer, final boolean allHands) {
final List<VHand> hands = new ArrayList<VHand>(); final List<VHand> hands = new ArrayList<VHand>();
int i = 0; int i = 0;
for (final PlayerView p : sortedPlayers) { 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); VHand newHand = new VHand(EDocID.Hands[i], p);
newHand.getLayoutControl().initialize(); newHand.getLayoutControl().initialize();
hands.add(newHand); hands.add(newHand);
@@ -181,22 +173,6 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
view.setHandViews(hands); view.setHandViews(hands);
} }
private List<PlayerView> shiftPlayersPlaceLocalFirst(final List<PlayerView> players, final LobbyPlayer localPlayer) {
// get an arranged list so that the first local player is at index 0
final List<PlayerView> 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 * Resets all phase buttons in all fields to "inactive", so highlight won't
* be drawn on them. "Enabled" state remains the same. * 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) { 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) { if (selectedDocBeforeCombat == null) {
IVDoc<? extends ICDoc> combatDoc = EDocID.REPORT_COMBAT.getDoc(); IVDoc<? extends ICDoc> combatDoc = EDocID.REPORT_COMBAT.getDoc();
if (combatDoc.getParentCell() != null) { if (combatDoc.getParentCell() != null) {

View File

@@ -40,7 +40,6 @@ import forge.toolbox.FSkin;
import forge.toolbox.SaveOpenDialog; import forge.toolbox.SaveOpenDialog;
import forge.toolbox.SaveOpenDialog.Filetypes; import forge.toolbox.SaveOpenDialog.Filetypes;
import forge.view.FView; import forge.view.FView;
import forge.view.IGameView;
/** /**
* Controls the dock panel in the match UI. * Controls the dock panel in the match UI.
@@ -52,11 +51,6 @@ public enum CDock implements ICDoc {
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
private int arcState; private int arcState;
private IGameView game;
public void setModel(final IGameView game0) {
game = game0;
}
/** /**
* End turn. * End turn.
@@ -156,33 +150,6 @@ public enum CDock implements ICDoc {
//FModel.SINGLETON_INSTANCE.getPreferences().save(); //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<Player> 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. */ /** Toggle targeting overlay painting. */
public void toggleTargeting() { public void toggleTargeting() {
arcState++; arcState++;
@@ -271,7 +238,7 @@ public enum CDock implements ICDoc {
VDock.SINGLETON_INSTANCE.getBtnAlphaStrike().setCommand(new UiCommand() { VDock.SINGLETON_INSTANCE.getBtnAlphaStrike().setCommand(new UiCommand() {
@Override @Override
public void run() { public void run() {
alphaStrike(); Singletons.getControl().getGameView().alphaStrike();
} }
}); });
VDock.SINGLETON_INSTANCE.getBtnTargeting().setCommand(new UiCommand() { VDock.SINGLETON_INSTANCE.getBtnTargeting().setCommand(new UiCommand() {

View File

@@ -23,7 +23,6 @@ import java.awt.event.MouseListener;
import com.google.common.base.Function; import com.google.common.base.Function;
import forge.LobbyPlayer;
import forge.Singletons; import forge.Singletons;
import forge.UiCommand; import forge.UiCommand;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -41,8 +40,6 @@ import forge.view.PlayerView;
public class CField implements ICDoc { public class CField implements ICDoc {
// The one who owns cards on this side of table // The one who owns cards on this side of table
private final PlayerView player; private final PlayerView player;
// Tho one who looks at screen and 'performs actions'
private final LobbyPlayer viewer;
private final VField view; private final VField view;
private boolean initializedAlready = false; private boolean initializedAlready = false;
@@ -60,9 +57,8 @@ public class CField implements ICDoc {
* @param v0 &emsp; {@link forge.screens.match.views.VField} * @param v0 &emsp; {@link forge.screens.match.views.VField}
* @param playerViewer * @param playerViewer
*/ */
public CField(final PlayerView player0, final VField v0, LobbyPlayer playerViewer) { public CField(final PlayerView player0, final VField v0) {
this.player = player0; this.player = player0;
this.viewer = playerViewer;
this.view = v0; this.view = v0;
final ZoneAction handAction = new ZoneAction(player, ZoneType.Hand, MatchConstants.HUMANHAND); final ZoneAction handAction = new ZoneAction(player, ZoneType.Hand, MatchConstants.HUMANHAND);
@@ -74,7 +70,7 @@ public class CField implements ICDoc {
@Override @Override
protected void doAction(final CardView c) { protected void doAction(final CardView c) {
// activate cards only via your own flashback button // activate cards only via your own flashback button
if (player.getLobbyPlayer() != CField.this.viewer) { if (player.getLobbyPlayer() != Singletons.getControl().getGuiPlayer()) {
return; return;
} }
@@ -88,7 +84,7 @@ public class CField implements ICDoc {
Function<Byte, Void> manaAction = new Function<Byte, Void>() { Function<Byte, Void> manaAction = new Function<Byte, Void>() {
public Void apply(Byte colorCode) { 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()); Singletons.getControl().getGameView().useMana(colorCode.byteValue());
} }
return null; return null;

View File

@@ -5,8 +5,6 @@ import forge.UiCommand;
import forge.FThreads; import forge.FThreads;
import forge.gui.framework.ICDoc; import forge.gui.framework.ICDoc;
import forge.screens.match.views.VLog; import forge.screens.match.views.VLog;
import forge.view.IGameView;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
@@ -20,8 +18,6 @@ public enum CLog implements ICDoc, Observer {
/** */ /** */
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
private IGameView model;
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.gui.framework.ICDoc#getCommandOnSelect() * @see forge.gui.framework.ICDoc#getCommandOnSelect()
*/ */
@@ -41,19 +37,10 @@ public enum CLog implements ICDoc, Observer {
private final Runnable r = new Runnable() { private final Runnable r = new Runnable() {
@Override @Override
public void run() { 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) /* (non-Javadoc)
* @see java.util.Observer#update(java.util.Observable, java.lang.Object) * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/ */

View File

@@ -3,7 +3,6 @@ package forge.screens.match.controllers;
import forge.UiCommand; import forge.UiCommand;
import forge.gui.framework.ICDoc; import forge.gui.framework.ICDoc;
import forge.screens.match.views.VPlayers; import forge.screens.match.views.VPlayers;
import forge.view.IGameView;
/** /**
* Controls the combat panel in the match UI. * Controls the combat panel in the match UI.
@@ -14,7 +13,6 @@ import forge.view.IGameView;
public enum CPlayers implements ICDoc { public enum CPlayers implements ICDoc {
/** */ /** */
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
private IGameView game;
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.gui.framework.ICDoc#getCommandOnSelect() * @see forge.gui.framework.ICDoc#getCommandOnSelect()
@@ -36,11 +34,6 @@ public enum CPlayers implements ICDoc {
*/ */
@Override @Override
public void update() { public void update() {
VPlayers.SINGLETON_INSTANCE.update(game); VPlayers.SINGLETON_INSTANCE.update();
} }
public void setModel(IGameView game) {
this.game = game;
}
} }

View File

@@ -5,8 +5,6 @@ import forge.gui.framework.EDocID;
import forge.gui.framework.ICDoc; import forge.gui.framework.ICDoc;
import forge.gui.framework.SDisplayUtil; import forge.gui.framework.SDisplayUtil;
import forge.screens.match.views.VStack; import forge.screens.match.views.VStack;
import forge.view.IGameView;
import forge.view.PlayerView;
/** /**
* Controls the combat panel in the match UI. * Controls the combat panel in the match UI.
@@ -18,9 +16,6 @@ public enum CStack implements ICDoc {
/** */ /** */
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
private IGameView model;
private PlayerView localPlayer;
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.gui.framework.ICDoc#getCommandOnSelect() * @see forge.gui.framework.ICDoc#getCommandOnSelect()
*/ */
@@ -39,12 +34,6 @@ public enum CStack implements ICDoc {
@Override @Override
public void update() { public void update() {
SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc()); 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;
}
} }

View File

@@ -119,7 +119,7 @@ public final class GameMenu {
return new ActionListener() { return new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
controller.alphaStrike(); Singletons.getControl().getGameView().alphaStrike();
} }
}; };
} }

View File

@@ -18,7 +18,6 @@
package forge.screens.match.views; package forge.screens.match.views;
import java.awt.Dimension; import java.awt.Dimension;
import java.util.List;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
@@ -26,6 +25,7 @@ import javax.swing.JPanel;
import javax.swing.SwingConstants; import javax.swing.SwingConstants;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import forge.Singletons;
import forge.gui.CardPicturePanel; import forge.gui.CardPicturePanel;
import forge.gui.WrapLayout; import forge.gui.WrapLayout;
import forge.gui.framework.DragCell; import forge.gui.framework.DragCell;
@@ -55,7 +55,6 @@ public enum VAntes implements IVDoc<CAntes> {
private final FScrollPane scroller = new FScrollPane(pnl, false); private final FScrollPane scroller = new FScrollPane(pnl, false);
private final SortedSet<AntePanel> allAntes = new TreeSet<AntePanel>(); private final SortedSet<AntePanel> allAntes = new TreeSet<AntePanel>();
private Iterable<PlayerView> players;
//========== Constructor //========== Constructor
private VAntes() { private VAntes() {
pnl.setLayout(new WrapLayout()); pnl.setLayout(new WrapLayout());
@@ -72,9 +71,8 @@ public enum VAntes implements IVDoc<CAntes> {
parentCell.getBody().setLayout(new MigLayout("insets 0, gap 0")); parentCell.getBody().setLayout(new MigLayout("insets 0, gap 0"));
parentCell.getBody().add(scroller, "w 100%!, h 100%!"); parentCell.getBody().add(scroller, "w 100%!, h 100%!");
} }
public final void setModel(final List<PlayerView> players) { public final void setModel() {
this.players = players;
update(); update();
} }
@@ -122,7 +120,7 @@ public enum VAntes implements IVDoc<CAntes> {
allAntes.clear(); allAntes.clear();
pnl.removeAll(); pnl.removeAll();
for (final PlayerView p : players) { for (final PlayerView p : Singletons.getControl().getGameView().getPlayers()) {
for (final CardView c : p.getAnteCards()) { for (final CardView c : p.getAnteCards()) {
final AntePanel pnlTemp = new AntePanel(c); final AntePanel pnlTemp = new AntePanel(c);
allAntes.add(pnlTemp); allAntes.add(pnlTemp);

View File

@@ -28,7 +28,6 @@ import javax.swing.border.Border;
import javax.swing.border.LineBorder; import javax.swing.border.LineBorder;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import forge.LobbyPlayer;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.framework.DragCell; import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab; import forge.gui.framework.DragTab;
@@ -84,7 +83,7 @@ public class VField implements IVDoc<CField> {
* @param p &emsp; {@link forge.game.player.Player} * @param p &emsp; {@link forge.game.player.Player}
* @param id0 &emsp; {@link forge.gui.framework.EDocID} * @param id0 &emsp; {@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; this.docID = id0;
id0.setDoc(this); id0.setDoc(this);
@@ -98,7 +97,7 @@ public class VField implements IVDoc<CField> {
// (haven't looked into it too deeply). Doublestrike 12-04-12 // (haven't looked into it too deeply). Doublestrike 12-04-12
tabletop = new PlayArea(scroller, id0 == EDocID.FIELD_1, player, ZoneType.Battlefield); 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.setOpaque(false);
avatarArea.setBackground(FSkin.getColor(FSkin.Colors.CLR_HOVER)); avatarArea.setBackground(FSkin.getColor(FSkin.Colors.CLR_HOVER));

View File

@@ -25,6 +25,7 @@ import net.miginfocom.swing.MigLayout;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.Singletons;
import forge.game.GameLogEntry; import forge.game.GameLogEntry;
import forge.game.GameLogEntryType; import forge.game.GameLogEntryType;
import forge.gui.framework.DragCell; import forge.gui.framework.DragCell;
@@ -38,6 +39,7 @@ import forge.screens.match.controllers.CLog;
import forge.toolbox.FSkin; import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinFont; import forge.toolbox.FSkin.SkinFont;
import forge.view.IGameView; import forge.view.IGameView;
import forge.view.LocalGameView;
/** /**
* Assembles Swing components of game log report. * Assembles Swing components of game log report.
@@ -124,8 +126,9 @@ public enum VLog implements IVDoc<CLog> {
* <p> * <p>
* @param model contains list of log entries. * @param model contains list of log entries.
*/ */
public void updateConsole(final IGameView model) { public void updateConsole() {
if (isGameLogConsoleVisible()) { if (isGameLogConsoleVisible()) {
LocalGameView model = Singletons.getControl().getGameView();
resetDisplayIfNewGame(model); resetDisplayIfNewGame(model);
displayNewGameLogEntries(model); displayNewGameLogEntries(model);
// Important : refreshLayout() needs to be called every update. // Important : refreshLayout() needs to be called every update.

View File

@@ -28,6 +28,7 @@ import javax.swing.ScrollPaneConstants;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import forge.Singletons;
import forge.gui.framework.DragCell; import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab; import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID; import forge.gui.framework.EDocID;
@@ -39,7 +40,6 @@ import forge.toolbox.FScrollPanel;
import forge.toolbox.FSkin; import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedLabel; import forge.toolbox.FSkin.SkinnedLabel;
import forge.view.CardView; import forge.view.CardView;
import forge.view.IGameView;
import forge.view.PlayerView; import forge.view.PlayerView;
/** /**
@@ -142,10 +142,10 @@ public enum VPlayers implements IVDoc<CPlayers> {
//========== Observer update methods //========== Observer update methods
/** @param game {@link forge.game.player.Player} */ /** @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 // No need to update if this panel isn't showing
if (parentCell == null || !this.equals(parentCell.getSelected())) { return; } if (parentCell == null || !this.equals(parentCell.getSelected())) { return; }
boolean isCommander = game.isCommander(); boolean isCommander = Singletons.getControl().getGameView().isCommander();
for(final Entry<PlayerView, JLabel[]> rr : infoLBLs.entrySet()) { for(final Entry<PlayerView, JLabel[]> rr : infoLBLs.entrySet()) {
PlayerView p0 = rr.getKey(); PlayerView p0 = rr.getKey();

View File

@@ -36,8 +36,10 @@ import javax.swing.border.EmptyBorder;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import forge.ImageCache; import forge.ImageCache;
import forge.Singletons;
import forge.card.CardDetailUtil; import forge.card.CardDetailUtil;
import forge.card.CardDetailUtil.DetailColors; import forge.card.CardDetailUtil.DetailColors;
import forge.game.player.Player;
import forge.gui.framework.DragCell; import forge.gui.framework.DragCell;
import forge.gui.framework.DragTab; import forge.gui.framework.DragTab;
import forge.gui.framework.EDocID; import forge.gui.framework.EDocID;
@@ -51,7 +53,7 @@ import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedTextArea; import forge.toolbox.FSkin.SkinnedTextArea;
import forge.view.CardView; import forge.view.CardView;
import forge.view.IGameView; import forge.view.IGameView;
import forge.view.PlayerView; import forge.view.LocalGameView;
import forge.view.StackItemView; import forge.view.StackItemView;
import forge.view.arcane.CardPanel; import forge.view.arcane.CardPanel;
@@ -132,9 +134,10 @@ public enum VStack implements IVDoc<CStack> {
//========== Observer update methods //========== Observer update methods
/** /**
* @param model * @param models
* @param viewer */ * @param viewer */
public void updateStack(final IGameView model, final PlayerView localPlayer) { public void updateStack() {
final LocalGameView model = Singletons.getControl().getGameView();
final List<StackItemView> items = model.getStack(); final List<StackItemView> items = model.getStack();
tab.setText("Stack : " + items.size()); tab.setText("Stack : " + items.size());
@@ -145,7 +148,7 @@ public enum VStack implements IVDoc<CStack> {
boolean isFirst = true; boolean isFirst = true;
for (final StackItemView item : items) { 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")); scroller.add(tar, "pushx, growx" + (isFirst ? "" : ", gaptop 2px"));
@@ -175,9 +178,10 @@ public enum VStack implements IVDoc<CStack> {
private final CardView sourceCard; 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(); sourceCard = item.getSource();
final Player localPlayer = Singletons.getControl().getCurrentPlayer();
final String txt = (item.isOptionalTrigger() && item.getActivatingPlayer().equals(localPlayer) final String txt = (item.isOptionalTrigger() && item.getActivatingPlayer().equals(localPlayer)
? "(OPTIONAL) " : "") + item.getText(); ? "(OPTIONAL) " : "") + item.getText();
@@ -302,7 +306,7 @@ public enum VStack implements IVDoc<CStack> {
add(jmiAlwaysNo); 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.game = game;
this.item = item; this.item = item;
triggerID = Integer.valueOf(item.getSourceTrigger()); triggerID = Integer.valueOf(item.getSourceTrigger());

View File

@@ -239,12 +239,12 @@ public class GuiMobile implements IGuiBase {
@Override @Override
public IButton getBtnOK() { public IButton getBtnOK() {
return FControl.getView().getPrompt().getBtnOk(); return FControl.getView().getActivePrompt().getBtnOk();
} }
@Override @Override
public IButton getBtnCancel() { public IButton getBtnCancel() {
return FControl.getView().getPrompt().getBtnCancel(); return FControl.getView().getActivePrompt().getBtnCancel();
} }
@Override @Override

View File

@@ -6,6 +6,8 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@@ -23,7 +25,6 @@ import forge.Forge;
import forge.Graphics; import forge.Graphics;
import forge.GuiBase; import forge.GuiBase;
import forge.LobbyPlayer; import forge.LobbyPlayer;
import forge.ai.LobbyPlayerAi;
import forge.assets.FImage; import forge.assets.FImage;
import forge.assets.FSkin; import forge.assets.FSkin;
import forge.assets.FTextureRegionImage; import forge.assets.FTextureRegionImage;
@@ -71,7 +72,6 @@ import forge.view.CardView;
import forge.view.CardView.CardStateView; import forge.view.CardView.CardStateView;
import forge.view.CombatView; import forge.view.CombatView;
import forge.view.GameEntityView; import forge.view.GameEntityView;
import forge.view.IGameView;
import forge.view.LocalGameView; import forge.view.LocalGameView;
import forge.view.PlayerView; import forge.view.PlayerView;
import forge.view.WatchLocalGame; import forge.view.WatchLocalGame;
@@ -80,13 +80,10 @@ public class FControl {
private FControl() { } //don't allow creating instance private FControl() { } //don't allow creating instance
private static Game game; private static Game game;
private static IGameView gameView; private static List<LocalGameView> gameViews = new ArrayList<LocalGameView>();
private static MatchScreen view; private static MatchScreen view;
private static InputQueue inputQueue;
private static final EventBus uiEvents; private static final EventBus uiEvents;
private static boolean gameHasHumanPlayer;
private static final MatchUiEventVisitor visitor = new MatchUiEventVisitor(); private static final MatchUiEventVisitor visitor = new MatchUiEventVisitor();
private static FControlGameEventHandler fcVisitor;
private static FControlGamePlayback playbackControl; private static FControlGamePlayback playbackControl;
private static final Map<LobbyPlayer, FImage> avatarImages = new HashMap<LobbyPlayer, FImage>(); private static final Map<LobbyPlayer, FImage> avatarImages = new HashMap<LobbyPlayer, FImage>();
@@ -147,30 +144,63 @@ public class FControl {
game.subscribeToEvents(qc); // this one listens to player's mulligans ATM game.subscribeToEvents(qc); // this one listens to player's mulligans ATM
} }
inputQueue = new InputQueue(game);
game.subscribeToEvents(Forge.getSoundSystem()); game.subscribeToEvents(Forge.getSoundSystem());
Player humanLobbyPlayer = game.getRegisteredPlayers().get(0); final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
// The UI controls should use these game data as models
initMatch(game.getRegisteredPlayers(), humanLobbyPlayer);
actuateMatchPreferences(); // Instantiate all required field slots (user at 0)
final List<Player> sortedPlayers = new ArrayList<Player>(game.getRegisteredPlayers());
Collections.sort(sortedPlayers, new Comparator<Player>() {
@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 gameViews.clear();
game.subscribeToEvents(fcVisitor); List<VPlayerPanel> playerPanels = new ArrayList<VPlayerPanel>();
// Add playback controls to match if needed int i = 0;
gameHasHumanPlayer = false; int avatarIndex = 0;
boolean gameHasAiPlayer = false; int humanCount = 0;
for (Player p : game.getPlayers()) { for (Player p : sortedPlayers) {
if (p.getController().getLobbyPlayer() == getGuiPlayer()) { if (i < indices.length) {
gameHasHumanPlayer = true; avatarIndex = Integer.parseInt(indices[i]);
} else if (p.getLobbyPlayer() instanceof LobbyPlayerAi) { i++;
gameHasAiPlayer = true; }
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); game.subscribeToEvents(playbackControl);
//add special object that pauses game if screen touched //add special object that pauses game if screen touched
@@ -189,16 +219,7 @@ public class FControl {
}); });
} }
if (!gameHasAiPlayer) { actuateMatchPreferences();
// 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);
}
}
}
Forge.openScreen(view); Forge.openScreen(view);
@@ -216,8 +237,21 @@ public class FControl {
return game; return game;
} }
public static IGameView getGameView() { public static LocalGameView getGameView() {
return gameView; 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() { public static MatchScreen getView() {
@@ -225,7 +259,11 @@ public class FControl {
} }
public static InputQueue getInputQueue() { 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) { public static boolean stopAtPhase(final PlayerView turn, final PhaseType phase) {
@@ -234,69 +272,7 @@ public class FControl {
} }
public static void endCurrentTurn() { public static void endCurrentTurn() {
gameView.passPriorityUntilEndOfTurn(); getGameView().passPriorityUntilEndOfTurn();
}
public static void initMatch(final List<Player> players, Player localPlayer) {
final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
// Instantiate all required field slots (user at 0)
final List<Player> sortedPlayers = shiftPlayersPlaceLocalFirst(players, localPlayer);
List<VPlayerPanel> playerPanels = new ArrayList<VPlayerPanel>();
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<Player> shiftPlayersPlaceLocalFirst(final List<Player> players, Player localPlayer) {
// get an arranged list so that the first local player is at index 0
List<Player> sortedPlayers = new ArrayList<Player>(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;
} }
public static void resetAllPhaseButtons() { public static void resetAllPhaseButtons() {
@@ -306,7 +282,10 @@ public class FControl {
} }
public static void showMessage(final String s0) { 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) { public static VPlayerPanel getPlayerPanel(final PlayerView playerView) {
@@ -333,6 +312,8 @@ public class FControl {
} }
public static Player getCurrentPlayer() { public static Player getCurrentPlayer() {
if (game == null) { return null; }
// try current priority // try current priority
Player currentPriority = game.getPhaseHandler().getPriorityPlayer(); Player currentPriority = game.getPhaseHandler().getPriorityPlayer();
if (null != currentPriority && currentPriority.getLobbyPlayer() == getGuiPlayer()) { if (null != currentPriority && currentPriority.getLobbyPlayer() == getGuiPlayer()) {
@@ -350,7 +331,7 @@ public class FControl {
} }
public static void alphaStrike() { public static void alphaStrike() {
gameView.alphaStrike(); getGameView().alphaStrike();
} }
public static void showCombat(CombatView combat) { public static void showCombat(CombatView combat) {
@@ -537,7 +518,7 @@ public class FControl {
} }
else { else {
game.isGameOver(); // this is synchronized method - it's used to make Game-0 thread see changes made here 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) { if (playbackControl != null) {
@@ -556,6 +537,7 @@ public class FControl {
public static void pause() { public static void pause() {
Forge.getSoundSystem().pause(); Forge.getSoundSystem().pause();
//pause playback if needed //pause playback if needed
InputQueue inputQueue = getInputQueue();
if (inputQueue != null && inputQueue.getInput() instanceof InputPlaybackControl) { if (inputQueue != null && inputQueue.getInput() instanceof InputPlaybackControl) {
((InputPlaybackControl)inputQueue.getInput()).pause(); ((InputPlaybackControl)inputQueue.getInput()).pause();
} }

View File

@@ -14,6 +14,7 @@ import com.google.common.collect.Maps;
import forge.Forge; import forge.Forge;
import forge.menu.FMenuBar; import forge.menu.FMenuBar;
import forge.model.FModel; import forge.model.FModel;
import forge.player.LobbyPlayerHuman;
import forge.properties.ForgePreferences; import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref; import forge.properties.ForgePreferences.FPref;
import forge.screens.FScreen; import forge.screens.FScreen;
@@ -34,7 +35,6 @@ import forge.animation.AbilityEffect;
import forge.assets.FSkinColor; import forge.assets.FSkinColor;
import forge.assets.FSkinTexture; import forge.assets.FSkinTexture;
import forge.assets.FSkinColor.Colors; import forge.assets.FSkinColor.Colors;
import forge.game.zone.ZoneType;
import forge.toolbox.FEvent; import forge.toolbox.FEvent;
import forge.toolbox.FEvent.FEventHandler; import forge.toolbox.FEvent.FEventHandler;
import forge.toolbox.FScrollPane; import forge.toolbox.FScrollPane;
@@ -42,52 +42,72 @@ import forge.util.Callback;
import forge.view.CardView; import forge.view.CardView;
import forge.view.CombatView; import forge.view.CombatView;
import forge.view.GameEntityView; import forge.view.GameEntityView;
import forge.view.IGameView;
import forge.view.PlayerView; import forge.view.PlayerView;
public class MatchScreen extends FScreen { public class MatchScreen extends FScreen {
public static FSkinColor BORDER_COLOR = FSkinColor.get(Colors.CLR_BORDERS); public static FSkinColor BORDER_COLOR = FSkinColor.get(Colors.CLR_BORDERS);
private final IGameView gameView;
private final Map<PlayerView, VPlayerPanel> playerPanels = Maps.newHashMap(); private final Map<PlayerView, VPlayerPanel> playerPanels = Maps.newHashMap();
private final VPrompt prompt;
private final VLog log; private final VLog log;
private final VStack stack; private final VStack stack;
private final VDevMenu devMenu; private final VDevMenu devMenu;
private final FieldScroller scroller; private final FieldScroller scroller;
private final VPrompt bottomPlayerPrompt, topPlayerPrompt;
private VPlayerPanel bottomPlayerPanel, topPlayerPanel; private VPlayerPanel bottomPlayerPanel, topPlayerPanel;
private AbilityEffect activeEffect; private AbilityEffect activeEffect;
public MatchScreen(final IGameView game, PlayerView localPlayer, List<VPlayerPanel> playerPanels0) { public MatchScreen(List<VPlayerPanel> playerPanels0) {
super(new FMenuBar()); super(new FMenuBar());
this.gameView = game;
scroller = add(new FieldScroller()); scroller = add(new FieldScroller());
int humanCount = 0;
for (VPlayerPanel playerPanel : playerPanels0) { for (VPlayerPanel playerPanel : playerPanels0) {
playerPanels.put(playerPanel.getPlayer(), scroller.add(playerPanel)); playerPanels.put(playerPanel.getPlayer(), scroller.add(playerPanel));
if (playerPanel.getPlayer().getLobbyPlayer() instanceof LobbyPlayerHuman) {
humanCount++;
}
} }
bottomPlayerPanel = playerPanels0.get(0); bottomPlayerPanel = playerPanels0.get(0);
topPlayerPanel = playerPanels0.get(1); topPlayerPanel = playerPanels0.get(1);
topPlayerPanel.setFlipped(true); topPlayerPanel.setFlipped(true);
bottomPlayerPanel.setSelectedZone(ZoneType.Hand);
prompt = add(new VPrompt("", "", bottomPlayerPrompt = add(new VPrompt("", "",
new FEventHandler() { new FEventHandler() {
@Override @Override
public void handleEvent(FEvent e) { public void handleEvent(FEvent e) {
game.selectButtonOk(); FControl.getGameView().selectButtonOk();
} }
}, },
new FEventHandler() { new FEventHandler() {
@Override @Override
public void handleEvent(FEvent e) { 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); log.setDropDownContainer(this);
stack = new VStack(game, localPlayer); stack = new VStack();
stack.setDropDownContainer(this); stack.setDropDownContainer(this);
devMenu = new VDevMenu(); devMenu = new VDevMenu();
devMenu.setDropDownContainer(this); devMenu.setDropDownContainer(this);
@@ -96,7 +116,7 @@ public class MatchScreen extends FScreen {
players.setDropDownContainer(this); players.setDropDownContainer(this);
FMenuBar menuBar = (FMenuBar)getHeader(); FMenuBar menuBar = (FMenuBar)getHeader();
menuBar.addTab("Game", new VGameMenu(game)); menuBar.addTab("Game", new VGameMenu());
menuBar.addTab("Players (" + playerPanels.size() + ")", players); menuBar.addTab("Players (" + playerPanels.size() + ")", players);
menuBar.addTab("Log", log); menuBar.addTab("Log", log);
menuBar.addTab("Dev", devMenu); menuBar.addTab("Dev", devMenu);
@@ -109,6 +129,20 @@ public class MatchScreen extends FScreen {
devMenu.getMenuTab().setVisible(ForgePreferences.DEV_MODE); 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() { public VLog getLog() {
return log; return log;
} }
@@ -117,10 +151,6 @@ public class MatchScreen extends FScreen {
return stack; return stack;
} }
public VPrompt getPrompt() {
return prompt;
}
public VPlayerPanel getTopPlayerPanel() { public VPlayerPanel getTopPlayerPanel() {
return topPlayerPanel; return topPlayerPanel;
} }
@@ -142,8 +172,12 @@ public class MatchScreen extends FScreen {
@Override @Override
protected void doLayout(float startY, float width, float height) { 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); 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 @Override
@@ -162,7 +196,7 @@ public class MatchScreen extends FScreen {
} }
//draw arrows for combat //draw arrows for combat
final CombatView combat = gameView.getCombat(); final CombatView combat = FControl.getGameView().getCombat();
if (combat != null) { if (combat != null) {
for (final CardView attacker : combat.getAttackers()) { for (final CardView attacker : combat.getAttackers()) {
//connect each attacker with planeswalker it's attacking if applicable //connect each attacker with planeswalker it's attacking if applicable
@@ -190,12 +224,12 @@ public class MatchScreen extends FScreen {
switch (keyCode) { switch (keyCode) {
case Keys.ENTER: case Keys.ENTER:
case Keys.SPACE: 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 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: case Keys.ESCAPE:
return prompt.getBtnCancel().trigger(); //otherwise trigger Cancel return getActivePrompt().getBtnCancel().trigger(); //otherwise trigger Cancel
case Keys.BACK: case Keys.BACK:
return true; //suppress Back button so it's not bumped when trying to press OK or Cancel buttons 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 case Keys.A: //alpha strike on Ctrl+A
@@ -218,7 +252,7 @@ public class MatchScreen extends FScreen {
break; break;
case Keys.Z: //undo on Ctrl+Z case Keys.Z: //undo on Ctrl+Z
if (KeyInputAdapter.isCtrlKeyDown()) { if (KeyInputAdapter.isCtrlKeyDown()) {
gameView.tryUndoLastAction(); FControl.getGameView().tryUndoLastAction();
return true; return true;
} }
break; break;

View File

@@ -14,13 +14,9 @@ import forge.screens.match.FControl;
import forge.screens.settings.SettingsScreen; import forge.screens.settings.SettingsScreen;
import forge.toolbox.FEvent; import forge.toolbox.FEvent;
import forge.toolbox.FEvent.FEventHandler; import forge.toolbox.FEvent.FEventHandler;
import forge.view.IGameView;
public class VGameMenu extends FDropDownMenu { public class VGameMenu extends FDropDownMenu {
private final IGameView gameView; public VGameMenu() {
public VGameMenu(IGameView gameView0) {
gameView = gameView0;
} }
@Override @Override
@@ -71,7 +67,7 @@ public class VGameMenu extends FDropDownMenu {
//if re-enabling auto-yields, auto-yield to current ability on stack if applicable //if re-enabling auto-yields, auto-yield to current ability on stack if applicable
SpellAbility ability = game.getStack().peekAbility(); SpellAbility ability = game.getStack().peekAbility();
if (ability != null && ability.isAbility() && localPlayer.getController().shouldAutoYield(ability.toUnsuppressedString())) { if (ability != null && ability.isAbility() && localPlayer.getController().shouldAutoYield(ability.toUnsuppressedString())) {
gameView.passPriority(); FControl.getGameView().passPriority();
} }
} }
} }

View File

@@ -14,9 +14,9 @@ import forge.game.GameLogEntryType;
import forge.menu.FDropDown; import forge.menu.FDropDown;
import forge.model.FModel; import forge.model.FModel;
import forge.properties.ForgePreferences.FPref; import forge.properties.ForgePreferences.FPref;
import forge.screens.match.FControl;
import forge.toolbox.FDisplayObject; import forge.toolbox.FDisplayObject;
import forge.util.Utils; import forge.util.Utils;
import forge.view.IGameView;
public class VLog extends FDropDown { public class VLog extends FDropDown {
private static final float PADDING = Utils.scale(5); 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 ROW_COLOR = ALT_ROW_COLOR.darker();
private static final FSkinColor FORE_COLOR = FSkinColor.get(Colors.CLR_TEXT); private static final FSkinColor FORE_COLOR = FSkinColor.get(Colors.CLR_TEXT);
private final IGameView gameView; public VLog() {
public VLog(IGameView log0) {
gameView = log0;
} }
@Override @Override
@@ -48,7 +45,7 @@ public class VLog extends FDropDown {
clear(); clear();
GameLogEntryType logVerbosityFilter = GameLogEntryType.valueOf(FModel.getPreferences().getPref(FPref.DEV_LOG_ENTRY_TYPE)); GameLogEntryType logVerbosityFilter = GameLogEntryType.valueOf(FModel.getPreferences().getPref(FPref.DEV_LOG_ENTRY_TYPE));
List<GameLogEntry> logEntrys = gameView.getLogEntries(logVerbosityFilter); List<GameLogEntry> logEntrys = FControl.getGameView().getLogEntries(logVerbosityFilter);
LogEntryDisplay logEntryDisplay; LogEntryDisplay logEntryDisplay;
float width = maxWidth - getMenuTab().getScreenPosition().x; //stretch from tab to edge of screen float width = maxWidth - getMenuTab().getScreenPosition().x; //stretch from tab to edge of screen

View File

@@ -44,9 +44,10 @@ public class VPlayerPanel extends FContainer {
private final List<InfoTab> tabs = new ArrayList<InfoTab>(); private final List<InfoTab> tabs = new ArrayList<InfoTab>();
private InfoTab selectedTab; private InfoTab selectedTab;
public VPlayerPanel(PlayerView player0) { public VPlayerPanel(PlayerView player0, boolean showHand) {
player = player0; player = player0;
phaseIndicator = add(new VPhaseIndicator()); phaseIndicator = add(new VPhaseIndicator());
field = add(new VField(player)); field = add(new VField(player));
avatar = add(new VAvatar(player)); avatar = add(new VAvatar(player));
lblLife = add(new LifeLabel()); lblLife = add(new LifeLabel());
@@ -65,6 +66,10 @@ public class VPlayerPanel extends FContainer {
addZoneDisplay(ZoneType.Exile, FSkinImage.EXILE); addZoneDisplay(ZoneType.Exile, FSkinImage.EXILE);
commandZone = add(new CommandZoneDisplay(player)); commandZone = add(new CommandZoneDisplay(player));
if (showHand) {
setSelectedZone(ZoneType.Hand);
}
} }
public PlayerView getPlayer() { public PlayerView getPlayer() {

View File

@@ -19,6 +19,7 @@ import forge.card.CardDetailUtil;
import forge.card.CardRenderer; import forge.card.CardRenderer;
import forge.card.CardZoom; import forge.card.CardZoom;
import forge.card.CardDetailUtil.DetailColors; import forge.card.CardDetailUtil.DetailColors;
import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.menu.FCheckBoxMenuItem; import forge.menu.FCheckBoxMenuItem;
import forge.menu.FDropDown; import forge.menu.FDropDown;
@@ -47,17 +48,13 @@ public class VStack extends FDropDown {
private static final float ALPHA_COMPOSITE = 0.5f; private static final float ALPHA_COMPOSITE = 0.5f;
private static final TextRenderer textRenderer = new TextRenderer(true); private static final TextRenderer textRenderer = new TextRenderer(true);
private final IGameView gameView;
private final PlayerView localPlayer;
private StackInstanceDisplay activeItem; private StackInstanceDisplay activeItem;
private StackItemView activeStackInstance; private StackItemView activeStackInstance;
private Map<PlayerView, Object> playersWithValidTargets; private Map<PlayerView, Object> playersWithValidTargets;
private int stackSize; private int stackSize;
public VStack(IGameView gameView0, PlayerView localPlayer0) { public VStack() {
gameView = gameView0;
localPlayer = localPlayer0;
} }
@Override @Override
@@ -93,7 +90,7 @@ public class VStack extends FDropDown {
activeStackInstance = null; //reset before updating stack activeStackInstance = null; //reset before updating stack
restoreOldZones(); restoreOldZones();
final List<StackItemView> stack = gameView.getStack(); final List<StackItemView> stack = FControl.getGameView().getStack();
if (stackSize != stack.size()) { if (stackSize != stack.size()) {
int oldStackSize = stackSize; int oldStackSize = stackSize;
stackSize = stack.size(); 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 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; float width = totalWidth - 2 * MARGINS;
final List<StackItemView> stack = gameView.getStack(); final List<StackItemView> stack = FControl.getGameView().getStack();
if (stack.isEmpty()) { //show label if stack empty if (stack.isEmpty()) { //show label if stack empty
FLabel label = add(new FLabel.Builder().text("[Empty]").font(FONT).align(HAlignment.CENTER).build()); 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(); text = stackInstance.getText();
if (stackInstance.isOptionalTrigger() && if (stackInstance.isOptionalTrigger() &&
stackInstance0.getActivatingPlayer().getLobbyPlayer().equals(localPlayer)) { stackInstance0.getActivatingPlayer().equals(FControl.getCurrentPlayer())) {
text = "(OPTIONAL) " + text; text = "(OPTIONAL) " + text;
} }
@@ -227,11 +224,14 @@ public class VStack extends FDropDown {
VStack.this.updateSizeAndPosition(); VStack.this.updateSizeAndPosition();
return true; 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()) { if (stackInstance.isAbility()) {
FPopupMenu menu = new FPopupMenu() { FPopupMenu menu = new FPopupMenu() {
@Override @Override
protected void buildMenu() { protected void buildMenu() {
final IGameView gameView = FControl.getGameView();
final Player player = FControl.getCurrentPlayer();
final String key = stackInstance.getKey(); final String key = stackInstance.getKey();
final boolean autoYield = gameView.shouldAutoYield(key); final boolean autoYield = gameView.shouldAutoYield(key);
addItem(new FCheckBoxMenuItem("Auto-Yield", autoYield, 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(); final int triggerID = stackInstance.getSourceTrigger();
addItem(new FCheckBoxMenuItem("Always Yes", addItem(new FCheckBoxMenuItem("Always Yes",
gameView.shouldAlwaysAcceptTrigger(triggerID), gameView.shouldAlwaysAcceptTrigger(triggerID),

View File

@@ -22,12 +22,10 @@ import java.util.Observer;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import forge.FThreads; import forge.FThreads;
import forge.game.Game;
import forge.interfaces.IGuiBase; import forge.interfaces.IGuiBase;
import forge.player.PlayerControllerHuman;
import forge.util.ITriggerEvent; import forge.util.ITriggerEvent;
import forge.util.gui.SOptionPane;
import forge.view.CardView; import forge.view.CardView;
import forge.view.LocalGameView;
import forge.view.PlayerView; import forge.view.PlayerView;
import forge.view.SpellAbilityView; import forge.view.SpellAbilityView;
@@ -43,48 +41,21 @@ public class InputProxy implements Observer {
/** The input. */ /** The input. */
private AtomicReference<Input> input = new AtomicReference<Input>(); private AtomicReference<Input> input = new AtomicReference<Input>();
private final Game game; private final LocalGameView gameView;
// private static final boolean DEBUG_INPUT = true; // false; // private static final boolean DEBUG_INPUT = true; // false;
private final PlayerControllerHuman controller; public InputProxy(final LocalGameView gameView0) {
public InputProxy(final PlayerControllerHuman controller, final Game game) { this.gameView = gameView0;
this.controller = controller;
this.game = game;
} }
private IGuiBase getGui() { private IGuiBase getGui() {
return this.controller.getGui(); return this.gameView.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;
} }
@Override @Override
public final void update(final Observable observable, final Object obj) { 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) /* if(DEBUG_INPUT)
System.out.printf("%s ... \t%s on %s, \tstack = %s%n", System.out.printf("%s ... \t%s on %s, \tstack = %s%n",
FThreads.debugGetStackTraceItem(6, true), nextInput == null ? "null" : nextInput.getClass().getSimpleName(), 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) { public final void selectPlayer(final PlayerView player, final ITriggerEvent triggerEvent) {
final Input inp = getInput(); final Input inp = getInput();
if (inp != null) { 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) { public final boolean selectCard(final CardView cardView, final ITriggerEvent triggerEvent) {
final Input inp = getInput(); final Input inp = getInput();
if (inp != null) { if (inp != null) {
return inp.selectCard(controller.getCard(cardView), triggerEvent); return inp.selectCard(gameView.getCard(cardView), triggerEvent);
} }
return false; return false;
} }
@@ -161,7 +132,7 @@ public class InputProxy implements Observer {
public final void selectAbility(final SpellAbilityView ab) { public final void selectAbility(final SpellAbilityView ab) {
final Input inp = getInput(); final Input inp = getInput();
if (inp != null) { 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} */ /** @return {@link forge.gui.InputProxy.InputBase} */
private Input getInput() { public Input getInput() {
return this.input.get(); return this.input.get();
} }
} }

View File

@@ -22,8 +22,7 @@ import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingDeque;
import forge.game.Game; import forge.game.Game;
import forge.game.player.Player; import forge.view.IGameView;
import forge.player.PlayerControllerHuman;
/** /**
* <p> * <p>
@@ -37,22 +36,18 @@ public class InputQueue extends Observable {
private final BlockingDeque<InputSynchronized> inputStack = new LinkedBlockingDeque<InputSynchronized>(); private final BlockingDeque<InputSynchronized> inputStack = new LinkedBlockingDeque<InputSynchronized>();
private final InputLockUI inputLock; private final InputLockUI inputLock;
public InputQueue(final Game game) { public InputQueue(final Game game, final InputProxy inputProxy) {
inputLock = new InputLockUI(game, this); inputLock = new InputLockUI(game, this);
for (final Player p : game.getPlayers()) { addObserver(inputProxy);
if (p.getController() instanceof PlayerControllerHuman) {
this.addObserver(((PlayerControllerHuman) p.getController()).getInputProxy());
}
}
} }
public final void updateObservers() { public final void updateObservers() {
this.setChanged(); setChanged();
this.notifyObservers(); notifyObservers();
} }
public final Input getInput() { public final Input getInput() {
return inputStack.isEmpty() ? null : this.inputStack.peek(); return inputStack.isEmpty() ? null : inputStack.peek();
} }
public final void removeInput(Input inp) { public final void removeInput(Input inp) {
@@ -71,9 +66,9 @@ public class InputQueue extends Observable {
* *
* @return a {@link forge.gui.input.InputBase} object. * @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 Input topMost = inputStack.peek(); // incoming input to Control
if (topMost != null && !game.isGameOver()) { if (topMost != null && !gameView.isGameOver()) {
return topMost; return topMost;
} }
return inputLock; return inputLock;
@@ -85,10 +80,10 @@ public class InputQueue extends Observable {
} }
public void setInput(final InputSynchronized input) { public void setInput(final InputSynchronized input) {
this.inputStack.push(input); inputStack.push(input);
inputLock.setGui(input.getGui()); inputLock.setGui(input.getGui());
syncPoint(); syncPoint();
this.updateObservers(); updateObservers();
} }
public void syncPoint() { public void syncPoint() {

View File

@@ -29,7 +29,6 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn
cdlDone.countDown(); cdlDone.countDown();
} }
public void showAndWait() { public void showAndWait() {
getGui().getInputQueue().setInput(this); getGui().getInputQueue().setInput(this);
awaitLatchRelease(); awaitLatchRelease();

View File

@@ -31,6 +31,7 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import forge.FThreads;
import forge.LobbyPlayer; import forge.LobbyPlayer;
import forge.achievement.AchievementCollection; import forge.achievement.AchievementCollection;
import forge.card.CardCharacteristicName; import forge.card.CardCharacteristicName;
@@ -118,9 +119,6 @@ import forge.view.StackItemView;
* Handles phase skips for now. * Handles phase skips for now.
*/ */
public class PlayerControllerHuman extends PlayerController { public class PlayerControllerHuman extends PlayerController {
private IGuiBase gui;
private final InputProxy inputProxy;
private final GameView gameView; private final GameView gameView;
/** /**
* Cards this player may look at right now, for example when searching a * 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) { public PlayerControllerHuman(final Game game0, final Player p, final LobbyPlayer lp, final IGuiBase gui) {
super(game0, p, lp); super(game0, p, lp);
this.gui = gui; this.gameView = new GameView(game0, gui);
this.inputProxy = new InputProxy(this, game0);
this.gameView = new GameView(game0);
// aggressively cache a view for each player (also caches cards) // aggressively cache a view for each player (also caches cards)
for (final Player player : game.getRegisteredPlayers()) { for (final Player player : game.getRegisteredPlayers()) {
@@ -142,11 +138,11 @@ public class PlayerControllerHuman extends PlayerController {
} }
public IGuiBase getGui() { public IGuiBase getGui() {
return gui; return gameView.getGui();
} }
public InputProxy getInputProxy() { public InputProxy getInputProxy() {
return inputProxy; return gameView.getInputProxy();
} }
public LocalGameView getGameView() { public LocalGameView getGameView() {
@@ -1334,8 +1330,8 @@ public class PlayerControllerHuman extends PlayerController {
* What follows are the View methods. * What follows are the View methods.
*/ */
private class GameView extends LocalGameView { private class GameView extends LocalGameView {
public GameView(Game game) { public GameView(Game game0, IGuiBase gui0) {
super(game); super(game0, gui0);
} }
@Override @Override
@@ -1395,12 +1391,29 @@ public class PlayerControllerHuman extends PlayerController {
@Override @Override
public boolean passPriority() { public boolean passPriority() {
return getInputProxy().passPriority(); return passPriority(false);
} }
@Override @Override
public boolean passPriorityUntilEndOfTurn() { 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 @Override
@@ -1472,11 +1485,11 @@ public class PlayerControllerHuman extends PlayerController {
@Override @Override
public boolean getDisableAutoYields() { public boolean getDisableAutoYields() {
return this.getGame().getDisableAutoYields(); return game.getDisableAutoYields();
} }
@Override @Override
public void setDisableAutoYields(final boolean b) { public void setDisableAutoYields(final boolean b) {
this.getGame().setDisableAutoYields(b); game.setDisableAutoYields(b);
} }
@Override @Override

View File

@@ -27,16 +27,37 @@ import forge.game.player.RegisteredPlayer;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance; import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.zone.ZoneType; 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 { 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(Game game0, IGuiBase gui0) {
public LocalGameView(final Game game) { game = game0;
this.game = game; gui = gui0;
inputProxy = new InputProxy(this);
inputQueue = new InputQueue(game, inputProxy);
} }
protected final Game getGame() { public final Game getGame() {
return this.game; return game;
}
public final IGuiBase getGui() {
return gui;
}
public final InputQueue getInputQueue() {
return inputQueue;
}
public InputProxy getInputProxy() {
return inputProxy;
} }
/** Cache of players. */ /** Cache of players. */
@@ -60,17 +81,17 @@ public abstract class LocalGameView implements IGameView {
*/ */
@Override @Override
public GameType getGameType() { public GameType getGameType() {
return this.game.getMatch().getRules().getGameType(); return game.getMatch().getRules().getGameType();
} }
@Override @Override
public int getTurnNumber() { public int getTurnNumber() {
return this.game.getPhaseHandler().getTurn(); return game.getPhaseHandler().getTurn();
} }
@Override @Override
public boolean isCommandZoneNeeded() { public boolean isCommandZoneNeeded() {
return this.game.getMatch().getRules().getGameType().isCommandZoneNeeded(); return game.getMatch().getRules().getGameType().isCommandZoneNeeded();
} }
@Override @Override
@@ -93,37 +114,37 @@ public abstract class LocalGameView implements IGameView {
*/ */
@Override @Override
public boolean isFirstGameInMatch() { public boolean isFirstGameInMatch() {
return this.game.getMatch().getPlayedGames().isEmpty(); return game.getMatch().getPlayedGames().isEmpty();
} }
@Override @Override
public boolean isMatchOver() { public boolean isMatchOver() {
return this.game.getMatch().isMatchOver(); return game.getMatch().isMatchOver();
} }
@Override @Override
public int getNumGamesInMatch() { public int getNumGamesInMatch() {
return this.game.getMatch().getRules().getGamesPerMatch(); return game.getMatch().getRules().getGamesPerMatch();
} }
@Override @Override
public int getNumPlayedGamesInMatch() { public int getNumPlayedGamesInMatch() {
return this.game.getMatch().getPlayedGames().size(); return game.getMatch().getPlayedGames().size();
} }
@Override @Override
public Iterable<GameOutcome> getOutcomesOfMatch() { public Iterable<GameOutcome> getOutcomesOfMatch() {
return Iterables.unmodifiableIterable(this.game.getMatch().getPlayedGames()); return Iterables.unmodifiableIterable(game.getMatch().getPlayedGames());
} }
@Override @Override
public boolean isMatchWonBy(final LobbyPlayer p) { public boolean isMatchWonBy(final LobbyPlayer p) {
return this.game.getMatch().isWonBy(p); return game.getMatch().isWonBy(p);
} }
@Override @Override
public int getGamesWonBy(final LobbyPlayer p) { public int getGamesWonBy(final LobbyPlayer p) {
return this.game.getMatch().getGamesWonBy(p); return game.getMatch().getGamesWonBy(p);
} }
@Override @Override
@@ -133,7 +154,7 @@ public abstract class LocalGameView implements IGameView {
@Override @Override
public Deck getDeck(final LobbyPlayer player) { 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)) { if (rp.getPlayer().equals(player)) {
return rp.getDeck(); return rp.getDeck();
} }

View File

@@ -5,6 +5,7 @@ package forge.view;
import forge.game.Game; import forge.game.Game;
import forge.game.card.Card; import forge.game.card.Card;
import forge.interfaces.IGuiBase;
import forge.match.input.Input; import forge.match.input.Input;
import forge.match.input.InputPlaybackControl; import forge.match.input.InputPlaybackControl;
import forge.match.input.InputQueue; import forge.match.input.InputQueue;
@@ -16,9 +17,6 @@ import forge.util.ITriggerEvent;
* *
*/ */
public class WatchLocalGame extends LocalGameView { public class WatchLocalGame extends LocalGameView {
private final InputQueue inputQueue;
/** /**
* @param game * @param game
* the @{link Game} to attach to. * the @{link Game} to attach to.
@@ -26,9 +24,8 @@ public class WatchLocalGame extends LocalGameView {
* the {@link InputQueue} of the game to enable playback * the {@link InputQueue} of the game to enable playback
* controls, or {@code null} to disallow them. * controls, or {@code null} to disallow them.
*/ */
public WatchLocalGame(final Game game, final InputQueue inputQueue) { public WatchLocalGame(Game game0, IGuiBase gui0) {
super(game); super(game0, gui0);
this.inputQueue = inputQueue;
} }
@Override @Override