diff --git a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java index 9d57b178961..320f0945901 100644 --- a/forge-gui-desktop/src/main/java/forge/GuiDesktop.java +++ b/forge-gui-desktop/src/main/java/forge/GuiDesktop.java @@ -270,7 +270,7 @@ public class GuiDesktop implements IGuiBase { public IGuiGame getNewGuiGame() { return new CMatchUI(); - }; + } @Override public HostedMatch hostMatch() { diff --git a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java index 832e25b2593..022d1fd05d4 100644 --- a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java +++ b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java @@ -245,7 +245,10 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener { } public Deck getDeck() { - DeckProxy proxy = lstDecks.getSelectedItem(); + final DeckProxy proxy = lstDecks.getSelectedItem(); + if (proxy == null) { + return null; + } return proxy.getDeck(); } @@ -271,12 +274,11 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener { if (decksComboBox == null) { //initialize components with delayed initialization the first time this is populated decksComboBox = new DecksComboBox(); lstDecksContainer = new ItemManagerContainer(lstDecks); - restoreSavedState(); decksComboBox.addListener(this); + restoreSavedState(); } else { removeAll(); - restoreSavedState(); //ensure decks refreshed and state restored in case any deleted or added since last loaded } this.setLayout(new MigLayout("insets 0, gap 0")); decksComboBox.addTo(this, "w 100%, h 30px!, gapbottom 5px, spanx 2, wrap"); diff --git a/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java b/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java index 2a8574ba092..2cf6e4ec884 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java +++ b/forge-gui-desktop/src/main/java/forge/gui/CardDetailPanel.java @@ -34,6 +34,7 @@ import forge.card.CardDetailUtil; import forge.card.CardDetailUtil.DetailColors; import forge.card.CardEdition; import forge.card.CardRarity; +import forge.game.GameView; import forge.game.card.Card; import forge.game.card.CardView; import forge.game.card.CardView.CardStateView; @@ -69,6 +70,8 @@ public class CardDetailPanel extends SkinnedPanel { private final FHtmlViewer cdArea; private final FScrollPane scrArea; + private GameView gameView = null; + public CardDetailPanel() { super(); setLayout(null); @@ -100,6 +103,10 @@ public class CardDetailPanel extends SkinnedPanel { add(scrArea); } + public void setGameView(final GameView gameView) { + this.gameView = gameView; + } + @Override public void doLayout() { int insets = 3; @@ -261,7 +268,7 @@ public class CardDetailPanel extends SkinnedPanel { idLabel.setText(canShow ? CardDetailUtil.formatCardId(state) : ""); // fill the card text - cdArea.setText(FSkin.encodeSymbols(CardDetailUtil.composeCardText(state, canShow), true)); + cdArea.setText(FSkin.encodeSymbols(CardDetailUtil.composeCardText(state, gameView, canShow), true)); SwingUtilities.invokeLater(new Runnable() { @Override diff --git a/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java b/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java index 1f8ae695a6d..fe816af3e97 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java +++ b/forge-gui-desktop/src/main/java/forge/gui/framework/EDocID.java @@ -3,6 +3,8 @@ */ package forge.gui.framework; +import com.google.common.collect.ObjectArrays; + import forge.screens.deckeditor.views.VAllDecks; import forge.screens.deckeditor.views.VCardCatalog; import forge.screens.deckeditor.views.VCurrentDeck; @@ -126,6 +128,7 @@ public enum EDocID { for (int i = 0; i < 8; i++) EDocID.Commands[i].setDoc(new VEmptyDoc(EDocID.Commands[i])); for (int i = 0; i < 8; i++) EDocID.Hands[i].setDoc(new VEmptyDoc(EDocID.Hands[i])); } + public final static EDocID[] VarDocs = ObjectArrays.concat(ObjectArrays.concat(Commands, Fields, EDocID.class), Hands, EDocID.class); // End enum declarations, start enum methods. private IVDoc vDoc; diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java b/forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java index e0560875086..dc53ffbea61 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java @@ -29,7 +29,7 @@ public class CLobby { Vector listData; Object val; - for (int i = 0; i < 8; i++) { + for (int i = 0; i < VLobby.MAX_PLAYERS; i++) { // Commander: reinit deck list and restore last selections (if any) deckList = view.getCommanderDeckLists().get(i); listData = new Vector(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java b/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java index 2bb00ab574c..160e9ca29bc 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java @@ -228,7 +228,6 @@ public class PlayerPanel extends FPanel { lobby.firePlayerChangeListener(index); avatarLabel.requestFocusInWindow(); lobby.updateVanguardList(index); - lobby.update(); } }; }; @@ -255,7 +254,6 @@ public class PlayerPanel extends FPanel { prefs.save(); } lobby.firePlayerChangeListener(index); - lobby.update(); } } }; diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java b/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java index 6f08f45ea0e..ae9fd8ad681 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java @@ -106,7 +106,7 @@ public class VLobby implements IUpdateable { // Deck frame elements private final JPanel decksFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap, hidemode 3")); - private final List deckChoosers = new ArrayList(8); + private final List deckChoosers = Lists.newArrayListWithCapacity(MAX_PLAYERS); private final FCheckBox cbSingletons = new FCheckBox("Singleton Mode"); private final FCheckBox cbArtifacts = new FCheckBox("Remove Artifacts"); private final Deck[] decks = new Deck[MAX_PLAYERS]; @@ -205,7 +205,7 @@ public class VLobby implements IUpdateable { populateVanguardLists(); } - public void update() { + public void update(final boolean fullUpdate) { activePlayersNum = lobby.getNumberOfSlots(); addPlayerBtn.setEnabled(activePlayersNum < MAX_PLAYERS); @@ -221,19 +221,22 @@ public class VLobby implements IUpdateable { // visible panels final LobbySlot slot = lobby.getSlot(i); final PlayerPanel panel; + final boolean isNewPanel; if (hasPanel) { panel = playerPanels.get(i); - panel.setVisible(true); + isNewPanel = !panel.isVisible(); } else { panel = new PlayerPanel(this, allowNetworking, i, slot, lobby.mayEdit(i), lobby.hasControl()); playerPanels.add(panel); String constraints = "pushx, growx, wrap, hidemode 3"; if (i == 0) { constraints += ", gaptop 5px"; - playerPanelWithFocus = panel; - playerPanelWithFocus.setFocused(true); } playersScroll.add(panel, constraints); + if (i == 0) { + changePlayerFocus(0); + } + isNewPanel = true; } panel.setType(slot.getType()); @@ -248,16 +251,24 @@ public class VLobby implements IUpdateable { panel.setMayRemove(lobby.mayRemove(i)); panel.update(); - deckChoosers.get(i).setIsAi(slot.getType() == LobbySlotType.AI); + final FDeckChooser deckChooser = getDeckChooser(i); + deckChooser.setIsAi(slot.getType() == LobbySlotType.AI); + if (fullUpdate) { + selectDeck(i); + } + if (isNewPanel) { + panel.setVisible(true); + } } else if (hasPanel) { playerPanels.get(i).setVisible(false); } } if (playerWithFocus >= activePlayersNum) { - playerWithFocus = activePlayersNum - 1; + changePlayerFocus(activePlayersNum - 1); + } else { + populateDeckPanel(getCurrentGameMode()); } - changePlayerFocus(playerWithFocus); refreshPanels(true, true); } @@ -268,7 +279,7 @@ public class VLobby implements IUpdateable { void setReady(final int index, final boolean ready) { if (ready && decks[index] == null) { GuiBase.getInterface().showOptionDialog("Select a deck before readying!", "Error", FSkinProp.ICO_WARNING, new String[] { "Ok" }, 0); - update(); + update(false); return; } @@ -280,13 +291,13 @@ public class VLobby implements IUpdateable { playerChangeListener.update(index, getSlot(index)); } } - void fireDeckChangeListener(final int index, final Deck deck) { + private void fireDeckChangeListener(final int index, final Deck deck) { decks[index] = deck; if (playerChangeListener != null) { playerChangeListener.update(index, UpdateLobbyPlayerEvent.deckUpdate(deck)); } } - void fireDeckSectionChangeListener(final int index, final DeckSection section, final CardPool cards) { + private void fireDeckSectionChangeListener(final int index, final DeckSection section, final CardPool cards) { decks[index].putSection(section, cards); if (playerChangeListener != null) { playerChangeListener.update(index, UpdateLobbyPlayerEvent.deckUpdate(section, cards)); @@ -314,12 +325,12 @@ public class VLobby implements IUpdateable { // Main deck final FDeckChooser mainChooser = new FDeckChooser(null, false); - mainChooser.initialize(); mainChooser.getLstDecks().setSelectCommand(new UiCommand() { @Override public final void run() { - VLobby.this.onDeckClicked(playerIndex, mainChooser.getSelectedDeckType(), mainChooser.getLstDecks().getSelectedItems()); + selectMainDeck(playerIndex); } }); + mainChooser.initialize(); deckChoosers.add(mainChooser); // Scheme deck list @@ -331,34 +342,7 @@ public class VLobby implements IUpdateable { schemeDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); schemeDeckList.addListSelectionListener(new ListSelectionListener() { @Override public final void valueChanged(final ListSelectionEvent e) { - if (playerIndex >= activePlayersNum) { - return; - } - - final Object selected = schemeDeckList.getSelectedValue(); - final Deck deck = decks[playerIndex]; - CardPool schemePool = null; - if (selected instanceof String) { - String sel = (String) selected; - if (sel.contains("Use deck's scheme section")) { - if (deck.has(DeckSection.Schemes)) { - schemePool = deck.get(DeckSection.Schemes); - } else { - sel = "Random"; - } - } - final IStorage sDecks = FModel.getDecks().getScheme(); - if (sel.equals("Random") && sDecks.size() != 0) { - schemePool = Aggregates.random(sDecks).get(DeckSection.Schemes); - } - } else if (selected instanceof Deck) { - schemePool = ((Deck) selected).get(DeckSection.Schemes); - } - if (schemePool == null) { //Can be null if player deselects the list selection or chose Generate - schemePool = DeckgenUtil.generateSchemePool(); - } - fireDeckSectionChangeListener(playerIndex, DeckSection.Schemes, schemePool); - getDeckChooser(playerIndex).saveState(); + selectSchemeDeck(playerIndex); } }); @@ -377,30 +361,9 @@ public class VLobby implements IUpdateable { commanderDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); commanderDeckList.addListSelectionListener(new ListSelectionListener() { @Override public final void valueChanged(final ListSelectionEvent e) { - if (playerIndex >= activePlayersNum) { - return; - } - - final Object selected = commanderDeckList.getSelectedValue(); - Deck deck = null; - if (selected instanceof String) { - final String sel = (String) selected; - final IStorage comDecks = FModel.getDecks().getCommander(); - if (sel.equals("Random") && comDecks.size() > 0) { - deck = Aggregates.random(comDecks); - } - } else if (selected instanceof Deck) { - deck = (Deck) selected; - } - final GameType commanderGameType = hasVariant(GameType.TinyLeaders) ? GameType.TinyLeaders : GameType.Commander; - if (deck == null) { //Can be null if player deselects the list selection or chose Generate - deck = DeckgenUtil.generateCommanderDeck(isPlayerAI(playerIndex), commanderGameType); - } - fireDeckChangeListener(playerIndex, deck); - getDeckChooser(playerIndex).saveState(); + selectCommanderDeck(playerIndex); } }); - final FScrollPane scrCommander = new FScrollPane(commanderDeckList, true, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); @@ -417,34 +380,7 @@ public class VLobby implements IUpdateable { planarDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); planarDeckList.addListSelectionListener(new ListSelectionListener() { @Override public final void valueChanged(final ListSelectionEvent e) { - if (playerIndex >= activePlayersNum) { - return; - } - - final Object selected = planarDeckList.getSelectedValue(); - final Deck deck = decks[playerIndex]; - CardPool planePool = null; - if (selected instanceof String) { - String sel = (String) selected; - if (sel.contains("Use deck's planes section")) { - if (deck.has(DeckSection.Planes)) { - planePool = deck.get(DeckSection.Planes); - } else { - sel = "Random"; - } - } - final IStorage pDecks = FModel.getDecks().getPlane(); - if (sel.equals("Random") && pDecks.size() != 0) { - planePool = Aggregates.random(pDecks).get(DeckSection.Planes); - } - } else if (selected instanceof Deck) { - planePool = ((Deck) selected).get(DeckSection.Planes); - } - if (planePool == null) { //Can be null if player deselects the list selection or chose Generate - planePool = DeckgenUtil.generatePlanarPool(); - } - fireDeckSectionChangeListener(playerIndex, DeckSection.Planes, planePool); - getDeckChooser(playerIndex).saveState(); + selectPlanarDeck(playerIndex); } }); @@ -477,11 +413,114 @@ public class VLobby implements IUpdateable { vgdPanels.add(vgdDeckPanel); } - protected void onDeckClicked(final int iPlayer, final DeckType type, final Collection selectedDecks) { + private void selectDeck(final int playerIndex) { + selectMainDeck(playerIndex); + selectCommanderDeck(playerIndex); + selectSchemeDeck(playerIndex); + selectPlanarDeck(playerIndex); + } + + private void selectMainDeck(final int playerIndex) { + if (hasVariant(GameType.Commander) || hasVariant(GameType.TinyLeaders)) { + // These game types use specific deck panel + return; + } + final FDeckChooser mainChooser = getDeckChooser(playerIndex); + VLobby.this.onDeckClicked(playerIndex, mainChooser.getSelectedDeckType(), mainChooser.getDeck(), mainChooser.getLstDecks().getSelectedItems()); + getDeckChooser(playerIndex).saveState(); + } + + private void selectSchemeDeck(final int playerIndex) { + if (playerIndex >= activePlayersNum || !(hasVariant(GameType.Archenemy) || hasVariant(GameType.ArchenemyRumble))) { + return; + } + + final Object selected = getSchemeDeckLists().get(playerIndex).getSelectedValue(); + final Deck deck = decks[playerIndex]; + CardPool schemePool = null; + if (selected instanceof String) { + String sel = (String) selected; + if (sel.contains("Use deck's scheme section")) { + if (deck.has(DeckSection.Schemes)) { + schemePool = deck.get(DeckSection.Schemes); + } else { + sel = "Random"; + } + } + final IStorage sDecks = FModel.getDecks().getScheme(); + if (sel.equals("Random") && sDecks.size() != 0) { + schemePool = Aggregates.random(sDecks).get(DeckSection.Schemes); + } + } else if (selected instanceof Deck) { + schemePool = ((Deck) selected).get(DeckSection.Schemes); + } + if (schemePool == null) { //Can be null if player deselects the list selection or chose Generate + schemePool = DeckgenUtil.generateSchemePool(); + } + fireDeckSectionChangeListener(playerIndex, DeckSection.Schemes, schemePool); + getDeckChooser(playerIndex).saveState(); + } + + private void selectCommanderDeck(final int playerIndex) { + if (playerIndex >= activePlayersNum || !(hasVariant(GameType.Commander) || hasVariant(GameType.TinyLeaders))) { + return; + } + + final Object selected = getCommanderDeckLists().get(playerIndex).getSelectedValue(); + Deck deck = null; + if (selected instanceof String) { + final String sel = (String) selected; + final IStorage comDecks = FModel.getDecks().getCommander(); + if (sel.equals("Random") && comDecks.size() > 0) { + deck = Aggregates.random(comDecks); + } + } else if (selected instanceof Deck) { + deck = (Deck) selected; + } + final GameType commanderGameType = hasVariant(GameType.TinyLeaders) ? GameType.TinyLeaders : GameType.Commander; + if (deck == null) { //Can be null if player deselects the list selection or chose Generate + deck = DeckgenUtil.generateCommanderDeck(isPlayerAI(playerIndex), commanderGameType); + } + fireDeckChangeListener(playerIndex, deck); + getDeckChooser(playerIndex).saveState(); + } + + private void selectPlanarDeck(final int playerIndex) { + if (playerIndex >= activePlayersNum) { + return; + } + + final Object selected = getPlanarDeckLists().get(playerIndex).getSelectedValue(); + final Deck deck = decks[playerIndex]; + CardPool planePool = null; + if (selected instanceof String) { + String sel = (String) selected; + if (sel.contains("Use deck's planes section")) { + if (deck.has(DeckSection.Planes)) { + planePool = deck.get(DeckSection.Planes); + } else { + sel = "Random"; + } + } + final IStorage pDecks = FModel.getDecks().getPlane(); + if (sel.equals("Random") && pDecks.size() != 0) { + planePool = Aggregates.random(pDecks).get(DeckSection.Planes); + } + } else if (selected instanceof Deck) { + planePool = ((Deck) selected).get(DeckSection.Planes); + } + if (planePool == null) { //Can be null if player deselects the list selection or chose Generate + planePool = DeckgenUtil.generatePlanarPool(); + } + fireDeckSectionChangeListener(playerIndex, DeckSection.Planes, planePool); + getDeckChooser(playerIndex).saveState(); + } + + protected void onDeckClicked(final int iPlayer, final DeckType type, final Deck deck, final Collection selectedDecks) { if (iPlayer < activePlayersNum && lobby.mayEdit(iPlayer)) { final String text = type.toString() + ": " + Lang.joinHomogenous(selectedDecks, DeckProxy.FN_GET_NAME); playerPanels.get(iPlayer).setDeckSelectorButtonText(text); - fireDeckChangeListener(iPlayer, selectedDecks.iterator().next().getDeck()); + fireDeckChangeListener(iPlayer, deck); } } @@ -560,10 +599,10 @@ public class VLobby implements IUpdateable { } void setCurrentGameMode(final GameType mode) { lobby.setGameType(mode); - update(); + update(true); } - public boolean isPlayerAI(final int playernum) { + private boolean isPlayerAI(final int playernum) { return playernum < activePlayersNum ? playerPanels.get(playernum).isAi() : false; } @@ -588,7 +627,9 @@ public class VLobby implements IUpdateable { } void changePlayerFocus(int newFocusOwner, GameType gType) { - playerPanelWithFocus.setFocused(false); + if (playerPanelWithFocus != null) { + playerPanelWithFocus.setFocused(false); + } playerWithFocus = newFocusOwner; playerPanelWithFocus = playerPanels.get(playerWithFocus); playerPanelWithFocus.setFocused(true); @@ -675,7 +716,6 @@ public class VLobby implements IUpdateable { } else { lobby.removeVariant(variantType); } - VLobby.this.update(); } }); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/online/CSubmenuOnlineLobby.java b/forge-gui-desktop/src/main/java/forge/screens/home/online/CSubmenuOnlineLobby.java index fce4169abd2..35bf3517fba 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/online/CSubmenuOnlineLobby.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/online/CSubmenuOnlineLobby.java @@ -45,8 +45,8 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider { FNetOverlay.SINGLETON_INSTANCE.showUp("Hosting game"); lobby.setListener(new IUpdateable() { - @Override public final void update() { - view.update(); + @Override public final void update(final boolean fullUpdate) { + view.update(fullUpdate); server.updateLobbyState(); } }); @@ -79,7 +79,7 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider { } }); - view.update(); + view.update(true); Singletons.getControl().setCurrentScreen(FScreen.ONLINE_LOBBY); FNetOverlay.SINGLETON_INSTANCE.showUp(String.format("Hosting on port %d", portNumber)); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuConstructed.java b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuConstructed.java index f492686844f..1df4f39e9af 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuConstructed.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/sanctioned/VSubmenuConstructed.java @@ -42,7 +42,7 @@ public enum VSubmenuConstructed implements IVSubmenu { } }); - vLobby.update(); + vLobby.update(false); } public VLobby getLobby() { 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 5bb57788b9f..2b1365f5710 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 @@ -66,12 +66,14 @@ import forge.gui.GuiChoose; import forge.gui.GuiDialog; import forge.gui.GuiUtils; import forge.gui.SOverlayUtils; +import forge.gui.framework.DragCell; import forge.gui.framework.EDocID; import forge.gui.framework.FScreen; import forge.gui.framework.ICDoc; import forge.gui.framework.IVDoc; import forge.gui.framework.SDisplayUtil; import forge.gui.framework.SLayoutIO; +import forge.gui.framework.VEmptyDoc; import forge.interfaces.IButton; import forge.item.InventoryItem; import forge.item.PaperCard; @@ -181,6 +183,7 @@ public final class CMatchUI @Override public void setGameView(final GameView gameView) { super.setGameView(gameView); + cDetailPicture.setGameView(gameView); screen.setTabCaption(gameView.getTitle()); if (sortedPlayers != null) { for (final PlayerView pv : sortedPlayers) { @@ -516,6 +519,16 @@ public final class CMatchUI public void register() { initHandViews(); registerDocs(); + for (final EDocID fieldDoc : EDocID.VarDocs) { + // Remove unnecessary docs for this match + if (!myDocs.containsKey(fieldDoc)) { + final DragCell parent = fieldDoc.getDoc().getParentCell(); + if (parent != null) { + parent.removeDoc(fieldDoc.getDoc()); + fieldDoc.setDoc(new VEmptyDoc(fieldDoc)); + } + } + } } @Override diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/VMatchUI.java b/forge-gui-desktop/src/main/java/forge/screens/match/VMatchUI.java index 7bc6c14b360..f7f3898129b 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/VMatchUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/VMatchUI.java @@ -7,7 +7,6 @@ import java.util.List; import javax.swing.SwingUtilities; import forge.Singletons; -import forge.game.GameView; import forge.gui.framework.DragCell; import forge.gui.framework.EDocID; import forge.gui.framework.FScreen; @@ -196,18 +195,16 @@ public class VMatchUI implements IVTopLevelUI { @Override public boolean onClosing(final FScreen screen) { if (!Singletons.getControl().getCurrentScreen().equals(screen)) { + // Switch to this screen if not already showing Singletons.getControl().setCurrentScreen(screen); } - final GameView gameView = control.getGameView(); - if (gameView != null && !gameView.isGameOver()) { - control.concede(); - return false; //delay hiding tab even if concede successful + if (control.concede()) { + //switch back to menus music when closing screen + SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MENUS); + return true; } - //switch back to menus music when closing screen - SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MENUS); - - return true; + return false; } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDetailPicture.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDetailPicture.java index d77067f5e82..18ef30b7825 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDetailPicture.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDetailPicture.java @@ -1,5 +1,6 @@ package forge.screens.match.controllers; +import forge.game.GameView; import forge.game.card.Card; import forge.game.card.CardView; import forge.interfaces.IMayViewCards; @@ -75,6 +76,10 @@ public class CDetailPicture { } } + public void setGameView(final GameView gameView) { + cDetail.getView().setGameView(gameView); + } + void flip() { if (mayFlip()) { isDisplayAlt = !isDisplayAlt; diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDev.java b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDev.java index 80b1f403e80..39b43fd5d7d 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDev.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/controllers/CDev.java @@ -61,7 +61,7 @@ public class CDev implements ICDoc { private final MouseListener madViewAll = new MouseAdapter() { @Override - public void mousePressed(MouseEvent e) { + public void mousePressed(final MouseEvent e) { toggleViewAllCards(); } }; @@ -228,8 +228,8 @@ public class CDev implements ICDoc { @Override public void update() { if (getController() != null) { - view.getLblUnlimitedLands().setToggled(!getController().canPlayUnlimitedLands()); - view.getLblViewAll().setToggled(!getController().mayLookAtAllCards()); + view.getLblUnlimitedLands().setToggled(getController().canPlayUnlimitedLands()); + view.getLblViewAll().setToggled(getController().mayLookAtAllCards()); } } } diff --git a/forge-gui-desktop/src/main/java/forge/screens/match/views/VDetail.java b/forge-gui-desktop/src/main/java/forge/screens/match/views/VDetail.java index 2df679b7e25..4e1851e18ad 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/match/views/VDetail.java +++ b/forge-gui-desktop/src/main/java/forge/screens/match/views/VDetail.java @@ -18,6 +18,7 @@ package forge.screens.match.views; import forge.assets.FSkinProp; +import forge.game.GameView; import forge.gui.CardDetailPanel; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; @@ -54,6 +55,10 @@ public class VDetail implements IVDoc { lblFlipcard.setVisible(false); } + public void setGameView(final GameView gameView) { + this.pnlDetail.setGameView(gameView); + } + //========= Overridden methods /* (non-Javadoc) * @see forge.gui.framework.IVDoc#populate() diff --git a/forge-gui-mobile/src/forge/card/CardImageRenderer.java b/forge-gui-mobile/src/forge/card/CardImageRenderer.java index 11d9bfb476b..a6355e2cd2f 100644 --- a/forge-gui-mobile/src/forge/card/CardImageRenderer.java +++ b/forge-gui-mobile/src/forge/card/CardImageRenderer.java @@ -20,6 +20,7 @@ import forge.assets.TextRenderer; import forge.card.CardDetailUtil.DetailColors; import forge.card.CardRenderer.CardStackPosition; import forge.card.mana.ManaCost; +import forge.game.GameView; import forge.game.card.CardView; import forge.game.card.CardView.CardStateView; import forge.game.zone.ZoneType; @@ -328,10 +329,10 @@ public class CardImageRenderer { } } - public static void drawZoom(Graphics g, CardView card, boolean altState, float x, float y, float w, float h) { + public static void drawZoom(Graphics g, CardView card, GameView gameView, boolean altState, float x, float y, float w, float h) { final Texture image = ImageCache.getImage(card.getState(altState).getImageKey(MatchController.instance.getCurrentPlayer()), true); if (image == null) { //draw details if can't draw zoom - drawDetails(g, card, altState, x, y, w, h); + drawDetails(g, card, gameView, altState, x, y, w, h); return; } @@ -344,7 +345,7 @@ public class CardImageRenderer { CardRenderer.drawFoilEffect(g, card, x, y, w, y); } - public static void drawDetails(Graphics g, CardView card, boolean altState, float x, float y, float w, float h) { + public static void drawDetails(Graphics g, CardView card, GameView gameView, boolean altState, float x, float y, float w, float h) { updateStaticFields(w, h); float blackBorderThickness = w * BLACK_BORDER_THICKNESS_RATIO; @@ -393,7 +394,7 @@ public class CardImageRenderer { y += cardNameBoxHeight + innerBorderThickness; Color textBoxColor1 = FSkinColor.tintColor(Color.WHITE, color1, CardRenderer.TEXT_BOX_TINT); Color textBoxColor2 = color2 == null ? null : FSkinColor.tintColor(Color.WHITE, color2, CardRenderer.TEXT_BOX_TINT); - drawDetailsTextBox(g, card, state, canShow, textBoxColor1, textBoxColor2, x, y, w, textBoxHeight); + drawDetailsTextBox(g, state, gameView, canShow, textBoxColor1, textBoxColor2, x, y, w, textBoxHeight); y += textBoxHeight + innerBorderThickness; Color ptColor1 = FSkinColor.tintColor(Color.WHITE, color1, CardRenderer.PT_BOX_TINT); @@ -457,7 +458,7 @@ public class CardImageRenderer { g.drawText(CardDetailUtil.formatCardType(state, canShow), TYPE_FONT, Color.BLACK, x, y, w, h, false, HAlignment.LEFT, true); } - private static void drawDetailsTextBox(Graphics g, CardView card, CardStateView state, boolean canShow, Color color1, Color color2, float x, float y, float w, float h) { + private static void drawDetailsTextBox(Graphics g, CardStateView state, GameView gameView, boolean canShow, Color color1, Color color2, float x, float y, float w, float h) { if (color2 == null) { g.fillRect(color1, x, y, w, h); } @@ -472,7 +473,7 @@ public class CardImageRenderer { y += padY; w -= 2 * padX; h -= 2 * padY; - cardTextRenderer.drawText(g, CardDetailUtil.composeCardText(state, canShow), TEXT_FONT, Color.BLACK, x, y, w, h, y, h, true, HAlignment.LEFT, false); + cardTextRenderer.drawText(g, CardDetailUtil.composeCardText(state, gameView, canShow), TEXT_FONT, Color.BLACK, x, y, w, h, y, h, true, HAlignment.LEFT, false); } private static void drawDetailsIdAndPtBox(Graphics g, CardView card, CardStateView state, boolean canShow, Color idForeColor, Color color1, Color color2, float x, float y, float w, float h) { diff --git a/forge-gui-mobile/src/forge/card/CardZoom.java b/forge-gui-mobile/src/forge/card/CardZoom.java index 9949a2e596d..eeae77d3401 100644 --- a/forge-gui-mobile/src/forge/card/CardZoom.java +++ b/forge-gui-mobile/src/forge/card/CardZoom.java @@ -7,9 +7,11 @@ import java.util.Map.Entry; import com.badlogic.gdx.graphics.g2d.BitmapFont.HAlignment; import com.badlogic.gdx.math.Rectangle; +import forge.Forge; import forge.Graphics; import forge.ImageKeys; import forge.assets.FSkinImage; +import forge.game.GameView; import forge.game.card.CardView; import forge.item.IPaperCard; import forge.item.InventoryItem; @@ -166,6 +168,8 @@ public class CardZoom extends FOverlay { @Override public void drawOverlay(Graphics g) { + final GameView gameView = Forge.hostedMatch.getGameView(); + float w = getWidth(); float h = getHeight(); float messageHeight = FDialog.MSG_HEIGHT; @@ -181,10 +185,10 @@ public class CardZoom extends FOverlay { cardHeight = FCardPanel.ASPECT_RATIO * cardWidth; y = (h - cardHeight) / 2; if (prevCard != null) { - CardImageRenderer.drawZoom(g, prevCard, false, 0, y, cardWidth, cardHeight); + CardImageRenderer.drawZoom(g, prevCard, gameView, false, 0, y, cardWidth, cardHeight); } if (nextCard != null) { - CardImageRenderer.drawZoom(g, nextCard, false, w - cardWidth, y, cardWidth, cardHeight); + CardImageRenderer.drawZoom(g, nextCard, gameView, false, w - cardWidth, y, cardWidth, cardHeight); } cardWidth = w * 0.7f; cardHeight = FCardPanel.ASPECT_RATIO * cardWidth; @@ -197,10 +201,10 @@ public class CardZoom extends FOverlay { float x = (w - cardWidth) / 2; y = (h - cardHeight) / 2; if (zoomMode) { - CardImageRenderer.drawZoom(g, currentCard, showAltState, x, y, cardWidth, cardHeight); + CardImageRenderer.drawZoom(g, currentCard, gameView, showAltState, x, y, cardWidth, cardHeight); } else { - CardImageRenderer.drawDetails(g, currentCard, showAltState, x, y, cardWidth, cardHeight); + CardImageRenderer.drawDetails(g, currentCard, gameView, showAltState, x, y, cardWidth, cardHeight); } if (flipIconBounds != null) { diff --git a/forge-gui/src/main/java/forge/card/CardDetailUtil.java b/forge-gui/src/main/java/forge/card/CardDetailUtil.java index 5be0a8521f0..db4e07426b8 100644 --- a/forge-gui/src/main/java/forge/card/CardDetailUtil.java +++ b/forge-gui/src/main/java/forge/card/CardDetailUtil.java @@ -10,6 +10,7 @@ import org.apache.commons.lang3.StringUtils; import com.google.common.collect.Sets; +import forge.game.GameView; import forge.game.card.CardUtil; import forge.game.card.CardView; import forge.game.card.CardView.CardStateView; @@ -201,7 +202,7 @@ public class CardDetailUtil { return id.isEmpty() ? id : "[" + id + "]"; } - public static String composeCardText(final CardStateView state, final boolean canShow) { + public static String composeCardText(final CardStateView state, final GameView gameView, final boolean canShow) { if (!canShow) { return ""; } final CardView card = state.getCard(); @@ -479,10 +480,7 @@ public class CardDetailUtil { } //show current storm count for storm cards - // TODO add Storm - /* if (state.hasStorm()) { - GameView gameView = HostedMatch.getGameView(); if (gameView != null) { if (area.length() != 0) { area.append("\n\n"); @@ -490,7 +488,6 @@ public class CardDetailUtil { area.append("Current Storm Count: " + gameView.getStormCount()); } } - */ return area.toString(); } } diff --git a/forge-gui/src/main/java/forge/interfaces/IUpdateable.java b/forge-gui/src/main/java/forge/interfaces/IUpdateable.java index fdce8345bf5..0685a64a988 100644 --- a/forge-gui/src/main/java/forge/interfaces/IUpdateable.java +++ b/forge-gui/src/main/java/forge/interfaces/IUpdateable.java @@ -1,5 +1,5 @@ package forge.interfaces; public interface IUpdateable { - void update(); + void update(boolean fullUpdate); } diff --git a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java index 3ddd42074b0..4540333a0c2 100644 --- a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java +++ b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java @@ -158,40 +158,31 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { } /** Concede game, bring up WinLose UI. */ - public void concede() { - final String userPrompt = - "This will end the current game and you will not be able to resume.\n\n" + - "Concede anyway?"; - if (hasLocalPlayers() && showConfirmDialog(userPrompt, "Concede Game?", "Concede", "Cancel")) { - for (final IGameController c : getGameControllers()) { - // Concede each player on this Gui - c.concede(); - } - /* - if (humanCount == 0) { // no human? then all players surrender! - for (Player p : game.getPlayers()) { - p.concede(); + public boolean concede() { + if (gameView.isGameOver()) { + return true; + } + if (hasLocalPlayers()) { + if (showConfirmDialog("This will concede the current game and you will lose.\n\nConcede anyway?", "Concede Game?", "Concede", "Cancel")) { + for (final IGameController c : getGameControllers()) { + // Concede each player on this Gui + c.concede(); } } - else { - getCurrentPlayer().concede(); + if (gameView.isGameOver()) { + // Don't immediately close, wait for win/lose screen + return false; + } else { + return true; } - - Player priorityPlayer = game.getPhaseHandler().getPriorityPlayer(); - boolean humanHasPriority = priorityPlayer == null || priorityPlayer.getLobbyPlayer() instanceof LobbyPlayerHuman; - - if (humanCount > 0 && humanHasPriority) { - game.getAction().checkGameOverCondition(); + } else { + if (showConfirmDialog("This will close this game and you will not be able to resume watching it.\n\nClose anyway?", "Close Game?", "Close", "Cancel")) { + //if (playbackControl != null) { + //playbackControl.onGameStopRequested(); + //} + return true; } - else { - game.isGameOver(); // this is synchronized method - it's used to make Game-0 thread see changes made here - onGameOver(false); //release any waiting input, effectively passing priority - } - - if (playbackControl != null) { - playbackControl.onGameStopRequested(); - } - */ + return false; } } diff --git a/forge-gui/src/main/java/forge/match/GameLobby.java b/forge-gui/src/main/java/forge/match/GameLobby.java index f4926748426..8e03380d610 100644 --- a/forge-gui/src/main/java/forge/match/GameLobby.java +++ b/forge-gui/src/main/java/forge/match/GameLobby.java @@ -65,7 +65,7 @@ public abstract class GameLobby { } public void setData(final GameLobbyData data) { this.data = data; - updateView(); + updateView(true); } public GameType getGameType() { @@ -73,7 +73,6 @@ public abstract class GameLobby { } public void setGameType(final GameType type) { data.currentGameMode = type; - updateView(); } public boolean hasVariant(final GameType variant) { @@ -99,7 +98,8 @@ public abstract class GameLobby { final boolean triesToChangeArchenemy = event.getArchenemy() != null; final boolean archenemyRemoved = triesToChangeArchenemy && !event.getArchenemy().booleanValue(); final boolean hasArchenemyChanged = triesToChangeArchenemy && slot.isArchenemy() != event.getArchenemy().booleanValue(); - slot.apply(event); + + final boolean changed = slot.apply(event) || hasArchenemyChanged; // Change archenemy teams if (hasVariant(GameType.Archenemy) && hasArchenemyChanged) { @@ -116,7 +116,10 @@ public abstract class GameLobby { otherSlot.setIsArchenemy(becomesArchenemy); } } - updateView(); + + if (changed) { + updateView(false); + } } public IGameController getController(final int index) { @@ -130,7 +133,8 @@ public abstract class GameLobby { public abstract boolean mayEdit(final int index); public abstract boolean mayControl(final int index); public abstract boolean mayRemove(final int index); - public abstract IGuiGame getGui(final int index); + protected abstract IGuiGame getGui(final int index); + protected abstract void gameStarted(); public void addSlot() { final int newIndex = getNumberOfSlots(); @@ -151,7 +155,7 @@ public abstract class GameLobby { slot.setIsArchenemy(true); lastArchenemy = 0; } - updateView(); + updateView(false); } private String randomName() { final List names = Lists.newArrayListWithCapacity(MAX_PLAYERS); @@ -189,7 +193,7 @@ public abstract class GameLobby { lastArchenemy--; } data.slots.remove(index); - updateView(); + updateView(false); } public void applyVariant(final GameType variant) { @@ -217,12 +221,13 @@ public abstract class GameLobby { break; case MomirBasic: data.appliedVariants.remove(GameType.Commander); + data.appliedVariants.remove(GameType.TinyLeaders); data.appliedVariants.remove(GameType.Vanguard); break; default: break; } - updateView(); + updateView(true); } public void removeVariant(final GameType variant) { @@ -230,7 +235,16 @@ public abstract class GameLobby { if (data.appliedVariants.isEmpty()) { data.appliedVariants.add(GameType.Constructed); } - updateView(); + if (variant == data.currentGameMode) { + if (hasVariant(GameType.Commander)) { + data.currentGameMode = GameType.Commander; + } else if (hasVariant(GameType.TinyLeaders)) { + data.currentGameMode = GameType.TinyLeaders; + } else { + data.currentGameMode = GameType.Constructed; + } + } + updateView(true); } private boolean isEnoughTeams() { @@ -247,9 +261,9 @@ public abstract class GameLobby { return false; } - protected final void updateView() { + protected final void updateView(final boolean fullUpdate) { if (listener != null) { - listener.update(); + listener.update(fullUpdate); } } @@ -422,6 +436,8 @@ public abstract class GameLobby { gameControllers.put(slot, (IGameController) p.getController()); } } + + gameStarted(); } public final static class GameLobbyData implements Serializable { diff --git a/forge-gui/src/main/java/forge/match/LobbySlot.java b/forge-gui/src/main/java/forge/match/LobbySlot.java index 8f43c6f73d3..c3707d6ae26 100644 --- a/forge-gui/src/main/java/forge/match/LobbySlot.java +++ b/forge-gui/src/main/java/forge/match/LobbySlot.java @@ -32,33 +32,42 @@ public final class LobbySlot implements Serializable { this.setAiOptions(aiOptions); } - void apply(final UpdateLobbyPlayerEvent data) { + boolean apply(final UpdateLobbyPlayerEvent data) { + boolean changed = false; if (data.getType() != null) { setType(data.getType()); + changed = true; } if (data.getName() != null) { setName(data.getName()); + changed = true; } if (data.getAvatarIndex() != -1) { setAvatarIndex(data.getAvatarIndex()); + changed = true; } if (data.getTeam() != -1) { setTeam(data.getTeam()); + changed = true; } if (data.getArchenemy() != null) { setIsArchenemy(data.getArchenemy().booleanValue()); + changed = true; } if (data.getReady() != null) { setIsReady(data.getReady().booleanValue()); + changed = true; } if (data.getAiOptions() != null) { setAiOptions(data.getAiOptions()); + changed = true; } if (data.getDeck() != null) { setDeck(data.getDeck()); } else if (getDeck() != null && data.getSection() != null && data.getCards() != null) { getDeck().putSection(data.getSection(), data.getCards()); } + return changed; } public LobbySlotType getType() { diff --git a/forge-gui/src/main/java/forge/match/LocalLobby.java b/forge-gui/src/main/java/forge/match/LocalLobby.java index edb982228bb..56740484aba 100644 --- a/forge-gui/src/main/java/forge/match/LocalLobby.java +++ b/forge-gui/src/main/java/forge/match/LocalLobby.java @@ -9,6 +9,7 @@ import forge.net.game.LobbySlotType; public final class LocalLobby extends GameLobby { + private IGuiGame gui = null; public LocalLobby() { super(false); @@ -38,7 +39,14 @@ public final class LocalLobby extends GameLobby { return index >= 2; } - @Override public IGuiGame getGui(final int index) { - return GuiBase.getInterface().getNewGuiGame(); + @Override protected IGuiGame getGui(final int index) { + if (gui == null) { + gui = GuiBase.getInterface().getNewGuiGame(); + } + return gui; + } + + @Override protected void gameStarted() { + gui = null; } } diff --git a/forge-gui/src/main/java/forge/net/ClientGameLobby.java b/forge-gui/src/main/java/forge/net/ClientGameLobby.java index 31a06afc063..fbc7fe3dab9 100644 --- a/forge-gui/src/main/java/forge/net/ClientGameLobby.java +++ b/forge-gui/src/main/java/forge/net/ClientGameLobby.java @@ -30,7 +30,10 @@ public final class ClientGameLobby extends GameLobby { return false; } - @Override public IGuiGame getGui(final int index) { + @Override protected IGuiGame getGui(final int index) { return null; } + + @Override protected void gameStarted() { + } } diff --git a/forge-gui/src/main/java/forge/net/ServerGameLobby.java b/forge-gui/src/main/java/forge/net/ServerGameLobby.java index aed7320aea6..f5541ae4388 100644 --- a/forge-gui/src/main/java/forge/net/ServerGameLobby.java +++ b/forge-gui/src/main/java/forge/net/ServerGameLobby.java @@ -33,13 +33,13 @@ public final class ServerGameLobby extends GameLobby { slot.setType(LobbySlotType.REMOTE); slot.setName(name); slot.setAvatarIndex(avatarIndex); - updateView(); + updateView(false); } public void disconnectPlayer(final int index) { final LobbySlot slot = getSlot(index); slot.setType(LobbySlotType.OPEN); slot.setName(StringUtils.EMPTY); - updateView(); + updateView(false); } @Override public boolean hasControl() { @@ -59,7 +59,11 @@ public final class ServerGameLobby extends GameLobby { return true; } - @Override public IGuiGame getGui(final int index) { + @Override protected IGuiGame getGui(final int index) { return FServerManager.getInstance().getGui(index); } + + @Override + protected void gameStarted() { + } }