mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
Merge branch 'multiplayer' into 'master'
further multiplayer fixes See merge request core-developers/forge!238
This commit is contained in:
@@ -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<LobbySlot, IGameController> gameControllers = Maps.newHashMap();
|
||||
private final HashMap<LobbySlot, IGameController> 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();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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<LobbySlot, IGameController> gameControllers = null;
|
||||
private Runnable startGameHook = null;
|
||||
private final List<PlayerControllerHuman> humanControllers = Lists.newArrayList();
|
||||
private Map<RegisteredPlayer, IGuiGame> 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);
|
||||
|
||||
@@ -27,6 +27,8 @@ final class GameClientHandler extends GameProtocolHandler<IGuiGame> {
|
||||
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<IGuiGame> {
|
||||
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<IGuiGame> {
|
||||
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<PlayerView>) args[0]) {
|
||||
if (myPlayer.getTracker() == null) {
|
||||
myPlayer.setTracker(this.tracker);
|
||||
}
|
||||
}
|
||||
// get a tracker
|
||||
this.tracker = createTracker();
|
||||
|
||||
final TrackableCollection<PlayerView> myPlayers = (TrackableCollection<PlayerView>) 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<PlayerView>) args[0]) {
|
||||
if (myPlayer.getTracker() == null) {
|
||||
myPlayer.setTracker(this.tracker);
|
||||
}
|
||||
}
|
||||
|
||||
final TrackableCollection<PlayerView> myPlayers = (TrackableCollection<PlayerView>) args[0];
|
||||
client.setGameControllers(myPlayers);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -108,19 +106,17 @@ final class GameClientHandler extends GameProtocolHandler<IGuiGame> {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates the necessary objects and state to retrieve a <b>Tracker</b> object.
|
||||
*
|
||||
* Near as I can tell, that means that we need to create a <b>Match</b>.
|
||||
* This method retrieves enough of the existing (incomplete) game state to
|
||||
* recreate a new viable Match object
|
||||
*
|
||||
* Creating a <b>Match</b> requires that we have:
|
||||
* * <b>GameRules</b>
|
||||
* * <b>RegisteredPlayers</b>
|
||||
* * 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<IGuiGame> {
|
||||
|
||||
// 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 <b>Tracker</b> 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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
Reference in New Issue
Block a user