diff --git a/build.gradle b/build.gradle index 928cd432d..341b6b0e2 100644 --- a/build.gradle +++ b/build.gradle @@ -44,6 +44,8 @@ minecraft { property 'forge.logging.markers', '' property 'forge.logging.console.level', 'debug' property 'mixin.debug.export', 'true' + property 'mixin.env.remapRefMap', 'true' + property 'mixin.env.refMapRemappingFile', "${projectDir}/build/createSrgToMcp/output.srg" arg '-mixin.config=flywheel.mixins.json' @@ -102,12 +104,23 @@ repositories { name 'tterrag maven' url 'https://maven.tterrag.com/' } + maven { + name = "Modrinth" + url = "https://api.modrinth.com/maven" + content { + includeGroup "maven.modrinth" + } + } } dependencies { minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" - compileOnly fg.deobf("curse.maven:starlight-526854:3599856") + // switch to implementation for debugging + compileOnly fg.deobf("maven.modrinth:starlight-forge:1.0.2+1.18.2") + + compileOnly fg.deobf("maven.modrinth:rubidium:0.5.2a") + compileOnly fg.deobf("curse.maven:oculus-581495:3821406") // https://discord.com/channels/313125603924639766/725850371834118214/910619168821354497 // Prevent Mixin annotation processor from getting into IntelliJ's annotation processor settings diff --git a/src/main/java/com/jozufozu/flywheel/Flywheel.java b/src/main/java/com/jozufozu/flywheel/Flywheel.java index 3ae7e9691..be8be85d0 100644 --- a/src/main/java/com/jozufozu/flywheel/Flywheel.java +++ b/src/main/java/com/jozufozu/flywheel/Flywheel.java @@ -4,7 +4,7 @@ import org.apache.maven.artifact.versioning.ArtifactVersion; import org.slf4j.Logger; import com.jozufozu.flywheel.backend.Backend; -import com.jozufozu.flywheel.backend.OptifineHandler; +import com.jozufozu.flywheel.backend.ShadersModHandler; import com.jozufozu.flywheel.config.BackendTypeArgument; import com.jozufozu.flywheel.config.FlwCommands; import com.jozufozu.flywheel.config.FlwConfig; @@ -65,7 +65,7 @@ public class Flywheel { private static void clientInit(IEventBus forgeEventBus, IEventBus modEventBus) { CrashReportCallables.registerCrashCallable("Flywheel Backend", Backend::getBackendDescriptor); - OptifineHandler.init(); + ShadersModHandler.init(); Backend.init(); forgeEventBus.addListener(FlwCommands::registerClientCommands); diff --git a/src/main/java/com/jozufozu/flywheel/backend/Backend.java b/src/main/java/com/jozufozu/flywheel/backend/Backend.java index d3be6f353..77528cb30 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/Backend.java +++ b/src/main/java/com/jozufozu/flywheel/backend/Backend.java @@ -96,7 +96,7 @@ public class Backend { BackendType preferredChoice = FlwConfig.get() .getBackendType(); - boolean usingShaders = OptifineHandler.isUsingShaders(); + boolean usingShaders = ShadersModHandler.isShaderPackInUse(); boolean canUseEngine = switch (preferredChoice) { case OFF -> true; case BATCHING -> !usingShaders; diff --git a/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java b/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java deleted file mode 100644 index 1e49c7270..000000000 --- a/src/main/java/com/jozufozu/flywheel/backend/OptifineHandler.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.jozufozu.flywheel.backend; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.function.BooleanSupplier; - -import javax.annotation.Nullable; - -import net.minecraft.client.Camera; -import net.minecraft.client.renderer.culling.Frustum; - -public final class OptifineHandler { - public static final String OPTIFINE_ROOT_PACKAGE = "net.optifine"; - public static final String SHADER_PACKAGE = "net.optifine.shaders"; - - private static boolean isOptifineInstalled; - private static BooleanSupplier shadersEnabledSupplier; - private static BooleanSupplier shadowPassSupplier; - private static FrustumConstructor shadowFrustumConstructor; - - private OptifineHandler() { - } - - private static FrustumConstructor createShadowFrustumConstructor() { - try { - Class ofShaders = Class.forName("net.optifine.shaders.ShadersRender"); - Method method = ofShaders.getDeclaredMethod("makeShadowFrustum", Camera.class, Float.TYPE); - method.setAccessible(true); - return (cam, pt) -> { - try { - return (Frustum) method.invoke(null, cam, pt); - } catch (Exception ignored) { - return null; - } - }; - } catch (Exception ignored) { - return ($, $$) -> null; - } - } - - private static BooleanSupplier createShadowPassSupplier() { - try { - Class ofShaders = Class.forName("net.optifine.shaders.Shaders"); - Field field = ofShaders.getDeclaredField("isShadowPass"); - field.setAccessible(true); - return () -> { - try { - return field.getBoolean(null); - } catch (IllegalAccessException ignored) { - return false; - } - }; - } catch (Exception ignored) { - return () -> false; - } - } - - private static BooleanSupplier createShadersEnabledSupplier() { - try { - Class ofShaders = Class.forName("net.optifine.shaders.Shaders"); - Field field = ofShaders.getDeclaredField("shaderPackLoaded"); - field.setAccessible(true); - return () -> { - try { - return field.getBoolean(null); - } catch (IllegalAccessException ignored) { - return false; - } - }; - } catch (Exception ignored) { - return () -> false; - } - } - - public static void init() { - Package optifinePackage = Package.getPackage(OPTIFINE_ROOT_PACKAGE); - isOptifineInstalled = optifinePackage != null; - - if (isOptifineInstalled) { - Backend.LOGGER.info("Optifine detected."); - } else { - Backend.LOGGER.info("Optifine not detected."); - } - - shadersEnabledSupplier = createShadersEnabledSupplier(); - shadowPassSupplier = createShadowPassSupplier(); - shadowFrustumConstructor = createShadowFrustumConstructor(); - } - - public static boolean isOptifineInstalled() { - return isOptifineInstalled; - } - - public static boolean isUsingShaders() { - return shadersEnabledSupplier.getAsBoolean(); - } - - public static boolean isShadowPass() { - return shadowPassSupplier.getAsBoolean(); - } - - @Nullable - public static Frustum createShadowFrustum(Camera camera, float partialTicks) { - var frustum = shadowFrustumConstructor.create(camera, partialTicks); - if (frustum != null) { - var position = camera.getPosition(); - frustum.prepare(position.x, position.y, position.z); - } - return frustum; - } - - @FunctionalInterface - public interface FrustumConstructor { - @Nullable - Frustum create(Camera camera, float partialTicks); - } -} diff --git a/src/main/java/com/jozufozu/flywheel/backend/ShadersModHandler.java b/src/main/java/com/jozufozu/flywheel/backend/ShadersModHandler.java new file mode 100644 index 000000000..d96eef8a0 --- /dev/null +++ b/src/main/java/com/jozufozu/flywheel/backend/ShadersModHandler.java @@ -0,0 +1,179 @@ +package com.jozufozu.flywheel.backend; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.function.BooleanSupplier; + +import javax.annotation.Nullable; + +import net.irisshaders.iris.api.v0.IrisApi; +import net.minecraft.client.Camera; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraftforge.fml.ModList; + +public final class ShadersModHandler { + public static final String OPTIFINE_ROOT_PACKAGE = "net.optifine"; + public static final String SHADER_PACKAGE = "net.optifine.shaders"; + + private static final boolean isOculusLoaded; + private static final boolean isOptifineInstalled; + private static final InternalHandler internalHandler; + + static { + Package optifinePackage = Package.getPackage(OPTIFINE_ROOT_PACKAGE); + isOptifineInstalled = optifinePackage != null; + isOculusLoaded = ModList.get() + .isLoaded("oculus"); + + // optfine and oculus are assumed to be mutually exclusive + + if (isOptifineInstalled) { + Backend.LOGGER.info("Optifine detected."); + internalHandler = new Optifine(); + } else if (isOculusLoaded) { + Backend.LOGGER.info("Oculus detected."); + internalHandler = new Oculus(); + } else { + Backend.LOGGER.info("No shaders mod detected."); + internalHandler = new InternalHandler() {}; + } + } + + private ShadersModHandler() { + } + + public static void init() { + // noop, load statics + } + + public static boolean isOptifineInstalled() { + return isOptifineInstalled; + } + + public static boolean isOculusLoaded() { + return isOculusLoaded; + } + + public static boolean isShaderPackInUse() { + return internalHandler.isShaderPackInUse(); + } + + public static boolean isRenderingShadowPass() { + return internalHandler.isRenderingShadowPass(); + } + + private interface InternalHandler { + default boolean isShaderPackInUse() { + return false; + }; + + default boolean isRenderingShadowPass() { + return false; + }; + } + + // simple, lovely api calls + private static class Oculus implements InternalHandler { + @Override + public boolean isShaderPackInUse() { + return IrisApi.getInstance() + .isShaderPackInUse(); + } + + @Override + public boolean isRenderingShadowPass() { + return IrisApi.getInstance() + .isRenderingShadowPass(); + } + } + + // evil reflection + private static class Optifine implements InternalHandler { + private final BooleanSupplier shadersEnabledSupplier; + private final BooleanSupplier shadowPassSupplier; + private final FrustumConstructor shadowFrustumConstructor; + + Optifine() { + shadersEnabledSupplier = createShadersEnabledSupplier(); + shadowPassSupplier = createShadowPassSupplier(); + shadowFrustumConstructor = createShadowFrustumConstructor(); + } + + @Override + public boolean isShaderPackInUse() { + return shadersEnabledSupplier.getAsBoolean(); + } + + @Override + public boolean isRenderingShadowPass() { + return shadowPassSupplier.getAsBoolean(); + } + + @Nullable + public Frustum createShadowFrustum(Camera camera, float partialTicks) { + var frustum = shadowFrustumConstructor.create(camera, partialTicks); + if (frustum != null) { + var position = camera.getPosition(); + frustum.prepare(position.x, position.y, position.z); + } + return frustum; + } + + private static FrustumConstructor createShadowFrustumConstructor() { + try { + Class ofShaders = Class.forName("net.optifine.shaders.ShadersRender"); + Method method = ofShaders.getDeclaredMethod("makeShadowFrustum", Camera.class, Float.TYPE); + method.setAccessible(true); + return (cam, pt) -> { + try { + return (Frustum) method.invoke(null, cam, pt); + } catch (Exception ignored) { + return null; + } + }; + } catch (Exception ignored) { + return ($, $$) -> null; + } + } + + private static BooleanSupplier createShadowPassSupplier() { + try { + Class ofShaders = Class.forName("net.optifine.shaders.Shaders"); + Field field = ofShaders.getDeclaredField("isShadowPass"); + field.setAccessible(true); + return () -> { + try { + return field.getBoolean(null); + } catch (IllegalAccessException ignored) { + return false; + } + }; + } catch (Exception ignored) { + return () -> false; + } + } + + private static BooleanSupplier createShadersEnabledSupplier() { + try { + Class ofShaders = Class.forName("net.optifine.shaders.Shaders"); + Field field = ofShaders.getDeclaredField("shaderPackLoaded"); + field.setAccessible(true); + return () -> { + try { + return field.getBoolean(null); + } catch (IllegalAccessException ignored) { + return false; + } + }; + } catch (Exception ignored) { + return () -> false; + } + } + + @FunctionalInterface + public interface FrustumConstructor { + @Nullable + Frustum create(Camera camera, float partialTicks); + } + } +} diff --git a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java index 14b2cd212..37787e7c6 100644 --- a/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java +++ b/src/main/java/com/jozufozu/flywheel/backend/instancing/batching/BatchedMaterialGroup.java @@ -7,7 +7,7 @@ import com.jozufozu.flywheel.api.InstanceData; import com.jozufozu.flywheel.api.MaterialGroup; import com.jozufozu.flywheel.api.struct.Batched; import com.jozufozu.flywheel.api.struct.StructType; -import com.jozufozu.flywheel.backend.OptifineHandler; +import com.jozufozu.flywheel.backend.ShadersModHandler; import com.jozufozu.flywheel.backend.instancing.BatchDrawingTracker; import com.jozufozu.flywheel.backend.instancing.TaskEngine; import com.jozufozu.flywheel.backend.model.DirectVertexConsumer; @@ -56,7 +56,7 @@ public class BatchedMaterialGroup implements MaterialGroup { for (BatchedMaterial material : materials.values()) { for (CPUInstancer instancer : material.models.values()) { - instancer.sbb.context.outputColorDiffuse = !consumer.hasOverlay() && !OptifineHandler.isUsingShaders(); + instancer.sbb.context.outputColorDiffuse = !consumer.hasOverlay() && !ShadersModHandler.isShaderPackInUse(); instancer.submitTasks(stack, pool, consumer); } } diff --git a/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java b/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java index c0edf6bf0..789e2773b 100644 --- a/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java +++ b/src/main/java/com/jozufozu/flywheel/mixin/FrustumMixin.java @@ -5,7 +5,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.jozufozu.flywheel.backend.OptifineHandler; +import com.jozufozu.flywheel.backend.ShadersModHandler; import com.jozufozu.flywheel.core.LastActiveCamera; import com.jozufozu.flywheel.event.BeginFrameEvent; @@ -18,7 +18,7 @@ public class FrustumMixin { @Inject(method = "prepare", at = @At("TAIL")) private void onPrepare(double x, double y, double z, CallbackInfo ci) { - if (OptifineHandler.isShadowPass()) { + if (ShadersModHandler.isRenderingShadowPass()) { MinecraftForge.EVENT_BUS.post(new BeginFrameEvent(Minecraft.getInstance().level, LastActiveCamera.getActiveCamera(), (Frustum) (Object) this)); } }