📄 server.java
字号:
/* * MegaMek - * Copyright (C) 2000,2001,2002,2003,2004,2005 Ben Mazur (bmazur@sev.org) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */package megamek.server;import megamek.MegaMek;import megamek.common.AmmoType;import megamek.common.BattleArmor;import megamek.common.BipedMech;import megamek.common.Board;import megamek.common.Building;import megamek.common.CommonConstants;import megamek.common.Compute;import megamek.common.Coords;import megamek.common.CriticalSlot;import megamek.common.Entity;import megamek.common.EntitySelector;import megamek.common.EntityWeightClass;import megamek.common.EquipmentMode;import megamek.common.EquipmentType;import megamek.common.Flare;import megamek.common.FuelTank;import megamek.common.Game;import megamek.common.GameTurn;import megamek.common.GunEmplacement;import megamek.common.HitData;import megamek.common.IArmorState;import megamek.common.IBoard;import megamek.common.IEntityMovementMode;import megamek.common.IEntityMovementType;import megamek.common.IEntityRemovalConditions;import megamek.common.IGame;import megamek.common.IHex;import megamek.common.ILocationExposureStatus;import megamek.common.INarcPod;import megamek.common.IOffBoardDirections;import megamek.common.ITerrain;import megamek.common.Infantry;import megamek.common.InfernoTracker;import megamek.common.LocationFullException;import megamek.common.LosEffects;import megamek.common.MapSettings;import megamek.common.Mech;import megamek.common.MechWarrior;import megamek.common.Minefield;import megamek.common.MiscType;import megamek.common.Mounted;import megamek.common.MovePath;import megamek.common.MoveStep;import megamek.common.PhysicalResult;import megamek.common.Pilot;import megamek.common.PilotingRollData;import megamek.common.Player;import megamek.common.Protomech;import megamek.common.QuadMech;import megamek.common.Report;import megamek.common.TagInfo;import megamek.common.Tank;import megamek.common.TargetRoll;import megamek.common.Targetable;import megamek.common.Team;import megamek.common.Terrain;import megamek.common.Terrains;import megamek.common.ToHitData;import megamek.common.TurnOrdered;import megamek.common.TurnVectors;import megamek.common.UnitLocation;import megamek.common.VTOL;import megamek.common.WeaponResult;import megamek.common.WeaponType;import megamek.common.actions.AbstractAttackAction;import megamek.common.actions.ArtilleryAttackAction;import megamek.common.actions.AttackAction;import megamek.common.actions.BreakGrappleAttackAction;import megamek.common.actions.BrushOffAttackAction;import megamek.common.actions.ChargeAttackAction;import megamek.common.actions.ClearMinefieldAction;import megamek.common.actions.ClubAttackAction;import megamek.common.actions.DfaAttackAction;import megamek.common.actions.DodgeAction;import megamek.common.actions.EntityAction;import megamek.common.actions.FindClubAction;import megamek.common.actions.FlipArmsAction;import megamek.common.actions.GrappleAttackAction;import megamek.common.actions.JumpJetAttackAction;import megamek.common.actions.KickAttackAction;import megamek.common.actions.LayExplosivesAttackAction;import megamek.common.actions.LayMinefieldAction;import megamek.common.actions.NukeAttackAction;import megamek.common.actions.ProtomechPhysicalAttackAction;import megamek.common.actions.PunchAttackAction;import megamek.common.actions.PushAttackAction;import megamek.common.actions.SearchlightAttackAction;import megamek.common.actions.SpotAction;import megamek.common.actions.ThrashAttackAction;import megamek.common.actions.TripAttackAction;import megamek.common.actions.TorsoTwistAction;import megamek.common.actions.TriggerAPPodAction;import megamek.common.actions.UnjamAction;import megamek.common.actions.UnloadStrandedAction;import megamek.common.actions.WeaponAttackAction;import megamek.common.net.Connection;import megamek.common.net.ConnectionFactory;import megamek.common.net.ConnectionListenerAdapter;import megamek.common.net.DisconnectedEvent;import megamek.common.net.Packet;import megamek.common.net.PacketReceivedEvent;import megamek.common.options.IBasicOption;import megamek.common.options.IOption;import megamek.common.preference.PreferenceManager;import megamek.common.util.BoardUtilities;import megamek.common.util.StringUtil;import megamek.common.verifier.EntityVerifier;import megamek.common.verifier.TestEntity;import megamek.common.verifier.TestMech;import megamek.common.verifier.TestTank;import megamek.server.commands.DefeatCommand;import megamek.server.commands.FixElevationCommand;import megamek.server.commands.HelpCommand;import megamek.server.commands.KickCommand;import megamek.server.commands.LocalSaveGameCommand;import megamek.server.commands.NukeCommand;import megamek.server.commands.ResetCommand;import megamek.server.commands.RollCommand;import megamek.server.commands.SaveGameCommand;import megamek.server.commands.SeeAllCommand;import megamek.server.commands.ServerCommand;import megamek.server.commands.SkipCommand;import megamek.server.commands.VictoryCommand;import megamek.server.commands.WhoCommand;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;import java.net.UnknownHostException;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.Date;import java.util.Enumeration;import java.util.HashSet;import java.util.Hashtable;import java.util.Iterator;import java.util.Map;import java.util.StringTokenizer;import java.util.Timer;import java.util.TimerTask;import java.util.Vector;/** * @author Ben Mazur */public class Server implements Runnable { // public final static String LEGAL_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.-"; public final static String DEFAULT_BOARD = MapSettings.BOARD_SURPRISE; private final static String VERIFIER_CONFIG_FILENAME = "data/mechfiles/UnitVerifierOptions.xml"; // server setup private String password; private ServerSocket serverSocket; private String motd; // game info private Vector connections = new Vector(4); private Vector connectionsPending = new Vector(4); private Hashtable connectionIds = new Hashtable(); private int connectionCounter; private int entityCounter; private IGame game = new Game(); private Vector vPhaseReport = new Vector(); private MapSettings mapSettings = new MapSettings(); // commands private Hashtable commandsHash = new Hashtable(); // listens for and connects players private Thread connector; // Track buildings that are affected by an entity's movement. private Hashtable affectedBldgs = new Hashtable(); // Track Physical Action results, HACK to deal with opposing pushes // canceling each other private Vector physicalResults = new Vector(); private Vector<DynamicTerrainProcessor> terrainProcessors = new Vector(); private Timer timer = new Timer(); /* Tracks entities which have been destroyed recently. Allows refactoring of the * damage and kill logic from Server, where it is now, to the Entity subclasses eventually. * This has not been implemented yet -- I am just starting to build the groundwork into Server. * It isn't in the execution path and shouldn't cause any bugs */ //Note from another coder - I have commented out your groundwork //for now because it is using HashSet, which isn't available in //Java 1.1 unless you import the collections classes. Since the //Server class isn't using any other collecitons classes, there //might be a reason we're avoiding them here...if not, feel free //to add the import. //private HashSet knownDeadEntities = new HashSet(); private static EntityVerifier entityVerifier; private ConnectionListenerAdapter connectionListener = new ConnectionListenerAdapter() { /** * Called when it is sensed that a connection has terminated. */ public void disconnected(DisconnectedEvent e) { Connection conn = e.getConnection(); // write something in the log System.out.println("s: connection " + conn.getId()+ " disconnected"); connections.removeElement(conn); connectionsPending.removeElement(conn); connectionIds.remove(new Integer(conn.getId())); // if there's a player for this connection, remove it too Player player = getPlayer(conn.getId()); if (null != player) { Server.this.disconnected( player ); } } public void packetReceived(PacketReceivedEvent e) { Server.this.handle(e.getConnection().getId(),e.getPacket()); } }; /** * Construct a new GameHost and begin listening for * incoming clients. * @param password the <code>String</code> that is set as a password * @param port the <code>int</code> value that specifies the port that * is used */ public Server(String password, int port) throws IOException { this.password = password.length() > 0 ? password : null; // initialize server socket serverSocket = new ServerSocket(port); motd = createMotd(); game.getOptions().initialize(); game.getOptions().loadOptions(); changePhase(IGame.PHASE_LOUNGE); // display server start text System.out.println("s: starting a new server..."); try { String host = InetAddress.getLocalHost().getHostName(); System.out.print("s: hostname = '" ); System.out.print( host ); System.out.print( "' port = " ); System.out.println( serverSocket.getLocalPort() ); InetAddress[] addresses = InetAddress.getAllByName(host); for (int i = 0; i < addresses.length; i++) { System.out.println("s: hosting on address = " + addresses[i].getHostAddress()); } } catch (UnknownHostException e) { // oh well. } System.out.println("s: password = " + this.password); // register commands registerCommand(new DefeatCommand(this)); registerCommand(new HelpCommand(this)); registerCommand(new KickCommand(this)); registerCommand(new ResetCommand(this)); registerCommand(new RollCommand(this)); registerCommand(new SaveGameCommand(this)); registerCommand(new SkipCommand(this)); registerCommand(new VictoryCommand(this)); registerCommand(new WhoCommand(this)); registerCommand(new SeeAllCommand(this)); registerCommand(new LocalSaveGameCommand(this)); registerCommand(new FixElevationCommand(this)); registerCommand(new NukeCommand(this)); //register terrain processors terrainProcessors.add(new FireProcessor(this)); terrainProcessors.add(new GeyserProcessor(this)); terrainProcessors.add(new ElevatorProcessor(this)); //Fully initialised, now accept connections connector = new Thread(this, "Connection Listener"); connector.start(); } /** * Sets the game for this server. Restores any transient fields, and sets * all players as ghosts. * This should only be called during server initialization before any * players have connected. */ public void setGame(IGame g) { game = g; // reattach the transient fields and ghost the players for (Enumeration e = game.getEntities(); e.hasMoreElements(); ) { Entity ent = (Entity)e.nextElement(); ent.setGame(game); } game.setOutOfGameEntitiesVector(game.getOutOfGameEntitiesVector()); for (Enumeration e = game.getPlayers(); e.hasMoreElements(); ) { Player p = (Player)e.nextElement(); p.setGame(game); p.setGhost(true); } } /** Returns the current game object */ public IGame getGame() { return game; } /** * Make a default message o' the day containing the version string, and * if it was found, the build timestamp */ private String createMotd() { StringBuffer buf = new StringBuffer(); buf.append("Welcome to MegaMek. Server is running version "); buf.append(MegaMek.VERSION);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -