diff --git a/MekWarsClient/build.gradle b/MekWarsClient/build.gradle index 1ae44008..9de3751c 100644 --- a/MekWarsClient/build.gradle +++ b/MekWarsClient/build.gradle @@ -91,16 +91,14 @@ tasks.named('installDist') { distributions { main { contents { + from stageFiles from jar - // execute build with -PexcludeData to skip data copy if (!project.hasProperty('excludeData')) { from (project.sourceSets.main.runtimeClasspath.files .findAll { it.name.endsWith(".jar") }) { into lib } - - from stageFiles from "${mmDir}/megamek/build/libs/MegaMek.jar" from "${mmDir}/megamek/build/files" } diff --git a/MekWarsClient/src/mekwars/admin/AdminMapPopupMenu.java b/MekWarsClient/src/mekwars/admin/AdminMapPopupMenu.java index f1406bc3..cbf12f27 100644 --- a/MekWarsClient/src/mekwars/admin/AdminMapPopupMenu.java +++ b/MekWarsClient/src/mekwars/admin/AdminMapPopupMenu.java @@ -161,7 +161,7 @@ public void actionPerformed(ActionEvent ex) { item = new JMenuItem("Destroy Planet"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ex) { - int result = JOptionPane.showConfirmDialog(new JFrame(),"Are you Sure you want to Destroy this planet?"); + int result = JOptionPane.showConfirmDialog(new JFrame(),"Are you sure you want to Destroy this planet?"); if (result == JOptionPane.YES_OPTION) { mwclient.sendChat(GameHost.CAMPAIGN_PREFIX + "c admindestroyplanet#"+ pname); diff --git a/MekWarsClient/src/mekwars/client/MWClient.java b/MekWarsClient/src/mekwars/client/MWClient.java index 426828b3..ff1af153 100644 --- a/MekWarsClient/src/mekwars/client/MWClient.java +++ b/MekWarsClient/src/mekwars/client/MWClient.java @@ -22,7 +22,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; @@ -31,9 +30,7 @@ import java.io.PrintStream; import java.lang.management.ManagementFactory; import java.lang.management.RuntimeMXBean; -import java.lang.reflect.Constructor; import java.net.ConnectException; -import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.SocketException; import java.nio.file.Files; @@ -42,7 +39,6 @@ import java.security.MessageDigest; import java.text.MessageFormat; import java.text.NumberFormat; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -57,7 +53,6 @@ import java.util.TreeSet; import java.util.Vector; import javax.swing.JOptionPane; -import megamek.MMConstants; import megamek.Version; import megamek.client.ui.swing.GameOptionsDialog; import megamek.common.CriticalSlot; @@ -65,20 +60,15 @@ import megamek.common.EquipmentType; import megamek.common.Game; import megamek.common.Mech; -import megamek.common.MechWarrior; import megamek.common.event.GameCFREvent; import megamek.common.event.GameEvent; import megamek.common.icons.Camouflage; import megamek.common.options.GameOptions; import megamek.common.options.IBasicOption; -import megamek.common.preference.ClientPreferences; -import megamek.common.preference.PreferenceManager; -import megamek.server.GameManager; import megamek.server.Server; import mekwars.client.campaign.CCampaign; import mekwars.client.campaign.CPlayer; import mekwars.client.campaign.CUnit; -import mekwars.client.cmd.Command; import mekwars.client.common.campaign.clientutils.GameHost; import mekwars.client.common.campaign.clientutils.protocol.CConnector; import mekwars.client.common.campaign.clientutils.protocol.IClient; @@ -109,7 +99,6 @@ import mekwars.common.PlanetEnvironment; import mekwars.common.Unit; import mekwars.common.campaign.Buildings; -import mekwars.common.campaign.clientutils.SerializeEntity; import mekwars.common.util.GameReport; import mekwars.common.util.ThreadManager; import mekwars.common.util.TokenReader; @@ -139,8 +128,6 @@ public final class MWClient extends GameHost implements IClient { private SoundManager soundManager; private String password = ""; - private String myDedOwners = ""; - private int myPort = -1; private int gameCount = 0; // number of games played on a ded private long lastResetCheck = System.currentTimeMillis(); private int dedRestartAt = 50; // number of games played on a ded before auto @@ -169,17 +156,10 @@ public final class MWClient extends GameHost implements IClient { private CCampaign theCampaign; private CPlayer myPlayer; - int Status = STATUS_DISCONNECTED; int LastStatus = STATUS_DISCONNECTED; TreeMap GUICommands = new TreeMap(); - /** - * Maps the task prefixes as HS, PL, SP etc. to a command under package cmd. - * key: String, value: cmd.Command - */ - HashMap commands = new HashMap(); - String LastQuery = ""; // receiver of last mail Vector IgnorePublic = new Vector(1, 1); // people whose // public messages @@ -246,17 +226,6 @@ public MWClient(GUIClientConfig config) { ProtCommands = new TreeMap<>(); Config = config; - if (isDedicated()) { - try { - Runtime runTime = Runtime.getRuntime(); - String[] call = { "java", "-Xmx512m", "-jar", "MekWarsDed.jar" }; - runTime.exec(call); - System.exit(0); - } catch (Exception ex) { - LOGGER.error("Unable to find MekWarsDed.jar"); - } - } - try { RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean(); LOGGER.info("RT Info: " + rt.getName()); @@ -266,77 +235,33 @@ public MWClient(GUIClientConfig config) { Connector = new CConnector(this); Users = Collections.synchronizedList(new Vector(1, 1)); + theCampaign = new CCampaign(this); + myPlayer = theCampaign.getPlayer(); + createProtCommands(); + createGUICommands(); - // Non-ded's get a GUI, show signon dialog, etc. - if (!isDedicated()) { - - theCampaign = new CCampaign(this); - myPlayer = theCampaign.getPlayer(); - createProtCommands(); - createGUICommands(); - - hpgClient = new HPGClient(this); - try { - String trackerEnabledConfig = getConfigParam("TrackerEnabled"); - if (Boolean.parseBoolean(trackerEnabledConfig)) { - String trackerAddress = getConfigParam("TrackerAddress"); - hpgClient.connect(new InetSocketAddress(trackerAddress, - HPGClient.TRACKER_PORT)); - } - } catch (IOException e) { - LOGGER.error("Unable to connect to HPGTracker"); + hpgClient = new HPGClient(this); + try { + String trackerEnabledConfig = getConfigParam("TrackerEnabled"); + if (Boolean.parseBoolean(trackerEnabledConfig)) { + String trackerAddress = getConfigParam("TrackerAddress"); + hpgClient.connect(new InetSocketAddress(trackerAddress, + HPGClient.TRACKER_PORT)); } + } catch (IOException e) { + LOGGER.error("Unable to connect to HPGTracker"); + } - guiClient = new GUIClient(this, config); - guiClient.init(); + guiClient = new GUIClient(this, config); + guiClient.init(); soundManager = new SoundManager(config); - // Dedicated servers have no GUI, no signon dialogs, etc. - } else { - createProtCommands(); - dataFetcher = new DataFetchClient(Integer.parseInt(Config - .getParam("DATAPORT")), Integer.parseInt(Config - .getParam("SOCKETTIMEOUTDELAY"))); - dataFetcher.setData(Config.getParam("SERVERIP"), FileSystem.getInstance().getConfigDir().toString()); - try { - dataFetcher.getServerConfigData(this); - } catch (Exception ex) { - LOGGER.error("Error While getting server config file."); - LOGGER.catching(ex); - } - - dataFetcher.closeDataConnection(); - - // Remove any MM option files that deds may have. - File localGameOptions = new File("./mmconf"); - try { - if (localGameOptions.exists()) { - localGameOptions = new File("./mmconf/gameoptions.xml"); - if (localGameOptions.exists()) { - localGameOptions.delete(); - } - } - } catch (Exception ex) { - LOGGER.catching(ex); - } - getData(); - } myUsername = getConfigParam("NAME"); - // if this is dedicated host, we mark its name with "[Dedicated]" stamp - if (isDedicated() && !myUsername.startsWith("[Dedicated]")) { - // set New timestamp - dataFetcher.setLastTimestamp(new Date(System.currentTimeMillis())); - dataFetcher.store(); - Config.setParam("NAME", "[Dedicated] " + Config.getParam("NAME")); - myUsername = Config.getParam("NAME"); - } - dedRestartAt = Integer.parseInt(getConfigParam("DEDAUTORESTART")); savedGamesMaxDays = Integer .parseInt(getConfigParam("MAXSAVEDGAMEDAYS")); - myDedOwners = getConfigParam("DEDICATEDOWNERNAME"); myPort = Integer.parseInt(getConfigParam("PORT")); IgnorePublic = splitString(Config.getParam("IGNOREPUBLIC"), ","); IgnoreHouse = splitString(Config.getParam("IGNOREHOUSE"), ","); @@ -351,43 +276,6 @@ public MWClient(GUIClientConfig config) { LOGGER.info("Starting pAS"); PurgeAutoSaves pAS = new PurgeAutoSaves(); new Thread(pAS).start(); - /* - * Load IP and Port to connect to from the config. In older code the - * signon dialog was shown at this point. The dialog has been moved, and - * is now displayed -before- the client attempts to fetch vital data, - * like the map. - */ - - /* - * Non-dedicated. Draw the UI, shut down the splash screen, and then - * request any stored messages. - */ - - // repeated connection attempts for dedicated hosts. - if (isDedicated()) { - String chatServerIP = ""; - int chatServerPort = -1; - try { - chatServerIP = Config.getParam("SERVERIP"); - chatServerPort = Config.getIntParam("SERVERPORT"); - } catch (Exception e) { - LOGGER.catching(e); - System.exit(1); - } - int retryCount = 0; - while ((Status == STATUS_DISCONNECTED) && (retryCount++ < 20)) { - connectToServer(chatServerIP, chatServerPort); - if (Status == STATUS_DISCONNECTED) { - LOGGER.info("Couldn't connect to server. Retrying in 90 seconds."); - try { - Thread.sleep(90000); - } catch (Exception exe) { - LOGGER.catching(exe); - System.exit(2); - } - } - } - }// end else(is Dedicated host) // start checking for timeouts TimeOut = Long.parseLong(Config.getParam("TIMEOUT")); @@ -433,6 +321,7 @@ public SoundManager getSoundManager() { * Info (TI|TIMETILLNEXT) SP = Show PopupWindow SM = Show Miscellaneous * (Puts text into Misc Tab) */ + @Override public synchronized void doParseDataInput(String input) { // non-null main frame, unbuffer or just pass through @@ -473,707 +362,6 @@ public byte[] createChecksum(String filename) throws Exception { return complete.digest(); } - /* - * Actual GUI-mode parseData. Before we started streaming data over the chat - * part, this was called directly. Now we buffer all incoming non-data chat - * and spit it out at once when the GUI draws. Once the GUI is up, this is - * called by a simple pass through from doParseDataInput(), above. Ded's - * call the helper directly to bypass the buffer. - */ - private void doParseDataHelper(String input) { - try { - - // 0-length input is spurious call from MWClient constructor. - if (input.length() == 0) { - return; - } - - StringTokenizer ST = null; - String task = null; - - // debug info - LOGGER.debug(input); - - // Create a String Tokenizer to parse the elements of the input - ST = new StringTokenizer(input, COMMAND_DELIMITER); - task = ST.nextToken(); - - if (!commands.containsKey(task)) { - try { - Class cmdClass = Class.forName(getClass().getPackage() - .getName() + ".cmd." + task); - Constructor c = cmdClass - .getConstructor(new Class[] { MWClient.class }); - Command cmd = (Command) c - .newInstance(new Object[] { this }); - commands.put(task, cmd); - } catch (Exception e) { - LOGGER.catching(e); - } - } - if (commands.containsKey(task)) { - commands.get(task).execute(input); - } - } catch (Exception ex) { - LOGGER.catching(ex); - } - } - - public synchronized void parseDedDataInput(String data) { - StringTokenizer st, own; - String name, owner, command; - int port; - - /* - * New users, report requests and data should be sent to standard - * processor. PM's are checked below, and all other commands are tossed - * (e.g. - CH). Note that ded's bypass the doParseDeda() buffering - * process (never have a main frame, so no null check or buffer needed) - * and call doParseDataHelper() directly. - */ - if (data.startsWith("US|") || data.startsWith("NU|") - || data.startsWith("UG|") || data.startsWith("RGTS|") - || data.startsWith("DSD|") || data.startsWith("USD|")) { - doParseDataHelper(data);// bypass the buffering process - - // ded's never have a main fraime - return; - } - - // only parse PM's for commands - if (!data.startsWith("PM|")) { - return; - } - - data = data.substring(3);// strip "PM|" - st = new StringTokenizer(data, "|"); - own = new StringTokenizer(myDedOwners, "$"); - - name = st.nextToken().trim(); - if (!st.hasMoreTokens()) { - return; - } // it's not real chat message - if (name.equals(myUsername)) { - return; - } // server can't send commands to itself - command = st.nextToken().trim(); - - /* - * Commands that can be executed by ANY user. - */ - if (command.equals("checkrestartcount")) {// check the restart amount. - checkForRestart(); - return; - } else if (command.equals("displaymegameklog")) { // display - // megameklog.txt - LOGGER.info("display megameklog command received from {}", name); - try { - File logFile = new File("./logs/megameklog.txt"); - FileInputStream fis = new FileInputStream(logFile); - BufferedReader dis = new BufferedReader(new InputStreamReader( - fis)); - sendChat(IClient.PROTOCOL_PREFIX + "c sendtomisc#" + name - + "#MegaMek Log from " + myUsername); - int counter = 0; - while (dis.ready()) { - sendChat(IClient.PROTOCOL_PREFIX + "c sendtomisc#" + name + "#" - + dis.readLine()); - // problems with huge logs getting shoved down players - // throats so a 100ms delay should allow - // the message queue to breath. - if ((counter++ % 100) == 0) { - try { - Thread.sleep(100); - } catch (Exception ex) { - // Do nothing - } - } - } - fis.close(); - dis.close(); - - } catch (Exception ex) { - // do nothing? - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the display megamek logs command on " + myUsername); - return; - } else if (command.equals("displaydederrorlog")) { // display - // error.0 - LOGGER.info("display ded error command received from {}", name); - try { - File logFile = new File("./logs/errlog.0"); - FileInputStream fis = new FileInputStream(logFile); - BufferedReader dis = new BufferedReader(new InputStreamReader( - fis)); - sendChat(IClient.PROTOCOL_PREFIX + "c sendtomisc#" + name - + "#Error Log from " + myUsername); - int counter = 0; - while (dis.ready()) { - sendChat(IClient.PROTOCOL_PREFIX + "c sendtomisc#" + name + "#" - + dis.readLine()); - // problems with huge logs getting shoved down players - // throats so a 100ms delay should allow - // the message queue to breath. - if ((counter++ % 100) == 0) { - try { - Thread.sleep(100); - } catch (Exception ex) { - // Do nothing - } - } - } - fis.close(); - dis.close(); - - } catch (Exception ex) { - // do nothing? - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the display ded error log command on " - + myUsername); - return; - } else if (command.equals("displaydedlog")) { // display - // log.0 - LOGGER.info("display ded log command received from {}", name); - try { - File logFile = new File("./logs/infolog.0"); - FileInputStream fis = new FileInputStream(logFile); - BufferedReader dis = new BufferedReader(new InputStreamReader( - fis)); - sendChat(IClient.PROTOCOL_PREFIX + "c sendtomisc#" + name - + "#Ded Log from " + myUsername); - int counter = 0; - while (dis.ready()) { - sendChat(IClient.PROTOCOL_PREFIX + "c sendtomisc#" + name + "#" - + dis.readLine()); - // problems with huge logs getting shoved down players - // throats so a 100ms delay should allow - // the message queue to breath. - if ((counter++ % 100) == 0) { - try { - Thread.sleep(100); - } catch (Exception ex) { - // Do nothing - } - } - } - fis.close(); - dis.close(); - - } catch (Exception ex) { - // do nothing? - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the display ded log command on " + myUsername); - return; - } - - /* - * Commands that can only be executed by owners, mods, or in the absence - * of an owner list. - */ - while (myDedOwners.equals("") || own.hasMoreTokens()) { - - if (own.hasMoreTokens()) { - owner = own.nextToken(); - } else { - owner = ""; - } - - if (myDedOwners.isEmpty() || name.equals(owner) - || (getUser(name).getUserlevel() >= 100)) { // if - // no - // owners - // set, - // anyone - // can - // send - // commands - - if (command.equals("restart")) { // Restart the dedicated - // server - - LOGGER.info("Restart command received from {}", name); - stopHost();// kill the host - - // Remove any MM option files that deds may have. - File localGameOptions = new File("./mmconf"); - try { - if (localGameOptions.exists()) { - localGameOptions = new File( - "./mmconf/gameoptions.xml"); - if (localGameOptions.exists()) { - localGameOptions.delete(); - } - } - } catch (Exception ex) { - LOGGER.catching(ex); - } - - // sleep for a few seconds before restarting - try { - Thread.sleep(5000); - } catch (Exception ex) { - LOGGER.catching(ex); - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the restart command on " + myUsername); - - try { - Runtime runTime = Runtime.getRuntime(); - if (new File("MekWarsDed.jar").exists()) { - String[] call = { "java", "-Xmx512m", "-jar", - "MekWarsDed.jar" }; - runTime.exec(call); - } else { - String[] call = { "java", "-Xmx512m", "-jar", - "MekWarsClient.jar" }; - runTime.exec(call); - } - System.exit(0); - - } catch (Exception ex) { - LOGGER.error("Unable to find MekWarsDed.jar"); - } - return; - - } else if (command.equals("reset")) { // server reset (like - // /reset in MM) - - LOGGER.info("Reset command received from " - + name); - if (myServer != null) { - resetGame(); - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the reset command on " + myUsername); - return; - - } else if (command.equals("die")) { // shut the dedicated down - - goodbye(); - System.exit(0); - - } else if (command.equals("start")) { // start hosting a MM - // game - - LOGGER.info("Start command received from {}", name); - if (myServer == null) { - startHost(true, false, false); - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the start command on " + myUsername); - return; - - } else if (command.equals("stop")) { // stop MM host, but w/o - // killing ded's - // connection - - // stop the host - LOGGER.info("Stop command received from {}", name); - if (myServer != null) { - stopHost(); - } - - // sleep, then wait around for a start command ... - try { - Thread.sleep(5000); - } catch (Exception ex) { - LOGGER.catching(ex); - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the stop command on " + myUsername); - return; - - } else if (command.equals("owners")) { // return a list of - // owners - - LOGGER.info("Owners command received from " - + name); - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name + ", My owners: " - + myDedOwners.replace('$', ' ')); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the owners command on " + myUsername); - return; - - } else if (command.startsWith("owner ")) { // add new owner(s) - - LOGGER.info("Owner command received from {}", name); - if (!myDedOwners.equals("")) { - myDedOwners = myDedOwners + "$"; - } - - myDedOwners = myDedOwners - + command.substring(("owner ").length()).trim(); - getConfig().setParam("DEDICATEDOWNERNAME", myDedOwners); - getConfig().saveConfig(); - setConfig(); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the owner " + myDedOwners + " command on " - + myUsername); - return; - - } else if (command.equals("clearowners")) { // clear owners, and - // send feedback. - - LOGGER.info("Clearowners command received from {}", name); - myDedOwners = ""; - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name + ", My owners: " - + myDedOwners); - getConfig().setParam("DEDICATEDOWNERNAME", myDedOwners); - getConfig().saveConfig(); - setConfig(); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the clear owners command on " + myUsername); - return; - - } else if (command.equals("port")) {// return the server's port - - LOGGER.info("Port command received from {}", name); - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name + ", My port: " - + myPort); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the port command on " + myUsername); - return; - - } else if (command.startsWith("port ")) {// new server port - - LOGGER.info("Port (set) command received from {}", name); - try { - port = Integer.parseInt(command.substring( - ("port ").length()).trim()); - } catch (Exception ex) { - LOGGER.error("Command error: {}: non-numeral port.", command); - return; - } - - if ((port > 0) && (port < 65536)) { - myPort = port; - }// check for legal port range - else { - LOGGER.error("Command error: {}: port out of valid range.", command); - } - String portString = Integer.toString(myPort); - getConfig().setParam("PORT", portString); - getConfig().saveConfig(); - setConfig(); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " changed the port for " + myUsername + " to " - + myPort); - return; - - } else if (command.equals("savegamepurge")) {// server days - // to purge - - LOGGER.info("Save game purge command received from {}", name); - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", I purge saved games that are " - + savedGamesMaxDays + " days old, or older."); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the save game purge command on " - + myUsername); - return; - - } else if (command.startsWith("savegamepurge ")) { // set - // number of - // days to - // delete is - // purge is - // called - - int mySavedGamesMaxDays = 7; - LOGGER.info("Savegamepurge command received from {}", name); - try { - mySavedGamesMaxDays = Integer.parseInt(command - .substring(("savegamepurge ").length()).trim()); - } catch (Exception ex) { - LOGGER.error("Command error: {}: invalid number.", command); - return; - } - - String purgeString = Integer.toString(mySavedGamesMaxDays); - getConfig().setParam("MAXSAVEDGAMEDAYS", purgeString); - getConfig().saveConfig(); - setConfig(); - savedGamesMaxDays = mySavedGamesMaxDays; - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " changed the save game purge for " + myUsername - + " to " + mySavedGamesMaxDays + " days."); - return; - - } else if (command.equals("displaysavedgames")) { // display - // saved - // games - - LOGGER.info("displaysavedgames command received from {}", name); - File[] fileList; - String list = "
Saved files on " + myUsername - + "
"; - String dateTimeFormat = "MM/dd/yyyy HH:mm:ss"; - SimpleDateFormat sDF = new SimpleDateFormat(dateTimeFormat); - try { - File tempFile = new File("./savegames/"); - fileList = tempFile.listFiles(); - for (File dateFile : fileList) { - Date date = new Date(dateFile.lastModified()); - String dateTime = sDF.format(date); - list += "Load " + dateFile + " " - + dateTime + "
"; - } - } catch (Exception ex) { - // do something? - } - - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name + ", " + list); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the display saved games command on " - + myUsername); - return; - - } else if (command.equals("update")) { // update the dedicated - // host using - // MWAutoUpdate - - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the update command on " + myUsername); - LOGGER.info("Update command received from {}", name); - try { - if (myServer != null) { - myServer.die(); - } - goodbye(); - Runtime runtime = Runtime.getRuntime(); - String[] call = { "java", "-jar", - "MekWarsAutoUpdate.jar", "DEDICATED", - getConfigParam("DEDUPDATECOMMANDFILE") }; - runtime.exec(call); - } catch (Exception ex) { - LOGGER.catching(ex); - } - System.exit(0);// restart the ded - return; - - } else if (command.equals("ping")) { // ping dedicated - - LOGGER.info("Ping command received from {}", name); - Version version = MWClient.CLIENT_VERSION; - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", I'm active with version " + version + "."); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the ping command on " + myUsername); - return; - - } - if (command.equals("loadgame") - || command.startsWith("loadgame ")) { // load - // game - // from - // file - - LOGGER.info("Loadgame command received from {}", name); - String filename = ""; - if (command.startsWith("loadgame ")) { - filename = command.substring(("loadgame ").length()) - .trim(); - } - if (command.equals("loadgame") || filename.isEmpty()) { - filename = "autosave.sav"; - } - if (myServer != null) { - if (!loadGame(filename)) { - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", Unable to load saved game."); - } else { - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", Saved game loaded."); - } - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " loaded game " + filename + " on " + myUsername); - return; - - } else if (command.startsWith("loadgamewithfullpath ")) { // load - // game - // from - // file, - // using - // full - // path - - LOGGER.info("Loadgamewithfullpath command received from {}", name); - String filename = ""; - if (command.startsWith("loadgamewithfullpath ")) { - filename = command.substring( - ("loadgamewithfullpath ").length()).trim(); - } - if (command.equals("loadgamewithfullpath") - || filename.isEmpty()) { - filename = "autosave.sav"; - } - if (myServer != null) { - if (!loadGameWithFullPath(filename)) { - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", Unable to load saved game."); - } else { - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", Saved game loaded."); - } - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " loaded game " + filename + " on " + myUsername); - return; - - } else if (command.equals("loadautosave")) { // load the most - // recent auto - // save file - - LOGGER.info("Loadautosave command received from {}", name); - String filename = "autosave.sav"; - if (myServer != null) { - if (Boolean.parseBoolean(this - .getServerConfigs("MMTimeStampLogFile"))) { - filename = getParanoidAutoSave(); - } - - if (!loadGame(filename)) { - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", Unable to load saved game."); - } else { - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name + ", " - + filename + " loaded."); - } - } - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name + " loaded " - + filename + " game on " + myUsername); - return; - - } else if (command.startsWith("name ")) { // new command - // prefix - - LOGGER.info("Name command received from {}", name); - String myComName = command.substring(("name ").length()) - .trim(); - getConfig().setParam("NAME", myComName); - getConfig().saveConfig(); - setConfig(); - sendChat(IClient.PROTOCOL_PREFIX - + "c mm# " - + name - + " used the set name command to change the name to " - + myComName + " command on " + myUsername); - Config.setParam("NAME", "[Dedicated] " + myComName); - myUsername = Config.getParam("NAME"); - return; - - } else if (command.startsWith("comment ")) { // new command - // prefix - - LOGGER.info("Prefix command received from {}", name); - String myComComment = command.substring( - ("comment ").length()).trim(); - getConfig().setParam("COMMENT", myComComment); - getConfig().saveConfig(); - setConfig(); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " has set the comment to " + myComComment - + " on " + myUsername); - return; - - } else if (command.startsWith("players ")) { // new command - // prefix - - LOGGER.info("Prefix command received from {}", name); - try { - String numPlayers = command.substring( - ("players ").length()).trim(); - getConfig().setParam("MAXPLAYERS", numPlayers); - getConfig().saveConfig(); - setConfig(); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " has set the max number of players to " - + numPlayers + " on " + myUsername); - return; - } catch (Exception ex) { - LOGGER.error("Unable to convert number of players to int"); - LOGGER.catching(ex); - return; - } - - } else if (command.equals("restartcount")) { // server port - - LOGGER.info("Restartcount command received from {}", name); - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", My restart count is set to " + dedRestartAt - + " my current game count is " + gameCount); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the restartcount command on " + myUsername); - return; - - } else if (command.startsWith("restartcount ")) {// new - // server - // port - - LOGGER.info("restartcount change command received from ", name); - try { - dedRestartAt = Integer.parseInt(command.substring( - ("restartcount ").length()).trim()); - } catch (Exception ex) { - LOGGER.error("Command error: {}: bad counter", command); - return; - } - String restartString = Integer.toString(dedRestartAt); - getConfig().setParam("DEDAUTORESTART", restartString); - getConfig().saveConfig(); - setConfig(); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " changed the restart count for " + myUsername - + " to " + dedRestartAt); - return; - - } else if (command.equals("getupdateurl")) {// find out what url - // the ded is set to - // update with - - LOGGER.info("GetUpdateUrl command received from {}", name); - String updateURL = getConfigParam("UPDATEURL"); - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name - + " used the getUpdateURL command on " + myUsername); - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", My update URL is " + updateURL + "."); - return; - - } else if (command.startsWith("setupdateurl ")) { - - LOGGER.info("setUpdateURL command received from {}", name); - String myUpdateURL = command.substring( - ("setupdateurl ").length()).trim(); - getConfig().setParam("UPDATEURL", myUpdateURL); - getConfig().saveConfig(); - setConfig(); - sendChat(IClient.PROTOCOL_PREFIX - + "c mm# " - + name - + " used the set update url command to change the the update url to " - + myUpdateURL + " on " + myUsername); - return; - - } - - LOGGER.info("Command error: {}: unknown command." + command); - return; - } - } - - sendChat(IClient.PROTOCOL_PREFIX + "c mm# " + name + " tried to use the " - + command + " on " + myUsername - + ", but does not have ownership."); - sendChat(IClient.PROTOCOL_PREFIX + "mail " + name - + ", You do not have management rights for this host!"); - LOGGER.error("Command error: {}: access denied for {}.", command, name); - } - public void processGUIInput(String input) { String s = null; @@ -1264,10 +452,6 @@ public void setLastQuery(String name) { LastQuery = name; } - public int getMyStatus() { - return Status; - } - public void setLastPing(long lastping) { LastPing = lastping; } @@ -1395,25 +579,6 @@ public boolean hasKeyWords(String input) { return (false); } - public String getStatus() { - if (Status == STATUS_DISCONNECTED) { - return ("Not connected"); - } - if (Status == STATUS_LOGGEDOUT) { - return ("Logged out"); - } - if (Status == STATUS_RESERVE) { - return ("Reserve duty"); - } - if (Status == STATUS_ACTIVE) { - return ("Active duty"); - } - if (Status == STATUS_FIGHTING) { - return ("Fighting"); - } - return (""); - } - public void setPlayerStartingEdge(int edge) { playerStartingEdge = edge; } @@ -1665,10 +830,6 @@ public String getConfigParam(String p) { tparam = ""; } - if (tparam.isEmpty() && p.equals("NAME") && isDedicated()) { - LOGGER.error("No dedicated name set."); - System.exit(1); - } return (tparam); } @@ -1676,25 +837,19 @@ public String getConfigParam(String p) { @Override public void systemMessage(String message) { - if (!isDedicated()) { - String sysColour = getConfigParam("SYSMESSAGECOLOR"); - message = "" + message - + ""; + String sysColour = getConfigParam("SYSMESSAGECOLOR"); + message = "" + message + + ""; - getGUIClient().addToChat(message, CCommPanel.CHANNEL_SLOG); - if (Config.isParam("MAINCHANNELSM")) { - getGUIClient().addToChat(message); - } + getGUIClient().addToChat(message, CCommPanel.CHANNEL_SLOG); + if (Config.isParam("MAINCHANNELSM")) { + getGUIClient().addToChat(message); } } @Override public void errorMessage(String message) { - if (!isDedicated()) { - JOptionPane.showMessageDialog(getGUIClient().getMainFrame(), message); - } else { - LOGGER.error(message); - } + JOptionPane.showMessageDialog(getGUIClient().getMainFrame(), message); } @Override @@ -1732,42 +887,14 @@ public void processIncoming(String incoming) { @Override public void connectionLost() { - Status = STATUS_DISCONNECTED; + setStatus(STATUS_DISCONNECTED); if (SignOff) { return; } errorMessage("Connection lost."); - if (isDedicated()) { - - // no point in having a server open w/o connection to campaign - // server - stopHost(); - - // wait at least 90 seconds before trying to connect again - try { - Thread.sleep(90000); - } catch (Exception ex) { - LOGGER.catching(ex); - } - - // keep retrying every two minutes after the first 90 sec downtime. - while (Status == STATUS_DISCONNECTED) { - connectToServer(Config.getParam("SERVERIP"), - Config.getIntParam("SERVERPORT")); - if (Status == STATUS_DISCONNECTED) { - LOGGER.error("Couldn't reconnect to server. Retrying in 120 seconds."); - try { - Thread.sleep(90000); - } catch (Exception exe) { - LOGGER.catching(exe); - } - } - } - } else { - Users.clear(); - getGUIClient().getMainFrame().changeStatus(Status, LastStatus); - } + Users.clear(); + getGUIClient().getMainFrame().changeStatus(getStatus(), LastStatus); } @Override @@ -1794,10 +921,8 @@ public void connectionEstablished() { + "\t" + passToSend + "\t" + getProtocolVersion() + "\t" + Config.getParam("COLOR") + "\t" + CLIENT_VERSION + "\t" + ST.nextToken()); - Status = STATUS_LOGGEDOUT; - if (!isDedicated()) { - getGUIClient().getMainFrame().changeStatus(Status, LastStatus); - } + setStatus(STATUS_LOGGEDOUT); + getGUIClient().getMainFrame().changeStatus(getStatus(), LastStatus); } // IClient interface @@ -1814,21 +939,19 @@ public void connectToServer(String ip, int port) { // connect to specific ip and port // System exits from connector on failure. Connector.connect(ip, port); - if (!isDedicated()) { - /* - * Send client version and saved mail request to the server. Doing - * this after the main frame is build and visible will (I hope) fix - * the "PM Ping Crash" TT users have with Client 0.1.44.5. - */ - sendChat(GameHost.CAMPAIGN_PREFIX + "c setclientversion#" - + getUsername().trim() + "#" + MWClient.CLIENT_VERSION); - sendChat("/getsavedmail"); - } + /* + * Send client version and saved mail request to the server. Doing + * this after the main frame is build and visible will (I hope) fix + * the "PM Ping Crash" TT users have with Client 0.1.44.5. + */ + sendChat(GameHost.CAMPAIGN_PREFIX + "c setclientversion#" + + getUsername().trim() + "#" + MWClient.CLIENT_VERSION); + sendChat("/getsavedmail"); } public void goodbye() { SignOff = true; - if (!isDedicated() && (Status > STATUS_LOGGEDOUT)) { + if ((getStatus() > STATUS_LOGGEDOUT)) { getConfig().setParam( "PANELDIVIDER", Integer.toString(getGUIClient().getMainFrame().getMainPanel() @@ -1853,7 +976,7 @@ public void goodbye() { Integer.toString(getGUIClient().getMainFrame().getY())); getConfig().saveConfig(); } - if (Status != STATUS_DISCONNECTED) { + if (getStatus() != STATUS_DISCONNECTED) { // serverSend("GB"); Connector.send(IClient.PROTOCOL_PREFIX + "signoff"); dataFetcher.closeDataConnection(); @@ -1865,153 +988,44 @@ public void goodbye() { } } + @Override + public void loadSavegame() { + FileDialog f = new FileDialog(getGUIClient().getMainFrame(), "Load Savegame"); + f.setDirectory(System.getProperty("user.dir") + "/savegames"); + f.setVisible(true); + myServer.loadGame(new File(f.getDirectory(), f.getFile())); + } + + + @Override public void startHost(boolean dedicated, boolean deploy, boolean loadSavegame) { ArrayList meks; ArrayList autoArmy; - //@salient - check quirk xml file sizes with server - if(Boolean.parseBoolean(getServerConfigs("EnableQuirks"))) - { - File canon = new File("data" + File.separator + "canonUnitQuirks.xml"); - File custom = new File("data" + File.separator + "mmconf" + File.separator + "unitQuirksOverride.xml"); - long canonFileLength = canon.length(); // returns 0L if does not exist - long customFileLength = custom.length(); - sendChat(GameHost.CAMPAIGN_PREFIX + "c QUIRKCHECK#" + canonFileLength + "#" + customFileLength); - } - - // reread the config to allow the user to change setting during runtime - String ip = "127.0.0.1"; - if (!getConfigParam("IP:").isEmpty()) {// IP Setting set, override IP - // detection. - try { - ip = getConfigParam("IP:"); - InetAddress IA = InetAddress.getByName(ip); // Resolve Dyndns - // Entries - ip = IA.getHostAddress(); - } catch (Exception ex) { - getGUIClient().showInfoWindow("Couldn't set IP. Please check the spelling of mwconfig.txt's IP value or comment it out to use autodetection."); - return; - } - } - - Version MMVersion = new Version(getServerConfigs("AllowedMegaMekVersion")); - if (!MMVersion.equals("-1") - && !MMVersion.is(megamek.MMConstants.VERSION)) { - if (isDedicated()) { - LOGGER.error("You are using an invalid version of MegaMek. Please use version {}", MMVersion); - try { - stopHost(); - goodbye(); - Runtime runtime = Runtime.getRuntime(); - String[] call = { "java", "-jar", "MekWarsAutoUpdate.jar", - "DEDICATED" }; - runtime.exec(call); - } catch (Exception ex) { - LOGGER.error("Exception: ", ex); - } - System.exit(0); - } else { - getGUIClient().showInfoWindow("You are using an invalid version of MegaMek. Please use version " - + MMVersion); - } - return; - } - - if (servers.get(myUsername) != null) { - if (isDedicated()) { - LOGGER.error("Attempted to start a second host while host was already running."); - } else { - String toUser = "CH|CLIENT: You already have a host open."; - doParseDataInput(toUser); - } - return; - } - - // int port = Integer.parseInt(getConfigParam("PORT:")); - int MaxPlayers = Integer.parseInt(getConfigParam("MAXPLAYERS:")); - String comment = getConfigParam("COMMENT:"); - String gpassword = getConfigParam("GAMEPASSWORD:"); - - if (gpassword == null) { - gpassword = ""; - } try { - myServer = new Server(gpassword, myPort, new GameManager()); - if (loadSavegame) { - FileDialog f = new FileDialog(getGUIClient().getMainFrame(), "Load Savegame"); - f.setDirectory(System.getProperty("user.dir") + "/savegames"); - f.setVisible(true); - myServer.loadGame(new File(f.getDirectory(), f.getFile())); - } - } catch (Exception ex) { - try { - if (myServer == null) { - LOGGER.error("Error opening dedicated server. Result = null host."); - LOGGER.catching(ex); - } else { - LOGGER.error("Error opening dedicated server. Will attempt a .die()."); - LOGGER.catching(ex); - myServer.die(); - myServer = null; - } - } catch (Exception e) { - LOGGER.error("Further error while trying to clean up failed host attempt."); - LOGGER.catching(e); - } + super.startHost(dedicated, deploy, loadSavegame); + } catch (Exception exception) { + JOptionPane.showMessageDialog(null, "Unable to start host " + exception.getMessage()); + LOGGER.error("Unable to start host", exception); return; } - ((Game)myServer.getGame()).addGameListener(this); - // Send the new game info to the Server - serverSend("NG|" - + new MMGame(myUsername, ip, myPort, MaxPlayers, - MMConstants.VERSION, comment) - .toString()); - if (!dedicated) { - - if (deploy) { - meks = myPlayer.getLockedUnits(); - autoArmy = myPlayer.getAutoArmy(); - } else { - meks = new ArrayList(); - autoArmy = new ArrayList(); - } - LOGGER.info("Joining own game!"); - - ClientThread MMGameThread = new ClientThread(myUsername, - myUsername, "127.0.0.1", myPort, this, meks, autoArmy); - mmClientThreads.add(MMGameThread); - ThreadManager.getInstance().runInThreadFromPool(MMGameThread); - serverSend("JG|" + myUsername); + if (deploy) { + meks = myPlayer.getLockedUnits(); + autoArmy = myPlayer.getAutoArmy(); } else { - clearSavedGames(); - purgeOldLogs(); - ClientPreferences cs = PreferenceManager.getClientPreferences(); - cs.setStampFilenames(Boolean - .parseBoolean(getServerConfigs("MMTimeStampLogFile"))); + meks = new ArrayList(); + autoArmy = new ArrayList(); } - } + LOGGER.info("Joining own game!"); - // Stop & send the close game event to the Server - public void stopHost() { - serverSend("CG");// send close game to server - try { - myServer.die(); - } catch (Exception ex) { - LOGGER.error("Megamek Error:"); - LOGGER.catching(ex); - } - myServer = null; - } - - public void resetGame() { // reset hosted game - if (myServer != null) { - myServer.resetGame(); - ((Game) myServer.getGame()).getGameListeners().clear(); - ((Game) myServer.getGame()).addGameListener(this); - } + ClientThread MMGameThread = new ClientThread(myUsername, + myUsername, "127.0.0.1", myPort, this, meks, autoArmy); + mmClientThreads.add(MMGameThread); + ThreadManager.getInstance().runInThreadFromPool(MMGameThread); + serverSend("JG|" + myUsername); } public boolean loadGame(String filename) {// load saved game @@ -2061,7 +1075,6 @@ public boolean isServerRunning() { } public void startClient(String hostName, boolean deploy) { - ArrayList meks = new ArrayList(); ArrayList autoArmy = new ArrayList(); @@ -2105,7 +1118,6 @@ public void startClient(String hostName, boolean deploy) { } public void closingGame(String hostName) { - // update battles tab for all players, via server LOGGER.info("Leaving " + hostName); serverSend("LG|" + hostName); @@ -2139,7 +1151,6 @@ public void getBlackMarketSettings() { } catch (Exception ex) { LOGGER.catching(ex); } - } protected class TimeOutThread extends Thread { @@ -2157,7 +1168,7 @@ public void run() { } catch (Exception ex) { LOGGER.catching(ex); } - if (Status != MWClient.STATUS_DISCONNECTED) { + if (getStatus() != MWClient.STATUS_DISCONNECTED) { long timeout = (System.currentTimeMillis() / 1000) - LastPing; if (timeout > TimeOut) { @@ -2279,7 +1290,7 @@ public void loadBannedAmmo() { * @return Returns the data. */ public CampaignData getData() { - if ((data == null) && !isDedicated()) { + if ((data == null)) { // Lets reload everything from the cache and then pull down and // planet changes @@ -2461,42 +1472,43 @@ public Buildings getBuildingTemplate() { * * @param newStatus */ - public void changeStatus(int newStatus) { - LastStatus = Status; - Status = newStatus; + @Override + public void setStatus(int newStatus) { + LastStatus = getStatus(); + super.setStatus(newStatus); - if (Status == MWClient.STATUS_RESERVE) { + if (getStatus() == MWClient.STATUS_RESERVE) { // there commands now send as part of the MWClient contructor. // sendChat(GameHost.CAMPAIGN_PREFIX + "c setclientversion#" + // this.myUsername+ "#" + CLIENT_VERSION); // this.sendChat("/getsavedmail"); - } else if (Status == STATUS_LOGGEDOUT) { + } else if (getStatus() == STATUS_LOGGEDOUT) { clearUserCampaignData(); } // update the activity button - if (Status == MWClient.STATUS_FIGHTING) { + if (getStatus() == MWClient.STATUS_FIGHTING) { // this.getGUIClient().getMainFrame().getMainPanel().getUserListPanel().setActivityButton(false); getGUIClient().getMainFrame().getMainPanel().getUserListPanel() .setActivityButtonEnabled(false); - } else if (Status == MWClient.STATUS_ACTIVE) { + } else if (getStatus() == MWClient.STATUS_ACTIVE) { if (LastStatus != MWClient.STATUS_FIGHTING) { getGUIClient().getMainFrame().getMainPanel().getUserListPanel() .setActivityButton(false); } getGUIClient().getMainFrame().getMainPanel().getUserListPanel() .setActivityButtonEnabled(true); - } else if (Status == MWClient.STATUS_DISCONNECTED) { + } else if (getStatus() == MWClient.STATUS_DISCONNECTED) { getGUIClient().getMainFrame().getMainPanel().getUserListPanel() .setActivateButtonText("Disconnected"); getGUIClient().getMainFrame().getMainPanel().getUserListPanel() .setActivityButtonEnabled(false); - } else if (Status == MWClient.STATUS_LOGGEDOUT) { + } else if (getStatus() == MWClient.STATUS_LOGGEDOUT) { getGUIClient().getMainFrame().getMainPanel().getUserListPanel() .setActivateButtonText("Login"); getGUIClient().getMainFrame().getMainPanel().getUserListPanel() .setActivityButtonEnabled(true); - } else if (Status == MWClient.STATUS_RESERVE) { + } else if (getStatus() == MWClient.STATUS_RESERVE) { if (LastStatus != MWClient.STATUS_LOGGEDOUT) { getGUIClient().getMainFrame().getMainPanel().getUserListPanel() .setActivityButton(true); @@ -2508,7 +1520,7 @@ public void changeStatus(int newStatus) { // update the CMainFrame Attack menu getGUIClient().getMainFrame().updateAttackMenu(); - getGUIClient().getMainFrame().changeStatus(Status, LastStatus); + getGUIClient().getMainFrame().changeStatus(getStatus(), LastStatus); getGUIClient().refreshGUI(GUIClient.REFRESH_HQPANEL); getGUIClient().refreshGUI(GUIClient.REFRESH_PLAYERPANEL); } @@ -2543,51 +1555,6 @@ public int getUserLevel() { return getUser(getUsername()).getUserlevel(); } - // this adds 1 to the number of games played and if it matched the restart - // amount it restarts the ded. - public void checkForRestart() { - gameCount++; - - // only check for restart once every 30 seconds. - if ((System.currentTimeMillis() - 30000) < lastResetCheck) { - return; - } - - if (gameCount >= dedRestartAt) { - LOGGER.info("System has reached {} games played and is restarting", gameCount); - try { - Thread.sleep(5000); - }// give people time to vacate - catch (Exception ex) { - LOGGER.catching(ex); - } - stopHost(); - try { - Thread.sleep(5000); - } catch (Exception ex) { - LOGGER.catching(ex); - } - try { - Runtime runTime = Runtime.getRuntime(); - if (new File("MekWarsDed.jar").exists()) { - String[] call = { "java", "-Xmx512m", "-jar", - "MekWarsDed.jar" }; - runTime.exec(call); - } else { - String[] call = { "java", "-Xmx512m", "-jar", - "MekWarsClient.jar" }; - runTime.exec(call); - } - System.exit(0); - - } catch (Exception ex) { - LOGGER.error("Unable to find MekWarsDed.jar"); - } - } - - lastResetCheck = System.currentTimeMillis(); - } - public void clearSavedGames() { long daysInSeconds = ((long) savedGamesMaxDays) * 24 * 60 * 60 * 1000; @@ -2940,66 +1907,13 @@ public int getTechLaborCosts(Entity unit, int techType) { return UnitUtils.getTechLaborCosts(unit, techCost); } - public void retrieveOpData(String type, String data) { - - StringTokenizer st = new StringTokenizer(data, "#"); - - String opName = st.nextToken(); - - File opFile = new File("./data/operations/" + type); - - if (!opFile.exists()) { - opFile.mkdirs(); - } - - opFile = new File("./data/operations/" + type + "/" + opName + ".txt"); - try { - FileOutputStream out = new FileOutputStream(opFile); - PrintStream p = new PrintStream(out); - while (st.hasMoreTokens()) { - p.println(st.nextToken().replaceAll("\\(pound\\)", "#")); - } - p.close(); - out.close(); - } catch (Exception ex) { - LOGGER.catching(ex); - } - } - - public void retrieveMul(String data) { - - StringTokenizer st = new StringTokenizer(data, "#"); - - String mulName = st.nextToken(); - - File mulFile = new File("./data/armies/"); - - if (!mulFile.exists()) { - mulFile.mkdirs(); - } - - mulFile = new File("./data/armies/" + mulName); - try { - FileOutputStream out = new FileOutputStream(mulFile); - PrintStream p = new PrintStream(out); - while (st.hasMoreTokens()) { - p.println(st.nextToken().replaceAll("\\(pound\\)", "#")); - } - p.close(); - out.close(); - } catch (Exception ex) { - LOGGER.catching(ex); - } - - } - public boolean isUsingAdvanceRepairs() { return Boolean.parseBoolean(getServerConfigs("UseAdvanceRepair")) || Boolean.parseBoolean(getServerConfigs("UseSimpleRepair")); } public boolean isDedicated() { - return Config.isParam("DEDICATED"); + return false; } public void updateOpData(boolean deleteCache) { @@ -3191,36 +2105,6 @@ public void createNewHouse(StringTokenizer st) { public void gamePlayerStatusChange(GameEvent e) { } - protected void sendServerGameUpdate() { - // Report the mech stat - - // Only send data for units currently on the board. - // any units removed from play will have already sent thier final - // update. - Iterator en = ((Game)myServer.getGame()).getEntities(); - while (en.hasNext()) { - Entity ent = en.next(); - 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))) { - continue; - } - if ((ent instanceof Mech) && (ent.getInternal(Mech.LOC_CT) <= 0)) { - serverSend("IPU|" - + SerializeEntity.serializeEntity(ent, true, true, - isUsingAdvanceRepairs())); - } else { - serverSend("IPU|" - + SerializeEntity.serializeEntity(ent, true, false, - isUsingAdvanceRepairs())); - } - } - } - protected void sendGameReport() { if (myServer == null) { return; @@ -3236,12 +2120,6 @@ protected void sendGameReport() { // we may assume that a server which reports a game is no longer // "Running" serverSend("SHS|" + myUsername + "|Open"); - - // myServer.resetGame(); - - if (isDedicated()) { - checkForRestart(); - } } public boolean getTargetSystemBanStatus(int type) { diff --git a/MekWarsClient/src/mekwars/client/cmd/CS.java b/MekWarsClient/src/mekwars/client/cmd/CS.java index 73db604f..a728d116 100644 --- a/MekWarsClient/src/mekwars/client/cmd/CS.java +++ b/MekWarsClient/src/mekwars/client/cmd/CS.java @@ -36,6 +36,6 @@ public CS(MWClient mwclient) { */ @Override public void execute(String input) { - mwclient.changeStatus(Integer.parseInt(decode(input).nextToken())); + mwclient.setStatus(Integer.parseInt(decode(input).nextToken())); } } diff --git a/MekWarsClient/src/mekwars/client/common/campaign/clientutils/DuplicateHostException.java b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/DuplicateHostException.java new file mode 100644 index 00000000..1634c68c --- /dev/null +++ b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/DuplicateHostException.java @@ -0,0 +1,19 @@ +/* + * MekWars - Copyright (C) 2025 + * + * Derived from MegaMekNET (http://www.sourceforge.net/projects/megameknet) Original author Helge Richter (McWizard) + * + * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + */ + +package mekwars.client.common.campaign.clientutils; + +class DuplicateHostException extends Exception { + public DuplicateHostException(String errorMessage) { + super(errorMessage); + } +} diff --git a/MekWarsClient/src/mekwars/client/common/campaign/clientutils/GameHost.java b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/GameHost.java index c6cc9546..d85334ad 100644 --- a/MekWarsClient/src/mekwars/client/common/campaign/clientutils/GameHost.java +++ b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/GameHost.java @@ -1,11 +1,33 @@ package mekwars.client.common.campaign.clientutils; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.lang.reflect.Constructor; +import java.net.InetAddress; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; +import java.util.StringTokenizer; +import java.util.TreeMap; +import java.util.Vector; +import megamek.MMConstants; +import megamek.Version; import megamek.common.Building; +import megamek.common.Entity; import megamek.common.Game; +import megamek.common.Mech; +import megamek.common.MechWarrior; import megamek.common.enums.GamePhase; import megamek.common.event.*; +import megamek.server.GameManager; import megamek.server.Server; +import mekwars.client.cmd.Command; import mekwars.client.common.campaign.clientutils.protocol.CConnector; import mekwars.client.common.campaign.clientutils.protocol.IClient; import mekwars.client.common.campaign.clientutils.protocol.commands.IProtCommand; @@ -16,19 +38,10 @@ import mekwars.common.campaign.clientutils.IGameHost; import mekwars.common.campaign.clientutils.SerializeEntity; import mekwars.common.campaign.clientutils.protocol.TransportCodec; +import mekwars.common.util.UnitUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.util.Date; -import java.util.Enumeration; -import java.util.StringTokenizer; -import java.util.TreeMap; -import java.util.Vector; - public abstract class GameHost implements GameListener, IGameHost { private static final Logger LOGGER = LogManager.getLogger(GameHost.class); @@ -55,12 +68,20 @@ public abstract class GameHost implements GameListener, IGameHost { protected Vector decodeBuffer = new Vector(1, 1);// used to buffer incoming data until CMainFrame is built protected Buildings buildingTemplate = null; + + /** + * Maps the task prefixes as HS, PL, SP etc. to a command under package cmd. + * key: String, value: cmd.Command + */ + HashMap commands = new HashMap(); protected int savedGamesMaxDays = 30; // max number of days a save game can be before // its deleted. protected GamePhase currentPhase = GamePhase.DEPLOYMENT; protected int turn = 0; + protected int myPort = -1; + private int status = 0; @Override public void gameBoardChanged(GameBoardChangeEvent arg0) { @@ -155,8 +176,7 @@ public void gamePhaseChange(GamePhaseChangeEvent e) { */ sendServerGameUpdate(); - }// end try - catch (Exception ex) { + } catch (Exception ex) { LOGGER.error("Error reporting game!"); LOGGER.error("Exception: ", ex); } @@ -214,8 +234,6 @@ public void gameTurnChange(GameTurnChangeEvent e) { } } - protected abstract void sendServerGameUpdate(); - public void gameVictory(GameVictoryEvent e) { sendGameReport(); LOGGER.info("GAME END"); @@ -356,4 +374,247 @@ public void serverSend(String s) { LOGGER.error("Exception: ", e); } } + + /** + * @throws InvalidVersionException When the GameHost's {@link Version} is not allowed. + * + * @throws DuplicateHostException When a GameHost is already started. + * + * @throws UnknownHostException If the IP of the GameHost cannot be found. + */ + public void startHost(boolean dedicated, boolean deploy, + boolean loadSavegame) throws Exception { + + //@salient - check quirk xml file sizes with server + if(Boolean.parseBoolean(getServerConfigs("EnableQuirks"))) { + File canon = new File("data" + File.separator + "canonUnitQuirks.xml"); + File custom = new File("data" + File.separator + "mmconf" + File.separator + "unitQuirksOverride.xml"); + long canonFileLength = canon.length(); // returns 0L if does not exist + long customFileLength = custom.length(); + sendChat(GameHost.CAMPAIGN_PREFIX + "c QUIRKCHECK#" + canonFileLength + "#" + customFileLength); + } + + // reread the config to allow the user to change setting during runtime + String ip = "127.0.0.1"; + if (!getConfigParam("IP:").isEmpty()) {// IP Setting set, override IP + // detection. + ip = getConfigParam("IP:"); + InetAddress IA = InetAddress.getByName(ip); // Resolve Dyndns + // Entries + ip = IA.getHostAddress(); + } + + Version MMVersion = new Version(getServerConfigs("AllowedMegaMekVersion")); + if (!MMVersion.equals("-1") + && !MMVersion.is(megamek.MMConstants.VERSION)) { + throw new InvalidVersionException("You are using an invalid version of MegaMek. Please use version " + MMVersion.toString()); + } + + if (servers.get(myUsername) != null) { + throw new DuplicateHostException("Attempted to start a second host while host was already running."); + } + + int MaxPlayers = Integer.parseInt(getConfigParam("MAXPLAYERS:")); + String comment = getConfigParam("COMMENT:"); + String gpassword = getConfigParam("GAMEPASSWORD:"); + + if (gpassword == null) { + gpassword = ""; + } + try { + myServer = new Server(gpassword, myPort, new GameManager()); + if (loadSavegame) { + loadSavegame(); + } + } catch (Exception ex) { + try { + if (myServer == null) { + LOGGER.error("Error opening dedicated server. Result = null host.", ex); + } else { + LOGGER.error("Error opening dedicated server. Will attempt a .die().", ex); + myServer.die(); + myServer = null; + } + } catch (Exception e) { + LOGGER.error("Further error while trying to clean up failed host attempt.", e); + } + return; + } + + ((Game)myServer.getGame()).addGameListener(this); + // Send the new game info to the Server + serverSend("NG|" + + new MMGame(myUsername, ip, myPort, MaxPlayers, + MMConstants.VERSION, comment) + .toString()); + } + + // Stop & send the close game event to the Server + public void stopHost() { + serverSend("CG");// send close game to server + try { + if (myServer != null) { + myServer.die(); + } + } catch (Exception ex) { + LOGGER.error("Megamek Error: ", ex); + } + myServer = null; + } + + public void retrieveOpData(String type, String data) { + StringTokenizer st = new StringTokenizer(data, "#"); + String opName = st.nextToken(); + File opFile = new File("./data/operations/" + type); + + if (!opFile.exists()) { + opFile.mkdirs(); + } + + opFile = new File("./data/operations/" + type + "/" + opName + ".txt"); + try { + FileOutputStream out = new FileOutputStream(opFile); + PrintStream p = new PrintStream(out); + while (st.hasMoreTokens()) { + p.println(st.nextToken().replaceAll("\\(pound\\)", "#")); + } + p.close(); + out.close(); + } catch (Exception ex) { + LOGGER.error("Exception: ", ex); + } + } + + public void retrieveMul(String data) { + StringTokenizer st = new StringTokenizer(data, "#"); + String mulName = st.nextToken(); + File mulFile = new File("./data/armies/"); + + if (!mulFile.exists()) { + mulFile.mkdirs(); + } + + mulFile = new File("./data/armies/" + mulName); + try { + FileOutputStream out = new FileOutputStream(mulFile); + PrintStream p = new PrintStream(out); + while (st.hasMoreTokens()) { + p.println(st.nextToken().replaceAll("\\(pound\\)", "#")); + } + p.close(); + out.close(); + } catch (Exception ex) { + LOGGER.catching(ex); + } + } + + /** + * Changes the duty to a new status. + * + * @param newStatus + */ + public void setStatus(int newStatus) { + status = newStatus; + } + + public int getStatus() { + return status; + } + + public String getStatusString() { + if (status == STATUS_DISCONNECTED) { + return ("Not connected"); + } + if (status == STATUS_LOGGEDOUT) { + return ("Logged out"); + } + if (status == STATUS_RESERVE) { + return ("Reserve duty"); + } + if (status == STATUS_ACTIVE) { + return ("Active duty"); + } + if (status == STATUS_FIGHTING) { + return ("Fighting"); + } + return (""); + } + + + protected void sendServerGameUpdate() { + // Report the mech stat + + // Only send data for units currently on the board. + // any units removed from play will have already sent thier final + // update. + Iterator en = ((Game)myServer.getGame()).getEntities(); + while (en.hasNext()) { + Entity ent = en.next(); + 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))) { + continue; + } + if ((ent instanceof Mech) && (ent.getInternal(Mech.LOC_CT) <= 0)) { + serverSend("IPU|" + + SerializeEntity.serializeEntity(ent, true, true, + isUsingAdvanceRepairs())); + } else { + serverSend("IPU|" + + SerializeEntity.serializeEntity(ent, true, false, + isUsingAdvanceRepairs())); + } + } + } + + + + /* + * Actual GUI-mode parseData. Before we started streaming data over the chat + * part, this was called directly. Now we buffer all incoming non-data chat + * and spit it out at once when the GUI draws. Once the GUI is up, this is + * called by a simple pass through from doParseDataInput(), above. + * + * Ded's call the helper directly to bypass the buffer. + */ + protected void doParseDataHelper(String input) { + try { + + // 0-length input is spurious call from MWDedHost constructor. + if (input.length() == 0) { + return; + } + + StringTokenizer ST = null; + String task = null; + + LOGGER.debug(input); + + // Create a String Tokenizer to parse the elements of the input + ST = new StringTokenizer(input, COMMAND_DELIMITER); + task = ST.nextToken(); + + if (!commands.containsKey(task)) { + try { + Class cmdClass = Class.forName(getClass().getPackage().getName() + ".cmd." + task); + Constructor c = cmdClass.getConstructor(new Class[] + { getClass() }); + Command cmd = (Command) c.newInstance(new Object[] + { this }); + commands.put(task, cmd); + } catch (Exception e) { + LOGGER.error("Unable to store command", e); + } + } + if (commands.containsKey(task)) { + commands.get(task).execute(input); + } + } catch (Exception ex) { + LOGGER.error("Unable to parse data", ex); + } + } } diff --git a/MekWarsClient/src/mekwars/client/common/campaign/clientutils/InvalidVersionException.java b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/InvalidVersionException.java new file mode 100644 index 00000000..a1ca7276 --- /dev/null +++ b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/InvalidVersionException.java @@ -0,0 +1,19 @@ +/* + * MekWars - Copyright (C) 2025 + * + * Derived from MegaMekNET (http://www.sourceforge.net/projects/megameknet) Original author Helge Richter (McWizard) + * + * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + */ + +package mekwars.client.common.campaign.clientutils; + +class InvalidVersionException extends Exception { + public InvalidVersionException(String errorMessage) { + super(errorMessage); + } +} diff --git a/MekWarsClient/src/mekwars/client/common/campaign/clientutils/protocol/IClient.java b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/protocol/IClient.java index 81e7891d..c73338f5 100644 --- a/MekWarsClient/src/mekwars/client/common/campaign/clientutils/protocol/IClient.java +++ b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/protocol/IClient.java @@ -19,31 +19,29 @@ public interface IClient { public static final String DEFLATED = "/deflated"; // called when there's a system message to show - public void systemMessage(String message); + void systemMessage(String message); // called when there's an error message to show - public void errorMessage(String message); + void errorMessage(String message); // called when there's server input to process - public void processIncoming(String incoming); + void processIncoming(String incoming); // called when connection is lost - public void connectionLost(); + void connectionLost(); // called when connection is established - public void connectionEstablished(); + void connectionEstablished(); - public CConnector getConnector(); + CConnector getConnector(); - public void startHost(boolean dedicated, boolean deploy, boolean loadSavedGame); + void startHost(boolean dedicated, boolean deploy, boolean loadSavedGame); - public boolean isDedicated(); + boolean isDedicated(); - public void setUsername(String name); + void setUsername(String name); - public void doParseDataInput(String input); + void doParseDataInput(String input); - public void parseDedDataInput(String input); - - public void setLastPing(long lastPing); + void setLastPing(long lastPing); } diff --git a/MekWarsClient/src/mekwars/client/common/campaign/clientutils/protocol/commands/CommPCmd.java b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/protocol/commands/CommPCmd.java index faae29bb..53fd84bc 100644 --- a/MekWarsClient/src/mekwars/client/common/campaign/clientutils/protocol/commands/CommPCmd.java +++ b/MekWarsClient/src/mekwars/client/common/campaign/clientutils/protocol/commands/CommPCmd.java @@ -24,12 +24,9 @@ public boolean execute(String input) { StringTokenizer ST = new StringTokenizer(input, delimiter); if (check(ST.nextToken()) && ST.hasMoreTokens()) { input = TransportCodec.unescape(ST.nextToken()); - if (!client.isDedicated()) {client.doParseDataInput(input);} - else {client.parseDedDataInput(input);} + client.doParseDataInput(input); return true; } - - //else return false; } diff --git a/MekWarsClient/src/mekwars/client/gui/AttackMenu.java b/MekWarsClient/src/mekwars/client/gui/AttackMenu.java index 26033d9b..41be3995 100644 --- a/MekWarsClient/src/mekwars/client/gui/AttackMenu.java +++ b/MekWarsClient/src/mekwars/client/gui/AttackMenu.java @@ -429,7 +429,7 @@ else if (!tp.isHomeWorld() && homeInfo.equals("only")) this.add(toAdd, 0); if ( Boolean.parseBoolean(mwclient.getServerConfigs("AllowAttackFromReserve")) - && mwclient.getMyStatus() == MWClient.STATUS_RESERVE){ + && mwclient.getStatus() == MWClient.STATUS_RESERVE){ this.add(new JSeparator()); toAdd = new JMenuItem("Attack From Reserve"); toAdd.addActionListener(this); @@ -449,7 +449,7 @@ else if (!tp.isHomeWorld() && homeInfo.equals("only")) toAdd.setMnemonic('G'); this.add(toAdd); - if (mwclient.getMyStatus() >= MWClient.STATUS_ACTIVE) { + if (mwclient.getStatus() >= MWClient.STATUS_ACTIVE) { toAdd = new JMenuItem("Cancel Game"); toAdd.addActionListener(this); toAdd.setActionCommand("cmdCancelGames"); @@ -605,11 +605,11 @@ public void actionPerformed(ActionEvent e) { * anything else is a nonstarter unless the player * is actually active. */ - if (mwclient.getMyStatus() < MWClient.STATUS_ACTIVE) { + if (mwclient.getStatus() < MWClient.STATUS_ACTIVE) { String toUser = "CH|CLIENT: You must be active in order to initiate standard attacks."; mwclient.doParseDataInput(toUser); return; - } else if (mwclient.getMyStatus() == MWClient.STATUS_FIGHTING) { + } else if (mwclient.getStatus() == MWClient.STATUS_FIGHTING) { String toUser = "CH|CLIENT: You may not initiate an attack while you are in a game."; mwclient.doParseDataInput(toUser); return; diff --git a/MekWarsClient/src/mekwars/client/gui/CHQPanel.java b/MekWarsClient/src/mekwars/client/gui/CHQPanel.java index e30846e1..299c8cab 100644 --- a/MekWarsClient/src/mekwars/client/gui/CHQPanel.java +++ b/MekWarsClient/src/mekwars/client/gui/CHQPanel.java @@ -260,7 +260,7 @@ private void btnRemoveAllArmiesActionPerformed(ActionEvent evt) { if (result == JOptionPane.NO_OPTION) return; //Baruk Khazad! 20151204 - end block 1 // only remove all if he's logged in, not fighting/active/logout/discon - if (mwclient.getMyStatus() != MWClient.STATUS_RESERVE) { + if (mwclient.getStatus() != MWClient.STATUS_RESERVE) { return; } @@ -609,7 +609,7 @@ public void mouseDragged(MouseEvent e) { if (currArmy == null) { // if the unit is from an army, could remove. show minus. - if ((startArmy != null) && (mwclient.getMyStatus() == MWClient.STATUS_RESERVE)) { + if ((startArmy != null) && (mwclient.getStatus() == MWClient.STATUS_RESERVE)) { tblMeks.setCursor(removeCursor); } else if (startArmy != null) { tblMeks.setCursor(notAllowedCursor); @@ -625,7 +625,7 @@ public void mouseDragged(MouseEvent e) { // from hangar to an army if (startArmy == null) { - if (mwclient.getMyStatus() != MWClient.STATUS_RESERVE) { + if (mwclient.getStatus() != MWClient.STATUS_RESERVE) { tblMeks.setCursor(notAllowedCursor); } else if (Player.getAmountOfTimesUnitExistsInArmies(dragUnit.getId()) >= Integer.parseInt(mwclient.getServerConfigs("UnitsInMultipleArmiesAmount"))) { tblMeks.setCursor(maxCursor); @@ -641,7 +641,7 @@ public void mouseDragged(MouseEvent e) { // within the same army, change positions else if (currArmy.getID() == startArmy.getID()) { - if ((currUnit != null) && (dragUnit.getId() != currUnit.getId()) && (mwclient.getMyStatus() != MWClient.STATUS_FIGHTING)) { + if ((currUnit != null) && (dragUnit.getId() != currUnit.getId()) && (mwclient.getStatus() != MWClient.STATUS_FIGHTING)) { tblMeks.setCursor(positionCursor); } else { tblMeks.setCursor(notAllowedCursor); @@ -775,7 +775,7 @@ private void maybeShowPopup(MouseEvent e) { menuItem.setActionCommand("AO|" + lid); menuItem.addActionListener(this); boolean canCheckFromReserve = Boolean.parseBoolean(mwclient.getServerConfigs("ProbeInReserve")); - if ((mwclient.getMyStatus() != MWClient.STATUS_ACTIVE) && !canCheckFromReserve) { + if ((mwclient.getStatus() != MWClient.STATUS_ACTIVE) && !canCheckFromReserve) { menuItem.setEnabled(false); } popup.add(menuItem); @@ -3112,6 +3112,7 @@ public String getValueAt(int row, int col) { // else CArmy army = getArmyAt(row); StringBuilder result = new StringBuilder(cm.getModelName()); + // TODO: When registering as a new player the player's house is null for a second. String skillSet = cm.getPilot().getSkillString(false, mwclient.getData().getHouseByName(mwclient.getPlayer().getHouse()).getBasePilotSkill(cm.getType())); StringTokenizer skills = new StringTokenizer(skillSet, ","); while (skills.hasMoreElements()) { diff --git a/MekWarsClient/src/mekwars/client/gui/CMainFrame.java b/MekWarsClient/src/mekwars/client/gui/CMainFrame.java index e132c5da..1e0e11b4 100644 --- a/MekWarsClient/src/mekwars/client/gui/CMainFrame.java +++ b/MekWarsClient/src/mekwars/client/gui/CMainFrame.java @@ -332,21 +332,21 @@ public void enableMenu() { userLevel = mwclient.getUserLevel(); mwclient.loadServerCommmands(); - if (mwclient.getMyStatus() == MWClient.STATUS_DISCONNECTED) { + if (mwclient.getStatus() == MWClient.STATUS_DISCONNECTED) { disconnected = true; } - if (mwclient.getMyStatus() == MWClient.STATUS_LOGGEDOUT) { + if (mwclient.getStatus() == MWClient.STATUS_LOGGEDOUT) { loggedout = true; } - if (mwclient.getMyStatus() == MWClient.STATUS_RESERVE) { + if (mwclient.getStatus() == MWClient.STATUS_RESERVE) { loggedin = true; reserve = true; } - if (mwclient.getMyStatus() == MWClient.STATUS_ACTIVE) { + if (mwclient.getStatus() == MWClient.STATUS_ACTIVE) { loggedin = true; active = true; } - if (mwclient.getMyStatus() == MWClient.STATUS_FIGHTING) { + if (mwclient.getStatus() == MWClient.STATUS_FIGHTING) { loggedin = true; // fighting = true; } @@ -1428,7 +1428,7 @@ public void jMenuFileNick_actionPerformed() { public void jMenuFileConnect_actionPerformed() { mwclient.connectToServer(); // Set Version upon reconnect. - if (!mwclient.getStatus().equals("Not connected")) { + if (!mwclient.getStatusString().equals("Not connected")) { mwclient.sendChat(GameHost.CAMPAIGN_PREFIX + "c setclientversion#" + mwclient.myUsername.trim() + "#" + MWClient.CLIENT_VERSION); } } diff --git a/MekWarsClient/src/mekwars/client/gui/CUserListPanel.java b/MekWarsClient/src/mekwars/client/gui/CUserListPanel.java index 9c59d76f..40844ab3 100644 --- a/MekWarsClient/src/mekwars/client/gui/CUserListPanel.java +++ b/MekWarsClient/src/mekwars/client/gui/CUserListPanel.java @@ -429,11 +429,11 @@ public void setActivityButtonEnabled(boolean b) { */ public void actionPerformed(ActionEvent e) { if (e.getSource() == ActivityButton) { - if(mwclient.getMyStatus() == MWClient.STATUS_RESERVE)//is reserve + if(mwclient.getStatus() == MWClient.STATUS_RESERVE)//is reserve mwclient.sendChat(GameHost.CAMPAIGN_PREFIX + "c activate#" + MWClient.CLIENT_VERSION); - else if (mwclient.getMyStatus() == MWClient.STATUS_ACTIVE)//is active + else if (mwclient.getStatus() == MWClient.STATUS_ACTIVE)//is active mwclient.sendChat("/c deactivate"); - else if (mwclient.getMyStatus() == MWClient.STATUS_LOGGEDOUT)//is logged out + else if (mwclient.getStatus() == MWClient.STATUS_LOGGEDOUT)//is logged out mwclient.sendChat("/c login"); } } diff --git a/MekWarsCommon/src/mekwars/common/campaign/clientutils/IGameHost.java b/MekWarsCommon/src/mekwars/common/campaign/clientutils/IGameHost.java index 01e4fa69..20fef24a 100644 --- a/MekWarsCommon/src/mekwars/common/campaign/clientutils/IGameHost.java +++ b/MekWarsCommon/src/mekwars/common/campaign/clientutils/IGameHost.java @@ -1,11 +1,25 @@ package mekwars.common.campaign.clientutils; +import java.util.Properties; +import megamek.Version; import megamek.common.event.GameCFREvent; public interface IGameHost { - public void changeStatus(int newStatus); - public boolean isAdmin(); - public boolean isMod(); - public String getUsername(); - void gameClientFeedbackRquest(GameCFREvent arg0); + void setStatus(int newStatus); + + boolean isAdmin(); + + boolean isMod(); + + String getUsername(); + + void gameClientFeedbackRquest(GameCFREvent arg0); + + String getServerConfigs(String key); + + Properties getServerConfigs(); + + void loadSavegame(); + + String getConfigParam(String param); } diff --git a/MekWarsCommon/src/mekwars/common/util/GameReport.java b/MekWarsCommon/src/mekwars/common/util/GameReport.java index 1eb0f5f7..ad8f0d4b 100644 --- a/MekWarsCommon/src/mekwars/common/util/GameReport.java +++ b/MekWarsCommon/src/mekwars/common/util/GameReport.java @@ -20,12 +20,10 @@ import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; - +import megamek.common.Entity; import mekwars.common.GameInterface; import mekwars.common.campaign.Buildings; import mekwars.common.campaign.clientutils.SerializeEntity; - -import megamek.common.Entity; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/MekWarsDedicatedHost/build.gradle b/MekWarsDedicatedHost/build.gradle index 9914c010..e472a73b 100644 --- a/MekWarsDedicatedHost/build.gradle +++ b/MekWarsDedicatedHost/build.gradle @@ -55,11 +55,32 @@ jar { } } -task stageFiles(type: Copy) { - file(fileStagingDir).mkdirs() - File batFile = new File("${fileStagingDir}/${project.tasks.getByName("jar").archiveBaseName.get()}.bat") - batFile.text = "start /min java ${project.application.applicationDefaultJvmArgs.join(' ')} ${jar.archiveFileName.get()}" +task mekWarsBat(type: Copy) { + if(!file(fileStagingDir).exists()) { + file(fileStagingDir).mkdirs() + } + + def jarTask = tasks.named('jar').get() + def jvmArgs = (project.application.applicationDefaultJvmArgs ?: []).join(' ') + def jarName = jarTask.archiveFileName.get() // MekWars.jar + def baseName = jarTask.archiveBaseName.get() // MekWars + + File batFile = new File(fileStagingDir, "${baseName}.bat") + batFile.text = "start /min javaw ${project.application.applicationDefaultJvmArgs.join(' ')} ${jar.archiveFileName.get()} -jar \"%~dp0MekWars.jar\" %*" from batFile +} + +task stageFiles(type: Copy) { + description = 'Stages files that are to be copied into the distribution.' + dependsOn gradle.includedBuild('megamek').task(':megamek:stageFiles') + + from projectDir + + include "data/**" + include "docs/**" + include "mconf/**" + include "userdata/**" + into fileStagingDir } @@ -67,13 +88,19 @@ distributions { main { contents { from stageFiles - from project(':MekWarsClient').jar - from jar from "${mmDir}/megamek/build/libs/MegaMek.jar" + from "${mmDir}/megamek/build/files" + from jar + from project(':MekWarsClient').jar + copy { + from mekWarsBat + into "." + } from (project.sourceSets.main.runtimeClasspath.files .findAll { it.name.endsWith(".jar") }) { into "${lib}" } + from "${mmDir}/megamek/build/files/mechfiles" duplicatesStrategy = 'exclude' } } diff --git a/MekWarsDedicatedHost/src/mekwars/dedicatedhost/DedConfig.java b/MekWarsDedicatedHost/src/mekwars/dedicatedhost/DedConfig.java index 09914e3b..dfb51df6 100644 --- a/MekWarsDedicatedHost/src/mekwars/dedicatedhost/DedConfig.java +++ b/MekWarsDedicatedHost/src/mekwars/dedicatedhost/DedConfig.java @@ -133,100 +133,6 @@ public void createConfig() { try { FileOutputStream fos = new FileOutputStream(CONFIG_FILE); PrintStream ps = new PrintStream(fos); - - /* - * Options below are supported in code, but not yet in config dialog. - */ - //ps.println("#If you want a Password for your game, enter it here"); - //ps.println("#GAMEPASSWORD: "); - //ps.println("#Size of chat font (as in html font tag)"); - //ps.println("#CHATFONTSIZE: +0"); - //ps.println("#Color of chat font (as in html font tag)"); - //ps.println("#CHATFONTCOLOR: black"); - //ps.println("#If you don't want the Player Panel to be visible, set it to NO"); - //ps.println("PLAYERPANEL: YES"); - //ps.println("#Put player panel height in pixels (excluding logo height) here (default is 130)"); - //ps.println("#PLAYERPANELHEIGHT: 130"); - //ps.println("#If you don't want the Logo to be visible, set it to NO"); - //ps.println("LOGO: NO"); - //ps.println("#A picture (from /data/images) to be shown as your logo in client. If you comment it out, it will download your unit logo!"); - //ps.println("LOGOIMAGE: logo.jpg"); - //ps.println("#The thickness of splitters dividing client windows"); - //ps.println("#SPLITTERSIZE: 7"); - //ps.println("#set to NO if you do not want server messages to appear as popup."); - //ps.println("#if turned off, messages will appear in main chat."); - //ps.println("POPUPONMESSAGE: NO"); - - /* - * Options below are supported in config dialog. - */ - //ps.println("#Your Color used for your name in the chat "); - //ps.println("#Color of your name in chat."); - //ps.println("#Choices: standard HTML colours, any hex colour with a Red Value under AA)"); - //ps.println("COLOR: black"); - //ps.println("#IP of MekWars Server you are connecting to"); - //ps.println("#Servers listed on forums @ http://www.sourceforge.net/projects/mekwars"); - //ps.println("SERVERIP: SEE THE MEKWARS PROJECT PAGE FOR A LIST OF KNOWN SERVERS"); - //ps.println("#MegaMek host settings"); - //ps.println("#IF and only IF your ip isn't detected correctly, you may edit this setting (very unlikely that this happens)"); - //ps.println("#This is your current IP, needed to host games. You can use a Dynamically assigned DNS entry or just your plain IP here."); - //ps.println("#If you don't know your IP-Address try this website: http://www.whatismyip.com"); - //ps.println("#You only need to enable that line if your IP isn't shown correctly when you create a game."); - //ps.println("#IP: 127.0.0.1"); - //ps.println("#The maximum number of players you want to join your host. (If you host a game) Default: 12"); - //ps.println("MAXPLAYERS: 12"); - //ps.println("#A comment for your game (If you host a game)"); - //ps.println("COMMENT: "); - //ps.println("#SOUND SETTINGS"); - //ps.println("#Play this file if anyone calls my name"); - //ps.println("SOUNDONCALL: ./data/sounds/call.wav"); - //ps.println("#Play this file when a Player joins the room"); - //ps.println("#SOUNDONJOIN: ./data/sounds/join.wav"); - //ps.println("#Play this file when a Player exits the room"); - //ps.println("#SOUNDONEXIT: ./data/sounds/exit.wav"); - //ps.println("#Play this file when someone sends you a message"); - //ps.println("SOUNDONMESSAGE: ./data/sounds/mail.wav"); - //ps.println("#Play this file when someone attacks you"); - //ps.println("SOUNDONATTACK: ./data/sounds/attack.wav"); - //ps.println("#Dedicated server settings"); - //ps.println("#Should this be a Dedicated Server ONLY?"); - //ps.println("DEDICATED: NO"); - //ps.println("#(Only if Dedicated Only) Put names of people allowed to reset him here, separated with commas"); - //ps.println("DEDICATEDOWNERNAME: "); - //ps.println("#If you don't want to see news and statuses in Main Channel, set it to NO"); - //ps.println("MAINCHANNELNEWS: YES"); - //ps.println("#If you don't want to see faction mails in Main Channel, set it to NO"); - //ps.println("MAINCHANNELHM: NO"); - //ps.println("#If you don't want to see private mails in Main Channel, set it to NO"); - //ps.println("MAINCHANNELPM: NO"); - //ps.println("#If you don't want to see system messages in Main Channel, set it to NO"); - //ps.println("MAINCHANNELSM: NO"); - //ps.println("#If you don't want to see misc messages in Main Channel, set it to NO"); - //ps.println("MAINCHANNELMISC: NO"); - //ps.println("#If you want to hear a sound when specific word is received, put them in here, separated with commas"); - //ps.println("#REPLYTOSENDER: YES"); - //ps.println("#If you don't want PM tab reply to last mail receiver, set it to NO"); - //ps.println("#REPLYTORECEIVER: NO"); - //ps.println("#If you don't want dialog to popup on when you are attacked, set it to NO"); - //ps.println("#POPUPONATTACK: YES"); - //ps.println("#PanelDivider set between 1-100"); - //ps.println("PANELDIVIDER: 40"); - //ps.println("#bind commands to Function keys. /c is automatically added."); - //ps.println("#Example binding for F1 to mysatus and transfermomey follow."); - //ps.println("#F1BIND: transfermoney#urgru#30"); - //ps.println("F1BIND: mystatus"); - //ps.println("F2BIND:"); - //ps.println("F3BIND:"); - //ps.println("F4BIND:"); - //ps.println("F5BIND:"); - //ps.println("#number of games a ded will play before it restarts"); - //ps.println("DEDAUTORESTART: 20"); - - //these should be pre-empted by the serverdata.dat values set by server op - //ps.println("CAMPAIGNSERVERNAME: MekWars Server"); - //ps.println("TRAYIMAGE: reserve_colored.gif"); - //ps.println("UPDATEKEY: -1"); - ps.close(); fos.close(); } catch (Exception ex) { diff --git a/MekWarsDedicatedHost/src/mekwars/dedicatedhost/MWDedHost.java b/MekWarsDedicatedHost/src/mekwars/dedicatedhost/MWDedHost.java index c2912dff..03934d04 100644 --- a/MekWarsDedicatedHost/src/mekwars/dedicatedhost/MWDedHost.java +++ b/MekWarsDedicatedHost/src/mekwars/dedicatedhost/MWDedHost.java @@ -18,41 +18,27 @@ package mekwars.dedicatedhost; import java.awt.Dimension; -import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.FilenameFilter; +import java.io.IOException; import java.io.InputStreamReader; -import java.io.PrintStream; -import java.lang.reflect.Constructor; -import java.net.InetAddress; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Collections; import java.util.Date; -import java.util.Enumeration; -import java.util.HashMap; import java.util.Iterator; -import java.util.List; import java.util.Properties; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.Vector; - -import mekwars.dedicatedhost.cmd.Command; -import megamek.MMConstants; -import megamek.common.Entity; import megamek.common.Game; -import megamek.common.Mech; -import megamek.common.MechWarrior; import megamek.common.enums.GamePhase; import megamek.common.event.GameCFREvent; import megamek.common.options.IOption; import megamek.common.preference.ClientPreferences; import megamek.common.preference.PreferenceManager; -import megamek.server.GameManager; import megamek.server.Server; import mekwars.client.common.campaign.clientutils.GameHost; import mekwars.client.common.campaign.clientutils.protocol.CConnector; @@ -62,13 +48,10 @@ import mekwars.client.common.campaign.clientutils.protocol.commands.IProtCommand; import mekwars.client.common.campaign.clientutils.protocol.commands.PingPCmd; import mekwars.client.common.campaign.clientutils.protocol.commands.PongPCmd; -import mekwars.dedicatedhost.protocol.DataFetchClient; -import mekwars.common.GameInterface; import mekwars.common.GameWrapper; -import mekwars.common.MMGame; import mekwars.common.campaign.Buildings; -import mekwars.common.campaign.clientutils.SerializeEntity; -import mekwars.common.util.UnitUtils; +import mekwars.common.util.GameReport; +import mekwars.dedicatedhost.protocol.DataFetchClient; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -91,7 +74,6 @@ public final class MWDedHost extends GameHost implements IClient { boolean SignOff = false; String password = ""; String myDedOwners = ""; - int myPort = -1; int gameCount = 0; // number of games played on a ded long lastResetCheck = System.currentTimeMillis(); // how quick a reset check // can be done on a ded. @@ -101,20 +83,10 @@ public final class MWDedHost extends GameHost implements IClient { // its deleted. long TimeOut = 120; long LastPing = 0; - int Status = 0; - - private GamePhase currentPhase = GamePhase.DEPLOYMENT; - private int turn = 0; Dimension MapSize; Dimension BoardSize; - /** - * Maps the task prefixes as HS, PL, SP etc. to a command under package cmd. - * key: String, value: cmd.Command - */ - HashMap commands = new HashMap(); - String LastQuery = ""; // receiver of last mail private String cacheDir; @@ -127,24 +99,6 @@ public final class MWDedHost extends GameHost implements IClient { public static void main(String[] args) { DedConfig config; - /* - * put StdErr and StdOut into ./logs/megameklog.txt, because MegaMek - * uses StdOut and StdErr, but the part of MegaMek that sets that up - * does not get called when we launch MegaMek in MekWars Redirect output - * to logfiles, unless turned off. Moved megameklog.txt to the logs - * folder -- Torren - */ - String logFileName = "./logs/megameklog.txt"; - - try { - PrintStream ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(logFileName), 64)); - System.setOut(ps); - System.setErr(ps); - } catch (Exception ex) { - LOGGER.error("Exception: ", ex); - LOGGER.error("Unable to redirect MegaMek output to " + logFileName); - } - LOGGER.info("Starting MekWars Client Version: " + CLIENT_VERSION); try { config = new DedConfig(true); @@ -167,19 +121,16 @@ public static void main(String[] args) { } } - public MWDedHost(DedConfig config) { - + public MWDedHost(DedConfig config) throws IOException { ProtCommands = new TreeMap(); - Config = config; - Connector = new CConnector(this); - Users = Collections.synchronizedList(new Vector(1, 1)); createProtCommands(); dataFetcher = new DataFetchClient(Integer.parseInt(Config.getParam("DATAPORT")), Integer.parseInt(Config.getParam("SOCKETTIMEOUTDELAY"))); dataFetcher.setData(Config.getParam("SERVERIP"), getCacheDir()); + dataFetcher.getServerConfigData(this); dataFetcher.closeDataConnection(); // Remove any MM option files that deds may have. @@ -195,13 +146,6 @@ public MWDedHost(DedConfig config) { LOGGER.error("Exception: ", ex); } - // set New timestamp - // this.dataFetcher.setLastTimestamp(new - // Date(System.currentTimeMillis())); - // this.dataFetcher.store(); - - getServerConfigData(); - myUsername = getConfigParam("NAME"); // if this is dedicated host, we mark its name with "[Dedicated]" stamp @@ -241,9 +185,9 @@ public MWDedHost(DedConfig config) { } int retryCount = 0; - while ((Status == STATUS_DISCONNECTED) && (retryCount++ < 20)) { + while ((getStatus() == STATUS_DISCONNECTED) && (retryCount++ < 20)) { connectToServer(chatServerIP, chatServerPort); - if (Status == STATUS_DISCONNECTED) { + if (getStatus() == STATUS_DISCONNECTED) { LOGGER.info("Couldn't connect to server. Retrying in 90 seconds."); try { Thread.sleep(90000); @@ -288,69 +232,7 @@ public MWDedHost(DedConfig config) { * Info (TI|TIMETILLNEXT) SP = Show PopupWindow SM = Show Miscellaneous * (Puts text into Misc Tab) */ - public synchronized void doParseDataInput(String input) { - - // non-null main frame, unbuffer or just pass through - if (decodeBuffer.size() > 0) { - Iterator i = decodeBuffer.iterator(); - while (i.hasNext()) { - String currS = i.next(); - doParseDataHelper(currS); - i.remove(); - } - } else { - doParseDataHelper(input); - } - } - - /* - * Actual GUI-mode parseData. Before we started streaming data over the chat - * part, this was called directly. Now we buffer all incoming non-data chat - * and spit it out at once when the GUI draws. Once the GUI is up, this is - * called by a simple pass through from doParseDataInput(), above. - * - * Ded's call the helper directly to bypass the buffer. - */ - private void doParseDataHelper(String input) { - try { - - // 0-length input is spurious call from MWDedHost constructor. - if (input.length() == 0) { - return; - } - - StringTokenizer ST = null; - String task = null; - - // debug info - LOGGER.info(input); - - // Create a String Tokenizer to parse the elements of the input - ST = new StringTokenizer(input, COMMAND_DELIMITER); - task = ST.nextToken(); - - if (!commands.containsKey(task)) { - try { - Class cmdClass = Class.forName(getClass().getPackage().getName() + ".cmd." + task); - Constructor c = cmdClass.getConstructor(new Class[] - { MWDedHost.class }); - Command cmd = (Command) c.newInstance(new Object[] - { this }); - commands.put(task, cmd); - } catch (Exception e) { - LOGGER.error("Exception: ", e); - } - } - if (commands.containsKey(task)) { - commands.get(task).execute(input); - } - } catch (Exception ex) { - LOGGER.error("Exception: ", ex); - } - } - - public synchronized void parseDedDataInput(String data) { - + public synchronized void doParseDataInput(String data) { // Debug info // LOGGER.info(data); @@ -494,7 +376,6 @@ public synchronized void parseDedDataInput(String data) { * of an owner list. */ while (myDedOwners.equals("") || own.hasMoreTokens()) { - if (own.hasMoreTokens()) { owner = own.nextToken(); } else { @@ -544,7 +425,6 @@ public synchronized void parseDedDataInput(String data) { return; } else if (command.equals("die")) { // shut the dedicated down - goodbye(); System.exit(0); @@ -586,7 +466,6 @@ public synchronized void parseDedDataInput(String data) { return; } else if (command.startsWith("owner ")) { // add new owner(s) - LOGGER.info("Owner command received from " + name); if (!myDedOwners.equals("")) { myDedOwners = myDedOwners + "$"; @@ -619,7 +498,6 @@ public synchronized void parseDedDataInput(String data) { return; } else if (command.startsWith("port ")) {// new server port - LOGGER.info("Port (set) command received from " + name); try { port = Integer.parseInt(command.substring(("port ").length()).trim()); @@ -904,24 +782,10 @@ public void setLastQuery(String name) { LastQuery = name; } - public int getMyStatus() { - return Status; - } - public void setLastPing(long lastping) { LastPing = lastping; } - public String getStatus() { - if (Status == STATUS_DISCONNECTED) { - return ("Not connected"); - } - if (Status == STATUS_LOGGEDOUT) { - return ("Logged out"); - } - return (""); - } - public String getShortTime() { mytime = new Date(); StringTokenizer s = new StringTokenizer(mytime.toString()); @@ -991,7 +855,7 @@ public void setPassword(String s) { } public DedConfig getConfig() { - return (DedConfig) (Config); + return (DedConfig) Config; } public void setConfig() { @@ -1016,7 +880,7 @@ public String getConfigParam(String p) { tparam = ""; } - if (tparam.isEmpty() && p.equals("NAME") && isDedicated()) { + if (tparam.isEmpty() && p.equals("NAME")) { LOGGER.info("Error: no dedicated name set."); System.exit(1); } @@ -1052,45 +916,38 @@ public void processIncoming(String incoming) { } public void connectionLost() { - - Status = STATUS_DISCONNECTED; + setStatus(STATUS_DISCONNECTED); if (SignOff) { return; } errorMessage("Connection lost."); - if (isDedicated()) { - - // no point in having a server open w/o connection to campaign - // server - stopHost(); + // no point in having a server open w/o connection to campaign + // server + stopHost(); - // wait at least 90 seconds before trying to connect again - try { - Thread.sleep(90000); - } catch (Exception ex) { - LOGGER.error("Exception: ", ex); - } + // wait at least 90 seconds before trying to connect again + try { + Thread.sleep(90000); + } catch (Exception ex) { + LOGGER.error("Exception: ", ex); + } - // keep retrying every two minutes after the first 90 sec downtime. - while (Status == STATUS_DISCONNECTED) { - connectToServer(Config.getParam("SERVERIP"), Config.getIntParam("SERVERPORT")); - if (Status == STATUS_DISCONNECTED) { - LOGGER.info("Couldn't reconnect to server. Retrying in 120 seconds."); - try { - Thread.sleep(90000); - } catch (Exception ex) { - LOGGER.error("Exception: ", ex); - } + // keep retrying every two minutes after the first 90 sec downtime. + while (getStatus() == STATUS_DISCONNECTED) { + connectToServer(Config.getParam("SERVERIP"), Config.getIntParam("SERVERPORT")); + if (getStatus() == STATUS_DISCONNECTED) { + LOGGER.info("Couldn't reconnect to server. Retrying in 120 seconds."); + try { + Thread.sleep(90000); + } catch (Exception ex) { + LOGGER.error("Exception: ", ex); } } - } else { - Users.clear(); } } public void connectionEstablished() { - LastPing = System.currentTimeMillis() / 1000; LOGGER.error("Connected. Signing on."); @@ -1110,7 +967,7 @@ public void connectionEstablished() { } Connector.send(PROTOCOL_PREFIX + "signon\t" + getConfigParam("NAME") + "\t" + passToSend + "\t" + getProtocolVersion() + "\t" + Config.getParam("COLOR") + "\t" + CLIENT_VERSION + "\t" + ST.nextToken()); - Status = STATUS_LOGGEDOUT; + setStatus(STATUS_LOGGEDOUT); } // IClient interface @@ -1130,7 +987,7 @@ public void connectToServer(String ip, int port) { public void goodbye() { SignOff = true; - if (Status != STATUS_DISCONNECTED) { + if (getStatus() != STATUS_DISCONNECTED) { // serverSend("GB"); Connector.send(PROTOCOL_PREFIX + "signoff"); dataFetcher.closeDataConnection(); @@ -1139,97 +996,26 @@ public void goodbye() { } + @Override public void startHost(boolean dedicated, boolean deploy, boolean loadSavegame) { - - // reread the config to allow the user to change setting during runtime - String ip = "127.0.0.1"; - if (!getConfigParam("IP:").equals("")) {// IP Setting set, override IP - // detection. - try { - ip = getConfigParam("IP:"); - InetAddress IA = InetAddress.getByName(ip); // Resolve Dyndns - // Entries - ip = IA.getHostAddress(); - } catch (Exception ex) { - return; - } - } - - String MMVersion = getServerConfigs("AllowedMegaMekVersion"); - if (!MMVersion.equals("-1") && !MMVersion.equalsIgnoreCase(megamek.MMConstants.VERSION.toString())) { - LOGGER.error("You are using an invalid version of MegaMek. Please use version {}", MMVersion); - stopHost(); - updateDed(); - return; - } - - if (servers.get(myUsername) != null) { - if (isDedicated()) { - LOGGER.error("Attempted to start a second host while host was already running."); - } else { - String toUser = "CH|CLIENT: You already have a host open."; - doParseDataInput(toUser); - } - return; - } - - // int port = Integer.parseInt(getConfigParam("PORT:")); - int MaxPlayers = Integer.parseInt(getConfigParam("MAXPLAYERS:")); - String comment = getConfigParam("COMMENT:"); - String gpassword = getConfigParam("GAMEPASSWORD:"); - - if (gpassword == null) { - gpassword = ""; - } try { - myServer = new Server(gpassword, myPort, new GameManager()); - } catch (Exception ex) { - try { - if (myServer == null) { - LOGGER.error("Error opening dedicated server. Result = null host."); - LOGGER.error("Exception: ", ex); - } else { - LOGGER.error("Error opening dedicated server. Will attempt a .die()."); - LOGGER.error("Exception: ", ex); - myServer.die(); - myServer = null; - } - } catch (Exception e) { - LOGGER.error("Further error while trying to clean up failed host attempt."); - LOGGER.error("Exception: ", e); - } + super.startHost(dedicated, deploy, loadSavegame); + } catch (Exception exception) { + LOGGER.error("Unable to start host", exception); return; } - - ((Game)myServer.getGame()).addGameListener(this); - // Send the new game info to the Server - serverSend("NG|" + new MMGame(myUsername, ip, myPort, MaxPlayers, MMConstants.VERSION, comment).toString()); clearSavedGames(); purgeOldLogs(); ClientPreferences cs = PreferenceManager.getClientPreferences(); cs.setStampFilenames(Boolean.parseBoolean(getServerConfigs("MMTimeStampLogFile"))); } - // Stop & send the close game event to the Server - public void stopHost() { - - serverSend("CG");// send close game to server - try { - if (myServer != null) { - myServer.die(); - } - } catch (Exception ex) { - LOGGER.error("Megamek Error:"); - LOGGER.error("Exception: ", ex); - } - myServer = null; - } public void resetGame() { // reset hosted game if (myServer != null) { myServer.resetGame(); - ((Game)myServer.getGame()).getGameListeners().clear(); - ((Game)myServer.getGame()).addGameListener(this); + ((Game) myServer.getGame()).purgeGameListeners(); + ((Game) myServer.getGame()).addGameListener(this); } } @@ -1279,7 +1065,6 @@ public boolean isServerRunning() { } public void closingGame(String hostName) { - // update battles tab for all players, via server LOGGER.info("Leaving " + hostName); serverSend("LG|" + hostName); @@ -1316,7 +1101,7 @@ public void run() { } catch (Exception ex) { LOGGER.error("Exception: ", ex); } - if (mwdedhost.Status != MWDedHost.STATUS_DISCONNECTED) { + if (mwdedhost.getStatus() != MWDedHost.STATUS_DISCONNECTED) { long timeout = (System.currentTimeMillis() / 1000) - LastPing; if (timeout > mwdedhost.TimeOut) { systemMessage("Ping timeout (" + timeout + " s)"); @@ -1354,15 +1139,6 @@ public String getCacheDir() { return cacheDir; } - /** - * Changes the duty to a new status. - * - * @param newStatus - */ - public void changeStatus(int newStatus) { - Status = newStatus; - } - // this adds 1 to the number of games played and if it matched the restart // amount it restarts the ded. public void checkForRestart() { @@ -1390,15 +1166,13 @@ public void checkForRestart() { } restartDed(); } - lastResetCheck = System.currentTimeMillis(); } public void clearSavedGames() { - long daysInSeconds = ((long) savedGamesMaxDays) * 24 * 60 * 60 * 1000; - File saveFiles = new File("./savegames/"); + if (!saveFiles.exists()) { return; } @@ -1418,7 +1192,6 @@ public void clearSavedGames() { } public String getParanoidAutoSave() { - File tempFile = new File("./savegames/"); FilenameFilter filter = new AutoSaveFilter(); File[] fileList = tempFile.listFiles(filter); @@ -1433,62 +1206,6 @@ public String getParanoidAutoSave() { return saveFile; } - - - public void retrieveOpData(String type, String data) { - - StringTokenizer st = new StringTokenizer(data, "#"); - - String opName = st.nextToken(); - - File opFile = new File("./data/operations/" + type); - - if (!opFile.exists()) { - opFile.mkdirs(); - } - - opFile = new File("./data/operations/" + type + "/" + opName + ".txt"); - try { - FileOutputStream out = new FileOutputStream(opFile); - PrintStream p = new PrintStream(out); - while (st.hasMoreTokens()) { - p.println(st.nextToken().replaceAll("\\(pound\\)", "#")); - } - p.close(); - out.close(); - } catch (Exception ex) { - LOGGER.error("Exception: ", ex); - } - - } - - public void retrieveMul(String data) { - - StringTokenizer st = new StringTokenizer(data, "#"); - - String mulName = st.nextToken(); - - File mulFile = new File("./data/armies/"); - - if (!mulFile.exists()) { - mulFile.mkdirs(); - } - - mulFile = new File("./data/armies/" + mulName); - try { - FileOutputStream out = new FileOutputStream(mulFile); - PrintStream p = new PrintStream(out); - while (st.hasMoreTokens()) { - p.println(st.nextToken().replaceAll("\\(pound\\)", "#")); - } - p.close(); - out.close(); - } catch (Exception ex) { - LOGGER.error("Exception: ", ex); - } - - } - public boolean isDedicated() { return true; } @@ -1559,13 +1276,11 @@ public void run() { }// end PurgeAutoSaves public void errorMessage(String message) { - // TODO Auto-generated method stub - + LOGGER.error(message); } public void systemMessage(String message) { - // TODO Auto-generated method stub - + LOGGER.error(message); } public void getServerConfigData() { @@ -1599,12 +1314,12 @@ private void restartDed() { String memory = Config.getParam("DEDMEMORY"); Runtime runTime = Runtime.getRuntime(); String[] call = - { "java", "-Xmx" + memory + "m", "-jar", "MekWarsDed.jar" }; + { "java", "-Xmx" + memory + "m", "-jar", "MekWarsDedicatedHost.jar" }; runTime.exec(call); System.exit(0); } catch (Exception ex) { - LOGGER.error("Unable to find MekWarsDed.jar"); + LOGGER.error("Unable to find MekWarsDedicatedHost.jar"); } } @@ -1624,240 +1339,19 @@ private void updateDed() { System.exit(0);// restart the ded } - protected void sendServerGameUpdate() { - // Report the mech stat - - // Only send data for units currently on the board. - // any units removed from play will have already sent thier final - // update. - Iterator en = ((Game)myServer.getGame()).getEntities(); - while (en.hasNext()) { - Entity ent = en.next(); - 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))) { - continue; - } - if ((ent instanceof Mech) && (ent.getInternal(Mech.LOC_CT) <= 0)) { - serverSend("IPU|" - + SerializeEntity.serializeEntity(ent, true, true, - isUsingAdvanceRepairs())); - } else { - serverSend("IPU|" - + SerializeEntity.serializeEntity(ent, true, false, - isUsingAdvanceRepairs())); - } - } - } - - public static StringBuilder prepareReport(GameInterface myGame, boolean usingAdvancedRepairs, Buildings buildingTemplate) { - StringBuilder result = new StringBuilder(); - String name = ""; - // Parse the real playername from the Modified In game one.. - String winnerName = ""; - if (myGame.hasWinner()) { - - int numberOfWinners = 0; - // Multiple Winners - List winners = myGame.getWinners(); - - //TODO: Winners is sometimes coming up empty. Let's see why - LOGGER.error("Finding winners:"); - LOGGER.error(winners.toString()); - - for (String winner: winners){ - StringTokenizer st = new StringTokenizer(winner, "~"); - name = ""; - while (st.hasMoreElements()) { - name = st.nextToken().trim(); - } - // some of the players set themselves as a team of 1. - // This keeps that from happening. - if (numberOfWinners > 0) { - winnerName += "*"; - } - numberOfWinners++; - - winnerName += name; - } - if (winnerName.endsWith("*")) { - winnerName = winnerName.substring(0, winnerName.length() - 1); - } - winnerName += "#"; - } - - else { - winnerName = "DRAW#"; - } - - result.append(winnerName); - - // Report the mech stat - Enumeration en = myGame.getDevastatedEntities(); - while (en.hasMoreElements()) { - Entity ent = en.nextElement(); - if (ent.getOwner().getName().startsWith("War Bot")) { - continue; - } - result.append(SerializeEntity.serializeEntity(ent, true, false, usingAdvancedRepairs)); - result.append("#"); - } - en = myGame.getGraveyardEntities(); - while (en.hasMoreElements()) { - Entity ent = en.nextElement(); - if (ent.getOwner().getName().startsWith("War Bot")) { - continue; - } - result.append(SerializeEntity.serializeEntity(ent, true, false, usingAdvancedRepairs)); - result.append("#"); - - } - Iterator en2 = myGame.getEntities(); - while (en2.hasNext()) { - Entity ent = en2.next(); - if (ent.getOwner().getName().startsWith("War Bot")) { - continue; - } - result.append(SerializeEntity.serializeEntity(ent, true, false, usingAdvancedRepairs)); - result.append("#"); - } - en = myGame.getRetreatedEntities(); - while (en.hasMoreElements()) { - Entity ent = en.nextElement(); - if (ent.getOwner().getName().startsWith("War Bot")) { - continue; - } - result.append(SerializeEntity.serializeEntity(ent, true, false, usingAdvancedRepairs)); - result.append("#"); - } - - if (buildingTemplate != null) { - result.append("BL*" + buildingTemplate); - } - LOGGER.info("CR|" + result); - return result; - } - protected void sendGameReport() { if (myServer == null) { return; } - //GameReporter.prepareReport(myGame, usingAdvancedRepairs, buildingTemplate) - - StringBuilder result = prepareReport(new GameWrapper(((Game)myServer.getGame())), isUsingAdvanceRepairs(), buildingTemplate); + StringBuilder result = GameReport.prepareReport(new GameWrapper(((Game)myServer.getGame())), isUsingAdvanceRepairs(), buildingTemplate); serverSend("CR|" + result.toString()); -/* StringBuilder result = new StringBuilder(); - String name = ""; - // Parse the real playername from the Modified In game one.. - String winnerName = ""; - if (((Game)myServer.getGame()).getVictoryTeam() != Player.TEAM_NONE) { - - int numberOfWinners = 0; - // Multiple Winners - Enumeration en = ((Game)myServer.getGame()).getPlayers(); - while (en.hasMoreElements()) { - Player p = en.nextElement(); - if (p.getTeam() == ((Game)myServer.getGame()).getVictoryTeam()) { - StringTokenizer st = new StringTokenizer(p.getName().trim(), "~"); - name = ""; - while (st.hasMoreElements()) { - name = st.nextToken().trim(); - } - // some of the players set themselves as a team of 1. - // This keeps that from happening. - if (numberOfWinners > 0) { - winnerName += "*"; - } - numberOfWinners++; - - winnerName += name; - } - } - if (winnerName.endsWith("*")) { - winnerName = winnerName.substring(0, winnerName.length() - 1); - } - winnerName += "#"; - } - - // Only one winner - else { - if (((Game)myServer.getGame()).getVictoryPlayerId() == Player.PLAYER_NONE) { - winnerName = "DRAW#"; - } else { - winnerName = ((Game)myServer.getGame()).getPlayer(((Game)myServer.getGame()).getVictoryPlayerId()).getName(); - StringTokenizer st = new StringTokenizer(winnerName, "~"); - name = ""; - while (st.hasMoreElements()) { - name = st.nextToken().trim(); - } - winnerName = name + "#"; - } - } - - result.append(winnerName); - - // Report the mech stat - Enumeration en = ((Game)myServer.getGame()).getDevastatedEntities(); - while (en.hasMoreElements()) { - Entity ent = en.nextElement(); - if (ent.getOwner().getName().startsWith("War Bot")) { - continue; - } - result.append(SerializeEntity.serializeEntity(ent, true, false, isUsingAdvanceRepairs())); - result.append("#"); - } - en = ((Game)myServer.getGame()).getGraveyardEntities(); - while (en.hasMoreElements()) { - Entity ent = en.nextElement(); - if (ent.getOwner().getName().startsWith("War Bot")) { - continue; - } - result.append(SerializeEntity.serializeEntity(ent, true, false, isUsingAdvanceRepairs())); - result.append("#"); - - } - en = ((Game)myServer.getGame()).getEntities(); - while (en.hasMoreElements()) { - Entity ent = en.nextElement(); - if (ent.getOwner().getName().startsWith("War Bot")) { - continue; - } - result.append(SerializeEntity.serializeEntity(ent, true, false, isUsingAdvanceRepairs())); - result.append("#"); - } - en = ((Game)myServer.getGame()).getRetreatedEntities(); - while (en.hasMoreElements()) { - Entity ent = en.nextElement(); - if (ent.getOwner().getName().startsWith("War Bot")) { - continue; - } - result.append(SerializeEntity.serializeEntity(ent, true, false, isUsingAdvanceRepairs())); - result.append("#"); - } - - if (getBuildingTemplate() != null) { - result.append("BL*" + getBuildingsLeft()); - } - LOGGER.info("CR|" + result); - - // send the autoreport - serverSend("CR|" + result.toString());*/ - // we may assume that a server which reports a game is no longer // "Running" serverSend("SHS|" + myUsername + "|Open"); - // myServer.resetGame(); - - if (isDedicated()) { - checkForRestart(); - } + checkForRestart(); } @Override @@ -1865,4 +1359,10 @@ public void gameClientFeedbackRequest(GameCFREvent arg0) { // TODO Auto-generated method stub } + + // Cannot load savegames + @Override + public void loadSavegame() { + throw new UnsupportedOperationException("Dedicated server is unable to load savegames"); + } } diff --git a/MekWarsDedicatedHost/src/mekwars/dedicatedhost/cmd/CS.java b/MekWarsDedicatedHost/src/mekwars/dedicatedhost/cmd/CS.java index 0164baf7..85b43919 100644 --- a/MekWarsDedicatedHost/src/mekwars/dedicatedhost/cmd/CS.java +++ b/MekWarsDedicatedHost/src/mekwars/dedicatedhost/cmd/CS.java @@ -36,6 +36,6 @@ public CS(MWDedHost mwclient) { */ @Override public void execute(String input) { - mwclient.changeStatus(Integer.parseInt(decode(input).nextToken())); + mwclient.setStatus(Integer.parseInt(decode(input).nextToken())); } } diff --git a/MekWarsDedicatedHost/src/mekwars/dedicatedhost/cmd/PL.java b/MekWarsDedicatedHost/src/mekwars/dedicatedhost/cmd/PL.java index f1b935f6..fd6e3174 100644 --- a/MekWarsDedicatedHost/src/mekwars/dedicatedhost/cmd/PL.java +++ b/MekWarsDedicatedHost/src/mekwars/dedicatedhost/cmd/PL.java @@ -26,41 +26,42 @@ */ public class PL extends Command { - - /** - * @param client - */ - public PL(MWDedHost mwclient) { - super(mwclient); - } - - /** - * @see client.cmd.Command#execute(java.lang.String) - */ - @Override - public void execute(String input) { - StringTokenizer st = decode(input); - - String cmd = st.nextToken(); - - if (!st.hasMoreTokens()) - return; + + /** + * @param client + */ + public PL(MWDedHost mwclient) { + super(mwclient); + } + + /** + * @see client.cmd.Command#execute(java.lang.String) + */ + @Override + public void execute(String input) { + StringTokenizer st = decode(input); + + String cmd = st.nextToken(); + + if (!st.hasMoreTokens()) { + return; + } - if(cmd.equals("GBB"))//Go bye bye - mwclient.getConnector().closeConnection(); - else if(cmd.equals("RSOD"))//Retrieve Short Op Data - mwclient.retrieveOpData("short",st.nextToken()); - else if(cmd.equals("UCP"))//Update/Set a clients param + if(cmd.equals("GBB")) {//Go bye bye + mwclient.getConnector().closeConnection(); + } else if (cmd.equals("RSOD")) { //Retrieve Short Op Data + mwclient.retrieveOpData("short", st.nextToken()); + } else if (cmd.equals("UCP")) { //Update/Set a clients param mwclient.updateParam(st); - else if ( cmd.equals("RMF") ) { - mwclient.retrieveMul(st.nextToken()); - } else if ( cmd.equals("UAR") ) { - while ( st.hasMoreTokens() ){ + } else if (cmd.equals("RMF")) { + mwclient.retrieveMul(st.nextToken()); + } else if (cmd.equals("UAR")) { + while (st.hasMoreTokens()) { mwclient.getConfig().setParam(st.nextToken(), st.nextToken()); } mwclient.getConfig().saveConfig(); + } else { + return; } - else - return; - } + } } diff --git a/MekWarsServer/data/campaignconfig.txt b/MekWarsServer/data/campaignconfig.txt index 8b88659a..727a0871 100644 --- a/MekWarsServer/data/campaignconfig.txt +++ b/MekWarsServer/data/campaignconfig.txt @@ -1,6 +1,6 @@ -#Timestamp=1755982095530 +#Timestamp=1769909030156 #Server Config -#Sat Aug 23 15:48:15 CDT 2025 +#Sat Jan 31 19:23:50 CST 2026 MediumAeroInf=2 AssaultBattleArmorPrice=40 MaxBMSalesTicks=100 diff --git a/build.gradle b/build.gradle index 2c1fbb84..111f1cb9 100644 --- a/build.gradle +++ b/build.gradle @@ -59,6 +59,7 @@ distributions { into "${lib}" } from "${mmDir}/megamek/build/libs/MegaMek.jar" + from "${mmDir}/megamek/build/files/data/mechfiles" duplicatesStrategy = 'exclude' } } @@ -80,6 +81,7 @@ distributions { into "${lib}" } from "${mmDir}/megamek/build/libs/MegaMek.jar" + from "${mmDir}/megamek/build/files" duplicatesStrategy = 'exclude' } }