From 705d6cb9370c8e6ae730c81713dbf16d3aad35d2 Mon Sep 17 00:00:00 2001 From: elcnesh Date: Mon, 20 Apr 2015 14:40:26 +0000 Subject: [PATCH] - Remove old net code - Remove "Start/Stop Server" buttons (related to old code) - Move new net code to forge-gui/forge/net/** - Remove all dependencies on project forge-net --- .gitattributes | 25 +- forge-gui-android/pom.xml | 5 - forge-gui-desktop/pom.xml | 5 - .../src/main/java/forge/gui/FNetOverlay.java | 4 +- .../main/java/forge/screens/home/CHomeUI.java | 28 -- .../java/forge/screens/home/PlayerPanel.java | 2 +- .../main/java/forge/screens/home/VHomeUI.java | 31 +- .../main/java/forge/screens/home/VLobby.java | 4 +- .../home/online/CSubmenuOnlineLobby.java | 18 +- .../screens/home/online/VOnlineLobby.java | 4 +- .../home/sanctioned/VSubmenuConstructed.java | 2 +- forge-gui-ios/.classpath | 5 +- forge-gui-ios/pom.xml | 5 - forge-gui-mobile/pom.xml | 5 - forge-gui/CHANGES.txt | 10 +- forge-gui/pom.xml | 5 - .../main/java/forge/interfaces/ILobby.java | 2 +- .../interfaces/IPlayerChangeListener.java | 2 +- .../src/main/java/forge/match/GameLobby.java | 3 +- .../src/main/java/forge/match/LobbySlot.java | 3 +- .../main/java/forge/match/LobbySlotType.java | 8 + .../src/main/java/forge/match/LocalLobby.java | 1 - .../src/main/java/forge/net/FGameClient.java | 398 ------------------ .../src/main/java/forge/net/IRemote.java | 11 + .../main/java/forge/net/LobbyUpdateEvent.java | 28 -- .../src/main/java/forge/net/ReplyPool.java | 57 +++ .../net/{ => client}/ClientGameLobby.java | 2 +- .../java/forge/net/client/FGameClient.java | 151 +++++++ .../forge/net/client/GameClientHandler.java | 268 ++++++++++++ .../main/java/forge/net/client/IToServer.java | 6 + .../net/{ => client}/NetGameController.java | 5 +- .../java/forge/net/client/package-info.java | 1 + .../main/java/forge/net/event/ReplyEvent.java | 31 ++ .../net/event/UpdateLobbyPlayerEvent.java | 83 ++++ .../java/forge/net/event/package-info.java | 1 + .../net/{ => server}/FServerManager.java | 26 +- .../main/java/forge/net/server/IToClient.java | 6 + .../forge/net/{ => server}/NetGuiGame.java | 5 +- .../java/forge/net/server/RemoteClient.java | 52 +++ .../net/{ => server}/ServerGameLobby.java | 4 +- .../java/forge/net/server/package-info.java | 1 + 41 files changed, 749 insertions(+), 564 deletions(-) create mode 100644 forge-gui/src/main/java/forge/match/LobbySlotType.java delete mode 100644 forge-gui/src/main/java/forge/net/FGameClient.java create mode 100644 forge-gui/src/main/java/forge/net/IRemote.java delete mode 100644 forge-gui/src/main/java/forge/net/LobbyUpdateEvent.java create mode 100644 forge-gui/src/main/java/forge/net/ReplyPool.java rename forge-gui/src/main/java/forge/net/{ => client}/ClientGameLobby.java (96%) create mode 100644 forge-gui/src/main/java/forge/net/client/FGameClient.java create mode 100644 forge-gui/src/main/java/forge/net/client/GameClientHandler.java create mode 100644 forge-gui/src/main/java/forge/net/client/IToServer.java rename forge-gui/src/main/java/forge/net/{ => client}/NetGameController.java (97%) create mode 100644 forge-gui/src/main/java/forge/net/client/package-info.java create mode 100644 forge-gui/src/main/java/forge/net/event/ReplyEvent.java create mode 100644 forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java create mode 100644 forge-gui/src/main/java/forge/net/event/package-info.java rename forge-gui/src/main/java/forge/net/{ => server}/FServerManager.java (97%) create mode 100644 forge-gui/src/main/java/forge/net/server/IToClient.java rename forge-gui/src/main/java/forge/net/{ => server}/NetGuiGame.java (99%) create mode 100644 forge-gui/src/main/java/forge/net/server/RemoteClient.java rename forge-gui/src/main/java/forge/net/{ => server}/ServerGameLobby.java (97%) create mode 100644 forge-gui/src/main/java/forge/net/server/package-info.java diff --git a/.gitattributes b/.gitattributes index 3b8b5a846da..fe6a40338d4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17671,6 +17671,7 @@ forge-gui/src/main/java/forge/match/AbstractGuiGame.java -text forge-gui/src/main/java/forge/match/GameLobby.java -text forge-gui/src/main/java/forge/match/HostedMatch.java -text forge-gui/src/main/java/forge/match/LobbySlot.java -text +forge-gui/src/main/java/forge/match/LobbySlotType.java -text forge-gui/src/main/java/forge/match/LocalLobby.java -text forge-gui/src/main/java/forge/match/MatchButtonType.java -text forge-gui/src/main/java/forge/match/MatchConstants.java -text @@ -17705,14 +17706,24 @@ forge-gui/src/main/java/forge/model/MetaSet.java -text forge-gui/src/main/java/forge/model/MultipleForgeJarsFoundError.java -text forge-gui/src/main/java/forge/model/UnOpenedMeta.java -text forge-gui/src/main/java/forge/model/package-info.java svneol=native#text/plain -forge-gui/src/main/java/forge/net/ClientGameLobby.java -text -forge-gui/src/main/java/forge/net/FGameClient.java -text -forge-gui/src/main/java/forge/net/FServerManager.java -text -forge-gui/src/main/java/forge/net/LobbyUpdateEvent.java -text -forge-gui/src/main/java/forge/net/NetGameController.java -text -forge-gui/src/main/java/forge/net/NetGuiGame.java -text -forge-gui/src/main/java/forge/net/ServerGameLobby.java -text +forge-gui/src/main/java/forge/net/IRemote.java -text +forge-gui/src/main/java/forge/net/ReplyPool.java -text +forge-gui/src/main/java/forge/net/client/ClientGameLobby.java -text +forge-gui/src/main/java/forge/net/client/FGameClient.java -text +forge-gui/src/main/java/forge/net/client/GameClientHandler.java -text +forge-gui/src/main/java/forge/net/client/IToServer.java -text +forge-gui/src/main/java/forge/net/client/NetGameController.java -text +forge-gui/src/main/java/forge/net/client/package-info.java -text +forge-gui/src/main/java/forge/net/event/ReplyEvent.java -text +forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java -text +forge-gui/src/main/java/forge/net/event/package-info.java -text forge-gui/src/main/java/forge/net/package-info.java -text +forge-gui/src/main/java/forge/net/server/FServerManager.java -text +forge-gui/src/main/java/forge/net/server/IToClient.java -text +forge-gui/src/main/java/forge/net/server/NetGuiGame.java -text +forge-gui/src/main/java/forge/net/server/RemoteClient.java -text +forge-gui/src/main/java/forge/net/server/ServerGameLobby.java -text +forge-gui/src/main/java/forge/net/server/package-info.java -text forge-gui/src/main/java/forge/planarconquest/ConquestAction.java -text forge-gui/src/main/java/forge/planarconquest/ConquestCommander.java -text forge-gui/src/main/java/forge/planarconquest/ConquestController.java -text diff --git a/forge-gui-android/pom.xml b/forge-gui-android/pom.xml index 4df10ee44cf..d986bd78054 100644 --- a/forge-gui-android/pom.xml +++ b/forge-gui-android/pom.xml @@ -62,11 +62,6 @@ forge-ai ${project.version} - - forge - forge-net - ${project.version} - forge forge-gui diff --git a/forge-gui-desktop/pom.xml b/forge-gui-desktop/pom.xml index 39b06391a87..e26617a73a6 100644 --- a/forge-gui-desktop/pom.xml +++ b/forge-gui-desktop/pom.xml @@ -174,11 +174,6 @@ forge-ai ${project.version} - - forge - forge-net - ${project.version} - forge forge-gui diff --git a/forge-gui-desktop/src/main/java/forge/gui/FNetOverlay.java b/forge-gui-desktop/src/main/java/forge/gui/FNetOverlay.java index 52e35b3aa5f..c77d81f5a96 100644 --- a/forge-gui-desktop/src/main/java/forge/gui/FNetOverlay.java +++ b/forge-gui-desktop/src/main/java/forge/gui/FNetOverlay.java @@ -18,8 +18,8 @@ import org.apache.commons.lang3.StringUtils; import forge.Singletons; import forge.gui.framework.SDisplayUtil; import forge.model.FModel; -import forge.net.game.IRemote; -import forge.net.game.MessageEvent; +import forge.net.IRemote; +import forge.net.event.MessageEvent; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.toolbox.FLabel; diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/CHomeUI.java b/forge-gui-desktop/src/main/java/forge/screens/home/CHomeUI.java index b56d8bce60e..199982c4c4a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/CHomeUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/CHomeUI.java @@ -6,14 +6,11 @@ import javax.swing.JMenu; import forge.Singletons; import forge.UiCommand; -import forge.gui.FNetOverlay; import forge.gui.framework.EDocID; import forge.gui.framework.ICDoc; import forge.menus.IMenuProvider; import forge.menus.MenuUtil; import forge.model.FModel; -import forge.net.FServer; -import forge.net.FServerManager; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.screens.home.sanctioned.VSubmenuConstructed; @@ -83,31 +80,6 @@ public enum CHomeUI implements ICDoc, IMenuProvider { Singletons.getControl().getForgeMenu().setProvider(this); selectPrevious(); - - VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setCommand(new Runnable() { - @Override - public void run() { - //final NetServer srv = FServer.getServer(); - //srv.listen(ForgeConstants.SERVER_PORT_NUMBER); - - VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setEnabled(true); - VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setEnabled(false); - - FNetOverlay.SINGLETON_INSTANCE.showUp("");//"Server listening on port " + srv.getPortNumber()); - } - }); - - VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setCommand(new Runnable() { - @Override - public void run() { - FServer.getServer().stop(); - FServerManager.getInstance().stopServer(); - VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setEnabled(false); - VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setEnabled(true); - - FNetOverlay.SINGLETON_INSTANCE.getWindow().setVisible(false); - } - }); } /* (non-Javadoc) 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 673209314ad..85aa49d3a8a 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 @@ -30,8 +30,8 @@ import forge.game.GameType; import forge.gui.framework.FScreen; import forge.item.PaperCard; import forge.match.LobbySlot; +import forge.match.LobbySlotType; import forge.model.FModel; -import forge.net.game.LobbySlotType; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.screens.deckeditor.CDeckEditorUI; diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java b/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java index 5e83e8300fa..38ad108cedd 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java @@ -41,7 +41,6 @@ import forge.gui.framework.ICDoc; import forge.gui.framework.ILocalRepaint; import forge.gui.framework.IVTopLevelUI; import forge.model.FModel; -import forge.properties.ForgeConstants; import forge.properties.ForgePreferences.FPref; import forge.screens.home.gauntlet.VSubmenuGauntletBuild; import forge.screens.home.gauntlet.VSubmenuGauntletContests; @@ -97,35 +96,17 @@ public enum VHomeUI implements IVTopLevelUI { .iconAlignX(SwingConstants.CENTER) .iconInBackground(true).iconScaleFactor(1.0).build(); - private final FLabel lblStartServer = new FLabel.ButtonBuilder().text("Start Server").fontSize(14).build(); - private final FLabel lblStopServer = new FLabel.ButtonBuilder().text("Stop Server").fontSize(14).build(); - private VHomeUI() { // Add main menu containing logo and menu buttons final JPanel pnlMainMenu = new JPanel(new MigLayout("w 200px!, ax center, insets 0, gap 0, wrap")); pnlMainMenu.setOpaque(false); - final List mainMenuButtons = new ArrayList(); - if (ForgeConstants.SERVER_PORT_NUMBER >= 80) { - mainMenuButtons.add(lblStartServer); - mainMenuButtons.add(lblStopServer); - lblStopServer.setEnabled(false); - } - final int logoSize = 170; final int logoBottomGap = 4; - final int buttonHeight = 30; - final int buttonBottomGap = 8; - final int pnlMainMenuHeight = logoSize + logoBottomGap + - mainMenuButtons.size() * (buttonHeight + buttonBottomGap); + final int pnlMainMenuHeight = logoSize + logoBottomGap; pnlMainMenu.add(lblLogo, "w " + logoSize + "px!, h " + logoSize + "px!, gap 0 4px 0 " + logoBottomGap + "px"); - String buttonLayout = "w 170px!, h " + buttonHeight + - "px!, gap 0 0 0 " + buttonBottomGap + "px"; - for (FLabel button : mainMenuButtons) { - pnlMainMenu.add(button, buttonLayout); - } pnlMenu.add(pnlMainMenu); pnlSubmenus = new FScrollPanel(new MigLayout("insets 0, gap 0, wrap, hidemode 3"), true, @@ -137,7 +118,7 @@ public enum VHomeUI implements IVTopLevelUI { allSubmenus.add(VSubmenuSealed.SINGLETON_INSTANCE); //allSubmenus.add(VSubmenuWinston.SINGLETON_INSTANCE); - //allSubmenus.add(VSubmenuOnlineLobby.SINGLETON_INSTANCE); + allSubmenus.add(VSubmenuOnlineLobby.SINGLETON_INSTANCE); allSubmenus.add(VSubmenuDuels.SINGLETON_INSTANCE); allSubmenus.add(VSubmenuChallenges.SINGLETON_INSTANCE); @@ -189,14 +170,6 @@ public enum VHomeUI implements IVTopLevelUI { pnlDisplay.setBackground(l00.alphaColor(100)); } - public final FLabel getLblStartServer() { - return lblStartServer; - } - - public final FLabel getLblStopServer() { - return lblStopServer; - } - /** @return {@link javax.swing.JPanel} */ public JPanel getPnlMenu() { return pnlMenu; 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 7a48bf81c62..c984915c782 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 @@ -42,9 +42,9 @@ import forge.interfaces.IUpdateable; import forge.item.PaperCard; import forge.match.GameLobby; import forge.match.LobbySlot; +import forge.match.LobbySlotType; import forge.model.FModel; -import forge.net.game.LobbySlotType; -import forge.net.game.UpdateLobbyPlayerEvent; +import forge.net.event.UpdateLobbyPlayerEvent; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.toolbox.FCheckBox; 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 b3f64f8f9b3..157d1221557 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 @@ -20,15 +20,15 @@ import forge.match.GameLobby.GameLobbyData; import forge.menus.IMenuProvider; import forge.menus.MenuUtil; import forge.model.FModel; -import forge.net.ClientGameLobby; -import forge.net.FGameClient; -import forge.net.FServerManager; -import forge.net.ServerGameLobby; -import forge.net.game.IRemote; -import forge.net.game.IdentifiableNetEvent; -import forge.net.game.MessageEvent; -import forge.net.game.NetEvent; -import forge.net.game.UpdateLobbyPlayerEvent; +import forge.net.IRemote; +import forge.net.client.ClientGameLobby; +import forge.net.client.FGameClient; +import forge.net.event.IdentifiableNetEvent; +import forge.net.event.MessageEvent; +import forge.net.event.NetEvent; +import forge.net.event.UpdateLobbyPlayerEvent; +import forge.net.server.FServerManager; +import forge.net.server.ServerGameLobby; import forge.properties.ForgePreferences.FPref; import forge.screens.home.VLobby; import forge.screens.home.sanctioned.ConstructedGameMenu; diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/online/VOnlineLobby.java b/forge-gui-desktop/src/main/java/forge/screens/home/online/VOnlineLobby.java index 08338b5b5ef..a9c53d27721 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/online/VOnlineLobby.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/online/VOnlineLobby.java @@ -14,8 +14,8 @@ import forge.gui.framework.FScreen; import forge.gui.framework.IVDoc; import forge.gui.framework.IVTopLevelUI; import forge.match.GameLobby; -import forge.net.FGameClient; -import forge.net.FServerManager; +import forge.net.client.FGameClient; +import forge.net.server.FServerManager; import forge.screens.home.VLobby; import forge.toolbox.FPanel; import forge.util.gui.SOptionPane; 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 0d8255eaefd..2fa6399bd43 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 @@ -12,7 +12,7 @@ import forge.gui.framework.EDocID; import forge.interfaces.IPlayerChangeListener; import forge.match.GameLobby; import forge.match.LocalLobby; -import forge.net.game.UpdateLobbyPlayerEvent; +import forge.net.event.UpdateLobbyPlayerEvent; import forge.screens.home.EMenuGroup; import forge.screens.home.IVSubmenu; import forge.screens.home.VHomeUI; diff --git a/forge-gui-ios/.classpath b/forge-gui-ios/.classpath index 0424fe8e344..ed9f6578cf4 100644 --- a/forge-gui-ios/.classpath +++ b/forge-gui-ios/.classpath @@ -10,7 +10,6 @@ - @@ -24,7 +23,9 @@ + - + + diff --git a/forge-gui-ios/pom.xml b/forge-gui-ios/pom.xml index b5d0f0ca7de..114619ac944 100644 --- a/forge-gui-ios/pom.xml +++ b/forge-gui-ios/pom.xml @@ -56,11 +56,6 @@ forge-ai ${project.version} - - forge - forge-net - ${project.version} - forge forge-gui diff --git a/forge-gui-mobile/pom.xml b/forge-gui-mobile/pom.xml index a6d4d533ab1..4f50834d96d 100644 --- a/forge-gui-mobile/pom.xml +++ b/forge-gui-mobile/pom.xml @@ -35,11 +35,6 @@ forge-ai ${project.version} - - forge - forge-net - ${project.version} - forge forge-gui diff --git a/forge-gui/CHANGES.txt b/forge-gui/CHANGES.txt index 3a387647e2e..15e3215768c 100644 --- a/forge-gui/CHANGES.txt +++ b/forge-gui/CHANGES.txt @@ -8,7 +8,7 @@ Forge Beta: #-#-2015 ver 1.5.39 Release Notes ------------- -Interface Update +- Interface Update - The interface has received several small changes. - The "Players" panel has been removed. This information can now be viewed by hovering the cursor over a player's avatar. @@ -17,6 +17,14 @@ The interface has received several small changes. - The poison counters button has been replaced with a Command Zone button. The command zone panels have been removed. +- Network play (BETA) - +This version of Forge includes a preliminary version of peer-to-peer (P2P) +network support. If one player hosts, other players can connect to that +player's machine by filling out the corresponding IP address and port number +(default 36743), provided the lobby contains one or more open player slots. +Do not expect network support to work reliably yet, any bug reports or other +comments are welcome! + - Smarter Deck Color Determination - When determining the color of decks, colors of hybrid and phyrexian cards are no longer considered unless they can be produced by a land in the deck diff --git a/forge-gui/pom.xml b/forge-gui/pom.xml index e2af288c748..0bbc37acf6e 100644 --- a/forge-gui/pom.xml +++ b/forge-gui/pom.xml @@ -35,11 +35,6 @@ forge forge-ai ${project.version} - - - forge - forge-net - ${project.version} com.google.guava diff --git a/forge-gui/src/main/java/forge/interfaces/ILobby.java b/forge-gui/src/main/java/forge/interfaces/ILobby.java index 054dd0f3f37..65dddf747f8 100644 --- a/forge-gui/src/main/java/forge/interfaces/ILobby.java +++ b/forge-gui/src/main/java/forge/interfaces/ILobby.java @@ -1,7 +1,7 @@ package forge.interfaces; import forge.match.GameLobby; -import forge.net.game.server.RemoteClient; +import forge.net.server.RemoteClient; public interface ILobby { GameLobby getState(); diff --git a/forge-gui/src/main/java/forge/interfaces/IPlayerChangeListener.java b/forge-gui/src/main/java/forge/interfaces/IPlayerChangeListener.java index 373f50e03e4..61146fe105e 100644 --- a/forge-gui/src/main/java/forge/interfaces/IPlayerChangeListener.java +++ b/forge-gui/src/main/java/forge/interfaces/IPlayerChangeListener.java @@ -1,6 +1,6 @@ package forge.interfaces; -import forge.net.game.UpdateLobbyPlayerEvent; +import forge.net.event.UpdateLobbyPlayerEvent; public interface IPlayerChangeListener { void update(int index, UpdateLobbyPlayerEvent event); diff --git a/forge-gui/src/main/java/forge/match/GameLobby.java b/forge-gui/src/main/java/forge/match/GameLobby.java index b559b0e8d87..816fbab934f 100644 --- a/forge-gui/src/main/java/forge/match/GameLobby.java +++ b/forge-gui/src/main/java/forge/match/GameLobby.java @@ -30,8 +30,7 @@ import forge.interfaces.IGuiGame; import forge.interfaces.IUpdateable; import forge.item.PaperCard; import forge.model.FModel; -import forge.net.game.LobbySlotType; -import forge.net.game.UpdateLobbyPlayerEvent; +import forge.net.event.UpdateLobbyPlayerEvent; import forge.player.GamePlayerUtil; import forge.properties.ForgePreferences.FPref; import forge.util.NameGenerator; diff --git a/forge-gui/src/main/java/forge/match/LobbySlot.java b/forge-gui/src/main/java/forge/match/LobbySlot.java index 055095fce95..9bdff9edc15 100644 --- a/forge-gui/src/main/java/forge/match/LobbySlot.java +++ b/forge-gui/src/main/java/forge/match/LobbySlot.java @@ -7,8 +7,7 @@ import com.google.common.collect.ImmutableSet; import forge.AIOption; import forge.deck.Deck; -import forge.net.game.LobbySlotType; -import forge.net.game.UpdateLobbyPlayerEvent; +import forge.net.event.UpdateLobbyPlayerEvent; public final class LobbySlot implements Serializable { private static final long serialVersionUID = 6918205436608794289L; diff --git a/forge-gui/src/main/java/forge/match/LobbySlotType.java b/forge-gui/src/main/java/forge/match/LobbySlotType.java new file mode 100644 index 00000000000..8e764b232b4 --- /dev/null +++ b/forge-gui/src/main/java/forge/match/LobbySlotType.java @@ -0,0 +1,8 @@ +package forge.match; + +public enum LobbySlotType { + LOCAL, + AI, + OPEN, + REMOTE; +} \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/match/LocalLobby.java b/forge-gui/src/main/java/forge/match/LocalLobby.java index 63e9857b65d..3fc2e23182e 100644 --- a/forge-gui/src/main/java/forge/match/LocalLobby.java +++ b/forge-gui/src/main/java/forge/match/LocalLobby.java @@ -5,7 +5,6 @@ import java.util.Collections; import forge.AIOption; import forge.GuiBase; import forge.interfaces.IGuiGame; -import forge.net.game.LobbySlotType; public final class LocalLobby extends GameLobby { diff --git a/forge-gui/src/main/java/forge/net/FGameClient.java b/forge-gui/src/main/java/forge/net/FGameClient.java deleted file mode 100644 index 1e0c6c09c8b..00000000000 --- a/forge-gui/src/main/java/forge/net/FGameClient.java +++ /dev/null @@ -1,398 +0,0 @@ -package forge.net; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInboundHandlerAdapter; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.serialization.ClassResolvers; -import io.netty.handler.codec.serialization.ObjectDecoder; -import io.netty.handler.codec.serialization.ObjectEncoder; - -import java.io.Serializable; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeoutException; - -import com.google.common.base.Function; -import com.google.common.collect.Lists; - -import forge.FThreads; -import forge.UiCommand; -import forge.assets.FSkinProp; -import forge.deck.CardPool; -import forge.game.GameEntityView; -import forge.game.GameView; -import forge.game.card.CardView; -import forge.game.phase.PhaseType; -import forge.game.player.DelayedReveal; -import forge.game.player.PlayerView; -import forge.game.spellability.SpellAbilityView; -import forge.game.zone.ZoneType; -import forge.interfaces.IButton; -import forge.interfaces.IGuiGame; -import forge.interfaces.ILobbyListener; -import forge.match.MatchButtonType; -import forge.model.FModel; -import forge.net.game.GuiGameEvent; -import forge.net.game.IdentifiableNetEvent; -import forge.net.game.LoginEvent; -import forge.net.game.MessageEvent; -import forge.net.game.NetEvent; -import forge.net.game.ReplyEvent; -import forge.net.game.client.IToServer; -import forge.player.PlayerZoneUpdates; -import forge.properties.ForgePreferences.FPref; -import forge.trackable.TrackableCollection; -import forge.util.ITriggerEvent; - -public class FGameClient implements IToServer { - private final IGuiGame clientGui; - public FGameClient(final String username, final String roomKey, final IGuiGame clientGui) { - this.clientGui = clientGui; - } - - private final List lobbyListeners = Lists.newArrayList(); - private final ReplyPool replies = new ReplyPool(); - - static final int SIZE = Integer.parseInt(System.getProperty("size", "256")); - - private Channel channel; - public void connect(final String host, final int port) { - final EventLoopGroup group = new NioEventLoopGroup(); - try { - final Bootstrap b = new Bootstrap() - .group(group) - .channel(NioSocketChannel.class) - .handler(new ChannelInitializer() { - @Override - public void initChannel(final SocketChannel ch) throws Exception { - final ChannelPipeline pipeline = ch.pipeline(); - pipeline.addLast( - new ObjectEncoder(), - new ObjectDecoder(ClassResolvers.cacheDisabled(null)), - new MessageHandler(), - new LobbyUpdateHandler(), - new GameClientHandler()); - } - }); - - // Start the connection attempt. - channel = b.connect(host, port).sync().channel(); - final ChannelFuture ch = channel.closeFuture(); - new Thread(new Runnable() { - @Override public void run() { - try { - ch.sync(); - } catch (final InterruptedException e) { - e.printStackTrace(); - } finally { - group.shutdownGracefully(); - } - } - }).start(); - } catch (final InterruptedException e) { - e.printStackTrace(); - } - } - - public void close() { - channel.close(); - } - - @Override - public void send(final NetEvent event) { - System.out.println("Client sent " + event); - channel.writeAndFlush(event); - } - - @Override - public Object sendAndWait(final IdentifiableNetEvent event) throws TimeoutException { - replies.initialize(event.getId()); - - send(event); - - // Wait for reply - return replies.get(event.getId()); - } - - public void addLobbyListener(final ILobbyListener listener) { - lobbyListeners.add(listener); - } - - private void setGameControllers(final Iterable myPlayers) { - for (final PlayerView p : myPlayers) { - clientGui.setGameController(p, new NetGameController(this)); - } - } - - private class GameClientHandler extends ChannelInboundHandlerAdapter { - /** - * Creates a client-side handler. - */ - public GameClientHandler() { - } - - @Override - public void channelActive(final ChannelHandlerContext ctx) { - // Don't use send() here, as this.channel is not yet set! - ctx.channel().writeAndFlush(new LoginEvent(FModel.getPreferences().getPref(FPref.PLAYER_NAME), Integer.parseInt(FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",")[0]))); - } - - @SuppressWarnings("unchecked") - @Override - public void channelRead(final ChannelHandlerContext ctx, final Object msg) { - System.out.println("Client received: " + msg); - if (msg instanceof ReplyEvent) { - final ReplyEvent event = (ReplyEvent) msg; - replies.complete(event.getIndex(), event.getReply()); - } else if (msg instanceof GuiGameEvent) { - final GuiGameEvent event = (GuiGameEvent) msg; - final String method = event.getMethod(); - final Object[] args = event.getObjects(); - Serializable reply = null; - boolean doReply = false; - - final IButton btn; - if (method.startsWith("btn_") && args.length >= 2 && args[0] instanceof PlayerView && args[1] instanceof MatchButtonType) { - btn = args[1] == MatchButtonType.OK ? clientGui.getBtnOK((PlayerView) args[0]) : clientGui.getBtnCancel((PlayerView) args[0]); - } else { - btn = null; - } - - switch (method) { - case "setGameView": - clientGui.setGameView((GameView) args[0]); - break; - case "openView": - final TrackableCollection myPlayers = (TrackableCollection) args[0]; - setGameControllers(myPlayers); - FThreads.invokeInEdtNowOrLater(new Runnable() { - @Override public final void run() { - //clientGui.setGameView(new NetGameView(FGameClient.this)); - clientGui.openView(myPlayers); - } - }); - break; - case "afterGameEnd": - clientGui.afterGameEnd(); - break; - case "showCombat": - clientGui.showCombat(); - break; - case "showPromptMessage": - clientGui.showPromptMessage((PlayerView) args[0], (String) args[1]); - break; - case "stopAtPhase": - reply = clientGui.stopAtPhase((PlayerView) args[0], (PhaseType) args[1]); - doReply = true; - break; - case "focusButton": - clientGui.focusButton((MatchButtonType) args[0]); - break; - case "flashIncorrectAction": - clientGui.flashIncorrectAction(); - break; - case "updatePhase": - clientGui.updatePhase(); - break; - case "updateTurn": - FThreads.invokeInEdtNowOrLater(new Runnable() { - @Override public final void run() { - clientGui.updateTurn((PlayerView) args[0]); - } - }); - break; - case "udpdatePlayerControl": - clientGui.updatePlayerControl(); - break; - case "enableOverlay": - clientGui.enableOverlay(); - break; - case "disbleOverlay": - clientGui.disableOverlay(); - break; - case "finishGame": - clientGui.finishGame(); - break; - case "showManaPool": - clientGui.showManaPool((PlayerView) args[0]); - break; - case "hideManaPool": - clientGui.hideManaPool((PlayerView) args[0], args[1]); - break; - case "updateStack": - clientGui.updateStack(); - break; - case "updateZones": - FThreads.invokeInEdtNowOrLater(new Runnable() { - @Override public final void run() { - clientGui.updateZones((PlayerZoneUpdates) args[0]); - } - }); - break; - case "updateSingleCard": - clientGui.updateSingleCard((CardView) args[0]); - break; - case "updateManaPool": - clientGui.updateManaPool((Iterable) args[0]); - break; - case "updateLives": - clientGui.updateLives((Iterable) args[0]); - break; - case "setPanelSelection": - clientGui.setPanelSelection((CardView) args[0]); - break; - case "getAbilityToPlay": - reply = clientGui.getAbilityToPlay((List) args[0], (ITriggerEvent) args[1]); - doReply = true; - break; - case "assignDamage": - reply = (Serializable) clientGui.assignDamage((CardView) args[0], (List) args[1], (int) args[2], (GameEntityView) args[3], (boolean) args[4]); - doReply = true; - break; - case "message": - clientGui.message((String) args[0], (String) args[1]); - break; - case "showErrorDialog": - clientGui.showErrorDialog((String) args[0], (String) args[1]); - break; - case "showConfirmDialog": - reply = clientGui.showConfirmDialog((String) args[0], (String) args[1], (String) args[2], (String) args[3], (boolean) args[4]); - doReply = true; - break; - case "showOptionDialog": - reply = clientGui.showOptionDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String[]) args[3], (int) args[4]); - doReply = true; - break; - case "showCardOptionDialog": - reply = clientGui.showCardOptionDialog((CardView) args[0], (String) args[1], (String) args[2], (FSkinProp) args[3], (String[]) args[4], (int) args[5]); - doReply = true; - break; - case "showInputDialog": - reply = clientGui.showInputDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String) args[3], (String[]) args[4]); - doReply = true; - break; - case "confirm": - reply = clientGui.confirm((CardView) args[0], (String) args[1], (boolean) args[2], (String[]) args[3]); - doReply = true; - break; - case "getChoices": - reply = (Serializable) clientGui.getChoices((String) args[0], (int) args[1], (int) args[2], (Collection) args[3], args[4], (Function) args[5]); - doReply = true; - break; - case "order": - reply = (Serializable) clientGui.order((String) args[0], (String) args[1], (int) args[2], (int) args[3], (List) args[4], (List) args[5], (CardView) args[6], (boolean) args[7]); - doReply = true; - break; - case "sideboard": - reply = (Serializable) clientGui.sideboard((CardPool) args[0], (CardPool) args[1]); - doReply = true; - break; - case "chooseSingleEntityForEffect": - reply = clientGui.chooseSingleEntityForEffect((String) args[0], (TrackableCollection) args[1], (DelayedReveal) args[2], (boolean) args[3]); - doReply = true; - break; - case "setCard": - clientGui.setCard((CardView) args[0]); - break; - // TODO case "setPlayerAvatar": - case "openZones": - reply = clientGui.openZones((Collection) args[0], (Map) args[1]); - doReply = true; - break; - case "restoreOldZones": - clientGui.restoreOldZones((Map) args[0]); - break; - case "isUiSetToSkipPhase": - reply = clientGui.isUiSetToSkipPhase((PlayerView) args[0], (PhaseType) args[1]); - doReply = true; - break; - // BUTTONS - case "btn_setEnabled": - btn.setEnabled((boolean) args[2]); - break; - case "btn_setVisible": - btn.setVisible((boolean) args[2]); - break; - case "btn_setText": - btn.setText((String) args[2]); - break; - case "btn_isSelected": - reply = btn.isSelected(); - doReply = true; - break; - case "btn_setSelected": - btn.setSelected((boolean) args[2]); - break; - case "btn_requestFocusInWindows": - reply = btn.requestFocusInWindow(); - doReply = true; - break; - case "btn_setCommand": - btn.setCommand((UiCommand) args[2]); - break; - case "btn_setTextColor": - if (args.length == 3) { - btn.setTextColor((FSkinProp) args[2]); - } else { - btn.setTextColor((int) args[2], (int) args[3], (int) args[4]); - } - default: - System.err.println("Unsupported game event " + event.getMethod()); - break; - } - if (doReply) { - send(new ReplyEvent(event.getId(), reply)); - } - } - } - - @Override - public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { - cause.printStackTrace(); - ctx.close(); - } - } - - private class MessageHandler extends ChannelInboundHandlerAdapter { - @Override - public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { - if (msg instanceof MessageEvent) { - final MessageEvent event = (MessageEvent) msg; - for (final ILobbyListener listener : lobbyListeners) { - listener.message(event.getSource(), event.getMessage()); - } - } - super.channelRead(ctx, msg); - } - } - - private class LobbyUpdateHandler extends ChannelInboundHandlerAdapter { - @Override - public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { - if (msg instanceof LobbyUpdateEvent) { - for (final ILobbyListener listener : lobbyListeners) { - final LobbyUpdateEvent event = (LobbyUpdateEvent) msg; - listener.update(event.getState(), event.getSlot()); - } - } - super.channelRead(ctx, msg); - } - - @Override - public void channelInactive(final ChannelHandlerContext ctx) throws Exception { - for (final ILobbyListener listener : lobbyListeners) { - listener.close(); - } - super.channelInactive(ctx); - } - } -} diff --git a/forge-gui/src/main/java/forge/net/IRemote.java b/forge-gui/src/main/java/forge/net/IRemote.java new file mode 100644 index 00000000000..ffc14b01ce2 --- /dev/null +++ b/forge-gui/src/main/java/forge/net/IRemote.java @@ -0,0 +1,11 @@ +package forge.net; + +import java.util.concurrent.TimeoutException; + +import forge.net.event.IdentifiableNetEvent; +import forge.net.event.NetEvent; + +public interface IRemote { + void send(NetEvent event); + Object sendAndWait(IdentifiableNetEvent event) throws TimeoutException; +} diff --git a/forge-gui/src/main/java/forge/net/LobbyUpdateEvent.java b/forge-gui/src/main/java/forge/net/LobbyUpdateEvent.java deleted file mode 100644 index cec6c055b16..00000000000 --- a/forge-gui/src/main/java/forge/net/LobbyUpdateEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -package forge.net; - -import forge.match.GameLobby.GameLobbyData; -import forge.net.game.NetEvent; -import forge.net.game.server.RemoteClient; - -public class LobbyUpdateEvent implements NetEvent { - private static final long serialVersionUID = 7114918637727047985L; - - private final GameLobbyData state; - private int slot; - public LobbyUpdateEvent(final GameLobbyData state) { - this.state = state; - } - - @Override - public void updateForClient(final RemoteClient client) { - this.slot = client.getIndex(); - } - - public GameLobbyData getState() { - return state; - } - - public int getSlot() { - return slot; - } -} diff --git a/forge-gui/src/main/java/forge/net/ReplyPool.java b/forge-gui/src/main/java/forge/net/ReplyPool.java new file mode 100644 index 00000000000..bea35cfe8cd --- /dev/null +++ b/forge-gui/src/main/java/forge/net/ReplyPool.java @@ -0,0 +1,57 @@ +package forge.net; + +import java.util.Map; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import com.google.common.collect.Maps; + +public class ReplyPool { + + private final Map pool = Maps.newHashMap(); + + public ReplyPool() { + } + + public void initialize(final int index) { + synchronized (pool) { + pool.put(Integer.valueOf(index), new CompletableFuture()); + } + } + + public void complete(final int index, final Object value) { + synchronized (pool) { + pool.get(Integer.valueOf(index)).set(value); + } + } + + public Object get(final int index) throws TimeoutException { + final CompletableFuture future; + synchronized (pool) { + future = pool.get(Integer.valueOf(index)); + } + try { + return future.get(1, TimeUnit.MINUTES); + } catch (final InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + private static final class CompletableFuture extends FutureTask { + public CompletableFuture() { + super(new Callable() { + @Override public Object call() throws Exception { + return null; + } + }); + } + + @Override + public void set(final Object v) { + super.set(v); + } + } +} diff --git a/forge-gui/src/main/java/forge/net/ClientGameLobby.java b/forge-gui/src/main/java/forge/net/client/ClientGameLobby.java similarity index 96% rename from forge-gui/src/main/java/forge/net/ClientGameLobby.java rename to forge-gui/src/main/java/forge/net/client/ClientGameLobby.java index 264079011c0..87d5da06413 100644 --- a/forge-gui/src/main/java/forge/net/ClientGameLobby.java +++ b/forge-gui/src/main/java/forge/net/client/ClientGameLobby.java @@ -1,4 +1,4 @@ -package forge.net; +package forge.net.client; import forge.interfaces.IGuiGame; import forge.match.GameLobby; diff --git a/forge-gui/src/main/java/forge/net/client/FGameClient.java b/forge-gui/src/main/java/forge/net/client/FGameClient.java new file mode 100644 index 00000000000..af9d15a8c55 --- /dev/null +++ b/forge-gui/src/main/java/forge/net/client/FGameClient.java @@ -0,0 +1,151 @@ +package forge.net.client; + +import io.netty.bootstrap.Bootstrap; +import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.EventLoopGroup; +import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.codec.serialization.ClassResolvers; +import io.netty.handler.codec.serialization.ObjectDecoder; +import io.netty.handler.codec.serialization.ObjectEncoder; + +import java.util.List; +import java.util.concurrent.TimeoutException; + +import com.google.common.collect.Lists; + +import forge.game.player.PlayerView; +import forge.interfaces.IGuiGame; +import forge.interfaces.ILobbyListener; +import forge.net.ReplyPool; +import forge.net.event.IdentifiableNetEvent; +import forge.net.event.LobbyUpdateEvent; +import forge.net.event.MessageEvent; +import forge.net.event.NetEvent; + +public class FGameClient implements IToServer { + + private final IGuiGame clientGui; + private final List lobbyListeners = Lists.newArrayList(); + private final ReplyPool replies = new ReplyPool(); + private Channel channel; + + public FGameClient(final String username, final String roomKey, final IGuiGame clientGui) { + this.clientGui = clientGui; + } + + final IGuiGame getGui() { + return clientGui; + } + final ReplyPool getReplyPool() { + return replies; + } + + public void connect(final String host, final int port) { + final EventLoopGroup group = new NioEventLoopGroup(); + try { + final Bootstrap b = new Bootstrap() + .group(group) + .channel(NioSocketChannel.class) + .handler(new ChannelInitializer() { + @Override + public void initChannel(final SocketChannel ch) throws Exception { + final ChannelPipeline pipeline = ch.pipeline(); + pipeline.addLast( + new ObjectEncoder(), + new ObjectDecoder(ClassResolvers.cacheDisabled(null)), + new MessageHandler(), + new LobbyUpdateHandler(), + new GameClientHandler(FGameClient.this)); + } + }); + + // Start the connection attempt. + channel = b.connect(host, port).sync().channel(); + final ChannelFuture ch = channel.closeFuture(); + new Thread(new Runnable() { + @Override public void run() { + try { + ch.sync(); + } catch (final InterruptedException e) { + e.printStackTrace(); + } finally { + group.shutdownGracefully(); + } + } + }).start(); + } catch (final InterruptedException e) { + e.printStackTrace(); + } + } + + public void close() { + channel.close(); + } + + @Override + public void send(final NetEvent event) { + System.out.println("Client sent " + event); + channel.writeAndFlush(event); + } + + @Override + public Object sendAndWait(final IdentifiableNetEvent event) throws TimeoutException { + replies.initialize(event.getId()); + + send(event); + + // Wait for reply + return replies.get(event.getId()); + } + + public void addLobbyListener(final ILobbyListener listener) { + lobbyListeners.add(listener); + } + + void setGameControllers(final Iterable myPlayers) { + for (final PlayerView p : myPlayers) { + clientGui.setGameController(p, new NetGameController(this)); + } + } + + private class MessageHandler extends ChannelInboundHandlerAdapter { + @Override + public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { + if (msg instanceof MessageEvent) { + final MessageEvent event = (MessageEvent) msg; + for (final ILobbyListener listener : lobbyListeners) { + listener.message(event.getSource(), event.getMessage()); + } + } + super.channelRead(ctx, msg); + } + } + + private class LobbyUpdateHandler extends ChannelInboundHandlerAdapter { + @Override + public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception { + if (msg instanceof LobbyUpdateEvent) { + for (final ILobbyListener listener : lobbyListeners) { + final LobbyUpdateEvent event = (LobbyUpdateEvent) msg; + listener.update(event.getState(), event.getSlot()); + } + } + super.channelRead(ctx, msg); + } + + @Override + public void channelInactive(final ChannelHandlerContext ctx) throws Exception { + for (final ILobbyListener listener : lobbyListeners) { + listener.close(); + } + super.channelInactive(ctx); + } + } +} diff --git a/forge-gui/src/main/java/forge/net/client/GameClientHandler.java b/forge-gui/src/main/java/forge/net/client/GameClientHandler.java new file mode 100644 index 00000000000..72ca8126ac7 --- /dev/null +++ b/forge-gui/src/main/java/forge/net/client/GameClientHandler.java @@ -0,0 +1,268 @@ +package forge.net.client; + +import forge.FThreads; +import forge.UiCommand; +import forge.assets.FSkinProp; +import forge.deck.CardPool; +import forge.game.GameEntityView; +import forge.game.GameView; +import forge.game.card.CardView; +import forge.game.phase.PhaseType; +import forge.game.player.DelayedReveal; +import forge.game.player.PlayerView; +import forge.game.spellability.SpellAbilityView; +import forge.game.zone.ZoneType; +import forge.interfaces.IButton; +import forge.interfaces.IGuiGame; +import forge.match.MatchButtonType; +import forge.model.FModel; +import forge.net.event.GuiGameEvent; +import forge.net.event.LoginEvent; +import forge.net.event.ReplyEvent; +import forge.player.PlayerZoneUpdates; +import forge.properties.ForgePreferences.FPref; +import forge.trackable.TrackableCollection; +import forge.util.ITriggerEvent; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; + +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import com.google.common.base.Function; + +class GameClientHandler extends ChannelInboundHandlerAdapter { + private final FGameClient client; + private final IGuiGame gui; + + /** + * Creates a client-side game handler. + */ + public GameClientHandler(final FGameClient client) { + this.client = client; + this.gui = client.getGui(); + } + + @Override + public void channelActive(final ChannelHandlerContext ctx) { + // Don't use send() here, as this.channel is not yet set! + ctx.channel().writeAndFlush(new LoginEvent(FModel.getPreferences().getPref(FPref.PLAYER_NAME), Integer.parseInt(FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",")[0]))); + } + + @SuppressWarnings("unchecked") + @Override + public void channelRead(final ChannelHandlerContext ctx, final Object msg) { + System.out.println("Client received: " + msg); + if (msg instanceof ReplyEvent) { + final ReplyEvent event = (ReplyEvent) msg; + client.getReplyPool().complete(event.getIndex(), event.getReply()); + } else if (msg instanceof GuiGameEvent) { + final GuiGameEvent event = (GuiGameEvent) msg; + final String method = event.getMethod(); + final Object[] args = event.getObjects(); + Serializable reply = null; + boolean doReply = false; + + final IButton btn; + if (method.startsWith("btn_") && args.length >= 2 && args[0] instanceof PlayerView && args[1] instanceof MatchButtonType) { + btn = args[1] == MatchButtonType.OK ? gui.getBtnOK((PlayerView) args[0]) : gui.getBtnCancel((PlayerView) args[0]); + } else { + btn = null; + } + + switch (method) { + case "setGameView": + gui.setGameView((GameView) args[0]); + break; + case "openView": + final TrackableCollection myPlayers = (TrackableCollection) args[0]; + client.setGameControllers(myPlayers); + FThreads.invokeInEdtNowOrLater(new Runnable() { + @Override public final void run() { + gui.openView(myPlayers); + } + }); + break; + case "afterGameEnd": + gui.afterGameEnd(); + break; + case "showCombat": + gui.showCombat(); + break; + case "showPromptMessage": + gui.showPromptMessage((PlayerView) args[0], (String) args[1]); + break; + case "stopAtPhase": + reply = gui.stopAtPhase((PlayerView) args[0], (PhaseType) args[1]); + doReply = true; + break; + case "focusButton": + gui.focusButton((MatchButtonType) args[0]); + break; + case "flashIncorrectAction": + gui.flashIncorrectAction(); + break; + case "updatePhase": + gui.updatePhase(); + break; + case "updateTurn": + FThreads.invokeInEdtNowOrLater(new Runnable() { + @Override public final void run() { + gui.updateTurn((PlayerView) args[0]); + } + }); + break; + case "udpdatePlayerControl": + gui.updatePlayerControl(); + break; + case "enableOverlay": + gui.enableOverlay(); + break; + case "disbleOverlay": + gui.disableOverlay(); + break; + case "finishGame": + gui.finishGame(); + break; + case "showManaPool": + gui.showManaPool((PlayerView) args[0]); + break; + case "hideManaPool": + gui.hideManaPool((PlayerView) args[0], args[1]); + break; + case "updateStack": + gui.updateStack(); + break; + case "updateZones": + FThreads.invokeInEdtNowOrLater(new Runnable() { + @Override public final void run() { + gui.updateZones((PlayerZoneUpdates) args[0]); + } + }); + break; + case "updateSingleCard": + gui.updateSingleCard((CardView) args[0]); + break; + case "updateManaPool": + gui.updateManaPool((Iterable) args[0]); + break; + case "updateLives": + gui.updateLives((Iterable) args[0]); + break; + case "setPanelSelection": + gui.setPanelSelection((CardView) args[0]); + break; + case "getAbilityToPlay": + reply = gui.getAbilityToPlay((List) args[0], (ITriggerEvent) args[1]); + doReply = true; + break; + case "assignDamage": + reply = (Serializable) gui.assignDamage((CardView) args[0], (List) args[1], (int) args[2], (GameEntityView) args[3], (boolean) args[4]); + doReply = true; + break; + case "message": + gui.message((String) args[0], (String) args[1]); + break; + case "showErrorDialog": + gui.showErrorDialog((String) args[0], (String) args[1]); + break; + case "showConfirmDialog": + reply = gui.showConfirmDialog((String) args[0], (String) args[1], (String) args[2], (String) args[3], (boolean) args[4]); + doReply = true; + break; + case "showOptionDialog": + reply = gui.showOptionDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String[]) args[3], (int) args[4]); + doReply = true; + break; + case "showCardOptionDialog": + reply = gui.showCardOptionDialog((CardView) args[0], (String) args[1], (String) args[2], (FSkinProp) args[3], (String[]) args[4], (int) args[5]); + doReply = true; + break; + case "showInputDialog": + reply = gui.showInputDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String) args[3], (String[]) args[4]); + doReply = true; + break; + case "confirm": + reply = gui.confirm((CardView) args[0], (String) args[1], (boolean) args[2], (String[]) args[3]); + doReply = true; + break; + case "getChoices": + reply = (Serializable) gui.getChoices((String) args[0], (int) args[1], (int) args[2], (Collection) args[3], args[4], (Function) args[5]); + doReply = true; + break; + case "order": + reply = (Serializable) gui.order((String) args[0], (String) args[1], (int) args[2], (int) args[3], (List) args[4], (List) args[5], (CardView) args[6], (boolean) args[7]); + doReply = true; + break; + case "sideboard": + reply = (Serializable) gui.sideboard((CardPool) args[0], (CardPool) args[1]); + doReply = true; + break; + case "chooseSingleEntityForEffect": + reply = gui.chooseSingleEntityForEffect((String) args[0], (TrackableCollection) args[1], (DelayedReveal) args[2], (boolean) args[3]); + doReply = true; + break; + case "setCard": + gui.setCard((CardView) args[0]); + break; + // TODO case "setPlayerAvatar": + case "openZones": + reply = gui.openZones((Collection) args[0], (Map) args[1]); + doReply = true; + break; + case "restoreOldZones": + gui.restoreOldZones((Map) args[0]); + break; + case "isUiSetToSkipPhase": + reply = gui.isUiSetToSkipPhase((PlayerView) args[0], (PhaseType) args[1]); + doReply = true; + break; + // BUTTONS + case "btn_setEnabled": + btn.setEnabled((boolean) args[2]); + break; + case "btn_setVisible": + btn.setVisible((boolean) args[2]); + break; + case "btn_setText": + btn.setText((String) args[2]); + break; + case "btn_isSelected": + reply = btn.isSelected(); + doReply = true; + break; + case "btn_setSelected": + btn.setSelected((boolean) args[2]); + break; + case "btn_requestFocusInWindows": + reply = btn.requestFocusInWindow(); + doReply = true; + break; + case "btn_setCommand": + btn.setCommand((UiCommand) args[2]); + break; + case "btn_setTextColor": + if (args.length == 3) { + btn.setTextColor((FSkinProp) args[2]); + } else { + btn.setTextColor((int) args[2], (int) args[3], (int) args[4]); + } + break; + default: + System.err.println("Unsupported game event " + event.getMethod()); + break; + } + if (doReply) { + client.send(new ReplyEvent(event.getId(), reply)); + } + } + } + + @Override + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } +} \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/net/client/IToServer.java b/forge-gui/src/main/java/forge/net/client/IToServer.java new file mode 100644 index 00000000000..9f69092a186 --- /dev/null +++ b/forge-gui/src/main/java/forge/net/client/IToServer.java @@ -0,0 +1,6 @@ +package forge.net.client; + +import forge.net.IRemote; + +public interface IToServer extends IRemote { +} diff --git a/forge-gui/src/main/java/forge/net/NetGameController.java b/forge-gui/src/main/java/forge/net/client/NetGameController.java similarity index 97% rename from forge-gui/src/main/java/forge/net/NetGameController.java rename to forge-gui/src/main/java/forge/net/client/NetGameController.java index d067b5032cf..84b1329478e 100644 --- a/forge-gui/src/main/java/forge/net/NetGameController.java +++ b/forge-gui/src/main/java/forge/net/client/NetGameController.java @@ -1,4 +1,4 @@ -package forge.net; +package forge.net.client; import java.util.List; import java.util.concurrent.TimeoutException; @@ -9,8 +9,7 @@ import forge.game.spellability.SpellAbilityView; import forge.interfaces.IDevModeCheats; import forge.interfaces.IGameController; import forge.match.NextGameDecision; -import forge.net.game.GuiGameEvent; -import forge.net.game.client.IToServer; +import forge.net.event.GuiGameEvent; import forge.util.ITriggerEvent; public class NetGameController implements IGameController { diff --git a/forge-gui/src/main/java/forge/net/client/package-info.java b/forge-gui/src/main/java/forge/net/client/package-info.java new file mode 100644 index 00000000000..7747d9eabb7 --- /dev/null +++ b/forge-gui/src/main/java/forge/net/client/package-info.java @@ -0,0 +1 @@ +package forge.net.client; \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/net/event/ReplyEvent.java b/forge-gui/src/main/java/forge/net/event/ReplyEvent.java new file mode 100644 index 00000000000..7114536bc0e --- /dev/null +++ b/forge-gui/src/main/java/forge/net/event/ReplyEvent.java @@ -0,0 +1,31 @@ +package forge.net.event; + +import java.io.Serializable; + +import forge.net.server.RemoteClient; + +public final class ReplyEvent implements NetEvent { + private static final long serialVersionUID = -2814651319617795386L; + + private final int index; + private final Serializable reply; + public ReplyEvent(final int index, final Serializable reply) { + this.index = index; + this.reply = reply; + } + + public int getIndex() { + return index; + } + public Object getReply() { + return reply; + } + + @Override public void updateForClient(final RemoteClient client) { + } + + @Override + public String toString() { + return String.format("Reply (%d): %s", index, reply); + } +} diff --git a/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java b/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java new file mode 100644 index 00000000000..3cd11597b1f --- /dev/null +++ b/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java @@ -0,0 +1,83 @@ +package forge.net.event; + +import java.util.Collections; +import java.util.Set; + +import forge.AIOption; +import forge.deck.CardPool; +import forge.deck.Deck; +import forge.deck.DeckSection; +import forge.match.LobbySlotType; +import forge.net.server.RemoteClient; + +public final class UpdateLobbyPlayerEvent implements NetEvent { + private static final long serialVersionUID = -5073305607515425968L; + + private final LobbySlotType type; + private final String name; + private final int avatarIndex; + private final int team; + private final Boolean isArchenemy; + private final Boolean isReady; + private final Deck deck; + private final DeckSection section; + private final CardPool cards; + private final Set aiOptions; + + public static UpdateLobbyPlayerEvent create(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final boolean isReady, final Set aiOptions) { + return new UpdateLobbyPlayerEvent(type, name, avatarIndex, team, isArchenemy, isReady, null, null, null, aiOptions); + } + public static UpdateLobbyPlayerEvent deckUpdate(final Deck deck) { + return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, deck, null, null, null); + } + public static UpdateLobbyPlayerEvent deckUpdate(final DeckSection section, final CardPool cards) { + return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, null, section, cards, null); + } + + private UpdateLobbyPlayerEvent(final LobbySlotType type, final String name, final int avatarIndex, final int team, final Boolean isArchenemy, final Boolean isReady, final Deck deck, final DeckSection section, final CardPool cards, final Set aiOptions) { + this.type = type; + this.name = name; + this.avatarIndex = avatarIndex; + this.team = team; + this.isArchenemy = isArchenemy; + this.isReady = isReady; + this.deck = deck; + this.section = section; + this.cards = cards; + this.aiOptions = aiOptions; + } + + public void updateForClient(final RemoteClient client) { + } + + public LobbySlotType getType() { + return type; + } + public String getName() { + return name; + } + public int getAvatarIndex() { + return avatarIndex; + } + public int getTeam() { + return team; + } + public Boolean getArchenemy() { + return isArchenemy; + } + public Boolean getReady() { + return isReady; + } + public Deck getDeck() { + return deck; + } + public DeckSection getSection() { + return section; + } + public CardPool getCards() { + return cards; + } + public Set getAiOptions() { + return aiOptions == null ? null : Collections.unmodifiableSet(aiOptions); + } +} diff --git a/forge-gui/src/main/java/forge/net/event/package-info.java b/forge-gui/src/main/java/forge/net/event/package-info.java new file mode 100644 index 00000000000..b6f2560b69e --- /dev/null +++ b/forge-gui/src/main/java/forge/net/event/package-info.java @@ -0,0 +1 @@ +package forge.net.event; \ No newline at end of file diff --git a/forge-gui/src/main/java/forge/net/FServerManager.java b/forge-gui/src/main/java/forge/net/server/FServerManager.java similarity index 97% rename from forge-gui/src/main/java/forge/net/FServerManager.java rename to forge-gui/src/main/java/forge/net/server/FServerManager.java index 5200e64e3f6..4331977c4d7 100644 --- a/forge-gui/src/main/java/forge/net/FServerManager.java +++ b/forge-gui/src/main/java/forge/net/server/FServerManager.java @@ -1,4 +1,4 @@ -package forge.net; +package forge.net.server; import forge.FThreads; import forge.GuiBase; @@ -11,16 +11,16 @@ import forge.interfaces.IGameController; import forge.interfaces.IGuiGame; import forge.interfaces.ILobbyListener; import forge.match.LobbySlot; +import forge.match.LobbySlotType; import forge.match.NextGameDecision; -import forge.net.game.GuiGameEvent; -import forge.net.game.LobbySlotType; -import forge.net.game.LoginEvent; -import forge.net.game.LogoutEvent; -import forge.net.game.MessageEvent; -import forge.net.game.NetEvent; -import forge.net.game.ReplyEvent; -import forge.net.game.UpdateLobbyPlayerEvent; -import forge.net.game.server.RemoteClient; +import forge.net.event.GuiGameEvent; +import forge.net.event.LobbyUpdateEvent; +import forge.net.event.LoginEvent; +import forge.net.event.LogoutEvent; +import forge.net.event.MessageEvent; +import forge.net.event.NetEvent; +import forge.net.event.ReplyEvent; +import forge.net.event.UpdateLobbyPlayerEvent; import forge.properties.ForgeConstants; import forge.util.ITriggerEvent; import io.netty.bootstrap.ServerBootstrap; @@ -41,7 +41,7 @@ import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; import java.io.Serializable; -import java.net.Inet4Address; +import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Collection; import java.util.Collections; @@ -205,7 +205,7 @@ public final class FServerManager { private void mapNatPort(final int port) { final String localAddress; try { - localAddress = Inet4Address.getLocalHost().getHostAddress(); + localAddress = InetAddress.getLocalHost().getHostAddress(); } catch (final UnknownHostException e) { throw new RuntimeException(e); } @@ -436,7 +436,7 @@ public final class FServerManager { if (msg instanceof LoginEvent) { final String username = ((LoginEvent) msg).getUsername(); client.setUsername(username); - broadcast(new MessageEvent(null, String.format("%s joined the room", username))); + broadcast(new MessageEvent(String.format("%s joined the room", username))); updateLobbyState(); } else if (msg instanceof UpdateLobbyPlayerEvent) { localLobby.applyToSlot(client.getIndex(), (UpdateLobbyPlayerEvent) msg); diff --git a/forge-gui/src/main/java/forge/net/server/IToClient.java b/forge-gui/src/main/java/forge/net/server/IToClient.java new file mode 100644 index 00000000000..f5ca229fe3d --- /dev/null +++ b/forge-gui/src/main/java/forge/net/server/IToClient.java @@ -0,0 +1,6 @@ +package forge.net.server; + +import forge.net.IRemote; + +public interface IToClient extends IRemote { +} diff --git a/forge-gui/src/main/java/forge/net/NetGuiGame.java b/forge-gui/src/main/java/forge/net/server/NetGuiGame.java similarity index 99% rename from forge-gui/src/main/java/forge/net/NetGuiGame.java rename to forge-gui/src/main/java/forge/net/server/NetGuiGame.java index ed1f5a16f59..101214cc927 100644 --- a/forge-gui/src/main/java/forge/net/NetGuiGame.java +++ b/forge-gui/src/main/java/forge/net/server/NetGuiGame.java @@ -1,4 +1,4 @@ -package forge.net; +package forge.net.server; import java.util.Collection; import java.util.EnumMap; @@ -26,8 +26,7 @@ import forge.interfaces.IButton; import forge.item.PaperCard; import forge.match.AbstractGuiGame; import forge.match.MatchButtonType; -import forge.net.game.GuiGameEvent; -import forge.net.game.server.IToClient; +import forge.net.event.GuiGameEvent; import forge.player.PlayerZoneUpdate; import forge.trackable.TrackableCollection; import forge.util.ITriggerEvent; diff --git a/forge-gui/src/main/java/forge/net/server/RemoteClient.java b/forge-gui/src/main/java/forge/net/server/RemoteClient.java new file mode 100644 index 00000000000..a2675746f17 --- /dev/null +++ b/forge-gui/src/main/java/forge/net/server/RemoteClient.java @@ -0,0 +1,52 @@ +package forge.net.server; + +import forge.net.ReplyPool; +import forge.net.event.IdentifiableNetEvent; +import forge.net.event.NetEvent; +import io.netty.channel.Channel; + +import java.util.concurrent.TimeoutException; + +public final class RemoteClient implements IToClient { + + private final Channel channel; + private String username; + private int index; + private ReplyPool replies = new ReplyPool(); + public RemoteClient(final Channel channel) { + this.channel = channel; + } + + @Override + public void send(final NetEvent event) { + System.out.println("Sending event " + event + " to " + channel); + channel.writeAndFlush(event); + } + + @Override + public Object sendAndWait(final IdentifiableNetEvent event) throws TimeoutException { + replies.initialize(event.getId()); + + send(event); + + return replies.get(event.getId()); + } + + public String getUsername() { + return username; + } + public void setUsername(final String username) { + this.username = username; + } + + public int getIndex() { + return index; + } + public void setIndex(final int index) { + this.index = index; + } + + public void setReply(final int id, final Object reply) { + replies.complete(id, reply); + } +} diff --git a/forge-gui/src/main/java/forge/net/ServerGameLobby.java b/forge-gui/src/main/java/forge/net/server/ServerGameLobby.java similarity index 97% rename from forge-gui/src/main/java/forge/net/ServerGameLobby.java rename to forge-gui/src/main/java/forge/net/server/ServerGameLobby.java index f85b7216093..54d3a81b8df 100644 --- a/forge-gui/src/main/java/forge/net/ServerGameLobby.java +++ b/forge-gui/src/main/java/forge/net/server/ServerGameLobby.java @@ -1,4 +1,4 @@ -package forge.net; +package forge.net.server; import java.util.Collections; @@ -8,7 +8,7 @@ import forge.AIOption; import forge.interfaces.IGuiGame; import forge.match.GameLobby; import forge.match.LobbySlot; -import forge.net.game.LobbySlotType; +import forge.match.LobbySlotType; public final class ServerGameLobby extends GameLobby { diff --git a/forge-gui/src/main/java/forge/net/server/package-info.java b/forge-gui/src/main/java/forge/net/server/package-info.java new file mode 100644 index 00000000000..346f318f84b --- /dev/null +++ b/forge-gui/src/main/java/forge/net/server/package-info.java @@ -0,0 +1 @@ +package forge.net.server; \ No newline at end of file