diff --git a/megamek/build.gradle b/megamek/build.gradle index 6d94571c683..5e11812c02f 100644 --- a/megamek/build.gradle +++ b/megamek/build.gradle @@ -9,7 +9,7 @@ plugins { id 'jacoco' id 'java' id 'org.ec4j.editorconfig' version '0.1.0' - + id 'org.openjfx.javafxplugin' version '0.1.0' } java { @@ -17,6 +17,12 @@ java { targetCompatibility = JavaVersion.VERSION_17 } +javafx { + // Version 23 requires JDK 21 + version = "22.0.2" + modules = [ 'javafx.base' ] +} + sourceSets { main { java { diff --git a/megamek/src/megamek/common/Entity.java b/megamek/src/megamek/common/Entity.java index a0600fea0e5..e8ff017592d 100644 --- a/megamek/src/megamek/common/Entity.java +++ b/megamek/src/megamek/common/Entity.java @@ -15,6 +15,9 @@ package megamek.common; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; import megamek.MMConstants; import megamek.client.bot.princess.FireControl; import megamek.client.ui.Base64Image; @@ -50,6 +53,10 @@ import megamek.utilities.xml.MMXMLUtility; import java.awt.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serial; import java.math.BigInteger; import java.util.List; import java.util.*; @@ -453,7 +460,7 @@ public enum InvalidSourceBuildReason { /** * A list of all mounted equipment. (Weapons, ammo, and misc) */ - protected List> equipmentList = new ArrayList<>(); + protected transient ObservableList> equipmentList = FXCollections.observableArrayList(); /** * A list of all mounted weapons. This only includes regular weapons, not @@ -15846,4 +15853,54 @@ public boolean canonUnitWithInvalidBuild() { return false; } + private final List>> equipmentListeners = new ArrayList<>(); + + /** + * Adds a listener to this entity's equipment list + * @param listener an object which will be informed when the entity's equipment changes + */ + public void addEquipmentChangedListener(ListChangeListener> listener) { + equipmentList.addListener(listener); + equipmentListeners.add(listener); + } + + /** + * Removes a listener from this entity's equipment list + * @param listener the listener to rmove + */ + public void removeEquipmentChangedListener(ListChangeListener> listener) { + equipmentList.removeListener(listener); + equipmentListeners.remove(listener); + } + + /** + * Replaces any existing equipment listeners with a new one. + * Only listeners of the exact same class of the listener are replaced. + * This can help prevent memory leaks, if a listening object is no longer needed it will be removed from the list of listeners by the replacing object. + * @param listener The new listener to add. + */ + public void replaceEquipmentChangedListener(ListChangeListener> listener) { + for (Iterator>> iterator = equipmentListeners.iterator(); iterator.hasNext(); ) { + var existing = iterator.next(); + if (listener.getClass().equals(existing.getClass())) { + equipmentList.removeListener(existing); + iterator.remove(); + } + } + + equipmentList.addListener(listener); + equipmentListeners.add(listener); + } + + @Serial + private void writeObject(ObjectOutputStream out) throws IOException { + out.defaultWriteObject(); + out.writeObject(new ArrayList<>(equipmentList)); + } + + @Serial + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { + in.defaultReadObject(); + equipmentList = FXCollections.observableArrayList((ArrayList>) in.readObject()); + } }