From c5041de5d4e19cee4423bf85ceeb765b06ab8ff8 Mon Sep 17 00:00:00 2001 From: coolGi Date: Sun, 16 Jul 2023 23:07:14 +0930 Subject: [PATCH] Added proper clamping so values don't get out of range --- .../distanthorizons/core/config/Config.java | 4 +- .../core/config/NumberUtil.java | 38 +++++++++ .../core/config/file/ConfigFileHandling.java | 10 +-- .../core/config/types/ConfigEntry.java | 78 +++++++++++++++---- 4 files changed, 108 insertions(+), 22 deletions(-) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/config/NumberUtil.java 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..d76f23d19 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 @@ -51,7 +51,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 +456,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(); 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..9d63ce909 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/NumberUtil.java @@ -0,0 +1,38 @@ +package com.seibel.distanthorizons.core.config; + +import java.util.HashMap; +import java.util.Map; + +/** + * Gets the minimum or maximum values of a given type + * + * @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); + } +} 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..0cb1aaa2a 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,11 +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()); - return; + entry.clampWithinRange(); } LOGGER.warn("Entry ["+ entry.getNameWCategory() +"] is invalid. Expected " + entry.getType() + " but got " + workConfig.get(entry.getNameWCategory()).getClass() + ". Using default value."); 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..56f2953cb 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 { @@ -41,8 +42,7 @@ public class ConfigEntry extends AbstractConfigType> implem super(appearance, value); this.defaultValue = value; this.comment = comment; - this.min = min; - this.max = max; + this.setMinMax(min, max); this.allowApiOverride = allowApiOverride; this.performance = performance; this.listenerList = listenerList; @@ -104,19 +104,47 @@ public class ConfigEntry extends AbstractConfigType> implem public T getMin() { return this.min; } /** Sets the min value */ @Override - public void setMin(T newMin) { this.min = newMin; } + @SuppressWarnings("unchecked") // Suppress due to its always safe + public void setMin(T newMin) { + if (newMin == null) + newMin = (T) NumberUtil.getMinimum(newMin.getClass()); + this.min = newMin; + } /** Gets the max value */ @Override public T getMax() { return this.max; } /** Sets the max value */ @Override - public void setMax(T newMax) { this.max = newMax; } - /** Sets the min and max in 1 setter */ + @SuppressWarnings("unchecked") // Suppress due to its always safe + public void setMax(T newMax) { + if (newMax == null) + newMax = (T) NumberUtil.getMinimum(newMax.getClass()); + this.max = newMax; + } + /** 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(min.getClass()); + if (validness == 1) this.value = (T) NumberUtil.getMinimum(max.getClass()); } @Override @@ -150,17 +178,41 @@ 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;