diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index c3c27afc0..05f70c537 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -27,6 +27,7 @@ import com.seibel.distanthorizons.api.enums.config.quickOptions.EThreadPreset; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode; import com.seibel.distanthorizons.core.config.eventHandlers.QuickRenderToggleConfigEventHandler; import com.seibel.distanthorizons.core.config.eventHandlers.RenderCacheConfigEventHandler; +import com.seibel.distanthorizons.core.config.eventHandlers.UnsafeValuesConfigListener; import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler; import com.seibel.distanthorizons.core.config.eventHandlers.presets.RenderQualityPresetConfigEventHandler; import com.seibel.distanthorizons.core.config.types.ConfigCategory; @@ -51,7 +52,7 @@ import java.util.*; * Otherwise, you will have issues where only some of the config entries will exist when your listener is created. * * @author coolGi - * @version 2023-6-12 + * @version 2023-7-16 */ public class Config @@ -456,7 +457,7 @@ public class Config .build(); public static ConfigEntry noiseSteps = new ConfigEntry.Builder() - .setMinDefaultMax(0, 4, null) + .setMinDefaultMax(1, 4, null) .comment("" + "How many steps of noise should be applied to LODs?") .build(); @@ -1011,10 +1012,17 @@ public class Config + " Additionally, only stuff that's loaded after you enable this \n" + " will render their debug wireframes.") .build(); - + + // Note: This will reset on game restart, and should have a warning on the tooltip + public static ConfigEntry allowUnsafeValues = new ConfigEntry.Builder() + .set(false) + .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) + .addListener(UnsafeValuesConfigListener.INSTANCE) + .build(); + // can be set to public inorder to show in the config file and UI - private static ConfigCategory exampleConfigScreen = new ConfigCategory.Builder() + public static ConfigCategory exampleConfigScreen = new ConfigCategory.Builder() .set(ExampleConfigScreen.class) .build(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/ConfigBase.java b/core/src/main/java/com/seibel/distanthorizons/core/config/ConfigBase.java index 580f92143..7b0ddd4e3 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/ConfigBase.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/ConfigBase.java @@ -68,7 +68,7 @@ public class ConfigBase }}; /** Disables the minimum and maximum of any variable */ - public boolean disableMinMax = false; // Very fun to use + public boolean disableMinMax = false; // Very fun to use, but should always be disabled by default public final List> entries = new ArrayList<>(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/NumberUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/config/NumberUtil.java new file mode 100644 index 000000000..1731da4d0 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/NumberUtil.java @@ -0,0 +1,68 @@ +package com.seibel.distanthorizons.core.config; + +import java.util.HashMap; +import java.util.Map; + +/** + * Helps with working with numbers that the value of which is unknown + * + * @author coolGi + * @version 2023-7-16 + */ +// TODO: Should this be moved out of here into somewhere like the util section +public class NumberUtil { + // Is there no better way of doing this? + public static Map minValues = new HashMap() {{ + put(Byte.class, Byte.MIN_VALUE); + put(Short.class, Short.MIN_VALUE); + put(Integer.class, Integer.MIN_VALUE); + put(Long.class, Long.MIN_VALUE); + put(Double.class, Double.MIN_VALUE); + put(Float.class, Float.MIN_VALUE); + }}; + public static Map maxValues = new HashMap() {{ + put(Byte.class, Byte.MAX_VALUE); + put(Short.class, Short.MAX_VALUE); + put(Integer.class, Integer.MAX_VALUE); + put(Long.class, Long.MAX_VALUE); + put(Double.class, Double.MAX_VALUE); + put(Float.class, Float.MAX_VALUE); + }}; + + public static Number getMinimum(Class c) { + return minValues.get(c); + } + public static Number getMaximum(Class c) { + return maxValues.get(c); + } + + /** Does a greater than (>) operator on any number */ + public static boolean greaterThan(Number a, Number b) { + if (a.getClass() != b.getClass()) + return false; + Class typeClass = a.getClass(); + + if (typeClass == Byte.class) return a.byteValue() > b.byteValue(); + if (typeClass == Short.class) return a.shortValue() > b.shortValue(); + if (typeClass == Integer.class) return a.intValue() > b.intValue(); + if (typeClass == Long.class) return a.longValue() > b.longValue(); + if (typeClass == Double.class) return a.doubleValue() > b.doubleValue(); + if (typeClass == Float.class) return a.floatValue() > b.floatValue(); + return false; + } + + /** Does a less than (<) operator on any number */ + public static boolean lessThan(Number a, Number b) { + if (a.getClass() != b.getClass()) + return false; + Class typeClass = a.getClass(); + + if (typeClass == Byte.class) return a.byteValue() < b.byteValue(); + if (typeClass == Short.class) return a.shortValue() < b.shortValue(); + if (typeClass == Integer.class) return a.intValue() < b.intValue(); + if (typeClass == Long.class) return a.longValue() < b.longValue(); + if (typeClass == Double.class) return a.doubleValue() < b.doubleValue(); + if (typeClass == Float.class) return a.floatValue() < b.floatValue(); + return false; + } +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/UnsafeValuesConfigListener.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/UnsafeValuesConfigListener.java new file mode 100644 index 000000000..4c0eca3bc --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/UnsafeValuesConfigListener.java @@ -0,0 +1,19 @@ +package com.seibel.distanthorizons.core.config.eventHandlers; + +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.config.listeners.IConfigListener; + +public class UnsafeValuesConfigListener implements IConfigListener { + public static UnsafeValuesConfigListener INSTANCE = new UnsafeValuesConfigListener(); + + @Override + public void onConfigValueSet() { + Config.Client.Advanced.Debugging.allowUnsafeValues.configBase.disableMinMax = + Config.Client.Advanced.Debugging.allowUnsafeValues.get(); + } + + @Override + public void onUiModify() { + + } +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java b/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java index 2f51a9571..270ecda4c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/file/ConfigFileHandling.java @@ -17,7 +17,7 @@ import java.nio.file.Path; * Handles reading and writing config files. * * @author coolGi - * @version 2022-9-9 + * @version 2023-7-16 */ public class ConfigFileHandling { private static final Logger LOGGER = ConfigBase.LOGGER; @@ -136,7 +136,7 @@ public class ConfigFileHandling { if (workConfig.contains(entry.getNameWCategory())) { try { if (entry.getType().isEnum()) { - entry.setWithoutSaving((T) ( workConfig.getEnum(entry.getNameWCategory(), (Class) entry.getType()) )); + entry.setWithoutSaving((T) ( workConfig.getEnum(entry.getNameWCategory(), (Class) entry.getType()))); return; } if (ConfigTypeConverters.convertObjects.containsKey(entry.getType())) { @@ -146,10 +146,7 @@ public class ConfigFileHandling { if (entry.getType() == workConfig.get(entry.getNameWCategory()).getClass()) { // If the types are the same entry.setWithoutSaving((T) workConfig.get(entry.getNameWCategory())); - - if (entry.isValid() == 0) return; - else if (entry.isValid() == -1) entry.setWithoutSaving(entry.getMin()); - else if (entry.isValid() == 1) entry.setWithoutSaving(entry.getMax()); + entry.clampWithinRange(); return; } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java index 6aa4b9d28..6cc64d209 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java @@ -1,6 +1,7 @@ package com.seibel.distanthorizons.core.config.types; +import com.seibel.distanthorizons.core.config.NumberUtil; import com.seibel.distanthorizons.core.config.listeners.IConfigListener; import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance; import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryPerformance; @@ -14,7 +15,7 @@ import java.util.Arrays; * for types that are not supported by it look in ConfigBase * * @author coolGi - * @version 2022-5-26 + * @version 2023-7-16 */ public class ConfigEntry extends AbstractConfigType> implements IConfigEntry { @@ -111,12 +112,30 @@ public class ConfigEntry extends AbstractConfigType> implem /** Sets the max value */ @Override public void setMax(T newMax) { this.max = newMax; } - /** Sets the min and max in 1 setter */ + /** Sets the min and max within a single setter */ @Override - public void setMinMax(T newMin, T newMax) - { - this.max = newMin; - this.min = newMax; + public void setMinMax(T newMin, T newMax) { + this.setMin(newMin); + this.setMax(newMax); + } + + /** + * Clamps the value within the set range + * @apiNote This does not save the value + */ + public void clampWithinRange() { this.clampWithinRange(this.min, this.max); } + /** + * Clamps the value within a set range + * + * @param min The minimum that the value can be + * @param max The maximum that the value can be + * @apiNote This does not save the value + */ + @SuppressWarnings("unchecked") // Suppress due to its always safe + public void clampWithinRange(T min, T max) { + byte validness = this.isValid(min, max); + if (validness == -1) this.value = (T) NumberUtil.getMinimum(this.value.getClass()); + if (validness == 1) this.value = (T) NumberUtil.getMaximum(this.value.getClass()); } @Override @@ -150,26 +169,50 @@ 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, this.min, this.max); } /** * Checks if a new value is valid * + * @param value Value that is being checked whether valid * @return 0 == valid *

2 == invalid *

1 == number too high *

-1 == number too low */ - @Override - public byte isValid(T value) { + @Override + public byte isValid(T value) { return this.isValid(value, this.min, this.max); } + /** + * Checks if a new value is valid + * + * @param min The minimum that the value can be + * @param max The maximum that the value can be + * @return 0 == valid + *

2 == invalid + *

1 == number too high + *

-1 == number too low + */ + public byte isValid(T min, T max) { return this.isValid(this.value, min, max); } + /** + * Checks if a new value is valid + * + * @param value Value that is being checked whether valid + * @param min The minimum that the value can be + * @param max The maximum that the value can be + * @return 0 == valid + *

2 == invalid + *

1 == number too high + *

-1 == number too low + */ + public byte isValid(T value, T min, T max) { if (this.configBase.disableMinMax) return 0; - if (value.getClass() != this.value.getClass()) // If the 2 variables aren't the same type then it will be invalid + if (value == null || this.value == null || value.getClass() != this.value.getClass()) // If the 2 variables aren't the same type then it will be invalid return 2; if (Number.class.isAssignableFrom(value.getClass())) { // Only check min max if it is a number - if (this.max != null && Float.parseFloat(value.toString()) > Float.parseFloat(max.toString())) + if (max != null && NumberUtil.greaterThan((Number) value, (Number) max)) return 1; - if (this.min != null && Float.parseFloat(value.toString()) < Float.parseFloat(min.toString())) + if (min != null && NumberUtil.lessThan((Number) value, (Number) min)) return -1; return 0;