diff --git a/forge-gui/src/main/java/forge/match/GameLobby.java b/forge-gui/src/main/java/forge/match/GameLobby.java index 168a331c60b..097705ed545 100644 --- a/forge-gui/src/main/java/forge/match/GameLobby.java +++ b/forge-gui/src/main/java/forge/match/GameLobby.java @@ -4,10 +4,12 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; + import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; @@ -49,7 +51,7 @@ public abstract class GameLobby implements IHasGameType { private final boolean allowNetworking; private HostedMatch hostedMatch; - private final Map gameControllers = Maps.newHashMap(); + private final HashMap gameControllers = Maps.newHashMap(); protected GameLobby(final boolean allowNetworking) { this.allowNetworking = allowNetworking; } @@ -481,6 +483,8 @@ public abstract class GameLobby implements IHasGameType { } } + hostedMatch.gameControllers = gameControllers; + onGameStarted(); } }; diff --git a/forge-gui/src/main/java/forge/match/HostedMatch.java b/forge-gui/src/main/java/forge/match/HostedMatch.java index 3e3f757a962..d42aaa68072 100644 --- a/forge-gui/src/main/java/forge/match/HostedMatch.java +++ b/forge-gui/src/main/java/forge/match/HostedMatch.java @@ -3,11 +3,14 @@ package forge.match; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import forge.LobbyPlayer; +import forge.interfaces.IGameController; import forge.util.TextUtil; import org.apache.commons.lang3.StringUtils; @@ -55,6 +58,7 @@ public class HostedMatch { private Match match; private Game game; private String title; + public HashMap gameControllers = null; private Runnable startGameHook = null; private final List humanControllers = Lists.newArrayList(); private Map guis; @@ -180,6 +184,12 @@ public class HostedMatch { game.subscribeToEvents(new FControlGameEventHandler(humanController)); playersPerGui.add(gui, p.getView()); + + if (gameControllers != null ) { + LobbySlot lobbySlot = getLobbySlot(p.getLobbyPlayer()); + gameControllers.put(lobbySlot, humanController); + } + humanControllers.add(humanController); humanCount++; } @@ -238,6 +248,18 @@ public class HostedMatch { }); } + private LobbySlot getLobbySlot(LobbyPlayer lobbyPlayer) { + for (LobbySlot key: gameControllers.keySet()) { + IGameController value = gameControllers.get(key); + if (value instanceof PlayerControllerHuman) { + if (lobbyPlayer == ((PlayerControllerHuman) value).getLobbyPlayer()) { + return key; + } + } + } + return null; + } + public void registerSpectator(final IGuiGame gui) { final PlayerControllerHuman humanController = new WatchLocalGame(game, null, gui); gui.setSpectator(humanController); diff --git a/forge-gui/src/main/java/forge/net/client/GameClientHandler.java b/forge-gui/src/main/java/forge/net/client/GameClientHandler.java index f15a4576bc5..08955a4d2c1 100644 --- a/forge-gui/src/main/java/forge/net/client/GameClientHandler.java +++ b/forge-gui/src/main/java/forge/net/client/GameClientHandler.java @@ -27,6 +27,8 @@ final class GameClientHandler extends GameProtocolHandler { private final FGameClient client; private final IGuiGame gui; private Tracker tracker; + private Match match; + private Game game; /** * Creates a client-side game handler. @@ -36,6 +38,8 @@ final class GameClientHandler extends GameProtocolHandler { this.client = client; this.gui = client.getGui(); this.tracker = null; + this.match = null; + this.game = null; } @Override @@ -58,32 +62,26 @@ final class GameClientHandler extends GameProtocolHandler { protected void beforeCall(final ProtocolMethod protocolMethod, final Object[] args) { switch (protocolMethod) { case openView: - if (this.tracker == null) { - int maxAttempts = 5; - for (int numAttempts = 0; numAttempts < maxAttempts; numAttempts++) { - try { + // only need one **match** + if (this.match == null) { + this.match = createMatch(); + } - this.tracker = createTracker(); + // openView is called **once** per game, for now create a new Game instance each time + this.game = createGame(); - for (PlayerView myPlayer : (TrackableCollection) args[0]) { - if (myPlayer.getTracker() == null) { - myPlayer.setTracker(this.tracker); - } - } + // get a tracker + this.tracker = createTracker(); - final TrackableCollection myPlayers = (TrackableCollection) args[0]; - client.setGameControllers(myPlayers); - - } catch (Exception e) { - System.err.println("Failed: attempt number: " + numAttempts + " - " + e.toString()); - try { - Thread.sleep(100); - } catch (InterruptedException e1) { - e1.printStackTrace(); - } - } + for (PlayerView myPlayer : (TrackableCollection) args[0]) { + if (myPlayer.getTracker() == null) { + myPlayer.setTracker(this.tracker); } } + + final TrackableCollection myPlayers = (TrackableCollection) args[0]; + client.setGameControllers(myPlayers); + break; default: break; @@ -108,19 +106,17 @@ final class GameClientHandler extends GameProtocolHandler { } /** - * This method creates the necessary objects and state to retrieve a Tracker object. - * - * Near as I can tell, that means that we need to create a Match. + * This method retrieves enough of the existing (incomplete) game state to + * recreate a new viable Match object * * Creating a Match requires that we have: * * GameRules * * RegisteredPlayers * * Title * - * @return Tracker + * @return Match */ - private Tracker createTracker() { - + private Match createMatch() { // retrieve what we can from the existing (but incomplete) state final IGuiGame gui = client.getGui(); GameView gameView = gui.getGameView(); @@ -134,12 +130,24 @@ final class GameClientHandler extends GameProtocolHandler { // create a valid match object and game Match match = new Match(gameRules, registeredPlayers, title); - Game game = match.createGame(); + return match; + } + + private Game createGame() { + this.tracker = null; + return this.match.createGame(); + } + + /** + * Ensure the stored GameView is correct and retrieve a Tracker object. + * + * @return Tracker + */ + private Tracker createTracker() { // replace the existing incomplete GameView with the newly created one gui.setGameView(null); gui.setGameView(game.getView()); - return gui.getGameView().getTracker(); } diff --git a/forge-gui/src/main/java/forge/net/server/FServerManager.java b/forge-gui/src/main/java/forge/net/server/FServerManager.java index 8b8416c8a04..2d9118764e5 100644 --- a/forge-gui/src/main/java/forge/net/server/FServerManager.java +++ b/forge-gui/src/main/java/forge/net/server/FServerManager.java @@ -55,6 +55,7 @@ import com.google.common.collect.Maps; public final class FServerManager { private static FServerManager instance = null; + private byte[] externalAddress = new byte[]{8,8,8,8}; private boolean isHosting = false; private final EventLoopGroup bossGroup = new NioEventLoopGroup(1); private final EventLoopGroup workerGroup = new NioEventLoopGroup(); @@ -210,7 +211,7 @@ public final class FServerManager { // https://stackoverflow.com/a/901943 private String getRoutableAddress(boolean preferIpv4, boolean preferIPv6) throws SocketException, UnknownHostException { DatagramSocket s = new DatagramSocket(); - s.connect(InetAddress.getByAddress(new byte[]{8,8,8,8}), 0); + s.connect(InetAddress.getByAddress(this.externalAddress), 0); NetworkInterface n = NetworkInterface.getByInetAddress(s.getLocalAddress()); Enumeration en = n.getInetAddresses(); while (en.hasMoreElements()) {