/** * Called when a team's score changes. * * @param teamID the team id * @param teamScore the team score */ public void onTeamScoreChanged(int teamID, int teamScore) { // System.out.println("server: onTeamScoreChanged"); synchronized (getNetworkPlayers()) { for (NetworkPlayer networkPlayer : getNetworkPlayers()) { try { DataOutputStream out = networkPlayer.getOutStream(); synchronized (out) { // Message type out.writeInt(NetworkConstants.S2C.TEAM_SCORE_CHANGE.ordinal()); // Team ID out.writeInt(teamID); // Team score out.writeInt(teamScore); } } catch (IOException e) { removeNetworkPlayer(networkPlayer); continue; } } } }
/** * Called when a client disconnects - removes the player from the server * * @param socket the socket associated with the disconnected player */ public void onSocketDisconnect(Socket socket) { for (NetworkPlayer networkPlayer : this.getNetworkPlayers()) { if (networkPlayer.getSocket() == socket) { removeNetworkPlayer(networkPlayer); break; } } }
/** * Gets the network player associated with a socket * * @param socket the socket * @return the network player */ public NetworkPlayer socketToNetworkPlayer(Socket socket) { for (NetworkPlayer networkPlayer : this.networkPlayers) { if (socket == networkPlayer.getSocket()) { return networkPlayer; } } return null; }
/** This method is called to update the server world */ @Override public void update(int delta) { // Remove network players that are marked to be deleted and add new ones updateNetworkPlayers(); // Do physics physics.update(delta); // Update entities synchronized (this.getEntities()) { for (Entity entity : this.getEntities()) { entity.update(delta); } } // Do networking synchronized (this.networkPlayers) { for (NetworkPlayer networkPlayer : this.networkPlayers) { Socket socket = networkPlayer.getSocket(); if (socket == null) continue; try { broadcastServerTime(networkPlayer); if (this.deadEntities.size() > 0) broadcastDeadEntities(networkPlayer); if (this.newEntities.size() > 0) broadcastNewEntities(networkPlayer); if (this.entityFieldsToBroadcast.size() > 0) broadcastEntityUpdates(networkPlayer); } catch (IOException e) { e.printStackTrace(); removeNetworkPlayer(networkPlayer); } } } // Remove entities that are marked to be deleted deleteDeadEntities(); // this.deadEntities.clear(); this.newEntities.clear(); this.entityFieldsToBroadcast.clear(); }
/** * Sends the new entity information to the network player * * @param networkPlayer the player being contacted * @throws IOException if there is an error writing to the output stream */ private void broadcastNewEntities(NetworkPlayer networkPlayer) throws IOException { System.out.println("sending new entities"); DataOutputStream out = networkPlayer.getOutStream(); synchronized (out) { // Message type out.writeInt(NetworkConstants.S2C.CREATE_ENTITIES.ordinal()); synchronized (this.newEntities) { // Number of entities out.writeInt(this.newEntities.size()); for (Entity entity : this.newEntities) { // entity class name (without shared.entities. prefix) out.writeUTF(entity.getClass().getSimpleName()); // entity properties entity.writeToNetStream(out); } } } }
/** * Called when there is a change in mouse position * * @param socket the socket where the change originated * @throws IOException if there was an error reading from the socket */ public void onMousePosition(Socket socket) throws IOException { NetworkPlayer networkPlayer = socketToNetworkPlayer(socket); Player networkPlayerEntity = networkPlayer.getPlayerEntity(); DataInputStream in = new DataInputStream(socket.getInputStream()); float mouseX = in.readFloat(); float mouseY = in.readFloat(); Vector2f mouseMapPos = new Vector2f(mouseX, mouseY); networkPlayerEntity.calculateAimVec(mouseMapPos, this); // System.out.println("onMousePosition: " + networkPlayer.getPlayerEntity().getID() + "," + // mouseMapPos); }
/** * Sends the server time to the network player * * @param networkPlayer the player being contacted * @throws IOException if there is an error writing to the output stream */ private void broadcastServerTime(NetworkPlayer networkPlayer) throws IOException { DataOutputStream out = networkPlayer.getOutStream(); synchronized (out) { // Message type out.writeInt(NetworkConstants.S2C.SET_SERVER_TIME.ordinal()); // Server time out.writeLong(getTime()); } }
/** Closes all conections and shuts down the server */ public void shutdown() { System.out.println("shutdown server"); for (NetworkPlayer networkPlayer : this.getNetworkPlayers()) { Socket s = networkPlayer.getSocket(); if (s == null) continue; try { s.close(); } catch (IOException e) { e.printStackTrace(); } } if (clientAcceptor != null) clientAcceptor.shutdown(); }
/** * Updates network players list. Adds newly connected players and removes disconnected players. */ private void updateNetworkPlayers() { synchronized (this.networkPlayers) { for (NetworkPlayer networkPlayer : this.newNetworkPlayers) { this.networkPlayers.add(networkPlayer); } for (NetworkPlayer networkPlayer : this.deadNetworkPlayers) { // Remove player from team list Team playerTeam = networkPlayer.getPlayerEntity().getTeam(); if (playerTeam != null) playerTeam.removePlayer(networkPlayer.getPlayerEntity()); // Remove from network players list this.networkPlayers.remove(networkPlayer); } } this.newNetworkPlayers.clear(); this.deadNetworkPlayers.clear(); }
/** * Sends the entity update information to the network player * * @param networkPlayer the player being contacted * @throws IOException if there is an error writing to the output stream */ private void broadcastEntityUpdates(NetworkPlayer networkPlayer) throws IOException { DataOutputStream out = networkPlayer.getOutStream(); synchronized (out) { synchronized (this.entityFieldsToBroadcast) { for (NetworkedEntityField entityField : this.entityFieldsToBroadcast) { // Message type out.writeInt(NetworkConstants.S2C.UPDATE_ENTITY_FIELD.ordinal()); // Entity ID out.writeInt(entityField.getParentEntityID()); // Field ID out.writeInt(entityField.getFieldID()); // Field value entityField.writeToNetStream(out); } } } }
/** * Sends the information of dead entities to the network player * * @param networkPlayer the player being contacted * @throws IOException if there is an error writing to the output stream */ private void broadcastDeadEntities(NetworkPlayer networkPlayer) throws IOException { DataOutputStream out = networkPlayer.getOutStream(); synchronized (out) { // Message type out.writeInt(NetworkConstants.S2C.DELETE_ENTITIES.ordinal()); synchronized (this.deadEntities) { // Number of entities out.writeInt(this.deadEntities.size()); for (Entity entity : this.deadEntities) { // entity id out.writeInt(entity.getID()); } } } }
/** * Called when a client fires their gun. * * @param socket client socket * @throws IOException if there was an error reading from the socket */ public void onGunShotInfo(Socket socket) throws IOException { NetworkPlayer networkPlayer = socketToNetworkPlayer(socket); Player networkPlayerEntity = networkPlayer.getPlayerEntity(); DataInputStream in = new DataInputStream(socket.getInputStream()); // Current mouse position in map coordinates float mouseX = in.readFloat(); float mouseY = in.readFloat(); Vector2f mouseMapPos = new Vector2f(mouseX, mouseY); // List of intersection info int intersectionCount = in.readInt(); ArrayList<EntityIntersectionInfo> intersectionInfoList = null; if (intersectionCount > 0) { intersectionInfoList = new ArrayList<EntityIntersectionInfo>(intersectionCount); // Read intersection info for (int i = 0; i < intersectionCount; i++) { boolean ignore = false; Entity hitEntity = getEntityByID(in.readInt()); if (hitEntity == null) { System.out.println("Invalid intersection info received"); ignore = true; // throw new IOException("Invalid intersection info received"); } EntityIntersectionInfo info = new EntityIntersectionInfo(hitEntity); // List of intersection points int intersectionPointCount = in.readInt(); for (int j = 0; j < intersectionPointCount; j++) { float x = in.readFloat(); float y = in.readFloat(); Vector2f p = new Vector2f(x, y); info.addIntersectionPoint(p); } if (!ignore) { // Store intersection info intersectionInfoList.add(info); } } } if (networkPlayerEntity.getIsDead()) { System.out.println("gun shot when player is dead"); return; } // Network gun shot to other players networkPlayerEntity.calculateAimVec(mouseMapPos, this); // networkPlayerEntity.shoot(); networkPlayerEntity.fireGun(); handleGunShot(networkPlayerEntity, intersectionInfoList); }
/** * Removes a network player from the entity list * * @param networkPlayer the player to be removed */ private void removeNetworkPlayer(NetworkPlayer networkPlayer) { deadNetworkPlayers.add(networkPlayer); addDeadEntity(networkPlayer.getPlayerEntity()); }