From 1d77d382b63c022d18c1b496da36d8b4f2af7d53 Mon Sep 17 00:00:00 2001 From: psikomonkie <189469115+psikomonkie@users.noreply.github.com> Date: Thu, 15 May 2025 17:52:54 -0400 Subject: [PATCH] Issue #7012: Properly update capacities when changing Transporters via refit --- MekHQ/src/mekhq/campaign/Campaign.java | 14 ++++++++ .../campaign/CampaignTransporterMap.java | 36 +++++++++++++------ MekHQ/src/mekhq/campaign/parts/Refit.java | 7 ++-- .../unit/AbstractTransportedUnitsSummary.java | 10 +++++- MekHQ/src/mekhq/campaign/unit/Unit.java | 15 +++++++- .../unit/actions/RestoreUnitAction.java | 1 + .../menus/AssignForceToShipTransportMenu.java | 12 +------ .../AssignForceToTacticalTransportMenu.java | 12 +------ .../gui/menus/AssignForceToTransportMenu.java | 23 ++++++++++++ 9 files changed, 94 insertions(+), 36 deletions(-) diff --git a/MekHQ/src/mekhq/campaign/Campaign.java b/MekHQ/src/mekhq/campaign/Campaign.java index 354ca3868d4..61505b8be9c 100644 --- a/MekHQ/src/mekhq/campaign/Campaign.java +++ b/MekHQ/src/mekhq/campaign/Campaign.java @@ -1654,6 +1654,20 @@ public void addCampaignTransport(CampaignTransportType campaignTransportType, Un } } + /** + * This will update the transport in the transports list with current capacities. When a unit is added or removed + * from a transport, that information needs updated in the campaign transport map. This method will update the + * map for every {@code CampaignTransportType} for the given transport. + * + * @see Campaign#updateTransportInTransports(CampaignTransportType, Unit) + * @param transport Unit + */ + public void updateTransportInTransports(Unit transport) { + for (CampaignTransportType campaignTransportType : CampaignTransportType.values()) { + updateTransportInTransports (campaignTransportType, transport); + } + } + /** * This will update the transport in the transports list with current capacities. When a unit is added or removed * from a transport, that information needs updated in the campaign transport map. This method takes the diff --git a/MekHQ/src/mekhq/campaign/CampaignTransporterMap.java b/MekHQ/src/mekhq/campaign/CampaignTransporterMap.java index 4ec472b6312..3b70d7e249b 100644 --- a/MekHQ/src/mekhq/campaign/CampaignTransporterMap.java +++ b/MekHQ/src/mekhq/campaign/CampaignTransporterMap.java @@ -87,11 +87,18 @@ public void updateTransportInTransporterMap(Unit transport) { return; } AbstractTransportedUnitsSummary transportedUnitsSummary = transport.getTransportedUnitsSummary(campaignTransportType); - for (TransporterType transporterType : transportedUnitsSummary.getTransportCapabilities()) { + + // Let's make a list of all the transportTypes in the map, and all the transportTypes the unit has + Set transporterTypes = new HashSet<>(); + transporterTypes.addAll(transportedUnitsSummary.getTransportCapabilities()); + transporterTypes.addAll(transportersMap.keySet()); + + // Now let's update the current transporterTypes + for (TransporterType transporterType : transporterTypes) { if (transportersMap.containsKey(transporterType)) { Set oldCapacities = transportersMap.get(transporterType).keySet(); Double newCapacity = transportedUnitsSummary.getCurrentTransportCapacity(transporterType); - //First, if this is a new capacity for the map, let's manually add it + // First, if this is a new capacity for the map, let's manually add it if (!oldCapacities.contains(newCapacity)) { addTransporterToCapacityMap(transport, transporterType); } @@ -105,9 +112,14 @@ public void updateTransportInTransporterMap(Unit transport) { addTransporterToCapacityMap(transport, transporterType); } } + + // Finally, let's remove this from the map & get out if the transport doesn't have this transporterType + if (!transportedUnitsSummary.getTransportCapabilities().contains(transporterType)) { + removeTransportFromCapacityMap(transport, transporterType, 0); + } } else { - logger.error(String.format("Invalid transporter type %s", transporterType)); + addTransporterToCapacityMap (transport, transporterType); } } } @@ -183,14 +195,18 @@ public void removeTransport(Unit transport) { for (TransporterType transporterTypeToRemove : toRemoveMap.keySet()) { double capacity = toRemoveMap.get(transporterTypeToRemove); + removeTransportFromCapacityMap(transport, transporterTypeToRemove, capacity); + } + } - transportersMap.get(transporterTypeToRemove).get(capacity).remove(transport.getId()); - if (transportersMap.get(transporterTypeToRemove).get(capacity).isEmpty()) { - transportersMap.get(transporterTypeToRemove).remove(capacity); - } - if (transportersMap.get(transporterTypeToRemove).isEmpty()) { - transportersMap.remove(transporterTypeToRemove); - } + private void removeTransportFromCapacityMap(Unit transport, TransporterType transporterTypeToRemove, double capacity) { + + transportersMap.get(transporterTypeToRemove).get(capacity).remove(transport.getId()); + if (transportersMap.get(transporterTypeToRemove).get(capacity).isEmpty()) { + transportersMap.get(transporterTypeToRemove).remove(capacity); + } + if (transportersMap.get(transporterTypeToRemove).isEmpty()) { + transportersMap.remove(transporterTypeToRemove); } } } diff --git a/MekHQ/src/mekhq/campaign/parts/Refit.java b/MekHQ/src/mekhq/campaign/parts/Refit.java index e17b5755ff8..6582b995647 100644 --- a/MekHQ/src/mekhq/campaign/parts/Refit.java +++ b/MekHQ/src/mekhq/campaign/parts/Refit.java @@ -1554,8 +1554,6 @@ private void complete() { // don't forget to switch entities! // ----------------- from here on oldUnit refers to the new entity ------------------------- oldUnit.setEntity(newEntity); - // Bay capacities might have changed - reset them - oldUnit.initializeAllTransportSpace(); // set up new parts ArrayList newParts = new ArrayList<>(); @@ -1697,6 +1695,11 @@ private void complete() { getCampaign().reloadGameEntities(); C3Util.copyC3Networks(oldEntity, oldUnit.getEntity()); + // Bay capacities might have changed - reset them + oldUnit.clearAllTransportSpace(); + oldUnit.initializeAllTransportSpace(); + campaign.updateTransportInTransports(oldUnit); + // reload any soldiers for (Person soldier : soldiers) { if (!oldUnit.canTakeMoreGunners()) { diff --git a/MekHQ/src/mekhq/campaign/unit/AbstractTransportedUnitsSummary.java b/MekHQ/src/mekhq/campaign/unit/AbstractTransportedUnitsSummary.java index 22bd5d1424d..ecfce2a5b85 100644 --- a/MekHQ/src/mekhq/campaign/unit/AbstractTransportedUnitsSummary.java +++ b/MekHQ/src/mekhq/campaign/unit/AbstractTransportedUnitsSummary.java @@ -161,7 +161,7 @@ public boolean hasTransportCapacity(TransporterType transporterType) { * @return The current capacity of the transporter, or 0 */ @Override - public double getCurrentTransportCapacity(TransporterType transporterType) { + public double getCurrentTransportCapacity(@Nullable TransporterType transporterType) { return transportCapacity.getOrDefault(transporterType, 0.0); } @@ -228,6 +228,14 @@ public void clearTransportedUnits() { clearTransportedEntities(); } + /** + * Completely clears the capacity map. Helpful if the transportCapacity has a TransporterType for a Transporter + * the unit no longer has - such as after a refit. + */ + public void clearTransportCapacityMap() { + transportCapacity = new HashMap<>(); + } + protected Set clearTransportedEntities() { Set transportedEntities = new HashSet<>(); if (transport.getEntity() != null) { diff --git a/MekHQ/src/mekhq/campaign/unit/Unit.java b/MekHQ/src/mekhq/campaign/unit/Unit.java index 3b0963a454a..d8e326e9160 100644 --- a/MekHQ/src/mekhq/campaign/unit/Unit.java +++ b/MekHQ/src/mekhq/campaign/unit/Unit.java @@ -384,6 +384,19 @@ public void initializeAllTransportSpace() { } } + public void clearAllTransportSpace() { + for (CampaignTransportType campaignTransportType : CampaignTransportType.values()) { + clearTransportSpace(campaignTransportType); + } + } + + private void clearTransportSpace(CampaignTransportType campaignTransportType) { + AbstractTransportedUnitsSummary summary = getTransportedUnitsSummary(campaignTransportType); + if (summary != null) { + summary.clearTransportCapacityMap(); + } + } + private ShipTransportedUnitsSummary getShipTransportedUnitsSummary() { return (ShipTransportedUnitsSummary) getTransportedUnitsSummary(SHIP_TRANSPORT); } @@ -445,7 +458,7 @@ private boolean hasTransportedUnitsType(CampaignTransportType campaignTransportT * * @return transported units summary of that type, or null */ - public AbstractTransportedUnitsSummary getTransportedUnitsSummary(CampaignTransportType campaignTransportType) { + public @Nullable AbstractTransportedUnitsSummary getTransportedUnitsSummary(CampaignTransportType campaignTransportType) { for (AbstractTransportedUnitsSummary transportedUnitSummary : transportedUnitsSummaries) { if (transportedUnitSummary.getClass() == campaignTransportType.getTransportedUnitsSummaryType()) { return transportedUnitSummary; diff --git a/MekHQ/src/mekhq/campaign/unit/actions/RestoreUnitAction.java b/MekHQ/src/mekhq/campaign/unit/actions/RestoreUnitAction.java index 3c72f23a114..9a6e259dea2 100644 --- a/MekHQ/src/mekhq/campaign/unit/actions/RestoreUnitAction.java +++ b/MekHQ/src/mekhq/campaign/unit/actions/RestoreUnitAction.java @@ -121,6 +121,7 @@ private void restoreUnit(Campaign campaign, Unit unit, Entity newEntity) { unit.removeParts(); unit.initializeAllTransportSpace(); + campaign.updateTransportInTransports(unit); unit.initializeParts(true); unit.runDiagnostic(false); diff --git a/MekHQ/src/mekhq/gui/menus/AssignForceToShipTransportMenu.java b/MekHQ/src/mekhq/gui/menus/AssignForceToShipTransportMenu.java index 048f31341ef..6af5da94091 100644 --- a/MekHQ/src/mekhq/gui/menus/AssignForceToShipTransportMenu.java +++ b/MekHQ/src/mekhq/gui/menus/AssignForceToShipTransportMenu.java @@ -31,10 +31,8 @@ import mekhq.campaign.unit.enums.TransporterType; import mekhq.campaign.utilities.CampaignTransportUtilities; import mekhq.utilities.MHQInternationalization; -import mekhq.MekHQ; import mekhq.campaign.Campaign; import mekhq.campaign.enums.CampaignTransportType; -import mekhq.campaign.event.UnitChangedEvent; import mekhq.campaign.unit.Unit; import javax.swing.*; @@ -106,15 +104,7 @@ protected void transportMenuAction(ActionEvent evt, TransporterType transporterT } Set oldTransports = transport.loadShipTransport(transporterType, units); - if (!oldTransports.isEmpty()) { - oldTransports.forEach(oldTransport -> campaign.updateTransportInTransports(campaignTransportType, oldTransport)); - oldTransports.forEach(oldTransport -> MekHQ.triggerEvent(new UnitChangedEvent(transport))); - } - for (Unit unit : units) { - MekHQ.triggerEvent(new UnitChangedEvent(unit)); - } - campaign.updateTransportInTransports(campaignTransportType, transport); - MekHQ.triggerEvent(new UnitChangedEvent(transport)); + updateTransportsForTransportMenuAction(SHIP_TRANSPORT, transport, units, oldTransports); } } diff --git a/MekHQ/src/mekhq/gui/menus/AssignForceToTacticalTransportMenu.java b/MekHQ/src/mekhq/gui/menus/AssignForceToTacticalTransportMenu.java index fc699e6c2be..146b52cd788 100644 --- a/MekHQ/src/mekhq/gui/menus/AssignForceToTacticalTransportMenu.java +++ b/MekHQ/src/mekhq/gui/menus/AssignForceToTacticalTransportMenu.java @@ -31,10 +31,8 @@ import mekhq.campaign.unit.enums.TransporterType; import mekhq.campaign.utilities.CampaignTransportUtilities; import mekhq.utilities.MHQInternationalization; -import mekhq.MekHQ; import mekhq.campaign.Campaign; import mekhq.campaign.enums.CampaignTransportType; -import mekhq.campaign.event.UnitChangedEvent; import mekhq.campaign.unit.Unit; import javax.swing.*; @@ -106,14 +104,6 @@ protected void transportMenuAction(ActionEvent evt, TransporterType transporterT } Set oldTransports = transport.loadTacticalTransport(transporterType, units); - if (!oldTransports.isEmpty()) { - oldTransports.forEach(oldTransport -> campaign.updateTransportInTransports(TACTICAL_TRANSPORT, oldTransport)); - oldTransports.forEach(oldTransport -> MekHQ.triggerEvent(new UnitChangedEvent(transport))); - } - for (Unit unit : units) { - MekHQ.triggerEvent(new UnitChangedEvent(unit)); - } - campaign.updateTransportInTransports(TACTICAL_TRANSPORT, transport); - MekHQ.triggerEvent(new UnitChangedEvent(transport)); + updateTransportsForTransportMenuAction(TACTICAL_TRANSPORT, transport, units, oldTransports); } } diff --git a/MekHQ/src/mekhq/gui/menus/AssignForceToTransportMenu.java b/MekHQ/src/mekhq/gui/menus/AssignForceToTransportMenu.java index abfb9a10e9e..34cf770c6d4 100644 --- a/MekHQ/src/mekhq/gui/menus/AssignForceToTransportMenu.java +++ b/MekHQ/src/mekhq/gui/menus/AssignForceToTransportMenu.java @@ -28,8 +28,10 @@ package mekhq.gui.menus; +import mekhq.MekHQ; import mekhq.campaign.Campaign; import mekhq.campaign.enums.CampaignTransportType; +import mekhq.campaign.event.UnitChangedEvent; import mekhq.campaign.force.Force; import mekhq.campaign.unit.Unit; import mekhq.campaign.unit.enums.TransporterType; @@ -171,4 +173,25 @@ private Set createTransportMenus(TransporterType transporterType, Set */ protected abstract void transportMenuAction(ActionEvent evt, TransporterType transporterType, Unit transport, Set units); + /** + * Shared updates used by {@link AssignForceToShipTransportMenu} and {@link AssignForceToTacticalTransportMenu} + * @param transport transport (Unit) that has loaded these units + * @param units units being assigned to the transport + * @param oldTransports transports (Unit) that had previously transported the units + */ + protected void updateTransportsForTransportMenuAction(CampaignTransportType campaignTransportType, Unit transport, + Set units, Set oldTransports) { + if (!oldTransports.isEmpty()) { + oldTransports.forEach(oldTransport -> { + oldTransport.initializeAllTransportSpace(); + campaign.updateTransportInTransports(campaignTransportType, oldTransport); + }); + oldTransports.forEach(oldTransport -> MekHQ.triggerEvent(new UnitChangedEvent(transport))); + } + for (Unit unit : units) { + MekHQ.triggerEvent(new UnitChangedEvent(unit)); + } + campaign.updateTransportInTransports(campaignTransportType, transport); + MekHQ.triggerEvent(new UnitChangedEvent(transport)); + } }