Some changes to user / session / chat / tournament handling (not all tested yet).

This commit is contained in:
LevelX2 2014-08-28 17:18:36 +02:00
parent e8cfb2231c
commit d3a2ba683c
13 changed files with 105 additions and 86 deletions

View file

@ -171,6 +171,17 @@ public class ChatManager {
} }
} }
public void sendReconnectMessage(UUID userId) {
User user = UserManager.getInstance().getUser(userId);
if (user != null) {
for (ChatSession chat: chatSessions.values()) {
if (chat.hasUser(userId)) {
chat.broadcast(null, user.getName() + " has reconnected", MessageColor.BLUE, true, MessageType.STATUS);
}
}
}
}
public void removeUser(UUID userId, DisconnectReason reason) { public void removeUser(UUID userId, DisconnectReason reason) {
for (ChatSession chat: chatSessions.values()) { for (ChatSession chat: chatSessions.values()) {
chat.kill(userId, reason); chat.kill(userId, reason);

View file

@ -64,7 +64,7 @@ public class ChatSession {
if (user != null && !clients.containsKey(userId)) { if (user != null && !clients.containsKey(userId)) {
String userName = user.getName(); String userName = user.getName();
clients.put(userId, userName); clients.put(userId, userName);
broadcast(null, new StringBuilder(userName).append(" has joined").toString(), MessageColor.BLUE, true, MessageType.STATUS); broadcast(null, userName + " has joined", MessageColor.BLUE, true, MessageType.STATUS);
logger.debug(userName + " joined chat " + chatId); logger.debug(userName + " joined chat " + chatId);
} }
} }
@ -78,8 +78,10 @@ public class ChatSession {
} }
if (reason != null && userId != null && clients.containsKey(userId)) { if (reason != null && userId != null && clients.containsKey(userId)) {
String userName = clients.get(userId); String userName = clients.get(userId);
clients.remove(userId); if (!reason.equals(DisconnectReason.LostConnection)) { // for lost connection the user will be reconnected or session expire so no remove of chat yet
logger.debug(userName + "(" + reason.toString() + ")" + " removed from chatId " + chatId); clients.remove(userId);
logger.debug(userName + "(" + reason.toString() + ")" + " removed from chatId " + chatId);
}
String message; String message;
switch (reason) { switch (reason) {
case Disconnected: case Disconnected:
@ -151,8 +153,7 @@ public class ChatSession {
user.fireCallback(new ClientCallback("chatMessage", chatId, new ChatMessage(username, msg, time, color, messageType, soundToPlay))); user.fireCallback(new ClientCallback("chatMessage", chatId, new ChatMessage(username, msg, time, color, messageType, soundToPlay)));
} }
else { else {
logger.debug("user not found - killed from chat session - userId: " + userId +" chatId: " +chatId); logger.debug("user not found but chat still exists - userId: " + userId +" chatId: " +chatId);
kill(userId, DisconnectReason.CleaningUp);
} }
} }
} }

View file

@ -202,13 +202,19 @@ public class Main {
if (throwable instanceof ClientDisconnectedException) { if (throwable instanceof ClientDisconnectedException) {
// Seems like the random diconnects from public server land here and should not be handled as explicit disconnects // Seems like the random diconnects from public server land here and should not be handled as explicit disconnects
// So it should be possible to reconnect to server and continue games if DisconnectReason is set to LostConnection // So it should be possible to reconnect to server and continue games if DisconnectReason is set to LostConnection
//SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.Disconnected); //SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.Disconnected);
SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.LostConnection); SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.LostConnection);
logger.debug("Client disconnected - " + sessionInfo + " throwable: " + throwable == null ? "null" :throwable.getMessage()); logger.info("CLIENT DISCONNECTED - " + sessionInfo, throwable);
if (logger.isDebugEnabled()) {
throwable.printStackTrace();
}
} }
else { else {
SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.LostConnection); SessionManager.getInstance().disconnect(client.getSessionId(), DisconnectReason.LostConnection);
logger.info("Connection to client lost - " + sessionInfo + " throwable: " + (throwable == null ? "null" :throwable.getMessage())); logger.info("CONNECTION LOST - " + sessionInfo, throwable);
if (logger.isDebugEnabled()) {
throwable.printStackTrace();
}
} }
} }
} }

View file

@ -98,9 +98,10 @@ public class Session {
user = UserManager.getInstance().findUser(userName); user = UserManager.getInstance().findUser(userName);
if (user.getHost().equals(host)) { if (user.getHost().equals(host)) {
user.updateLastActivity(); // minimizes possible expiration user.updateLastActivity(); // minimizes possible expiration
this.userId = user.getId();
if (user.getSessionId().isEmpty()) { if (user.getSessionId().isEmpty()) {
// TODO Send Chat message to tables (user is not registered yet) // TODO Send Chat message to tables (user is not registered yet)
// ChatManager.getInstance().broadcast([CHAT ID TABLES], "has reconnected", ChatMessage.MessageColor.GREEN); ChatManager.getInstance().sendReconnectMessage(user.getId());
logger.info("Reconnecting session for " + userName); logger.info("Reconnecting session for " + userName);
} else { } else {
//throw new MageException("This machine is already connected"); //throw new MageException("This machine is already connected");
@ -195,24 +196,13 @@ public class Session {
return sessionId; return sessionId;
} }
//synchronized public void userLostConnection() { // because different threads can activate this
public void userLostConnection() { synchronized public void userLostConnection() {
User user = UserManager.getInstance().getUser(userId); User user = UserManager.getInstance().getUser(userId);
if (user == null) { if (user == null || !user.isConnected()) {
logger.error("User for session not found sessionId: " + sessionId + " userId: " +userId); return; //user was already disconnected by other thread
// can happen if user from same host sign in multiple time with multiple clients, after he disconnects with one client
return;
}
if (user.getSessionId().isEmpty()) {
logger.debug("User was already disconnected sessionId: " + sessionId + " userId: " +userId);
return;
}
if (logger.isInfoEnabled()) {
StringBuilder sb = new StringBuilder(user.getName());
sb.append(" lost connection - userId: ").append(userId);
sb.append(" sessionId: ").append(sessionId);
logger.info(sb);
} }
logger.info("LOST CONNECTION - " + user.getName());
UserManager.getInstance().disconnect(userId, DisconnectReason.LostConnection); UserManager.getInstance().disconnect(userId, DisconnectReason.LostConnection);
} }
@ -225,7 +215,10 @@ public class Session {
call.setMessageId(messageId++); call.setMessageId(messageId++);
callbackHandler.handleCallbackOneway(new Callback(call)); callbackHandler.handleCallbackOneway(new Callback(call));
} catch (HandleCallbackException ex) { } catch (HandleCallbackException ex) {
logger.info(new StringBuilder("Session of userId ").append(userId).append(" callback exception: ").append(ex.getMessage()).toString()); logger.info("CALLBACK EXCEPTION - userId " + userId, ex);
if (logger.isDebugEnabled()) {
ex.printStackTrace();
}
userLostConnection(); userLostConnection();
} }
} }

View file

@ -111,32 +111,37 @@ public class SessionManager {
return false; return false;
} }
public synchronized void disconnect(String sessionId, DisconnectReason reason) { public void disconnect(String sessionId, DisconnectReason reason) {
Session session = sessions.get(sessionId); Session session = sessions.get(sessionId);
if (session != null) { if (session != null) {
sessions.remove(sessionId); synchronized (session) {
switch (reason) { if (!sessions.containsKey(sessionId)) {
case Disconnected: // session was removed meanwhile by another thread so we can return
session.kill(reason); return;
LogServiceImpl.instance.log(LogKeys.KEY_SESSION_KILLED, sessionId); }
break; sessions.remove(sessionId);
case SessionExpired: switch (reason) {
session.kill(reason); case Disconnected:
LogServiceImpl.instance.log(LogKeys.KEY_SESSION_EXPIRED, sessionId); session.kill(reason);
break; LogServiceImpl.instance.log(LogKeys.KEY_SESSION_KILLED, sessionId);
case AdminDisconnect: break;
session.kill(reason); case SessionExpired:
break; session.kill(reason);
case LostConnection: LogServiceImpl.instance.log(LogKeys.KEY_SESSION_EXPIRED, sessionId);
session.userLostConnection(); break;
LogServiceImpl.instance.log(LogKeys.KEY_SESSION_DISCONNECTED, sessionId); case AdminDisconnect:
break; session.kill(reason);
default: break;
logger.error("endSession: unexpected reason " + reason.toString() + " - sessionId: "+ sessionId); case LostConnection:
session.userLostConnection();
LogServiceImpl.instance.log(LogKeys.KEY_SESSION_DISCONNECTED, sessionId);
break;
default:
logger.error("endSession: unexpected reason " + reason.toString() + " - sessionId: "+ sessionId);
}
} }
} else { }
logger.error("endSession: could not find session with id " + sessionId);
}
} }
public Map<String, Session> getSessions() { public Map<String, Session> getSessions() {

View file

@ -184,7 +184,7 @@ public class TableController {
return true; return true;
} else { } else {
throw new GameException("Playertype " + seat.getPlayerType().toString() + " could not be created."); throw new GameException("Playertype " + seat.getPlayerType() + " could not be created.");
} }
} }

View file

@ -155,7 +155,7 @@ public class User {
return connectionTime; return connectionTime;
} }
public synchronized void fireCallback(final ClientCallback call) { public void fireCallback(final ClientCallback call) {
if (isConnected()) { if (isConnected()) {
Session session = SessionManager.getInstance().getSession(sessionId); Session session = SessionManager.getInstance().getSession(sessionId);
if (session != null) { if (session != null) {
@ -373,22 +373,25 @@ public class User {
if (table.isTournament()) { if (table.isTournament()) {
if (tableEntry.getKey() != null) { if (tableEntry.getKey() != null) {
TournamentPlayer tournamentPlayer = table.getTournament().getPlayer(tableEntry.getKey()); TournamentPlayer tournamentPlayer = table.getTournament().getPlayer(tableEntry.getKey());
if (tournamentPlayer != null && !tournamentPlayer.isEliminated()) { if (tournamentPlayer != null) {
switch (table.getState()) { if (!tournamentPlayer.isEliminated()) {
case CONSTRUCTING: switch (table.getState()) {
construct++; case CONSTRUCTING:
break; construct++;
case DRAFTING: break;
draft++; case DRAFTING:
break; draft++;
case DUELING: break;
tournament++; case DUELING:
break; tournament++;
} break;
if (!isConnected()) { }
tournamentPlayer.setDisconnectInfo(disconnectInfo);
} else { if (!isConnected()) {
tournamentPlayer.setDisconnectInfo(""); tournamentPlayer.setDisconnectInfo(disconnectInfo);
} else {
tournamentPlayer.setDisconnectInfo("");
}
} }
} else { } else {
// can happen if tournamet has just ended // can happen if tournamet has just ended

View file

@ -63,10 +63,11 @@ public class TournamentManager {
} }
public void quit(UUID tournamentId, UUID userId) { public void quit(UUID tournamentId, UUID userId) {
if (controllers.containsKey(tournamentId)) { TournamentController tournamentController = controllers.get(tournamentId);
controllers.get(tournamentId).quit(userId); if (tournamentController != null) {
tournamentController.quit(userId);
} else { } else {
Logger.getLogger(TournamentManager.class).error("TournamentManager.quit tournament controller missing tournamentid: " + tournamentId + " userId: " + userId); Logger.getLogger(TournamentManager.class).error("Tournament controller missing tournamentid: " + tournamentId + " userId: " + userId);
} }
} }

View file

@ -176,7 +176,7 @@ public class TournamentSession {
} }
private void cleanUp() { private void cleanUp() {
if (!futureTimeout.isDone()) { if (futureTimeout != null && !futureTimeout.isDone()) {
futureTimeout.cancel(true); futureTimeout.cancel(true);
} }
} }

View file

@ -67,9 +67,6 @@ public class CandelabraOfTawnos extends CardImpl {
} }
} }
class CandelabraOfTawnosAbility extends ActivatedAbilityImpl implements AdjustingSourceCosts{ class CandelabraOfTawnosAbility extends ActivatedAbilityImpl implements AdjustingSourceCosts{
public CandelabraOfTawnosAbility(){ public CandelabraOfTawnosAbility(){
super(Zone.BATTLEFIELD, new UntapTargetEffect(), new TapSourceCost()); super(Zone.BATTLEFIELD, new UntapTargetEffect(), new TapSourceCost());
@ -109,10 +106,5 @@ class CandelabraOfTawnosAbility extends ActivatedAbilityImpl implements Adjustin
public String getRule(String source) { public String getRule(String source) {
return "{X}, {T}: Untap X target lands"; return "{X}, {T}: Untap X target lands";
} }
}
}

View file

@ -455,6 +455,12 @@ public abstract class GameImpl implements Game, Serializable {
} }
if (remainingPlayers <= 1 || numLosers >= state.getPlayers().size() - 1) { if (remainingPlayers <= 1 || numLosers >= state.getPlayers().size() - 1) {
end(); end();
if (remainingPlayers == 0 && logger.isDebugEnabled()) {
logger.debug("DRAW for gameId: " + getId());
for (Player player: state.getPlayers().values()) {
logger.debug("-- " + player.getName() + " left: " + (player.hasLeft() ? "Y":"N") + " lost: " + (player.hasLost()? "Y":"N"));
}
}
for (Player player: state.getPlayers().values()) { for (Player player: state.getPlayers().values()) {
if (!player.hasLeft() && !player.hasLost()) { if (!player.hasLeft() && !player.hasLost()) {
logger.debug(new StringBuilder("Player ").append(player.getName()).append(" has won gameId: ").append(this.getId())); logger.debug(new StringBuilder("Player ").append(player.getName()).append(" has won gameId: ").append(this.getId()));

View file

@ -444,7 +444,7 @@ public abstract class TournamentImpl implements Tournament {
protected void winners() { protected void winners() {
List<TournamentPlayer> winners = new ArrayList<>(); List<TournamentPlayer> winners = new ArrayList<>();
int pointsWinner = Integer.MIN_VALUE; int pointsWinner = 1; // with less than 1 point you can't win
for(TournamentPlayer tournamentPlayer: this.getPlayers()) { for(TournamentPlayer tournamentPlayer: this.getPlayers()) {
if (pointsWinner < tournamentPlayer.getPoints()) { if (pointsWinner < tournamentPlayer.getPoints()) {
winners.clear(); winners.clear();
@ -454,7 +454,7 @@ public abstract class TournamentImpl implements Tournament {
winners.add(tournamentPlayer); winners.add(tournamentPlayer);
} }
} }
// set winner state for the players with the most points // set winner state for the players with the most points > 0
for (TournamentPlayer tournamentPlayer: winners) { for (TournamentPlayer tournamentPlayer: winners) {
tournamentPlayer.setStateInfo("Winner"); tournamentPlayer.setStateInfo("Winner");
} }

View file

@ -88,6 +88,7 @@ public class TournamentPlayer {
} }
public void setEliminated() { public void setEliminated() {
this.setDisconnectInfo("");
this.setState(TournamentPlayerState.ELIMINATED); this.setState(TournamentPlayerState.ELIMINATED);
this.eliminated = true; this.eliminated = true;
} }