diff --git a/Readme.md b/Readme.md
index 668aca089..1e82c25af 100644
--- a/Readme.md
+++ b/Readme.md
@@ -20,8 +20,5 @@ https://github.com/lz4/lz4-java
NightConfig for Json & Toml (config handling)\
https://github.com/TheElectronWill/night-config
-SVG Salamander for SVG's\
+SVG Salamander for SVG support (not being used atm)\
https://github.com/blackears/svgSalamander
-
-FlatLaf for theming (for development testing, may remove later)\
-https://www.formdev.com/flatlaf/
diff --git a/api/build.gradle b/api/build.gradle
index cb3195792..9172e5bf8 100644
--- a/api/build.gradle
+++ b/api/build.gradle
@@ -77,3 +77,13 @@ task addSourcesToCompiledJar(type: ShadowJar) {
}
}
+
+javadoc {
+ options {
+ // Don't log warnings.
+ // There are a lot of warnings related to missing @param and @return javadocs
+ // that aren't necessary and would clutter up said javadocs.
+ // For more info see: https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javadoc.html
+ addStringOption('Xdoclint:all,-missing', '-quiet')
+ }
+}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java
index 5abdee02b..527f93ada 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/DhApi.java
@@ -20,18 +20,43 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverri
* For example: you can access singletons which handle the config or event binding.
*
* Q: Why should I use this class instead of just getting the API singleton I need?
- *
* A: This way there is a lower chance of your code breaking if we change something on our end.
* For example, if we realized there is a much better way of handling dependency injection we would keep the
* interface the same so your code doesn't have to change. Whereas if you were directly referencing
* the concrete object we replaced, there would be issues.
*
* @author James Seibel
- * @version 2023-6-29
+ * @version 2023-8-26
* @since API 1.0.0
*/
public class DhApi
{
+ /**
+ * If you can see this Java Doc, this can be ignored.
+ * This is just to you know that Javadocs are available and that you should use the API jar
+ * instead of the full mod jar.
+ *
+ * Note: Don't use this string in your code. It may change and is only for reference.
+ */
+ public static String READ_ME =
+ "If you don't see Javadocs something is wrong. \n" +
+ "If you are only using the full DH Mod in your build script, you won't have access to our javadocs and could potentially call into unsafe code. \n" +
+ "\n" +
+ "Please use the API jar in your build script as a compile time dependency " +
+ "and the full DH jar as a runtime dependency. \n" +
+ "\n" +
+ "Please refer to the example API project or the DH Developer Wiki for additional information " +
+ "and suggested setup. \n" + // DH Dev note: no links were included to prevent link rot.
+ "";
+ public static String readMe() { return READ_ME; }
+ /**
+ * This is just a humorous way to reference the {@link DhApi#READ_ME} constant string and hopefully peak a few people's attention
+ * vs the relatively boring "readMe".
+ */
+ public static String heyYou_YoureFinallyAwake() { return READ_ME; }
+
+
+
/**
* WARNING:
* All objects in this class will be null until after DH initializes for the first time.
@@ -73,6 +98,7 @@ public class DhApi
}
+
// always available //
/**
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigValue.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigValue.java
index fc91e534a..b5ac00375 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigValue.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/IDhApiConfigValue.java
@@ -1,5 +1,7 @@
package com.seibel.distanthorizons.api.interfaces.config;
+import java.util.function.Consumer;
+
/**
* An interface for Distant Horizon's Config.
*
@@ -16,17 +18,17 @@ public interface IDhApiConfigValue
* Returns the True value if either the config cannot be overridden by
* the API or if it hasn't been set by the API.
*/
- public T getValue();
+ T getValue();
/**
* Returns the value held by this config.
* This is the value stored in the config file.
*/
- public T getTrueValue();
- /**
+ T getTrueValue();
+ /*
* Returns the value of the config if it was set by the API.
* Returns null if the config wasn't set by the API.
*/
- public T getApiValue();
+ //T getApiValue(); // not currently implemented
/**
* Sets the config's value.
@@ -36,16 +38,20 @@ public interface IDhApiConfigValue
*
* @return true if the value was set, false otherwise.
*/
- public boolean setValue(T newValue);
+ boolean setValue(T newValue);
/** Returns true if this config can be set via the API, false otherwise. */
- public boolean getCanBeOverrodeByApi();
+ boolean getCanBeOverrodeByApi();
/** Returns the default value for this config. */
- public T getDefaultValue();
+ T getDefaultValue();
/** Returns the max value for this config, null if there is no max. */
- public T getMaxValue();
+ T getMaxValue();
/** Returns the min value for this config, null if there is no min. */
- public T getMinValue();
+ T getMinValue();
+
+ /** Adds a {@link Consumer} that will be called whenever the config changes to a new value. */
+ void addChangeListener(Consumer onValueChangeFunc);
+ //void removeListener(Consumer onValueChangeFunc); // not currently implemented
}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java
index 79cdd31c0..9be0d8559 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/events/IDhApiEventInjector.java
@@ -35,6 +35,8 @@ public interface IDhApiEventInjector extends IDependencyInjector
/**
* Unlinks the given event handler, preventing the handler from being called in the future.
*
+ * @param dependencyInterface the base interface for the {@link IDhApiEvent}
+ * @param dependencyClassToRemove the concrete {@link IDhApiEvent} class to remove
* @return true if the handler was unbound, false if the handler wasn't bound.
* @throws IllegalArgumentException if the implementation object doesn't implement the interface
*/
@@ -48,6 +50,7 @@ public interface IDhApiEventInjector extends IDependencyInjector
* @param abstractEvent event type
* @param eventParameterObject event parameter
* @param the parameter type taken by the event handlers.
+ * @param the {@link IDhApiEvent}'s class
* @return if any of bound event handlers returned that this event should be canceled.
*/
> boolean fireAllEvents(Class abstractEvent, T eventParameterObject);
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/IDhApiOverrideable.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/IDhApiOverrideable.java
index 1736e52d7..493ceaada 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/IDhApiOverrideable.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/IDhApiOverrideable.java
@@ -13,8 +13,10 @@ import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverri
public interface IDhApiOverrideable extends IBindable
{
/**
- * Higher (larger numerical) priorities override lower (smaller numerical) priorities .
+ * Higher (larger numerical) priorities override lower (smaller numerical) priorities.
* For most developers this can be left at the default.
+ *
+ * @return The priority of this interface, the lowest legal value is {@link IOverrideInjector#MIN_NON_CORE_OVERRIDE_PRIORITY}.
*/
default int getPriority() { return IOverrideInjector.DEFAULT_NON_CORE_OVERRIDE_PRIORITY; }
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java
index 2698c2d06..32892ae9e 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/AbstractDhApiChunkWorldGenerator.java
@@ -61,10 +61,14 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh
/**
* This method is called to generate terrain over a given area
* from a thread defined by Distant Horizons.
- *
- * See {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator.generateChunks}
- * for the list of Object's this method should return along with additional documentation.
- *
+ *
+ * @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level)
+ * @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level)
+ * @param generatorMode how far into the world gen pipeline this method run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
+ *
+ * @return See {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator.generateChunks}
+ * for the list of Object's this method should return along with additional documentation.
+ *
* @see IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator#generateChunks
*/
public abstract Object[] generateChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode);
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java
index 8396ff340..3c412e96b 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/worldGenerator/IDhApiWorldGenerator.java
@@ -28,7 +28,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
*
* TODO: System currently only supports 1x1 block per data.
*
- * @see EDhApiDetailLevel
+ * @see EDhApiDetailLevel
*/
default byte getSmallestDataDetailLevel() { return EDhApiDetailLevel.BLOCK.detailLevel; }
/**
@@ -37,7 +37,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* Default detail level is 0
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}.
*
- * @see EDhApiDetailLevel
+ * @see EDhApiDetailLevel
*/
default byte getLargestDataDetailLevel() { return EDhApiDetailLevel.BLOCK.detailLevel; }
@@ -49,7 +49,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* Default detail level is 4
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}.
*
- * @see EDhApiDetailLevel
+ * @see EDhApiDetailLevel
*/
default byte getMinGenerationGranularity() { return EDhApiDetailLevel.CHUNK.detailLevel; }
@@ -61,11 +61,11 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* Default detail level is 6 (4x4 chunks)
* For more information on what detail levels represent see: {@link EDhApiDetailLevel}.
*
- * @see EDhApiDetailLevel
+ * @see EDhApiDetailLevel
*/
default byte getMaxGenerationGranularity() { return (byte) (EDhApiDetailLevel.CHUNK.detailLevel + 2); }
- /** Returns true if the generator is unable to accept new generation requests. */
+ /** @return true if the generator is unable to accept new generation requests. */
boolean isBusy();
@@ -81,13 +81,22 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* After a chunk has been generated it (and any necessary supporting objects as listed below) should be passed into the
* resultConsumer's {@link Consumer#accept} method. If the Consumer is given the wrong data
* type(s) it will disable the world generator and log an error with a list of objects it was expecting.
- * Note: these objects are minecraft version dependent and will change without notice!
+ * Note: these objects are minecraft version dependent and will change without notice!
* Please run your generator in game at least once to confirm the objects you are returning are correct.
*
* Consumer expected inputs for each minecraft version (in order):
* 1.16, 1.17, 1.18, 1.19, 1.20:
* - [net.minecraft.world.level.chunk.ChunkAccess]
* - [net.minecraft.world.level.ServerLevel] or [net.minecraft.world.level.ClientLevel]
+ *
+ * @param chunkPosMinX the chunk X position closest to negative infinity
+ * @param chunkPosMinZ the chunk Z position closest to negative infinity
+ * @param granularity TODO find a central location to store the definition of granularity. For now it is stored in the Core method: WorldGenerationQueue#startGenerationEvent
+ * @param targetDataDetail the LOD Detail level requested to generate. See {@link EDhApiDetailLevel} for additional information.
+ * @param generatorMode how far into the world gen pipeline this method run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
+ * @param worldGeneratorThreadPool the thread pool that should be used when generating the returned {@link CompletableFuture}.
+ * @param resultConsumer the consumer that should be fired whenever a chunk finishes generating.
+ * @return a future that should run on the worldGeneratorThreadPool and complete once the given generation task has completed.
*/
CompletableFuture generateChunks(
int chunkPosMinX, int chunkPosMinZ,
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/config/DhApiConfigValue.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/config/DhApiConfigValue.java
index e1d16c485..2931cb9fa 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/objects/config/DhApiConfigValue.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/config/DhApiConfigValue.java
@@ -5,6 +5,8 @@ import com.seibel.distanthorizons.coreapi.interfaces.config.IConfigEntry;
import com.seibel.distanthorizons.coreapi.interfaces.config.IConverter;
import com.seibel.distanthorizons.coreapi.util.converters.DefaultConverter;
+import java.util.function.Consumer;
+
/**
* A wrapper used to interface with Distant Horizon's Config.
*
@@ -68,8 +70,18 @@ public class DhApiConfigValue implements IDhApiConfigValue onValueChangeFunc)
+ {
+ this.configEntry.addValueChangeListener((coreValue) ->
+ {
+ apiType apiValue = this.configConverter.convertToApiType(coreValue);
+ onValueChangeFunc.accept(apiValue);
+ });
+ }
+
}
diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java
index 36325d085..e268c7c2d 100644
--- a/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java
+++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/DependencyInjection/ApiEventInjector.java
@@ -172,6 +172,15 @@ public class ApiEventInjector extends DependencyInjector implements
}
+ /**
+ * Wraps the event parameter object in a {@link DhApiCancelableEventParam} or {@link DhApiEventParam} depending on
+ * if it should allow cancellation or not.
+ *
+ * @param event the event instance
+ * @param parameter the event's parameter object
+ * @param the event parameter type
+ * @return the event parameter wrapped in a {@link DhApiCancelableEventParam} or {@link DhApiEventParam}
+ */
public static DhApiEventParam createEventParamWrapper(IDhApiEvent event, T parameter)
{
return (event instanceof IDhApiCancelableEvent) ? new DhApiCancelableEventParam<>(parameter) : new DhApiEventParam<>(parameter);
diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java
index fb137f3bc..afb6dad1e 100644
--- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java
+++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/config/IConfigEntry.java
@@ -1,6 +1,8 @@
package com.seibel.distanthorizons.coreapi.interfaces.config;
+import java.util.function.Consumer;
+
/**
* Use for making the config variables
*
@@ -56,4 +58,6 @@ public interface IConfigEntry
/** Is the value of this equal to another */
boolean equals(IConfigEntry> obj);
+ void addValueChangeListener(Consumer onValueChangeFunc);
+
}
diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java
index 266c43e66..3024405b1 100644
--- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java
+++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IDependencyInjector.java
@@ -25,7 +25,7 @@ public interface IDependencyInjector
/**
- * This does not return incomplete dependencies.
+ * Does not return incomplete dependencies.
* See {@link #get(Class, boolean) get(Class, boolean)} for full documentation.
*
* @see #get(Class, boolean)
diff --git a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java
index 15f9dcbc4..bf1d3d6ce 100644
--- a/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java
+++ b/api/src/main/java/com/seibel/distanthorizons/coreapi/interfaces/dependencyInjection/IOverrideInjector.java
@@ -7,12 +7,12 @@ public interface IOverrideInjector
{
/**
* All core overrides should have this priority.
- * Should be lower than MIN_OVERRIDE_PRIORITY.
+ * Should be lower than {@link IOverrideInjector#MIN_NON_CORE_OVERRIDE_PRIORITY}.
*/
public static final int CORE_PRIORITY = -1;
/**
* The lowest priority non-core overrides can have.
- * Should be higher than CORE_PRIORITY.
+ * Should be higher than {@link IOverrideInjector#CORE_PRIORITY}.
*/
public static final int MIN_NON_CORE_OVERRIDE_PRIORITY = 0;
/** The priority given to overrides that don't explicitly define a priority. */
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
index 3684e61a6..22483c81b 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/Initializer.java
@@ -29,7 +29,6 @@ public class Initializer
Class> compressor = LZ4Compressor.class;
Class> networking = ByteBuf.class;
Class> toml = com.electronwill.nightconfig.core.Config.class;
- Class> flatlaf = com.formdev.flatlaf.FlatDarculaLaf.class;
}
catch (NoClassDefFoundError e)
{
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
index e6e28024c..3731c5a75 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
@@ -152,7 +152,6 @@ public class Config
+ "\n"
+ "Lowest Quality: " + EMaxHorizontalResolution.CHUNK + "\n"
+ "Highest Quality: " + EMaxHorizontalResolution.BLOCK)
- .addListener(RenderCacheConfigEventHandler.INSTANCE)
.setPerformance(EConfigEntryPerformance.MEDIUM)
.build();
@@ -173,7 +172,6 @@ public class Config
+ "Lowest Quality: " + EVerticalQuality.HEIGHT_MAP + "\n"
+ "Highest Quality: " + EVerticalQuality.EXTREME)
.setPerformance(EConfigEntryPerformance.VERY_HIGH)
- .addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry ssao = new ConfigEntry.Builder()
@@ -200,7 +198,6 @@ public class Config
+ ETransparency.DISABLED + ": LODs will be opaque. \n"
+ "")
.setPerformance(EConfigEntryPerformance.MEDIUM)
- .addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry blocksToIgnore = new ConfigEntry.Builder()
@@ -212,7 +209,6 @@ public class Config
+ EBlocksToAvoid.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(RenderCacheConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry tintWithAvoidedBlocks = new ConfigEntry.Builder()
@@ -224,7 +220,6 @@ public class Config
+ "False: skipped blocks will not change color of surface below them. "
+ "")
.setPerformance(EConfigEntryPerformance.NONE)
- .addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
// TODO fixme
@@ -532,7 +527,6 @@ public class Config
+ "0 = black \n"
+ "1 = normal \n"
+ "2 = near white")
- .addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry saturationMultiplier = new ConfigEntry.Builder() // TODO: Make this a float (the ClassicConfigGUI doesnt support floats)
@@ -543,7 +537,6 @@ public class Config
+ "0 = black and white \n"
+ "1 = normal \n"
+ "2 = very saturated")
- .addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry enableCaveCulling = new ConfigEntry.Builder()
@@ -601,7 +594,6 @@ public class Config
+ ELodShading.NONE + ": All LOD sides will be rendered with the same brightness. \n"
+ "")
.setPerformance(EConfigEntryPerformance.NONE)
- .addListener(RenderCacheConfigEventHandler.INSTANCE)
.build();
}
@@ -1242,6 +1234,7 @@ public class Config
ThreadPresetConfigEventHandler.INSTANCE.setUiOnlyConfigValues();
RenderQualityPresetConfigEventHandler.INSTANCE.setUiOnlyConfigValues();
QuickRenderToggleConfigEventHandler.INSTANCE.setUiOnlyConfigValues();
+ RenderCacheConfigEventHandler.getInstance();
}
catch (Exception e)
{
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java
index 4ad052173..ac3eb4cb1 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/RenderCacheConfigEventHandler.java
@@ -1,9 +1,12 @@
package com.seibel.distanthorizons.core.config.eventHandlers;
import com.seibel.distanthorizons.api.DhApi;
+import com.seibel.distanthorizons.api.enums.config.EBlocksToAvoid;
import com.seibel.distanthorizons.api.enums.config.ELodShading;
import com.seibel.distanthorizons.api.enums.config.EMaxHorizontalResolution;
import com.seibel.distanthorizons.api.enums.config.EVerticalQuality;
+import com.seibel.distanthorizons.api.enums.rendering.ETransparency;
+import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
import com.seibel.distanthorizons.core.config.listeners.IConfigListener;
import com.seibel.distanthorizons.core.config.Config;
@@ -16,28 +19,52 @@ import java.util.TimerTask;
*
* Note: if additional settings should clear the render cache, add those to this listener, don't create a new listener
*/
-public class RenderCacheConfigEventHandler implements IConfigListener
+public class RenderCacheConfigEventHandler
{
- public static RenderCacheConfigEventHandler INSTANCE = new RenderCacheConfigEventHandler();
+ private static RenderCacheConfigEventHandler INSTANCE;
+
+
+ // previous values used to check if a watched setting was actually modified
+ private final ConfigChangeListener horizontalResolutionChangeListener;
+ private final ConfigChangeListener verticalQualityChangeListener;
+ private final ConfigChangeListener transparencyChangeListener;
+ private final ConfigChangeListener blocksToIgnoreChangeListener;
+ private final ConfigChangeListener tintWithAvoidedBlocksChangeListener;
+
+ private final ConfigChangeListener brightnessMultiplierChangeListener;
+ private final ConfigChangeListener saturationMultiplierChangeListener;
+ private final ConfigChangeListener lodShadingChangeListener;
/** how long to wait in milliseconds before applying the config changes */
private static final long TIMEOUT_IN_MS = 4_000L;
private Timer cacheClearingTimer;
- /** private since we only ever need one handler at a time */
- private RenderCacheConfigEventHandler() { }
-
-
- @Override
- public void onConfigValueSet()
+ public static RenderCacheConfigEventHandler getInstance()
{
- this.refreshRenderDataAfterTimeout();
+ if (INSTANCE == null)
+ {
+ INSTANCE = new RenderCacheConfigEventHandler();
+ }
+
+ return INSTANCE;
}
- @Override
- public void onUiModify() { /* do nothing, we only care about modified config values */ }
+ /** private since we only ever need one handler at a time */
+ private RenderCacheConfigEventHandler()
+ {
+ this.horizontalResolutionChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.maxHorizontalResolution, (newValue) -> this.refreshRenderDataAfterTimeout());
+ this.verticalQualityChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.verticalQuality, (newValue) -> this.refreshRenderDataAfterTimeout());
+ this.transparencyChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.transparency, (newValue) -> this.refreshRenderDataAfterTimeout());
+ this.blocksToIgnoreChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.blocksToIgnore, (newValue) -> this.refreshRenderDataAfterTimeout());
+ this.tintWithAvoidedBlocksChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.Quality.tintWithAvoidedBlocks, (newValue) -> this.refreshRenderDataAfterTimeout());
+
+ this.brightnessMultiplierChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.AdvancedGraphics.brightnessMultiplier, (newValue) -> this.refreshRenderDataAfterTimeout());
+ this.saturationMultiplierChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.AdvancedGraphics.saturationMultiplier, (newValue) -> this.refreshRenderDataAfterTimeout());
+ this.lodShadingChangeListener = new ConfigChangeListener<>(Config.Client.Advanced.Graphics.AdvancedGraphics.lodShading, (newValue) -> this.refreshRenderDataAfterTimeout());
+
+ }
/** Calling this method multiple times will reset the timer */
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/IConfigListener.java b/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/IConfigListener.java
index 5d643db5b..79ea44005 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/IConfigListener.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/config/listeners/IConfigListener.java
@@ -3,9 +3,9 @@ package com.seibel.distanthorizons.core.config.listeners;
public interface IConfigListener
{
/** Called whenever the value is set (including in core DH code) */
- default void onConfigValueSet() {};
+ default void onConfigValueSet() {}
/** Called whenever the value is changed through the UI */
- default void onUiModify() {};
+ default void onUiModify() {}
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java
index 2fbd85471..92b6d26a1 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/config/types/ConfigEntry.java
@@ -2,6 +2,7 @@ package com.seibel.distanthorizons.core.config.types;
import com.seibel.distanthorizons.core.config.NumberUtil;
+import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
import com.seibel.distanthorizons.core.config.listeners.IConfigListener;
import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance;
import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryPerformance;
@@ -9,6 +10,7 @@ import com.seibel.distanthorizons.coreapi.interfaces.config.IConfigEntry;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.function.Consumer;
/**
* Use for making the config variables
@@ -166,7 +168,16 @@ public class ConfigEntry extends AbstractConfigType> implem
/** Gets the performance impact of an option */
public EConfigEntryPerformance getPerformance() { return this.performance; }
+ /** Fired whenever the config value changes to a new value. */
+ public void addValueChangeListener(Consumer onValueChangeFunc)
+ {
+ ConfigChangeListener changeListener = new ConfigChangeListener<>(this, onValueChangeFunc);
+ this.addListener(changeListener);
+ }
+ /** Fired whenever the config value is updated, including when the value doesn't change (IE when the UI changes state or the config is reloaded). */
public void addListener(IConfigListener newListener) { this.listenerList.add(newListener); }
+
+ //public void removeValueChangeListener(Consumer onValueChangeFunc) { } // not currently implemented
public void removeListener(IConfigListener oldListener) { this.listenerList.remove(oldListener); }
public void clearListeners() { this.listenerList.clear(); }
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java
index b0164d2f7..b87e664bd 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java
@@ -146,7 +146,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler
this.incompleteDataSources.put(pos, dataSource);
// queue this section to be generated
GenTask genTask = new GenTask(pos, new WeakReference<>(dataSource));
- worldGenQueue.submitGenTask(new DhLodPos(pos), dataSource.getDataDetailLevel(), genTask)
+ worldGenQueue.submitGenTask(pos, dataSource.getDataDetailLevel(), genTask)
.whenComplete((genTaskResult, ex) ->
{
if (genTaskResult.success)
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java
index 30c5e64b9..95db143bc 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/file/renderfile/RenderSourceFileHandler.java
@@ -447,7 +447,7 @@ public class RenderSourceFileHandler implements ILodRenderSourceProvider
// Skip updating the cache if the data file is already up-to-date
FullDataMetaFile dataFile = this.fullDataSourceProvider.getFileIfExist(file.pos);
- if (!ALWAYS_INVALIDATE_CACHE && dataFile != null && dataFile.baseMetaData.checksum == file.baseMetaData.dataVersion.get()) {
+ if (!ALWAYS_INVALIDATE_CACHE && dataFile != null && dataFile.baseMetaData != null && dataFile.baseMetaData.checksum == file.baseMetaData.dataVersion.get()) {
LOGGER.debug("Skipping render cache update for {}", file.pos);
renderSource.localVersion.incrementAndGet();
return CompletableFuture.completedFuture(null);
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/IWorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/IWorldGenerationQueue.java
index 7181ae80e..100c6d9fb 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/generation/IWorldGenerationQueue.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/IWorldGenerationQueue.java
@@ -14,7 +14,7 @@ public interface IWorldGenerationQueue extends Closeable
/** the largest numerical detail level */
byte largestDataDetail();
- CompletableFuture submitGenTask(DhLodPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker);
+ CompletableFuture submitGenTask(DhSectionPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker);
void cancelGenTasks(Iterable positions);
/** @param targetPos the position that world generation should be centered around, generally this will be the player's position. */
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java
index 51e34783f..33e3f981b 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/WorldGenerationQueue.java
@@ -41,9 +41,9 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
/** contains the positions that need to be generated */
//private final QuadTree waitingTaskQuadTree;
- private final ConcurrentHashMap waitingTasks = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap waitingTasks = new ConcurrentHashMap<>();
- private final ConcurrentHashMap inProgressGenTasksByLodPos = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap inProgressGenTasksByLodPos = new ConcurrentHashMap<>();
// granularity is the detail level for batching world generator requests together
public final byte maxGranularity;
@@ -73,8 +73,8 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
// debug variables to test for duplicate world generator requests //
/** limits how many of the previous world gen requests we should track */
private static final int MAX_ALREADY_GENERATED_COUNT = 100;
- private final HashMap alreadyGeneratedPosHashSet = new HashMap<>(MAX_ALREADY_GENERATED_COUNT);
- private final Queue alreadyGeneratedPosQueue = new LinkedList<>();
+ private final HashMap alreadyGeneratedPosHashSet = new HashMap<>(MAX_ALREADY_GENERATED_COUNT);
+ private final Queue alreadyGeneratedPosQueue = new LinkedList<>();
private static RateLimitedThreadPoolExecutor worldGeneratorThreadPool;
private static ConfigChangeListener configListener;
@@ -119,7 +119,8 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
// task handling //
//=================//
- public CompletableFuture submitGenTask(DhLodPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker)
+ @Override
+ public CompletableFuture submitGenTask(DhSectionPos pos, byte requiredDataDetail, IWorldGenTaskTracker tracker)
{
// the generator is shutting down, don't add new tasks
if (this.generatorClosingFuture != null)
@@ -139,9 +140,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
}
// Assert that the data at least can fill in 1 single ChunkSizedFullDataAccessor
- LodUtil.assertTrue(pos.detailLevel > requiredDataDetail + LodUtil.CHUNK_DETAIL_LEVEL);
-
- DhSectionPos requestPos = new DhSectionPos(pos.detailLevel, pos.x, pos.z);
+ LodUtil.assertTrue(pos.sectionDetailLevel > requiredDataDetail + LodUtil.CHUNK_DETAIL_LEVEL);
//if (this.waitingTaskQuadTree.isSectionPosInBounds(requestPos))
@@ -330,7 +329,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
}
Mapper closestTaskMap = waitingTasks.reduceEntries(1024,
- v -> new Mapper(v.getValue(), v.getValue().pos.getCenterBlockPos().toPos2D().chebyshevDist(targetPos.toPos2D())),
+ v -> new Mapper(v.getValue(), v.getValue().pos.getSectionBBoxPos().getCenterBlockPos().toPos2D().chebyshevDist(targetPos.toPos2D())),
(a, b) -> a.dist < b.dist ? a : b);
closestTask = closestTaskMap.task;
@@ -375,14 +374,14 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
// split up the task and add each one to the tree
LinkedList> childFutures = new LinkedList<>();
- DhSectionPos sectionPos = new DhSectionPos(closestTask.pos.detailLevel, closestTask.pos.x, closestTask.pos.z);
+ DhSectionPos sectionPos = new DhSectionPos(closestTask.pos.sectionDetailLevel, closestTask.pos.sectionX, closestTask.pos.sectionZ);
WorldGenTask finalClosestTask = closestTask;
sectionPos.forEachChild((childDhSectionPos) ->
{
CompletableFuture newFuture = new CompletableFuture<>();
childFutures.add(newFuture);
- WorldGenTask newGenTask = new WorldGenTask(new DhLodPos(childDhSectionPos.sectionDetailLevel, childDhSectionPos.sectionX, childDhSectionPos.sectionZ), childDhSectionPos.sectionDetailLevel, finalClosestTask.taskTracker, newFuture);
+ WorldGenTask newGenTask = new WorldGenTask(childDhSectionPos, childDhSectionPos.sectionDetailLevel, finalClosestTask.taskTracker, newFuture);
waitingTasks.put(newGenTask.pos, newGenTask);
//this.waitingTaskQuadTree.setValue(new DhSectionPos(childDhSectionPos.sectionDetailLevel, childDhSectionPos.sectionX, childDhSectionPos.sectionZ), newGenTask);
@@ -402,12 +401,12 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
private void startWorldGenTaskGroup(InProgressWorldGenTaskGroup inProgressTaskGroup)
{
byte taskDetailLevel = inProgressTaskGroup.group.dataDetail;
- DhLodPos taskPos = inProgressTaskGroup.group.pos;
- byte granularity = (byte) (taskPos.detailLevel - taskDetailLevel);
+ DhSectionPos taskPos = inProgressTaskGroup.group.pos;
+ byte granularity = (byte) (taskPos.sectionDetailLevel - taskDetailLevel);
LodUtil.assertTrue(granularity >= this.minGranularity && granularity <= this.maxGranularity);
LodUtil.assertTrue(taskDetailLevel >= this.smallestDataDetail && taskDetailLevel <= this.largestDataDetail);
- DhChunkPos chunkPosMin = new DhChunkPos(taskPos.getCornerBlockPos());
+ DhChunkPos chunkPosMin = new DhChunkPos(taskPos.getSectionBBoxPos().getCornerBlockPos());
// check if this is a duplicate generation task
if (this.alreadyGeneratedPosHashSet.containsKey(inProgressTaskGroup.group.pos))
@@ -418,7 +417,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
//StackTraceElement[] stackTrace = this.alreadyGeneratedPosHashSet.get(inProgressTaskGroup.group.pos);
// sending a success result is necessary to make sure the render sections are reloaded correctly
- inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos))));
+ inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.sectionX, taskPos.sectionZ))));
return;
}
this.alreadyGeneratedPosHashSet.put(inProgressTaskGroup.group.pos, Thread.currentThread().getStackTrace());
@@ -427,7 +426,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
// remove extra tracked duplicate positions
while (this.alreadyGeneratedPosQueue.size() > MAX_ALREADY_GENERATED_COUNT)
{
- DhLodPos posToRemove = this.alreadyGeneratedPosQueue.poll();
+ DhSectionPos posToRemove = this.alreadyGeneratedPosQueue.poll();
this.alreadyGeneratedPosHashSet.remove(posToRemove);
}
@@ -452,7 +451,7 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
else
{
//LOGGER.info("Section generation at "+pos+" completed");
- inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos))));
+ inProgressTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(new DhSectionPos(granularity, taskPos.sectionX, taskPos.sectionZ))));
}
boolean worked = this.inProgressGenTasksByLodPos.remove(taskPos, inProgressTaskGroup);
LodUtil.assertTrue(worked);
@@ -666,9 +665,9 @@ public class WorldGenerationQueue implements IWorldGenerationQueue, IDebugRender
// helper methods //
//================//
- private boolean canGeneratePos(byte worldGenTaskGroupDetailLevel /*when in doubt use 0*/ , DhLodPos taskPos)
+ private boolean canGeneratePos(byte worldGenTaskGroupDetailLevel /*when in doubt use 0*/ , DhSectionPos taskPos)
{
- byte granularity = (byte) (taskPos.detailLevel - worldGenTaskGroupDetailLevel);
+ byte granularity = (byte) (taskPos.sectionDetailLevel - worldGenTaskGroupDetailLevel);
return (granularity >= this.minGranularity && granularity <= this.maxGranularity);
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java
index 427bd7396..78fa9a24b 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTask.java
@@ -1,6 +1,7 @@
package com.seibel.distanthorizons.core.generation.tasks;
import com.seibel.distanthorizons.core.pos.DhLodPos;
+import com.seibel.distanthorizons.core.pos.DhSectionPos;
import java.util.concurrent.CompletableFuture;
@@ -10,14 +11,14 @@ import java.util.concurrent.CompletableFuture;
*/
public final class WorldGenTask
{
- public final DhLodPos pos;
+ public final DhSectionPos pos;
public final byte dataDetailLevel;
public final IWorldGenTaskTracker taskTracker;
public final CompletableFuture future;
- public WorldGenTask(DhLodPos pos, byte dataDetail, IWorldGenTaskTracker taskTracker, CompletableFuture future)
+ public WorldGenTask(DhSectionPos pos, byte dataDetail, IWorldGenTaskTracker taskTracker, CompletableFuture future)
{
this.dataDetailLevel = dataDetail;
this.pos = pos;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java
index 3eda6d9b7..209677419 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/generation/tasks/WorldGenTaskGroup.java
@@ -2,6 +2,7 @@ package com.seibel.distanthorizons.core.generation.tasks;
import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor;
import com.seibel.distanthorizons.core.pos.DhLodPos;
+import com.seibel.distanthorizons.core.pos.DhSectionPos;
import java.util.Iterator;
import java.util.LinkedList;
@@ -13,14 +14,14 @@ import java.util.function.Consumer;
*/
public final class WorldGenTaskGroup
{
- public final DhLodPos pos;
+ public final DhSectionPos pos;
public byte dataDetail;
/** Only accessed by the generator polling thread */
public final LinkedList worldGenTasks = new LinkedList<>();
- public WorldGenTaskGroup(DhLodPos pos, byte dataDetail)
+ public WorldGenTaskGroup(DhSectionPos pos, byte dataDetail)
{
this.pos = pos;
this.dataDetail = dataDetail;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/BaseJFrame.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/BaseJFrame.java
index a230fec5e..8445c5d54 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/BaseJFrame.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/gui/BaseJFrame.java
@@ -1,8 +1,5 @@
package com.seibel.distanthorizons.core.jar.gui;
-import com.formdev.flatlaf.FlatDarkLaf;
-import com.formdev.flatlaf.FlatLightLaf;
-import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.seibel.distanthorizons.core.jar.JarUtils;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.ILangWrapper;
@@ -13,6 +10,7 @@ import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.InputStreamReader;
+import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.List;
@@ -41,7 +39,7 @@ public class BaseJFrame extends JFrame
setTitle(SingletonInjector.INSTANCE.get(ILangWrapper.class).getLang("lod.title"));
try
{
- setIconImage(new FlatSVGIcon(JarUtils.accessFile("iconLegacy.svg")).getImage()); // SVG Salamander (the library which we use for svg files) doesn't support css class colors
+ setIconImage(ImageIO.read(JarUtils.accessFile("icon.png")));
}
catch (Exception e)
{
@@ -96,7 +94,8 @@ public class BaseJFrame extends JFrame
add(languageBox);
- // ========== THEMING ==========
+ // ========== THEMING ========== //
+ /**
// TODO: Change the theme to a toggle switch rather than having 2 buttons
int themeButtonSize = 25;
JButton lightMode = null;
@@ -132,6 +131,7 @@ public class BaseJFrame extends JFrame
// Finally add the buttons
add(lightMode);
add(darkMode);
+ */
}
public BaseJFrame addLogo()
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java
index 4e8b1cbe9..dd6eafac6 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java
@@ -287,9 +287,6 @@ public class LodRenderer
{
profiler.popPush("LOD SSAO");
SSAORenderer.INSTANCE.render(partialTicks);
-
- // TODO: Fix this file (or check the result is the same) so that SSAORenderer could be deleted
- //SSAOShader.INSTANCE.render(partialTicks); // For some reason this looks slightly different :/
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java
index 5abae934e..4fe99dcc8 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java
@@ -30,7 +30,6 @@ public class FogShader extends AbstractShaderRenderer
public final int fogVerticalScaleUniform;
public final int nearFogStartUniform;
public final int nearFogLengthUniform;
- ;
public final int fullFogModeUniform;
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java
index 102cf4c5f..553150f8a 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAORenderer.java
@@ -16,18 +16,13 @@ import org.lwjgl.opengl.GL32;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-// TODO: Move over to SSAOShader
-// For some reason this version looks slightly different to that, even tough there isnt much visible change in the code
public class SSAORenderer
{
public static SSAORenderer INSTANCE = new SSAORenderer();
- public SSAORenderer()
- {
- }
-
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
+ private static final int MAX_KERNEL_SIZE = 128;
private static final float[] box_vertices = {
-1, -1,
1, -1,
@@ -37,67 +32,115 @@ public class SSAORenderer
-1, 1,
};
- ShaderProgram ssaoShader;
- ShaderProgram applyShader;
- GLVertexBuffer boxBuffer;
- VertexAttribute va;
- boolean init = false;
- private static final int MAX_KERNEL_SIZE = 32;
+
+ private ShaderProgram ssaoShader;
+ private ShaderProgram applyShader;
+ private GLVertexBuffer boxBuffer;
+ private VertexAttribute va;
+ private boolean init = false;
+
private float[] kernel = new float[MAX_KERNEL_SIZE * 3];
- public void init()
- {
- if (init) return;
-
- init = true;
- va = VertexAttribute.create();
- va.bind();
- // Pos
- va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
- va.completeAndCheck(Float.BYTES * 2);
- ssaoShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag",
- "fragColor", new String[]{"vPosition"});
-
- applyShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/apply-frag.frag",
- "fragColor", new String[]{"vPosition"});
-
-
- // Generate kernel
- kernel = genKernel();
- // Framebuffer
- createBuffer();
- }
-
private int width = -1;
private int height = -1;
private int ssaoFramebuffer = -1;
private int ssaoTexture = -1;
+ // ssao uniforms
+ private final SsaoShaderUniforms ssaoShaderUniforms = new SsaoShaderUniforms();
+ private static class SsaoShaderUniforms
+ {
+ public int gProjUniform;
+ public int gSampleRadUniform;
+ public int gFactorUniform;
+ public int gPowerUniform;
+ public int gKernelUniform;
+ public int gDepthMapUniform;
+ }
+
+ // apply uniforms
+ private final ApplyShaderUniforms applyShaderUniforms = new ApplyShaderUniforms();
+ private static class ApplyShaderUniforms
+ {
+ public int gSSAOMapUniform;
+ public int gDepthMapUniform;
+ }
+
+
+
+ //=============//
+ // constructor //
+ //=============//
+
+ private SSAORenderer() { }
+
+ public void init()
+ {
+ if (this.init)
+ {
+ return;
+ }
+
+
+ this.init = true;
+ this.va = VertexAttribute.create();
+ this.va.bind();
+ // Pos
+ this.va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
+ this.va.completeAndCheck(Float.BYTES * 2);
+ this.ssaoShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag",
+ "fragColor", new String[]{"vPosition"});
+
+ this.applyShader = new ShaderProgram("shaders/normal.vert", "shaders/ssao/apply-frag.frag",
+ "fragColor", new String[]{"vPosition"});
+
+
+
+ // SSAO uniform setup
+ this.ssaoShaderUniforms.gProjUniform = this.ssaoShader.getUniformLocation("gProj");
+ this.ssaoShaderUniforms.gSampleRadUniform = this.ssaoShader.getUniformLocation("gSampleRad");
+ this.ssaoShaderUniforms.gFactorUniform = this.ssaoShader.getUniformLocation("gFactor");
+ this.ssaoShaderUniforms.gPowerUniform = this.ssaoShader.getUniformLocation("gPower");
+ this.ssaoShaderUniforms.gKernelUniform = this.ssaoShader.getUniformLocation("gKernel");
+ this.ssaoShaderUniforms.gDepthMapUniform = this.ssaoShader.getUniformLocation("gDepthMap");
+
+ // Apply uniform setup
+ this.applyShaderUniforms.gSSAOMapUniform = this.applyShader.getUniformLocation("gSSAOMap");
+ this.applyShaderUniforms.gDepthMapUniform = this.applyShader.getUniformLocation("gDepthMap");
+
+
+
+ // Generate kernel
+ this.kernel = genKernel();
+ // Framebuffer
+ this.createBuffer();
+ }
+
private void createFramebuffer(int width, int height)
{
- if (ssaoFramebuffer != -1)
+ if (this.ssaoFramebuffer != -1)
{
- GL32.glDeleteFramebuffers(ssaoFramebuffer);
- ssaoFramebuffer = -1;
+ GL32.glDeleteFramebuffers(this.ssaoFramebuffer);
+ this.ssaoFramebuffer = -1;
}
- if (ssaoTexture != -1)
+ if (this.ssaoTexture != -1)
{
- GL32.glDeleteTextures(ssaoTexture);
- ssaoTexture = -1;
+ GL32.glDeleteTextures(this.ssaoTexture);
+ this.ssaoTexture = -1;
}
- ssaoFramebuffer = GL32.glGenFramebuffers();
- GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer);
+ this.ssaoFramebuffer = GL32.glGenFramebuffers();
+ GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer);
- ssaoTexture = GL32.glGenTextures();
- GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture);
+ this.ssaoTexture = GL32.glGenTextures();
+ GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.ssaoTexture);
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RED, width, height, 0, GL32.GL_RED, GL32.GL_FLOAT, (ByteBuffer) null);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST);
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_NEAREST);
- GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, ssaoTexture, 0);
+ GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.ssaoTexture, 0);
}
private void createBuffer()
@@ -106,9 +149,9 @@ public class SSAORenderer
buffer.order(ByteOrder.nativeOrder());
buffer.asFloatBuffer().put(box_vertices);
buffer.rewind();
- boxBuffer = new GLVertexBuffer(false);
- boxBuffer.bind();
- boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
+ this.boxBuffer = new GLVertexBuffer(false);
+ this.boxBuffer.bind();
+ this.boxBuffer.uploadBuffer(buffer, box_vertices.length, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
}
private static float[] genKernel()
@@ -140,11 +183,16 @@ public class SSAORenderer
return kernel;
}
+
+
+ //========//
+ // render //
+ //========//
+
public void render(float partialTicks)
{
GLState state = new GLState();
- init();
- //GL32.glDepthMask(false);
+ this.init();
int width = MC_RENDER.getTargetFrameBufferViewportWidth();
int height = MC_RENDER.getTargetFrameBufferViewportHeight();
@@ -152,10 +200,10 @@ public class SSAORenderer
{
this.width = width;
this.height = height;
- createFramebuffer(width, height);
+ this.createFramebuffer(width, height);
}
- GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, ssaoFramebuffer);
+ GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.ssaoFramebuffer);
GL32.glViewport(0, 0, width, height);
GL32.glDisable(GL32.GL_DEPTH_TEST);
GL32.glDisable(GL32.GL_BLEND);
@@ -168,35 +216,36 @@ public class SSAORenderer
RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks),
(float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2)));
- ssaoShader.bind();
- ssaoShader.setUniform(ssaoShader.getUniformLocation("gProj"), perspective);
- ssaoShader.setUniform(ssaoShader.getUniformLocation("gSampleRad"), 3.0f);
- ssaoShader.setUniform(ssaoShader.getUniformLocation("gFactor"), 0.8f);
- ssaoShader.setUniform(ssaoShader.getUniformLocation("gPower"), 1.0f);
- va.bind();
- va.bindBufferToAllBindingPoint(boxBuffer.getId());
+ this.ssaoShader.bind();
+ this.ssaoShader.setUniform(this.ssaoShaderUniforms.gProjUniform, perspective);
+ this.ssaoShader.setUniform(this.ssaoShaderUniforms.gSampleRadUniform, 3.0f);
+ this.ssaoShader.setUniform(this.ssaoShaderUniforms.gFactorUniform, 0.8f);
+ this.ssaoShader.setUniform(this.ssaoShaderUniforms.gPowerUniform, 1.0f);
+
+ this.va.bind();
+ this.va.bindBufferToAllBindingPoint(this.boxBuffer.getId());
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
- GL32.glUniform3fv(ssaoShader.getUniformLocation("gKernel"), kernel);
- GL32.glUniform1i(ssaoShader.getUniformLocation("gDepthMap"), 0);
+ GL32.glUniform3fv(this.ssaoShaderUniforms.gKernelUniform, this.kernel);
+ GL32.glUniform1i(this.ssaoShaderUniforms.gDepthMapUniform, 0);
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
- applyShader.bind();
+ this.applyShader.bind();
GL32.glEnable(GL11.GL_BLEND);
GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
GL32.glActiveTexture(GL32.GL_TEXTURE0);
- GL32.glBindTexture(GL32.GL_TEXTURE_2D, ssaoTexture);
- GL32.glUniform1i(applyShader.getUniformLocation("gSSAOMap"), 0);
+ GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.ssaoTexture);
+ GL32.glUniform1i(this.applyShaderUniforms.gSSAOMapUniform, 0);
GL32.glActiveTexture(GL32.GL_TEXTURE1);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, MC_RENDER.getDepthTextureId());
- GL32.glUniform1i(applyShader.getUniformLocation("gDepthMap"), 1);
+ GL32.glUniform1i(this.applyShaderUniforms.gDepthMapUniform, 1);
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, 6);
@@ -206,8 +255,8 @@ public class SSAORenderer
public void free()
{
- ssaoShader.free();
- applyShader.free();
+ this.ssaoShader.free();
+ this.applyShader.free();
}
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java
deleted file mode 100644
index ce357c140..000000000
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOShader.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.seibel.distanthorizons.core.render.renderer.shaders;
-
-import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
-import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAttribute;
-import com.seibel.distanthorizons.core.util.LodUtil;
-import com.seibel.distanthorizons.core.util.RenderUtil;
-import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
-import org.lwjgl.opengl.GL32;
-
-public class SSAOShader extends AbstractShaderRenderer
-{
- public static SSAOShader INSTANCE = new SSAOShader();
-
- private static final int MAX_KERNEL_SIZE = 32;
- private float[] kernel = new float[MAX_KERNEL_SIZE * 3];
-
-
- public SSAOShader()
- {
- super(
- new ShaderProgram("shaders/normal.vert", "shaders/ssao/ao.frag",
- "fragColor", new String[]{"vPosition"}),
- new ShaderProgram("shaders/normal.vert", "shaders/ssao/apply-frag.frag",
- "fragColor", new String[]{"vPosition"})
- );
-
- }
- @Override
- void postInit()
- {
- // Generate kernel
- kernel = genKernel();
- }
-
- @Override
- void setVertexAttributes()
- {
- va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
- }
-
- @Override
- void setShaderUniforms(float partialTicks)
- {
- Mat4f perspective = Mat4f.perspective(
- (float) MC_RENDER.getFov(partialTicks),
- MC_RENDER.getTargetFrameBufferViewportWidth() / (float) MC_RENDER.getTargetFrameBufferViewportHeight(),
- RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks),
- (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2)));
-
- this.shader.setUniform(this.shader.getUniformLocation("gProj"), perspective);
- this.shader.setUniform(this.shader.getUniformLocation("gSampleRad"), 3.0f);
- this.shader.setUniform(this.shader.getUniformLocation("gFactor"), 0.8f);
- this.shader.setUniform(this.shader.getUniformLocation("gPower"), 1.0f);
-
- GL32.glUniform3fv(this.shader.getUniformLocation("gKernel"), kernel);
- GL32.glUniform1i(this.shader.getUniformLocation("gDepthMap"), 0);
- }
-
- private static float[] genKernel()
- {
- float[] kernel = new float[MAX_KERNEL_SIZE * 3];
- for (int i = 0; i < MAX_KERNEL_SIZE; i++)
- {
- float sampleX = (float) (Math.random() * 2.0 - 1.0);
- float sampleY = (float) (Math.random() * 2.0 - 1.0);
- float sampleZ = (float) Math.random();
-
-
- // Normalize
- float magnitude = (float) Math.sqrt(Math.pow(sampleX, 2) + Math.pow(sampleY, 2) + Math.pow(sampleZ, 2));
- sampleX /= magnitude;
- sampleY /= magnitude;
- sampleZ /= magnitude;
-
- float scale = i / (float) MAX_KERNEL_SIZE;
- float interpolatedScale = (float) (0.1 + (scale * scale) * (0.9));
-
- sampleX *= interpolatedScale;
- sampleY *= interpolatedScale;
- sampleZ *= interpolatedScale;
- kernel[i * 3] = sampleX;
- kernel[i * 3 + 1] = sampleY;
- kernel[i * 3 + 2] = sampleZ;
- }
- return kernel;
- }
-
-}
diff --git a/core/src/main/resources/shaders/ssao/ao.frag b/core/src/main/resources/shaders/ssao/ao.frag
index 9538f54c4..0e5501870 100644
--- a/core/src/main/resources/shaders/ssao/ao.frag
+++ b/core/src/main/resources/shaders/ssao/ao.frag
@@ -10,7 +10,7 @@ uniform float gFactor;
uniform float gPower;
uniform mat4 gProj;
-const int MAX_KERNEL_SIZE = 32;
+const int MAX_KERNEL_SIZE = 128;
const float INV_MAX_KERNEL_SIZE_F = 1.0 / float(MAX_KERNEL_SIZE);
const vec2 HALF_2 = vec2(0.5);
uniform vec3 gKernel[MAX_KERNEL_SIZE];
@@ -55,7 +55,7 @@ void main()
float rangeCheck = smoothstep(0.0, 1.0, gSampleRad / abs(viewPos.z - geometryDepth));
// the number added to the samplePos.z can be used to reduce noise in the SSAO application at the cost of reducing the overall affect
- occlusion_factor += float(geometryDepth >= samplePos.z + 1.0) * rangeCheck;
+ occlusion_factor += float(geometryDepth >= samplePos.z + 0.1) * rangeCheck;
}