Skip to content

Commit

Permalink
feat: make WorldConfigurator subscribable (#5233)
Browse files Browse the repository at this point in the history
* interested parties can subscribe to receive change notifications for all or specific properties available
* change notifications include information about the changed property as well as the old and new values
* no longer interested parties can subscribe from all or specific properties
* subscriptions to all properties will remain intact in case a no longer interested party cancels their subscription for specific properties
  • Loading branch information
jdrueckert authored Apr 14, 2024
1 parent 82fd5c4 commit 215e968
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@
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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class FacetedWorldConfigurator implements WorldConfigurator {

Expand All @@ -19,6 +24,7 @@ public class FacetedWorldConfigurator implements WorldConfigurator {
private final Map<String, Component> properties = Maps.newHashMap();

private final List<ConfigurableFacetProvider> providers;
private Map<String, Set<PropertyChangeListener>> listeners = new HashMap<>();

public FacetedWorldConfigurator(List<ConfigurableFacetProvider> providersList) {
for (ConfigurableFacetProvider provider : providersList) {
Expand All @@ -40,11 +46,79 @@ 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);

PropertyChangeEvent event = new PropertyChangeEvent(this, key, oldComp, comp);
Set<PropertyChangeListener> allPropListeners = listeners.get("*");
if (allPropListeners != null) {
allPropListeners.forEach(listener -> {
listener.propertyChange(event);
});
}
Set<PropertyChangeListener> specPropListeners = listeners.get(key);
if (specPropListeners != null) {
specPropListeners.forEach(listener -> {
listener.propertyChange(event);
});
}

return;
}
}

logger.warn("No property {} found", key);
}

/**
* Subscribes a new listener to receive change notifications for all properties.
* @param changeListener
*/
@Override
public void subscribe(PropertyChangeListener changeListener) {
Set<PropertyChangeListener> ls = listeners.computeIfAbsent("*", k -> new HashSet<>());
ls.add(changeListener);
}

/**
* Unsubscribes an existing listener from receiving change notifications for all properties.
* If the listener was subscribed to a specific property separately
* via {@link FacetedWorldConfigurator#unsubscribe(String, PropertyChangeListener)},
* it will continue to receive change notifications for that property.
* @param changeListener
*/
@Override
public void unsubscribe(PropertyChangeListener changeListener) {
listeners.computeIfPresent("*", (k, v) -> {
v.remove(changeListener);
return v;
});
}

/**
* Subscribes a new listener to receive change notifications for the specified property.
* @param propertyName
* @param changeListener
*/
@Override
public void subscribe(String propertyName, PropertyChangeListener changeListener) {
Set<PropertyChangeListener> ls = listeners.computeIfAbsent(propertyName, k -> new HashSet<>());
ls.add(changeListener);
}

/**
* Unsubscribes an existing listener from receiving change notifications for the specified property.
* If the listener was subscribed to all properties separately
* via {@link FacetedWorldConfigurator#unsubscribe(PropertyChangeListener)},
* it will continue to receive change notifications for all properties including the one it is being unsubscribed from now.
* @param propertyName
* @param changeListener
*/
@Override
public void unsubscribe(String propertyName, PropertyChangeListener changeListener) {
listeners.computeIfPresent(propertyName, (k, v) -> {
v.remove(changeListener);
return v;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
// SPDX-License-Identifier: Apache-2.0
package org.terasology.engine.world.generator;

import org.terasology.engine.utilities.subscribables.Subscribable;
import org.terasology.gestalt.entitysystem.component.Component;

import java.util.Map;

/**
* Allows for configuration of world generators.
* Interested parties can subscribe to all or only specific properties and receive change notifications.
*/
public interface WorldConfigurator {
public interface WorldConfigurator extends Subscribable {

/**
* The values are supposed to be annotated with {@link org.terasology.nui.properties.Property}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import org.terasology.gestalt.entitysystem.component.Component;

import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.Map;

Expand All @@ -21,4 +22,24 @@ public Map<String, Component> getProperties() {
public void setProperty(String key, Component comp) {
// simply ignore
}

@Override
public void subscribe(PropertyChangeListener changeListener) {
// simply ignore
}

@Override
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
}
}

0 comments on commit 215e968

Please sign in to comment.