diff --git a/megamek/i18n/megamek/client/messages.properties b/megamek/i18n/megamek/client/messages.properties index 272747b8bbc..1cdc8974ba9 100644 --- a/megamek/i18n/megamek/client/messages.properties +++ b/megamek/i18n/megamek/client/messages.properties @@ -3714,6 +3714,7 @@ MegaMek.MapEditor.label=Map Editor MegaMek.SaveGameDialog.title=Select saved game MegaMek.LoadGameAlert.title=Load a Game MegaMek.LoadGameAlert.message=Error: unable to load game file "%s" +MegaMek.LoadGameMissingVersion.message=Error: MegaMek does not support version migration, and thus cannot load a save file missing a version into %s. MegaMek.LoadGameIncorrectVersion.message=Error: MegaMek does not support version migration, and thus cannot load a save file from %s into %s. MegaMek.HostGameAlert.title=Host a Game MegaMek.HostDialog.title=Start Game @@ -3725,7 +3726,6 @@ MegaMek.ScenarioDialog.title=Set Scenario Players MegaMek.ScenarioDialog.me=Me MegaMek.ScenarioDialog.otherh=Other Human MegaMek.ScenarioDialog.bot=Princess -MegaMek.ScenarioDialog.otherbot=Test Bot (Do not use) MegaMek.ScenarioDialog.Camo=Camo MegaMek.SkinEditor.label=Skin Editor MegaMek.NoCamoBtn=No Camo diff --git a/megamek/src/megamek/Version.java b/megamek/src/megamek/Version.java index 9e49554fa3f..cb9004184d3 100644 --- a/megamek/src/megamek/Version.java +++ b/megamek/src/megamek/Version.java @@ -26,6 +26,7 @@ import javax.swing.*; import java.io.PrintWriter; import java.io.Serializable; +import java.util.Objects; /** * This is used for versioning, and to track the current Version the suite is running at. @@ -55,6 +56,15 @@ public Version(final @Nullable String text) { this(); fillFromText(text); } + + public Version(final String release, final String major, final String minor, + final String snapshot) throws NumberFormatException { + this(); + setRelease(Integer.parseInt(release)); + setMajor(Integer.parseInt(major)); + setMinor(Integer.parseInt(minor)); + setSnapshot(Boolean.parseBoolean(snapshot)); + } //endregion Constructors //region Getters diff --git a/megamek/src/megamek/client/ui/swing/MegaMekGUI.java b/megamek/src/megamek/client/ui/swing/MegaMekGUI.java index 696d9c54dc2..8f6e1e2759b 100644 --- a/megamek/src/megamek/client/ui/swing/MegaMekGUI.java +++ b/megamek/src/megamek/client/ui/swing/MegaMekGUI.java @@ -16,9 +16,9 @@ */ package megamek.client.ui.swing; -import com.thoughtworks.xstream.XStream; -import megamek.MegaMek; import megamek.MMConstants; +import megamek.MegaMek; +import megamek.Version; import megamek.client.Client; import megamek.client.bot.BotClient; import megamek.client.bot.TestBot; @@ -38,6 +38,7 @@ import megamek.client.ui.swing.widget.SkinSpecification; import megamek.client.ui.swing.widget.SkinSpecification.UIComponents; import megamek.client.ui.swing.widget.SkinXMLHandler; +import megamek.codeUtilities.StringUtility; import megamek.common.*; import megamek.common.annotations.Nullable; import megamek.common.enums.GamePhase; @@ -48,21 +49,26 @@ import megamek.common.preference.PreferenceManager; import megamek.common.util.EmailService; import megamek.common.util.ImageUtil; -import megamek.common.util.SerializationHelper; import megamek.common.util.fileUtils.MegaMekFile; import megamek.server.GameManager; import megamek.server.ScenarioLoader; import megamek.server.Server; +import megamek.utilities.xml.MMXMLUtility; import org.apache.logging.log4j.LogManager; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import javax.swing.*; import javax.swing.filechooser.FileFilter; +import javax.xml.parsers.DocumentBuilder; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; -import java.awt.image.BufferedImage; import java.awt.image.BaseMultiResolutionImage; +import java.awt.image.BufferedImage; import java.io.*; import java.net.MalformedURLException; import java.net.URL; @@ -79,8 +85,6 @@ public class MegaMekGUI implements IPreferenceChangeListener { private static final String FILENAME_ICON_48X48 = "megamek-icon-48x48.png"; private static final String FILENAME_ICON_256X256 = "megamek-icon-256x256.png"; - private static final int DEFAULT_DISPLAY_DPI = 96; - private JFrame frame; private Client client; private Server server; @@ -400,8 +404,9 @@ void host() { hd.getPlayerName()); } - public void startHost(String serverPassword, int port, boolean isRegister, String metaServer, - String mailPropertiesFileName, File savegame, String playerName) { + public void startHost(@Nullable String serverPassword, int port, boolean isRegister, + @Nullable String metaServer, @Nullable String mailPropertiesFileName, + @Nullable File savegame, String playerName) { if (!startServer(serverPassword, port, isRegister, metaServer, mailPropertiesFileName, savegame)) { return; } @@ -422,7 +427,7 @@ public boolean startServer(@Nullable String serverPassword, int port, boolean is } EmailService mailer = null; - if ( (mailPropertiesFileName != null) && (!mailPropertiesFileName.isBlank())) { + if (!StringUtility.isNullOrBlank(mailPropertiesFileName)) { File propsFile = new File(mailPropertiesFileName); try (var propsReader = new FileReader(propsFile)) { var mailProperties = new Properties(); @@ -442,11 +447,13 @@ public boolean startServer(@Nullable String serverPassword, int port, boolean is // kick off a RNG check d6(); + // start server try { gameManager = new GameManager(); server = new Server(serverPassword, port, gameManager, isRegister, metaServer, mailer, false); - MegaMek.printToOut(Messages.getFormattedString("MegaMek.ServerStarted", server.getHost(), server.getPort(), server.isPassworded() ? "enabled" : "disabled") + "\n"); + MegaMek.printToOut(Messages.getFormattedString("MegaMek.ServerStarted", + server.getHost(), server.getPort(), server.isPassworded() ? "enabled" : "disabled") + "\n"); } catch (IOException ex) { LogManager.getLogger().error("Could not create server socket on port " + port, ex); JOptionPane.showMessageDialog(frame, @@ -528,7 +535,8 @@ void loadGame() { fc.setFileFilter(new FileFilter() { @Override public boolean accept(File dir) { - return ((dir.getName().endsWith(MMConstants.SAVE_FILE_EXT) || dir.getName().endsWith(MMConstants.SAVE_FILE_GZ_EXT) || dir.isDirectory())); + return dir.getName().endsWith(MMConstants.SAVE_FILE_EXT) + || dir.getName().endsWith(MMConstants.SAVE_FILE_GZ_EXT) || dir.isDirectory(); } @Override @@ -542,32 +550,50 @@ public String getDescription() { return; } - // extract game data before starting to check and get player names - Game newGame; - try (InputStream is = new FileInputStream(fc.getSelectedFile()); InputStream gzi = new GZIPInputStream(is)) { - XStream xstream = SerializationHelper.getXStream(); - newGame = (Game) xstream.fromXML(gzi); - } catch (Exception e) { - LogManager.getLogger().error("Unable to load file: " + fc.getSelectedFile().getAbsolutePath(), e); - JOptionPane.showMessageDialog(frame, Messages.getFormattedString("MegaMek.LoadGameAlert.message", fc.getSelectedFile().getAbsolutePath()), - Messages.getString("MegaMek.LoadGameAlert.title"), JOptionPane.ERROR_MESSAGE); - return; - } + final Vector playerNames = new Vector<>(); + + // Handrolled extraction, as we require Server initialization to use XStream and don't need + // the additional overhead of initializing everything twice + try (InputStream is = new FileInputStream(fc.getSelectedFile()); + InputStream gzi = new GZIPInputStream(is)) { + // Using factory get an instance of document builder + final DocumentBuilder documentBuilder = MMXMLUtility.newSafeDocumentBuilder(); + // Parse using builder to get DOM representation of the XML file + final Document xmlDocument = documentBuilder.parse(gzi); + + final Element gameElement = xmlDocument.getDocumentElement(); + gameElement.normalize(); + + final NodeList nl = gameElement.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) { + final Node n = nl.item(i); + if (n.getNodeType() != Node.ELEMENT_NODE) { + continue; + } - if (!MMConstants.VERSION.is(newGame.getVersion())) { - final String message = String.format(Messages.getString("MegaMek.LoadGameIncorrectVersion.message"), - newGame.getVersion(), MMConstants.VERSION); - JOptionPane.showMessageDialog(frame, message, - Messages.getString("MegaMek.LoadGameAlert.title"), JOptionPane.ERROR_MESSAGE); - LogManager.getLogger().error(message); + switch (n.getNodeName()) { + case "version": + if (!validateSaveVersion(n)) { + return; + } + break; + case "players": + parsePlayerNames(n, playerNames); + break; + default: + break; + } + } + } catch (Exception ex) { + LogManager.getLogger().error("Unable to load file: " + fc.getSelectedFile().getAbsolutePath(), ex); + JOptionPane.showMessageDialog(frame, + Messages.getFormattedString("MegaMek.LoadGameAlert.message", + fc.getSelectedFile().getAbsolutePath()), + Messages.getString("MegaMek.LoadGameAlert.title"), + JOptionPane.ERROR_MESSAGE); return; } - Vector playerNames = new Vector<>(); - for (Player player : newGame.getPlayersVector()) { - playerNames.add(player.getName()); - } - HostDialog hd = new HostDialog(frame, playerNames); hd.setVisible(true); @@ -579,6 +605,88 @@ public String getDescription() { hd.isRegister(), hd.isRegister() ? hd.getMetaserver() : "", null, fc.getSelectedFile(), hd.getPlayerName()); } + + private boolean validateSaveVersion(final Node n) { + if (!n.hasChildNodes()) { + final String message = String.format( + Messages.getString("MegaMek.LoadGameMissingVersion.message"), + MMConstants.VERSION); + JOptionPane.showMessageDialog(frame, message, + Messages.getString("MegaMek.LoadGameAlert.title"), + JOptionPane.ERROR_MESSAGE); + LogManager.getLogger().error(message); + return false; + } + + final NodeList nl = n.getChildNodes(); + String release = null; + String major = null; + String minor = null; + String snapshot = null; + for (int i = 0; i < nl.getLength(); i++) { + final Node n2 = nl.item(i); + if (n2.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + + switch (n2.getNodeName()) { + case "release": + release = n2.getTextContent(); + break; + case "major": + major = n2.getTextContent(); + break; + case "minor": + minor = n2.getTextContent(); + break; + case "snapshot": + snapshot = n2.getTextContent(); + break; + default: + break; + } + } + + final Version version = new Version(release, major, minor, snapshot); + if (MMConstants.VERSION.is(version)) { + return true; + } else { + final String message = String.format( + Messages.getString("MegaMek.LoadGameIncorrectVersion.message"), + version, MMConstants.VERSION); + JOptionPane.showMessageDialog(frame, message, + Messages.getString("MegaMek.LoadGameAlert.title"), JOptionPane.ERROR_MESSAGE); + LogManager.getLogger().error(message); + return false; + } + } + + private void parsePlayerNames(final Node n, final Vector playerNames) { + if (!n.hasChildNodes()) { + return; + } + + final NodeList nl = n.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) { + final Node n2 = nl.item(i); + if ((n2.getNodeType() != Node.ELEMENT_NODE) || !n2.hasChildNodes() + || !Player.class.getName().equals(n2.getNodeName())) { + continue; + } + + final NodeList nl2 = n2.getChildNodes(); + for (int j = 0; j < nl2.getLength(); j++) { + final Node n3 = nl2.item(j); + if (n3.getNodeType() != Node.ELEMENT_NODE) { + continue; + } + + if ("name".equals(n3.getNodeName())) { + playerNames.add(n3.getTextContent()); + } + } + } + } /** Developer Utility: Loads "quicksave.sav.gz" with the last used connection settings. */ public void quickLoadGame() { @@ -592,8 +700,8 @@ public void quickLoadGame() { return; } - startHost("", 0, false, "", null, - file, PreferenceManager.getClientPreferences().getLastPlayerName()); + startHost("", 0, false, "", null, file, + PreferenceManager.getClientPreferences().getLastPlayerName()); } /** diff --git a/megamek/src/megamek/common/EquipmentType.java b/megamek/src/megamek/common/EquipmentType.java index 501595ff4d6..73d307a2742 100644 --- a/megamek/src/megamek/common/EquipmentType.java +++ b/megamek/src/megamek/common/EquipmentType.java @@ -1419,20 +1419,8 @@ public String toString() { return "EquipmentType: " + name; } - protected static GameOptions getGameOptions() { - if (Server.getServerInstance() == null) { - return null; - } else if (Server.getServerInstance().getGame() == null) { - return null; - } - return Server.getServerInstance().getGame().getOptions(); - } - public String getShortName() { - if (shortName.isBlank()) { - return getName(); - } - return shortName; + return shortName.isBlank() ? getName() : shortName; } public String getShortName(double size) { diff --git a/megamek/src/megamek/common/Game.java b/megamek/src/megamek/common/Game.java index 5c7e94012f0..7ac1de83e04 100644 --- a/megamek/src/megamek/common/Game.java +++ b/megamek/src/megamek/common/Game.java @@ -57,6 +57,10 @@ public class Game implements IGame, Serializable { */ public final Version version = MMConstants.VERSION; + private Vector players = new Vector<>(); + private Hashtable playerIds = new Hashtable<>(); + private Vector teams = new Vector<>(); + private GameOptions options = new GameOptions(); private Board board = new Board(); @@ -71,11 +75,6 @@ public class Game implements IGame, Serializable { */ private Vector vOutOfGame = new Vector<>(); - private Vector players = new Vector<>(); - private Vector teams = new Vector<>(); - - private Hashtable playerIds = new Hashtable<>(); - private final Map> entityPosLookup = new HashMap<>(); /** diff --git a/megamek/src/megamek/common/weapons/ACAPHandler.java b/megamek/src/megamek/common/weapons/ACAPHandler.java index 99381a09c80..baa2e62e075 100644 --- a/megamek/src/megamek/common/weapons/ACAPHandler.java +++ b/megamek/src/megamek/common/weapons/ACAPHandler.java @@ -34,39 +34,23 @@ public class ACAPHandler extends ACWeaponHandler { private static final long serialVersionUID = -4251291510045646817L; - /** - * @param t - * @param w - * @param g - */ public ACAPHandler(ToHitData t, WeaponAttackAction w, Game g, GameManager m) { super(t, w, g, m); generalDamageType = HitData.DAMAGE_ARMOR_PIERCING; } - /* - * (non-Javadoc) - * - * @see - * megamek.common.weapons.WeaponHandler#handleEntityDamage(megamek.common - * .Entity, java.util.Vector, megamek.common.Building, int, int, int, int) - */ @Override - protected void handleEntityDamage(Entity entityTarget, - Vector vPhaseReport, Building bldg, int hits, int nCluster, - int bldgAbsorbs) { + protected void handleEntityDamage(Entity entityTarget, Vector vPhaseReport, + Building bldg, int hits, int nCluster, int bldgAbsorbs) { AmmoType atype = (AmmoType) weapon.getLinked().getType(); - HitData hit = entityTarget.rollHitLocation(toHit.getHitTable(), - toHit.getSideTable(), waa.getAimedLocation(), - waa.getAimingMode(), toHit.getCover()); + HitData hit = entityTarget.rollHitLocation(toHit.getHitTable(), toHit.getSideTable(), + waa.getAimedLocation(), waa.getAimingMode(), toHit.getCover()); hit.setGeneralDamageType(generalDamageType); hit.setAttackerId(getAttackerId()); - if (entityTarget.removePartialCoverHits(hit.getLocation(), toHit - .getCover(), Compute.targetSideTable(ae, entityTarget, weapon - .getCalledShot().getCall()))) { + if (entityTarget.removePartialCoverHits(hit.getLocation(), toHit.getCover(), + Compute.targetSideTable(ae, entityTarget, weapon.getCalledShot().getCall()))) { // Weapon strikes Partial Cover. - handlePartialCoverHit(entityTarget, vPhaseReport, hit, bldg, hits, - nCluster, bldgAbsorbs); + handlePartialCoverHit(entityTarget, vPhaseReport, hit, bldg, hits, nCluster, bldgAbsorbs); return; } @@ -98,8 +82,8 @@ protected void handleEntityDamage(Entity entityTarget, Hex targetHex = game.getBoard().getHex(target.getPosition()); boolean targetStickingOutOfBuilding = unitStickingOutOfBuilding(targetHex, entityTarget); - nDamage = absorbBuildingDamage(nDamage, entityTarget, bldgAbsorbs, - vPhaseReport, bldg, targetStickingOutOfBuilding); + nDamage = absorbBuildingDamage(nDamage, entityTarget, bldgAbsorbs, vPhaseReport, bldg, + targetStickingOutOfBuilding); nDamage = checkTerrain(nDamage, entityTarget, vPhaseReport); @@ -133,12 +117,9 @@ protected void handleEntityDamage(Entity entityTarget, critModifier += toHit.getMoS() / 3; } hit.makeArmorPiercing(atype, critModifier); - vPhaseReport - .addAll(gameManager.damageEntity(entityTarget, hit, nDamage, - false, ae.getSwarmTargetId() == entityTarget - .getId() ? DamageType.IGNORE_PASSENGER - : damageType, false, false, throughFront, - underWater)); + vPhaseReport.addAll(gameManager.damageEntity(entityTarget, hit, nDamage, false, + ae.getSwarmTargetId() == entityTarget.getId() ? DamageType.IGNORE_PASSENGER : damageType, + false, false, throughFront, underWater)); } } } diff --git a/megamek/src/megamek/common/weapons/AmmoWeaponHandler.java b/megamek/src/megamek/common/weapons/AmmoWeaponHandler.java index d73cf9c3c14..782c7295095 100644 --- a/megamek/src/megamek/common/weapons/AmmoWeaponHandler.java +++ b/megamek/src/megamek/common/weapons/AmmoWeaponHandler.java @@ -26,6 +26,7 @@ import megamek.common.options.OptionsConstants; import megamek.server.GameManager; import megamek.server.Server; +import org.apache.logging.log4j.LogManager; /** * @author Andrew Hunter @@ -40,28 +41,18 @@ protected AmmoWeaponHandler() { // deserialization only } - /** - * @param t - * @param w - * @param g - */ - public AmmoWeaponHandler(ToHitData t, WeaponAttackAction w, Game g, - GameManager m) { + public AmmoWeaponHandler(ToHitData t, WeaponAttackAction w, Game g, GameManager m) { super(t, w, g, m); generalDamageType = HitData.DAMAGE_BALLISTIC; } - /* - * (non-Javadoc) - * - * @see megamek.common.weapons.WeaponHandler#UseAmmo() - */ @Override protected void useAmmo() { checkAmmo(); - if (ammo == null) {// Can't happen. w/o legal ammo, the weapon - // *shouldn't* fire. - System.out.println("Handler can't find any ammo! Oh no!"); + if (ammo == null) { + // Can't happen. w/o legal ammo, the weapon *shouldn't* fire. + LogManager.getLogger().error("Handler can't find any ammo! Oh no!", new Exception()); + return; } if (ammo.getUsableShotsLeft() <= 0) { @@ -84,8 +75,7 @@ protected void checkAmmo() { * For ammo weapons, this number can be less than the full number if the * amount of ammo is not high enough * - * @return the number of weapons of this type firing (for squadron weapon - * groups) + * @return the number of weapons of this type firing (for squadron weapon groups) */ @Override protected int getNumberWeapons() { @@ -161,8 +151,7 @@ protected void explodeRoundInBarrel(Vector vPhaseReport) { int wloc = weapon.getLocation(); for (int i = 0; i < ae.getNumberOfCriticals(wloc); i++) { CriticalSlot slot1 = ae.getCritical(wloc, i); - if ((slot1 == null) || - (slot1.getType() == CriticalSlot.TYPE_SYSTEM)) { + if ((slot1 == null) || (slot1.getType() == CriticalSlot.TYPE_SYSTEM)) { continue; } Mounted mounted = slot1.getMount(); diff --git a/megamek/src/megamek/common/weapons/BayWeaponHandler.java b/megamek/src/megamek/common/weapons/BayWeaponHandler.java index e9905678333..794a316b294 100644 --- a/megamek/src/megamek/common/weapons/BayWeaponHandler.java +++ b/megamek/src/megamek/common/weapons/BayWeaponHandler.java @@ -34,12 +34,6 @@ protected BayWeaponHandler() { // deserialization only } - /** - * @param t - * @param w - * @param g - * @param m - */ public BayWeaponHandler(ToHitData t, WeaponAttackAction w, Game g, GameManager m) { super(t, w, g, m); } @@ -241,8 +235,7 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { // Works out fire setting, AMS shots, and whether continuation is // necessary. - if (!handleSpecialMiss(entityTarget, bldgDamagedOnMiss, bldg, - vPhaseReport)) { + if (!handleSpecialMiss(entityTarget, bldgDamagedOnMiss, bldg, vPhaseReport)) { return false; } } @@ -264,8 +257,7 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { // Targeting a building. if (target.getTargetType() == Targetable.TYPE_BUILDING) { // The building takes the full brunt of the attack - handleBuildingDamage(vPhaseReport, bldg, nDamPerHit, - target.getPosition()); + handleBuildingDamage(vPhaseReport, bldg, nDamPerHit, target.getPosition()); return false; } @@ -319,19 +311,16 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { // absorbed damage shouldn't reduce incoming damage, // since the incoming damage was reduced in // Compute.directBlowInfantryDamage - nDamage = -wtype.getDamage(nRange) - * Math.min(nCluster, hits); + nDamage = -wtype.getDamage(nRange) * Math.min(nCluster, hits); } - bldgAbsorbs = (int) Math.round(nDamage - * bldg.getInfDmgFromInside()); + bldgAbsorbs = (int) Math.round(nDamage * bldg.getInfDmgFromInside()); } else { // Used later to indicate a special report bldgAbsorbs = Integer.MIN_VALUE; } } - handleEntityDamage(entityTarget, vPhaseReport, bldg, hits, - nCluster, bldgAbsorbs); + handleEntityDamage(entityTarget, vPhaseReport, bldg, hits, nCluster, bldgAbsorbs); gameManager.creditKill(entityTarget, ae); } // Handle the next weapon in the bay Report.addNewline(vPhaseReport); @@ -341,7 +330,6 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { /** * Calculate the starting armor value of a flight of Capital Missiles * Used for Aero Sanity. This is done in calcAttackValue() otherwise - * */ protected int initializeCapMissileArmor() { return 0; @@ -469,7 +457,7 @@ public boolean handleAeroSanity(GamePhase phase, Vector vPhaseReport) { vPhaseReport.addElement(r); } - //Don't add heat here, because that will be handled by individual weapons (even if heat by arc) + // Don't add heat here, because that will be handled by individual weapons (even if heat by arc) // Any necessary PSRs, jam checks, etc. // If this boolean is true, don't report @@ -486,8 +474,8 @@ public boolean handleAeroSanity(GamePhase phase, Vector vPhaseReport) { return false; } - //Large missiles - //use this if AMS counterfire destroys all the missiles + // Large missiles + // use this if AMS counterfire destroys all the missiles if (amsBayEngagedCap && (CapMissileArmor <= 0)) { r = new Report(3356); r.indent(); @@ -495,7 +483,7 @@ public boolean handleAeroSanity(GamePhase phase, Vector vPhaseReport) { vPhaseReport.addElement(r); return false; } - //use this if PD counterfire destroys all the Capital missiles + // use this if PD counterfire destroys all the Capital missiles if (pdBayEngagedCap && (CapMissileArmor <= 0)) { r = new Report(3355); r.indent(); @@ -512,10 +500,10 @@ public boolean handleAeroSanity(GamePhase phase, Vector vPhaseReport) { } } - //Report point defense effects - //Set up a cluster hits table modifier + // Report point defense effects + // Set up a cluster hits table modifier double counterAVMod = getCounterAV(); - //Report a failure due to overheating + // Report a failure due to overheating if (pdOverheated && (!(amsBayEngaged || amsBayEngagedCap @@ -528,16 +516,16 @@ public boolean handleAeroSanity(GamePhase phase, Vector vPhaseReport) { r.indent(); vPhaseReport.addElement(r); } else if (pdOverheated) { - //Report a partial failure + // Report a partial failure r = new Report (3361); r.subject = subjectId; r.indent(); vPhaseReport.addElement(r); - //Halve the effectiveness of cluster hits modification + // Halve the effectiveness of cluster hits modification counterAVMod /= 2.0; } - //Now report the effects, if any - //Missiles using the cluster hits table + // Now report the effects, if any + // Missiles using the cluster hits table if (amsBayEngaged || pdBayEngaged) { r = new Report(3366); r.indent(); @@ -573,7 +561,7 @@ public boolean handleAeroSanity(GamePhase phase, Vector vPhaseReport) { } bayWHandler.handle(phase, vPhaseReport); if (vPhaseReport.size() > replaceReport) { - //fix the reporting - is there a better way to do this + // fix the reporting - is there a better way to do this Report currentReport = vPhaseReport.get(replaceReport); while (null != currentReport) { vPhaseReport.remove(replaceReport); diff --git a/megamek/src/megamek/common/weapons/CLIATMHandler.java b/megamek/src/megamek/common/weapons/CLIATMHandler.java index deb0f08e9be..7131bb728b0 100644 --- a/megamek/src/megamek/common/weapons/CLIATMHandler.java +++ b/megamek/src/megamek/common/weapons/CLIATMHandler.java @@ -31,22 +31,11 @@ public class CLIATMHandler extends ATMHandler { private static final long serialVersionUID = 5476183194060709574L; boolean isAngelECMAffected; - /** - * @param t - * @param w - * @param g - * @param m - */ public CLIATMHandler(ToHitData t, WeaponAttackAction w, Game g, GameManager m) { super(t, w, g, m); isAngelECMAffected = ComputeECM.isAffectedByAngelECM(ae, ae.getPosition(), target.getPosition()); } - /* - * (non-Javadoc) - * - * @see megamek.common.weapons.WeaponHandler#calcDamagePerHit() - */ @Override protected int calcDamagePerHit() { double toReturn; @@ -83,24 +72,16 @@ protected int calcDamagePerHit() { return (int) toReturn; } - /* - * (non-Javadoc) - * - * @see megamek.common.weapons.WeaponHandler#calcHits(java.util.Vector) - */ @Override protected int calcHits(Vector vPhaseReport) { - // conventional infantry gets hit in one lump - gets calculated in the - // sub functions + // conventional infantry gets hit in one lump - gets calculated in the sub functions // don't need to check for BAs, because BA can't mount ATMs - int hits; AmmoType atype = (AmmoType) ammo.getType(); // TacOPs p.84 Cluster Hit Penalites will only effect ATM HE // I'm doing my own hit calcs here. Special ammo gets its own method. - // compute ammount of missiles hit - this is the same for all ATM ammo - // types. - hits = calcMissileHits(vPhaseReport); + // compute ammount of missiles hit - this is the same for all ATM ammo types. + int hits = calcMissileHits(vPhaseReport); // If we use IIW or IMP we are done. if ((atype.getMunitionType() == AmmoType.M_IATM_IIW) @@ -125,15 +106,10 @@ protected int calcHits(Vector vPhaseReport) { */ @Override protected int calcAttackValue() { - // TODO: Should handle speical munitions AV + // TODO: Should handle specical munitions AV return super.calcAttackValue(); } - /* - * (non-Javadoc) - * - * @see megamek.common.weapons.WeaponHandler#calcHits(java.util.Vector) - */ protected int calcMissileHits(Vector vPhaseReport) { AmmoType atype = (AmmoType) ammo.getType(); @@ -145,8 +121,7 @@ protected int calcMissileHits(Vector vPhaseReport) { Report r = new Report(3325); r.newlines = 0; r.subject = subjectId; - r.add(wtype.getRackSize() - * ((BattleArmor) ae).getShootingStrength()); + r.add(wtype.getRackSize() * ((BattleArmor) ae).getShootingStrength()); r.add(sSalvoType); r.add(toHit.getTableDesc()); vPhaseReport.add(r); @@ -182,10 +157,9 @@ protected int calcMissileHits(Vector vPhaseReport) { // Only apply if not all shots hit. IATM IMP have HE ranges and thus // suffer from spread too - if (((atype.getMunitionType() == AmmoType.M_HIGH_EXPLOSIVE) || (atype - .getMunitionType() == AmmoType.M_IATM_IMP)) - && tacopscluster - && !allShotsHit()) { + if (((atype.getMunitionType() == AmmoType.M_HIGH_EXPLOSIVE) + || (atype.getMunitionType() == AmmoType.M_IATM_IMP)) + && tacopscluster && !allShotsHit()) { if (nRange <= 1) { nMissilesModifier += 1; } else if (nRange <= ranges[RangeType.RANGE_MEDIUM]) { @@ -198,7 +172,7 @@ protected int calcMissileHits(Vector vPhaseReport) { // ////// // This applies even with streaks. if (game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_RANGE) - && (nRange > wtype.getRanges(weapon)[RangeType.RANGE_LONG])) { + && (nRange > wtype.getRanges(weapon)[RangeType.RANGE_LONG])) { nMissilesModifier -= 2; } if (game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_LOS_RANGE) @@ -309,8 +283,7 @@ protected int calcMissileHits(Vector vPhaseReport) { // I don't think i need to change anything here for iATMs. Seems just to // handle Minefield clearance @Override - protected boolean specialResolution(Vector vPhaseReport, - Entity entityTarget) { + protected boolean specialResolution(Vector vPhaseReport, Entity entityTarget) { if (!bMissed && (target.getTargetType() == Targetable.TYPE_MINEFIELD_CLEAR)) { Report r = new Report(3255); @@ -319,13 +292,11 @@ protected boolean specialResolution(Vector vPhaseReport, vPhaseReport.addElement(r); Coords coords = target.getPosition(); - Enumeration minefields = game.getMinefields(coords) - .elements(); + Enumeration minefields = game.getMinefields(coords).elements(); ArrayList mfRemoved = new ArrayList<>(); while (minefields.hasMoreElements()) { Minefield mf = minefields.nextElement(); - if (gameManager.clearMinefield(mf, ae, - Minefield.CLEAR_NUMBER_WEAPON, vPhaseReport)) { + if (gameManager.clearMinefield(mf, ae, Minefield.CLEAR_NUMBER_WEAPON, vPhaseReport)) { mfRemoved.add(mf); } } @@ -339,11 +310,6 @@ protected boolean specialResolution(Vector vPhaseReport, return false; } - /* - * (non-Javadoc) - * - * @see megamek.common.weapons.WeaponHandler#allShotsHit() - */ @Override protected boolean allShotsHit() { // If we IDF, we don't get the streak bonus @@ -354,11 +320,6 @@ protected boolean allShotsHit() { return super.allShotsHit() || !isAngelECMAffected; } - /* - * (non-Javadoc) - * - * @see megamek.common.weapons.WeaponHandler#addHeat() - */ @Override protected void addHeat() { // call super function if we are in IDF mode since we don't have streak @@ -374,11 +335,6 @@ protected void addHeat() { } } - /* - * (non-Javadoc) - * - * @see megamek.common.weapons.WeaponHandler#UseAmmo() - */ @Override protected void useAmmo() { // call super function if we are in IDF mode, since we don't have streak @@ -405,11 +361,6 @@ protected void useAmmo() { } } - /* - * (non-Javadoc) - * - * @see megamek.common.weapons.WeaponHandler#reportMiss(java.util.Vector) - */ @Override protected void reportMiss(Vector vPhaseReport) { // again, call super if we are in IDF mode. diff --git a/megamek/src/megamek/common/weapons/FireExtinguisherHandler.java b/megamek/src/megamek/common/weapons/FireExtinguisherHandler.java index 8f7b77dac0a..fcce425b09d 100644 --- a/megamek/src/megamek/common/weapons/FireExtinguisherHandler.java +++ b/megamek/src/megamek/common/weapons/FireExtinguisherHandler.java @@ -13,18 +13,11 @@ */ package megamek.common.weapons; -import java.util.Vector; - -import megamek.common.Entity; -import megamek.common.Game; -import megamek.common.Report; -import megamek.common.Tank; -import megamek.common.Targetable; -import megamek.common.Terrains; -import megamek.common.ToHitData; +import megamek.common.*; import megamek.common.actions.WeaponAttackAction; import megamek.server.GameManager; -import megamek.server.Server; + +import java.util.Vector; /** * @author Sebastian Brocks @@ -33,22 +26,10 @@ public class FireExtinguisherHandler extends WeaponHandler { private static final long serialVersionUID = -7047033962986081773L; - /** - * @param toHit - * @param waa - * @param g - */ public FireExtinguisherHandler(ToHitData toHit, WeaponAttackAction waa, Game g, GameManager m) { super(toHit, waa, g, m); } - /* - * (non-Javadoc) - * - * @see - * megamek.common.weapons.WeaponHandler#specialResolution(java.util.Vector, - * megamek.common.Entity, boolean) - */ @Override protected boolean specialResolution(Vector vPhaseReport, Entity entityTarget) { if (!bMissed) { diff --git a/megamek/src/megamek/common/weapons/FlamerHandler.java b/megamek/src/megamek/common/weapons/FlamerHandler.java index 5288a9f9b9d..f7f846179d0 100644 --- a/megamek/src/megamek/common/weapons/FlamerHandler.java +++ b/megamek/src/megamek/common/weapons/FlamerHandler.java @@ -17,7 +17,6 @@ import megamek.common.actions.WeaponAttackAction; import megamek.common.options.OptionsConstants; import megamek.server.GameManager; -import megamek.server.Server; import java.util.Vector; @@ -28,11 +27,6 @@ public class FlamerHandler extends WeaponHandler { private static final long serialVersionUID = -7348456582587703751L; - /** - * @param toHit - * @param waa - * @param g - */ public FlamerHandler(ToHitData toHit, WeaponAttackAction waa, Game g, GameManager m) { super(toHit, waa, g, m); generalDamageType = HitData.DAMAGE_ENERGY; diff --git a/megamek/src/megamek/common/weapons/MissileWeaponHandler.java b/megamek/src/megamek/common/weapons/MissileWeaponHandler.java index 8e0492c4c5c..505cb2031c9 100644 --- a/megamek/src/megamek/common/weapons/MissileWeaponHandler.java +++ b/megamek/src/megamek/common/weapons/MissileWeaponHandler.java @@ -33,14 +33,7 @@ public class MissileWeaponHandler extends AmmoWeaponHandler { boolean advancedPD = false; boolean multiAMS = false; - /** - * @param t - * @param w - * @param g - * @param m - */ - public MissileWeaponHandler(ToHitData t, WeaponAttackAction w, Game g, - GameManager m) { + public MissileWeaponHandler(ToHitData t, WeaponAttackAction w, Game g, GameManager m) { super(t, w, g, m); generalDamageType = HitData.DAMAGE_MISSILE; advancedAMS = g.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_TACOPS_AMS); @@ -117,12 +110,10 @@ protected int calcHits(Vector vPhaseReport) { } else { nMissilesModifier += 2; } - } else if (((mLinker != null) && (mLinker.getType() instanceof MiscType) && !mLinker.isDestroyed() && !mLinker.isMissing() - && !mLinker.isBreached() && mLinker.getType().hasFlag( - MiscType.F_ARTEMIS_PROTO)) + && !mLinker.isBreached() && mLinker.getType().hasFlag(MiscType.F_ARTEMIS_PROTO)) && (atype.getMunitionType() == AmmoType.M_ARTEMIS_CAPABLE)) { if (bECMAffected) { // ECM prevents bonus @@ -142,8 +133,7 @@ protected int calcHits(Vector vPhaseReport) { } else if (((mLinker != null) && (mLinker.getType() instanceof MiscType) && !mLinker.isDestroyed() && !mLinker.isMissing() - && !mLinker.isBreached() && mLinker.getType().hasFlag( - MiscType.F_ARTEMIS_V)) + && !mLinker.isBreached() && mLinker.getType().hasFlag(MiscType.F_ARTEMIS_V)) && (atype.getMunitionType() == AmmoType.M_ARTEMIS_V_CAPABLE)) { if (bECMAffected) { // ECM prevents bonus @@ -163,8 +153,7 @@ protected int calcHits(Vector vPhaseReport) { } else if (((mLinker != null) && (mLinker.getType() instanceof MiscType) && !mLinker.isDestroyed() && !mLinker.isMissing() - && !mLinker.isBreached() && mLinker.getType().hasFlag( - MiscType.F_APOLLO)) + && !mLinker.isBreached() && mLinker.getType().hasFlag(MiscType.F_APOLLO)) && (atype.getAmmoType() == AmmoType.T_MRM)) { nMissilesModifier -= 1; } else if (atype.getAmmoType() == AmmoType.T_ATM) { @@ -184,15 +173,14 @@ protected int calcHits(Vector vPhaseReport) { nMissilesModifier += 2; } } else if ((entityTarget != null) - && (entityTarget.isNarcedBy(ae.getOwner().getTeam()) || entityTarget - .isINarcedBy(ae.getOwner().getTeam()))) { + && (entityTarget.isNarcedBy(ae.getOwner().getTeam()) + || entityTarget.isINarcedBy(ae.getOwner().getTeam()))) { // only apply Narc bonus if we're not suffering ECM effect // and we are using narc ammo, and we're not firing indirectly. // narc capable missiles are only affected if the narc pod, which // sits on the target, is ECM affected boolean bTargetECMAffected = false; - bTargetECMAffected = ComputeECM.isAffectedByECM(ae, - target.getPosition(), target.getPosition()); + bTargetECMAffected = ComputeECM.isAffectedByECM(ae, target.getPosition(), target.getPosition()); if (((atype.getAmmoType() == AmmoType.T_LRM) || (atype.getAmmoType() == AmmoType.T_LRM_IMP) || (atype.getAmmoType() == AmmoType.T_SRM) @@ -224,24 +212,20 @@ protected int calcHits(Vector vPhaseReport) { if (allShotsHit()) { // We want buildings and large craft to be able to affect this number with AMS // treat as a Streak launcher (cluster roll 11) to make this happen - missilesHit = Compute.missilesHit(wtype.getRackSize(), - nMissilesModifier, weapon.isHotLoaded(), true, - isAdvancedAMS()); + missilesHit = Compute.missilesHit(wtype.getRackSize(), nMissilesModifier, + weapon.isHotLoaded(), true, isAdvancedAMS()); } else { if (ae instanceof BattleArmor) { int shootingStrength = 1; if ((weapon.getLocation() == BattleArmor.LOC_SQUAD) - && !(weapon.isSquadSupportWeapon())) { + && !weapon.isSquadSupportWeapon()) { shootingStrength = ((BattleArmor) ae).getShootingStrength(); } - missilesHit = Compute.missilesHit(wtype.getRackSize() - * shootingStrength, - nMissilesModifier, weapon.isHotLoaded(), false, - isAdvancedAMS()); + missilesHit = Compute.missilesHit(wtype.getRackSize() * shootingStrength, + nMissilesModifier, weapon.isHotLoaded(), false, isAdvancedAMS()); } else { - missilesHit = Compute.missilesHit(wtype.getRackSize(), - nMissilesModifier, weapon.isHotLoaded(), false, - isAdvancedAMS()); + missilesHit = Compute.missilesHit(wtype.getRackSize(), nMissilesModifier, + weapon.isHotLoaded(), false, isAdvancedAMS()); } } @@ -314,8 +298,7 @@ protected int calcAttackValue() { int bonus = 0; if (((mLinker != null) && (mLinker.getType() instanceof MiscType) && !mLinker.isDestroyed() && !mLinker.isMissing() - && !mLinker.isBreached() && mLinker.getType().hasFlag( - MiscType.F_ARTEMIS)) + && !mLinker.isBreached() && mLinker.getType().hasFlag(MiscType.F_ARTEMIS)) && (atype.getMunitionType() == AmmoType.M_ARTEMIS_CAPABLE)) { // MML3 gets no bonus from Artemis IV (how sad) if (atype.getRackSize() > 3) { @@ -325,10 +308,10 @@ protected int calcAttackValue() { } } } + if (((mLinker != null) && (mLinker.getType() instanceof MiscType) && !mLinker.isDestroyed() && !mLinker.isMissing() - && !mLinker.isBreached() && mLinker.getType().hasFlag( - MiscType.F_ARTEMIS_PROTO)) + && !mLinker.isBreached() && mLinker.getType().hasFlag(MiscType.F_ARTEMIS_PROTO)) && (atype.getMunitionType() == AmmoType.M_ARTEMIS_CAPABLE)) { // MML3 gets no bonus from Artemis IV (how sad) if (atype.getRackSize() > 3) { @@ -338,10 +321,10 @@ protected int calcAttackValue() { } } } + if (((mLinker != null) && (mLinker.getType() instanceof MiscType) && !mLinker.isDestroyed() && !mLinker.isMissing() - && !mLinker.isBreached() && mLinker.getType().hasFlag( - MiscType.F_ARTEMIS_V)) + && !mLinker.isBreached() && mLinker.getType().hasFlag(MiscType.F_ARTEMIS_V)) && (atype.getMunitionType() == AmmoType.M_ARTEMIS_V_CAPABLE)) { // MML3 WOULD get a bonus from Artemis V, if you were crazy enough // to cross-tech it @@ -426,6 +409,7 @@ protected boolean handleSpecialMiss(Entity entityTarget, boolean bldgDamagedOnMi || (toHit.getValue() == TargetRoll.AUTOMATIC_FAIL)) { return false; } + return true; } @@ -434,7 +418,7 @@ protected boolean handleSpecialMiss(Entity entityTarget, boolean bldgDamagedOnMi protected double getAeroSanityAMSHitsMod() { if (getParentBayHandler() != null) { WeaponHandler bayHandler = getParentBayHandler(); - double counterAVMod = (bayHandler.getCounterAV() / bayHandler.weapon.getBayWeapons().size()); + double counterAVMod = bayHandler.getCounterAV() / bayHandler.weapon.getBayWeapons().size(); // use this if point defenses engage the missiles if (bayHandler.pdOverheated) { // Halve the effectiveness @@ -501,8 +485,7 @@ protected int getAMSHitsMod(Vector vPhaseReport) { if (!(counter.getType() instanceof WeaponType) || !counter.isReady() || counter.isMissing() // no AMS when a shield in the AMS location - || (pdEnt.hasShield() && pdEnt.hasActiveShield( - counter.getLocation(), false)) + || (pdEnt.hasShield() && pdEnt.hasActiveShield(counter.getLocation(), false)) // shutdown means no AMS || pdEnt.isShutDown()) { continue; @@ -585,6 +568,7 @@ protected int getAMSHitsMod(Vector vPhaseReport) { break; default: // 4+ minApdsMod = -4; + break; } } apdsMod = Math.min(minApdsMod + dist, 0); @@ -618,8 +602,7 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { } Entity entityTarget = (target.getTargetType() == Targetable.TYPE_ENTITY) ? (Entity) target : null; - final boolean targetInBuilding = Compute.isInBuilding(game, - entityTarget); + final boolean targetInBuilding = Compute.isInBuilding(game, entityTarget); final boolean bldgDamagedOnMiss = targetInBuilding && !(target instanceof Infantry) && ae.getPosition().distance(target.getPosition()) <= 1; @@ -657,16 +640,16 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { boolean shotAtNemesisTarget = false; if (bNemesisConfusable && !waa.isNemesisConfused()) { // loop through nemesis targets - for (Enumeration e = game.getNemesisTargets(ae, - target.getPosition()); e.hasMoreElements();) { + for (Enumeration e = game.getNemesisTargets(ae, target.getPosition()); + e.hasMoreElements(); ) { Entity entity = e.nextElement(); // friendly unit with attached iNarc Nemesis pod standing in the way r = new Report(3125); r.subject = subjectId; vPhaseReport.addElement(r); weapon.setUsedThisRound(false); - WeaponAttackAction newWaa = new WeaponAttackAction(ae.getId(), - entity.getTargetId(), waa.getWeaponId()); + WeaponAttackAction newWaa = new WeaponAttackAction(ae.getId(), entity.getTargetId(), + waa.getWeaponId()); newWaa.setNemesisConfused(true); Mounted m = ae.getEquipment(waa.getWeaponId()); Weapon w = (Weapon) m.getType(); @@ -812,8 +795,7 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { reportMiss(vPhaseReport); // Works out fire setting, AMS shots, and whether continuation is necessary. - if (!handleSpecialMiss(entityTarget, bldgDamagedOnMiss, bldg, - vPhaseReport)) { + if (!handleSpecialMiss(entityTarget, bldgDamagedOnMiss, bldg, vPhaseReport)) { return false; } } @@ -841,12 +823,13 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { r.indent(); vPhaseReport.addElement(r); } else if (pdOverheated) { - //Report a partial failure + // Report a partial failure r = new Report (3361); r.subject = subjectId; r.indent(); vPhaseReport.addElement(r); } + if (!bMissed && amsEngaged && isTbolt() && !ae.isCapitalFighter()) { // Thunderbolts are destroyed by AMS 50% of the time whether Aero Sanity is on or not hits = calcHits(vPhaseReport); @@ -855,6 +838,7 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { r.subject = subjectId; vPhaseReport.addElement(r); } + // This is for aero attacks as attack value. Does not apply if Aero Sanity is on if (!game.getOptions().booleanOption(OptionsConstants.ADVAERORULES_AERO_SANITY)) { if (!bMissed && amsEngaged && !isTbolt() && !ae.isCapitalFighter()) { @@ -874,7 +858,7 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { r.subject = subjectId; vPhaseReport.addElement(r); } else if (amsBayEngaged) { - //use this if AMS counterfire destroys some of the missiles + // use this if AMS counterfire destroys some of the missiles CounterAV = getCounterAV(); r = new Report(3354); r.indent(); @@ -885,12 +869,12 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { // Report any Point Defense bay action against standard missiles. } else if (pdBayEngaged && (originalAV <= 0)) { - //use this if PD counterfire destroys all the missiles + // use this if PD counterfire destroys all the missiles r = new Report(3355); r.subject = subjectId; vPhaseReport.addElement(r); } else if (pdBayEngaged) { - //use this if PD counterfire destroys some of the missiles + // use this if PD counterfire destroys some of the missiles r = new Report(3353); r.add(CounterAV); r.subject = subjectId; @@ -935,8 +919,7 @@ public boolean handle(GamePhase phase, Vector vPhaseReport) { // Compute.directBlowInfantryDamage nDamage = -wtype.getDamage(nRange) * Math.min(nCluster, hits); } - bldgAbsorbs = (int) Math.round(nDamage - * bldg.getInfDmgFromInside()); + bldgAbsorbs = (int) Math.round(nDamage * bldg.getInfDmgFromInside()); } else { // Used later to indicate a special report bldgAbsorbs = Integer.MIN_VALUE; diff --git a/megamek/src/megamek/common/weapons/Weapon.java b/megamek/src/megamek/common/weapons/Weapon.java index 64699269baa..e76dfe1ecda 100644 --- a/megamek/src/megamek/common/weapons/Weapon.java +++ b/megamek/src/megamek/common/weapons/Weapon.java @@ -13,13 +13,7 @@ */ package megamek.common.weapons; -import java.io.Serializable; - -import megamek.common.AmmoType; -import megamek.common.Game; -import megamek.common.TargetRoll; -import megamek.common.ToHitData; -import megamek.common.WeaponType; +import megamek.common.*; import megamek.common.actions.WeaponAttackAction; import megamek.common.annotations.Nullable; import megamek.common.options.GameOptions; @@ -28,6 +22,8 @@ import megamek.common.weapons.bayweapons.SubCapLaserBayWeapon; import megamek.server.GameManager; +import java.io.Serializable; + /** * A class representing a weapon. * @author Andrew Hunter diff --git a/megamek/src/megamek/common/weapons/WeaponHandler.java b/megamek/src/megamek/common/weapons/WeaponHandler.java index 772cc34fd50..dbf0b6f66d2 100644 --- a/megamek/src/megamek/common/weapons/WeaponHandler.java +++ b/megamek/src/megamek/common/weapons/WeaponHandler.java @@ -40,7 +40,6 @@ * @author Andrew Hunter */ public class WeaponHandler implements AttackHandler, Serializable { - private static final long serialVersionUID = 7137408139594693559L; public ToHitData toHit; protected HitData hit; @@ -91,7 +90,7 @@ public class WeaponHandler implements AttackHandler, Serializable { protected boolean isStrafing = false; /** - * Boolean flag that determiens if this shot was the first one by a + * Boolean flag that determines if this shot was the first one by a * particular weapon in a strafing run. Used to ensure that heat is only * added once. */ @@ -428,21 +427,19 @@ private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); } - private void readObject(ObjectInputStream in) throws IOException, - ClassNotFoundException { + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); gameManager = (GameManager) Server.getServerInstance().getGameManager(); } /** - * @return a boolean value indicating wether or not this attack + * @return a boolean value indicating whether or not this attack * needs further calculating, like a missed shot hitting a building, * or an AMS only shooting down some missiles. */ - protected boolean handleSpecialMiss(Entity entityTarget, - boolean bldgDamagedOnMiss, Building bldg, - Vector vPhaseReport) { + protected boolean handleSpecialMiss(Entity entityTarget, boolean bldgDamagedOnMiss, + Building bldg, Vector vPhaseReport) { // Shots that miss an entity can set fires. // Buildings can't be accidentally ignited, // and some weapons can't ignite fires. @@ -1090,9 +1087,7 @@ public boolean handle(GamePhase phase, Vector returnedReports) { int nDamage; if ((target.getTargetType() == Targetable.TYPE_HEX_TAG) || (target.getTargetType() == Targetable.TYPE_BLDG_TAG)) { - - TagInfo info = new TagInfo(ae.getId(), - target.getTargetType(), target, false); + TagInfo info = new TagInfo(ae.getId(), target.getTargetType(), target, false); game.addTagInfo(info); ae.setSpotting(true); @@ -1116,12 +1111,10 @@ public boolean handle(GamePhase phase, Vector returnedReports) { } else if (target.getTargetType() == Targetable.TYPE_BUILDING) { // The building takes the full brunt of the attack. nDamage = nDamPerHit * hits; - handleBuildingDamage(vPhaseReport, bldg, nDamage, - target.getPosition()); + handleBuildingDamage(vPhaseReport, bldg, nDamage, target.getPosition()); hits = 0; } else if (entityTarget != null) { - handleEntityDamage(entityTarget, vPhaseReport, bldg, - hits, nCluster, bldgAbsorbs); + handleEntityDamage(entityTarget, vPhaseReport, bldg, hits, nCluster, bldgAbsorbs); gameManager.creditKill(entityTarget, ae); hits -= nCluster; firstHit = false; @@ -1133,7 +1126,6 @@ public boolean handle(GamePhase phase, Vector returnedReports) { } } // Handle the next cluster. } else { // We missed, but need to handle special miss cases - // When shooting at a non-infantry unit in a building and the // shot misses, the building is damaged instead, TW pg 171 if (bldgDamagedOnMiss) { @@ -1153,6 +1145,7 @@ public boolean handle(GamePhase phase, Vector returnedReports) { hits = 0; } } + if (game.getOptions().booleanOption(OptionsConstants.ADVCOMBAT_UAC_TWOROLLS) && ((wtype.getAmmoType() == AmmoType.T_AC_ULTRA) || (wtype .getAmmoType() == AmmoType.T_AC_ULTRA_THB)) @@ -1418,18 +1411,16 @@ protected void handlePartialCoverHit(Entity entityTarget, } else if (damageableCoverType == LosEffects.DAMAGABLE_COVER_BUILDING) { // Normal damage int nDamage = nDamPerHit * Math.min(nCluster, hits); - Vector buildingReport = gameManager.damageBuilding( - coverBuilding, nDamage, " blocks the shot and takes ", - coverLoc); + Vector buildingReport = gameManager.damageBuilding(coverBuilding, nDamage, + " blocks the shot and takes ", coverLoc); for (Report report : buildingReport) { report.subject = subjectId; report.indent(); } vPhaseReport.addAll(buildingReport); // Damage any infantry in the building. - Vector infantryReport = gameManager.damageInfantryIn( - coverBuilding, nDamage, coverLoc, - wtype.getInfantryDamageClass()); + Vector infantryReport = gameManager.damageInfantryIn(coverBuilding, nDamage, + coverLoc, wtype.getInfantryDamageClass()); for (Report report : infantryReport) { report.indent(2); } @@ -1545,13 +1536,11 @@ protected void handleEntityDamage(Entity entityTarget, hit.makeGlancingBlow(); } - vPhaseReport - .addAll(gameManager.damageEntity(entityTarget, hit, nDamage, - false, ae.getSwarmTargetId() == entityTarget - .getId() ? DamageType.IGNORE_PASSENGER - : damageType, false, false, throughFront, - underWater, nukeS2S)); - if (damageType.equals(DamageType.ANTI_TSM) && (target instanceof Mech) && entityTarget.antiTSMVulnerable()) { + vPhaseReport.addAll(gameManager.damageEntity(entityTarget, hit, nDamage, false, + ae.getSwarmTargetId() == entityTarget.getId() ? DamageType.IGNORE_PASSENGER : damageType, + false, false, throughFront, underWater, nukeS2S)); + if (damageType.equals(DamageType.ANTI_TSM) && (target instanceof Mech) + && entityTarget.antiTSMVulnerable()) { vPhaseReport.addAll(gameManager.doGreenSmokeDamage(entityTarget)); } // for salvo shots, report that the aimed location was hit after @@ -1594,13 +1583,13 @@ protected boolean unitStickingOutOfBuilding(Hex targetHex, Entity entityTarget) (entityTarget.getElevation() < targetHex.ceiling()) && (entityTarget.relHeight() >= targetHex.ceiling()); } - + /** * Worker function to (maybe) have a building absorb damage meant for the entity */ - protected int absorbBuildingDamage(int nDamage, Entity entityTarget, int bldgAbsorbs, - Vector vPhaseReport, Building bldg, boolean targetStickingOutOfBuilding) { - + protected int absorbBuildingDamage(int nDamage, Entity entityTarget, int bldgAbsorbs, + Vector vPhaseReport, Building bldg, + boolean targetStickingOutOfBuilding) { // if the building will absorb some damage and the target is actually // entirely inside the building: if ((bldgAbsorbs > 0) && !targetStickingOutOfBuilding) { @@ -1635,8 +1624,7 @@ protected int absorbBuildingDamage(int nDamage, Entity entityTarget, int bldgAbs return nDamage; } - protected void handleIgnitionDamage(Vector vPhaseReport, - Building bldg, int hits) { + protected void handleIgnitionDamage(Vector vPhaseReport, Building bldg, int hits) { if (!bSalvo) { // hits! Report r = new Report(2270); @@ -1652,13 +1640,12 @@ protected void handleIgnitionDamage(Vector vPhaseReport, } } - protected void handleClearDamage(Vector vPhaseReport, - Building bldg, int nDamage) { + protected void handleClearDamage(Vector vPhaseReport, Building bldg, int nDamage) { handleClearDamage(vPhaseReport, bldg, nDamage, true); } - protected void handleClearDamage(Vector vPhaseReport, - Building bldg, int nDamage, boolean hitReport) { + protected void handleClearDamage(Vector vPhaseReport, Building bldg, int nDamage, + boolean hitReport) { if (!bSalvo && hitReport) { // hits! Report r = new Report(2270); @@ -1679,14 +1666,11 @@ protected void handleClearDamage(Vector vPhaseReport, // a 5 or less // you do a normal ignition as though for intentional fires if ((bldg != null) - && gameManager.tryIgniteHex(target.getPosition(), subjectId, false, - false, - new TargetRoll(wtype.getFireTN(), wtype.getName()), 5, - vPhaseReport)) { + && gameManager.tryIgniteHex(target.getPosition(), subjectId, false, false, + new TargetRoll(wtype.getFireTN(), wtype.getName()), 5, vPhaseReport)) { return; } - Vector clearReports = gameManager.tryClearHex(target.getPosition(), - nDamage, subjectId); + Vector clearReports = gameManager.tryClearHex(target.getPosition(), nDamage, subjectId); if (!clearReports.isEmpty()) { vPhaseReport.lastElement().newlines = 0; } diff --git a/megamek/src/megamek/common/weapons/autocannons/ACWeapon.java b/megamek/src/megamek/common/weapons/autocannons/ACWeapon.java index 7fd1fa98aaa..82d6538cf8b 100644 --- a/megamek/src/megamek/common/weapons/autocannons/ACWeapon.java +++ b/megamek/src/megamek/common/weapons/autocannons/ACWeapon.java @@ -33,6 +33,7 @@ import megamek.common.weapons.RapidfireACWeaponHandler; import megamek.common.weapons.Weapon; import megamek.server.GameManager; +import megamek.server.Server; /** * N.B. This class is overridden for AC/2, AC/5, AC/10, AC/10, NOT ultras/LB/RAC. @@ -106,13 +107,12 @@ public int getDamage() { if ((dmg != 5) && (dmg != 2)) { return dmg; } - GameOptions options = getGameOptions(); - if (options == null) { - return dmg; - } - if (options.getOption(OptionsConstants.ADVCOMBAT_INCREASED_AC_DMG).booleanValue()) { + + if (Server.getServerInstance().getGame().getOptions() + .getOption(OptionsConstants.ADVCOMBAT_INCREASED_AC_DMG).booleanValue()) { dmg++; } + return dmg; } diff --git a/megamek/src/megamek/common/weapons/lasers/ISERLaserLarge.java b/megamek/src/megamek/common/weapons/lasers/ISERLaserLarge.java index 633065fdc40..bfa81cb777b 100644 --- a/megamek/src/megamek/common/weapons/lasers/ISERLaserLarge.java +++ b/megamek/src/megamek/common/weapons/lasers/ISERLaserLarge.java @@ -15,6 +15,7 @@ import megamek.common.options.GameOptions; import megamek.common.options.OptionsConstants; +import megamek.server.Server; /** * @author Andrew Hunter @@ -62,15 +63,13 @@ public ISERLaserLarge() { @Override public int getLongRange() { - GameOptions options = getGameOptions(); - if (options == null) { + GameOptions options = Server.getServerInstance().getGame().getOptions(); + if (options.getOption(OptionsConstants.ADVCOMBAT_INCREASED_ISERLL_RANGE) == null) { return super.getLongRange(); - } else if (options.getOption(OptionsConstants.ADVCOMBAT_INCREASED_ISERLL_RANGE) == null) { - return super.getLongRange(); - } - if (options.getOption(OptionsConstants.ADVCOMBAT_INCREASED_ISERLL_RANGE).booleanValue()) { + } else if (options.getOption(OptionsConstants.ADVCOMBAT_INCREASED_ISERLL_RANGE).booleanValue()) { return 21; + } else { + return super.getLongRange(); } - return super.getLongRange(); } } diff --git a/megamek/src/megamek/common/weapons/prototypes/ISERLaserLargePrototype.java b/megamek/src/megamek/common/weapons/prototypes/ISERLaserLargePrototype.java index b53093f3d6b..c7b09367d43 100644 --- a/megamek/src/megamek/common/weapons/prototypes/ISERLaserLargePrototype.java +++ b/megamek/src/megamek/common/weapons/prototypes/ISERLaserLargePrototype.java @@ -23,6 +23,7 @@ import megamek.common.weapons.PrototypeLaserHandler; import megamek.common.weapons.lasers.LaserWeapon; import megamek.server.GameManager; +import megamek.server.Server; /** * @author Andrew Hunter @@ -86,16 +87,14 @@ protected AttackHandler getCorrectHandler(ToHitData toHit, WeaponAttackAction wa @Override public int getLongRange() { - GameOptions options = getGameOptions(); - if (options == null) { + GameOptions options = Server.getServerInstance().getGame().getOptions(); + if (options.getOption(OptionsConstants.ADVCOMBAT_INCREASED_ISERLL_RANGE) == null) { return super.getLongRange(); - } else if (options.getOption(OptionsConstants.ADVCOMBAT_INCREASED_ISERLL_RANGE) == null) { - return super.getLongRange(); - } - if (options.getOption(OptionsConstants.ADVCOMBAT_INCREASED_ISERLL_RANGE).booleanValue()) { + } else if (options.getOption(OptionsConstants.ADVCOMBAT_INCREASED_ISERLL_RANGE).booleanValue()) { return 21; + } else { + return super.getLongRange(); } - return super.getLongRange(); } @Override diff --git a/megamek/src/megamek/server/Server.java b/megamek/src/megamek/server/Server.java index 129fcf864f3..b4a64d2a210 100644 --- a/megamek/src/megamek/server/Server.java +++ b/megamek/src/megamek/server/Server.java @@ -20,6 +20,7 @@ import megamek.MegaMek; import megamek.Version; import megamek.client.ui.swing.util.PlayerColour; +import megamek.codeUtilities.StringUtility; import megamek.common.*; import megamek.common.annotations.Nullable; import megamek.common.commandline.AbstractCommandLineParser.ParseException; @@ -271,7 +272,7 @@ public static String validatePlayerName(String playerName) throws ParseException * @return valid password or null if no password or password is blank string */ public static @Nullable String validatePassword(@Nullable String password) { - return ((password == null) || password.isBlank()) ? null : password.trim(); + return StringUtility.isNullOrBlank(password) ? null : password.trim(); } /** @@ -281,7 +282,7 @@ public static String validatePlayerName(String playerName) throws ParseException * @return true if the user-supplied data matches the server password or no password is set. */ public boolean passwordMatches(Object password) { - return (this.password == null) || this.password.isBlank() || this.password.equals(password); + return StringUtility.isNullOrBlank(this.password) || this.password.equals(password); } /** @@ -300,21 +301,15 @@ public static int validatePort(int port) throws ParseException { } } - public Server(String password, int port, IGameManager gameManager) throws IOException { + public Server(@Nullable String password, int port, IGameManager gameManager) throws IOException { this(password, port, gameManager, false, "", null, false); } - public Server(String password, int port, IGameManager gameManager, - boolean registerWithServerBrowser, String metaServerUrl) throws IOException { + public Server(@Nullable String password, int port, IGameManager gameManager, + boolean registerWithServerBrowser, @Nullable String metaServerUrl) throws IOException { this(password, port, gameManager, registerWithServerBrowser, metaServerUrl, null, false); } - public Server(String password, int port, IGameManager gameManager, - boolean registerWithServerBrowser, String metaServerUrl, EmailService mailer) - throws IOException { - this(password, port, gameManager, registerWithServerBrowser, metaServerUrl, mailer, false); - } - /** * Construct a new GameHost and begin listening for incoming clients. * @@ -330,10 +325,9 @@ public Server(String password, int port, IGameManager gameManager, public Server(@Nullable String password, int port, IGameManager gameManager, boolean registerWithServerBrowser, @Nullable String metaServerUrl, @Nullable EmailService mailer, boolean dedicated) throws IOException { - this.metaServerUrl = (metaServerUrl != null) && (!metaServerUrl.isBlank()) ? metaServerUrl : null; - this.password = (password != null) && (!password.isBlank()) ? password : null; + this.metaServerUrl = StringUtility.isNullOrBlank(metaServerUrl) ? null : metaServerUrl; + this.password = StringUtility.isNullOrBlank(password) ? null : password; this.gameManager = gameManager; - this.mailer = mailer; this.dedicated = dedicated; @@ -376,7 +370,7 @@ public Server(@Nullable String password, int port, IGameManager gameManager, packetPumpThread.start(); if (registerWithServerBrowser) { - if ((metaServerUrl != null) && (!metaServerUrl.isBlank())) { + if (!StringUtility.isNullOrBlank(metaServerUrl)) { final TimerTask register = new TimerTask() { @Override public void run() { @@ -410,7 +404,7 @@ public void setGame(IGame g) { gameManager.setGame(g); } - public IGame getGame() { + public @Nullable IGame getGame() { return gameManager.getGame(); }