fixed issue 25 - server waits for all clients to confirm initialization before starting game

This commit is contained in:
BetaSteward 2010-11-30 04:35:26 +00:00
parent f81c238994
commit 3ca748e16d
9 changed files with 56 additions and 45 deletions

View file

@ -508,8 +508,8 @@ public class MageFrame extends javax.swing.JFrame {
if (g != null) { if (g != null) {
renderSplashFrame(g); renderSplashFrame(g);
} }
splash.update();
} }
splash.update();
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) { public void uncaughtException(Thread t, Throwable e) {

View file

@ -99,6 +99,7 @@ public class Client implements CallbackClient {
} }
else if (callback.getMethod().equals("gameInit")) { else if (callback.getMethod().equals("gameInit")) {
session.getGame().init((GameView) callback.getData()); session.getGame().init((GameView) callback.getData());
session.ack("gameInit");
} }
else if (callback.getMethod().equals("gameOver")) { else if (callback.getMethod().equals("gameOver")) {
session.getGame().modalMessage((String) callback.getData()); session.getGame().modalMessage((String) callback.getData());

View file

@ -28,7 +28,6 @@
package mage.client.remote; package mage.client.remote;
import java.awt.Component;
import java.rmi.NotBoundException; import java.rmi.NotBoundException;
import java.rmi.RemoteException; import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry; import java.rmi.registry.LocateRegistry;
@ -46,7 +45,6 @@ import mage.Constants.RangeOfInfluence;
import mage.cards.decks.DeckCardLists; import mage.cards.decks.DeckCardLists;
import mage.client.MageFrame; import mage.client.MageFrame;
import mage.client.chat.ChatPanel; import mage.client.chat.ChatPanel;
import mage.client.components.MageComponents;
import mage.client.components.MageUI; import mage.client.components.MageUI;
import mage.client.game.GamePanel; import mage.client.game.GamePanel;
import mage.client.util.Config; import mage.client.util.Config;
@ -130,6 +128,16 @@ public class Session {
} }
} }
public void ack(String message) {
try {
server.ack(message, sessionId);
} catch (RemoteException ex) {
handleRemoteException(ex);
} catch (MageException ex) {
handleMageException(ex);
}
}
public boolean isConnected() { public boolean isConnected() {
return server != null; return server != null;
} }

View file

@ -48,6 +48,7 @@ public interface Server extends Remote, CallbackServer {
public UUID registerClient(String userName, UUID clientId) throws RemoteException, MageException; public UUID registerClient(String userName, UUID clientId) throws RemoteException, MageException;
public void deregisterClient(UUID sessionId) throws RemoteException, MageException; public void deregisterClient(UUID sessionId) throws RemoteException, MageException;
public void ack(String message, UUID sessionId) throws RemoteException, MageException;
public ServerState getServerState() throws RemoteException, MageException; public ServerState getServerState() throws RemoteException, MageException;

View file

@ -1,5 +1,5 @@
# Default global logging level. # Default global logging level.
.level=FINE .level=FINER
# Set the default logging level for new ConsoleHandler instances # Set the default logging level for new ConsoleHandler instances
java.util.logging.ConsoleHandler.level = ALL java.util.logging.ConsoleHandler.level = ALL

View file

@ -54,7 +54,6 @@ import mage.server.game.ReplayManager;
import mage.server.game.TableManager; import mage.server.game.TableManager;
import mage.util.Logging; import mage.util.Logging;
import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageColor;
import mage.view.GameTypeView;
import mage.view.TableView; import mage.view.TableView;
/** /**
@ -91,6 +90,11 @@ public class ServerImpl extends RemoteServer implements Server {
return SessionManager.getInstance().getSession(sessionId).callback(); return SessionManager.getInstance().getSession(sessionId).callback();
} }
@Override
public void ack(String message, UUID sessionId) throws RemoteException, MageException {
SessionManager.getInstance().getSession(sessionId).ack(message);
}
@Override @Override
public UUID registerClient(String userName, UUID clientId) throws MageException, RemoteException { public UUID registerClient(String userName, UUID clientId) throws MageException, RemoteException {
@ -447,39 +451,6 @@ public class ServerImpl extends RemoteServer implements Server {
return null; return null;
} }
// @Override
// public List<GameTypeView> getGameTypes() throws MageException {
// try {
// return GameFactory.getInstance().getGameTypes();
// }
// catch (Exception ex) {
// handleException(ex);
// }
// return null;
// }
//
// @Override
// public String[] getPlayerTypes() throws MageException {
// try {
// return PlayerFactory.getInstance().getPlayerTypes().toArray(new String[0]);
// }
// catch (Exception ex) {
// handleException(ex);
// }
// return null;
// }
//
// @Override
// public String[] getDeckTypes() throws MageException {
// try {
// return DeckValidatorFactory.getInstance().getDeckTypes().toArray(new String[0]);
// }
// catch (Exception ex) {
// handleException(ex);
// }
// return null;
// }
@Override @Override
public void cheat(UUID gameId, UUID sessionId, UUID playerId, DeckCardLists deckList) throws MageException { public void cheat(UUID gameId, UUID sessionId, UUID playerId, DeckCardLists deckList) throws MageException {
try { try {

View file

@ -49,6 +49,7 @@ public class Session {
private UUID clientId; private UUID clientId;
private String username; private String username;
private int messageId = 0; private int messageId = 0;
private String ackMessage;
private final CallbackServerSession callback = new CallbackServerSession(); private final CallbackServerSession callback = new CallbackServerSession();
public Session(String userName, UUID clientId) { public Session(String userName, UUID clientId) {
@ -77,11 +78,11 @@ public class Session {
return null; return null;
} }
public synchronized void fireCallback(ClientCallback call) { public synchronized void fireCallback(final ClientCallback call) {
call.setMessageId(messageId++);
if (logger.isLoggable(Level.FINE))
logger.fine(sessionId + " - " + call.getMessageId() + " - " + call.getMethod());
try { try {
call.setMessageId(messageId++);
if (logger.isLoggable(Level.FINE))
logger.fine(sessionId + " - " + call.getMessageId() + " - " + call.getMethod());
callback.setCallback(call); callback.setCallback(call);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
logger.log(Level.SEVERE, null, ex); logger.log(Level.SEVERE, null, ex);
@ -100,6 +101,18 @@ public class Session {
fireCallback(new ClientCallback("replayGame", null)); fireCallback(new ClientCallback("replayGame", null));
} }
public void ack(String message) {
this.ackMessage = message;
}
public String getAckMessage() {
return ackMessage;
}
public void clearAck() {
this.ackMessage = "";
}
public String getUsername() { public String getUsername() {
return username; return username;
} }

View file

@ -165,10 +165,15 @@ public class GameController implements GameCallback {
GameSession gameSession = new GameSession(game, sessionId, playerId); GameSession gameSession = new GameSession(game, sessionId, playerId);
gameSessions.put(playerId, gameSession); gameSessions.put(playerId, gameSession);
logger.info("player " + playerId + " has joined game " + game.getId()); logger.info("player " + playerId + " has joined game " + game.getId());
// gameSession.init(getGameView(playerId));
ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(playerId).getName() + " has joined the game", MessageColor.BLACK); ChatManager.getInstance().broadcast(chatId, "", game.getPlayer(playerId).getName() + " has joined the game", MessageColor.BLACK);
if (allJoined()) { if (allJoined()) {
startGame(); ThreadExecutor.getInstance().getRMIExecutor().execute(
new Runnable() {
@Override
public void run() {
startGame();
}
});
} }
} }
@ -177,6 +182,8 @@ public class GameController implements GameCallback {
for (final Entry<UUID, GameSession> entry: gameSessions.entrySet()) { for (final Entry<UUID, GameSession> entry: gameSessions.entrySet()) {
if (!entry.getValue().init(getGameView(entry.getKey()))) { if (!entry.getValue().init(getGameView(entry.getKey()))) {
logger.severe("Unable to initialize client"); logger.severe("Unable to initialize client");
//TODO: generate client error message
return;
} }
} }
GameWorker worker = new GameWorker(game, this); GameWorker worker = new GameWorker(game, this);

View file

@ -60,13 +60,23 @@ public class GameWatcher {
if (!killed) { if (!killed) {
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) { if (session != null) {
session.clearAck();
session.fireCallback(new ClientCallback("gameInit", gameView)); session.fireCallback(new ClientCallback("gameInit", gameView));
return true; if (waitForAck("gameInit"))
return true;
} }
} }
return false; return false;
} }
public boolean waitForAck(String message) {
Session session = SessionManager.getInstance().getSession(sessionId);
do {
//TODO: add timeout
} while (!session.getAckMessage().equals(message) && !killed);
return true;
}
public void update(final GameView gameView) { public void update(final GameView gameView) {
if (!killed) { if (!killed) {
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);