Advertisement
Guest User

Untitled

a guest
Mar 18th, 2016
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 81.01 KB | None | 0 0
  1. /*
  2.  * MekWars - Copyright (C) 2004
  3.  *
  4.  * Derived from MegaMekNET (http://www.sourceforge.net/projects/megameknet)
  5.  * Original author Helge Richter (McWizard)
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify it
  8.  * under the terms of the GNU General Public License as published by the Free
  9.  * Software Foundation; either version 2 of the License, or (at your option)
  10.  * any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful, but
  13.  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14.  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  15.  * for more details.
  16.  */
  17.  
  18. package dedicatedhost;
  19.  
  20. import java.awt.Dimension;
  21. import java.io.BufferedOutputStream;
  22. import java.io.BufferedReader;
  23. import java.io.File;
  24. import java.io.FileInputStream;
  25. import java.io.FileOutputStream;
  26. import java.io.FilenameFilter;
  27. import java.io.InputStreamReader;
  28. import java.io.PrintStream;
  29. import java.lang.reflect.Constructor;
  30. import java.net.InetAddress;
  31. import java.text.SimpleDateFormat;
  32. import java.util.Collection;
  33. import java.util.Collections;
  34. import java.util.Date;
  35. import java.util.Enumeration;
  36. import java.util.HashMap;
  37. import java.util.Iterator;
  38. import java.util.List;
  39. import java.util.Properties;
  40. import java.util.StringTokenizer;
  41. import java.util.TreeMap;
  42. import java.util.Vector;
  43.  
  44. import megamek.MegaMek;
  45. import megamek.common.Building;
  46. import megamek.common.Entity;
  47. import megamek.common.IGame;
  48. import megamek.common.Mech;
  49. import megamek.common.MechWarrior;
  50. import megamek.common.Player;
  51. import megamek.common.IGame.Phase;
  52. import megamek.common.event.GameBoardChangeEvent;
  53. import megamek.common.event.GameBoardNewEvent;
  54. import megamek.common.event.GameCFREvent;
  55. import megamek.common.event.GameEndEvent;
  56. import megamek.common.event.GameEntityChangeEvent;
  57. import megamek.common.event.GameEntityNewEvent;
  58. import megamek.common.event.GameEntityNewOffboardEvent;
  59. import megamek.common.event.GameEntityRemoveEvent;
  60. import megamek.common.event.GameEvent;
  61. import megamek.common.event.GameListener;
  62. import megamek.common.event.GameMapQueryEvent;
  63. import megamek.common.event.GameNewActionEvent;
  64. import megamek.common.event.GamePhaseChangeEvent;
  65. import megamek.common.event.GamePlayerChangeEvent;
  66. import megamek.common.event.GamePlayerChatEvent;
  67. import megamek.common.event.GamePlayerConnectedEvent;
  68. import megamek.common.event.GamePlayerDisconnectedEvent;
  69. import megamek.common.event.GameReportEvent;
  70. import megamek.common.event.GameSettingsChangeEvent;
  71. import megamek.common.event.GameTurnChangeEvent;
  72. import megamek.common.event.GameVictoryEvent;
  73. import megamek.common.options.IOption;
  74. import megamek.common.preference.IClientPreferences;
  75. import megamek.common.preference.PreferenceManager;
  76. import megamek.server.Server;
  77.  
  78. import common.CampaignData;
  79. import common.GameInterface;
  80. import common.GameWrapper;
  81. import common.MMGame;
  82. import common.campaign.Buildings;
  83. import common.util.UnitUtils;
  84.  
  85. import dedicatedhost.cmd.Command;
  86. import dedicatedhost.protocol.CConnector;
  87. import dedicatedhost.protocol.DataFetchClient;
  88. import dedicatedhost.protocol.IClient;
  89. import dedicatedhost.protocol.TransportCodec;
  90. import dedicatedhost.protocol.commands.AckSignonPCmd;
  91. import dedicatedhost.protocol.commands.CommPCmd;
  92. import dedicatedhost.protocol.commands.IProtCommand;
  93. import dedicatedhost.protocol.commands.PingPCmd;
  94. import dedicatedhost.protocol.commands.PongPCmd;
  95. import dedicatedhost.util.SerializeEntity;
  96.  
  97. // This is the Client used for connecting to the master server.
  98. // @Author: Helge Richter (McWizard@gmx.de)
  99.  
  100. public final class MWDedHost implements IClient, GameListener {
  101.  
  102.     CConfig Config;
  103.     DataFetchClient dataFetcher;
  104.     public static final int STATUS_DISCONNECTED = 0;
  105.     public static final int STATUS_LOGGEDOUT = 1;
  106.  
  107.     public static final String CLIENT_VERSION = "0.3.7.0"; // change this with
  108.     // all client
  109.     // changes @Torren
  110.  
  111.     CConnector Connector;
  112.     TimeOutThread TO;
  113.     Collection<CUser> Users;
  114.     TreeMap<String, MMGame> servers = new TreeMap<String, MMGame>();// hostname,mmgame
  115.     Server myServer = null;
  116.     Date mytime = new Date(System.currentTimeMillis());
  117.     Vector<IOption> GameOptions = new Vector<IOption>(1, 1);
  118.     Vector<String> decodeBuffer = new Vector<String>(1, 1);// used to buffer
  119.     // incoming data
  120.     // until CMainFrame
  121.     // is built
  122.  
  123.     boolean SignOff = false;
  124.     public String myUsername = "";// public b/c used in RGTS command to set
  125.     // server status. HACK!
  126.     String password = "";
  127.     String myDedOwners = "";
  128.     int myPort = -1;
  129.     int gameCount = 0; // number of games played on a ded
  130.     long lastResetCheck = System.currentTimeMillis(); // how quick a reset check
  131.     // can be done on a ded.
  132.     int dedRestartAt = 50; // number of games played on a ded before auto
  133.     // restart.
  134.     int savedGamesMaxDays = 30; // max number of days a save game can be before
  135.     // its deleted.
  136.     long TimeOut = 120;
  137.     long LastPing = 0;
  138.     int Status = 0;
  139.  
  140.     private Phase currentPhase = IGame.Phase.PHASE_DEPLOYMENT;
  141.     private int turn = 0;
  142.  
  143.     Dimension MapSize;
  144.     Dimension BoardSize;
  145.  
  146.     public static final String CAMPAIGN_PATH = "data/campaign/";
  147.  
  148.     public static final String PROTOCOL_DELIMITER = "\t"; // delimiter for
  149.     // protocol commands
  150.     public static final String PROTOCOL_PREFIX = "/"; // prefix for protocol
  151.     // commands
  152.     public static final String COMMAND_DELIMITER = "|"; // delimiter for client
  153.     // commands
  154.     public static final String GUI_PREFIX = "/"; // prefix for commands in
  155.     // GUI
  156.     public static final String CAMPAIGN_PREFIX = "/"; // prefix for campaign
  157.     // commands
  158.  
  159.     TreeMap<String, IProtCommand> ProtCommands = new TreeMap<String, IProtCommand>();
  160.  
  161.     /**
  162.      * Maps the task prefixes as HS, PL, SP etc. to a command under package cmd.
  163.      * key: String, value: cmd.Command
  164.      */
  165.     HashMap<String, Command> commands = new HashMap<String, Command>();
  166.  
  167.     String LastQuery = ""; // receiver of last mail
  168.     private String cacheDir;
  169.  
  170.     /**
  171.      * @author Torren place holder until I can think of something better to say.
  172.      */
  173.     public Properties serverConfigs = new Properties();
  174.  
  175.     Buildings buildingTemplate = null;
  176.  
  177.     // Main-Method
  178.     public static void main(String[] args) {
  179.  
  180.         CConfig config;
  181.         CampaignData.mwlog.enableLogging(true);
  182.         CampaignData.mwlog.enableSeconds(true);
  183.  
  184.         CampaignData.mwlog.createClientLoggers();
  185.  
  186.         /*
  187.          * put StdErr and StdOut into ./logs/megameklog.txt, because MegaMek
  188.          * uses StdOut and StdErr, but the part of MegaMek that sets that up
  189.          * does not get called when we launch MegaMek in MekWars Redirect output
  190.          * to logfiles, unless turned off. Moved megameklog.txt to the logs
  191.          * folder -- Torren
  192.          */
  193.         String logFileName = "./logs/megameklog.txt";
  194.  
  195.         try {
  196.             PrintStream ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(logFileName), 64));
  197.             System.setOut(ps);
  198.             System.setErr(ps);
  199.         } catch (Exception ex) {
  200.             CampaignData.mwlog.errLog(ex);
  201.             CampaignData.mwlog.errLog("Unable to redirect MegaMek output to " + logFileName);
  202.         }
  203.  
  204.         CampaignData.mwlog.infoLog("Starting MekWars Client Version: " + CLIENT_VERSION);
  205.         try {
  206.             config = new CConfig(true);
  207.  
  208.             /*
  209.              * clear any cache'd unit files. these will be rebuilt later in the
  210.              * start process. clearing @ each start ensures that updates take
  211.              * hold properly.
  212.              */
  213.             File cache = new File("./data/mechfiles/units.cache");
  214.             if (cache.exists()) {
  215.                 cache.delete();
  216.             }
  217.  
  218.             /*
  219.              * Config files have been loaded, and command line args have been
  220.              * parsed. Construct the actual client.
  221.              *
  222.              * NOTE: Client constrtuctor attempts to pull the oplist, campaign
  223.              * config and other non-interactive data over the DATAPORT before
  224.              * client.start() attempts to connect to the chat server on the
  225.              * SERVERPORT.
  226.              */
  227.             new MWDedHost(config);
  228.  
  229.         } catch (Exception ex) {
  230.             CampaignData.mwlog.errLog(ex);
  231.             CampaignData.mwlog.errLog("Couldn't create Client Object");
  232.             System.exit(1);
  233.         }
  234.     }
  235.  
  236.     public MWDedHost(CConfig config) {
  237.  
  238.         Config = config;
  239.  
  240.         Connector = new CConnector(this);
  241.  
  242.         Users = Collections.synchronizedList(new Vector<CUser>(1, 1));
  243.  
  244.         createProtCommands();
  245.         dataFetcher = new DataFetchClient(Integer.parseInt(Config.getParam("DATAPORT")), Integer.parseInt(Config.getParam("SOCKETTIMEOUTDELAY")));
  246.         dataFetcher.setData(Config.getParam("SERVERIP"), getCacheDir());
  247.         dataFetcher.closeDataConnection();
  248.  
  249.         // Remove any MM option files that deds may have.
  250.         File localGameOptions = new File("./mmconf");
  251.         try {
  252.             if (localGameOptions.exists()) {
  253.                 localGameOptions = new File("./mmconf/gameoptions.xml");
  254.                 if (localGameOptions.exists()) {
  255.                     localGameOptions.delete();
  256.                 }
  257.             }
  258.         } catch (Exception ex) {
  259.             CampaignData.mwlog.errLog(ex);
  260.         }
  261.  
  262.         // set New timestamp
  263.         // this.dataFetcher.setLastTimestamp(new
  264.         // Date(System.currentTimeMillis()));
  265.         // this.dataFetcher.store();
  266.  
  267.         getServerConfigData();
  268.  
  269.         myUsername = getConfigParam("NAME");
  270.  
  271.         // if this is dedicated host, we mark its name with "[Dedicated]" stamp
  272.         if (!myUsername.startsWith("[Dedicated]")) {
  273.             Config.setParam("NAME", "[Dedicated] " + Config.getParam("NAME"));
  274.             myUsername = Config.getParam("NAME");
  275.         }
  276.  
  277.         dedRestartAt = Integer.parseInt(getConfigParam("DEDAUTORESTART"));
  278.         savedGamesMaxDays = Integer.parseInt(getConfigParam("MAXSAVEDGAMEDAYS"));
  279.         myDedOwners = getConfigParam("DEDICATEDOWNERNAME");
  280.         myPort = Integer.parseInt(getConfigParam("PORT"));
  281.  
  282.         /*
  283.          * Start the pruge thread when the client starts, not when the host
  284.          * starts. This prevents the creation of multiple threads when the host
  285.          * is restarted, or after disconnections.
  286.          */
  287.         CampaignData.mwlog.infoLog("Starting pAS");
  288.         PurgeAutoSaves pAS = new PurgeAutoSaves();
  289.         new Thread(pAS).start();
  290.  
  291.         /*
  292.          * Load IP and Port to connect to from the config. In older code the
  293.          * signon dialog was shown at this point. The dialog has been moved, and
  294.          * is now displayed -before- the client attempts to fetch vital data,
  295.          * like the map.
  296.          */
  297.         String chatServerIP = "";
  298.         int chatServerPort = -1;
  299.         try {
  300.             chatServerIP = Config.getParam("SERVERIP");
  301.             chatServerPort = Config.getIntParam("SERVERPORT");
  302.         } catch (Exception e) {
  303.             CampaignData.mwlog.errLog(e);
  304.             System.exit(1);
  305.         }
  306.  
  307.         int retryCount = 0;
  308.         while ((Status == STATUS_DISCONNECTED) && (retryCount++ < 20)) {
  309.             connectToServer(chatServerIP, chatServerPort);
  310.             if (Status == STATUS_DISCONNECTED) {
  311.                 CampaignData.mwlog.infoLog("Couldn't connect to server. Retrying in 90 seconds.");
  312.                 try {
  313.                     Thread.sleep(90000);
  314.                 } catch (Exception exe) {
  315.                     CampaignData.mwlog.errLog(exe);
  316.                     System.exit(2);
  317.                 }
  318.             }
  319.         }
  320.  
  321.         // start checking for timeouts
  322.         TimeOut = Long.parseLong(Config.getParam("TIMEOUT"));
  323.         LastPing = System.currentTimeMillis() / 1000;
  324.         TO = new TimeOutThread(this);
  325.         TO.run();
  326.     }
  327.  
  328.     /*
  329.      * NOTE: this list is ancient. sometimes useful. often out of date.
  330.      *
  331.      * List of Abreviations for the protocol used by the client only: NG = New
  332.      * Game (NG|<IP>|<Port>|<MaxPlayers>|<Version>|<Comment>) CG = Close Game
  333.      * (CG) GB = Goodbye (Client exit) (GB) SO = Sign-On
  334.      * (SO|<Version>|<UserName>)
  335.      *
  336.      * Used by Both: CH = Chat Server news:(CH|<text>) Client Chat:
  337.      * (CH|<UserName>|<Color>|<Text>)
  338.      *
  339.      * Used only by the Server: SL|NG = Games
  340.      * (GS|<MMGame.toString()>|<MMGame.toString()|...) SL|CG = close game SL|JG
  341.      * = add a player to game list SL|LG = remove a player from game list SL|SHS
  342.      * = Set Host Status (SHS|<GameID>|<Status>) US = Users
  343.      * (US|<MMClientInfo.toString()>|<MMClientInfo.toString()>|..) UG = User
  344.      * Gone (UG|<MMClientInfo.toString>|[Gone]) Gone is used when the client
  345.      * didn't just change his name NU = New User
  346.      * (NU|<MMClientInfo.toString>|[NEW]) NEW is used the same way as GONE in UG
  347.      * ER = Error (Not yet used) (ER|<ErrorLevel>|<description>) NN = New name
  348.      * (My name Change was successful) CT = Campaign Task Offset (CT|Offset) CS
  349.      * = Campaign Status (CS|Status) GO = Game Options
  350.      * (GO|OPTION1NAME|OPTION1VALUE|OPTION2NAME...) PE = SPlanet Environment
  351.      * (Used to initialize the MM map generator) HS = SHouse Status TI = Tick
  352.      * Info (TI|TIMETILLNEXT) SP = Show PopupWindow SM = Show Miscellaneous
  353.      * (Puts text into Misc Tab)
  354.      */
  355.     public synchronized void doParseDataInput(String input) {
  356.  
  357.         // non-null main frame, unbuffer or just pass through
  358.         if (decodeBuffer.size() > 0) {
  359.             Iterator<String> i = decodeBuffer.iterator();
  360.             while (i.hasNext()) {
  361.                 String currS = i.next();
  362.                 doParseDataHelper(currS);
  363.                 i.remove();
  364.             }
  365.         } else {
  366.             doParseDataHelper(input);
  367.         }
  368.     }
  369.  
  370.     /*
  371.      * Actual GUI-mode parseData. Before we started streaming data over the chat
  372.      * part, this was called directly. Now we buffer all incoming non-data chat
  373.      * and spit it out at once when the GUI draws. Once the GUI is up, this is
  374.      * called by a simple pass through from doParseDataInput(), above.
  375.      *
  376.      * Ded's call the helper directly to bypass the buffer.
  377.      */
  378.     private void doParseDataHelper(String input) {
  379.         try {
  380.  
  381.             // 0-length input is spurious call from MWDedHost constructor.
  382.             if (input.length() == 0) {
  383.                 return;
  384.             }
  385.  
  386.             StringTokenizer ST = null;
  387.             String task = null;
  388.  
  389.             // debug info
  390.             CampaignData.mwlog.infoLog(input);
  391.  
  392.             // Create a String Tokenizer to parse the elements of the input
  393.             ST = new StringTokenizer(input, COMMAND_DELIMITER);
  394.             task = ST.nextToken();
  395.  
  396.             if (!commands.containsKey(task)) {
  397.                 try {
  398.                     Class<?> cmdClass = Class.forName(getClass().getPackage().getName() + ".cmd." + task);
  399.                     Constructor<?> c = cmdClass.getConstructor(new Class[]
  400.                         { MWDedHost.class });
  401.                     Command cmd = (Command) c.newInstance(new Object[]
  402.                         { this });
  403.                     commands.put(task, cmd);
  404.                 } catch (Exception e) {
  405.                     CampaignData.mwlog.errLog(e);
  406.                 }
  407.             }
  408.             if (commands.containsKey(task)) {
  409.                 commands.get(task).execute(input);
  410.             }
  411.         } catch (Exception ex) {
  412.             CampaignData.mwlog.errLog(ex);
  413.         }
  414.     }
  415.  
  416.     public synchronized void parseDedDataInput(String data) {
  417.  
  418.         // Debug info
  419.         // CampaignData.mwlog.infoLog(data);
  420.  
  421.         StringTokenizer st, own;
  422.         String name, owner, command;
  423.         int port;
  424.  
  425.         /*
  426.          * New users, report requests and data should be sent to standard
  427.          * processor. PM's are checked below, and all other commands are tossed
  428.          * (e.g. - CH).
  429.          *
  430.          * Note that ded's bypass the doParseDeda() buffering process (never
  431.          * have a main frame, so no null check or buffer needed) and call
  432.          * doParseDataHelper() directly.
  433.          */
  434.         if (data.startsWith("US|") || data.startsWith("NU|") || data.startsWith("UG|") || data.startsWith("RGTS|") || data.startsWith("DSD|") || data.startsWith("USD|")) {
  435.             doParseDataHelper(data);// bypass the buffering process -
  436.             // ded's never have a main fraime
  437.             return;
  438.         }
  439.  
  440.         // only parse PM's for commands
  441.         if (!data.startsWith("PM|")) {
  442.             return;
  443.         }
  444.  
  445.         data = data.substring(3);// strip "PM|"
  446.         st = new StringTokenizer(data, "|");
  447.         own = new StringTokenizer(myDedOwners, "$");
  448.  
  449.         name = st.nextToken().trim();
  450.         if (!st.hasMoreTokens()) {
  451.             return;
  452.         } // it's not real chat message
  453.         if (name.equals(myUsername)) {
  454.             return;
  455.         } // server can't send commands to itself
  456.         command = st.nextToken().trim();
  457.  
  458.         /*
  459.          * Commands that can be executed by ANY user.
  460.          */
  461.         if (command.equals("checkrestartcount")) {// check the restart amount.
  462.             checkForRestart();
  463.             return;
  464.         } else if (command.equals("displaymegameklog")) { // display
  465.             // megameklog.txt
  466.             CampaignData.mwlog.infoLog("display megameklog command received from " + name);
  467.             try {
  468.                 File logFile = new File("./logs/megameklog.txt");
  469.                 FileInputStream fis = new FileInputStream(logFile);
  470.                 BufferedReader dis = new BufferedReader(new InputStreamReader(fis));
  471.                 sendChat(PROTOCOL_PREFIX + "c sendtomisc#" + name + "#MegaMek Log from " + myUsername);
  472.                 int counter = 0;
  473.                 while (dis.ready()) {
  474.                     sendChat(PROTOCOL_PREFIX + "c sendtomisc#" + name + "#" + dis.readLine());
  475.                     // problems with huge logs getting shoved down players
  476.                     // throats so a 100ms delay should allow
  477.                     // the message queue to breath.
  478.                     if ((counter++ % 100) == 0) {
  479.                         try {
  480.                             Thread.sleep(100);
  481.                         } catch (Exception ex) {
  482.                             // Do nothing
  483.                         }
  484.                     }
  485.                 }
  486.                 fis.close();
  487.                 dis.close();
  488.  
  489.             } catch (Exception ex) {
  490.                 // do nothing?
  491.             }
  492.             sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the display megamek logs command on " + myUsername);
  493.             return;
  494.         } else if (command.equals("displaydederrorlog")) { // display
  495.             // error.0
  496.             CampaignData.mwlog.infoLog("display ded error command received from " + name);
  497.             try {
  498.                 File logFile = new File("./logs/errlog.0");
  499.                 FileInputStream fis = new FileInputStream(logFile);
  500.                 BufferedReader dis = new BufferedReader(new InputStreamReader(fis));
  501.                 sendChat(PROTOCOL_PREFIX + "c sendtomisc#" + name + "#Error Log from " + myUsername);
  502.                 int counter = 0;
  503.                 while (dis.ready()) {
  504.                     sendChat(PROTOCOL_PREFIX + "c sendtomisc#" + name + "#" + dis.readLine());
  505.                     // problems with huge logs getting shoved down players
  506.                     // throats so a 100ms delay should allow
  507.                     // the message queue to breath.
  508.                     if ((counter++ % 100) == 0) {
  509.                         try {
  510.                             Thread.sleep(100);
  511.                         } catch (Exception ex) {
  512.                             // Do nothing
  513.                         }
  514.                     }
  515.                 }
  516.                 fis.close();
  517.                 dis.close();
  518.  
  519.             } catch (Exception ex) {
  520.                 // do nothing?
  521.             }
  522.             sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the display ded error log command on " + myUsername);
  523.             return;
  524.         } else if (command.equals("displaydedlog")) { // display
  525.             // log.0
  526.             CampaignData.mwlog.infoLog("display ded log command received from " + name);
  527.             try {
  528.                 File logFile = new File("./logs/infolog.0");
  529.                 FileInputStream fis = new FileInputStream(logFile);
  530.                 BufferedReader dis = new BufferedReader(new InputStreamReader(fis));
  531.                 sendChat(PROTOCOL_PREFIX + "c sendtomisc#" + name + "#Ded Log from " + myUsername);
  532.                 int counter = 0;
  533.                 while (dis.ready()) {
  534.                     sendChat(PROTOCOL_PREFIX + "c sendtomisc#" + name + "#" + dis.readLine());
  535.                     // problems with huge logs getting shoved down players
  536.                     // throats so a 100ms delay should allow
  537.                     // the message queue to breath.
  538.                     if ((counter++ % 100) == 0) {
  539.                         try {
  540.                             Thread.sleep(100);
  541.                         } catch (Exception ex) {
  542.                             // Do nothing
  543.                         }
  544.                     }
  545.                 }
  546.                 fis.close();
  547.                 dis.close();
  548.  
  549.             } catch (Exception ex) {
  550.                 // do nothing?
  551.             }
  552.             sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the display ded log command on " + myUsername);
  553.             return;
  554.         }
  555.  
  556.         /*
  557.          * Commands that can only be executed by owners, mods, or in the absence
  558.          * of an owner list.
  559.          */
  560.         while (myDedOwners.equals("") || own.hasMoreTokens()) {
  561.  
  562.             if (own.hasMoreTokens()) {
  563.                 owner = own.nextToken();
  564.             } else {
  565.                 owner = "";
  566.             }
  567.  
  568.             if (myDedOwners.equals("") || name.equals(owner) || (getUser(name).getUserlevel() >= 100)) {
  569.                 // if no owners set, anyone can send commands
  570.  
  571.                 if (command.equals("restart")) { // Restart the dedicated
  572.                     // server
  573.  
  574.                     CampaignData.mwlog.infoLog("Restart command received from " + name);
  575.                     stopHost();// kill the host
  576.  
  577.                     // Remove any MM option files that deds may have.
  578.                     File localGameOptions = new File("./mmconf");
  579.                     try {
  580.                         if (localGameOptions.exists()) {
  581.                             localGameOptions = new File("./mmconf/gameoptions.xml");
  582.                             if (localGameOptions.exists()) {
  583.                                 localGameOptions.delete();
  584.                             }
  585.                         }
  586.                     } catch (Exception ex) {
  587.                         CampaignData.mwlog.errLog(ex);
  588.                     }
  589.  
  590.                     // sleep for a few seconds before restarting
  591.                     try {
  592.                         Thread.sleep(5000);
  593.                     } catch (Exception ex) {
  594.                         CampaignData.mwlog.errLog(ex);
  595.                     }
  596.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the restart command on " + myUsername);
  597.                     restartDed();
  598.                     return;
  599.  
  600.                 } else if (command.equals("reset")) { // server reset (like
  601.                     // /reset in MM)
  602.  
  603.                     CampaignData.mwlog.infoLog("Reset command received from " + name);
  604.                     if (myServer != null) {
  605.                         resetGame();
  606.                     }
  607.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the reset command on " + myUsername);
  608.                     return;
  609.  
  610.                 } else if (command.equals("die")) { // shut the dedicated down
  611.  
  612.                     goodbye();
  613.                     System.exit(0);
  614.  
  615.                 } else if (command.equals("start")) { // start hosting a MM
  616.                     // game
  617.  
  618.                     CampaignData.mwlog.infoLog("Start command received from " + name);
  619.                     if (myServer == null) {
  620.                         startHost(true, false, false);
  621.                     }
  622.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the start command on " + myUsername);
  623.                     return;
  624.  
  625.                 } else if (command.equals("stop")) { // stop MM host, but w/o
  626.                     // killing ded's
  627.                     // connection
  628.  
  629.                     // stop the host
  630.                     CampaignData.mwlog.infoLog("Stop command received from " + name);
  631.                     if (myServer != null) {
  632.                         stopHost();
  633.                     }
  634.  
  635.                     // sleep, then wait around for a start command ...
  636.                     try {
  637.                         Thread.sleep(5000);
  638.                     } catch (Exception ex) {
  639.                         CampaignData.mwlog.errLog(ex);
  640.                     }
  641.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the stop command on " + myUsername);
  642.                     return;
  643.  
  644.                 } else if (command.equals("owners")) { // return a list of
  645.                     // owners
  646.  
  647.                     CampaignData.mwlog.infoLog("Owners command received from " + name);
  648.                     sendChat(PROTOCOL_PREFIX + "mail " + name + ", My owners: " + myDedOwners.replace('$', ' '));
  649.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the owners command on " + myUsername);
  650.                     return;
  651.  
  652.                 } else if (command.startsWith("owner ")) { // add new owner(s)
  653.  
  654.                     CampaignData.mwlog.infoLog("Owner command received from " + name);
  655.                     if (!myDedOwners.equals("")) {
  656.                         myDedOwners = myDedOwners + "$";
  657.                     }
  658.  
  659.                     myDedOwners = myDedOwners + command.substring(("owner ").length()).trim();
  660.                     getConfig().setParam("DEDICATEDOWNERNAME", myDedOwners);
  661.                     getConfig().saveConfig();
  662.                     setConfig();
  663.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the owner " + myDedOwners + " command on " + myUsername);
  664.                     return;
  665.  
  666.                 } else if (command.equals("clearowners")) { // clear owners, and
  667.                     // send feedback.
  668.  
  669.                     CampaignData.mwlog.infoLog("Clearowners command received from " + name);
  670.                     myDedOwners = "";
  671.                     sendChat(PROTOCOL_PREFIX + "mail " + name + ", My owners: " + myDedOwners);
  672.                     getConfig().setParam("DEDICATEDOWNERNAME", myDedOwners);
  673.                     getConfig().saveConfig();
  674.                     setConfig();
  675.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the clear owners command on " + myUsername);
  676.                     return;
  677.  
  678.                 } else if (command.equals("port")) {// return the server's port
  679.  
  680.                     CampaignData.mwlog.infoLog("Port command received from " + name);
  681.                     sendChat(PROTOCOL_PREFIX + "mail " + name + ", My port: " + myPort);
  682.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the port command on " + myUsername);
  683.                     return;
  684.  
  685.                 } else if (command.startsWith("port ")) {// new server port
  686.  
  687.                     CampaignData.mwlog.infoLog("Port (set) command received from " + name);
  688.                     try {
  689.                         port = Integer.parseInt(command.substring(("port ").length()).trim());
  690.                     } catch (Exception ex) {
  691.                         CampaignData.mwlog.infoLog("Command error: " + command + ": non-numeral port.");
  692.                         return;
  693.                     }
  694.  
  695.                     if ((port > 0) && (port < 65536)) {
  696.                         myPort = port;
  697.                     }// check for legal port range
  698.                     else {
  699.                         CampaignData.mwlog.infoLog("Command error: " + command + ": port out of valid range.");
  700.                     }
  701.                     String portString = Integer.toString(myPort);
  702.                     getConfig().setParam("PORT", portString);
  703.                     getConfig().saveConfig();
  704.                     setConfig();
  705.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " changed the port for " + myUsername + " to " + myPort);
  706.                     return;
  707.  
  708.                 } else if (command.equals("savegamepurge")) {// server days
  709.                     // to purge
  710.  
  711.                     CampaignData.mwlog.infoLog("Save game purge command received from " + name);
  712.                     sendChat(PROTOCOL_PREFIX + "mail " + name + ", I purge saved games that are " + savedGamesMaxDays + " days old, or older.");
  713.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the save game purge command on " + myUsername);
  714.                     return;
  715.  
  716.                 } else if (command.startsWith("savegamepurge ")) { // set
  717.                     // number of
  718.                     // days to
  719.                     // delete is
  720.                     // purge is
  721.                     // called
  722.  
  723.                     int mySavedGamesMaxDays = 7;
  724.                     CampaignData.mwlog.infoLog("Savegamepurge command received from " + name);
  725.                     try {
  726.                         mySavedGamesMaxDays = Integer.parseInt(command.substring(("savegamepurge ").length()).trim());
  727.                     } catch (Exception ex) {
  728.                         CampaignData.mwlog.infoLog("Command error: " + command + ": invalid number.");
  729.                         return;
  730.                     }
  731.  
  732.                     String purgeString = Integer.toString(mySavedGamesMaxDays);
  733.                     getConfig().setParam("MAXSAVEDGAMEDAYS", purgeString);
  734.                     getConfig().saveConfig();
  735.                     setConfig();
  736.                     savedGamesMaxDays = mySavedGamesMaxDays;
  737.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " changed the save game purge for " + myUsername + " to " + mySavedGamesMaxDays + " days.");
  738.                     return;
  739.  
  740.                 } else if (command.equals("displaysavedgames")) { // display
  741.                     // saved
  742.                     // games
  743.  
  744.                     CampaignData.mwlog.infoLog("displaysavedgames command received from " + name);
  745.                     File[] fileList;
  746.                     String list = "<br><b>Saved files on " + myUsername + "</b><br>";
  747.                     String dateTimeFormat = "MM/dd/yyyy HH:mm:ss";
  748.                     SimpleDateFormat sDF = new SimpleDateFormat(dateTimeFormat);
  749.                     try {
  750.                         File tempFile = new File("./savegames/");
  751.                         fileList = tempFile.listFiles();
  752.                         for (File dateFile : fileList) {
  753.                             Date date = new Date(dateFile.lastModified());
  754.                             String dateTime = sDF.format(date);
  755.                             list += "<a href=\"MEKMAIL" + myUsername + "*loadgamewithfullpath " + dateFile + "\">Load " + dateFile + "</a> " + dateTime + "<br>";
  756.                         }
  757.                     } catch (Exception ex) {
  758.                         // do something?
  759.                     }
  760.  
  761.                     sendChat(PROTOCOL_PREFIX + "mail " + name + ", " + list);
  762.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the display saved games command on " + myUsername);
  763.                     return;
  764.  
  765.                 } else if (command.equals("update")) { // update the dedicated
  766.                     // host using
  767.                     // MWAutoUpdate
  768.  
  769.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the update command on " + myUsername);
  770.                     CampaignData.mwlog.infoLog("Update command received from " + name);
  771.                     stopHost();
  772.                     updateDed();
  773.                     return;
  774.  
  775.                 } else if (command.equals("ping")) { // ping dedicated
  776.  
  777.                     CampaignData.mwlog.infoLog("Ping command received from " + name);
  778.                     String version = MWDedHost.CLIENT_VERSION;
  779.                     sendChat(PROTOCOL_PREFIX + "mail " + name + ", I'm active with version " + version + ".");
  780.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the ping command on " + myUsername);
  781.                     return;
  782.  
  783.                 }
  784.                 if (command.equals("loadgame") || command.startsWith("loadgame ")) { // load
  785.                     // game
  786.                     // from
  787.                     // file
  788.  
  789.                     CampaignData.mwlog.infoLog("Loadgame command received from " + name);
  790.                     String filename = "";
  791.                     if (command.startsWith("loadgame ")) {
  792.                         filename = command.substring(("loadgame ").length()).trim();
  793.                     }
  794.                     if (command.equals("loadgame") || filename.equals("")) {
  795.                         filename = "autosave.sav";
  796.                     }
  797.                     if (myServer != null) {
  798.                         if (!loadGame(filename)) {
  799.                             sendChat(PROTOCOL_PREFIX + "mail " + name + ", Unable to load saved game.");
  800.                         } else {
  801.                             sendChat(PROTOCOL_PREFIX + "mail " + name + ", Saved game loaded.");
  802.                         }
  803.                     }
  804.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " loaded game " + filename + " on " + myUsername);
  805.                     return;
  806.  
  807.                 } else if (command.startsWith("loadgamewithfullpath ")) { // load
  808.                     // game
  809.                     // from
  810.                     // file,
  811.                     // using
  812.                     // full
  813.                     // path
  814.  
  815.                     CampaignData.mwlog.infoLog("Loadgamewithfullpath command received from " + name);
  816.                     String filename = "";
  817.                     if (command.startsWith("loadgamewithfullpath ")) {
  818.                         filename = command.substring(("loadgamewithfullpath ").length()).trim();
  819.                     }
  820.                     if (command.equals("loadgamewithfullpath") || filename.equals("")) {
  821.                         filename = "autosave.sav";
  822.                     }
  823.                     if (myServer != null) {
  824.                         if (!loadGameWithFullPath(filename)) {
  825.                             sendChat(PROTOCOL_PREFIX + "mail " + name + ", Unable to load saved game.");
  826.                         } else {
  827.                             sendChat(PROTOCOL_PREFIX + "mail " + name + ", Saved game loaded.");
  828.                         }
  829.                     }
  830.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " loaded game " + filename + " on " + myUsername);
  831.                     return;
  832.  
  833.                 } else if (command.equals("loadautosave")) { // load the most
  834.                     // recent auto
  835.                     // save file
  836.  
  837.                     CampaignData.mwlog.infoLog("Loadautosave command received from " + name);
  838.                     String filename = "autosave.sav";
  839.                     if (myServer != null) {
  840.                         filename = getParanoidAutoSave();
  841.                         if (!loadGame(filename)) {
  842.                             sendChat(PROTOCOL_PREFIX + "mail " + name + ", Unable to load saved game.");
  843.                         } else {
  844.                             sendChat(PROTOCOL_PREFIX + "mail " + name + ", " + filename + " loaded.");
  845.                         }
  846.                     }
  847.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " loaded " + filename + " game on " + myUsername);
  848.                     return;
  849.  
  850.                 } else if (command.startsWith("name ")) { // new command
  851.                     // prefix
  852.  
  853.                     CampaignData.mwlog.infoLog("Name command received from " + name);
  854.                     String myComName = command.substring(("name ").length()).trim();
  855.                     getConfig().setParam("NAME", myComName);
  856.                     getConfig().saveConfig();
  857.                     setConfig();
  858.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the set name command to change the name to " + myComName + " command on " + myUsername);
  859.                     Config.setParam("NAME", "[Dedicated] " + myComName);
  860.                     myUsername = Config.getParam("NAME");
  861.                     return;
  862.  
  863.                 } else if (command.startsWith("comment ")) { // new command
  864.                     // prefix
  865.  
  866.                     CampaignData.mwlog.infoLog("Prefix command received from " + name);
  867.                     String myComComment = command.substring(("comment ").length()).trim();
  868.                     getConfig().setParam("COMMENT", myComComment);
  869.                     getConfig().saveConfig();
  870.                     setConfig();
  871.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " has set the comment to " + myComComment + " on " + myUsername);
  872.                     return;
  873.  
  874.                 } else if (command.startsWith("players ")) { // new command
  875.                     // prefix
  876.  
  877.                     CampaignData.mwlog.infoLog("Prefix command received from " + name);
  878.                     try {
  879.                         String numPlayers = command.substring(("players ").length()).trim();
  880.                         getConfig().setParam("MAXPLAYERS", numPlayers);
  881.                         getConfig().saveConfig();
  882.                         setConfig();
  883.                         sendChat(PROTOCOL_PREFIX + "c mm# " + name + " has set the max number of players to " + numPlayers + " on " + myUsername);
  884.                         return;
  885.                     } catch (Exception ex) {
  886.                         CampaignData.mwlog.errLog(ex);
  887.                         CampaignData.mwlog.errLog("Unable to convert number of players to int");
  888.                         return;
  889.                     }
  890.  
  891.                 } else if (command.equals("restartcount")) { // server port
  892.  
  893.                     CampaignData.mwlog.infoLog("Restartcount command received from " + name);
  894.                     sendChat(PROTOCOL_PREFIX + "mail " + name + ", My restart count is set to " + dedRestartAt + " my current game count is " + gameCount);
  895.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the restartcount command on " + myUsername);
  896.                     return;
  897.  
  898.                 } else if (command.startsWith("restartcount ")) {// new
  899.                     // server
  900.                     // port
  901.  
  902.                     CampaignData.mwlog.infoLog("restartcount change command received from " + name);
  903.                     try {
  904.                         dedRestartAt = Integer.parseInt(command.substring(("restartcount ").length()).trim());
  905.                     } catch (Exception ex) {
  906.                         CampaignData.mwlog.infoLog("Command error: " + command + ": bad counter.");
  907.                         return;
  908.                     }
  909.                     String restartString = Integer.toString(dedRestartAt);
  910.                     getConfig().setParam("DEDAUTORESTART", restartString);
  911.                     getConfig().saveConfig();
  912.                     setConfig();
  913.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " changed the restart count for " + myUsername + " to " + dedRestartAt);
  914.                     return;
  915.  
  916.                 } else if (command.equals("getupdateurl")) {// find out what url
  917.                     // the ded is set to
  918.                     // update with
  919.  
  920.                     CampaignData.mwlog.infoLog("GetUpdateUrl command received from " + name);
  921.                     String updateURL = getConfigParam("UPDATEURL");
  922.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the getUpdateURL command on " + myUsername);
  923.                     sendChat(PROTOCOL_PREFIX + "mail " + name + ", My update URL is " + updateURL + ".");
  924.                     return;
  925.  
  926.                 } else if (command.startsWith("setupdateurl ")) {
  927.  
  928.                     CampaignData.mwlog.infoLog("setUpdateURL command received from " + name);
  929.                     String myUpdateURL = command.substring(("setupdateurl ").length()).trim();
  930.                     getConfig().setParam("UPDATEURL", myUpdateURL);
  931.                     getConfig().saveConfig();
  932.                     setConfig();
  933.                     sendChat(PROTOCOL_PREFIX + "c mm# " + name + " used the set update url command to change the the update url to " + myUpdateURL + " on " + myUsername);
  934.                     return;
  935.  
  936.                 }
  937.  
  938.                 CampaignData.mwlog.infoLog("Command error: " + command + ": unknown command.");
  939.                 return;
  940.             }
  941.         }
  942.  
  943.         sendChat(PROTOCOL_PREFIX + "c mm# " + name + " tried to use the " + command + " on " + myUsername + ", but does not have ownership.");
  944.         sendChat(PROTOCOL_PREFIX + "mail " + name + ", You do not have management rights for this host!");
  945.         CampaignData.mwlog.infoLog("Command error: " + command + ": access denied for " + name + ".");
  946.     }
  947.  
  948.     protected void createProtCommands() {
  949.         addProtCommand(new CommPCmd(this));
  950.         addProtCommand(new PingPCmd(this));
  951.         addProtCommand(new PongPCmd(this));
  952.         addProtCommand(new AckSignonPCmd(this));
  953.     }
  954.  
  955.     protected void addProtCommand(IProtCommand command) {
  956.         ProtCommands.put(command.getName(), command);
  957.     }
  958.  
  959.     IProtCommand getProtCommand(String command) {
  960.         return ProtCommands.get(command);
  961.     }
  962.  
  963.     public String getLastQuery() {
  964.         return LastQuery;
  965.     }
  966.  
  967.     public void setLastQuery(String name) {
  968.         LastQuery = name;
  969.     }
  970.  
  971.     public int getMyStatus() {
  972.         return Status;
  973.     }
  974.  
  975.     public void setLastPing(long lastping) {
  976.         LastPing = lastping;
  977.     }
  978.  
  979.     public String getStatus() {
  980.         if (Status == STATUS_DISCONNECTED) {
  981.             return ("Not connected");
  982.         }
  983.         if (Status == STATUS_LOGGEDOUT) {
  984.             return ("Logged out");
  985.         }
  986.         return ("");
  987.     }
  988.  
  989.     public String getShortTime() {
  990.         mytime = new Date();
  991.         StringTokenizer s = new StringTokenizer(mytime.toString());
  992.         s.nextElement();
  993.         s.nextElement();
  994.         s.nextElement();
  995.         String t = (String) s.nextElement();
  996.         s = new StringTokenizer(t, ":");
  997.         String result = "[" + s.nextElement() + ":" + s.nextElement() + "] ";
  998.         return result;
  999.     }
  1000.  
  1001.     public void sendChat(String s) {
  1002.         // Sends the content of the Chatfield to the server
  1003.         // We need the StringTokenizer to enable Mulitline comments
  1004.         StringTokenizer st = new StringTokenizer(s, "\n");
  1005.  
  1006.         while (st.hasMoreElements()) {
  1007.             String str = (String) st.nextElement();
  1008.             // don't send empty lines
  1009.             if (!str.trim().equals("")) {
  1010.                 serverSend("CH|" + str);
  1011.             }
  1012.         }
  1013.     }
  1014.  
  1015.     public String doEscape(String str) {
  1016.  
  1017.         if (str.indexOf("<a href=\"MEKINFO") != -1) {
  1018.             return str;
  1019.         }
  1020.  
  1021.         // This function removes HTML Tags from the Chat, so no code may harm
  1022.         // anyone
  1023.         str = doEscapeString(str, '&', "&amp;");
  1024.         str = doEscapeString(str, '<', "&lt;");
  1025.         str = doEscapeString(str, '>', "&gt;");
  1026.         return str;
  1027.     }
  1028.  
  1029.     public String doEscapeString(String t, int character, String replace) {
  1030.  
  1031.         // find all occurences of character in t and replace them with replace
  1032.         int pos = t.indexOf(character);
  1033.         if (pos != -1) {
  1034.             String res = "";
  1035.             if (pos > 0) {
  1036.                 res += t.substring(0, pos);
  1037.             }
  1038.             res += replace;
  1039.             if (pos < t.length()) {
  1040.                 res += doEscapeString(t.substring(pos + 1), character, replace);
  1041.             }
  1042.             return res;
  1043.         }
  1044.         return t;
  1045.     }
  1046.  
  1047.     protected Vector<String> splitString(String string, String splitter) {
  1048.         Vector<String> vector = new Vector<String>(1, 1);
  1049.         String[] splitted = string.split(splitter);
  1050.         for (String element : splitted) {
  1051.             vector.add(element.trim());
  1052.         }
  1053.  
  1054.         /*
  1055.          * Remove empty entries from the set. Strip ",," and "" from the vector.
  1056.          * Helps with ignore and keyword lists.
  1057.          */
  1058.         Iterator<String> i = vector.iterator();
  1059.         while (i.hasNext()) {
  1060.             String currString = i.next();
  1061.             if (currString.trim().length() == 0) {
  1062.                 i.remove();
  1063.             }
  1064.         }
  1065.  
  1066.         return vector;
  1067.     }
  1068.  
  1069.     public TreeMap<String, MMGame> getServers() {
  1070.         return servers;
  1071.     }
  1072.  
  1073.     public synchronized CUser getUser(String name) {
  1074.  
  1075.         for (CUser currUser : Users) {
  1076.             if (currUser.getName().equalsIgnoreCase(name)) {
  1077.                 return currUser;
  1078.             }
  1079.         }
  1080.         CUser dummyUser = new CUser();
  1081.         return dummyUser;
  1082.     }
  1083.  
  1084.     public synchronized void clearUserCampaignData() {
  1085.         for (CUser currUser : Users) {
  1086.             currUser.clearCampaignData();
  1087.         }
  1088.     }
  1089.  
  1090.     public synchronized Collection<CUser> getUsers() {
  1091.         return Users;
  1092.     }
  1093.  
  1094.     public String getProtocolVersion() {
  1095.         return "4";
  1096.     }
  1097.  
  1098.     public void setUsername(String s) {
  1099.         myUsername = s.trim();
  1100.     }
  1101.  
  1102.     public void setPassword(String s) {
  1103.         password = s;
  1104.     }
  1105.  
  1106.     public String getUsername() {
  1107.         return myUsername;
  1108.     }
  1109.  
  1110.     public CConfig getConfig() {
  1111.         return (Config);
  1112.     }
  1113.  
  1114.     public void setConfig() {
  1115.         Config = new CConfig(false);
  1116.     }
  1117.  
  1118.     public String getConfigParam(String p) {
  1119.         String tparam = "";
  1120.  
  1121.         if (p.endsWith(":")) {
  1122.             p = p.substring(0, p.lastIndexOf(":"));
  1123.         }
  1124.         if (p.equals("NAME") && !(myUsername.equals(""))) {
  1125.             return myUsername;
  1126.         }
  1127.         if (p.equals("NAMEPASSWORD") && !password.equals("")) {
  1128.             return password;
  1129.         }
  1130.  
  1131.         tparam = Config.getParam(p);
  1132.         if (tparam == null) {
  1133.             tparam = "";
  1134.         }
  1135.  
  1136.         if (tparam.equals("") && p.equals("NAME") && isDedicated()) {
  1137.             CampaignData.mwlog.infoLog("Error: no dedicated name set.");
  1138.             System.exit(1);
  1139.         }
  1140.         return (tparam);
  1141.     }
  1142.  
  1143.     public void processIncoming(String incoming) {
  1144.         IProtCommand pcommand = null;
  1145.  
  1146.         // CampaignData.mwlog.infoLog("INCOMING: " + incoming);
  1147.         if (incoming.startsWith(PROTOCOL_PREFIX)) {
  1148.             incoming = incoming.substring(PROTOCOL_PREFIX.length());
  1149.             StringTokenizer ST = new StringTokenizer(incoming, PROTOCOL_DELIMITER);
  1150.             String s = ST.nextToken();
  1151.             pcommand = getProtCommand(s);
  1152.             if ((pcommand != null) && pcommand.check(s)) {
  1153.                 if (!pcommand.execute(incoming)) {
  1154.                     CampaignData.mwlog.infoLog("COMMAND ERROR: wrong protocol command executed or execution failed.");
  1155.                     CampaignData.mwlog.infoLog("COMMAND RECEIVED: " + incoming);
  1156.                 }
  1157.                 return;
  1158.             }
  1159.             if (pcommand == null) {
  1160.                 CampaignData.mwlog.infoLog("COMMAND ERROR: unknown protocol command from server.");
  1161.                 CampaignData.mwlog.infoLog("COMMAND RECEIVED: " + incoming);
  1162.                 return;
  1163.             }
  1164.         } else {
  1165.             CampaignData.mwlog.infoLog("COMMAND ERROR: received protocol command without protocol prefix.");
  1166.             CampaignData.mwlog.infoLog("COMMAND RECEIVED: " + incoming);
  1167.             return;
  1168.         }
  1169.     }
  1170.  
  1171.     public void connectionLost() {
  1172.  
  1173.         Status = STATUS_DISCONNECTED;
  1174.         if (SignOff) {
  1175.             return;
  1176.         }
  1177.  
  1178.         errorMessage("Connection lost.");
  1179.         if (isDedicated()) {
  1180.  
  1181.             // no point in having a server open w/o connection to campaign
  1182.             // server
  1183.             stopHost();
  1184.  
  1185.             // wait at least 90 seconds before trying to connect again
  1186.             try {
  1187.                 Thread.sleep(90000);
  1188.             } catch (Exception ex) {
  1189.                 CampaignData.mwlog.errLog(ex);
  1190.             }
  1191.  
  1192.             // keep retrying every two minutes after the first 90 sec downtime.
  1193.             while (Status == STATUS_DISCONNECTED) {
  1194.                 connectToServer(Config.getParam("SERVERIP"), Config.getIntParam("SERVERPORT"));
  1195.                 if (Status == STATUS_DISCONNECTED) {
  1196.                     CampaignData.mwlog.infoLog("Couldn't reconnect to server. Retrying in 120 seconds.");
  1197.                     try {
  1198.                         Thread.sleep(90000);
  1199.                     } catch (Exception exe) {
  1200.                         CampaignData.mwlog.errLog(exe);
  1201.                     }
  1202.                 }
  1203.             }
  1204.         } else {
  1205.             Users.clear();
  1206.         }
  1207.     }
  1208.  
  1209.     public void connectionEstablished() {
  1210.  
  1211.         LastPing = System.currentTimeMillis() / 1000;
  1212.         CampaignData.mwlog.errLog("Connected. Signing on.");
  1213.  
  1214.         String VersionSubID = new java.rmi.dgc.VMID().toString();
  1215.         StringTokenizer ST = new StringTokenizer(VersionSubID, ":");
  1216.  
  1217.         /*
  1218.          * If password is blank, send a filler password instead of an empty
  1219.          * token. This prevents the no-password "whitescreen" error. HACKY.
  1220.          *
  1221.          * It would be probably be better to actually fix the server SignOn so
  1222.          * an empty password creates a nobody, but this does the trick ...
  1223.          */
  1224.         String passToSend = getConfigParam("NAMEPASSWORD");
  1225.         if ((passToSend == null) || (passToSend.length() == 0)) {
  1226.             passToSend = "1337";
  1227.         }
  1228.  
  1229.         Connector.send(PROTOCOL_PREFIX + "signon\t" + getConfigParam("NAME") + "\t" + passToSend + "\t" + getProtocolVersion() + "\t" + Config.getParam("COLOR") + "\t" + CLIENT_VERSION + "\t" + ST.nextToken());
  1230.         Status = STATUS_LOGGEDOUT;
  1231.     }
  1232.  
  1233.     // IClient interface
  1234.     public void connectToServer() {
  1235.         connectToServer(Config.getParam("SERVERIP"), Config.getIntParam("SERVERPORT"));
  1236.     }
  1237.  
  1238.     public void connectToServer(String ip, int port) {
  1239.         if ((myUsername == null) || myUsername.equals("")) {
  1240.             errorMessage("Username not set.");
  1241.             return;
  1242.         }
  1243.         // connect to specific ip and port
  1244.         // System exits from connector on failure.
  1245.         Connector.connect(ip, port);
  1246.     }
  1247.  
  1248.     public void goodbye() {
  1249.         SignOff = true;
  1250.         if (Status != STATUS_DISCONNECTED) {
  1251.             // serverSend("GB");
  1252.             Connector.send(PROTOCOL_PREFIX + "signoff");
  1253.             dataFetcher.closeDataConnection();
  1254.             Connector.closeConnection();
  1255.         }
  1256.  
  1257.     }
  1258.  
  1259.     public CConnector getConnector() {
  1260.         return Connector;
  1261.     }
  1262.  
  1263.     public void serverSend(String s) {
  1264.         try {
  1265.             Connector.send(PROTOCOL_PREFIX + "comm" + "\t" + TransportCodec.encode(s));
  1266.         } catch (Exception e) {
  1267.             CampaignData.mwlog.errLog(e);
  1268.         }
  1269.     }
  1270.  
  1271.     public void startHost(boolean dedicated, boolean deploy, boolean loadSavegame) {
  1272.  
  1273.         // reread the config to allow the user to change setting during runtime
  1274.         String ip = "127.0.0.1";
  1275.         if (!getConfigParam("IP:").equals("")) {// IP Setting set, override IP
  1276.             // detection.
  1277.             try {
  1278.                 ip = getConfigParam("IP:");
  1279.                 InetAddress IA = InetAddress.getByName(ip); // Resolve Dyndns
  1280.                 // Entries
  1281.                 ip = IA.getHostAddress();
  1282.             } catch (Exception ex) {
  1283.                 return;
  1284.             }
  1285.         }
  1286.  
  1287.         String MMVersion = getserverConfigs("AllowedMegaMekVersion");
  1288.         if (!MMVersion.equals("-1") && !MMVersion.equalsIgnoreCase(MegaMek.VERSION)) {
  1289.             CampaignData.mwlog.errLog("You are using an invalid version of MegaMek. Please use version " + MMVersion);
  1290.             stopHost();
  1291.             updateDed();
  1292.             return;
  1293.         }
  1294.  
  1295.         if (servers.get(myUsername) != null) {
  1296.             if (isDedicated()) {
  1297.                 CampaignData.mwlog.errLog("Attempted to start a second host while host was already running.");
  1298.             } else {
  1299.                 String toUser = "CH|CLIENT: You already have a host open.";
  1300.                 doParseDataInput(toUser);
  1301.             }
  1302.             return;
  1303.         }
  1304.  
  1305.         // int port = Integer.parseInt(getConfigParam("PORT:"));
  1306.         int MaxPlayers = Integer.parseInt(getConfigParam("MAXPLAYERS:"));
  1307.         String comment = getConfigParam("COMMENT:");
  1308.         String gpassword = getConfigParam("GAMEPASSWORD:");
  1309.  
  1310.         if (gpassword == null) {
  1311.             gpassword = "";
  1312.         }
  1313.         try {
  1314.             myServer = new Server(gpassword, myPort);
  1315.         } catch (Exception ex) {
  1316.             try {
  1317.                 if (myServer == null) {
  1318.                     CampaignData.mwlog.errLog("Error opening dedicated server. Result = null host.");
  1319.                     CampaignData.mwlog.errLog(ex);
  1320.                 } else {
  1321.                     CampaignData.mwlog.errLog("Error opening dedicated server. Will attempt a .die().");
  1322.                     CampaignData.mwlog.errLog(ex);
  1323.                     myServer.die();
  1324.                     myServer = null;
  1325.                 }
  1326.             } catch (Exception e) {
  1327.                 CampaignData.mwlog.errLog("Further error while trying to clean up failed host attempt.");
  1328.                 CampaignData.mwlog.errLog(e);
  1329.             }
  1330.             return;
  1331.         }
  1332.  
  1333.         myServer.getGame().addGameListener(this);
  1334.         // Send the new game info to the Server
  1335.         serverSend("NG|" + new MMGame(myUsername, ip, myPort, MaxPlayers, MegaMek.VERSION + " " + MegaMek.TIMESTAMP, comment).toString());
  1336.         clearSavedGames();
  1337.         purgeOldLogs();
  1338.         IClientPreferences cs = PreferenceManager.getClientPreferences();
  1339.         cs.setStampFilenames(Boolean.parseBoolean(getserverConfigs("MMTimeStampLogFile")));
  1340.     }
  1341.  
  1342.     // Stop & send the close game event to the Server
  1343.     public void stopHost() {
  1344.  
  1345.         serverSend("CG");// send close game to server
  1346.         try {
  1347.             if (myServer != null) {
  1348.                 myServer.die();
  1349.             }
  1350.         } catch (Exception ex) {
  1351.             CampaignData.mwlog.errLog("Megamek Error:");
  1352.             CampaignData.mwlog.errLog(ex);
  1353.         }
  1354.         myServer = null;
  1355.     }
  1356.  
  1357.     public void resetGame() { // reset hosted game
  1358.         if (myServer != null) {
  1359.             myServer.resetGame();
  1360.             myServer.getGame().purgeGameListeners();
  1361.             myServer.getGame().addGameListener(this);
  1362.         }
  1363.     }
  1364.  
  1365.     public boolean loadGame(String filename) {// load saved game
  1366.         if ((myServer != null) && (filename != null) && !filename.equals("")) {
  1367.             boolean loaded = myServer.loadGame(new File("./savegames/", filename));
  1368.             myServer.getGame().addGameListener(this);
  1369.             return loaded;
  1370.         }
  1371.  
  1372.         // else (null server/filename)
  1373.         if (myServer == null) {
  1374.             CampaignData.mwlog.infoLog("MyServer == NULL!");
  1375.         }
  1376.         if (filename == null) {
  1377.             CampaignData.mwlog.infoLog("Filename == NULL!");
  1378.         } else if (filename.equals("")) {
  1379.             CampaignData.mwlog.infoLog("Filename == \"\"!");
  1380.         }
  1381.  
  1382.         return false;
  1383.     }
  1384.  
  1385.     public boolean loadGameWithFullPath(String filename) {// load saved game
  1386.         if ((myServer != null) && (filename != null) && !filename.equals("")) {
  1387.             boolean loaded = myServer.loadGame(new File(filename));
  1388.             myServer.getGame().addGameListener(this);
  1389.             return loaded;
  1390.  
  1391.         }
  1392.  
  1393.         // else (null server/filename)
  1394.         if (myServer == null) {
  1395.             CampaignData.mwlog.infoLog("MyServer == NULL!");
  1396.         }
  1397.         if (filename == null) {
  1398.             CampaignData.mwlog.infoLog("Filename == NULL!");
  1399.         } else if (filename.equals("")) {
  1400.             CampaignData.mwlog.infoLog("Filename == \"\"!");
  1401.         }
  1402.  
  1403.         return false;
  1404.     }
  1405.  
  1406.     public boolean isServerRunning() {
  1407.         return myServer != null;
  1408.     }
  1409.  
  1410.     public void closingGame(String hostName) {
  1411.  
  1412.         // update battles tab for all players, via server
  1413.         CampaignData.mwlog.infoLog("Leaving " + hostName);
  1414.         serverSend("LG|" + hostName);
  1415.  
  1416.         System.gc();
  1417.     }
  1418.  
  1419.     public Vector<IOption> getGameOptions() {
  1420.         return GameOptions;
  1421.     }
  1422.  
  1423.     public Dimension getMapSize() {
  1424.         return MapSize;
  1425.     }
  1426.  
  1427.     public Dimension getBoardSize() {
  1428.         return BoardSize;
  1429.     }
  1430.  
  1431.     protected class TimeOutThread extends Thread {
  1432.  
  1433.         MWDedHost mwdedhost;
  1434.  
  1435.         public TimeOutThread(MWDedHost client) {
  1436.             mwdedhost = client;
  1437.         }
  1438.  
  1439.         @Override
  1440.         public void run() {
  1441.             while (true) {
  1442.                 try {
  1443.                     Thread.sleep(mwdedhost.TimeOut * 100);
  1444.                 } catch (Exception ex) {
  1445.                     CampaignData.mwlog.errLog(ex);
  1446.                 }
  1447.                 if (mwdedhost.Status != MWDedHost.STATUS_DISCONNECTED) {
  1448.                     long timeout = (System.currentTimeMillis() / 1000) - LastPing;
  1449.                     if (timeout > mwdedhost.TimeOut) {
  1450.                         systemMessage("Ping timeout (" + timeout + " s)");
  1451.                         Connector.closeConnection();
  1452.                     }
  1453.                 } else {
  1454.                     LastPing = System.currentTimeMillis() / 1000;
  1455.                 }
  1456.             }
  1457.         }
  1458.     }
  1459.  
  1460.     public void loadServerMegaMekGameOptions() {
  1461.         try {
  1462.             dataFetcher.getServerMegaMekGameOptions();
  1463.         } catch (Exception ex) {
  1464.             CampaignData.mwlog.errLog("Error loading Server MegaMekGameOptions files");
  1465.             CampaignData.mwlog.errLog(ex);
  1466.         }
  1467.     }
  1468.  
  1469.     /**
  1470.      * Return the directory, where all cache files can go into. The dirname
  1471.      * depends on the server you connect.
  1472.      */
  1473.     public String getCacheDir() {
  1474.         // if (cacheDir == null) {
  1475.         // first access. Check if need to create directory.
  1476.         cacheDir = "data/servers/" + Config.getParam("SERVERIP") + "." + Config.getParam("SERVERPORT");
  1477.         File dir = new File(cacheDir);
  1478.         if (!dir.exists()) {
  1479.             dir.mkdirs();
  1480.         }
  1481.         // }
  1482.         return cacheDir;
  1483.     }
  1484.  
  1485.     /**
  1486.      * Changes the duty to a new status.
  1487.      *
  1488.      * @param newStatus
  1489.      */
  1490.     public void changeStatus(int newStatus) {
  1491.         Status = newStatus;
  1492.     }
  1493.  
  1494.     public boolean isAdmin() {
  1495.         return getUser(getUsername()).getUserlevel() >= 200;
  1496.     }
  1497.  
  1498.     public boolean isMod() {
  1499.         return getUser(getUsername()).getUserlevel() >= 100;
  1500.     }
  1501.  
  1502.     // this adds 1 to the number of games played and if it matched the restart
  1503.     // amount it restarts the ded.
  1504.     public void checkForRestart() {
  1505.         gameCount++;
  1506.  
  1507.         // only check for restart once every 30 seconds.
  1508.         if (System.currentTimeMillis() - 30000 < lastResetCheck) {
  1509.             return;
  1510.         }
  1511.  
  1512.         if (gameCount >= dedRestartAt) {
  1513.             CampaignData.mwlog.infoLog("System has reached " + gameCount + " games played and is restarting");
  1514.             try {
  1515.                 Thread.sleep(5000);
  1516.             }// give people time to vacate
  1517.             catch (Exception ex) {
  1518.                 CampaignData.mwlog.errLog(ex);
  1519.             }
  1520.             try {
  1521.                 stopHost();
  1522.                 Thread.sleep(5000);
  1523.             }// give people time to vacate
  1524.             catch (Exception ex) {
  1525.                 CampaignData.mwlog.errLog(ex);
  1526.             }
  1527.             restartDed();
  1528.         }
  1529.  
  1530.         lastResetCheck = System.currentTimeMillis();
  1531.     }
  1532.  
  1533.     public void clearSavedGames() {
  1534.  
  1535.         long daysInSeconds = ((long) savedGamesMaxDays) * 24 * 60 * 60 * 1000;
  1536.  
  1537.         File saveFiles = new File("./savegames/");
  1538.         if (!saveFiles.exists()) {
  1539.             return;
  1540.         }
  1541.         File[] fileList = saveFiles.listFiles();
  1542.         for (File savedFile : fileList) {
  1543.             long lastTime = savedFile.lastModified();
  1544.             if (savedFile.exists() && savedFile.isFile() && (lastTime < (System.currentTimeMillis() - daysInSeconds))) {
  1545.                 try {
  1546.                     CampaignData.mwlog.infoLog("Purging File: " + savedFile.getName() + " Time: " + lastTime + " purge Time: " + (System.currentTimeMillis() - daysInSeconds));
  1547.                     savedFile.delete();
  1548.                 } catch (Exception ex) {
  1549.                     CampaignData.mwlog.errLog("Error trying to delete these files!");
  1550.                     CampaignData.mwlog.errLog(ex);
  1551.                 }
  1552.             }
  1553.         }
  1554.     }
  1555.  
  1556.     public void purgeOldLogs() {
  1557.  
  1558.         long daysInSeconds = ((long) savedGamesMaxDays) * 24 * 60 * 60 * 1000;
  1559.  
  1560.         File saveFiles = new File("./logs/backup");
  1561.         if (!saveFiles.exists()) {
  1562.             return;
  1563.         }
  1564.         File[] fileList = saveFiles.listFiles();
  1565.         for (File savedFile : fileList) {
  1566.             long lastTime = savedFile.lastModified();
  1567.             if (savedFile.exists() && savedFile.isFile() && (lastTime < (System.currentTimeMillis() - daysInSeconds))) {
  1568.                 try {
  1569.                     CampaignData.mwlog.infoLog("Purging File: " + savedFile.getName() + " Time: " + lastTime + " purge Time: " + (System.currentTimeMillis() - daysInSeconds));
  1570.                     savedFile.delete();
  1571.                 } catch (Exception ex) {
  1572.                     CampaignData.mwlog.errLog("Error trying to delete these files!");
  1573.                     CampaignData.mwlog.errLog(ex);
  1574.                 }
  1575.             }
  1576.         }
  1577.     }
  1578.  
  1579.     public String getParanoidAutoSave() {
  1580.  
  1581.         File tempFile = new File("./savegames/");
  1582.         FilenameFilter filter = new AutoSaveFilter();
  1583.         File[] fileList = tempFile.listFiles(filter);
  1584.         long time = 0;
  1585.         String saveFile = "autosave.sav";
  1586.         for (File newFile : fileList) {
  1587.             if (newFile.lastModified() > time) {
  1588.                 time = newFile.lastModified();
  1589.                 saveFile = newFile.getName();
  1590.             }
  1591.         }
  1592.         return saveFile;
  1593.     }
  1594.  
  1595.     public void sendGameOptionsToServer() {
  1596.         StringBuilder packet = new StringBuilder();
  1597.  
  1598.         try {
  1599.             FileInputStream gameOptionsFile = new FileInputStream("./mmconf/gameoptions.xml");
  1600.             BufferedReader gameOptions = new BufferedReader(new InputStreamReader(gameOptionsFile));
  1601.  
  1602.             while (gameOptions.ready()) {
  1603.                 packet.append(gameOptions.readLine() + "#");
  1604.             }
  1605.         } catch (Exception ex) {
  1606.         }
  1607.  
  1608.         sendChat(MWDedHost.CAMPAIGN_PREFIX + "c servergameoptions#" + packet.toString());
  1609.     }
  1610.  
  1611.     public void retrieveOpData(String type, String data) {
  1612.  
  1613.         StringTokenizer st = new StringTokenizer(data, "#");
  1614.  
  1615.         String opName = st.nextToken();
  1616.  
  1617.         File opFile = new File("./data/operations/" + type);
  1618.  
  1619.         if (!opFile.exists()) {
  1620.             opFile.mkdirs();
  1621.         }
  1622.  
  1623.         opFile = new File("./data/operations/" + type + "/" + opName + ".txt");
  1624.         try {
  1625.             FileOutputStream out = new FileOutputStream(opFile);
  1626.             PrintStream p = new PrintStream(out);
  1627.             while (st.hasMoreTokens()) {
  1628.                 p.println(st.nextToken().replaceAll("\\(pound\\)", "#"));
  1629.             }
  1630.             p.close();
  1631.             out.close();
  1632.         } catch (Exception ex) {
  1633.             CampaignData.mwlog.errLog(ex);
  1634.         }
  1635.  
  1636.     }
  1637.  
  1638.     public void retrieveMul(String data) {
  1639.  
  1640.         StringTokenizer st = new StringTokenizer(data, "#");
  1641.  
  1642.         String mulName = st.nextToken();
  1643.  
  1644.         File mulFile = new File("./data/armies/");
  1645.  
  1646.         if (!mulFile.exists()) {
  1647.             mulFile.mkdirs();
  1648.         }
  1649.  
  1650.         mulFile = new File("./data/armies/" + mulName);
  1651.         try {
  1652.             FileOutputStream out = new FileOutputStream(mulFile);
  1653.             PrintStream p = new PrintStream(out);
  1654.             while (st.hasMoreTokens()) {
  1655.                 p.println(st.nextToken().replaceAll("\\(pound\\)", "#"));
  1656.             }
  1657.             p.close();
  1658.             out.close();
  1659.         } catch (Exception ex) {
  1660.             CampaignData.mwlog.errLog(ex);
  1661.         }
  1662.  
  1663.     }
  1664.  
  1665.     public boolean isDedicated() {
  1666.         return true;
  1667.     }
  1668.  
  1669.     public void updateParam(StringTokenizer ST) {
  1670.         try {
  1671.             getConfig().setParam(ST.nextToken(), ST.nextToken());
  1672.             getConfig().saveConfig();
  1673.             setConfig();
  1674.         } catch (Exception ex) {
  1675.             CampaignData.mwlog.errLog(ex);
  1676.         }
  1677.     }
  1678.  
  1679.     public Server getMyServer() {
  1680.         return myServer;
  1681.     }
  1682.  
  1683.     public boolean isUsingAdvanceRepairs() {
  1684.         return Boolean.parseBoolean(getserverConfigs("UseAdvanceRepair")) || Boolean.parseBoolean(getserverConfigs("UseSimpleRepair"));
  1685.     }
  1686.  
  1687.     /*
  1688.      * INNER CLASSES
  1689.      */
  1690.     static class AutoSaveFilter implements FilenameFilter {
  1691.         public boolean accept(File dir, String name) {
  1692.             return (name.startsWith("autosave"));
  1693.         }
  1694.     }
  1695.  
  1696.     private static class PurgeAutoSaves implements Runnable {
  1697.  
  1698.         public PurgeAutoSaves() {
  1699.             super();
  1700.         }
  1701.  
  1702.         public void run() {
  1703.             long twoHours = 2 * 60 * 60 * 1000;
  1704.             try {
  1705.                 while (true) {
  1706.                     File saveFiles = new File("./savegames");
  1707.                     if (!saveFiles.exists()) {
  1708.                         return;
  1709.                     }
  1710.                     FilenameFilter filter = new AutoSaveFilter();
  1711.                     File[] fileList = saveFiles.listFiles(filter);
  1712.                     for (File savedFile : fileList) {
  1713.                         long lastTime = savedFile.lastModified();
  1714.                         if (savedFile.exists() && savedFile.isFile() && (lastTime < (System.currentTimeMillis() - twoHours))) {
  1715.                             try {
  1716.                                 CampaignData.mwlog.infoLog("Purging File: " + savedFile.getName() + " Time: " + lastTime + " purge Time: " + (System.currentTimeMillis() - twoHours));
  1717.                                 savedFile.delete();
  1718.                             } catch (Exception ex) {
  1719.                                 CampaignData.mwlog.errLog("Error trying to delete these files!");
  1720.                                 CampaignData.mwlog.errLog(ex);
  1721.                             }
  1722.                         }
  1723.                     }
  1724.                     Thread.sleep(twoHours);
  1725.                 }
  1726.             } catch (Exception ex) {
  1727.                 return;
  1728.             }
  1729.         }
  1730.     }// end PurgeAutoSaves
  1731.  
  1732.     public void errorMessage(String message) {
  1733.         // TODO Auto-generated method stub
  1734.  
  1735.     }
  1736.  
  1737.     public void systemMessage(String message) {
  1738.         // TODO Auto-generated method stub
  1739.  
  1740.     }
  1741.  
  1742.     public void getServerConfigData() {
  1743.         try {
  1744.             dataFetcher.getServerConfigData(this);
  1745.         } catch (Exception ex) {
  1746.         }
  1747.     }
  1748.  
  1749.     public String getserverConfigs(String key) {
  1750.         if (serverConfigs.getProperty(key) == null) {
  1751.             return "-1";
  1752.         }
  1753.         return serverConfigs.getProperty(key).trim();
  1754.     }
  1755.  
  1756.     public Properties getServerConfigs() {
  1757.         return serverConfigs;
  1758.     }
  1759.  
  1760.     public void setBuildingTemplate(Buildings buildingTemplate) {
  1761.         this.buildingTemplate = buildingTemplate;
  1762.     }
  1763.  
  1764.     public Buildings getBuildingTemplate() {
  1765.         return buildingTemplate;
  1766.     }
  1767.  
  1768.     private void restartDed() {
  1769.         try {
  1770.             String memory = Config.getParam("DEDMEMORY");
  1771.             Runtime runTime = Runtime.getRuntime();
  1772.             String[] call =
  1773.                 { "java", "-Xmx" + memory + "m", "-jar", "MekWarsDed.jar" };
  1774.             runTime.exec(call);
  1775.             System.exit(0);
  1776.  
  1777.         } catch (Exception ex) {
  1778.             CampaignData.mwlog.errLog("Unable to find MekWarsDed.jar");
  1779.         }
  1780.     }
  1781.  
  1782.     private void updateDed() {
  1783.         try {
  1784.             if (myServer != null) {
  1785.                 myServer.die();
  1786.             }
  1787.             goodbye();
  1788.             Runtime runtime = Runtime.getRuntime();
  1789.             String[] call =
  1790.                 { "java", "-jar", "MekWarsAutoUpdate.jar", "DEDICATED", getConfigParam("DEDUPDATECOMMANDFILE") };
  1791.             runtime.exec(call);
  1792.         } catch (Exception ex) {
  1793.             CampaignData.mwlog.errLog(ex);
  1794.         }
  1795.         System.exit(0);// restart the ded
  1796.     }
  1797.  
  1798.     /**
  1799.      * redundant code since MM does not always send a discon event.
  1800.      */
  1801.     public void gamePlayerStatusChange(GameEvent e) {
  1802.     }
  1803.  
  1804.     public void gameTurnChange(GameTurnChangeEvent e) {
  1805.         if (myServer != null) {
  1806.             if (turn == 0) {
  1807.                 serverSend("SHS|" + getUsername() + "|Running");
  1808.             } else if ((myServer.getGame().getPhase() != currentPhase) && myServer.getGame().getOptions().booleanOption("paranoid_autosave")) {
  1809.                 sendServerGameUpdate();
  1810.                 currentPhase = myServer.getGame().getPhase();
  1811.             }
  1812.             turn += 1;
  1813.  
  1814.         }
  1815.     }
  1816.  
  1817.     public void gamePhaseChange(GamePhaseChangeEvent e) {
  1818.  
  1819.         try {
  1820.  
  1821.             if (myServer.getGame().getPhase() == IGame.Phase.PHASE_VICTORY) {
  1822.  
  1823.                 sendGameReport();
  1824.                 CampaignData.mwlog.infoLog("GAME END");
  1825.  
  1826.             }// end victory
  1827.  
  1828.             /*
  1829.              * Reporting phases show deaths - units that try to stand and blow
  1830.              * their ammo, units that have ammo explode from head, etc. This is
  1831.              * also an opportune time to correct isses with the gameRemoveEntity
  1832.              * ISU's. Removals happen ASAP, even if the removal condition and
  1833.              * final condition of the unit are not the same (ie - remove on
  1834.              * Engine crits even when a CT core comes later in the round).
  1835.              */
  1836.             else if (myServer.getGame().getPhase() == IGame.Phase.PHASE_END_REPORT) {
  1837.                 sendServerGameUpdate();
  1838.             }
  1839.  
  1840.         }// end try
  1841.         catch (Exception ex) {
  1842.             CampaignData.mwlog.errLog("Error reporting game!");
  1843.             CampaignData.mwlog.errLog(ex);
  1844.         }
  1845.     }
  1846.  
  1847.     /*
  1848.      * When an entity is removed from play, check the reason. If the unit is
  1849.      * ejected, captured or devestated and the player is invovled in the game at
  1850.      * hand, report the removal to the server. The server stores these reports
  1851.      * in pilotTree and deathTree in order to auto-resolve games after a player
  1852.      * disconnects. NOTE: This send thefirst possible removal condition, which
  1853.      * means that a unit which is simultanously head killed and then CT cored
  1854.      * will show as salvageable.
  1855.      */
  1856.     public void gameEntityRemove(GameEntityRemoveEvent e) {// only send if the
  1857.         // player is
  1858.         // actually involved
  1859.         // in the game
  1860.  
  1861.         // get the entity
  1862.         megamek.common.Entity removedE = e.getEntity();
  1863.         if (removedE.getOwner().getName().startsWith("War Bot")) {
  1864.             return;
  1865.         }
  1866.  
  1867.         String toSend = SerializeEntity.serializeEntity(removedE, true, false, isUsingAdvanceRepairs());
  1868.         serverSend("IPU|" + toSend);
  1869.     }
  1870.  
  1871.     public void gamePlayerConnected(GamePlayerConnectedEvent e) {
  1872.     }
  1873.  
  1874.     public void gamePlayerDisconnected(GamePlayerDisconnectedEvent e) {
  1875.     }
  1876.  
  1877.     public void gamePlayerChange(GamePlayerChangeEvent e) {
  1878.     }
  1879.  
  1880.     public void gamePlayerChat(GamePlayerChatEvent e) {
  1881.     }
  1882.  
  1883.     public void gameReport(GameReportEvent e) {
  1884.     }
  1885.  
  1886.     public void gameEnd(GameEndEvent e) {
  1887.     }
  1888.  
  1889.     public void gameBoardNew(GameBoardNewEvent e) {
  1890.     }
  1891.  
  1892.     public void gameBoardChanged(GameBoardChangeEvent e) {
  1893.     }
  1894.  
  1895.     public void gameSettingsChange(GameSettingsChangeEvent e) {
  1896.     }
  1897.  
  1898.     public void gameMapQuery(GameMapQueryEvent e) {
  1899.     }
  1900.  
  1901.     public void gameEntityNew(GameEntityNewEvent e) {
  1902.     }
  1903.  
  1904.     public void gameEntityNewOffboard(GameEntityNewOffboardEvent e) {
  1905.     }
  1906.  
  1907.     public void gameEntityChange(GameEntityChangeEvent e) {
  1908.     }
  1909.  
  1910.     public void gameNewAction(GameNewActionEvent e) {
  1911.     }
  1912.  
  1913.     public int getBuildingsLeft() {
  1914.         Enumeration<Building> buildings = myServer.getGame().getBoard().getBuildings();
  1915.         int buildingCount = 0;
  1916.         while (buildings.hasMoreElements()) {
  1917.             buildings.nextElement();
  1918.             buildingCount++;
  1919.         }
  1920.         return buildingCount;
  1921.     }
  1922.  
  1923.     private void sendServerGameUpdate() {
  1924.         // Report the mech stat
  1925.  
  1926.         // Only send data for units currently on the board.
  1927.         // any units removed from play will have already sent thier final
  1928.         // update.
  1929.         Enumeration<Entity> en = Collections.enumeration(myServer.getGame().getEntitiesVector());
  1930.         while (en.hasMoreElements()) {
  1931.             Entity ent = en.nextElement();
  1932.             if (ent.getOwner().getName().startsWith("War Bot") || (!(ent instanceof MechWarrior) && !UnitUtils.hasArmorDamage(ent) && !UnitUtils.hasISDamage(ent) && !UnitUtils.hasCriticalDamage(ent) && !UnitUtils.hasLowAmmo(ent) && !UnitUtils.hasEmptyAmmo(ent))) {
  1933.                 continue;
  1934.             }
  1935.             if ((ent instanceof Mech) && (ent.getInternal(Mech.LOC_CT) <= 0)) {
  1936.                 serverSend("IPU|" + SerializeEntity.serializeEntity(ent, true, true, isUsingAdvanceRepairs()));
  1937.             } else {
  1938.                 serverSend("IPU|" + SerializeEntity.serializeEntity(ent, true, false, isUsingAdvanceRepairs()));
  1939.             }
  1940.         }
  1941.     }
  1942.  
  1943.     public static StringBuilder prepareReport(GameInterface myGame, boolean usingAdvancedRepairs, Buildings buildingTemplate) {
  1944.         StringBuilder result = new StringBuilder();
  1945.         String name = "";
  1946.         // Parse the real playername from the Modified In game one..
  1947.         String winnerName = "";
  1948.         if (myGame.hasWinner()) {
  1949.  
  1950.             int numberOfWinners = 0;
  1951.             // Multiple Winners
  1952.             List<String> winners = myGame.getWinners();
  1953.             for (String winner: winners){
  1954.                 StringTokenizer st = new StringTokenizer(winner, "~");
  1955.                 name = "";
  1956.                 while (st.hasMoreElements()) {
  1957.                     name = st.nextToken().trim();
  1958.                 }
  1959.                 // some of the players set themselves as a team of 1.
  1960.                 // This keeps that from happening.
  1961.                 if (numberOfWinners > 0) {
  1962.                     winnerName += "*";
  1963.                 }
  1964.                 numberOfWinners++;
  1965.  
  1966.                 winnerName += name;
  1967.             }
  1968.             if (winnerName.endsWith("*")) {
  1969.                 winnerName = winnerName.substring(0, winnerName.length() - 1);
  1970.             }
  1971.             winnerName += "#";
  1972.         }
  1973.  
  1974.         else {
  1975.             winnerName = "DRAW#";
  1976.         }
  1977.  
  1978.         result.append(winnerName);
  1979.  
  1980.         // Report the mech stat
  1981.         Enumeration<Entity> en = myGame.getDevastatedEntities();
  1982.         while (en.hasMoreElements()) {
  1983.             Entity ent = en.nextElement();
  1984.             if (ent.getOwner().getName().startsWith("War Bot")) {
  1985.                 continue;
  1986.             }
  1987.             result.append(SerializeEntity.serializeEntity(ent, true, false, usingAdvancedRepairs));
  1988.             result.append("#");
  1989.         }
  1990.         en = myGame.getGraveyardEntities();
  1991.         while (en.hasMoreElements()) {
  1992.             Entity ent = en.nextElement();
  1993.             if (ent.getOwner().getName().startsWith("War Bot")) {
  1994.                 continue;
  1995.             }
  1996.             result.append(SerializeEntity.serializeEntity(ent, true, false, usingAdvancedRepairs));
  1997.             result.append("#");
  1998.  
  1999.         }
  2000.         en = myGame.getEntities();
  2001.         while (en.hasMoreElements()) {
  2002.             Entity ent = en.nextElement();
  2003.             if (ent.getOwner().getName().startsWith("War Bot")) {
  2004.                 continue;
  2005.             }
  2006.             result.append(SerializeEntity.serializeEntity(ent, true, false, usingAdvancedRepairs));
  2007.             result.append("#");
  2008.         }
  2009.         en = myGame.getRetreatedEntities();
  2010.         while (en.hasMoreElements()) {
  2011.             Entity ent = en.nextElement();
  2012.             if (ent.getOwner().getName().startsWith("War Bot")) {
  2013.                 continue;
  2014.             }
  2015.             result.append(SerializeEntity.serializeEntity(ent, true, false, usingAdvancedRepairs));
  2016.             result.append("#");
  2017.         }
  2018.  
  2019.         if (buildingTemplate != null) {
  2020.             result.append("BL*" + buildingTemplate);
  2021.         }
  2022.         CampaignData.mwlog.infoLog("CR|" + result);
  2023.         return result;
  2024.     }
  2025.  
  2026.    
  2027.     private void sendGameReport() {
  2028.         if (myServer == null) {
  2029.             return;
  2030.         }
  2031.        
  2032.         //GameReporter.prepareReport(myGame, usingAdvancedRepairs, buildingTemplate)
  2033.  
  2034.         StringBuilder result = prepareReport(new GameWrapper(myServer.getGame()), isUsingAdvanceRepairs(), buildingTemplate);
  2035.         serverSend("CR|" + result.toString());
  2036.        
  2037. /*        StringBuilder result = new StringBuilder();
  2038.         String name = "";
  2039.         // Parse the real playername from the Modified In game one..
  2040.         String winnerName = "";
  2041.         if (myServer.getGame().getVictoryTeam() != Player.TEAM_NONE) {
  2042.  
  2043.             int numberOfWinners = 0;
  2044.             // Multiple Winners
  2045.             Enumeration<Player> en = myServer.getGame().getPlayers();
  2046.             while (en.hasMoreElements()) {
  2047.                 Player p = en.nextElement();
  2048.                 if (p.getTeam() == myServer.getGame().getVictoryTeam()) {
  2049.                     StringTokenizer st = new StringTokenizer(p.getName().trim(), "~");
  2050.                     name = "";
  2051.                     while (st.hasMoreElements()) {
  2052.                         name = st.nextToken().trim();
  2053.                     }
  2054.                     // some of the players set themselves as a team of 1.
  2055.                     // This keeps that from happening.
  2056.                     if (numberOfWinners > 0) {
  2057.                         winnerName += "*";
  2058.                     }
  2059.                     numberOfWinners++;
  2060.  
  2061.                     winnerName += name;
  2062.                 }
  2063.             }
  2064.             if (winnerName.endsWith("*")) {
  2065.                 winnerName = winnerName.substring(0, winnerName.length() - 1);
  2066.             }
  2067.             winnerName += "#";
  2068.         }
  2069.  
  2070.         // Only one winner
  2071.         else {
  2072.             if (myServer.getGame().getVictoryPlayerId() == Player.PLAYER_NONE) {
  2073.                 winnerName = "DRAW#";
  2074.             } else {
  2075.                 winnerName = myServer.getGame().getPlayer(myServer.getGame().getVictoryPlayerId()).getName();
  2076.                 StringTokenizer st = new StringTokenizer(winnerName, "~");
  2077.                 name = "";
  2078.                 while (st.hasMoreElements()) {
  2079.                     name = st.nextToken().trim();
  2080.                 }
  2081.                 winnerName = name + "#";
  2082.             }
  2083.         }
  2084.  
  2085.         result.append(winnerName);
  2086.  
  2087.         // Report the mech stat
  2088.         Enumeration<Entity> en = myServer.getGame().getDevastatedEntities();
  2089.         while (en.hasMoreElements()) {
  2090.             Entity ent = en.nextElement();
  2091.             if (ent.getOwner().getName().startsWith("War Bot")) {
  2092.                 continue;
  2093.             }
  2094.             result.append(SerializeEntity.serializeEntity(ent, true, false, isUsingAdvanceRepairs()));
  2095.             result.append("#");
  2096.         }
  2097.         en = myServer.getGame().getGraveyardEntities();
  2098.         while (en.hasMoreElements()) {
  2099.             Entity ent = en.nextElement();
  2100.             if (ent.getOwner().getName().startsWith("War Bot")) {
  2101.                 continue;
  2102.             }
  2103.             result.append(SerializeEntity.serializeEntity(ent, true, false, isUsingAdvanceRepairs()));
  2104.             result.append("#");
  2105.  
  2106.         }
  2107.         en = myServer.getGame().getEntities();
  2108.         while (en.hasMoreElements()) {
  2109.             Entity ent = en.nextElement();
  2110.             if (ent.getOwner().getName().startsWith("War Bot")) {
  2111.                 continue;
  2112.             }
  2113.             result.append(SerializeEntity.serializeEntity(ent, true, false, isUsingAdvanceRepairs()));
  2114.             result.append("#");
  2115.         }
  2116.         en = myServer.getGame().getRetreatedEntities();
  2117.         while (en.hasMoreElements()) {
  2118.             Entity ent = en.nextElement();
  2119.             if (ent.getOwner().getName().startsWith("War Bot")) {
  2120.                 continue;
  2121.             }
  2122.             result.append(SerializeEntity.serializeEntity(ent, true, false, isUsingAdvanceRepairs()));
  2123.             result.append("#");
  2124.         }
  2125.  
  2126.         if (getBuildingTemplate() != null) {
  2127.             result.append("BL*" + getBuildingsLeft());
  2128.         }
  2129.         CampaignData.mwlog.infoLog("CR|" + result);
  2130.  
  2131.         // send the autoreport
  2132.         serverSend("CR|" + result.toString());*/
  2133.  
  2134.         // we may assume that a server which reports a game is no longer
  2135.         // "Running"
  2136.         serverSend("SHS|" + myUsername + "|Open");
  2137.  
  2138.         // myServer.resetGame();
  2139.  
  2140.         if (isDedicated()) {
  2141.             checkForRestart();
  2142.         }
  2143.     }
  2144.  
  2145. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement