From 3cdbf3eb679c337a42600b3b38d467da77d79b6b Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Tue, 21 Apr 2020 17:50:25 +0800 Subject: [PATCH 1/4] Update FControlGameEventHandler some method don't exist on mobile port and are specifically for desktop so let those routine run for its specific platform --- .../control/FControlGameEventHandler.java | 69 ++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java index 7444303276d..fca98ffe702 100644 --- a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java +++ b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java @@ -239,17 +239,20 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public Void visit(final GameEventSpellAbilityCast event) { - needStackUpdate = true; - processEvent(); - - final Runnable notifyStackAddition = new Runnable() { - @Override - public void run() { - matchController.notifyStackAddition(event); - } - }; - GuiBase.getInterface().invokeInEdtLater(notifyStackAddition); + needStackUpdate = true; + if(GuiBase.getInterface().isLibgdxPort()) { + return processEvent(); //mobile port don't have notify stack addition like the desktop + } else { + processEvent(); + final Runnable notifyStackAddition = new Runnable() { + @Override + public void run() { + matchController.notifyStackAddition(event); + } + }; + GuiBase.getInterface().invokeInEdtLater(notifyStackAddition); + } return null; } @@ -262,16 +265,19 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public Void visit(final GameEventSpellRemovedFromStack event) { needStackUpdate = true; - processEvent(); - - final Runnable notifyStackAddition = new Runnable() { - @Override - public void run() { - matchController.notifyStackRemoval(event); - } - }; - GuiBase.getInterface().invokeInEdtLater(notifyStackAddition); - + if(GuiBase.getInterface().isLibgdxPort()) { + return processEvent(); //mobile port don't have notify stack addition like the desktop + } else { + processEvent(); + + final Runnable notifyStackAddition = new Runnable() { + @Override + public void run() { + matchController.notifyStackRemoval(event); + } + }; + GuiBase.getInterface().invokeInEdtLater(notifyStackAddition); + } return null; } @@ -357,14 +363,12 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public Void visit(final GameEventCardChangeZone event) { - if(event.to.getZoneType() == ZoneType.Battlefield) - refreshFieldUpdate = true; - //pfps the change to the zones have already been performed with add and remove calls - // this is only for playing a sound - // updateZone(event.from); - //return updateZone(event.to); - return processEvent(); - + if(GuiBase.getInterface().isLibgdxPort()) { + updateZone(event.from); + return updateZone(event.to); + } else { + return processEvent(); + } } @Override @@ -399,10 +403,11 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public Void visit(final GameEventShuffle event) { - //pfps the change to the library has already been performed by a setCards call - // this is only for playing a sound - // return updateZone(event.player.getZone(ZoneType.Library)); - return processEvent(); + if (GuiBase.getInterface().isLibgdxPort()) { + return updateZone(event.player.getZone(ZoneType.Library)); + } else { + return processEvent(); + } } @Override From 8acb143fea29776cf0ad682714d1d981849c31d2 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Tue, 21 Apr 2020 17:52:05 +0800 Subject: [PATCH 2/4] Improve Online Lobby (Mobile port) --- .../forge/game/player/RegisteredPlayer.java | 4 +- .../src/forge/screens/LaunchScreen.java | 2 +- .../screens/constructed/LobbyScreen.java | 95 ++++++++++- .../screens/constructed/PlayerPanel.java | 151 ++++++++++++++++-- .../forge/screens/match/MatchController.java | 8 + .../src/forge/screens/match/MatchScreen.java | 52 +++--- .../src/forge/screens/match/views/VStack.java | 9 ++ .../src/main/java/forge/match/LobbySlot.java | 30 ++++ .../net/event/UpdateLobbyPlayerEvent.java | 32 +++- 9 files changed, 342 insertions(+), 41 deletions(-) diff --git a/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java b/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java index 094b94ad796..11606355bcd 100644 --- a/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java +++ b/forge-game/src/main/java/forge/game/player/RegisteredPlayer.java @@ -135,8 +135,8 @@ public class RegisteredPlayer { start.planes = planes; } if (appliedVariants.contains(GameType.Vanguard) || appliedVariants.contains(GameType.MomirBasic) - || appliedVariants.contains(GameType.MoJhoSto)) { - start.setVanguardAvatars(vanguardAvatar.toFlatList()); + || appliedVariants.contains(GameType.MoJhoSto)) { //fix the crash, if somehow the avatar is null, get it directly from the deck + start.setVanguardAvatars(vanguardAvatar == null ? deck.get(DeckSection.Avatar).toFlatList():vanguardAvatar.toFlatList()); } return start; } diff --git a/forge-gui-mobile/src/forge/screens/LaunchScreen.java b/forge-gui-mobile/src/forge/screens/LaunchScreen.java index 6732e89fb74..0f9c8452392 100644 --- a/forge-gui-mobile/src/forge/screens/LaunchScreen.java +++ b/forge-gui-mobile/src/forge/screens/LaunchScreen.java @@ -11,7 +11,7 @@ import forge.toolbox.FOptionPane; import forge.util.Utils; public abstract class LaunchScreen extends FScreen { - private static final float MAX_START_BUTTON_HEIGHT = 2 * Utils.AVG_FINGER_HEIGHT; + private static final float MAX_START_BUTTON_HEIGHT = 1.75f * Utils.AVG_FINGER_HEIGHT; private float START_BUTTON_RATIO = 0.f; private static final float PADDING = FOptionPane.PADDING; diff --git a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java index 5d6fd28f4d6..529df5cde9e 100644 --- a/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java +++ b/forge-gui-mobile/src/forge/screens/constructed/LobbyScreen.java @@ -14,6 +14,8 @@ import forge.deck.FDeckChooser; import forge.net.server.FServerManager; import forge.util.Localizer; +import forge.util.MyRandom; +import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; import com.badlogic.gdx.Gdx; @@ -281,7 +283,10 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { @Override protected void startMatch() { for (int i = 0; i < getNumPlayers(); i++) { - updateDeck(i);//TODO: Investigate why AI names cannot be overriden? + if(!lobby.isAllowNetworking()) //on networkplay, update deck will be handled differently + updateDeck(i); + + //TODO: Investigate why AI names cannot be overriden? updateName(i, getPlayerName(i)); } FThreads.invokeInBackgroundThread(new Runnable() { //must call startGame in background thread in case there are alerts @@ -326,6 +331,15 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { String[] avatarPrefs = prefs.getPref(FPref.UI_AVATARS).split(","); for (int i = 0; i < avatarPrefs.length; i++) { int avatarIndex = Integer.parseInt(avatarPrefs[i]); + if (avatarIndex < 0) { + int random = 0; + List usedAvatars = getUsedAvatars(); + do { + random = MyRandom.getRandom().nextInt(GuiBase.getInterface().getAvatarCount()); + } while (usedAvatars.contains(random)); + + avatarIndex = random; + } playerPanels.get(i).setAvatarIndex(avatarIndex); } @@ -333,6 +347,15 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { String[] sleevePrefs = prefs.getPref(FPref.UI_SLEEVES).split(","); for (int i = 0; i < sleevePrefs.length; i++) { int sleeveIndex = Integer.parseInt(sleevePrefs[i]); + if (sleeveIndex < 0) { + int random = 0; + List usedSleeves = getUsedSleeves(); + do { + random = MyRandom.getRandom().nextInt(GuiBase.getInterface().getSleevesCount()); + } while (usedSleeves.contains(random)); + + sleeveIndex = random; + } playerPanels.get(i).setSleeveIndex(sleeveIndex); } @@ -557,7 +580,7 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { } if (i == 0) { - slot.setIsDevMode(prefs.getPrefBoolean(FPref.DEV_MODE_ENABLED)); + slot.setIsDevMode(slot.isDevMode()); } final LobbySlotType type = slot.getType(); @@ -582,8 +605,21 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { panel.setMayEdit(lobby.mayEdit(i)); panel.setMayControl(lobby.mayControl(i)); panel.setMayRemove(lobby.mayRemove(i)); + if(allowNetworking) { + if(slot.getDeckName() != null) + panel.setDeckSelectorButtonText(slot.getDeckName()); - if (fullUpdate && (type == LobbySlotType.LOCAL || type == LobbySlotType.AI)) { + if(slot.getPlanarDeckName()!= null) + panel.setPlanarDeckName(slot.getPlanarDeckName()); + + if(slot.getSchemeDeckName()!= null) + panel.setSchemeDeckName(slot.getSchemeDeckName()); + + if(slot.getAvatarVanguard()!= null) + panel.setVanguarAvatarName(slot.getAvatarVanguard()); + } + + if (fullUpdate && (type == LobbySlotType.LOCAL || type == LobbySlotType.AI) && !allowNetworking) { updateDeck(i); } if (isNewPanel) { @@ -606,35 +642,46 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { if (playerIndex >= getNumPlayers()) { return; } PlayerPanel playerPanel = playerPanels.get(playerIndex); + String deckName = ""; Deck deck; if (hasVariant(GameType.Commander)) { deck = playerPanel.getCommanderDeck(); if (deck != null) { playerPanel.getCommanderDeckChooser().saveState(); + deckName = localizer.getMessage("lblCommanderDeck") + ": " + + playerPanel.getCommanderDeckChooser().getDeck().getName(); } } else if (hasVariant(GameType.Oathbreaker)) { deck = playerPanel.getOathbreakerDeck(); if (deck != null) { playerPanel.getOathbreakerDeckChooser().saveState(); + deckName = localizer.getMessage("lblOathbreakerDeck") + ": " + + playerPanel.getOathbreakerDeckChooser().getDeck().getName(); } } else if (hasVariant(GameType.TinyLeaders)) { deck = playerPanel.getTinyLeadersDeck(); if (deck != null) { playerPanel.getTinyLeadersDeckChooser().saveState(); + deckName = localizer.getMessage("lblTinyLeadersDeck") + ": " + + playerPanel.getTinyLeadersDeckChooser().getDeck().getName(); } } else if (hasVariant(GameType.Brawl)) { deck = playerPanel.getBrawlDeck(); if (deck != null) { playerPanel.getBrawlDeckChooser().saveState(); + deckName = localizer.getMessage("lblBrawlDeck") + ": " + + playerPanel.getBrawlDeckChooser().getDeck().getName(); } }else { deck = playerPanel.getDeck(); if (deck != null) { playerPanel.getDeckChooser().saveState(); + deckName = playerPanel.getDeckChooser().getSelectedDeckType().toString() + ": " + + playerPanel.getDeckChooser().getDeck().getName(); } } @@ -642,18 +689,31 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { return; } + //playerPanel.setDeckSelectorButtonText(deckName); + Deck playerDeck = deck; + String VanguardAvatar = null; + String SchemeDeckName= null; + String PlanarDeckname= null; if (hasVariant(GameType.Archenemy) || hasVariant(GameType.ArchenemyRumble)) { if (playerDeck == deck) { playerDeck = new Deck(deck); //create copy that can be modified } playerDeck.putSection(DeckSection.Schemes, playerPanel.getSchemeDeck().get(DeckSection.Schemes)); + if (!playerPanel.getSchemeDeck().getName().isEmpty()) { + SchemeDeckName = localizer.getMessage("lblSchemeDeck") + ": " + playerPanel.getSchemeDeck().getName(); + playerPanel.setSchemeDeckName(SchemeDeckName); + } } if (hasVariant(GameType.Planechase)) { if (playerDeck == deck) { playerDeck = new Deck(deck); //create copy that can be modified } playerDeck.putSection(DeckSection.Planes, playerPanel.getPlanarDeck().get(DeckSection.Planes)); + if(!playerPanel.getPlanarDeck().getName().isEmpty()) { + PlanarDeckname = localizer.getMessage("lblPlanarDeck") + ": " + playerPanel.getPlanarDeck().getName(); + playerPanel.setPlanarDeckName(PlanarDeckname); + } } if (hasVariant(GameType.Vanguard)) { if (playerDeck == deck) { @@ -662,11 +722,14 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { CardPool avatarPool = new CardPool(); avatarPool.add(playerPanel.getVanguardAvatar()); playerDeck.putSection(DeckSection.Avatar, avatarPool); + VanguardAvatar = localizer.getMessage("lblVanguard") + ": " + playerPanel.getVanguardAvatar().getName(); + playerPanel.setVanguarAvatarName(VanguardAvatar); } decks[playerIndex] = playerDeck; if (playerChangeListener != null) { playerChangeListener.update(playerIndex, UpdateLobbyPlayerEvent.deckUpdate(playerDeck)); + playerChangeListener.update(playerIndex, UpdateLobbyPlayerEvent.setDeckSchemePlaneVanguard(TextUtil.fastReplace(deckName," Generated Deck", ""), SchemeDeckName, PlanarDeckname, VanguardAvatar)); } } @@ -689,6 +752,11 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { } void setReady(final int index, final boolean ready) { + if (lobby.isAllowNetworking()){ + updateDeck(index); + fireReady(index, ready); + return; + } if (ready) { updateDeck(index); if (decks[index] == null) { @@ -697,7 +765,6 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { return; } } - firePlayerChangeListener(index); } void setDevMode(final int index) { @@ -714,7 +781,27 @@ public abstract class LobbyScreen extends LaunchScreen implements ILobbyView { playerChangeListener.update(index, getSlot(index)); } } + void fireReady(final int index, boolean ready){ + playerPanels.get(index).setIsReady(ready); + if (playerChangeListener != null) { + playerChangeListener.update(index, UpdateLobbyPlayerEvent.isReadyUpdate(ready)); + } + } + void updatemyTeam(int index, int team) { + if (playerChangeListener != null) { + playerChangeListener.update(index, UpdateLobbyPlayerEvent.teamUpdate(team)); + } + } + void updateMyDeck(int index) { + /* updateMyDeck is called via button handler when the user set their deck on network play*/ + //safety check + if(playerPanels.size() < 2) + return; + + updateDeck(index); + //fireReady(index, playerPanels.get(index).isReady()); + } public void removePlayer(final int index) { lobby.removeSlot(index); } diff --git a/forge-gui-mobile/src/forge/screens/constructed/PlayerPanel.java b/forge-gui-mobile/src/forge/screens/constructed/PlayerPanel.java index 5f0ba1e9be1..10347f465f7 100644 --- a/forge-gui-mobile/src/forge/screens/constructed/PlayerPanel.java +++ b/forge-gui-mobile/src/forge/screens/constructed/PlayerPanel.java @@ -112,9 +112,12 @@ public class PlayerPanel extends FContainer { deckChooser = new FDeckChooser(GameType.Constructed, isAi, new FEventHandler() { @Override public void handleEvent(FEvent e) { - btnDeck.setEnabled(true); + btnDeck.setEnabled(mayEdit); btnDeck.setText(deckChooser.getSelectedDeckType().toString() + ": " + Lang.joinHomogenous(((DeckManager)e.getSource()).getSelectedItems(), DeckProxy.FN_GET_NAME)); + if (allowNetworking && btnDeck.isEnabled() && humanAiSwitch.isToggled()) { //if its ready but changed the deck, update it + screen.updateMyDeck(index); + } } }); lstCommanderDecks = new FDeckChooser(GameType.Commander, isAi, new FEventHandler() { @@ -123,6 +126,9 @@ public class PlayerPanel extends FContainer { if( ((DeckManager)e.getSource()).getSelectedItem() != null) { btnCommanderDeck.setText(localizer.getMessage("lblCommanderDeck") + ": " + ((DeckManager) e.getSource()).getSelectedItem().getName()); lstCommanderDecks.saveState(); + if (allowNetworking && btnCommanderDeck.isEnabled() && humanAiSwitch.isToggled()) { + screen.updateMyDeck(index); + } }else{ btnCommanderDeck.setText(localizer.getMessage("lblCommanderDeck")); } @@ -134,6 +140,9 @@ public class PlayerPanel extends FContainer { if( ((DeckManager)e.getSource()).getSelectedItem() != null) { btnOathbreakDeck.setText(localizer.getMessage("lblOathbreakerDeck") + ": " + ((DeckManager) e.getSource()).getSelectedItem().getName()); lstOathbreakerDecks.saveState(); + if (allowNetworking && btnOathbreakDeck.isEnabled() && humanAiSwitch.isToggled()) { + screen.updateMyDeck(index); + } }else{ btnOathbreakDeck.setText(localizer.getMessage("lblOathbreakerDeck")); } @@ -145,6 +154,9 @@ public class PlayerPanel extends FContainer { if( ((DeckManager)e.getSource()).getSelectedItem() != null) { btnTinyLeadersDeck.setText(localizer.getMessage("lblTinyLeadersDeck") + ": " + ((DeckManager) e.getSource()).getSelectedItem().getName()); lstTinyLeadersDecks.saveState(); + if (allowNetworking && btnTinyLeadersDeck.isEnabled() && humanAiSwitch.isToggled()) { + screen.updateMyDeck(index); + } }else{ btnTinyLeadersDeck.setText(localizer.getMessage("lblTinyLeadersDeck")); } @@ -156,6 +168,9 @@ public class PlayerPanel extends FContainer { if( ((DeckManager)e.getSource()).getSelectedItem() != null) { btnBrawlDeck.setText(localizer.getMessage("lblBrawlDeck") + ": " + ((DeckManager) e.getSource()).getSelectedItem().getName()); lstBrawlDecks.saveState(); + if (allowNetworking && btnBrawlDeck.isEnabled() && humanAiSwitch.isToggled()) { + screen.updateMyDeck(index); + } }else{ btnBrawlDeck.setText(localizer.getMessage("lblBrawlDeck")); } @@ -166,6 +181,9 @@ public class PlayerPanel extends FContainer { public void handleEvent(FEvent e) { if( ((DeckManager)e.getSource()).getSelectedItem() != null){ btnSchemeDeck.setText(localizer.getMessage("lblSchemeDeck") + ": " + ((DeckManager)e.getSource()).getSelectedItem().getName()); + if (allowNetworking && btnSchemeDeck.isEnabled() && humanAiSwitch.isToggled()) { + screen.updateMyDeck(index); + } }else{ btnSchemeDeck.setText(localizer.getMessage("lblSchemeDeck")); } @@ -176,6 +194,9 @@ public class PlayerPanel extends FContainer { public void handleEvent(FEvent e) { if( ((DeckManager)e.getSource()).getSelectedItem() != null){ btnPlanarDeck.setText(localizer.getMessage("lblPlanarDeck") + ": " + ((DeckManager)e.getSource()).getSelectedItem().getName()); + if (allowNetworking && btnPlanarDeck.isEnabled() && humanAiSwitch.isToggled()) { + screen.updateMyDeck(index); + } }else{ btnPlanarDeck.setText(localizer.getMessage("lblPlanarDeck")); } @@ -185,6 +206,9 @@ public class PlayerPanel extends FContainer { @Override public void handleEvent(FEvent e) { btnVanguardAvatar.setText(localizer.getMessage("lblVanguard") + ": " + ((CardManager)e.getSource()).getSelectedItem().getName()); + if (allowNetworking && btnVanguardAvatar.isEnabled() && humanAiSwitch.isToggled()) { + screen.updateMyDeck(index); + } } }); @@ -512,7 +536,32 @@ public class PlayerPanel extends FContainer { }; public void setDeckSelectorButtonText(String text) { - btnDeck.setText(text); + if (btnDeck.isVisible()) + btnDeck.setText(text); + + if (btnCommanderDeck.isVisible()) + btnCommanderDeck.setText(text); + + if (btnOathbreakDeck.isVisible()) + btnOathbreakDeck.setText(text); + + if (btnTinyLeadersDeck.isVisible()) + btnTinyLeadersDeck.setText(text); + + if (btnBrawlDeck.isVisible()) + btnBrawlDeck.setText(text); + } + + public void setVanguarAvatarName(String text) { + btnVanguardAvatar.setText(text); + } + + public void setSchemeDeckName(String text) { + btnSchemeDeck.setText(text); + } + + public void setPlanarDeckName(String text) { + btnPlanarDeck.setText(text); } public void updateVariantControlsVisibility() { @@ -525,6 +574,7 @@ public class PlayerPanel extends FContainer { boolean isArchenemyApplied = false; boolean archenemyVisiblity = false; boolean isDeckBuildingAllowed = mayEdit; + boolean replacedbasicdeck = false; for (GameType variant : screen.getLobby().getAppliedVariants()) { switch (variant) { @@ -540,18 +590,22 @@ public class PlayerPanel extends FContainer { case Commander: isCommanderApplied = true; isDeckBuildingAllowed = false; //Commander deck replaces basic deck, so hide that + replacedbasicdeck = true; break; case Oathbreaker: isOathbreakerApplied = true; isDeckBuildingAllowed = false; //Oathbreaker deck replaces basic deck, so hide that + replacedbasicdeck = true; break; case TinyLeaders: isTinyLeadersApplied = true; isDeckBuildingAllowed = false; //Tiny Leaders deck replaces basic deck, so hide that + replacedbasicdeck = true; break; case Brawl: isBrawlApplied = true; isDeckBuildingAllowed = false; //Tiny Leaders deck replaces basic deck, so hide that + replacedbasicdeck = true; break; case Planechase: isPlanechaseApplied = true; @@ -562,24 +616,85 @@ public class PlayerPanel extends FContainer { default: if (variant.isAutoGenerated()) { isDeckBuildingAllowed = false; + replacedbasicdeck = true; } break; } } - btnDeck.setVisible(isDeckBuildingAllowed); - btnCommanderDeck.setVisible(isCommanderApplied && mayEdit); - btnOathbreakDeck.setVisible(isOathbreakerApplied && mayEdit); - btnTinyLeadersDeck.setVisible(isTinyLeadersApplied && mayEdit); - btnBrawlDeck.setVisible(isBrawlApplied && mayEdit); + if(allowNetworking) { + if (replacedbasicdeck) { + btnDeck.setVisible(false); + } else { + btnDeck.setVisible(true); + btnDeck.setEnabled(mayEdit); + } + if (isCommanderApplied) { + btnCommanderDeck.setVisible(true); + btnCommanderDeck.setEnabled(mayEdit); + } else { + btnCommanderDeck.setVisible(false); + } + if (isOathbreakerApplied) { + btnOathbreakDeck.setVisible(true); + btnOathbreakDeck.setEnabled(mayEdit); + } else { + btnOathbreakDeck.setVisible(false); + } + if (isTinyLeadersApplied) { + btnTinyLeadersDeck.setVisible(true); + btnTinyLeadersDeck.setEnabled(mayEdit); + } else { + btnTinyLeadersDeck.setVisible(false); + } + if (isBrawlApplied) { + btnBrawlDeck.setVisible(true); + btnBrawlDeck.setEnabled(mayEdit); + } else { + btnBrawlDeck.setVisible(false); + } + if (archenemyVisiblity) { + btnSchemeDeck.setVisible(true); + btnSchemeDeck.setEnabled(mayEdit); + } else { + btnSchemeDeck.setVisible(false); + } + if (!isArchenemyApplied) { + cbTeam.setVisible(true); + cbTeam.setEnabled(mayEdit); + cbArchenemyTeam.setVisible(false); + } else { + cbTeam.setVisible(false); + cbArchenemyTeam.setVisible(true); + cbArchenemyTeam.setEnabled(mayEdit); + } + if (isPlanechaseApplied) { + btnPlanarDeck.setVisible(true); + btnPlanarDeck.setEnabled(mayEdit); + } else { + btnPlanarDeck.setVisible(false); + } + if (isVanguardApplied) { + btnVanguardAvatar.setVisible(true); + btnVanguardAvatar.setEnabled(mayEdit); + } else { + btnVanguardAvatar.setVisible(false); + } + } else { + btnDeck.setVisible(isDeckBuildingAllowed); + btnCommanderDeck.setVisible(isCommanderApplied && mayEdit); + btnOathbreakDeck.setVisible(isOathbreakerApplied && mayEdit); + btnTinyLeadersDeck.setVisible(isTinyLeadersApplied && mayEdit); + btnBrawlDeck.setVisible(isBrawlApplied && mayEdit); - btnSchemeDeck.setVisible(archenemyVisiblity && mayEdit); + btnSchemeDeck.setVisible(archenemyVisiblity && mayEdit); - cbTeam.setVisible(!isArchenemyApplied); - cbArchenemyTeam.setVisible(isArchenemyApplied); + cbTeam.setVisible(!isArchenemyApplied); + cbArchenemyTeam.setVisible(isArchenemyApplied); - btnPlanarDeck.setVisible(isPlanechaseApplied && mayEdit); - btnVanguardAvatar.setVisible(isVanguardApplied && mayEdit); + btnPlanarDeck.setVisible(isPlanechaseApplied && mayEdit); + btnVanguardAvatar.setVisible(isVanguardApplied && mayEdit); + } } public boolean isNetworkHost() { @@ -626,6 +741,8 @@ public class PlayerPanel extends FContainer { pp.toggleIsPlayerArchenemy(); } } + } else { + screen.updatemyTeam(index, getTeam()); } } }; @@ -823,6 +940,16 @@ public class PlayerPanel extends FContainer { if (devModeSwitch != null) { devModeSwitch.setEnabled(mayEdit); } + if(allowNetworking) { + btnDeck.setEnabled(mayEdit); + btnCommanderDeck.setEnabled(mayEdit); + btnOathbreakDeck.setEnabled(mayEdit); + btnTinyLeadersDeck.setEnabled(mayEdit); + btnBrawlDeck.setEnabled(mayEdit); + btnSchemeDeck.setEnabled(mayEdit); + btnPlanarDeck.setEnabled(mayEdit); + cbArchenemyTeam.setEnabled(mayEdit); + } updateVariantControlsVisibility(); //if panel has height already, ensure height updated to account for button visibility changes diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index 3d6762b6c07..dd9dc99c313 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -146,6 +146,7 @@ public class MatchController extends AbstractGuiGame { } } view = new MatchScreen(playerPanels); + view.resetFields(); if (noHumans) { //add special object that pauses game if screen touched @@ -215,6 +216,13 @@ public class MatchController extends AbstractGuiGame { if (lbl != null) { lbl.setActive(true); } + if(GuiBase.isNetworkplay()) + checkStack(); + } + + + public void checkStack() { + view.getStack().checkEmptyStack(); } @Override diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index 82479ebb60c..b936f316255 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -481,6 +481,20 @@ public class MatchScreen extends FScreen { } } + public void resetFields() { + for (VPlayerPanel playerPanel : getPlayerPanels().values()) { + for (CardAreaPanel p : playerPanel.getField().getCardPanels()){ + p.resetForNewGame(); + p.reset(); + } + playerPanel.getZoneTab(ZoneType.Hand).getDisplayArea().clear(); + playerPanel.getZoneTab(ZoneType.Library).getDisplayArea().clear(); + playerPanel.getZoneTab(ZoneType.Graveyard).getDisplayArea().clear(); + playerPanel.getZoneTab(ZoneType.Exile).getDisplayArea().clear(); + + } + } + public void updateZones(final Iterable zonesToUpdate) { for (final PlayerZoneUpdate update : zonesToUpdate) { final PlayerView owner = update.getPlayer(); @@ -566,6 +580,9 @@ public class MatchScreen extends FScreen { float y; float w = getWidth(); Color color = Color.CYAN; + GameView game = MatchController.instance.getGameView(); + CombatView combat = game.getCombat(); + PlayerView currentPlayer = MatchController.instance.getCurrentPlayer(); //field separator lines if (!Forge.isLandscapeMode()) { @@ -592,8 +609,7 @@ public class MatchScreen extends FScreen { //Draw Priority Human Multiplayer 2 player float oldAlphaComposite = g.getfloatAlphaComposite(); - - + //TODO: support up to 4 players if ((getPlayerPanels().keySet().size() == 2) && (countHuman() == 2)){ for (VPlayerPanel playerPanel: playerPanelsList){ midField = playerPanel.getTop(); @@ -606,28 +622,22 @@ public class MatchScreen extends FScreen { else g.setAlphaComposite(0f); - if(MatchController.instance.getGameView()!= null) { - if(MatchController.instance.getGameView().getPhase()!=null) - { - if(MatchController.instance.getGameView().getPhase().isCombatPhase()){ - if(playerPanel.getPlayer() == MatchController.instance.getCurrentPlayer()) - g.setAlphaComposite(0.8f); - else - g.setAlphaComposite(0f); - } - } - - - if(MatchController.instance.getGameView().getCombat() != null) { - if(playerPanel.getPlayer() == MatchController.instance.getGameView().getPlayerTurn()) - color = Color.RED; + if(game!= null) { + if(combat!=null) { + //hide rectangle + if(playerPanel.getPlayer() == currentPlayer) + g.setAlphaComposite(0.8f); else - color = Color.LIME; - } - else + g.setAlphaComposite(0f); + //color rectangle + if(playerPanel.getPlayer() == game.getPlayerTurn()) + color = Color.RED; //attacking player + else + color = Color.LIME; //defending player + } else { color = Color.CYAN; + } } - g.drawRect(4f, color, playerPanel.getField().getLeft(), adjustY, playerPanel.getField().getWidth(), adjustH); g.setAlphaComposite(oldAlphaComposite); } diff --git a/forge-gui-mobile/src/forge/screens/match/views/VStack.java b/forge-gui-mobile/src/forge/screens/match/views/VStack.java index 07a9d9468ab..567665e69bd 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VStack.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VStack.java @@ -95,6 +95,15 @@ public class VStack extends FDropDown { restorablePlayerZones = null; } + public void checkEmptyStack() { //sort the bug in client when desynch happens + final FCollectionView stack = MatchController.instance.getGameView().getStack(); + if(stack!=null) + if(isVisible() && stack.isEmpty()) { //visible stack but empty already + hide(); + getMenuTab().setText(Localizer.getInstance().getMessage("lblStack") + " (" + 0 + ")"); + } + } + @Override public void update() { activeItem = null; diff --git a/forge-gui/src/main/java/forge/match/LobbySlot.java b/forge-gui/src/main/java/forge/match/LobbySlot.java index e7c97666f53..9a8b50160dd 100644 --- a/forge-gui/src/main/java/forge/match/LobbySlot.java +++ b/forge-gui/src/main/java/forge/match/LobbySlot.java @@ -22,6 +22,10 @@ public final class LobbySlot implements Serializable { private boolean isDevMode; private Deck deck; private ImmutableSet aiOptions; + private String AvatarVanguard; + private String SchemeDeckName; + private String PlanarDeckName; + private String DeckName; public LobbySlot(final LobbySlotType type, final String name, final int avatarIndex, final int sleeveIndex, final int team, final boolean isArchenemy, final boolean isReady, final Set aiOptions) { this.type = type; @@ -79,6 +83,22 @@ public final class LobbySlot implements Serializable { } else if (oldDeck != null && data.getSection() != null && data.getCards() != null) { oldDeck.putSection(data.getSection(), data.getCards()); } + if (data.getSchemeDeckName() != null) { + setSchemeDeckName(data.getSchemeDeckName()); + changed = true; + } + if (data.getAvatarVanguard() != null) { + setAvatarVanguard(data.getAvatarVanguard()); + changed = true; + } + if (data.getPlanarDeckName() != null) { + setPlanarDeckName(data.getPlanarDeckName()); + changed = true; + } + if (data.getDeckName() != null) { + setDeckName(data.getDeckName()); + changed = true; + } return changed; } @@ -116,6 +136,16 @@ public final class LobbySlot implements Serializable { this.team = team; } + public String getSchemeDeckName() { return SchemeDeckName; } + public String getAvatarVanguard() { return AvatarVanguard; } + public String getPlanarDeckName() { return PlanarDeckName; } + public String getDeckName() { return DeckName; } + + public void setSchemeDeckName(String schemeDeckName) { this.SchemeDeckName = schemeDeckName; } + public void setAvatarVanguard(String avatarVanguard) { this.AvatarVanguard = avatarVanguard; } + public void setPlanarDeckName(String planarDeckName) { this.PlanarDeckName = planarDeckName; } + public void setDeckName(String DeckName) { this.DeckName = DeckName; } + public boolean isArchenemy() { return isArchenemy; } diff --git a/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java b/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java index 7fae4077b10..1c8bdfe7232 100644 --- a/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java +++ b/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java @@ -25,6 +25,10 @@ public final class UpdateLobbyPlayerEvent implements NetEvent { private DeckSection section = null; private CardPool cards = null; private Set aiOptions = null; + private String AvatarVanguard = null; + private String SchemeDeckName = null; + private String PlanarDeckName = null; + private String DeckName = null; public static UpdateLobbyPlayerEvent create(final LobbySlotType type, final String name, final int avatarIndex, final int sleeveIndex, final int team, final boolean isArchenemy, final boolean isReady, final Set aiOptions) { @@ -53,17 +57,39 @@ public final class UpdateLobbyPlayerEvent implements NetEvent { public static UpdateLobbyPlayerEvent sleeveUpdate(final int index) { return new UpdateLobbyPlayerEvent(index, false); } - private UpdateLobbyPlayerEvent(int index, boolean avatar) { + public static UpdateLobbyPlayerEvent isReadyUpdate(final boolean isReady) { + return new UpdateLobbyPlayerEvent(isReady); + } + public static UpdateLobbyPlayerEvent teamUpdate(int team) { + return new UpdateLobbyPlayerEvent(team); + } + public static UpdateLobbyPlayerEvent setDeckSchemePlaneVanguard(final String DeckName, final String Scheme, final String Plane, final String Vanguard) { + return new UpdateLobbyPlayerEvent(DeckName, Scheme, Plane, Vanguard); + } + private UpdateLobbyPlayerEvent(final int index, final boolean avatar) { if (avatar) this.avatarIndex = index; else this.sleeveIndex = index; } + private UpdateLobbyPlayerEvent(final int team) { + this.team = team; + } + private UpdateLobbyPlayerEvent(final String DeckName, final String Scheme, final String Plane, final String Vanguard) { + this.SchemeDeckName = Scheme; + this.PlanarDeckName = Plane; + this.AvatarVanguard = Vanguard; + this.DeckName = DeckName; + } private UpdateLobbyPlayerEvent(final Deck deck) { this.deck = deck; } + private UpdateLobbyPlayerEvent(final boolean isReady) { + this.isReady = isReady; + } + private UpdateLobbyPlayerEvent(final DeckSection section, final CardPool cards) { this.section = section; this.cards = cards; @@ -149,4 +175,8 @@ public final class UpdateLobbyPlayerEvent implements NetEvent { public Set getAiOptions() { return aiOptions == null ? null : Collections.unmodifiableSet(aiOptions); } + public String getAvatarVanguard() { return AvatarVanguard; } + public String getSchemeDeckName() { return SchemeDeckName; } + public String getPlanarDeckName() { return PlanarDeckName; } + public String getDeckName() { return DeckName; } } From f68ac2e43ad0079d741aa97a45038c1633ce8b1c Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Tue, 21 Apr 2020 20:31:41 +0800 Subject: [PATCH 3/4] refactor stack -> deque --- forge-gui-mobile/src/forge/Forge.java | 33 ++++++++++++------------ forge-gui-mobile/src/forge/Graphics.java | 16 +++++++----- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index 4cbb9b327db..ef88c70b228 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -38,9 +38,10 @@ import forge.util.Utils; import java.io.File; import java.io.FileFilter; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; import java.util.List; -import java.util.Stack; public class Forge implements ApplicationListener { public static final String CURRENT_VERSION = "1.6.33.001"; @@ -57,7 +58,7 @@ public class Forge implements ApplicationListener { private static KeyInputAdapter keyInputAdapter; private static boolean exited; private static int continuousRenderingCount = 1; //initialize to 1 since continuous rendering is the default - private static final Stack screens = new Stack<>(); + private static final Deque Dscreens = new ArrayDeque<>(); private static boolean textureFiltering = false; private static boolean destroyThis = false; public static String extrawide = "default"; @@ -259,13 +260,13 @@ public class Forge implements ApplicationListener { } public static boolean onHomeScreen() { - return screens.size() == 1; + return Dscreens.size() == 1; } public static void back() { if(destroyThis && isLandscapeMode()) return; - if (screens.size() < 2) { + if (Dscreens.size() < 2) { exit(false); //prompt to exit if attempting to go back from home screen return; } @@ -273,8 +274,8 @@ public class Forge implements ApplicationListener { @Override public void run(Boolean result) { if (result) { - screens.pop(); - setCurrentScreen(screens.lastElement()); + Dscreens.removeFirst(); + setCurrentScreen(Dscreens.getFirst()); } } }); @@ -282,12 +283,12 @@ public class Forge implements ApplicationListener { //set screen that will be gone to on pressing Back before going to current Back screen public static void setBackScreen(final FScreen screen0, boolean replace) { - screens.remove(screen0); //remove screen from previous position in navigation history - int index = screens.size() - 1; + Dscreens.remove(screen0); //remove screen from previous position in navigation history + int index = Dscreens.size() - 1; if (index > 0) { - screens.add(index, screen0); + Dscreens.addLast(screen0); if (replace) { //remove previous back screen if replacing back screen - screens.remove(index - 1); + Dscreens.removeFirst(); } } } @@ -349,7 +350,7 @@ public class Forge implements ApplicationListener { if (currentScreen == screen0) { return; } if (currentScreen == null) { - screens.push(screen0); + Dscreens.addFirst(screen0); setCurrentScreen(screen0); return; } @@ -358,11 +359,11 @@ public class Forge implements ApplicationListener { @Override public void run(Boolean result) { if (result) { - if (replaceBackScreen && !screens.isEmpty()) { - screens.pop(); + if (replaceBackScreen && !Dscreens.isEmpty()) { + Dscreens.removeFirst(); } - if (screens.peek() != screen0) { //prevent screen being its own back screen - screens.push(screen0); + if (Dscreens.peekFirst() != screen0) { //prevent screen being its own back screen + Dscreens.addFirst(screen0); } setCurrentScreen(screen0); } @@ -505,7 +506,7 @@ public class Forge implements ApplicationListener { currentScreen.onClose(null); currentScreen = null; } - screens.clear(); + Dscreens.clear(); graphics.dispose(); SoundSystem.instance.dispose(); try { diff --git a/forge-gui-mobile/src/forge/Graphics.java b/forge-gui-mobile/src/forge/Graphics.java index a5df4f53ca7..f339a8af981 100644 --- a/forge-gui-mobile/src/forge/Graphics.java +++ b/forge-gui-mobile/src/forge/Graphics.java @@ -19,7 +19,9 @@ import forge.assets.FSkinFont; import forge.toolbox.FDisplayObject; import forge.util.Utils; import forge.util.TextBounds; -import java.util.Stack; + +import java.util.ArrayDeque; +import java.util.Deque; public class Graphics { private static final int GL_BLEND = GL20.GL_BLEND; @@ -27,7 +29,7 @@ public class Graphics { private final SpriteBatch batch = new SpriteBatch(); private final ShapeRenderer shapeRenderer = new ShapeRenderer(); - private final Stack transforms = new Stack<>(); + private final Deque Dtransforms = new ArrayDeque<>(); private final Vector3 tmp = new Vector3(); private float regionHeight; private Rectangle bounds; @@ -70,7 +72,7 @@ public class Graphics { batch.flush(); //must flush batch to prevent other things not rendering Rectangle clip = new Rectangle(adjustX(x), adjustY(y, h), w, h); - if (!transforms.isEmpty()) { //transform position if needed + if (!Dtransforms.isEmpty()) { //transform position if needed tmp.set(clip.x, clip.y, 0); tmp.mul(batch.getTransformMatrix()); float minX = tmp.x; @@ -121,7 +123,7 @@ public class Graphics { final Rectangle parentBounds = bounds; bounds = new Rectangle(parentBounds.x + displayObj.getLeft(), parentBounds.y + displayObj.getTop(), displayObj.getWidth(), displayObj.getHeight()); - if (!transforms.isEmpty()) { //transform screen position if needed by applying transform matrix to rectangle + if (!Dtransforms.isEmpty()) { //transform screen position if needed by applying transform matrix to rectangle updateScreenPosForRotation(displayObj); } else { @@ -542,7 +544,7 @@ public class Graphics { } private void startShape(ShapeType shapeType) { - if (!transforms.isEmpty()) { + if (!Dtransforms.isEmpty()) { //must copy matrix before starting shape if transformed shapeRenderer.setTransformMatrix(batch.getTransformMatrix()); } @@ -624,7 +626,7 @@ public class Graphics { public void startRotateTransform(float originX, float originY, float rotation) { batch.end(); - transforms.add(0, new Matrix4(batch.getTransformMatrix().idt())); //startshape is using this above as reference + Dtransforms.addFirst(new Matrix4(batch.getTransformMatrix().idt())); //startshape is using this above as reference batch.getTransformMatrix().idt().translate(adjustX(originX), adjustY(originY, 0), 0).rotate(Vector3.Z, rotation).translate(-adjustX(originX), -adjustY(originY, 0), 0); batch.begin(); } @@ -632,7 +634,7 @@ public class Graphics { public void endTransform() { batch.end(); shapeRenderer.setTransformMatrix(batch.getTransformMatrix().idt()); - transforms.pop(); + Dtransforms.removeFirst(); batch.getTransformMatrix().idt(); //reset shapeRenderer.getTransformMatrix().idt(); //reset batch.begin(); From 96e243e4c9ec858047606db3f835563cc3232746 Mon Sep 17 00:00:00 2001 From: Anthony Calosa Date: Wed, 22 Apr 2020 07:29:49 +0800 Subject: [PATCH 4/4] Refactor stack -> Deque, add check for transformCount --- .../java/forge/game/phase/PhaseHandler.java | 18 +++++++++--------- forge-gui-mobile/src/forge/Graphics.java | 8 ++++++++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java index 80d122ed83e..18f69184042 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -71,7 +71,7 @@ public class PhaseHandler implements java.io.Serializable { private int turn = 0; private final transient Stack extraTurns = new Stack<>(); - private final transient Map> extraPhases = Maps.newEnumMap(PhaseType.class); + private final transient Map> DextraPhases = Maps.newEnumMap(PhaseType.class); private int nUpkeepsThisTurn = 0; private int nUpkeepsThisGame = 0; @@ -151,12 +151,12 @@ public class PhaseHandler implements java.io.Serializable { else { // If the phase that's ending has a stack of additional phases // Take the LIFO one and move to that instead of the normal one - if (extraPhases.containsKey(phase)) { - PhaseType nextPhase = extraPhases.get(phase).pop(); + if (DextraPhases.containsKey(phase)) { + PhaseType nextPhase = DextraPhases.get(phase).removeFirst(); // If no more additional phases are available, remove it from the map // and let the next add, reput the key - if (extraPhases.get(phase).isEmpty()) { - extraPhases.remove(phase); + if (DextraPhases.get(phase).isEmpty()) { + DextraPhases.remove(phase); } setPhase(nextPhase); } @@ -918,10 +918,10 @@ public class PhaseHandler implements java.io.Serializable { public final void addExtraPhase(final PhaseType afterPhase, final PhaseType extraPhase) { // 500.8. Some effects can add phases to a turn. They do this by adding the phases directly after the specified phase. // If multiple extra phases are created after the same phase, the most recently created phase will occur first. - if (!extraPhases.containsKey(afterPhase)) { - extraPhases.put(afterPhase, new Stack<>()); + if (!DextraPhases.containsKey(afterPhase)) { + DextraPhases.put(afterPhase, new ArrayDeque<>()); } - extraPhases.get(afterPhase).push(extraPhase); + DextraPhases.get(afterPhase).addFirst(extraPhase); } public final boolean isFirstCombat() { @@ -1159,7 +1159,7 @@ public class PhaseHandler implements java.io.Serializable { public final void endTurnByEffect() { endCombat(); - extraPhases.clear(); + DextraPhases.clear(); setPhase(PhaseType.CLEANUP); onPhaseBegin(); } diff --git a/forge-gui-mobile/src/forge/Graphics.java b/forge-gui-mobile/src/forge/Graphics.java index f339a8af981..695634e659c 100644 --- a/forge-gui-mobile/src/forge/Graphics.java +++ b/forge-gui-mobile/src/forge/Graphics.java @@ -36,6 +36,7 @@ public class Graphics { private Rectangle visibleBounds; private int failedClipCount; private float alphaComposite = 1; + private int transformCount = 0; public Graphics() { } @@ -627,6 +628,7 @@ public class Graphics { public void startRotateTransform(float originX, float originY, float rotation) { batch.end(); Dtransforms.addFirst(new Matrix4(batch.getTransformMatrix().idt())); //startshape is using this above as reference + transformCount++; batch.getTransformMatrix().idt().translate(adjustX(originX), adjustY(originY, 0), 0).rotate(Vector3.Z, rotation).translate(-adjustX(originX), -adjustY(originY, 0), 0); batch.begin(); } @@ -635,6 +637,12 @@ public class Graphics { batch.end(); shapeRenderer.setTransformMatrix(batch.getTransformMatrix().idt()); Dtransforms.removeFirst(); + transformCount--; + if(transformCount != Dtransforms.size()) { + System.err.println(String.format("Stack count: %d, transformCount: %d", Dtransforms.size(), transformCount)); + transformCount = 0; + Dtransforms.clear(); + } batch.getTransformMatrix().idt(); //reset shapeRenderer.getTransformMatrix().idt(); //reset batch.begin();