From bae7f154dfa946e4e11810599d90fb9d39005426 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sun, 13 Aug 2017 16:22:18 +0200 Subject: [PATCH] Changed user disconnect handling. The user in the server is no longer deleted directly after connection problem, disconnect or quit. The user object remains now for 8 minutes so the rejoin not possible after disconnect problem should be solved (I hope so). We will see. Also fixed the problem, that the table panel was not shown, if a player disconected and reconected. --- .../src/main/java/mage/client/MageFrame.java | 22 +++++- .../src/main/java/mage/view/UserView.java | 8 +- .../mage/server/console/ConsolePanel.java | 39 +++++----- Mage.Server/config/config.xml | 2 +- .../main/java/mage/server/MageServerImpl.java | 17 +---- .../src/main/java/mage/server/Session.java | 51 +++++-------- .../main/java/mage/server/SessionManager.java | 50 ++++++------- .../src/main/java/mage/server/User.java | 71 +++++++++++------- .../main/java/mage/server/UserManager.java | 75 ++++++++++++++++--- .../java/mage/server/game/GamesRoomImpl.java | 55 +++++++------- 10 files changed, 220 insertions(+), 170 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/MageFrame.java b/Mage.Client/src/main/java/mage/client/MageFrame.java index 8fa1cdebb4..ec8b0a61d9 100644 --- a/Mage.Client/src/main/java/mage/client/MageFrame.java +++ b/Mage.Client/src/main/java/mage/client/MageFrame.java @@ -1022,8 +1022,9 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { // Show the tables pane if there wasn't already an active pane MagePane topPanebefore = getTopMost(tablesPane); - if (topPanebefore == null) { - setActive(tablesPane); + setActive(tablesPane); + if (topPanebefore != null && topPanebefore != tablesPane) { + setActive(topPanebefore); } } @@ -1189,7 +1190,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { private static final long serialVersionUID = -9104885239063142218L; private ImagePanel backgroundPane; - private TablesPane tablesPane; + private final TablesPane tablesPane; // private CollectionViewerPane collectionViewerPane; public void setStatusText(String status) { @@ -1319,7 +1320,10 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { DownloadPictures.startDownload(null, missingCards); break; case CLIENT_DISCONNECT: - SessionHandler.disconnect(false); + if (SessionHandler.isConnected()) { + endTables(); + SessionHandler.disconnect(false); + } tablesPane.clearChat(); showMessage("You have disconnected"); setWindowTitle(); @@ -1347,6 +1351,7 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { break; case CLIENT_EXIT: if (SessionHandler.isConnected()) { + endTables(); SessionHandler.disconnect(false); } CardRepository.instance.closeDB(); @@ -1374,6 +1379,15 @@ public class MageFrame extends javax.swing.JFrame implements MageClient { } } + private void endTables() { + for (UUID gameId : GAMES.keySet()) { + SessionHandler.quitMatch(gameId); + } + for (UUID draftId : DRAFTS.keySet()) { + SessionHandler.quitDraft(draftId); + } + } + public void changeGUISize() { ImageCaches.flush(); setGUISize(); diff --git a/Mage.Common/src/main/java/mage/view/UserView.java b/Mage.Common/src/main/java/mage/view/UserView.java index 1b4a9d082a..73a8057075 100644 --- a/Mage.Common/src/main/java/mage/view/UserView.java +++ b/Mage.Common/src/main/java/mage/view/UserView.java @@ -41,6 +41,7 @@ public class UserView implements Serializable { private final String host; private final String sessionId; private final Date timeConnected; + private final Date lastActivity; private final String gameInfo; private final String userState; private final Date muteChatUntil; @@ -48,11 +49,12 @@ public class UserView implements Serializable { private final String email; private final String userIdStr; - public UserView(String userName, String host, String sessionId, Date timeConnected, String gameInfo, String userState, Date muteChatUntil, String clientVersion, String email, String userIdStr) { + public UserView(String userName, String host, String sessionId, Date timeConnected, Date lastActivity, String gameInfo, String userState, Date muteChatUntil, String clientVersion, String email, String userIdStr) { this.userName = userName; this.host = host; this.sessionId = sessionId; this.timeConnected = timeConnected; + this.lastActivity = lastActivity; this.gameInfo = gameInfo; this.userState = userState; this.muteChatUntil = muteChatUntil; @@ -93,6 +95,10 @@ public class UserView implements Serializable { return timeConnected; } + public Date getLastActivity() { + return lastActivity; + } + public String getEmail() { return email; } diff --git a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java index 072e5673e9..b2c9768a2b 100644 --- a/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java +++ b/Mage.Server.Console/src/main/java/mage/server/console/ConsolePanel.java @@ -33,22 +33,20 @@ */ package mage.server.console; -import mage.remote.Session; -import mage.view.TableView; -import mage.view.UserView; -import org.apache.log4j.Logger; - -import javax.swing.*; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.TableRowSorter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; - +import javax.swing.*; import static javax.swing.JTable.AUTO_RESIZE_NEXT_COLUMN; import static javax.swing.JTable.AUTO_RESIZE_OFF; +import javax.swing.table.AbstractTableModel; +import javax.swing.table.TableRowSorter; +import mage.remote.Session; +import mage.view.TableView; +import mage.view.UserView; +import org.apache.log4j.Logger; /** * @author BetaSteward_at_googlemail.com @@ -359,13 +357,14 @@ class TableUserModel extends AbstractTableModel { public static final int POS_USER_NAME = 0; public static final int POS_HOST = 1; public static final int POS_TIME_CONNECTED = 2; - public static final int POS_SESSION_ID = 3; - public static final int POS_GAME_INFO = 4; - public static final int POS_USER_STATE = 5; - public static final int POS_CHAT_MUTE = 6; - public static final int POS_CLIENT_VERSION = 7; + public static final int POS_LAST_ACTIVITY = 3; + public static final int POS_SESSION_ID = 4; + public static final int POS_GAME_INFO = 5; + public static final int POS_USER_STATE = 6; + public static final int POS_CHAT_MUTE = 7; + public static final int POS_CLIENT_VERSION = 8; - private final String[] columnNames = new String[]{"User Name", "Host", "Time Connected", "SessionId", "Gameinfo", "User state", "Chat mute", "Client Version"}; + private final String[] columnNames = new String[]{"User Name", "Host", "Time Connected", "Last activity", "SessionId", "Gameinfo", "User state", "Chat mute", "Client Version"}; private UserView[] users = new UserView[0]; private static final DateFormat formatterTime = new SimpleDateFormat("HH:mm:ss"); private static final DateFormat formatterTimeStamp = new SimpleDateFormat("yy-M-dd HH:mm:ss"); @@ -394,6 +393,8 @@ class TableUserModel extends AbstractTableModel { return users[arg0].getHost(); case POS_TIME_CONNECTED: return formatterTime.format(users[arg0].getTimeConnected()); + case POS_LAST_ACTIVITY: + return formatterTime.format(users[arg0].getLastActivity()); case POS_SESSION_ID: return users[arg0].getSessionId(); case POS_GAME_INFO: @@ -544,10 +545,8 @@ class UpdateUsersTask extends SwingWorker> { return true; } for (UserView u1 : previousUsers) { - boolean found = false; for (UserView u2 : usersToCheck) { if (u1.getUserName().equals(u2.getUserName())) { - found = true; String s = u1.getUserName() + ',' + u1.getHost(); if (peopleIps.get(s) == null) { logger.warn("Found new user: " + u1.getUserName() + ',' + u1.getHost()); @@ -561,13 +560,9 @@ class UpdateUsersTask extends SwingWorker> { break; } } - if (!found) { - // some new user replaced old one - return true; - } } // seems nothing has been changed - return false; + return true; } @Override diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index f2ae1f3e4a..61efe2a6f6 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -43,7 +43,7 @@ leasePeriod="5000" socketWriteTimeout="10000" maxGameThreads="10" - maxSecondsIdle="600" + maxSecondsIdle="300" minUserNameLength="3" maxUserNameLength="14" invalidUserNamePattern="[^a-z0-9_]" diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index e207bce0d7..a2f346307b 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -1271,22 +1271,7 @@ public class MageServerImpl implements MageServer { @Override public List execute() throws MageException { - List users = new ArrayList<>(); - for (User user : UserManager.instance.getUsers()) { - users.add(new UserView( - user.getName(), - user.getHost(), - user.getSessionId(), - user.getConnectionTime(), - user.getGameInfo(), - user.getUserState().toString(), - user.getChatLockedUntil(), - user.getClientVersion(), - user.getEmail(), - user.getUserIdStr() - )); - } - return users; + return UserManager.instance.getUserInfoList(); } } diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index e06a561335..9ffa412181 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -38,6 +38,7 @@ import mage.interfaces.callback.ClientCallback; import mage.interfaces.callback.ClientCallbackMethod; import mage.players.net.UserData; import mage.players.net.UserGroup; +import static mage.server.DisconnectReason.LostConnection; import mage.server.game.GamesRoom; import mage.server.game.GamesRoomManager; import mage.server.util.ConfigSettings; @@ -270,12 +271,13 @@ public class Session { this.isAdmin = true; User user = UserManager.instance.createUser("Admin", host, null).orElse( UserManager.instance.getUserByName("Admin").get()); - UserData adminUserData = UserData.getDefaultUserDataView(); adminUserData.setGroupId(UserGroup.ADMIN.getGroupId()); user.setUserData(adminUserData); if (!UserManager.instance.connectToSession(sessionId, user.getId())) { logger.info("Error connecting Admin!"); + } else { + user.setUserState(User.UserState.Connected); } this.userId = user.getId(); } @@ -329,39 +331,20 @@ public class Session { // because different threads can activate this public void userLostConnection() { - boolean lockSet = false; - try { - if (lock.tryLock(5000, TimeUnit.MILLISECONDS)) { - lockSet = true; - logger.debug("SESSION LOCK SET sessionId: " + sessionId); - } else { - logger.warn("CAN'T GET LOCK - userId: " + userId + " hold count: " + lock.getHoldCount()); - } - Optional _user = UserManager.instance.getUser(userId); - if (!_user.isPresent()) { - return; //user was already disconnected by other thread - } - User user = _user.get(); - if (!user.isConnected()) { - return; - } - if (!user.getSessionId().equals(sessionId)) { - // user already reconnected with another instance - logger.info("OLD SESSION IGNORED - " + user.getName()); - return; - } - // logger.info("LOST CONNECTION - " + user.getName() + " id: " + userId); - UserManager.instance.disconnect(userId, DisconnectReason.LostConnection); - - } catch (InterruptedException ex) { - logger.error("SESSION LOCK lost connection - userId: " + userId, ex); - } finally { - if (lockSet) { - lock.unlock(); - logger.trace("SESSION LOCK UNLOCK sessionId: " + sessionId); - } + Optional _user = UserManager.instance.getUser(userId); + if (!_user.isPresent()) { + return; //user was already disconnected by other thread + } + User user = _user.get(); + if (!user.isConnected()) { + return; + } + if (!user.getSessionId().equals(sessionId)) { + // user already reconnected with another instance + logger.info("OLD SESSION IGNORED - " + user.getName()); + } else { + // logger.info("LOST CONNECTION - " + user.getName() + " id: " + userId); } - } public void kill(DisconnectReason reason) { @@ -397,7 +380,7 @@ public class Session { logger.warn(" - method: " + call.getMethod()); logger.warn(" - cause: " + getBasicCause(ex).toString()); logger.trace("Stack trace:", ex); - userLostConnection(); + SessionManager.instance.disconnect(sessionId, LostConnection); }); } } diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java index 1b66fce0c1..e32be43897 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManager.java @@ -125,34 +125,30 @@ public enum SessionManager { public void disconnect(String sessionId, DisconnectReason reason) { Session session = sessions.get(sessionId); if (session != null) { - if (reason != DisconnectReason.AdminDisconnect) { - if (!sessions.containsKey(sessionId)) { - // session was removed meanwhile by another thread so we can return - return; - } - logger.debug("DISCONNECT " + reason.toString() + " - sessionId: " + sessionId); - sessions.remove(sessionId); - switch (reason) { - case Disconnected: // regular session end or wrong client version - if (session.getUserId() != null) { // if wrong client version no userId is set - session.kill(reason); - } - break; - case SessionExpired: // session ends after no reconnect happens in the defined time span - session.kill(reason); - break; - case LostConnection: // user lost connection - session expires countdaoun starts - session.userLostConnection(); - break; - case ConnectingOtherInstance: - break; - default: - logger.trace("endSession: unexpected reason " + reason.toString() + " - sessionId: " + sessionId); - } - } else { - sessions.remove(sessionId); - session.kill(reason); + if (!sessions.containsKey(sessionId)) { + // session was removed meanwhile by another thread so we can return + return; } + logger.debug("DISCONNECT " + reason.toString() + " - sessionId: " + sessionId); + sessions.remove(sessionId); + switch (reason) { + case AdminDisconnect: + session.kill(reason); + break; + case ConnectingOtherInstance: + case Disconnected: // regular session end or wrong client version + UserManager.instance.disconnect(session.getUserId(), reason); + break; + case SessionExpired: // session ends after no reconnect happens in the defined time span + break; + case LostConnection: // user lost connection - session expires countdown starts + session.userLostConnection(); + UserManager.instance.disconnect(session.getUserId(), reason); + break; + default: + logger.trace("endSession: unexpected reason " + reason.toString() + " - sessionId: " + sessionId); + } + } } diff --git a/Mage.Server/src/main/java/mage/server/User.java b/Mage.Server/src/main/java/mage/server/User.java index 388d85bd22..523a892671 100644 --- a/Mage.Server/src/main/java/mage/server/User.java +++ b/Mage.Server/src/main/java/mage/server/User.java @@ -64,7 +64,10 @@ public class User { public enum UserState { - Created, Connected, Disconnected, Reconnected, Expired + Created, // Used if user is created an not connected to the session + Connected, // Used if user is correctly connected + Disconnected, // Used if the user lost connection + Offline // set if the user was disconnected and expired or regularly left XMage. Removed is the user later after some time } private final UUID userId; @@ -164,7 +167,7 @@ public class User { userState = UserState.Connected; logger.trace("USER - created: " + userName + " id: " + userId); } else { - userState = UserState.Reconnected; + userState = UserState.Connected; reconnect(); logger.trace("USER - reconnected: " + userName + " id: " + userId); } @@ -212,23 +215,14 @@ public class User { } public boolean isConnected() { - return userState == UserState.Connected || userState == UserState.Reconnected; + return userState == UserState.Connected; } public String getDisconnectDuration() { long secondsDisconnected = getSecondsDisconnected(); - long secondsLeft; - String sign = ""; - if (secondsDisconnected > (3 * 60)) { - sign = "-"; - secondsLeft = secondsDisconnected - (3 * 60); - } else { - secondsLeft = (3 * 60) - secondsDisconnected; - } - - int minutes = (int) secondsLeft / 60; - int seconds = (int) secondsLeft % 60; - return new StringBuilder(sign).append(Integer.toString(minutes)).append(':').append(seconds > 9 ? seconds : '0' + Integer.toString(seconds)).toString(); + int minutes = (int) secondsDisconnected / 60; + int seconds = (int) secondsDisconnected % 60; + return Integer.toString(minutes) + ':' + (seconds > 9 ? seconds : '0' + Integer.toString(seconds)); } public long getSecondsDisconnected() { @@ -239,6 +233,20 @@ public class User { return connectionTime; } + public Date getLastActivity() { + return lastActivity; + } + + public String getConnectionDuration() { + int minutes = (int) SystemUtil.getDateDiff(connectionTime, new Date(), TimeUnit.SECONDS) / 60; + int hours = 0; + if (minutes > 59) { + hours = (int) minutes / 60; + minutes = minutes - (hours * 60); + } + return Integer.toString(hours) + ":" + (minutes > 9 ? Integer.toString(minutes) : '0' + Integer.toString(minutes)); + } + public void fireCallback(final ClientCallback call) { if (isConnected()) { SessionManager.instance.getSession(sessionId).ifPresent(session @@ -331,19 +339,17 @@ public class User { } lastActivity = new Date(); if (userState == UserState.Disconnected) { // this can happen if user reconnects very fast after disconnect - userState = UserState.Reconnected; + userState = UserState.Connected; } } public boolean isExpired(Date expired) { if (lastActivity.before(expired)) { logger.trace(userName + " is expired!"); - userState = UserState.Expired; return true; } logger.trace("isExpired: User " + userName + " lastActivity: " + lastActivity + " expired: " + expired); return false; - /*userState == UserState.Disconnected && */ } @@ -511,11 +517,15 @@ public class User { tournament++; break; } - - if (!isConnected()) { - tournamentPlayer.setDisconnectInfo(" (discon. " + getDisconnectDuration() + ')'); - } else { - tournamentPlayer.setDisconnectInfo(""); + switch (getUserState()) { + case Disconnected: + tournamentPlayer.setDisconnectInfo(" (discon. " + getDisconnectDuration() + ')'); + break; + case Offline: + tournamentPlayer.setDisconnectInfo(" Offline"); + break; + default: + tournamentPlayer.setDisconnectInfo(""); } } } else { @@ -586,11 +596,18 @@ public class User { return userState; } + public void setUserState(UserState userState) { + this.userState = userState; + } + public String getPingInfo() { - if (isConnected()) { - return pingInfo; - } else { - return " (discon. " + getDisconnectDuration() + ')'; + switch (getUserState()) { + case Disconnected: + return " (discon. " + getDisconnectDuration() + ')'; + case Offline: + return " Offline"; + default: + return pingInfo + " " + getConnectionDuration(); } } diff --git a/Mage.Server/src/main/java/mage/server/UserManager.java b/Mage.Server/src/main/java/mage/server/UserManager.java index f33b3fe054..0379684bd1 100644 --- a/Mage.Server/src/main/java/mage/server/UserManager.java +++ b/Mage.Server/src/main/java/mage/server/UserManager.java @@ -33,6 +33,7 @@ import mage.server.User.UserState; import mage.server.record.UserStats; import mage.server.record.UserStatsRepository; import mage.server.util.ThreadExecutor; +import mage.view.UserView; import org.apache.log4j.Logger; /** @@ -44,7 +45,12 @@ import org.apache.log4j.Logger; public enum UserManager { instance; + private static final Logger logger = Logger.getLogger(UserManager.class); + protected final ScheduledExecutorService expireExecutor = Executors.newSingleThreadScheduledExecutor(); + protected final ScheduledExecutorService userListExecutor = Executors.newSingleThreadScheduledExecutor(); + + private List userInfoList = new ArrayList<>(); private static final Logger LOGGER = Logger.getLogger(UserManager.class); @@ -54,6 +60,8 @@ public enum UserManager { UserManager() { expireExecutor.scheduleAtFixedRate(this::checkExpired, 60, 60, TimeUnit.SECONDS); + + userListExecutor.scheduleAtFixedRate(this::updateUserInfoList, 4, 4, TimeUnit.SECONDS); } public Optional createUser(String userName, String host, AuthorizedUser authorizedUser) { @@ -100,10 +108,16 @@ public enum UserManager { } public void disconnect(UUID userId, DisconnectReason reason) { - if (userId != null) { - getUser(userId).ifPresent(user -> user.setSessionId(""));// Session will be set again with new id if user reconnects + Optional user = UserManager.instance.getUser(userId); + if (user.isPresent()) { + user.get().setSessionId(""); + if (reason == DisconnectReason.Disconnected) { + user.get().setUserState(UserState.Offline); + } + } + if (userId != null) { + ChatManager.instance.removeUser(userId, reason); } - ChatManager.instance.removeUser(userId, reason); } public boolean isAdmin(UUID userId) { @@ -148,18 +162,57 @@ public enum UserManager { } /** - * Is the connection lost for more than 3 minutes, the user will be removed - * (within 3 minutes the user can reconnect) + * Is the connection lost for more than 3 minutes, the user will be set to + * offline status. The user will be removed in validity check after 15 + * minutes of no activities + * */ private void checkExpired() { - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.MINUTE, -3); - List usersToCheck = new ArrayList<>(users.values()); - for (User user : usersToCheck) { - if (user.getUserState() != UserState.Expired && user.isExpired(calendar.getTime())) { - removeUser(user.getId(), DisconnectReason.SessionExpired); + Calendar calendarExp = Calendar.getInstance(); + calendarExp.add(Calendar.MINUTE, -3); + Calendar calendarRemove = Calendar.getInstance(); + calendarRemove.add(Calendar.MINUTE, -8); + List toRemove = new ArrayList<>(); + for (User user : users.values()) { + if (user.getUserState() == UserState.Disconnected || user.getUserState() == UserState.Offline + && user.isExpired(calendarExp.getTime())) { + user.setUserState(UserState.Offline); + } + if (user.getUserState() == UserState.Offline && user.isExpired(calendarRemove.getTime())) { + toRemove.add(user); } } + for (User user : toRemove) { + removeUser(user.getId(), DisconnectReason.SessionExpired); + } + } + + /** + * This method recreated the user list that will be send to all clients + * + */ + private void updateUserInfoList() { + List newUserInfoList = new ArrayList<>(); + for (User user : UserManager.instance.getUsers()) { + newUserInfoList.add(new UserView( + user.getName(), + user.getHost(), + user.getSessionId(), + user.getConnectionTime(), + user.getLastActivity(), + user.getGameInfo(), + user.getUserState().toString(), + user.getChatLockedUntil(), + user.getClientVersion(), + user.getEmail(), + user.getUserIdStr() + )); + } + userInfoList = newUserInfoList; + } + + public List getUserInfoList() { + return userInfoList; } public void handleException(Exception ex) { diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java index 4c4f116a2a..100190f24a 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java @@ -27,6 +27,12 @@ */ package mage.server.game; +import java.io.Serializable; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import mage.MageException; import mage.cards.decks.DeckCardLists; import mage.constants.TableState; @@ -48,13 +54,6 @@ import mage.view.TableView; import mage.view.UsersView; import org.apache.log4j.Logger; -import java.io.Serializable; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - /** * @author BetaSteward_at_googlemail.com */ @@ -107,26 +106,28 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable { matchView = matchList; List users = new ArrayList<>(); for (User user : UserManager.instance.getUsers()) { - try { - users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), - user.getMatchHistory(), user.getMatchQuitRatio(), user.getTourneyHistory(), - user.getTourneyQuitRatio(), user.getGameInfo(), user.getPingInfo(), - user.getUserData().getGeneralRating(), user.getUserData().getConstructedRating(), - user.getUserData().getLimitedRating())); - } catch (Exception ex) { - LOGGER.fatal("User update exception: " + user.getName() + " - " + ex.toString(), ex); - users.add(new UsersView( - (user.getUserData() != null && user.getUserData().getFlagName() != null) ? user.getUserData().getFlagName() : "world", - user.getName() != null ? user.getName() : "", - user.getMatchHistory() != null ? user.getMatchHistory() : "", - user.getMatchQuitRatio(), - user.getTourneyHistory() != null ? user.getTourneyHistory() : "", - user.getTourneyQuitRatio(), - "[exception]", - user.getPingInfo() != null ? user.getPingInfo() : "", - user.getUserData() != null ? user.getUserData().getGeneralRating() : 0, - user.getUserData() != null ? user.getUserData().getConstructedRating() : 0, - user.getUserData() != null ? user.getUserData().getLimitedRating() : 0)); + if (user.getUserState() != User.UserState.Offline && !user.getName().equals("Admin")) { + try { + users.add(new UsersView(user.getUserData().getFlagName(), user.getName(), + user.getMatchHistory(), user.getMatchQuitRatio(), user.getTourneyHistory(), + user.getTourneyQuitRatio(), user.getGameInfo(), user.getPingInfo(), + user.getUserData().getGeneralRating(), user.getUserData().getConstructedRating(), + user.getUserData().getLimitedRating())); + } catch (Exception ex) { + LOGGER.fatal("User update exception: " + user.getName() + " - " + ex.toString(), ex); + users.add(new UsersView( + (user.getUserData() != null && user.getUserData().getFlagName() != null) ? user.getUserData().getFlagName() : "world", + user.getName() != null ? user.getName() : "", + user.getMatchHistory() != null ? user.getMatchHistory() : "", + user.getMatchQuitRatio(), + user.getTourneyHistory() != null ? user.getTourneyHistory() : "", + user.getTourneyQuitRatio(), + "[exception]", + user.getPingInfo() != null ? user.getPingInfo() : "", + user.getUserData() != null ? user.getUserData().getGeneralRating() : 0, + user.getUserData() != null ? user.getUserData().getConstructedRating() : 0, + user.getUserData() != null ? user.getUserData().getLimitedRating() : 0)); + } } }