/** * Used whenever a player exits from the game. The most recent information stored for the player * will be saved into the database and any ties with the server will be removed as well. */ public void removePlayerData() { if (activeObjects.containsKey(Lobby.class)) { LobbyManager.getInstance().removeUser(getActiveObject(Lobby.class), player.getID()); } try { player.getSaveTimer().finish(); PlayerDAO.updateLogout(player.getID()); } catch (SQLException ex) { Log.println_e(ex.getMessage()); } GameServer.getInstance().removeActivePlayer(player.getID()); ResponseExitGame responseExitGame = new ResponseExitGame(); responseExitGame.setUserID(player.getID()); NetworkManager.addResponseForAllOnlinePlayers(player.getID(), responseExitGame); ResponseChat responseChat = new ResponseChat(); responseChat.setMessage("[" + player.getUsername() + "] has logged off."); NetworkManager.addResponseForAllOnlinePlayers(player.getID(), responseChat); ResponseGetPlayers responsePlayers = new ResponseGetPlayers(); responsePlayers.setPlayers(GameServer.getInstance().getActivePlayers()); NetworkManager.addResponseForAllOnlinePlayers(player.getID(), responsePlayers); Log.printf("User '%s' has logged off.", player.getUsername()); }
/** * Holds the main loop that processes incoming requests by first identifying its type, then * interpret the following data in each determined request class. Queued up responses created from * each request class will be sent after the request is finished processing. * * <p>The loop exits whenever the isPlaying flag is set to false. One of these occurrences is * triggered by a timeout. A timeout occurs whenever no activity is picked up from the client such * as being disconnected. */ @Override public void run() { long lastActivity = System.currentTimeMillis(); short requestCode = -1; while (!isDone) { try { // Extract the size of the package from the data stream short requestLength = DataReader.readShort(dataInputStream); if (requestLength > 0) { lastActivity = System.currentTimeMillis(); // Separate the remaining package from the data stream byte[] buffer = new byte[requestLength]; inputStream.read(buffer, 0, requestLength); DataInputStream dataInput = new DataInputStream(new ByteArrayInputStream(buffer)); // Extract the request code number requestCode = DataReader.readShort(dataInput); // Determine the type of request GameRequest request = GameRequestTable.get(requestCode); // If the request exists, process like following: if (request != null) { request.setGameClient(this); // Pass input stream to the request object request.setDataInputStream(dataInput); // Parse the input stream request.parse(); // Interpret the data request.doBusiness(); try { // Retrieve any responses created by the request object for (GameResponse response : request.getResponses()) { // Transform the response into bytes and pass it into the output stream send(response); } } catch (IOException ex) { Log.printf_e("Client %s connection lost", session_id); isDone = true; } } } else { // If there was no activity for the last moments, exit loop if ((System.currentTimeMillis() - lastActivity) / 1000 >= Constants.TIMEOUT_SECONDS) { isDone = true; } } } catch (Exception ex) { Log.printf_e("Request [%d] Error:", requestCode); Log.println_e(ex.getMessage()); Log.println_e("---"); ex.printStackTrace(); } } if (player != null) { removePlayerData(); } // Remove this GameClient from the server GameServer.getInstance().deletePlayerThreadOutOfActiveThreads(session_id); Log.printf("Client %s has ended", session_id); }