diff --git a/core/src/main/java/com/seibel/lod/core/config/eventHandlers/RenderCacheConfigEventHandler.java b/core/src/main/java/com/seibel/lod/core/config/eventHandlers/RenderCacheConfigEventHandler.java index 74b3af9d0..535a72522 100644 --- a/core/src/main/java/com/seibel/lod/core/config/eventHandlers/RenderCacheConfigEventHandler.java +++ b/core/src/main/java/com/seibel/lod/core/config/eventHandlers/RenderCacheConfigEventHandler.java @@ -4,6 +4,8 @@ import com.seibel.lod.api.DhApiMain; import com.seibel.lod.api.enums.config.EHorizontalResolution; import com.seibel.lod.api.enums.config.EVerticalQuality; import com.seibel.lod.core.config.Config; +import com.seibel.lod.core.config.listeners.ConfigChangeListener; +import com.seibel.lod.core.config.listeners.IConfigListener; import com.seibel.lod.core.config.types.ConfigEntry; import com.seibel.lod.core.util.DetailDistanceUtil; @@ -16,7 +18,7 @@ import com.seibel.lod.core.util.DetailDistanceUtil; * @author James Seibel * @version 2023-2-9 */ -public class RenderCacheConfigEventHandler implements ConfigEntry.Listener +public class RenderCacheConfigEventHandler implements IConfigListener { public static RenderCacheConfigEventHandler INSTANCE = new RenderCacheConfigEventHandler(); @@ -32,7 +34,7 @@ public class RenderCacheConfigEventHandler implements ConfigEntry.Listener @Override - public void onModify() + public void onConfigValueSet() { // confirm a setting was actually changed boolean refreshRenderData = false; diff --git a/core/src/main/java/com/seibel/lod/core/config/listeners/ConfigChangeListener.java b/core/src/main/java/com/seibel/lod/core/config/listeners/ConfigChangeListener.java new file mode 100644 index 000000000..9d99653fd --- /dev/null +++ b/core/src/main/java/com/seibel/lod/core/config/listeners/ConfigChangeListener.java @@ -0,0 +1,57 @@ +package com.seibel.lod.core.config.listeners; + +import com.seibel.lod.core.config.types.ConfigEntry; + +import java.io.Closeable; +import java.util.function.Consumer; + +/** + * A basic {@link IConfigListener} that will fire a {@link Consumer} + * when the value changes from the value the config started with + * when this object was created. + * + * @param the config value type + */ +public class ConfigChangeListener implements IConfigListener, Closeable +{ + private final ConfigEntry configEntry; + private final Consumer onValueChangeFunc; + + private T previousValue; + + + + public ConfigChangeListener(ConfigEntry configEntry, Consumer onValueChangeFunc) + { + this.configEntry = configEntry; + this.onValueChangeFunc = onValueChangeFunc; + + this.configEntry.addListener(this); + this.previousValue = this.configEntry.get(); + } + + + @Override + public void onConfigValueSet() + { + T newValue = this.configEntry.get(); + if (newValue != previousValue) + { + previousValue = newValue; + this.onValueChangeFunc.accept(newValue); + } + } + + @Override + public void onUiModify() { /* do nothing, we only care about when the actual value is modified */ } + + + + /** + * Removes the config event listener.
+ * Must be fired to prevent memory leaks. + */ + @Override + public void close() { this.configEntry.removeListener(this); } + +} diff --git a/core/src/main/java/com/seibel/lod/core/config/listeners/IConfigListener.java b/core/src/main/java/com/seibel/lod/core/config/listeners/IConfigListener.java new file mode 100644 index 000000000..09ac5eb3b --- /dev/null +++ b/core/src/main/java/com/seibel/lod/core/config/listeners/IConfigListener.java @@ -0,0 +1,11 @@ +package com.seibel.lod.core.config.listeners; + +public interface IConfigListener +{ + /** Called whenever the value is set (including in core DH code) */ + void onConfigValueSet(); + + /** Called whenever the value is changed through the UI (only when the done button is pressed) */ + void onUiModify(); // TODO + +} diff --git a/core/src/main/java/com/seibel/lod/core/config/types/ConfigEntry.java b/core/src/main/java/com/seibel/lod/core/config/types/ConfigEntry.java index d2657a4e9..2598ececd 100644 --- a/core/src/main/java/com/seibel/lod/core/config/types/ConfigEntry.java +++ b/core/src/main/java/com/seibel/lod/core/config/types/ConfigEntry.java @@ -1,6 +1,7 @@ package com.seibel.lod.core.config.types; +import com.seibel.lod.core.config.listeners.IConfigListener; import com.seibel.lod.coreapi.interfaces.config.IConfigEntry; import java.util.ArrayList; @@ -15,19 +16,11 @@ import java.util.Arrays; */ public class ConfigEntry extends AbstractConfigType> implements IConfigEntry { - public interface Listener - { - /** Called whenever the value changes at all (including in the code itself) */ - void onModify(); - /** Called whenever the value is changed through the UI (only when the done button is pressed) */ - void onUiModify(); // TODO - } - private final T defaultValue; private String comment; private T min; private T max; - private final ArrayList listener; + private final ArrayList listenerList; // API control // /** @@ -41,7 +34,8 @@ public class ConfigEntry extends AbstractConfigType> implem /** Creates the entry */ - private ConfigEntry(ConfigEntryAppearance appearance, T value, String comment, T min, T max, boolean allowApiOverride, ConfigEntryPerformance performance, ArrayList listener) { + private ConfigEntry(ConfigEntryAppearance appearance, T value, String comment, T min, T max, boolean allowApiOverride, ConfigEntryPerformance performance, ArrayList listenerList) + { super(appearance, value); this.defaultValue = value; this.comment = comment; @@ -49,40 +43,41 @@ public class ConfigEntry extends AbstractConfigType> implem this.max = max; this.allowApiOverride = allowApiOverride; this.performance = performance; - this.listener = listener; - } - - - /** Gets the default value of the option */ - @Override - public T getDefaultValue() { - return this.defaultValue; + this.listenerList = listenerList; } + + + /** Gets the default value of the option */ @Override - public void setApiValue(T newApiValue) { - this.apiValue = newApiValue; - } + public T getDefaultValue() { return this.defaultValue; } + @Override - public T getApiValue() { - return this.apiValue; - } + public void setApiValue(T newApiValue) { this.apiValue = newApiValue; } + @Override + public T getApiValue() { return this.apiValue; } @Override public boolean getAllowApiOverride() { return this.allowApiOverride; } @Override - public void set(T newValue) { + public void set(T newValue) + { super.set(newValue); - save(); - this.listener.forEach(Listener::onModify); + this.save(); + this.listenerList.forEach(IConfigListener::onConfigValueSet); } - public void uiSet(T newValue) { - set(newValue); - this.listener.forEach(Listener::onUiModify); + public void uiSet(T newValue) + { + this.set(newValue); + this.listenerList.forEach(IConfigListener::onUiModify); } @Override - public T get() { + public T get() + { if (allowApiOverride && apiValue != null) - return apiValue; + { + return apiValue; + } + return super.get(); } @Override @@ -92,77 +87,52 @@ public class ConfigEntry extends AbstractConfigType> implem /** Sets the value without saving */ @Override - public void setWithoutSaving(T newValue) { - super.set(newValue); - } + public void setWithoutSaving(T newValue) + { + super.set(newValue); + this.listenerList.forEach(IConfigListener::onConfigValueSet); + } /** Gets the min value */ @Override - public T getMin() { - return this.min; - } + public T getMin() { return this.min; } /** Sets the min value */ @Override - public void setMin(T newMin) { - this.min = newMin; - } + public void setMin(T newMin) { this.min = newMin; } /** Gets the max value */ @Override - public T getMax() { - return this.max; - } + public T getMax() { return this.max; } /** Sets the max value */ @Override - public void setMax(T newMax) { - this.max = newMax; - } + public void setMax(T newMax) { this.max = newMax; } /** Sets the min and max in 1 setter */ @Override - public void setMinMax(T newMin, T newMax) { + public void setMinMax(T newMin, T newMax) + { this.max = newMin; this.min = newMax; } - /** Gets the comment */ @Override - public String getComment() { - return this.comment; - } - /** Sets the comment */ + public String getComment() { return this.comment; } @Override - public void setComment(String newComment) { - this.comment = newComment; - } + public void setComment(String newComment) { this.comment = newComment; } /** Gets the performance impact of an option */ - public ConfigEntryPerformance getPerformance() { - return this.performance; - } + public ConfigEntryPerformance getPerformance() { return this.performance; } - /** Adds a listener */ - public void addListener(Listener newListener) { - this.listener.add(newListener); - } - /** Removes a listener */ - public void removeListener(Listener oldListener) { - this.listener.remove(oldListener); - } - /** Removes all listeners */ - public void clearListeners() { - this.listener.clear(); - } - /** Gets all the listeners */ - public ArrayList getListeners() { - return this.listener; - } - /** Sets/Replaces the listener list */ - public void setListeners(ArrayList newListeners) { - this.listener.clear(); - this.listener.addAll(newListeners); - } - public void setListeners(Listener... newListeners) { - this.listener.addAll(Arrays.asList(newListeners)); + public void addListener(IConfigListener newListener) { this.listenerList.add(newListener); } + public void removeListener(IConfigListener oldListener) { this.listenerList.remove(oldListener); } + + public void clearListeners() { this.listenerList.clear(); } + public ArrayList getListeners() { return this.listenerList; } + /** Replaces the listener list */ + public void setListeners(ArrayList newListeners) + { + this.listenerList.clear(); + this.listenerList.addAll(newListeners); } + public void setListeners(IConfigListener... newListeners) { this.listenerList.addAll(Arrays.asList(newListeners)); } /** @@ -174,9 +144,7 @@ public class ConfigEntry extends AbstractConfigType> implem *

-1 == number too low */ @Override - public byte isValid() { - return isValid(this.value); - } + public byte isValid() { return isValid(this.value); } /** Checks if a value is valid */ @Override public byte isValid(T value) { @@ -197,13 +165,9 @@ public class ConfigEntry extends AbstractConfigType> implem } /** This should normally not be called since set() automatically calls this */ - public void save() { - configBase.configFileINSTANCE.saveEntry(this); - } + public void save() { configBase.configFileINSTANCE.saveEntry(this); } /** This should normally not be called except for special circumstances */ - public void load() { - configBase.configFileINSTANCE.loadEntry(this); - } + public void load() { configBase.configFileINSTANCE.loadEntry(this); } @Override @@ -219,72 +183,90 @@ public class ConfigEntry extends AbstractConfigType> implem } - public static class Builder extends AbstractConfigType.Builder> { + public static class Builder extends AbstractConfigType.Builder> + { private String tmpComment = null; private T tmpMin; private T tmpMax; private boolean tmpUseApiOverwrite; private ConfigEntryPerformance tmpPerformance = ConfigEntryPerformance.DONT_SHOW; - protected ArrayList tmpListener = new ArrayList(); + protected ArrayList tmpIConfigListener = new ArrayList<>(); - public Builder comment(String newComment) { - this.tmpComment = newComment; - return this; - } + public Builder comment(String newComment) + { + this.tmpComment = newComment; + return this; + } /** Allows most values to be set by 1 setter */ - public Builder setMinDefaultMax(T newMin, T newDefault, T newMax) { - this.set(newDefault); - this.setMinMax(newMin, newMax); - return this; - } + public Builder setMinDefaultMax(T newMin, T newDefault, T newMax) + { + this.set(newDefault); + this.setMinMax(newMin, newMax); + return this; + } - public Builder setMinMax(T newMin, T newMax) { - this.tmpMin = newMin; - this.tmpMax = newMax; - return this; - } + public Builder setMinMax(T newMin, T newMax) + { + this.tmpMin = newMin; + this.tmpMax = newMax; + return this; + } - public Builder setMin(T newMin) { - this.tmpMin = newMin; - return this; - } - public Builder setMax(T newMax) { - this.tmpMax = newMax; - return this; - } + public Builder setMin(T newMin) + { + this.tmpMin = newMin; + return this; + } + + public Builder setMax(T newMax) + { + this.tmpMax = newMax; + return this; + } - public Builder setUseApiOverwrite(boolean newUseApiOverwrite) { - this.tmpUseApiOverwrite = newUseApiOverwrite; - return this; - } + public Builder setUseApiOverwrite(boolean newUseApiOverwrite) + { + this.tmpUseApiOverwrite = newUseApiOverwrite; + return this; + } - public Builder setPerformance(ConfigEntryPerformance newPerformance) { - this.tmpPerformance = newPerformance; - return this; - } + public Builder setPerformance(ConfigEntryPerformance newPerformance) + { + this.tmpPerformance = newPerformance; + return this; + } - public Builder replaceListener(ArrayList newListener) { - this.tmpListener = newListener; - return this; - } - public Builder addListeners(Listener... newListener) { - this.tmpListener.addAll(Arrays.asList(newListener)); - return this; - } - public Builder addListener(Listener newListener) { - this.tmpListener.add(newListener); - return this; - } - public Builder clearListeners() { - this.tmpListener.clear(); - return this; - } + public Builder replaceListener(ArrayList newConfigListener) + { + this.tmpIConfigListener = newConfigListener; + return this; + } + + public Builder addListeners(IConfigListener... newConfigListener) + { + this.tmpIConfigListener.addAll(Arrays.asList(newConfigListener)); + return this; + } + + public Builder addListener(IConfigListener newConfigListener) + { + this.tmpIConfigListener.add(newConfigListener); + return this; + } + + public Builder clearListeners() + { + this.tmpIConfigListener.clear(); + return this; + } - public ConfigEntry build() { - return new ConfigEntry(tmpAppearance, tmpValue, tmpComment, tmpMin, tmpMax, tmpUseApiOverwrite, tmpPerformance, tmpListener); + public ConfigEntry build() + { + return new ConfigEntry(tmpAppearance, tmpValue, tmpComment, tmpMin, tmpMax, tmpUseApiOverwrite, tmpPerformance, tmpIConfigListener); } + } } diff --git a/core/src/main/java/com/seibel/lod/core/file/fullDatafile/FullDataFileHandler.java b/core/src/main/java/com/seibel/lod/core/file/fullDatafile/FullDataFileHandler.java index 5fa1fae46..5ef378373 100644 --- a/core/src/main/java/com/seibel/lod/core/file/fullDatafile/FullDataFileHandler.java +++ b/core/src/main/java/com/seibel/lod/core/file/fullDatafile/FullDataFileHandler.java @@ -2,6 +2,7 @@ package com.seibel.lod.core.file.fullDatafile; import com.google.common.collect.HashMultimap; import com.seibel.lod.core.config.Config; +import com.seibel.lod.core.config.listeners.ConfigChangeListener; import com.seibel.lod.core.config.types.ConfigEntry; import com.seibel.lod.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor; import com.seibel.lod.core.dataObjects.fullData.sources.*; @@ -34,7 +35,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider private static final Logger LOGGER = DhLoggerBuilder.getLogger(); protected ExecutorService fileHandlerThreadPool; - protected final ConfigListener configListener = new ConfigListener(); + protected final ConfigChangeListener configListener; protected final ConcurrentHashMap fileBySectionPos = new ConcurrentHashMap<>(); protected final IDhLevel level; @@ -46,7 +47,7 @@ public class FullDataFileHandler implements IFullDataSourceProvider public FullDataFileHandler(IDhLevel level, File saveRootDir) { - Config.Client.Advanced.Threading.numberOfFileHandlerThreads.addListener(this.configListener); + configListener = new ConfigChangeListener<>(Config.Client.Advanced.Threading.numberOfFileHandlerThreads, (threadCount) -> { this.setThreadPoolSize(threadCount); }); int threadPoolSize = Config.Client.Advanced.Threading.numberOfFileHandlerThreads.get(); this.setThreadPoolSize(threadPoolSize); @@ -477,43 +478,10 @@ public class FullDataFileHandler implements IFullDataSourceProvider { FullDataMetaFile.debugPhantomLifeCycleCheck(); - Config.Client.Advanced.Threading.numberOfFileHandlerThreads.removeListener(configListener); + configListener.close(); // stop any existing file tasks this.fileHandlerThreadPool.shutdownNow(); } - - - //================// - // helper classes // - //================// - - private class ConfigListener implements ConfigEntry.Listener - { - private int previousThreadCount; - - - public ConfigListener() - { - this.previousThreadCount = Config.Client.Advanced.Threading.numberOfFileHandlerThreads.get(); - } - - - @Override - public void onModify() - { - int newThreadCount = Config.Client.Advanced.Threading.numberOfFileHandlerThreads.get(); - if (newThreadCount != previousThreadCount) - { - previousThreadCount = newThreadCount; - setThreadPoolSize(newThreadCount); - } - } - - @Override - public void onUiModify() { /* do nothing, we only care about when the actual value is modified */ } - - } - }