📄 server.java
字号:
buf.append(", build date "); if (MegaMek.TIMESTAMP > 0L) { buf.append(new Date(MegaMek.TIMESTAMP).toString()); } else { buf.append("unknown"); } buf.append('.'); return buf.toString(); } /** * @return true if the server has a password */ public boolean isPassworded() { return password != null; } /** * @return true if the password matches */ public boolean isPassword(Object guess) { return password.equals(guess); } /** * Registers a new command in the server command table */ private void registerCommand(ServerCommand command) { commandsHash.put(command.getName(), command); } /** * Returns the command associated with the specified name */ public ServerCommand getCommand(String name) { return (ServerCommand)commandsHash.get(name); } /** * Shuts down the server. */ public void die() { timer.cancel(); // kill thread accepting new connections connector = null; // close socket try { serverSocket.close(); } catch(IOException ex) {} // kill pending connnections for (Enumeration i=connectionsPending.elements();i.hasMoreElements();){ final Connection conn = (Connection)i.nextElement(); conn.close(); } connectionsPending.removeAllElements(); // Send "kill" commands to all connections // N.B. I may be starting a race here. for (Enumeration i = connections.elements(); i.hasMoreElements();) { final Connection conn = (Connection)i.nextElement(); send(conn.getId(), new Packet(Packet.COMMAND_CLOSE_CONNECTION)); } // kill active connnections for (Enumeration i = connections.elements(); i.hasMoreElements();) { final Connection conn = (Connection)i.nextElement(); conn.close(); } connections.removeAllElements(); connectionIds.clear(); System.out.flush(); } /** * Returns an enumeration of all the command names */ public Enumeration getAllCommandNames() { return commandsHash.keys(); } /** * Sent when a client attempts to connect. */ private void greeting(int cn) { // send server greeting -- client should reply with client info. sendToPending(cn, new Packet(Packet.COMMAND_SERVER_GREETING)); } /** * Returns a free connection id. */ public int getFreeConnectionId() { while (getPendingConnection(connectionCounter) != null || getConnection(connectionCounter) != null || getPlayer(connectionCounter) != null) { connectionCounter++; } return connectionCounter; } /** * Returns a free entity id. Perhaps this should be in Game instead. */ public int getFreeEntityId() { return game.getNextEntityId(); } /** * Allow the player to set whatever parameters he is able to */ private void receivePlayerInfo(Packet packet, int connId) { Player player = (Player)packet.getObject(0); Player connPlayer = game.getPlayer( connId ); if ( null != connPlayer ) { connPlayer.setColorIndex(player.getColorIndex()); connPlayer.setStartingPos(player.getStartingPos()); connPlayer.setTeam(player.getTeam()); connPlayer.setCamoCategory(player.getCamoCategory()); connPlayer.setCamoFileName(player.getCamoFileName()); connPlayer.setNbrMFConventional(player.getNbrMFConventional()); connPlayer.setNbrMFCommand(player.getNbrMFCommand()); connPlayer.setNbrMFVibra(player.getNbrMFVibra()); } } private String correctDupeName(String oldName) { for (Enumeration i = game.getPlayers(); i.hasMoreElements();) { Player player = (Player)i.nextElement(); if (player.getName().equals(oldName)) { // We need to correct it. String newName = oldName; int dupNum = 2; try { dupNum = Integer.parseInt(oldName.substring(oldName.lastIndexOf(".")+1)); dupNum++; newName = oldName.substring(0,oldName.lastIndexOf(".")); } catch (Exception e) { // If this fails, we don't care much. // Just assume it's the first time for this name. dupNum = 2; } newName = newName.concat(".").concat(Integer.toString(dupNum)); return correctDupeName(newName); } } return oldName; } /** * Recieves a player name, sent from a pending connection, and connects * that connection. */ private void receivePlayerName(Packet packet, int connId) { final Connection conn = getPendingConnection(connId); String name = (String)packet.getObject(0); boolean returning = false; // this had better be from a pending connection if (conn == null) { System.out.println("server: got a client name from a non-pending" + " connection"); return; } // check if they're connecting with the same name as a ghost player for (Enumeration i = game.getPlayers(); i.hasMoreElements();) { Player player = (Player)i.nextElement(); if (player.getName().equals(name)) { if (player.isGhost()) { returning = true; player.setGhost(false); // switch id connId = player.getId(); conn.setId(connId); } } } if (!returning) { // Check to avoid duplicate names... name = correctDupeName(name); send(connId, new Packet(Packet.COMMAND_SERVER_CORRECT_NAME, name)); } // right, switch the connection into the "active" bin connectionsPending.removeElement(conn); connections.addElement(conn); connectionIds.put(new Integer(conn.getId()), conn); // add and validate the player info if (!returning) { game.addPlayer(connId, new Player(connId, name)); validatePlayerInfo(connId); } // if it is not the lounge phase, this player becomes an observer Player player = getPlayer( connId ); if ( game.getPhase() != IGame.PHASE_LOUNGE && null != player && game.getEntitiesOwnedBy(player) < 1) { player.setObserver(true); } // send the player the motd sendServerChat(connId, motd); // send info that the player has connected send(createPlayerConnectPacket(connId)); // tell them their local playerId send(connId, new Packet(Packet.COMMAND_LOCAL_PN, new Integer(connId))); // send current game info sendCurrentInfo(connId); try { InetAddress[] addresses = InetAddress.getAllByName(InetAddress .getLocalHost() .getHostName()); for (int i = 0; i < addresses.length; i++) { sendServerChat(connId, "Machine IP is " + addresses[i].getHostAddress()); } } catch (UnknownHostException e) { // oh well. } // Send the port we're listening on. Only useful for the player // on the server machine to check. sendServerChat(connId, "Listening on port " + serverSocket .getLocalPort()); // Get the player *again*, because they may have disconnected. player = getPlayer( connId ); if ( null != player ) { StringBuffer buff = new StringBuffer(); buff.append( player.getName() ) .append( " connected from " ) .append( getClient(connId).getInetAddress() ); String who = buff.toString(); System.out.print( "s: player #" ); System.out.print( connId ); System.out.print( ", " ); System.out.println( who ); sendServerChat( who ); } // Found the player } /** * Sends a player the info they need to look at the current phase. * This is triggered when a player first connects to the server. */ private void sendCurrentInfo(int connId) { //why are these two outside the player != null check below? transmitAllPlayerConnects(connId); send(connId, createGameSettingsPacket()); Player player = game.getPlayer(connId); if ( null != player ) { send(connId, new Packet(Packet.COMMAND_SENDING_MINEFIELDS, player.getMinefields())); switch (game.getPhase()) { case IGame.PHASE_LOUNGE : send(connId, createMapSettingsPacket()); // Send Entities *after* the Lounge Phase Change send(connId, new Packet(Packet.COMMAND_PHASE_CHANGE, new Integer(game.getPhase()))); if (doBlind()) { send(connId, createFilteredFullEntitiesPacket(player)); } else { send(connId, createFullEntitiesPacket()); } break; default : send(connId, new Packet(Packet.COMMAND_ROUND_UPDATE, new Integer(game.getRoundCount()))); //send(connId, createReportPacket(player)); send(connId, createAllReportsPacket(player)); // Send entities *before* other phase changes. if (doBlind()) { send(connId, createFilteredFullEntitiesPacket(player)); } else { send(connId, createFullEntitiesPacket()); } player.setDone( game.getEntitiesOwnedBy(player) <= 0 ); send(connId, createBoardPacket()); send(connId, new Packet(Packet.COMMAND_PHASE_CHANGE, new Integer(game.getPhase()))); break; } if (game.getPhase() == IGame.PHASE_FIRING || game.getPhase() == IGame.PHASE_TARGETING || game.getPhase() == IGame.PHASE_OFFBOARD || game.getPhase() == IGame.PHASE_PHYSICAL) { // can't go above, need board to have been sent send(connId,createAttackPacket(game.getActionsVector(),0)); send(connId,createAttackPacket(game.getChargesVector(),1)); send(connId,createAttackPacket(game.getLayMinefieldActionsVector(),2)); } if (game.phaseHasTurns(game.getPhase())) { send(connId, createTurnVectorPacket()); send(connId, createTurnIndexPacket()); } send(connId, createArtilleryPacket(player)); send(connId, createFlarePacket()); } // Found the player. } /** * Resend entities to the player * called by seeall command */ public void sendEntities(int connId) { if(doBlind()) { send(connId, createFilteredEntitiesPacket(getPlayer(connId))); } else { send(connId, createEntitiesPacket()); } } /** * Validates the player info. */ public void validatePlayerInfo(int playerId) { final Player player = getPlayer(playerId); // maybe this isn't actually useful // // replace characters we don't like with "X" // StringBuffer nameBuff = new StringBuffer(player.getName()); // for (int i = 0; i < nameBuff.length(); i++) { // int chr = nameBuff.charAt(i); // if (LEGAL_CHARS.indexOf(chr) == -1) { // nameBuff.setCharAt(i, 'X'); // } // } // player.setName(nameBuff.toString()); //TODO: check for duplicate or reserved names // make sure colorIndex is unique boolean[] colorUsed = new boolean[Player.colorNames.length]; for (Enumeration i = game.getPlayers(); i.hasMoreElements();) { final Player otherPlayer = (Player)i.nextElement(); if (otherPlayer.getId() != playerId) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -