Compare commits

..

7 Commits

Author SHA1 Message Date
James Seibel 9ddd917f3b remove dev from version number 2025-10-13 16:32:29 -05:00
James Seibel c5945b1254 remove unused EConfigEntryPerformance
It is a cool idea, but one that unfortunately never got implemented
2025-10-13 07:46:53 -05:00
James Seibel 9060579615 Fix world gen progress ui button 2025-10-13 07:42:46 -05:00
James Seibel 8f0217185f Improve config gui object casting 2025-10-13 07:33:27 -05:00
James Seibel 656971b0b9 typo fixing for major config refactoring 2025-10-12 21:10:18 -05:00
James Seibel 5fa3a11024 major config backend refactoring 2025-10-12 20:56:15 -05:00
James Seibel ed3d00bfce up version number 2.3.5 -> 2.3.6 2025-10-11 20:55:36 -05:00
40 changed files with 509 additions and 631 deletions
@@ -38,7 +38,7 @@ public final class ModInfo
public static final String NAME = "DistantHorizons"; public static final String NAME = "DistantHorizons";
/** Human-readable version of NAME */ /** Human-readable version of NAME */
public static final String READABLE_NAME = "Distant Horizons"; public static final String READABLE_NAME = "Distant Horizons";
public static final String VERSION = "2.3.5-b"; public static final String VERSION = "2.3.6-b";
/** Returns true if the current build is an unstable developer build, false otherwise. */ /** Returns true if the current build is an unstable developer build, false otherwise. */
public static final boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev"); public static final boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev");
@@ -1,86 +0,0 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.coreapi.interfaces.config;
import java.util.function.Consumer;
/**
* Use for making the config variables
*
* @author coolGi
* @version 2022-5-26
*/
public interface IConfigEntry<T>
{
/** Gets the default value of the option */
T getDefaultValue();
void setApiValue(T newApiValue);
T getApiValue();
/** @return true if this config is able to be overridden by the API and an API user has set it */
boolean apiIsOverriding();
/** Returns true if this config can be set via the API. */
boolean getAllowApiOverride();
void set(T newValue);
T get();
/** gets the option ignoring what the API has overridden */
T getTrueValue();
/** Sets the value without saving */
void setWithoutSaving(T newValue);
/** Gets the min value */
T getMin();
/** Sets the min value */
void setMin(T newMin);
/** Gets the max value */
T getMax();
/** Sets the max value */
void setMax(T newMax);
/** Sets the min and max in 1 setter */
void setMinMax(T newMin, T newMax);
/** Gets the comment */
String getComment();
/** Sets the comment */
void setComment(String newComment);
/**
* Checks if the option is valid
*
* 0 == valid
* 2 == invalid
* 1 == number too high
* -1 == number too low
*/
byte isValid(); // TODO replace with an enum
/** Checks if a value is valid */
byte isValid(T value);
/** Is the value of this equal to another */
boolean equals(IConfigEntry<?> obj);
void addValueChangeListener(Consumer<T> onValueChangeFunc);
}
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiAmbientOcclusionConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiAmbientOcclusionConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
public class DhApiAmbientOcclusionConfig implements IDhApiAmbientOcclusionConfig public class DhApiAmbientOcclusionConfig implements IDhApiAmbientOcclusionConfig
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiDebuggingConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiDebuggingConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiDebugRendering; import com.seibel.distanthorizons.api.enums.rendering.EDhApiDebugRendering;
@@ -22,7 +22,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogFalloff; import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogFalloff;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiFarFogConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiFarFogConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
public class DhApiFarFogConfig implements IDhApiFarFogConfig public class DhApiFarFogConfig implements IDhApiFarFogConfig
@@ -25,9 +25,9 @@ import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiFarFogConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiFarFogConfig;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiFogConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiFogConfig;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiHeightFogConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiHeightFogConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.coreapi.util.converters.ApiFogDrawModeConverter; import com.seibel.distanthorizons.core.config.api.converters.ApiFogDrawModeConverter;
public class DhApiFogConfig implements IDhApiFogConfig public class DhApiFogConfig implements IDhApiFogConfig
{ {
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGenericRenderingConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGenericRenderingConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
public class DhApiGenericRenderingConfig implements IDhApiGenericRenderingConfig public class DhApiGenericRenderingConfig implements IDhApiGenericRenderingConfig
@@ -23,10 +23,10 @@ import com.seibel.distanthorizons.api.enums.config.*;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency; import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.*; import com.seibel.distanthorizons.api.interfaces.config.client.*;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode; import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.coreapi.util.converters.RenderModeEnabledConverter; import com.seibel.distanthorizons.core.config.api.converters.RenderModeEnabledConverter;
public class DhApiGraphicsConfig implements IDhApiGraphicsConfig public class DhApiGraphicsConfig implements IDhApiGraphicsConfig
{ {
@@ -24,7 +24,7 @@ import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogMixMode;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogDirection; import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogDirection;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiHeightFogConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiHeightFogConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
public class DhApiHeightFogConfig implements IDhApiHeightFogConfig public class DhApiHeightFogConfig implements IDhApiHeightFogConfig
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiMultiThreadingConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiMultiThreadingConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
public class DhApiMultiThreadingConfig implements IDhApiMultiThreadingConfig public class DhApiMultiThreadingConfig implements IDhApiMultiThreadingConfig
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiMultiplayerConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiMultiplayerConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.api.enums.config.EDhApiServerFolderNameMode; import com.seibel.distanthorizons.api.enums.config.EDhApiServerFolderNameMode;
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiNoiseTextureConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiNoiseTextureConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
public class DhApiNoiseTextureConfig implements IDhApiNoiseTextureConfig public class DhApiNoiseTextureConfig implements IDhApiNoiseTextureConfig
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.common;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.both.IDhApiWorldGenerationConfig; import com.seibel.distanthorizons.api.interfaces.config.both.IDhApiWorldGenerationConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.core.config.api.DhApiConfigValue;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
@@ -1,54 +0,0 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.core.config;
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
// TODO: Make this integrate with the config system
public class AppliedConfigState<T>
{
final ConfigEntry<T> entry;
T activeValue;
public AppliedConfigState(ConfigEntry<T> entryToWatch)
{
this.entry = entryToWatch;
this.activeValue = entryToWatch.get();
}
/** Returns true if the value was changed */
public boolean pollNewValue()
{
T newValue = this.entry.get();
if (newValue.equals(this.activeValue))
{
return false;
}
this.activeValue = newValue;
return true;
}
public T get() { return this.activeValue; }
}
@@ -45,14 +45,11 @@ import java.util.*;
import java.util.List; import java.util.List;
/** /**
* This handles any configuration the user has access to. <br><br> * This handles any configuration the user has access to.
*
* Note: <br>
* Only add simpler listeners here (IE listeners that only depend on 1 config entry).
* For listeners that depend on 2 or more config entries, add them before the config menu is opened.
* Otherwise, you will have issues where only some of the config entries will exist when your listener is created.
* *
* @author coolGi * @author coolGi
*
* @see ConfigHandler
*/ */
@SuppressWarnings("ConcatenationWithEmptyString") @SuppressWarnings("ConcatenationWithEmptyString")
public class Config public class Config
@@ -107,7 +104,7 @@ public class Config
public static ConfigUiLinkedEntry quickEnableWorldGenerator = new ConfigUiLinkedEntry(Common.WorldGenerator.enableDistantGeneration); public static ConfigUiLinkedEntry quickEnableWorldGenerator = new ConfigUiLinkedEntry(Common.WorldGenerator.enableDistantGeneration);
public static ConfigEntry<Boolean> quickShowWorldGenProgress = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> quickShowWorldGenProgress = new ConfigEntry.Builder<Boolean>()
.set(true) .set(false) // TODO should be set by the underlying world gen progress button, not a static default
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.build(); .build();
@@ -188,7 +185,6 @@ public class Config
.comment("" + .comment("" +
"The radius of the mod's render distance. (measured in chunks)\n" + "The radius of the mod's render distance. (measured in chunks)\n" +
"") "")
.setPerformance(EConfigEntryPerformance.HIGH)
.build(); .build();
public static ConfigEntry<EDhApiHorizontalQuality> horizontalQuality = new ConfigEntry.Builder<EDhApiHorizontalQuality>() public static ConfigEntry<EDhApiHorizontalQuality> horizontalQuality = new ConfigEntry.Builder<EDhApiHorizontalQuality>()
@@ -197,7 +193,6 @@ public class Config
+ "This indicates how quickly LODs decrease in quality the further away they are. \n" + "This indicates how quickly LODs decrease in quality the further away they are. \n"
+ "Higher settings will render higher quality fake chunks farther away, \n" + "Higher settings will render higher quality fake chunks farther away, \n"
+ "but will increase memory and GPU usage.") + "but will increase memory and GPU usage.")
.setPerformance(EConfigEntryPerformance.MEDIUM)
.build(); .build();
public static ConfigEntry<EDhApiMaxHorizontalResolution> maxHorizontalResolution = new ConfigEntry.Builder<EDhApiMaxHorizontalResolution>() public static ConfigEntry<EDhApiMaxHorizontalResolution> maxHorizontalResolution = new ConfigEntry.Builder<EDhApiMaxHorizontalResolution>()
@@ -214,7 +209,6 @@ public class Config
+ "\n" + "\n"
+ "Lowest Quality: " + EDhApiMaxHorizontalResolution.CHUNK + "\n" + "Lowest Quality: " + EDhApiMaxHorizontalResolution.CHUNK + "\n"
+ "Highest Quality: " + EDhApiMaxHorizontalResolution.BLOCK) + "Highest Quality: " + EDhApiMaxHorizontalResolution.BLOCK)
.setPerformance(EConfigEntryPerformance.MEDIUM)
.addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE)
.build(); .build();
@@ -228,7 +222,6 @@ public class Config
+ "\n" + "\n"
+ "Lowest Quality: " + EDhApiVerticalQuality.HEIGHT_MAP + "\n" + "Lowest Quality: " + EDhApiVerticalQuality.HEIGHT_MAP + "\n"
+ "Highest Quality: " + EDhApiVerticalQuality.EXTREME) + "Highest Quality: " + EDhApiVerticalQuality.EXTREME)
.setPerformance(EConfigEntryPerformance.VERY_HIGH)
.addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE)
.build(); .build();
@@ -241,7 +234,6 @@ public class Config
+ EDhApiTransparency.FAKE + ": LODs will be opaque, but shaded to match the blocks underneath. \n" + EDhApiTransparency.FAKE + ": LODs will be opaque, but shaded to match the blocks underneath. \n"
+ EDhApiTransparency.DISABLED + ": LODs will be opaque. \n" + EDhApiTransparency.DISABLED + ": LODs will be opaque. \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.MEDIUM)
.addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE)
.build(); .build();
@@ -253,7 +245,6 @@ public class Config
+ EDhApiBlocksToAvoid.NONE + ": Represent all blocks in the LODs \n" + EDhApiBlocksToAvoid.NONE + ": Represent all blocks in the LODs \n"
+ EDhApiBlocksToAvoid.NON_COLLIDING + ": Only represent solid blocks in the LODs (tall grass, torches, etc. won't count for a LOD's height) \n" + EDhApiBlocksToAvoid.NON_COLLIDING + ": Only represent solid blocks in the LODs (tall grass, torches, etc. won't count for a LOD's height) \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.NONE)
.addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE)
.build(); .build();
@@ -265,7 +256,6 @@ public class Config
+ "True: a red flower will tint the grass below it red. \n" + "True: a red flower will tint the grass below it red. \n"
+ "False: skipped blocks will not change color of surface below them. " + "False: skipped blocks will not change color of surface below them. "
+ "") + "")
.setPerformance(EConfigEntryPerformance.NONE)
.addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE)
.build(); .build();
@@ -286,7 +276,6 @@ public class Config
+ " Can be used to force LOD shading when using some shaders. \n" + " Can be used to force LOD shading when using some shaders. \n"
+ EDhApiLodShading.DISABLED + ": All LOD sides will be rendered with the same brightness. \n" + EDhApiLodShading.DISABLED + ": All LOD sides will be rendered with the same brightness. \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.NONE)
.addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE)
.build(); .build();
@@ -299,7 +288,6 @@ public class Config
+ EDhApiGrassSideRendering.FADE_TO_DIRT + ": sides fade from grass to dirt. \n" + EDhApiGrassSideRendering.FADE_TO_DIRT + ": sides fade from grass to dirt. \n"
+ EDhApiGrassSideRendering.AS_DIRT + ": sides render entirely as dirt. \n" + EDhApiGrassSideRendering.AS_DIRT + ": sides render entirely as dirt. \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.NONE)
.addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE) .addListener(ReloadLodsConfigEventHandler.DELAYED_INSTANCE)
.build(); .build();
@@ -310,7 +298,6 @@ public class Config
+ "If false LODs will cut off abruptly at a set distance from the camera. \n" + "If false LODs will cut off abruptly at a set distance from the camera. \n"
+ "This setting is affected by the vanilla overdraw prevention config. \n" + "This setting is affected by the vanilla overdraw prevention config. \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.LOW)
.build(); .build();
public static ConfigEntry<EDhApiMcRenderingFadeMode> vanillaFadeMode = new ConfigEntry.Builder<EDhApiMcRenderingFadeMode>() public static ConfigEntry<EDhApiMcRenderingFadeMode> vanillaFadeMode = new ConfigEntry.Builder<EDhApiMcRenderingFadeMode>()
@@ -322,7 +309,6 @@ public class Config
+ EDhApiMcRenderingFadeMode.SINGLE_PASS + ": Fades after MC's transparent pass, opaque blocks underwater won't be faded. \n" + EDhApiMcRenderingFadeMode.SINGLE_PASS + ": Fades after MC's transparent pass, opaque blocks underwater won't be faded. \n"
+ EDhApiMcRenderingFadeMode.DOUBLE_PASS + ": Slowest, fades after both MC's opaque and transparent passes, provides the smoothest transition. \n" + EDhApiMcRenderingFadeMode.DOUBLE_PASS + ": Slowest, fades after both MC's opaque and transparent passes, provides the smoothest transition. \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.LOW)
.build(); .build();
public static ConfigEntry<Double> brightnessMultiplier = new ConfigEntry.Builder<Double>() // TODO: Make this a float (the ClassicConfigGUI doesnt support floats) public static ConfigEntry<Double> brightnessMultiplier = new ConfigEntry.Builder<Double>() // TODO: Make this a float (the ClassicConfigGUI doesnt support floats)
@@ -367,7 +353,6 @@ public class Config
public static ConfigEntry<Boolean> enableSsao = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> enableSsao = new ConfigEntry.Builder<Boolean>()
.set(true) .set(true)
.comment("Enable Screen Space Ambient Occlusion") .comment("Enable Screen Space Ambient Occlusion")
.setPerformance(EConfigEntryPerformance.MEDIUM)
.build(); .build();
public static ConfigEntry<Integer> sampleCount = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> sampleCount = new ConfigEntry.Builder<Integer>()
@@ -376,7 +361,6 @@ public class Config
"Determines how many points in space are sampled for the occlusion test. \n" + "Determines how many points in space are sampled for the occlusion test. \n" +
"Higher numbers will improve quality and reduce banding, but will increase GPU load." + "Higher numbers will improve quality and reduce banding, but will increase GPU load." +
"") "")
.setPerformance(EConfigEntryPerformance.MEDIUM)
.build(); .build();
public static ConfigEntry<Double> radius = new ConfigEntry.Builder<Double>() public static ConfigEntry<Double> radius = new ConfigEntry.Builder<Double>()
@@ -384,7 +368,6 @@ public class Config
.comment("" + .comment("" +
"Determines the radius Screen Space Ambient Occlusion is applied, measured in blocks." + "Determines the radius Screen Space Ambient Occlusion is applied, measured in blocks." +
"") "")
.setPerformance(EConfigEntryPerformance.NONE)
.build(); .build();
public static ConfigEntry<Double> strength = new ConfigEntry.Builder<Double>() public static ConfigEntry<Double> strength = new ConfigEntry.Builder<Double>()
@@ -392,7 +375,6 @@ public class Config
.comment("" + .comment("" +
"Determines how dark the Screen Space Ambient Occlusion effect will be." + "Determines how dark the Screen Space Ambient Occlusion effect will be." +
"") "")
.setPerformance(EConfigEntryPerformance.NONE)
.build(); .build();
public static ConfigEntry<Double> bias = new ConfigEntry.Builder<Double>() public static ConfigEntry<Double> bias = new ConfigEntry.Builder<Double>()
@@ -400,7 +382,6 @@ public class Config
.comment("" + .comment("" +
"Increasing the value can reduce banding at the cost of reducing the strength of the effect." + "Increasing the value can reduce banding at the cost of reducing the strength of the effect." +
"") "")
.setPerformance(EConfigEntryPerformance.NONE)
.build(); .build();
public static ConfigEntry<Double> minLight = new ConfigEntry.Builder<Double>() public static ConfigEntry<Double> minLight = new ConfigEntry.Builder<Double>()
@@ -410,7 +391,6 @@ public class Config
"0 = totally black at the corners \n" + "0 = totally black at the corners \n" +
"1 = no shadow" + "1 = no shadow" +
"") "")
.setPerformance(EConfigEntryPerformance.NONE)
.build(); .build();
public static ConfigEntry<Integer> blurRadius = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> blurRadius = new ConfigEntry.Builder<Integer>()
@@ -419,7 +399,6 @@ public class Config
"The radius, measured in pixels, that blurring is calculated for the SSAO. \n" + "The radius, measured in pixels, that blurring is calculated for the SSAO. \n" +
"Higher numbers will reduce banding at the cost of GPU performance." + "Higher numbers will reduce banding at the cost of GPU performance." +
"") "")
.setPerformance(EConfigEntryPerformance.HIGH)
.build(); .build();
} }
@@ -482,7 +461,6 @@ public class Config
.comment("" .comment(""
+ "Determines if fog is drawn on DH LODs. \n" + "Determines if fog is drawn on DH LODs. \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.MEDIUM)
.build(); .build();
public static ConfigEntry<EDhApiFogColorMode> colorMode = new ConfigEntry.Builder<EDhApiFogColorMode>() public static ConfigEntry<EDhApiFogColorMode> colorMode = new ConfigEntry.Builder<EDhApiFogColorMode>()
@@ -492,7 +470,6 @@ public class Config
+ "\n" + "\n"
+ EDhApiFogColorMode.USE_WORLD_FOG_COLOR + ": Use the world's fog color. \n" + EDhApiFogColorMode.USE_WORLD_FOG_COLOR + ": Use the world's fog color. \n"
+ EDhApiFogColorMode.USE_SKY_COLOR + ": Use the sky's color.") + EDhApiFogColorMode.USE_SKY_COLOR + ": Use the sky's color.")
.setPerformance(EConfigEntryPerformance.NONE)
.build(); .build();
public static ConfigEntry<Boolean> enableVanillaFog = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> enableVanillaFog = new ConfigEntry.Builder<Boolean>()
@@ -727,12 +704,10 @@ public class Config
+ "\n" + "\n"
+ "Increasing the vanilla render distance increases the effectiveness of this setting." + "Increasing the vanilla render distance increases the effectiveness of this setting."
+ "") + "")
.setPerformance(EConfigEntryPerformance.NONE)
.build(); .build();
public static ConfigEntry<Boolean> enableCaveCulling = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> enableCaveCulling = new ConfigEntry.Builder<Boolean>()
.set(true) .set(true)
.setPerformance(EConfigEntryPerformance.HIGH)
.comment("" .comment(""
+ "If enabled caves won't be rendered. \n" + "If enabled caves won't be rendered. \n"
+ "\n" + "\n"
@@ -1701,7 +1676,6 @@ public class Config
.comment("" + .comment("" +
"Defines the distance allowed to generate around the player." + "Defines the distance allowed to generate around the player." +
"") "")
.setPerformance(EConfigEntryPerformance.HIGH)
.build(); .build();
public static ConfigEntry<Integer> generationBoundsX = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> generationBoundsX = new ConfigEntry.Builder<Integer>()
@@ -1746,7 +1720,6 @@ public class Config
.comment("" + .comment("" +
"Defines the distance the player will receive updates around." + "Defines the distance the player will receive updates around." +
"") "")
.setPerformance(EConfigEntryPerformance.HIGH)
.build(); .build();
@@ -1775,7 +1748,6 @@ public class Config
"Defines the distance allowed to be synchronized around the player. \n" + "Defines the distance allowed to be synchronized around the player. \n" +
"Should be the same or larger than maxGenerationRequestDistance in most cases." + "Should be the same or larger than maxGenerationRequestDistance in most cases." +
"") "")
.setPerformance(EConfigEntryPerformance.HIGH)
.build(); .build();
@@ -1849,7 +1821,6 @@ public class Config
try try
{ {
// TODO automatically get all instances of AbstractPresetConfigEventHandler and fire "setUiOnlyConfigValues"
ThreadPresetConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); ThreadPresetConfigEventHandler.INSTANCE.setUiOnlyConfigValues();
RenderQualityPresetConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); RenderQualityPresetConfigEventHandler.INSTANCE.setUiOnlyConfigValues();
QuickRenderToggleConfigEventHandler.INSTANCE.setUiOnlyConfigValues(); QuickRenderToggleConfigEventHandler.INSTANCE.setUiOnlyConfigValues();
@@ -26,29 +26,28 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
/** /**
* Indexes and sets everything up for the file handling and gui. * Sets up everything in {@link Config} for the file/GUI and keeps track of all
* This should be init after singletons have been bound * entries therein. <br>
* This should be run after the singletons have been bound.
* *
* @author coolGi * @author coolGi
* @author Ran * @author Ran
* @version 2023-8-26 *
* @see Config
*/ */
public class ConfigBase public class ConfigHandler
{ {
/** Our own config instance, don't modify unless you are the DH mod */
public static ConfigBase INSTANCE;
private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private static final IMinecraftSharedWrapper MC_SHARED = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class);
/** /**
* What the config works with * What the config works with
* <br> * <br>
@@ -69,7 +68,7 @@ public class ConfigBase
* <br> Map<String, T> * <br> Map<String, T>
* <br> HashMap<String, T> * <br> HashMap<String, T>
*/ */
public static final List<Class<?>> ACCEPTABLE_INPUTS = new ArrayList<Class<?>>() private static final List<Class<?>> ACCEPTABLE_INPUTS = new ArrayList<Class<?>>()
{{ {{
this.add(Boolean.class); this.add(Boolean.class);
this.add(Byte.class); this.add(Byte.class);
@@ -80,7 +79,7 @@ public class ConfigBase
this.add(Float.class); this.add(Float.class);
this.add(String.class); this.add(String.class);
// TODO[CONFIG]: Check the type of these is valid // partially implemented but not entirely
this.add(List.class); this.add(List.class);
this.add(ArrayList.class); this.add(ArrayList.class);
this.add(Map.class); this.add(Map.class);
@@ -89,15 +88,17 @@ public class ConfigBase
public ConfigFileHandler configFileHandler; public static final ConfigHandler INSTANCE = new ConfigHandler();
public final int configVersion; public final ConfigFileHandler configFileHandler = new ConfigFileHandler(getConfigPath());
public final List<AbstractConfigBase<?>> configBaseList = new ArrayList<>();
public boolean isLoaded = false; public boolean isLoaded = false;
/**
/** Disables the minimum and maximum of any variable */ * Disables the minimum and maximum validation. <Br>
public boolean disableMinMax = false; // Very fun to use, but should always be disabled by default * Fun to use, but should be disabled by default.
public final List<AbstractConfigType<?, ?>> entries = new ArrayList<>(); */
public boolean runMinMaxValidation = true;
@@ -105,92 +106,103 @@ public class ConfigBase
// constructor // // constructor //
//=============// //=============//
public static void RunFirstTimeSetup() public static void tryRunFirstTimeSetup()
{ {
if (INSTANCE != null) if (INSTANCE.isLoaded)
{ {
LOGGER.debug("ConfigBase setup already run, ignoring."); LOGGER.debug("ConfigHandler setup already run, ignoring.");
return; return;
} }
INSTANCE = new ConfigBase(Config.class, ModInfo.CONFIG_FILE_VERSION); INSTANCE.runFirstTimeSetup();
} }
private void runFirstTimeSetup()
private ConfigBase(Class<?> configClass, int configVersion)
{ {
LOGGER.info("Initialising config for [" + ModInfo.NAME + "]"); LOGGER.info("Initialising config for [" + ModInfo.NAME + "]");
this.configVersion = configVersion; this.initNestedClass(Config.class, ""); // Init root category
this.initNestedClass(configClass, ""); // Init root category
Path configPath = getConfigPath(ModInfo.NAME);
this.configFileHandler = new ConfigFileHandler(this, configPath);
this.configFileHandler.loadFromFile(); this.configFileHandler.loadFromFile();
this.isLoaded = true; this.isLoaded = true;
LOGGER.info("Config for [" + ModInfo.NAME + "] initialised"); LOGGER.info("[" + ModInfo.NAME + "] Config initialised");
} }
/** Gets the default config path given a mod name */ /** Gets the default config path given a mod name */
private static Path getConfigPath(String modName) private static Path getConfigPath()
{ {
return SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class) return MC_SHARED
.getInstallationDirectory().toPath().resolve("config").resolve(modName + ".toml"); .getInstallationDirectory().toPath()
.resolve("config")
.resolve(ModInfo.NAME + ".toml");
} }
/** Put all the config entries into configEntryList */
private void initNestedClass(Class<?> configClass, String category) private void initNestedClass(Class<?> configClass, String category)
{ {
// Put all the entries in entries Field[] fields = configClass.getFields();
for (Field field : fields)
for (Field field : configClass.getFields())
{ {
if (AbstractConfigType.class.isAssignableFrom(field.getType())) // ignore any non-config variables
if (!AbstractConfigBase.class.isAssignableFrom(field.getType()))
{ {
try continue;
}
// add this config to the master list
try
{
this.configBaseList.add((AbstractConfigBase<?>) field.get(field.getType()));
}
catch (IllegalAccessException e)
{
LOGGER.warn("Unable to add config ["+field.getType().getName()+"], error: ["+e.getMessage()+"].", e);
continue;
}
// set any necessary variables in this config
AbstractConfigBase<?> configBase = this.configBaseList.get(this.configBaseList.size() - 1);
configBase.category = category;
configBase.name = field.getName();
// validate the config's input type
if (ConfigEntry.class.isAssignableFrom(field.getType()))
{
if (!isAcceptableType(configBase.getType()))
{ {
this.entries.add((AbstractConfigType<?, ?>) field.get(field.getType())); LOGGER.error("Invalid variable type at [" + (category.isEmpty() ? "" : category + ".") + field.getName() + "].");
LOGGER.error("Type [" + configBase.getType() + "] is not one of these types [" + ACCEPTABLE_INPUTS.toString() + "]");
this.configBaseList.remove(this.configBaseList.size() - 1); // Delete the entry if it is invalid so the game can still run
} }
catch (IllegalAccessException exception) }
// recursively add deeper categories if present
if (ConfigCategory.class.isAssignableFrom(field.getType()))
{
ConfigCategory configCategory = (ConfigCategory) configBase;
if (configCategory.getDestination() == null)
{ {
LOGGER.warn(exception); configCategory.destination = configBase.getNameAndCategory();
} }
AbstractConfigType<?, ?> entry = this.entries.get(this.entries.size() - 1); // shouldn't happen, but just in case
entry.category = category; if (configBase.get() != null)
entry.name = field.getName(); {
entry.configBase = this; this.initNestedClass(configCategory.get(), configCategory.getDestination());
if (ConfigEntry.class.isAssignableFrom(field.getType()))
{
// If item is type ConfigEntry
if (!isAcceptableType(entry.getType()))
{
LOGGER.error("Invalid variable type at [" + (category.isEmpty() ? "" : category + ".") + field.getName() + "].");
LOGGER.error("Type [" + entry.getType() + "] is not one of these types [" + ACCEPTABLE_INPUTS.toString() + "]");
this.entries.remove(this.entries.size() - 1); // Delete the entry if it is invalid so the game can still run
}
}
if (ConfigCategory.class.isAssignableFrom(field.getType()))
{ // If it's a category then init the stuff inside it and put it in the category list
assert entry instanceof ConfigCategory;
if (((ConfigCategory) entry).getDestination() == null)
((ConfigCategory) entry).destination = entry.getNameWCategory();
if (entry.get() != null)
{
this.initNestedClass(((ConfigCategory) entry).get(), ((ConfigCategory) entry).getDestination());
}
} }
} }
} }
} }
private static boolean isAcceptableType(Class<?> Clazz) private static boolean isAcceptableType(Class<?> inputClass)
{ {
if (Clazz.isEnum()) if (inputClass.isEnum())
{ {
return true; return true;
} }
return ACCEPTABLE_INPUTS.contains(Clazz); return ACCEPTABLE_INPUTS.contains(inputClass);
} }
@@ -219,9 +231,9 @@ public class ConfigBase
String ending = "\",\n"; String ending = "\",\n";
// config entries // config entries
for (AbstractConfigType<?, ?> entry : this.entries) for (AbstractConfigBase<?> entry : this.configBaseList)
{ {
String entryPrefix = "distanthorizons.config." + entry.getNameWCategory(); String entryPrefix = "distanthorizons.config." + entry.getNameAndCategory();
if (checkEnums if (checkEnums
&& entry.getType().isEnum() && entry.getType().isEnum()
@@ -24,7 +24,7 @@ import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
public class ConfigEntryWithPresetOptions<TQuickEnum, TConfig> public class ConfigPresetOptions<TQuickEnum, TConfig>
{ {
public final ConfigEntry<TConfig> configEntry; public final ConfigEntry<TConfig> configEntry;
@@ -32,7 +32,11 @@ public class ConfigEntryWithPresetOptions<TQuickEnum, TConfig>
public ConfigEntryWithPresetOptions(ConfigEntry<TConfig> configEntry, HashMap<TQuickEnum, TConfig> configOptionByQualityOption) //=============//
// constructor //
//=============//
public ConfigPresetOptions(ConfigEntry<TConfig> configEntry, HashMap<TQuickEnum, TConfig> configOptionByQualityOption)
{ {
this.configEntry = configEntry; this.configEntry = configEntry;
this.configOptionByQualityOption = configOptionByQualityOption; this.configOptionByQualityOption = configOptionByQualityOption;
@@ -40,6 +44,10 @@ public class ConfigEntryWithPresetOptions<TQuickEnum, TConfig>
//=========//
// methods //
//=========//
public void updateConfigEntry(TQuickEnum quickQuality) public void updateConfigEntry(TQuickEnum quickQuality)
{ {
TConfig newValue = this.configOptionByQualityOption.get(quickQuality); TConfig newValue = this.configOptionByQualityOption.get(quickQuality);
@@ -17,12 +17,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.seibel.distanthorizons.api.objects.config; package com.seibel.distanthorizons.core.config.api;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConfigEntry; import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConverter; import com.seibel.distanthorizons.coreapi.interfaces.config.IConverter;
import com.seibel.distanthorizons.coreapi.util.converters.DefaultConverter; import com.seibel.distanthorizons.core.config.api.converters.DefaultConverter;
import java.util.function.Consumer; import java.util.function.Consumer;
@@ -41,7 +41,7 @@ import java.util.function.Consumer;
*/ */
public class DhApiConfigValue<coreType, apiType> implements IDhApiConfigValue<apiType> public class DhApiConfigValue<coreType, apiType> implements IDhApiConfigValue<apiType>
{ {
private final IConfigEntry<coreType> configEntry; private final ConfigEntry<coreType> configBase;
private final IConverter<coreType, apiType> configConverter; private final IConverter<coreType, apiType> configConverter;
@@ -53,9 +53,9 @@ public class DhApiConfigValue<coreType, apiType> implements IDhApiConfigValue<ap
* Uses the default object converter, this requires coreType and apiType to be the same. * Uses the default object converter, this requires coreType and apiType to be the same.
*/ */
@SuppressWarnings("unchecked") // DefaultConverter's cast is safe @SuppressWarnings("unchecked") // DefaultConverter's cast is safe
public DhApiConfigValue(IConfigEntry<coreType> newConfigEntry) public DhApiConfigValue(ConfigEntry<coreType> configBase)
{ {
this.configEntry = newConfigEntry; this.configBase = configBase;
this.configConverter = (IConverter<coreType, apiType>) new DefaultConverter<coreType>(); this.configConverter = (IConverter<coreType, apiType>) new DefaultConverter<coreType>();
} }
@@ -63,22 +63,22 @@ public class DhApiConfigValue<coreType, apiType> implements IDhApiConfigValue<ap
* This constructor should only be called internally. <br> * This constructor should only be called internally. <br>
* There is no reason for API users to create this object. <br><br> * There is no reason for API users to create this object. <br><br>
*/ */
public DhApiConfigValue(IConfigEntry<coreType> newConfigEntry, IConverter<coreType, apiType> newConverter) public DhApiConfigValue(ConfigEntry<coreType> configBase, IConverter<coreType, apiType> newConverter)
{ {
this.configEntry = newConfigEntry; this.configBase = configBase;
this.configConverter = newConverter; this.configConverter = newConverter;
} }
public apiType getValue() { return this.configConverter.convertToApiType(this.configEntry.get()); } public apiType getValue() { return this.configConverter.convertToApiType(this.configBase.get()); }
public apiType getTrueValue() { return this.configConverter.convertToApiType(this.configEntry.getTrueValue()); } public apiType getTrueValue() { return this.configConverter.convertToApiType(this.configBase.getTrueValue()); }
public apiType getApiValue() { return this.configConverter.convertToApiType(this.configEntry.getApiValue()); } public apiType getApiValue() { return this.configConverter.convertToApiType(this.configBase.getApiValue()); }
public boolean setValue(apiType newValue) public boolean setValue(apiType newValue)
{ {
if (this.configEntry.getAllowApiOverride()) if (this.configBase.getAllowApiOverride())
{ {
this.configEntry.setApiValue(this.configConverter.convertToCoreType(newValue)); this.configBase.setApiValue(this.configConverter.convertToCoreType(newValue));
return true; return true;
} }
else else
@@ -89,11 +89,11 @@ public class DhApiConfigValue<coreType, apiType> implements IDhApiConfigValue<ap
public boolean clearValue() public boolean clearValue()
{ {
if (this.configEntry.getAllowApiOverride()) if (this.configBase.getAllowApiOverride())
{ {
// no converter should be used here since null objects may need to be handled differently // no converter should be used here since null objects may need to be handled differently
// TODO the API should just have a bool to keep track of whether the API value is in use instead of using NULL // TODO the API should just have a bool to keep track of whether the API value is in use instead of using NULL
this.configEntry.setApiValue(null); this.configBase.setApiValue(null);
return true; return true;
} }
else else
@@ -102,16 +102,16 @@ public class DhApiConfigValue<coreType, apiType> implements IDhApiConfigValue<ap
} }
} }
public boolean getCanBeOverrodeByApi() { return this.configEntry.getAllowApiOverride(); } public boolean getCanBeOverrodeByApi() { return this.configBase.getAllowApiOverride(); }
public apiType getDefaultValue() { return this.configConverter.convertToApiType(this.configEntry.getDefaultValue()); } public apiType getDefaultValue() { return this.configConverter.convertToApiType(this.configBase.getDefaultValue()); }
public apiType getMaxValue() { return this.configConverter.convertToApiType(this.configEntry.getMax()); } public apiType getMaxValue() { return this.configConverter.convertToApiType(this.configBase.getMax()); }
public apiType getMinValue() { return this.configConverter.convertToApiType(this.configEntry.getMin()); } public apiType getMinValue() { return this.configConverter.convertToApiType(this.configBase.getMin()); }
public void addChangeListener(Consumer<apiType> onValueChangeFunc) public void addChangeListener(Consumer<apiType> onValueChangeFunc)
{ {
this.configEntry.addValueChangeListener((coreValue) -> this.configBase.addValueChangeListener((coreValue) ->
{ {
apiType apiValue = this.configConverter.convertToApiType(coreValue); apiType apiValue = this.configConverter.convertToApiType(coreValue);
onValueChangeFunc.accept(apiValue); onValueChangeFunc.accept(apiValue);
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.seibel.distanthorizons.coreapi.util.converters; package com.seibel.distanthorizons.core.config.api.converters;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogDrawMode; import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogDrawMode;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConverter; import com.seibel.distanthorizons.coreapi.interfaces.config.IConverter;
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.seibel.distanthorizons.coreapi.util.converters; package com.seibel.distanthorizons.core.config.api.converters;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConverter; import com.seibel.distanthorizons.coreapi.interfaces.config.IConverter;
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.seibel.distanthorizons.coreapi.util.converters; package com.seibel.distanthorizons.core.config.api.converters;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode; import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConverter; import com.seibel.distanthorizons.coreapi.interfaces.config.IConverter;
@@ -20,23 +20,22 @@
package com.seibel.distanthorizons.core.config.eventHandlers; package com.seibel.distanthorizons.core.config.eventHandlers;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.config.listeners.IConfigListener; import com.seibel.distanthorizons.core.config.listeners.IConfigListener;
/**
* handles enabling/disabling config validation when the
* {@link Config.Client.Advanced.Debugging#allowUnsafeValues} option
* is changed.
*/
public class UnsafeValuesConfigListener implements IConfigListener public class UnsafeValuesConfigListener implements IConfigListener
{ {
public static UnsafeValuesConfigListener INSTANCE = new UnsafeValuesConfigListener(); public static UnsafeValuesConfigListener INSTANCE = new UnsafeValuesConfigListener();
@Override @Override
public void onConfigValueSet() public void onConfigValueSet()
{ { ConfigHandler.INSTANCE.runMinMaxValidation = !Config.Client.Advanced.Debugging.allowUnsafeValues.get(); }
Config.Client.Advanced.Debugging.allowUnsafeValues.configBase.disableMinMax =
Config.Client.Advanced.Debugging.allowUnsafeValues.get();
}
@Override
public void onUiModify()
{
}
} }
@@ -19,13 +19,13 @@
package com.seibel.distanthorizons.core.config.eventHandlers.presets; package com.seibel.distanthorizons.core.config.eventHandlers.presets;
import com.seibel.distanthorizons.core.config.ConfigBase; import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.config.ConfigEntryWithPresetOptions; import com.seibel.distanthorizons.core.config.ConfigPresetOptions;
import com.seibel.distanthorizons.core.config.listeners.IConfigListener; import com.seibel.distanthorizons.core.config.listeners.IConfigListener;
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.util.TimerUtil; import com.seibel.distanthorizons.core.util.TimerUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui; import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConfigEntry;
import com.seibel.distanthorizons.coreapi.util.StringUtil; import com.seibel.distanthorizons.coreapi.util.StringUtil;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -39,10 +39,9 @@ public abstract class AbstractPresetConfigEventHandler<TPresetEnum extends Enum<
private static final long MS_DELAY_BEFORE_APPLYING_PRESET = 3_000; private static final long MS_DELAY_BEFORE_APPLYING_PRESET = 3_000;
@Nullable @Nullable
private static IConfigGui configGui = SingletonInjector.INSTANCE.get(IConfigGui.class); private static final IConfigGui CONFIG_GUI = SingletonInjector.INSTANCE.get(IConfigGui.class);
private static boolean guiListenersAdded = false;
protected final ArrayList<ConfigEntryWithPresetOptions<TPresetEnum, ?>> configList = new ArrayList<>(); protected final ArrayList<ConfigPresetOptions<TPresetEnum, ?>> configList = new ArrayList<>();
/** this timer is used so each preset isn't applied while a user is clicking through the config options */ /** this timer is used so each preset isn't applied while a user is clicking through the config options */
protected Timer applyPresetTimer = null; protected Timer applyPresetTimer = null;
/** the enum to apply after the timer expires or the UI screen changes. */ /** the enum to apply after the timer expires or the UI screen changes. */
@@ -59,9 +58,9 @@ public abstract class AbstractPresetConfigEventHandler<TPresetEnum extends Enum<
public AbstractPresetConfigEventHandler() public AbstractPresetConfigEventHandler()
{ {
// don't update the UI when running on a server // don't update the UI when running on a server
if (configGui != null) if (CONFIG_GUI != null)
{ {
configGui.addOnScreenChangeListener(this::onConfigUiClosed); CONFIG_GUI.addOnScreenChangeListener(this::onConfigUiClosed);
} }
} }
@@ -90,7 +89,7 @@ public abstract class AbstractPresetConfigEventHandler<TPresetEnum extends Enum<
public void onConfigValueSet() public void onConfigValueSet()
{ {
// don't try modifying the config before it's been loaded from file // don't try modifying the config before it's been loaded from file
if (!ConfigBase.INSTANCE.isLoaded) if (!ConfigHandler.INSTANCE.isLoaded)
{ {
return; return;
} }
@@ -144,7 +143,7 @@ public abstract class AbstractPresetConfigEventHandler<TPresetEnum extends Enum<
this.changingPreset = true; this.changingPreset = true;
// update the controlled config values // update the controlled config values
for (ConfigEntryWithPresetOptions<TPresetEnum, ?> configEntry : this.configList) for (ConfigPresetOptions<TPresetEnum, ?> configEntry : this.configList)
{ {
configEntry.updateConfigEntry(newPresetEnum); configEntry.updateConfigEntry(newPresetEnum);
} }
@@ -200,7 +199,7 @@ public abstract class AbstractPresetConfigEventHandler<TPresetEnum extends Enum<
// remove any quick options that aren't possible with the currently selected options // remove any quick options that aren't possible with the currently selected options
for (ConfigEntryWithPresetOptions<TPresetEnum, ?> configEntry : this.configList) for (ConfigPresetOptions<TPresetEnum, ?> configEntry : this.configList)
{ {
HashSet<TPresetEnum> optionPresetSet = configEntry.getPossibleQualitiesFromCurrentOptionValue(); HashSet<TPresetEnum> optionPresetSet = configEntry.getPossibleQualitiesFromCurrentOptionValue();
possiblePresetSet.retainAll(optionPresetSet); possiblePresetSet.retainAll(optionPresetSet);
@@ -230,7 +229,7 @@ public abstract class AbstractPresetConfigEventHandler<TPresetEnum extends Enum<
// abstract methods // // abstract methods //
//==================// //==================//
protected abstract IConfigEntry<TPresetEnum> getPresetConfigEntry(); protected abstract AbstractConfigBase<TPresetEnum> getPresetConfigEntry();
protected abstract List<TPresetEnum> getPresetEnumList(); protected abstract List<TPresetEnum> getPresetEnumList();
protected abstract TPresetEnum getCustomPresetEnum(); protected abstract TPresetEnum getCustomPresetEnum();
@@ -39,14 +39,17 @@ public class QuickShowWorldGenProgressConfigEventHandler
this.quickChangeListener = new ConfigChangeListener<>(Config.Client.quickShowWorldGenProgress, this.quickChangeListener = new ConfigChangeListener<>(Config.Client.quickShowWorldGenProgress,
(val) -> (val) ->
{ {
Config.Common.WorldGenerator.showGenerationProgress.set(Config.Client.quickShowWorldGenProgress.get() boolean quickShowProgress = Config.Client.quickShowWorldGenProgress.get();
? Config.Common.WorldGenerator.showGenerationProgress.getDefaultValue() Config.Common.WorldGenerator.showGenerationProgress.set(
quickShowProgress
? EDhApiDistantGeneratorProgressDisplayLocation.OVERLAY
: EDhApiDistantGeneratorProgressDisplayLocation.DISABLED); : EDhApiDistantGeneratorProgressDisplayLocation.DISABLED);
}); });
this.fullChangeListener = new ConfigChangeListener<>(Config.Common.WorldGenerator.showGenerationProgress, this.fullChangeListener = new ConfigChangeListener<>(Config.Common.WorldGenerator.showGenerationProgress,
(val) -> (val) ->
{ {
Config.Client.quickShowWorldGenProgress.set(Config.Common.WorldGenerator.showGenerationProgress.get() != EDhApiDistantGeneratorProgressDisplayLocation.DISABLED); boolean showProgress = Config.Common.WorldGenerator.showGenerationProgress.get() != EDhApiDistantGeneratorProgressDisplayLocation.DISABLED;
Config.Client.quickShowWorldGenProgress.setWithoutFiringEvents(showProgress);
}); });
} }
@@ -26,9 +26,9 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiVerticalQuality;
import com.seibel.distanthorizons.api.enums.config.quickOptions.EDhApiQualityPreset; import com.seibel.distanthorizons.api.enums.config.quickOptions.EDhApiQualityPreset;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency; import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.ConfigEntryWithPresetOptions; import com.seibel.distanthorizons.core.config.ConfigPresetOptions;
import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener; import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConfigEntry; import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -42,7 +42,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, EDhApiMaxHorizontalResolution> drawResolution = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.maxHorizontalResolution, private final ConfigPresetOptions<EDhApiQualityPreset, EDhApiMaxHorizontalResolution> drawResolution = new ConfigPresetOptions<>(Config.Client.Advanced.Graphics.Quality.maxHorizontalResolution,
new HashMap<EDhApiQualityPreset, EDhApiMaxHorizontalResolution>() new HashMap<EDhApiQualityPreset, EDhApiMaxHorizontalResolution>()
{{ {{
this.put(EDhApiQualityPreset.MINIMUM, EDhApiMaxHorizontalResolution.TWO_BLOCKS); this.put(EDhApiQualityPreset.MINIMUM, EDhApiMaxHorizontalResolution.TWO_BLOCKS);
@@ -51,7 +51,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
this.put(EDhApiQualityPreset.HIGH, EDhApiMaxHorizontalResolution.BLOCK); this.put(EDhApiQualityPreset.HIGH, EDhApiMaxHorizontalResolution.BLOCK);
this.put(EDhApiQualityPreset.EXTREME, EDhApiMaxHorizontalResolution.BLOCK); this.put(EDhApiQualityPreset.EXTREME, EDhApiMaxHorizontalResolution.BLOCK);
}}); }});
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, EDhApiVerticalQuality> verticalQuality = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.verticalQuality, private final ConfigPresetOptions<EDhApiQualityPreset, EDhApiVerticalQuality> verticalQuality = new ConfigPresetOptions<>(Config.Client.Advanced.Graphics.Quality.verticalQuality,
new HashMap<EDhApiQualityPreset, EDhApiVerticalQuality>() new HashMap<EDhApiQualityPreset, EDhApiVerticalQuality>()
{{ {{
this.put(EDhApiQualityPreset.MINIMUM, EDhApiVerticalQuality.HEIGHT_MAP); this.put(EDhApiQualityPreset.MINIMUM, EDhApiVerticalQuality.HEIGHT_MAP);
@@ -60,7 +60,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
this.put(EDhApiQualityPreset.HIGH, EDhApiVerticalQuality.HIGH); this.put(EDhApiQualityPreset.HIGH, EDhApiVerticalQuality.HIGH);
this.put(EDhApiQualityPreset.EXTREME, EDhApiVerticalQuality.EXTREME); this.put(EDhApiQualityPreset.EXTREME, EDhApiVerticalQuality.EXTREME);
}}); }});
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, EDhApiHorizontalQuality> horizontalQuality = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.horizontalQuality, private final ConfigPresetOptions<EDhApiQualityPreset, EDhApiHorizontalQuality> horizontalQuality = new ConfigPresetOptions<>(Config.Client.Advanced.Graphics.Quality.horizontalQuality,
new HashMap<EDhApiQualityPreset, EDhApiHorizontalQuality>() new HashMap<EDhApiQualityPreset, EDhApiHorizontalQuality>()
{{ {{
this.put(EDhApiQualityPreset.MINIMUM, EDhApiHorizontalQuality.LOWEST); this.put(EDhApiQualityPreset.MINIMUM, EDhApiHorizontalQuality.LOWEST);
@@ -69,7 +69,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
this.put(EDhApiQualityPreset.HIGH, EDhApiHorizontalQuality.HIGH); this.put(EDhApiQualityPreset.HIGH, EDhApiHorizontalQuality.HIGH);
this.put(EDhApiQualityPreset.EXTREME, EDhApiHorizontalQuality.EXTREME); this.put(EDhApiQualityPreset.EXTREME, EDhApiHorizontalQuality.EXTREME);
}}); }});
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, EDhApiTransparency> transparency = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.transparency, private final ConfigPresetOptions<EDhApiQualityPreset, EDhApiTransparency> transparency = new ConfigPresetOptions<>(Config.Client.Advanced.Graphics.Quality.transparency,
new HashMap<EDhApiQualityPreset, EDhApiTransparency>() new HashMap<EDhApiQualityPreset, EDhApiTransparency>()
{{ {{
this.put(EDhApiQualityPreset.MINIMUM, EDhApiTransparency.DISABLED); this.put(EDhApiQualityPreset.MINIMUM, EDhApiTransparency.DISABLED);
@@ -78,7 +78,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
this.put(EDhApiQualityPreset.HIGH, EDhApiTransparency.COMPLETE); this.put(EDhApiQualityPreset.HIGH, EDhApiTransparency.COMPLETE);
this.put(EDhApiQualityPreset.EXTREME, EDhApiTransparency.COMPLETE); this.put(EDhApiQualityPreset.EXTREME, EDhApiTransparency.COMPLETE);
}}); }});
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, Boolean> ssaoEnabled = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Ssao.enableSsao, private final ConfigPresetOptions<EDhApiQualityPreset, Boolean> ssaoEnabled = new ConfigPresetOptions<>(Config.Client.Advanced.Graphics.Ssao.enableSsao,
new HashMap<EDhApiQualityPreset, Boolean>() new HashMap<EDhApiQualityPreset, Boolean>()
{{ {{
this.put(EDhApiQualityPreset.MINIMUM, false); this.put(EDhApiQualityPreset.MINIMUM, false);
@@ -87,7 +87,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
this.put(EDhApiQualityPreset.HIGH, true); this.put(EDhApiQualityPreset.HIGH, true);
this.put(EDhApiQualityPreset.EXTREME, true); this.put(EDhApiQualityPreset.EXTREME, true);
}}); }});
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, EDhApiMcRenderingFadeMode> vanillaFade = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.vanillaFadeMode, private final ConfigPresetOptions<EDhApiQualityPreset, EDhApiMcRenderingFadeMode> vanillaFade = new ConfigPresetOptions<>(Config.Client.Advanced.Graphics.Quality.vanillaFadeMode,
new HashMap<EDhApiQualityPreset, EDhApiMcRenderingFadeMode>() new HashMap<EDhApiQualityPreset, EDhApiMcRenderingFadeMode>()
{{ {{
this.put(EDhApiQualityPreset.MINIMUM, EDhApiMcRenderingFadeMode.NONE); this.put(EDhApiQualityPreset.MINIMUM, EDhApiMcRenderingFadeMode.NONE);
@@ -96,7 +96,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
this.put(EDhApiQualityPreset.HIGH, EDhApiMcRenderingFadeMode.DOUBLE_PASS); this.put(EDhApiQualityPreset.HIGH, EDhApiMcRenderingFadeMode.DOUBLE_PASS);
this.put(EDhApiQualityPreset.EXTREME, EDhApiMcRenderingFadeMode.DOUBLE_PASS); this.put(EDhApiQualityPreset.EXTREME, EDhApiMcRenderingFadeMode.DOUBLE_PASS);
}}); }});
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, Boolean> dhDither = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.ditherDhFade, private final ConfigPresetOptions<EDhApiQualityPreset, Boolean> dhDither = new ConfigPresetOptions<>(Config.Client.Advanced.Graphics.Quality.ditherDhFade,
new HashMap<EDhApiQualityPreset, Boolean>() new HashMap<EDhApiQualityPreset, Boolean>()
{{ {{
this.put(EDhApiQualityPreset.MINIMUM, false); this.put(EDhApiQualityPreset.MINIMUM, false);
@@ -105,7 +105,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
this.put(EDhApiQualityPreset.HIGH, true); this.put(EDhApiQualityPreset.HIGH, true);
this.put(EDhApiQualityPreset.EXTREME, true); this.put(EDhApiQualityPreset.EXTREME, true);
}}); }});
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, Boolean> caveCulling = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Culling.enableCaveCulling, private final ConfigPresetOptions<EDhApiQualityPreset, Boolean> caveCulling = new ConfigPresetOptions<>(Config.Client.Advanced.Graphics.Culling.enableCaveCulling,
new HashMap<EDhApiQualityPreset, Boolean>() new HashMap<EDhApiQualityPreset, Boolean>()
{{ {{
this.put(EDhApiQualityPreset.MINIMUM, true); this.put(EDhApiQualityPreset.MINIMUM, true);
@@ -114,7 +114,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
this.put(EDhApiQualityPreset.HIGH, false); this.put(EDhApiQualityPreset.HIGH, false);
this.put(EDhApiQualityPreset.EXTREME, false); this.put(EDhApiQualityPreset.EXTREME, false);
}}); }});
private final ConfigEntryWithPresetOptions<EDhApiQualityPreset, Integer> biomeBlending = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.Graphics.Quality.lodBiomeBlending, private final ConfigPresetOptions<EDhApiQualityPreset, Integer> biomeBlending = new ConfigPresetOptions<>(Config.Client.Advanced.Graphics.Quality.lodBiomeBlending,
new HashMap<EDhApiQualityPreset, Integer>() new HashMap<EDhApiQualityPreset, Integer>()
{{ {{
this.put(EDhApiQualityPreset.MINIMUM, 0); this.put(EDhApiQualityPreset.MINIMUM, 0);
@@ -145,7 +145,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
this.configList.add(this.biomeBlending); this.configList.add(this.biomeBlending);
for (ConfigEntryWithPresetOptions<EDhApiQualityPreset, ?> config : this.configList) for (ConfigPresetOptions<EDhApiQualityPreset, ?> config : this.configList)
{ {
// ignore try-using, the listener should only ever be added once and should never be removed // ignore try-using, the listener should only ever be added once and should never be removed
new ConfigChangeListener<>(config.configEntry, (val) -> { this.onConfigValueChanged(); }); new ConfigChangeListener<>(config.configEntry, (val) -> { this.onConfigValueChanged(); });
@@ -159,7 +159,7 @@ public class RenderQualityPresetConfigEventHandler extends AbstractPresetConfigE
//==============// //==============//
@Override @Override
protected IConfigEntry<EDhApiQualityPreset> getPresetConfigEntry() { return Config.Client.qualityPresetSetting; } protected AbstractConfigBase<EDhApiQualityPreset> getPresetConfigEntry() { return Config.Client.qualityPresetSetting; }
@Override @Override
protected List<EDhApiQualityPreset> getPresetEnumList() { return Arrays.asList(EDhApiQualityPreset.values()); } protected List<EDhApiQualityPreset> getPresetEnumList() { return Arrays.asList(EDhApiQualityPreset.values()); }
@@ -22,8 +22,8 @@ package com.seibel.distanthorizons.core.config.eventHandlers.presets;
import com.seibel.distanthorizons.api.enums.config.quickOptions.EDhApiThreadPreset; import com.seibel.distanthorizons.api.enums.config.quickOptions.EDhApiThreadPreset;
import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener; import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.ConfigEntryWithPresetOptions; import com.seibel.distanthorizons.core.config.ConfigPresetOptions;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConfigEntry; import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
import com.seibel.distanthorizons.coreapi.util.MathUtil; import com.seibel.distanthorizons.coreapi.util.MathUtil;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -41,7 +41,7 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
public static int getDefaultThreadCount() { return getThreadCountByPercent(0.5); } public static int getDefaultThreadCount() { return getThreadCountByPercent(0.5); }
private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Integer> threadCount = new ConfigEntryWithPresetOptions<>(Config.Common.MultiThreading.numberOfThreads, private final ConfigPresetOptions<EDhApiThreadPreset, Integer> threadCount = new ConfigPresetOptions<>(Config.Common.MultiThreading.numberOfThreads,
new HashMap<EDhApiThreadPreset, Integer>() new HashMap<EDhApiThreadPreset, Integer>()
{{ {{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, getThreadCountByPercent(0.1)); this.put(EDhApiThreadPreset.MINIMAL_IMPACT, getThreadCountByPercent(0.1));
@@ -51,7 +51,7 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0));
}}); }});
public static double getDefaultRunTimeRatio() { return 1.0; } public static double getDefaultRunTimeRatio() { return 1.0; }
private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Double> threadRunTime = new ConfigEntryWithPresetOptions<>(Config.Common.MultiThreading.threadRunTimeRatio, private final ConfigPresetOptions<EDhApiThreadPreset, Double> threadRunTime = new ConfigPresetOptions<>(Config.Common.MultiThreading.threadRunTimeRatio,
new HashMap<EDhApiThreadPreset, Double>() new HashMap<EDhApiThreadPreset, Double>()
{{ {{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.5); this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.5);
@@ -74,7 +74,7 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
this.configList.add(this.threadCount); this.configList.add(this.threadCount);
this.configList.add(this.threadRunTime); this.configList.add(this.threadRunTime);
for (ConfigEntryWithPresetOptions<EDhApiThreadPreset, ?> config : this.configList) for (ConfigPresetOptions<EDhApiThreadPreset, ?> config : this.configList)
{ {
// ignore try-using, the listeners should only ever be added once and should never be removed // ignore try-using, the listeners should only ever be added once and should never be removed
new ConfigChangeListener<>(config.configEntry, (val) -> { this.onConfigValueChanged(); }); new ConfigChangeListener<>(config.configEntry, (val) -> { this.onConfigValueChanged(); });
@@ -119,7 +119,7 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
//==============// //==============//
@Override @Override
protected IConfigEntry<EDhApiThreadPreset> getPresetConfigEntry() { return Config.Client.threadPresetSetting; } protected AbstractConfigBase<EDhApiThreadPreset> getPresetConfigEntry() { return Config.Client.threadPresetSetting; }
@Override @Override
protected List<EDhApiThreadPreset> getPresetEnumList() { return Arrays.asList(EDhApiThreadPreset.values()); } protected List<EDhApiThreadPreset> getPresetEnumList() { return Arrays.asList(EDhApiThreadPreset.values()); }
@@ -20,13 +20,12 @@
package com.seibel.distanthorizons.core.config.file; package com.seibel.distanthorizons.core.config.file;
import com.electronwill.nightconfig.core.file.CommentedFileConfig; import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.config.ConfigBase; import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
import com.seibel.distanthorizons.core.config.types.AbstractConfigType;
import com.seibel.distanthorizons.core.config.types.ConfigEntry; import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@@ -47,7 +46,6 @@ public class ConfigFileHandler
private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public final ConfigBase configBase;
public final Path configPath; public final Path configPath;
private final Logger logger; private final Logger logger;
@@ -64,10 +62,9 @@ public class ConfigFileHandler
// constructor // // constructor //
//=============// //=============//
public ConfigFileHandler(ConfigBase configBase, Path configPath) public ConfigFileHandler(Path configPath)
{ {
this.logger = LogManager.getLogger(this.getClass().getSimpleName() + ", " + ModInfo.ID); this.logger = LogManager.getLogger(this.getClass().getSimpleName() + ", " + ModInfo.ID);
this.configBase = configBase;
this.configPath = configPath; this.configPath = configPath;
this.nightConfig = CommentedFileConfig this.nightConfig = CommentedFileConfig
@@ -104,7 +101,7 @@ public class ConfigFileHandler
this.loadNightConfig(nightConfig); this.loadNightConfig(nightConfig);
for (AbstractConfigType<?, ?> entry : this.configBase.entries) for (AbstractConfigBase<?> entry : ConfigHandler.INSTANCE.configBaseList)
{ {
if (ConfigEntry.class.isAssignableFrom(entry.getClass())) if (ConfigEntry.class.isAssignableFrom(entry.getClass()))
{ {
@@ -142,7 +139,7 @@ public class ConfigFileHandler
{ {
this.readWriteLock.lock(); this.readWriteLock.lock();
int currentCfgVersion = this.configBase.configVersion; int currentCfgVersion = ModInfo.CONFIG_FILE_VERSION;
try try
{ {
// Dont load the real `this.nightConfig`, instead create a tempoary one // Dont load the real `this.nightConfig`, instead create a tempoary one
@@ -154,13 +151,13 @@ public class ConfigFileHandler
} }
catch (Exception ignored) { } catch (Exception ignored) { }
if (currentCfgVersion == this.configBase.configVersion) if (currentCfgVersion == ModInfo.CONFIG_FILE_VERSION)
{ {
// handle normally // handle normally
} }
else if (currentCfgVersion > this.configBase.configVersion) else if (currentCfgVersion > ModInfo.CONFIG_FILE_VERSION)
{ {
this.logger.warn("Found config version [" + currentCfgVersion + "] which is newer than current mods config version of [" + this.configBase.configVersion + "]. You may have downgraded the mod and items may have been moved, you have been warned"); this.logger.warn("Found config version [" + currentCfgVersion + "] which is newer than current mods config version of [" + ModInfo.CONFIG_FILE_VERSION + "]. You may have downgraded the mod and items may have been moved, you have been warned");
} }
else // if (currentCfgVersion < configBase.configVersion) else // if (currentCfgVersion < configBase.configVersion)
{ {
@@ -176,7 +173,7 @@ public class ConfigFileHandler
} }
this.loadFromFile(this.nightConfig); this.loadFromFile(this.nightConfig);
this.nightConfig.set("_version", this.configBase.configVersion); this.nightConfig.set("_version", ModInfo.CONFIG_FILE_VERSION);
} }
finally finally
{ {
@@ -202,7 +199,7 @@ public class ConfigFileHandler
// Load all the entries // Load all the entries
for (AbstractConfigType<?, ?> entry : this.configBase.entries) for (AbstractConfigBase<?> entry : ConfigHandler.INSTANCE.configBaseList)
{ {
if (ConfigEntry.class.isAssignableFrom(entry.getClass()) if (ConfigEntry.class.isAssignableFrom(entry.getClass())
&& entry.getAppearance().showInFile) && entry.getAppearance().showInFile)
@@ -246,10 +243,10 @@ public class ConfigFileHandler
else if (entry.getTrueValue() == null) else if (entry.getTrueValue() == null)
{ {
// TODO when can this happen? // TODO when can this happen?
throw new IllegalArgumentException("Entry [" + entry.getNameWCategory() + "] is null, this may be a problem with [" + ModInfo.NAME + "]. Please contact the authors."); throw new IllegalArgumentException("Entry [" + entry.getNameAndCategory() + "] is null, this may be a problem with [" + ModInfo.NAME + "]. Please contact the authors.");
} }
workConfig.set(entry.getNameWCategory(), ConfigTypeConverters.attemptToConvertToString(entry.getType(), entry.getTrueValue())); workConfig.set(entry.getNameAndCategory(), ConfigTypeConverters.attemptToConvertToString(entry.getType(), entry.getTrueValue()));
} }
/** Loads an entry when only given the entry */ /** Loads an entry when only given the entry */
@@ -259,9 +256,11 @@ public class ConfigFileHandler
public <T> void loadEntry(ConfigEntry<T> entry, CommentedFileConfig nightConfig) public <T> void loadEntry(ConfigEntry<T> entry, CommentedFileConfig nightConfig)
{ {
if (!entry.getAppearance().showInFile) if (!entry.getAppearance().showInFile)
{
return; return;
}
if (!nightConfig.contains(entry.getNameWCategory())) if (!nightConfig.contains(entry.getNameAndCategory()))
{ {
this.saveEntry(entry, nightConfig); this.saveEntry(entry, nightConfig);
return; return;
@@ -272,13 +271,13 @@ public class ConfigFileHandler
{ {
if (entry.getType().isEnum()) if (entry.getType().isEnum())
{ {
entry.pureSet((T) (nightConfig.getEnum(entry.getNameWCategory(), (Class<? extends Enum>) entry.getType()))); entry.setWithoutFiringEvents((T) (nightConfig.getEnum(entry.getNameAndCategory(), (Class<? extends Enum>) entry.getType())));
return; return;
} }
// try converting the value if necessary // try converting the value if necessary
Class<?> expectedValueClass = entry.getType(); Class<?> expectedValueClass = entry.getType();
Object value = nightConfig.get(entry.getNameWCategory()); Object value = nightConfig.get(entry.getNameAndCategory());
Object convertedValue = ConfigTypeConverters.attemptToConvertFromString(expectedValueClass, value); Object convertedValue = ConfigTypeConverters.attemptToConvertFromString(expectedValueClass, value);
if (!convertedValue.getClass().equals(expectedValueClass)) if (!convertedValue.getClass().equals(expectedValueClass))
{ {
@@ -287,19 +286,18 @@ public class ConfigFileHandler
"Make sure a converter is defined in ["+ConfigTypeConverters.class.getSimpleName()+"]."); "Make sure a converter is defined in ["+ConfigTypeConverters.class.getSimpleName()+"].");
convertedValue = entry.getDefaultValue(); convertedValue = entry.getDefaultValue();
} }
entry.pureSet((T) convertedValue); entry.setWithoutFiringEvents((T) convertedValue);
if (entry.getTrueValue() == null) if (entry.getTrueValue() == null)
{ {
this.logger.warn("Entry [" + entry.getNameWCategory() + "] returned as null from the config. Using default value."); this.logger.warn("Entry [" + entry.getNameAndCategory() + "] returned as null from the config. Using default value.");
entry.pureSet(entry.getDefaultValue()); entry.setWithoutFiringEvents(entry.getDefaultValue());
} }
} }
catch (Exception e) catch (Exception e)
{ {
// e.printStackTrace(); this.logger.warn("Entry [" + entry.getNameAndCategory() + "] had an invalid value when loading the config. Using default value.");
this.logger.warn("Entry [" + entry.getNameWCategory() + "] had an invalid value when loading the config. Using default value."); entry.setWithoutFiringEvents(entry.getDefaultValue());
entry.pureSet(entry.getDefaultValue());
} }
} }
@@ -320,7 +318,7 @@ public class ConfigFileHandler
// the new line makes it easier to read and separate configs // the new line makes it easier to read and separate configs
// the space makes sure the first word of a comment isn't directly in line with the "#" // the space makes sure the first word of a comment isn't directly in line with the "#"
comment = "\n " + comment; comment = "\n " + comment;
nightConfig.setComment(entry.getNameWCategory(), comment); nightConfig.setComment(entry.getNameAndCategory(), comment);
} }
@@ -0,0 +1,10 @@
package com.seibel.distanthorizons.core.config.gui;
/**
* Points to a Common object that holds the GUI state.
* Having this interface allows for cleaner casting.
*/
public interface IConfigGuiInfo
{
}
@@ -19,25 +19,27 @@
package com.seibel.distanthorizons.core.config.types; package com.seibel.distanthorizons.core.config.types;
import com.seibel.distanthorizons.core.config.ConfigBase; import com.seibel.distanthorizons.core.config.gui.IConfigGuiInfo;
import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance; import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance;
/** /**
* The class where all config options should extend * The class all config options should extend
* *
* @author coolGi * @author coolGi
*/ */
// Note for devs: The "S" is the class that is extending this public abstract class AbstractConfigBase<T>
public abstract class AbstractConfigType<T, S>
{ {
public String category = ""; // This should only be set once in the init public String category = ""; // This should only be set once in the init
public String name; // This should only be set once in the init public String name; // This should only be set once in the init
protected final T defaultValue; protected final T defaultValue;
protected final boolean isFloatingPointNumber; protected final boolean isFloatingPointNumber;
protected T value; protected T value;
public ConfigBase configBase;
public Object guiValue; // This is a storage variable something like the gui can use /**
* This stores information related to the GUI state.
* This is set during config UI setup.
*/
public IConfigGuiInfo guiValue;
protected EConfigEntryAppearance appearance; protected EConfigEntryAppearance appearance;
@@ -47,7 +49,7 @@ public abstract class AbstractConfigType<T, S>
// constructor // // constructor //
//=============// //=============//
protected AbstractConfigType(EConfigEntryAppearance appearance, T defaultValue) protected AbstractConfigBase(EConfigEntryAppearance appearance, T defaultValue)
{ {
this.defaultValue = defaultValue; this.defaultValue = defaultValue;
this.value = defaultValue; this.value = defaultValue;
@@ -74,7 +76,7 @@ public abstract class AbstractConfigType<T, S>
public String getCategory() { return this.category; } public String getCategory() { return this.category; }
public String getName() { return this.name; } public String getName() { return this.name; }
public String getNameWCategory() { return (this.category.isEmpty() ? "" : this.category + ".") + this.name; } public String getNameAndCategory() { return (this.category.isEmpty() ? "" : this.category + ".") + this.name; }
/** Gets the class of T */ /** Gets the class of T */
@@ -27,10 +27,19 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance
* *
* @author coolGi * @author coolGi
*/ */
public class ConfigCategory extends AbstractConfigType<Class<?>, ConfigCategory> public class ConfigCategory extends AbstractConfigBase<Class<?>>
{ {
/** This should not be set by anything other than the config system itself */ /**
public String destination; // Where the category goes to * Defines where this category points to. <br>
* May be defined during config setup.
*/
public String destination;
//=============//
// constructor //
//=============//
private ConfigCategory(EConfigEntryAppearance appearance, Class<?> value, String destination) private ConfigCategory(EConfigEntryAppearance appearance, Class<?> value, String destination)
{ {
@@ -38,20 +47,26 @@ public class ConfigCategory extends AbstractConfigType<Class<?>, ConfigCategory>
this.destination = destination; this.destination = destination;
} }
public String getDestination()
{
return this.destination; //==================//
} // property getters //
//==================//
public String getDestination() { return this.destination; }
/** Use get() instead for category */ /** Use get() instead for category */
@Override @Override
@Deprecated @Deprecated
public Class<?> getType() public Class<?> getType() { return this.value; }
{
return value;
}
public static class Builder extends AbstractConfigType.Builder<Class<?>, Builder>
//=========//
// builder //
//=========//
public static class Builder extends AbstractConfigBase.Builder<Class<?>, Builder>
{ {
private String tmpDestination = null; private String tmpDestination = null;
@@ -20,13 +20,13 @@
package com.seibel.distanthorizons.core.config.types; package com.seibel.distanthorizons.core.config.types;
import com.seibel.distanthorizons.core.config.NumberUtil; import com.seibel.distanthorizons.core.config.ConfigHandler;
import com.seibel.distanthorizons.core.util.NumberUtil;
import com.seibel.distanthorizons.core.config.file.ConfigFileHandler; import com.seibel.distanthorizons.core.config.file.ConfigFileHandler;
import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener; import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
import com.seibel.distanthorizons.core.config.listeners.IConfigListener; 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.EConfigEntryAppearance;
import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryPerformance; import com.seibel.distanthorizons.core.config.types.enums.EConfigValidity;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConfigEntry;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
@@ -34,40 +34,38 @@ import java.util.Arrays;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
* Use for making the config variables * This config type allows for entering text, number, or enum values.
* for types that are not supported by it look in ConfigBase
* *
* @author coolGi * @author coolGi
* @version 2023-7-16
*/ */
public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> implements IConfigEntry<T> public class ConfigEntry<T> extends AbstractConfigBase<T>
{ {
private String comment; private final String comment;
private T min; private T min;
private T max; private T max;
private final ArrayList<IConfigListener> listenerList; private final ArrayList<IConfigListener> listenerList;
private final String chatCommandName; private final String chatCommandName;
private final EConfigEntryPerformance performance;
// API control //
/** /**
* If true this config can be controlled by the API <br> * If true this config can be controlled by the API <br>
* and any get() method calls will return the apiValue if it is set. * and any get() method calls will return the apiValue if it is set.
*/ */
public final boolean allowApiOverride; private final boolean allowApiOverride;
/** Will be null if un-set */ /** Will be null if un-set */
@Nullable @Nullable
private T apiValue; private T apiValue;
/** Creates the entry */ //=============//
// constructor //
//=============//
private ConfigEntry( private ConfigEntry(
EConfigEntryAppearance appearance, EConfigEntryAppearance appearance,
T value, String comment, T min, T max, String comment, String chatCommandName,
String chatCommandName, boolean allowApiOverride, T value, T min, T max,
EConfigEntryPerformance performance, boolean allowApiOverride,
ArrayList<IConfigListener> listenerList) ArrayList<IConfigListener> listenerList)
{ {
super(appearance, value); super(appearance, value);
@@ -77,40 +75,57 @@ public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
this.max = max; this.max = max;
this.chatCommandName = chatCommandName; this.chatCommandName = chatCommandName;
this.allowApiOverride = allowApiOverride; this.allowApiOverride = allowApiOverride;
this.performance = performance;
this.listenerList = listenerList; this.listenerList = listenerList;
} }
/** Gets the default value of the option */ //==========================//
@Override // property getters/setters //
public T getDefaultValue() { return super.defaultValue; } //==========================//
/** the string used when entering the config into the command line or chat */
public String getChatCommandName() { return this.chatCommandName; }
public String getComment() { return this.comment; }
/**
* If true this config can be controlled by the API <br>
* and any get() method calls will return the apiValue if it is set.
*/
public boolean getAllowApiOverride() { return this.allowApiOverride; }
public T getMin() { return this.min; }
public void setMin(T newMin) { this.min = newMin; }
public T getMax() { return this.max; }
public void setMax(T newMax) { this.max = newMax; }
//===============//
// value setters //
//===============//
@Override
public void setApiValue(T newApiValue) public void setApiValue(T newApiValue)
{ {
this.apiValue = newApiValue; this.apiValue = newApiValue;
this.listenerList.forEach(IConfigListener::onConfigValueSet); this.listenerList.forEach(IConfigListener::onConfigValueSet);
} }
@Override
public T getApiValue() { return this.apiValue; }
@Override
public boolean apiIsOverriding() { return this.allowApiOverride && this.apiValue != null; }
@Override
public boolean getAllowApiOverride() { return this.allowApiOverride; }
/** public boolean apiIsOverriding()
* DONT USE THIS IN YOUR CODE <br> {
* Sets the value without informing the rest of the code (ie, doesnt call listeners, or saves the value). <br> return this.allowApiOverride
* Should only be used when loading the config from the file (in places like the {@link ConfigFileHandler} or {@link com.seibel.distanthorizons.core.config.ConfigBase}) && this.apiValue != null;
*/
public void pureSet(T newValue) {
super.set(newValue);
} }
/**
* Should only be used when loading the config from file. <Br>
* Sets the value without informing the rest of the code (ie, it doesn't call listeners, or saving the value to file).
* @see ConfigFileHandler
*/
public void setWithoutFiringEvents(T newValue) { super.set(newValue); }
/** Sets the value without saving */ /** Sets the value without saving */
@Override
public void setWithoutSaving(T newValue) public void setWithoutSaving(T newValue)
{ {
super.set(newValue); super.set(newValue);
@@ -135,74 +150,35 @@ public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
} }
//===============//
// value getters //
//===============//
@Override @Override
public T get() public T get()
{ {
if (this.allowApiOverride && this.apiValue != null) if (this.allowApiOverride
&& this.apiValue != null)
{ {
return this.apiValue; return this.apiValue;
} }
return super.get(); return super.get();
} }
@Override /** Ignores the API value if set. */
public T getTrueValue() public T getTrueValue() { return super.get(); }
{
return super.get(); public T getDefaultValue() { return super.defaultValue; }
}
@Nullable
public T getApiValue() { return this.apiValue; }
/** Gets the min value */
@Override
public T getMin() { return this.min; }
/** Sets the min value */
@Override
public void setMin(T newMin) { 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 within a single setter */
@Override
public void setMinMax(T newMin, T newMax)
{
this.setMin(newMin);
this.setMax(newMax);
}
/** //===========//
* Clamps the value within the set range // listeners //
* //===========//
* @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());
}
// TODO is this for command line use?
public String getChatCommandName() { return this.chatCommandName; }
@Override
public String getComment() { return this.comment; }
@Override
public void setComment(String newComment) { this.comment = newComment; }
/** Gets the performance impact of an option */
public EConfigEntryPerformance getPerformance() { return this.performance; }
/** Fired whenever the config value changes to a new value. */ /** Fired whenever the config value changes to a new value. */
public void addValueChangeListener(Consumer<T> onValueChangeFunc) public void addValueChangeListener(Consumer<T> onValueChangeFunc)
@@ -227,116 +203,114 @@ public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
public void setListeners(IConfigListener... newListeners) { this.listenerList.addAll(Arrays.asList(newListeners)); } public void setListeners(IConfigListener... newListeners) { this.listenerList.addAll(Arrays.asList(newListeners)); }
/**
* Checks if the option is valid //====================//
* // min/max validation //
* @return 0 == valid //====================//
* <p> 2 == invalid
* <p> 1 == number too high /** Checks if this config's current value is valid */
* <p> -1 == number too low public EConfigValidity getValidity() { return this.getValidity(this.value, this.min, this.max); }
*/ /** Checks if the given value is valid */
@Override public EConfigValidity getValidity(@Nullable T value) { return this.getValidity(value, this.min, this.max); }
public byte isValid() { return isValid(this.value, this.min, this.max); } /** Checks if the given value is valid */
/** public EConfigValidity getValidity(@Nullable T value, @Nullable T min, @Nullable T max)
* Checks if a new value is valid
*
* @param value Value that is being checked whether valid
* @return 0 == valid
* <p> 2 == invalid
* <p> 1 == number too high
* <p> -1 == number too low
*/
@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
* <p> 2 == invalid
* <p> 1 == number too high
* <p> -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
* <p> 2 == invalid
* <p> 1 == number too high
* <p> -1 == number too low
*/
public byte isValid(T value, T min, T max)
{ {
if (this.configBase.disableMinMax) if (!ConfigHandler.INSTANCE.runMinMaxValidation)
{ {
return 0; return EConfigValidity.VALID;
} }
else if (min == null && max == null) else if (min == null
&& max == null)
{ {
// no validation is needed for this field // no validation is needed for this field
return 0; return EConfigValidity.VALID;
} }
else if (value == null || this.value == null else if (value == null
|| this.value == null
|| value.getClass() != this.value.getClass()) || value.getClass() != this.value.getClass())
{ {
// If the 2 variables aren't the same type then it will be invalid // If the 2 variables aren't the same type
return 2; // or the input is missing
// then it will be invalid
return EConfigValidity.INVALID;
} }
else if (Number.class.isAssignableFrom(value.getClass())) else if (value instanceof Number)
{ {
// Only check min max if it is a number // Only check min/max if this config's type is a number
if (max != null && NumberUtil.greaterThan((Number) value, (Number) max)) if (max != null
&& NumberUtil.greaterThan((Number) value, (Number) max))
{ {
return 1; return EConfigValidity.NUMBER_TOO_HIGH;
}
if (min != null && NumberUtil.lessThan((Number) value, (Number) min))
{
return -1;
} }
return 0; if (min != null
&& NumberUtil.lessThan((Number) value, (Number) min))
{
return EConfigValidity.NUMBER_TOO_LOW;
}
return EConfigValidity.VALID;
} }
else else
{ {
return 0; return EConfigValidity.VALID;
} }
} }
//===============//
// file handling //
//===============//
/** This should normally not be called since set() automatically calls this */ /** This should normally not be called since set() automatically calls this */
public void save() { configBase.configFileHandler.saveEntry(this); } public void save() { ConfigHandler.INSTANCE.configFileHandler.saveEntry(this); }
/** This should normally not be called except for special circumstances */ /** This should normally not be called except for special circumstances */
public void load() { configBase.configFileHandler.loadEntry(this); } public void load() { ConfigHandler.INSTANCE.configFileHandler.loadEntry(this); }
@Override
public boolean equals(IConfigEntry<?> obj) { return obj.getClass() == ConfigEntry.class && equals((ConfigEntry<?>) obj); } //================//
// base overrides //
//================//
public boolean equals(AbstractConfigBase<?> obj)
{
return obj.getClass() == ConfigEntry.class
&& this.equals((ConfigEntry<?>) obj);
}
/** Is the value of this equal to another */ /** Is the value of this equal to another */
public boolean equals(ConfigEntry<?> obj) public boolean equals(ConfigEntry<?> obj)
{ {
// Can all of this just be "return this.value.equals(obj.value)"? // Can all of this just be "return this.value.equals(obj.value)"?
if (Number.class.isAssignableFrom(this.value.getClass())) if (Number.class.isAssignableFrom(this.value.getClass()))
{
return this.value == obj.value; return this.value == obj.value;
}
else else
{
return this.value.equals(obj.value); return this.value.equals(obj.value);
}
} }
public static class Builder<T> extends AbstractConfigType.Builder<T, Builder<T>>
//=========//
// builder //
//=========//
public static class Builder<T> extends AbstractConfigBase.Builder<T, Builder<T>>
{ {
private String tmpComment = null; private String tmpComment = null;
private T tmpMin = null; private T tmpMin = null;
private T tmpMax = null; private T tmpMax = null;
protected String tmpChatCommandName = null; protected String tmpChatCommandName = null;
private boolean tmpUseApiOverwrite = true; private boolean tmpUseApiOverwrite = true;
private EConfigEntryPerformance tmpPerformance = EConfigEntryPerformance.DONT_SHOW;
protected ArrayList<IConfigListener> tmpIConfigListener = new ArrayList<>(); protected ArrayList<IConfigListener> tmpIConfigListener = new ArrayList<>();
public Builder<T> comment(String newComment) public Builder<T> comment(String newComment)
{ {
this.tmpComment = newComment; this.tmpComment = newComment;
@@ -382,12 +356,6 @@ public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
return this; return this;
} }
public Builder<T> setPerformance(EConfigEntryPerformance newPerformance)
{
this.tmpPerformance = newPerformance;
return this;
}
public Builder<T> replaceListeners(ArrayList<IConfigListener> newConfigListener) public Builder<T> replaceListeners(ArrayList<IConfigListener> newConfigListener)
@@ -416,13 +384,15 @@ public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
// build //
public ConfigEntry<T> build() public ConfigEntry<T> build()
{ {
return new ConfigEntry<>( return new ConfigEntry<>(
this.tmpAppearance, this.tmpAppearance,
this.tmpValue, this.tmpComment, this.tmpMin, this.tmpMax, this.tmpComment, this.tmpChatCommandName, this.tmpValue, this.tmpMin, this.tmpMax,
this.tmpChatCommandName, this.tmpUseApiOverwrite, this.tmpUseApiOverwrite,
this.tmpPerformance, this.tmpIConfigListener); this.tmpIConfigListener);
} }
} }
@@ -21,29 +21,42 @@ package com.seibel.distanthorizons.core.config.types;
import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance; import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance;
public class ConfigUIButton extends AbstractConfigType<Runnable, ConfigUIButton> public class ConfigUIButton extends AbstractConfigBase<Runnable>
{ {
public ConfigUIButton(Runnable runnable) //=============//
{ // constructor //
super(EConfigEntryAppearance.ONLY_IN_GUI, runnable); //=============//
}
/** Runs the action of the button. NOTE: Will run on the main thread (so can halt the main process if not offloaded to a different thread) */ public ConfigUIButton(Runnable runnable)
{ super(EConfigEntryAppearance.ONLY_IN_GUI, runnable); }
//=========//
// actions //
//=========//
/**
* Runs the action of the button.
* NOTE: This will run on the render thread
* (so it can halt the main process if it takes too long and isn't offloaded to another thread)
*/
public void runAction() { this.value.run(); } public void runAction() { this.value.run(); }
public static class Builder extends AbstractConfigType.Builder<Runnable, Builder>
//=========//
// builder //
//=========//
public static class Builder extends AbstractConfigBase.Builder<Runnable, Builder>
{ {
/** Appearance shouldn't be changed */ /** Appearance shouldn't be changed */
@Override @Override
public Builder setAppearance(EConfigEntryAppearance newAppearance) public Builder setAppearance(EConfigEntryAppearance newAppearance) { return this; }
{
return this;
}
public ConfigUIButton build() public ConfigUIButton build()
{ { return new ConfigUIButton(this.tmpValue); }
return new ConfigUIButton(this.tmpValue);
}
} }
@@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullable;
* *
* @author coolGi * @author coolGi
*/ */
public class ConfigUIComment extends AbstractConfigType<String, ConfigUIComment> public class ConfigUIComment extends AbstractConfigBase<String>
{ {
private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -43,8 +43,11 @@ public class ConfigUIComment extends AbstractConfigType<String, ConfigUIComment>
public ConfigUIComment() { this(null, null); } //=============//
public ConfigUIComment(String parentConfigPath, EConfigCommentTextPosition textPosition) // constructor //
//=============//
public ConfigUIComment(String parentConfigPath, @Nullable EConfigCommentTextPosition textPosition)
{ {
super(EConfigEntryAppearance.ONLY_IN_GUI, ""); super(EConfigEntryAppearance.ONLY_IN_GUI, "");
this.parentConfigPath = parentConfigPath; this.parentConfigPath = parentConfigPath;
@@ -53,6 +56,10 @@ public class ConfigUIComment extends AbstractConfigType<String, ConfigUIComment>
//=========//
// setters //
//=========//
/** Appearance shouldn't be changed */ /** Appearance shouldn't be changed */
@Override @Override
public void setAppearance(EConfigEntryAppearance newAppearance) { } public void setAppearance(EConfigEntryAppearance newAppearance) { }
@@ -63,9 +70,14 @@ public class ConfigUIComment extends AbstractConfigType<String, ConfigUIComment>
public static class Builder extends AbstractConfigType.Builder<String, Builder> //=========//
// builder //
//=========//
public static class Builder extends AbstractConfigBase.Builder<String, Builder>
{ {
public String tempParentConfigPath = null; public String tempParentConfigPath = null;
@Nullable
public EConfigCommentTextPosition tempTextPosition = null; public EConfigCommentTextPosition tempTextPosition = null;
@@ -155,9 +167,13 @@ public class ConfigUIComment extends AbstractConfigType<String, ConfigUIComment>
// build //
public ConfigUIComment build() public ConfigUIComment build()
{ return new ConfigUIComment(this.tempParentConfigPath, this.tempTextPosition); } { return new ConfigUIComment(this.tempParentConfigPath, this.tempTextPosition); }
} }
} }
@@ -25,13 +25,21 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance
* Adds empty space the height of a button. * Adds empty space the height of a button.
* Useful for separating different categories. * Useful for separating different categories.
*/ */
public class ConfigUISpacer extends AbstractConfigType<String, ConfigUISpacer> public class ConfigUISpacer extends AbstractConfigBase<String>
{ {
//=============//
// constructor //
//=============//
public ConfigUISpacer() public ConfigUISpacer()
{ super(EConfigEntryAppearance.ONLY_IN_GUI, ""); } { super(EConfigEntryAppearance.ONLY_IN_GUI, ""); }
//=========//
// setters //
//=========//
/** Appearance shouldn't be changed */ /** Appearance shouldn't be changed */
@Override @Override
public void setAppearance(EConfigEntryAppearance newAppearance) { } public void setAppearance(EConfigEntryAppearance newAppearance) { }
@@ -42,7 +50,11 @@ public class ConfigUISpacer extends AbstractConfigType<String, ConfigUISpacer>
public static class Builder extends AbstractConfigType.Builder<String, Builder> //=========//
// builder //
//=========//
public static class Builder extends AbstractConfigBase.Builder<String, Builder>
{ {
/** Appearance shouldn't be changed */ /** Appearance shouldn't be changed */
@Override @Override
@@ -23,16 +23,24 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance
/** /**
* Creates a UI element that copies everything from another element. * Creates a UI element that copies everything from another element.
* This only effects the UI * This element is only visible in the GUI.
* *
* @author coolGi * @author coolGi
*/ */
public class ConfigUiLinkedEntry extends AbstractConfigType<AbstractConfigType<?, ?>, ConfigUiLinkedEntry> public class ConfigUiLinkedEntry extends AbstractConfigBase<AbstractConfigBase<?>>
{ {
public ConfigUiLinkedEntry(AbstractConfigType<?, ?> value) //=============//
{ // constructor //
super(EConfigEntryAppearance.ONLY_IN_GUI, value); //=============//
}
public ConfigUiLinkedEntry(AbstractConfigBase<?> value)
{ super(EConfigEntryAppearance.ONLY_IN_GUI, value); }
//=========//
// setters //
//=========//
/** Appearance shouldn't be changed */ /** Appearance shouldn't be changed */
@Override @Override
@@ -40,10 +48,15 @@ public class ConfigUiLinkedEntry extends AbstractConfigType<AbstractConfigType<?
/** Value shouldn't be changed after creation */ /** Value shouldn't be changed after creation */
@Override @Override
public void set(AbstractConfigType<?, ?> newValue) { } public void set(AbstractConfigBase<?> newValue) { }
public static class Builder extends AbstractConfigType.Builder<AbstractConfigType<?, ?>, Builder>
//=========//
// builder //
//=========//
public static class Builder extends AbstractConfigBase.Builder<AbstractConfigBase<?>, Builder>
{ {
/** Appearance shouldn't be changed */ /** Appearance shouldn't be changed */
@Override @Override
@@ -59,4 +72,6 @@ public class ConfigUiLinkedEntry extends AbstractConfigType<AbstractConfigType<?
} }
} }
@@ -1,38 +0,0 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.core.config.types.enums;
/**
* What is the performance impact of an entry
* (default is DONT_SHOW)
*
* @author coolGi
*/
public enum EConfigEntryPerformance
{
NONE,
VERY_LOW,
LOW,
MEDIUM,
HIGH,
VERY_HIGH,
DONT_SHOW
}
@@ -0,0 +1,15 @@
package com.seibel.distanthorizons.core.config.types.enums;
/**
* VALID
* INVALID
* NUMBER_TOO_HIGH
* NUMBER_TOO_LOW
*/
public enum EConfigValidity
{
VALID,
INVALID,
NUMBER_TOO_HIGH,
NUMBER_TOO_LOW,
}
@@ -21,7 +21,6 @@ package com.seibel.distanthorizons.core.level;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.core.config.AppliedConfigState;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
@@ -86,7 +85,6 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
); );
public final WorldGenModule worldGenModule; public final WorldGenModule worldGenModule;
public final AppliedConfigState<Boolean> worldGeneratorEnabledConfig;
@Nullable @Nullable
private final SyncOnLoadRequestQueue syncOnLoadRequestQueue; private final SyncOnLoadRequestQueue syncOnLoadRequestQueue;
@@ -134,7 +132,6 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
} }
this.dataFileHandler = new RemoteFullDataSourceProvider(this, saveStructure, fullDataSaveDirOverride, this.syncOnLoadRequestQueue); this.dataFileHandler = new RemoteFullDataSourceProvider(this, saveStructure, fullDataSaveDirOverride, this.syncOnLoadRequestQueue);
this.worldGeneratorEnabledConfig = new AppliedConfigState<>(Config.Common.WorldGenerator.enableDistantGeneration);
this.worldGenModule = new WorldGenModule(this, this.dataFileHandler, () -> new WorldGenState(this, networkState)); this.worldGenModule = new WorldGenModule(this, this.dataFileHandler, () -> new WorldGenState(this, networkState));
this.clientside = new ClientLevelModule(this); this.clientside = new ClientLevelModule(this);
@@ -17,54 +17,50 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.seibel.distanthorizons.core.config; package com.seibel.distanthorizons.core.util;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
/** /**
* Helps with working with numbers that the value of which is unknown * Helps when working with numbers where the type is unknown.
* *
* @author coolGi * @author coolGi
* @version 2023-7-16
*/ */
// TODO: Should this be moved out of here into somewhere like the util section
public class NumberUtil public class NumberUtil
{ {
// Is there no better way of doing this? // Is there no better way of doing this?
public static Map<Class<?>, Number> minValues = new HashMap<Class<?>, Number>() public static Map<Class<?>, Number> minValues = new HashMap<Class<?>, Number>()
{{ {{
put(Byte.class, Byte.MIN_VALUE); this.put(Byte.class, Byte.MIN_VALUE);
put(Short.class, Short.MIN_VALUE); this.put(Short.class, Short.MIN_VALUE);
put(Integer.class, Integer.MIN_VALUE); this.put(Integer.class, Integer.MIN_VALUE);
put(Long.class, Long.MIN_VALUE); this.put(Long.class, Long.MIN_VALUE);
put(Double.class, Double.MIN_VALUE); this.put(Double.class, Double.MIN_VALUE);
put(Float.class, Float.MIN_VALUE); this. put(Float.class, Float.MIN_VALUE);
}}; }};
public static Map<Class<?>, Number> maxValues = new HashMap<Class<?>, Number>() public static Map<Class<?>, Number> maxValues = new HashMap<Class<?>, Number>()
{{ {{
put(Byte.class, Byte.MAX_VALUE); this.put(Byte.class, Byte.MAX_VALUE);
put(Short.class, Short.MAX_VALUE); this.put(Short.class, Short.MAX_VALUE);
put(Integer.class, Integer.MAX_VALUE); this.put(Integer.class, Integer.MAX_VALUE);
put(Long.class, Long.MAX_VALUE); this.put(Long.class, Long.MAX_VALUE);
put(Double.class, Double.MAX_VALUE); this.put(Double.class, Double.MAX_VALUE);
put(Float.class, Float.MAX_VALUE); this.put(Float.class, Float.MAX_VALUE);
}}; }};
public static Number getMinimum(Class<?> c)
{
return minValues.get(c); public static Number getMinimum(Class<?> c) { return minValues.get(c); }
} public static Number getMaximum(Class<?> c) { return maxValues.get(c); }
public static Number getMaximum(Class<?> c)
{
return maxValues.get(c);
}
/** Does a greater than (>) operator on any number */ /** Does a greater than (>) operator on any number */
public static boolean greaterThan(Number a, Number b) public static boolean greaterThan(Number a, Number b)
{ {
if (a.getClass() != b.getClass()) if (a.getClass() != b.getClass())
{
return false; return false;
}
Class<?> typeClass = a.getClass(); Class<?> typeClass = a.getClass();
if (typeClass == Byte.class) return a.byteValue() > b.byteValue(); if (typeClass == Byte.class) return a.byteValue() > b.byteValue();
@@ -73,6 +69,7 @@ public class NumberUtil
if (typeClass == Long.class) return a.longValue() > b.longValue(); if (typeClass == Long.class) return a.longValue() > b.longValue();
if (typeClass == Double.class) return a.doubleValue() > b.doubleValue(); if (typeClass == Double.class) return a.doubleValue() > b.doubleValue();
if (typeClass == Float.class) return a.floatValue() > b.floatValue(); if (typeClass == Float.class) return a.floatValue() > b.floatValue();
return false; return false;
} }
@@ -80,7 +77,9 @@ public class NumberUtil
public static boolean lessThan(Number a, Number b) public static boolean lessThan(Number a, Number b)
{ {
if (a.getClass() != b.getClass()) if (a.getClass() != b.getClass())
{
return false; return false;
}
Class<?> typeClass = a.getClass(); Class<?> typeClass = a.getClass();
if (typeClass == Byte.class) return a.byteValue() < b.byteValue(); if (typeClass == Byte.class) return a.byteValue() < b.byteValue();
@@ -89,6 +88,7 @@ public class NumberUtil
if (typeClass == Long.class) return a.longValue() < b.longValue(); if (typeClass == Long.class) return a.longValue() < b.longValue();
if (typeClass == Double.class) return a.doubleValue() < b.doubleValue(); if (typeClass == Double.class) return a.doubleValue() < b.doubleValue();
if (typeClass == Float.class) return a.floatValue() < b.floatValue(); if (typeClass == Float.class) return a.floatValue() < b.floatValue();
return false; return false;
} }
@@ -21,6 +21,7 @@ package com.seibel.distanthorizons.core.wrapperInterfaces.config;
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IBindable;
/** handles communication between DH Core and the currently active config screen */
public interface IConfigGui extends IBindable public interface IConfigGui extends IBindable
{ {