From 2b1837e812821e259f9cf461f48e51840f55bafe Mon Sep 17 00:00:00 2001 From: James Seibel Date: Thu, 24 Nov 2022 19:09:52 -0600 Subject: [PATCH] Move Optifine code out of ReflectionHandler and into AbstractOptifineAccessor --- .../dependencyInjection/IBindable.java | 4 +- .../seibel/lod/core/IReflectionHandler.java | 11 +- .../seibel/lod/core/ReflectionHandler.java | 165 +++--------------- .../ModAccessorInjector.java | 2 +- .../lod/core/render/fog/LodFogConfig.java | 14 +- .../modAccessor/AbstractOptifineAccessor.java | 113 ++++++++++++ .../modAccessor/IModAccessor.java | 4 +- .../modAccessor/IOptifineAccessor.java | 13 +- 8 files changed, 163 insertions(+), 163 deletions(-) create mode 100644 core/src/main/java/com/seibel/lod/core/wrapperInterfaces/modAccessor/AbstractOptifineAccessor.java 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(); }