diff --git a/api/src/main/java/com/seibel/lod/core/interfaces/dependencyInjection/IBindable.java b/api/src/main/java/com/seibel/lod/core/interfaces/dependencyInjection/IBindable.java
index 37db6fd05..f72eceb28 100644
--- a/api/src/main/java/com/seibel/lod/core/interfaces/dependencyInjection/IBindable.java
+++ b/api/src/main/java/com/seibel/lod/core/interfaces/dependencyInjection/IBindable.java
@@ -37,7 +37,7 @@ public interface IBindable
* If no circular dependencies are required this method
* doesn't have to be implemented.
*/
- public default void finishDelayedSetup() { }
+ default void finishDelayedSetup() { }
/**
* Returns if this dependency has been setup yet.
@@ -45,6 +45,6 @@ public interface IBindable
* If this object doesn't require a delayed setup, this
* method doesn't have to be implemented and should always return true.
*/
- public default boolean getDelayedSetupComplete() { return true; }
+ default boolean getDelayedSetupComplete() { return true; }
}
diff --git a/core/src/main/java/com/seibel/lod/core/IReflectionHandler.java b/core/src/main/java/com/seibel/lod/core/IReflectionHandler.java
index b88a58de4..6a281ad6b 100644
--- a/core/src/main/java/com/seibel/lod/core/IReflectionHandler.java
+++ b/core/src/main/java/com/seibel/lod/core/IReflectionHandler.java
@@ -35,18 +35,13 @@ import com.seibel.lod.core.interfaces.dependencyInjection.IBindable;
* different MC versions.
*
* @author James Seibel
- * @version 3-5-2022
+ * @version 2022-11-24
*/
public interface IReflectionHandler extends IBindable
{
- /** @return Whether Optifine is set to render fog or not. */
- EFogDrawMode getFogDrawMode();
-
- /** @return if Vivecraft is present. Attempts to find the "VRRenderer" class. */
- boolean vivecraftPresent();
-
- /** @return if Sodium (or a sodium like) mod is present. Attempts to find the "SodiumWorldRenderer" class. */
+ /** @return if Sodium (or a sodium like) mod is present. */
boolean sodiumPresent();
boolean optifinePresent();
+
}
diff --git a/core/src/main/java/com/seibel/lod/core/ReflectionHandler.java b/core/src/main/java/com/seibel/lod/core/ReflectionHandler.java
index 0bd82931f..322b126d6 100644
--- a/core/src/main/java/com/seibel/lod/core/ReflectionHandler.java
+++ b/core/src/main/java/com/seibel/lod/core/ReflectionHandler.java
@@ -20,186 +20,69 @@
package com.seibel.lod.core;
import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Field;
-import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.logging.DhLoggerBuilder;
-import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
+import com.seibel.lod.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
import org.apache.logging.log4j.Logger;
-import com.seibel.lod.api.enums.rendering.EFogDrawMode;
-
/**
- * A singleton used to get variables from methods
- * where they are private or potentially absent.
- * For example: the fog setting in Optifine or the
- * presence/absence of Vivecraft.
+ * A singleton used to determine if a class is present or
+ * access variables from methods where they are private
+ * or potentially absent.
+ *
+ * For example: presence/absence of Optifine.
*
* @author James Seibel
- * @version 2022-7-15
+ * @version 2022-11-24
*/
public class ReflectionHandler implements IReflectionHandler
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
- public static ReflectionHandler instance;
-
- private Field ofFogField = null;
- private Object mcOptionsObject;
+ public static final ReflectionHandler INSTANCE = new ReflectionHandler();
+ // populated when the methods are called the first time
private Boolean sodiumPresent = null;
- private boolean optifinePresent = false;
-
- private boolean delayedSetupDone = false;
+ private Boolean optifinePresent = false;
-
- @Override
- public void finishDelayedSetup()
- {
- mcOptionsObject = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).getOptionsObject();
- setupFogField(mcOptionsObject.getClass().getDeclaredFields());
-
- this.delayedSetupDone = true;
- }
-
- @Override
- public boolean getDelayedSetupComplete() { return this.delayedSetupDone; }
-
- private ReflectionHandler()
- {
- mcOptionsObject = null;
- }
-
- /**
- * @return the ReflectionHandler just created
- * @throws IllegalStateException if a ReflectionHandler already exists
- */
- public static ReflectionHandler createSingleton() throws IllegalStateException
- {
- if (instance != null)
- {
- throw new IllegalStateException();
- }
-
- instance = new ReflectionHandler();
- return instance;
- }
+ private ReflectionHandler() { }
+ //===================//
+ // is [mod] present? //
+ //===================//
-
-
- /** finds the Optifine fog type field */
- private void setupFogField(Field[] optionFields)
- {
- // try and find the ofFogType variable in gameSettings
- for (Field field : optionFields)
- {
- if (field.getName().equals("ofFogType"))
- {
- optifinePresent = true;
- ofFogField = field;
- return;
- }
- }
-
- // we didn't find the field,
- // either optifine isn't installed, or
- // optifine changed the name of the variable
- LOGGER.info("Unable to find the Optifine fog field. If Optifine isn't installed this can be ignored.");
- }
-
-
- /**
- * Get what type of fog optifine is currently set to render.
- * @return the fog quality
- */
- @Override
- public EFogDrawMode getFogDrawMode()
- {
- if (ofFogField == null)
- {
- // either optifine isn't installed,
- // the variable name was changed, or
- // the setup method wasn't called yet.
- return EFogDrawMode.FOG_ENABLED;
- }
-
- int returnNum = 0;
-
- try
- {
- returnNum = (int) ofFogField.get(mcOptionsObject);
- }
- catch (IllegalArgumentException | IllegalAccessException e)
- {
- e.printStackTrace();
- }
-
- switch (returnNum)
- {
- default:
- case 0:
- // optifine's "default" option,
- // it should never be called in this case
-
- // normal options
- case 1: // fast
- case 2: // fancy
- return EFogDrawMode.FOG_ENABLED;
- case 3: // off
- return EFogDrawMode.FOG_DISABLED;
- }
- }
-
-
-
- /** Detect if Vivecraft is present. Attempts to find the "VRRenderer" class. */
- @Override
- public boolean vivecraftPresent()
- {
- try
- {
- Class.forName("org.vivecraft.provider.VRRenderer");
- return true;
- }
- catch (ClassNotFoundException ignored)
- {
- LOGGER.info(ReflectionHandler.class.getSimpleName() + ": Vivecraft not detected.");
- }
- return false;
- }
@Override
public boolean optifinePresent()
{
- return optifinePresent;
+ if (this.optifinePresent == null)
+ {
+ // call the base accessor so we don't have duplicate code
+ this.optifinePresent = AbstractOptifineAccessor.isOptifinePresent();
+ }
+ return this.optifinePresent;
}
-
-
@Override
public boolean sodiumPresent()
{
- // we don't want to run a potentially expensive
- // reflection search operation every time this method is called
- if (sodiumPresent == null)
+ if (this.sodiumPresent == null)
{
try
{
Class.forName("me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer");
-
- sodiumPresent = true;
+ this.sodiumPresent = true;
}
catch (ClassNotFoundException e)
{
- sodiumPresent = false;
+ this.sodiumPresent = false;
}
}
- return sodiumPresent;
+ return this.sodiumPresent;
}
}
diff --git a/core/src/main/java/com/seibel/lod/core/dependencyInjection/ModAccessorInjector.java b/core/src/main/java/com/seibel/lod/core/dependencyInjection/ModAccessorInjector.java
index 20233d1ef..aa3befbcb 100644
--- a/core/src/main/java/com/seibel/lod/core/dependencyInjection/ModAccessorInjector.java
+++ b/core/src/main/java/com/seibel/lod/core/dependencyInjection/ModAccessorInjector.java
@@ -28,7 +28,7 @@ import org.apache.logging.log4j.Logger;
import java.lang.invoke.MethodHandles;
/**
- * This class takes care of dependency injection for mods accessors. (for mod compatibility
+ * This class takes care of dependency injection for mod accessors. (for mod compatibility
* support).
*
* If a IModAccessor returns null either that means the mod isn't loaded in the game
diff --git a/core/src/main/java/com/seibel/lod/core/render/fog/LodFogConfig.java b/core/src/main/java/com/seibel/lod/core/render/fog/LodFogConfig.java
index 79cd121f2..4fca8ffb1 100644
--- a/core/src/main/java/com/seibel/lod/core/render/fog/LodFogConfig.java
+++ b/core/src/main/java/com/seibel/lod/core/render/fog/LodFogConfig.java
@@ -21,10 +21,11 @@ package com.seibel.lod.core.render.fog;
import com.seibel.lod.api.enums.rendering.*;
import com.seibel.lod.core.config.Config;
-import com.seibel.lod.core.IReflectionHandler;
+import com.seibel.lod.core.dependencyInjection.ModAccessorInjector;
import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.render.glObject.shader.Shader;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
+import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -39,11 +40,11 @@ import static com.seibel.lod.core.render.glObject.GLProxy.GL_LOGGER;
*
* @author Leetom
* @author James Seibel
- * @version 2022-4-14
+ * @version 2022-11-24
*/
public class LodFogConfig
{
- private static final IReflectionHandler REFLECTION_HANDLER = SingletonInjector.INSTANCE.get(IReflectionHandler.class);
+ private static final IOptifineAccessor OPTIFINE = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonInjector.INSTANCE.get(ILodConfigWrapperSingleton.class);
public static final boolean DEBUG_DUMP_GENERATED_CODE = false;
@@ -62,9 +63,10 @@ public class LodFogConfig
public static LodFogConfig generateFogConfig()
{
EFogDrawMode fogMode = CONFIG.client().graphics().fogQuality().getFogDrawMode();
- if (fogMode == EFogDrawMode.USE_OPTIFINE_SETTING)
- fogMode = REFLECTION_HANDLER.getFogDrawMode();
-
+ if (fogMode == EFogDrawMode.USE_OPTIFINE_SETTING && OPTIFINE != null)
+ {
+ fogMode = OPTIFINE.getFogDrawMode();
+ }
return new LodFogConfig(fogMode);
}
diff --git a/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/AbstractOptifineAccessor.java b/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/AbstractOptifineAccessor.java
new file mode 100644
index 000000000..396306d84
--- /dev/null
+++ b/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/AbstractOptifineAccessor.java
@@ -0,0 +1,113 @@
+package com.seibel.lod.core.wrapperInterfaces.modAccessor;
+
+import com.seibel.lod.api.enums.rendering.EFogDrawMode;
+import com.seibel.lod.core.ReflectionHandler;
+import com.seibel.lod.core.dependencyInjection.SingletonInjector;
+import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
+
+import java.lang.reflect.Field;
+
+/**
+ * Contains any shared code between Optifine for Forge (official Optifine)
+ * and Optifine on Fabric (unofficial ports).
+ *
+ * @version 2022-11-24
+ * @author James Seibel
+ */
+public abstract class AbstractOptifineAccessor implements IOptifineAccessor
+{
+ public Field ofFogField = null;
+ public Object mcOptionsObject = null;
+
+
+
+ //=======//
+ // setup //
+ //=======//
+
+ public void finishDelayedSetup()
+ {
+ this.mcOptionsObject = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).getOptionsObject();
+ this.ofFogField = getOptifineFogField();
+ }
+
+ /** Returns null if Optifine isn't installed. */
+ public static Field getOptifineFogField()
+ {
+ Object mcOptions = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class).getOptionsObject();
+
+ // try and find the ofFogType variable in gameSettings
+ for (Field field : mcOptions.getClass().getDeclaredFields())
+ {
+ if (field.getName().equals("ofFogType"))
+ {
+ return field;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Should not be called frequently since this uses reflection calls to determine if Optifine is present.
+ * Use {@link ReflectionHandler#optifinePresent()} instead.
+ */
+ public static boolean isOptifinePresent() { return getOptifineFogField() != null; }
+
+
+
+ //===================//
+ // interface methods //
+ //===================//
+
+ @Override
+ public EFogDrawMode getFogDrawMode()
+ {
+ if (this.ofFogField == null)
+ {
+ // either optifine isn't installed,
+ // the variable name was changed, or
+ // the setup method wasn't called yet.
+ return EFogDrawMode.FOG_ENABLED;
+ }
+
+ int returnNum = 0;
+
+ try
+ {
+ returnNum = (int) this.ofFogField.get(this.mcOptionsObject);
+ }
+ catch (IllegalArgumentException | IllegalAccessException e)
+ {
+ e.printStackTrace();
+ }
+
+ switch (returnNum)
+ {
+ default:
+ case 0: // optifine's "default" option,
+ // it should never be used, so default to fog Enabled
+
+ // normal options
+ case 1: // fast
+ case 2: // fancy
+ return EFogDrawMode.FOG_ENABLED;
+ case 3: // off
+ return EFogDrawMode.FOG_DISABLED;
+ }
+ }
+
+
+ public double getRenderResolutionMultiplier()
+ {
+ /*
+ * TODO remove comment when done, this is just here as reference
+ * Returns the percentage multiplier of the screen's current resolution.
+ * 1.0 = 100%
+ * 1.5 = 150%
+ */
+
+ // TODO
+ return 1.0;
+ }
+
+}
diff --git a/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/IModAccessor.java b/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/IModAccessor.java
index 698c38786..f718545a9 100644
--- a/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/IModAccessor.java
+++ b/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/IModAccessor.java
@@ -25,6 +25,8 @@ import com.seibel.lod.core.interfaces.dependencyInjection.IBindable;
* @author Leetom
* @version 3-5-2022
*/
-public interface IModAccessor extends IBindable {
+public interface IModAccessor extends IBindable
+{
String getModName();
+
}
diff --git a/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/IOptifineAccessor.java b/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/IOptifineAccessor.java
index b5a935484..c8c74b852 100644
--- a/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/IOptifineAccessor.java
+++ b/core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/IOptifineAccessor.java
@@ -19,23 +19,28 @@
package com.seibel.lod.core.wrapperInterfaces.modAccessor;
+import com.seibel.lod.api.enums.rendering.EFogDrawMode;
+import com.seibel.lod.core.dependencyInjection.SingletonInjector;
import com.seibel.lod.core.pos.DhChunkPos;
+import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
+import java.lang.reflect.Field;
import java.util.HashSet;
public interface IOptifineAccessor extends IModAccessor
{
+
/** Can be null */
HashSet getNormalRenderedChunks();
+ /** Get what type of fog optifine is currently set to render. */
+ EFogDrawMode getFogDrawMode();
+
/**
* Returns the percentage multiplier of the screen's current resolution.
* 1.0 = 100%
* 1.5 = 150%
*/
- default double getRenderResolutionMultiplier()
- {
- return 1.0;
- }
+ double getRenderResolutionMultiplier();
}