diff --git a/megamek/src/megamek/common/BattleArmorHandles.java b/megamek/src/megamek/common/BattleArmorHandles.java index 7b71d52a34d..f16dde45d36 100644 --- a/megamek/src/megamek/common/BattleArmorHandles.java +++ b/megamek/src/megamek/common/BattleArmorHandles.java @@ -122,11 +122,6 @@ public final List getExternalUnits() { return getLoadedUnits(); } - @Override - public int getCargoMpReduction(Entity carrier) { - return 0; - } - @Override public String toString() { return "BattleArmorHandles - troopers:" + carriedUnit; diff --git a/megamek/src/megamek/common/Bay.java b/megamek/src/megamek/common/Bay.java index ee57d564eba..97246e797d8 100644 --- a/megamek/src/megamek/common/Bay.java +++ b/megamek/src/megamek/common/Bay.java @@ -290,11 +290,6 @@ public String getDefaultSlotDescription() { return ""; } - @Override - public boolean isWeaponBlockedAt(int loc, boolean isRear) { - return false; - } - @Override public Entity getExteriorUnitAt(int loc, boolean isRear) { return null; @@ -305,11 +300,6 @@ public final List getExternalUnits() { return new ArrayList<>(1); } - @Override - public int getCargoMpReduction(Entity carrier) { - return 0; - } - public String getType() { return "Unknown"; } diff --git a/megamek/src/megamek/common/DockingCollar.java b/megamek/src/megamek/common/DockingCollar.java index 82951ed8257..4c08dece2ca 100644 --- a/megamek/src/megamek/common/DockingCollar.java +++ b/megamek/src/megamek/common/DockingCollar.java @@ -133,11 +133,6 @@ public double getUnused() { return dockedUnits.isEmpty() ? 1 : 0; } - @Override - public boolean isWeaponBlockedAt(int loc, boolean isRear) { - return false; - } - @Override public @Nullable Entity getExteriorUnitAt(int loc, boolean isRear) { return null; @@ -148,11 +143,6 @@ public final List getExternalUnits() { return new ArrayList<>(); } - @Override - public int getCargoMpReduction(Entity carrier) { - return 0; - } - public boolean isDamaged() { return damaged; } diff --git a/megamek/src/megamek/common/InfantryCompartment.java b/megamek/src/megamek/common/InfantryCompartment.java index 6d90120ca8d..9e163178551 100644 --- a/megamek/src/megamek/common/InfantryCompartment.java +++ b/megamek/src/megamek/common/InfantryCompartment.java @@ -1,177 +1,89 @@ /* * Copyright (c) 2003-2004 Ben Mazur (bmazur@sev.org) + * Copyright (c) 2024 - The MegaMek Team. All Rights Reserved. * - * 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 file is part of MegaMek. * - * 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. + * MegaMek 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 3 of the License, or + * (at your option) any later version. + * + * MegaMek 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. + * + * You should have received a copy of the GNU General Public License + * along with MegaMek. If not, see . */ package megamek.common; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Vector; +import megamek.logging.MMLogger; + +import java.io.Serial; +import java.util.*; /** - * Represents a volume of space set aside for carrying troops and their equipment under battle - * conditions. Typically, a component of an APC. + * Represents a volume of space set aside for carrying Conventional Infantry and BattleArmor and their equipment under battle conditions. + * TM p.239; see e.g. JI2A1 Attack APC */ public final class InfantryCompartment implements Transporter { + @Serial private static final long serialVersionUID = 7837499891552862932L; + private static final MMLogger LOGGER = MMLogger.create(InfantryCompartment.class); - /** - * The troops being carried. - */ - Map troops = new HashMap<>(); - - /** - * The total amount of space available for troops. - */ - double totalSpace; + /** The carried troops, mapping unit ID to carried weight of the unit. */ + private final Map carriedTroops = new HashMap<>(); + final double totalSpace; + private double currentSpace; - /** - * The current amount of space available for troops. - */ - double currentSpace; - - transient Game game; - - /** - * The default constructor is only for serialization. - */ - private InfantryCompartment() { - totalSpace = 0; - currentSpace = 0; - } + private transient Game game; /** - * Create a space for the given tonnage of troops. For this class, only the - * weight of the troops (and their equipment) are considered; if you'd like - * to think that they are stacked like lumber, be my guest. + * Creates an InfantryCompartment for the given tonnage of troops. * - * @param space The weight of troops (in tons) this space can carry. + * @param tonnage The weight of troops (in tons) this space can carry */ - public InfantryCompartment(double space) { - totalSpace = space; - currentSpace = space; + public InfantryCompartment(double tonnage) { + totalSpace = tonnage; + currentSpace = tonnage; } - /** - * Determines if this object can accept the given unit. The unit may not be - * of the appropriate type or there may be no room for the unit. - * - * @param unit the Entity to be loaded. - * @return true if the unit can be loaded, false otherwise. - */ @Override public boolean canLoad(Entity unit) { - // Assume that we can carry the unit. - boolean result = true; - - // Only Infantry and BattleArmor can be carried in TroopSpace. - if (!(unit instanceof Infantry)) { - result = false; - } - - // We must have enough space for the new troops. - // POSSIBLE BUG: we may have to take the Math.ceil() of the weight. - else if (currentSpace < unit.getWeight()) { - result = false; - } - - // Return our result. - return result; + return unit.isInfantry() && (currentSpace >= unit.getWeight()); } - /** - * Load the given unit. - * - * @param unit the Entity to be loaded. - * @throws IllegalArgumentException If the unit can't be loaded - */ @Override public void load(Entity unit) throws IllegalArgumentException { - // If we can't load the unit, throw an exception. if (!canLoad(unit)) { - throw new IllegalArgumentException("Can not load " + unit.getShortName() + " into this troop space."); + throw new IllegalArgumentException("Can not load " + unit + " into this troop space."); } - // Decrement the available space. - // POSSIBLE BUG: we may have to take the Math.ceil() of the weight. currentSpace -= unit.getWeight(); - - // Add the unit to our list of troops. - troops.put(unit.getId(), unit.getWeight()); - + carriedTroops.put(unit.getId(), unit.getWeight()); } - /** - * Get a List of the units currently loaded into this payload. - * - * @return A List of loaded Entity units. This list will never be - * null, but it may be empty. The returned List is independent from - * the underlying data structure; modifying one does not affect the other. - */ @Override - public Vector getLoadedUnits() { - Vector loaded = new Vector<>(); - for (Map.Entry entry : troops.entrySet()) { - int key = entry.getKey(); - Entity entity = game.getEntity(key); - - if (entity != null) { - loaded.add(entity); - } - } - - return loaded; + public List getLoadedUnits() { + return carriedTroops.keySet().stream().map(game::getEntity).toList(); } - /** - * Unload the given unit. - * - * @param unit - * - the Entity to be unloaded. - * @return true if the unit was contained in this space, - * false otherwise. - */ @Override public boolean unload(Entity unit) { - // If this unit isn't loaded, nothing to do - if (!troops.containsKey(unit.getId())) { + if (unit == null) { + LOGGER.error("Trying to unload a null unit!"); + return false; + } else if (carriedTroops.containsKey(unit.getId())) { + currentSpace += carriedTroops.get(unit.getId()); + carriedTroops.remove(unit.getId()); + return true; + } else { return false; } - - // Remove the unit if we are carrying it. - boolean retval = false; - double unloadWeight = 0; - - if (unit != null) { - unloadWeight = troops.get(unit.getId()); - } - - // If we removed it, restore our space. - if (troops.remove(unit.getId()) != null) { - retval = true; - currentSpace += unloadWeight; - } - - // Return our status - return retval; } - /** - * Return a string that identifies the unused capacity of this transporter. - * - * @return A String meant for a human. - */ @Override public String getUnusedString() { return "Infantry Compartment - " + currentSpace + " tons"; @@ -182,40 +94,6 @@ public double getUnused() { return currentSpace; } - /** - * Determine if transported units prevent a weapon in the given location - * from firing. - * - * @param loc - * - the int location attempting to fire. - * @param isRear - * - a boolean value stating if the given location - * is rear facing; if false, the location is front - * facing. - * @return true if a transported unit is in the way, - * false if the weapon can fire. - */ - @Override - public boolean isWeaponBlockedAt(int loc, boolean isRear) { - return false; - } - - /** - * If a unit is being transported on the outside of the transporter, it can - * suffer damage when the transporter is hit by an attack. Currently, no - * more than one unit can be at any single location; that same unit can be - * "spread" over multiple locations. - * - * @param loc - * - the int location hit by attack. - * @param isRear - * - a boolean value stating if the given location - * is rear facing; if false, the location is front - * facing. - * @return The Entity being transported on the outside at that - * location. This value will be null if no unit is - * transported on the outside at that location. - */ @Override public Entity getExteriorUnitAt(int loc, boolean isRear) { return null; @@ -223,16 +101,12 @@ public Entity getExteriorUnitAt(int loc, boolean isRear) { @Override public List getExternalUnits() { - return new ArrayList<>(1); - } - - @Override - public int getCargoMpReduction(Entity carrier) { - return 0; + return Collections.emptyList(); } @Override public String toString() { + // Beware - this is used for saving to blk files - which is a bad idea return "troopspace:" + totalSpace; } @@ -243,7 +117,7 @@ public void setGame(Game game) { @Override public void resetTransporter() { - troops = new HashMap<>(); + carriedTroops.clear(); currentSpace = totalSpace; } } diff --git a/megamek/src/megamek/common/TankTrailerHitch.java b/megamek/src/megamek/common/TankTrailerHitch.java index c50331bac7e..57408f199ac 100644 --- a/megamek/src/megamek/common/TankTrailerHitch.java +++ b/megamek/src/megamek/common/TankTrailerHitch.java @@ -197,25 +197,6 @@ public void resetTransporter() { towed = Entity.NONE; } - /** - * Determine if transported units prevent a weapon in the given location - * from firing. - * - * @param loc - * - the int location attempting to fire. - * @param isRear - * - a boolean value stating if the given location - * is rear facing; if false, the location is front - * facing. - * @return true if a transported unit is in the way, - * false if the weapon can fire. - */ - @Override - public boolean isWeaponBlockedAt(int loc, boolean isRear) { - // Assume that the weapon is not blocked. See Entity.isWeaponBlockedByTowing() instead. - return false; - } - /** * If a unit is being transported on the outside of the transporter, it can * suffer damage when the transporter is hit by an attack. Currently, no @@ -247,11 +228,6 @@ public final List getExternalUnits() { return Collections.unmodifiableList(rv); } - @Override - public int getCargoMpReduction(Entity carrier) { - return 0; - } - @Override public String toString() { return "Trailer Hitch:" + getUnused(); diff --git a/megamek/src/megamek/common/Transporter.java b/megamek/src/megamek/common/Transporter.java index 3ea43277396..149759bd821 100644 --- a/megamek/src/megamek/common/Transporter.java +++ b/megamek/src/megamek/common/Transporter.java @@ -36,11 +36,13 @@ public interface Transporter extends Serializable { * otherwise. */ boolean canLoad(Entity unit); - + /** * Determines if this transporter can tow the given unit. By default, no. */ - default boolean canTow(Entity unit) { return false; } + default boolean canTow(Entity unit) { + return false; + } /** * Load the given unit. @@ -90,7 +92,9 @@ public interface Transporter extends Serializable { * @param isRear true if the weapon is rear-facing * @return True if a transported unit is in the way, false if the weapon can fire. */ - boolean isWeaponBlockedAt(int loc, boolean isRear); + default boolean isWeaponBlockedAt(int loc, boolean isRear) { + return false; + } /** * If a unit is being transported on the outside of the transporter, it can @@ -116,15 +120,17 @@ public interface Transporter extends Serializable { /** * @return the MP reduction due to cargo carried by this transporter */ - int getCargoMpReduction(Entity carrier); + default int getCargoMpReduction(Entity carrier) { + return 0; + } void setGame(Game game); - + /** * clear out all troops listed in the transporter. Used by MHQ to reset units after game */ void resetTransporter(); - + /** * Returns the number of Docking Collars (hardpoints) this transporter counts as toward * the maximum that a JumpShip (or WS, SS) may carry. TO:AUE p.146