From c1eeb55cd4eca8ccac87471717af5a7d00e47e80 Mon Sep 17 00:00:00 2001 From: Josephine Rueckert Date: Sun, 7 Apr 2024 20:40:18 +0200 Subject: [PATCH] refactor: use Subscribable instead of Observer * this allows for property-specific updates --- .../layers/mainMenu/UniverseSetupScreen.java | 16 ++++-- .../generation/FacetedWorldConfigurator.java | 52 ++++++++++++++++--- .../world/generator/WorldConfigurator.java | 7 +-- .../generator/WorldConfiguratorAdapter.java | 15 +++++- 4 files changed, 70 insertions(+), 20 deletions(-) diff --git a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseSetupScreen.java b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseSetupScreen.java index c89ba7077ad..b96b0bcd40a 100644 --- a/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseSetupScreen.java +++ b/engine/src/main/java/org/terasology/engine/rendering/nui/layers/mainMenu/UniverseSetupScreen.java @@ -78,6 +78,8 @@ import org.terasology.reflection.reflect.ReflectFactory; import org.terasology.reflection.reflect.ReflectionReflectFactory; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.nio.ByteBuffer; import java.util.HashSet; import java.util.List; @@ -91,7 +93,7 @@ * Sets up the Universe for a user. Displays a list of {@link WorldGenerator} * for a particular game template. */ -public class UniverseSetupScreen extends CoreScreenLayer implements UISliderOnChangeTriggeredListener, Observer { +public class UniverseSetupScreen extends CoreScreenLayer implements UISliderOnChangeTriggeredListener, PropertyChangeListener { public static final ResourceUrn ASSET_URI = new ResourceUrn("engine:universeSetupScreen"); @In @@ -307,11 +309,15 @@ public void update(float delta) { } /** - Called whenever there's a change to WorldConfigurator + Called whenever there's a change to WorldConfigurator properties + Provides information about the changed property as well as old and new value in {@link PropertyChangeEvent} */ @Override - public void update(WorldConfigurator layer) { - previewUpdateRequiredSince = time.getRealTimeInMs(); + public void propertyChange(PropertyChangeEvent propertyChangeEvent) { + System.out.println(propertyChangeEvent.getPropertyName()); + if (propertyChangeEvent.getPropertyName() == "Trees") { + previewUpdateRequiredSince = time.getRealTimeInMs(); + } } private void setSeed(String value) { @@ -498,7 +504,7 @@ private void configureProperties() { worldConfig = worldGenerator.getConfigurator(); universe.setWorldConfigurator(worldConfig); } - worldConfig.addObserver(this); + worldConfig.subscribe(this); Map params = worldConfig.getProperties(); diff --git a/engine/src/main/java/org/terasology/engine/world/generation/FacetedWorldConfigurator.java b/engine/src/main/java/org/terasology/engine/world/generation/FacetedWorldConfigurator.java index 4aaa217d5d2..d63a32ce937 100644 --- a/engine/src/main/java/org/terasology/engine/world/generation/FacetedWorldConfigurator.java +++ b/engine/src/main/java/org/terasology/engine/world/generation/FacetedWorldConfigurator.java @@ -3,14 +3,20 @@ package org.terasology.engine.world.generation; import com.google.common.collect.Maps; +import com.google.common.collect.Multimap; +import com.google.common.collect.Multiset; +import com.google.common.collect.SetMultimap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.terasology.engine.core.Observer; import org.terasology.engine.world.generator.WorldConfigurator; import org.terasology.gestalt.entitysystem.component.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -23,7 +29,7 @@ public class FacetedWorldConfigurator implements WorldConfigurator { private final Map properties = Maps.newHashMap(); private final List providers; - private Set> observers = new HashSet<>(); + private HashMap> listeners = new HashMap<>(); public FacetedWorldConfigurator(List providersList) { for (ConfigurableFacetProvider provider : providersList) { @@ -45,10 +51,22 @@ public void setProperty(String key, Component comp) { for (ConfigurableFacetProvider facetProvider : providers) { if (key.equals(facetProvider.getConfigurationName())) { facetProvider.setConfiguration(comp); + Component oldComp = properties.get(key); properties.put(key, comp); - observers.forEach(observer -> { - observer.update(this); - }); + + PropertyChangeEvent event = new PropertyChangeEvent(this, key, oldComp, comp); + Set allPropListeners = listeners.get("*"); + if (allPropListeners != null) { + allPropListeners.forEach(listener -> { + listener.propertyChange(event); + }); + } + Set specPropListeners = listeners.get(key); + if (specPropListeners != null) { + specPropListeners.forEach(listener -> { + listener.propertyChange(event); + }); + } return; } } @@ -57,12 +75,30 @@ public void setProperty(String key, Component comp) { } @Override - public void addObserver(Observer observer) { - observers.add(observer); + public void subscribe(PropertyChangeListener changeListener) { + Set ls = listeners.computeIfAbsent("*", k -> new HashSet<>()); + ls.add(changeListener); + } + + @Override + public void unsubscribe(PropertyChangeListener changeListener) { + listeners.computeIfPresent("*", (k, v) -> { + v.remove(changeListener); + return v; + }); + } + + @Override + public void subscribe(String propertyName, PropertyChangeListener changeListener) { + Set ls = listeners.computeIfAbsent(propertyName, k -> new HashSet<>()); + ls.add(changeListener); } @Override - public void removeObserver(Observer observer) { - observers.remove(observer); + public void unsubscribe(String propertyName, PropertyChangeListener changeListener) { + listeners.computeIfPresent(propertyName, (k, v) -> { + v.remove(changeListener); + return v; + }); } } diff --git a/engine/src/main/java/org/terasology/engine/world/generator/WorldConfigurator.java b/engine/src/main/java/org/terasology/engine/world/generator/WorldConfigurator.java index e44368f376d..9a16bb8f00d 100644 --- a/engine/src/main/java/org/terasology/engine/world/generator/WorldConfigurator.java +++ b/engine/src/main/java/org/terasology/engine/world/generator/WorldConfigurator.java @@ -3,6 +3,7 @@ package org.terasology.engine.world.generator; import org.terasology.engine.core.Observer; +import org.terasology.engine.utilities.subscribables.Subscribable; import org.terasology.gestalt.entitysystem.component.Component; import java.util.Map; @@ -11,7 +12,7 @@ /** * Allows for configuration of world generators. */ -public interface WorldConfigurator { +public interface WorldConfigurator extends Subscribable { /** * The values are supposed to be annotated with {@link org.terasology.nui.properties.Property} @@ -25,8 +26,4 @@ public interface WorldConfigurator { * @param comp the configuration component */ void setProperty(String key, Component comp); - - void addObserver(Observer observer); - - void removeObserver(Observer observer); } diff --git a/engine/src/main/java/org/terasology/engine/world/generator/WorldConfiguratorAdapter.java b/engine/src/main/java/org/terasology/engine/world/generator/WorldConfiguratorAdapter.java index 41b57ad5f7b..90bca0287ca 100644 --- a/engine/src/main/java/org/terasology/engine/world/generator/WorldConfiguratorAdapter.java +++ b/engine/src/main/java/org/terasology/engine/world/generator/WorldConfiguratorAdapter.java @@ -5,6 +5,7 @@ import org.terasology.engine.core.Observer; import org.terasology.gestalt.entitysystem.component.Component; +import java.beans.PropertyChangeListener; import java.util.Collections; import java.util.Map; @@ -24,12 +25,22 @@ public void setProperty(String key, Component comp) { } @Override - public void addObserver(Observer observer) { + public void subscribe(PropertyChangeListener changeListener) { // simply ignore } @Override - public void removeObserver(Observer observer) { + public void unsubscribe(PropertyChangeListener changeListener) { + // simply ignore + } + + @Override + public void subscribe(String propertyName, PropertyChangeListener changeListener) { + // simply ignore + } + + @Override + public void unsubscribe(String propertyName, PropertyChangeListener changeListener) { // simply ignore } }