Oculus compatibility

- Rename OptifineHandler to ShadersModHandler
 - Rename functions to match fabric version
This commit is contained in:
Jozufozu 2022-07-10 18:08:59 -04:00
parent c3b1a43beb
commit 273c99619f
7 changed files with 200 additions and 125 deletions

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -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));
}
}