fix config listener onValueSet and add ConfigChangeListener

This commit is contained in:
James Seibel
2023-06-04 22:03:59 -05:00
parent 4b29e96686
commit 05d4e4bf61
5 changed files with 199 additions and 179 deletions
@@ -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;
@@ -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 <T> the config value type
*/
public class ConfigChangeListener<T> implements IConfigListener, Closeable
{
private final ConfigEntry<T> configEntry;
private final Consumer<T> onValueChangeFunc;
private T previousValue;
public ConfigChangeListener(ConfigEntry<T> configEntry, Consumer<T> 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. <br>
* Must be fired to prevent memory leaks.
*/
@Override
public void close() { this.configEntry.removeListener(this); }
}
@@ -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
}
@@ -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<T> extends AbstractConfigType<T, ConfigEntry<T>> implements IConfigEntry<T>
{
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> listener;
private final ArrayList<IConfigListener> listenerList;
// API control //
/**
@@ -41,7 +34,8 @@ public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
/** Creates the entry */
private ConfigEntry(ConfigEntryAppearance appearance, T value, String comment, T min, T max, boolean allowApiOverride, ConfigEntryPerformance performance, ArrayList<Listener> listener) {
private ConfigEntry(ConfigEntryAppearance appearance, T value, String comment, T min, T max, boolean allowApiOverride, ConfigEntryPerformance performance, ArrayList<IConfigListener> listenerList)
{
super(appearance, value);
this.defaultValue = value;
this.comment = comment;
@@ -49,40 +43,41 @@ public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> 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<T> extends AbstractConfigType<T, ConfigEntry<T>> 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<Listener> getListeners() {
return this.listener;
}
/** Sets/Replaces the listener list */
public void setListeners(ArrayList<Listener> 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<IConfigListener> getListeners() { return this.listenerList; }
/** Replaces the listener list */
public void setListeners(ArrayList<IConfigListener> 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<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
* <p> -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<T> extends AbstractConfigType<T, ConfigEntry<T>> 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<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
}
public static class Builder<T> extends AbstractConfigType.Builder<T, Builder<T>> {
public static class Builder<T> extends AbstractConfigType.Builder<T, Builder<T>>
{
private String tmpComment = null;
private T tmpMin;
private T tmpMax;
private boolean tmpUseApiOverwrite;
private ConfigEntryPerformance tmpPerformance = ConfigEntryPerformance.DONT_SHOW;
protected ArrayList<Listener> tmpListener = new ArrayList<Listener>();
protected ArrayList<IConfigListener> tmpIConfigListener = new ArrayList<>();
public Builder<T> comment(String newComment) {
this.tmpComment = newComment;
return this;
}
public Builder<T> comment(String newComment)
{
this.tmpComment = newComment;
return this;
}
/** Allows most values to be set by 1 setter */
public Builder<T> setMinDefaultMax(T newMin, T newDefault, T newMax) {
this.set(newDefault);
this.setMinMax(newMin, newMax);
return this;
}
public Builder<T> setMinDefaultMax(T newMin, T newDefault, T newMax)
{
this.set(newDefault);
this.setMinMax(newMin, newMax);
return this;
}
public Builder<T> setMinMax(T newMin, T newMax) {
this.tmpMin = newMin;
this.tmpMax = newMax;
return this;
}
public Builder<T> setMinMax(T newMin, T newMax)
{
this.tmpMin = newMin;
this.tmpMax = newMax;
return this;
}
public Builder<T> setMin(T newMin) {
this.tmpMin = newMin;
return this;
}
public Builder<T> setMax(T newMax) {
this.tmpMax = newMax;
return this;
}
public Builder<T> setMin(T newMin)
{
this.tmpMin = newMin;
return this;
}
public Builder<T> setMax(T newMax)
{
this.tmpMax = newMax;
return this;
}
public Builder<T> setUseApiOverwrite(boolean newUseApiOverwrite) {
this.tmpUseApiOverwrite = newUseApiOverwrite;
return this;
}
public Builder<T> setUseApiOverwrite(boolean newUseApiOverwrite)
{
this.tmpUseApiOverwrite = newUseApiOverwrite;
return this;
}
public Builder<T> setPerformance(ConfigEntryPerformance newPerformance) {
this.tmpPerformance = newPerformance;
return this;
}
public Builder<T> setPerformance(ConfigEntryPerformance newPerformance)
{
this.tmpPerformance = newPerformance;
return this;
}
public Builder<T> replaceListener(ArrayList<Listener> newListener) {
this.tmpListener = newListener;
return this;
}
public Builder<T> addListeners(Listener... newListener) {
this.tmpListener.addAll(Arrays.asList(newListener));
return this;
}
public Builder<T> addListener(Listener newListener) {
this.tmpListener.add(newListener);
return this;
}
public Builder<T> clearListeners() {
this.tmpListener.clear();
return this;
}
public Builder<T> replaceListener(ArrayList<IConfigListener> newConfigListener)
{
this.tmpIConfigListener = newConfigListener;
return this;
}
public Builder<T> addListeners(IConfigListener... newConfigListener)
{
this.tmpIConfigListener.addAll(Arrays.asList(newConfigListener));
return this;
}
public Builder<T> addListener(IConfigListener newConfigListener)
{
this.tmpIConfigListener.add(newConfigListener);
return this;
}
public Builder<T> clearListeners()
{
this.tmpIConfigListener.clear();
return this;
}
public ConfigEntry<T> build() {
return new ConfigEntry<T>(tmpAppearance, tmpValue, tmpComment, tmpMin, tmpMax, tmpUseApiOverwrite, tmpPerformance, tmpListener);
public ConfigEntry<T> build()
{
return new ConfigEntry<T>(tmpAppearance, tmpValue, tmpComment, tmpMin, tmpMax, tmpUseApiOverwrite, tmpPerformance, tmpIConfigListener);
}
}
}
@@ -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<Integer> configListener;
protected final ConcurrentHashMap<DhSectionPos, FullDataMetaFile> 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 */ }
}
}