mirror of
https://github.com/Jozufozu/Flywheel.git
synced 2024-12-26 15:06:28 +01:00
Resolve redirect conflict and add more optifine hacks
- Fix entitiesForRendering redirect to be compatible with carpet. - Use more reflection for dealing with optifine - Fixes issue where flywheel would still be on immediately after enabling optifine shaders
This commit is contained in:
parent
e1af5b2533
commit
a4d3f17fb3
8 changed files with 125 additions and 129 deletions
|
@ -41,8 +41,6 @@ public class Backend {
|
|||
}
|
||||
|
||||
public static void refresh() {
|
||||
OptifineHandler.refresh();
|
||||
|
||||
engine = chooseEngine();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,25 +1,43 @@
|
|||
package com.jozufozu.flywheel.backend;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
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 boolean isUsingShaders;
|
||||
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");
|
||||
|
@ -37,28 +55,21 @@ public final class OptifineHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean areShadersDisabledInOptifineConfigFile() {
|
||||
File dir = Minecraft.getInstance().gameDirectory;
|
||||
|
||||
File shaderOptions = new File(dir, "optionsshaders.txt");
|
||||
|
||||
boolean shadersOff = true;
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(shaderOptions))) {
|
||||
|
||||
shadersOff = reader.lines()
|
||||
.anyMatch(it -> {
|
||||
String line = it.replaceAll("\\s", "");
|
||||
if (line.startsWith("shaderPack=")) {
|
||||
String setting = line.substring("shaderPack=".length());
|
||||
|
||||
return setting.equals("OFF") || setting.equals("(internal)");
|
||||
}
|
||||
return false;
|
||||
});
|
||||
} catch (IOException e) {
|
||||
Backend.LOGGER.info("No shader config found.");
|
||||
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;
|
||||
}
|
||||
return shadersOff;
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
|
@ -67,21 +78,13 @@ public final class OptifineHandler {
|
|||
|
||||
if (isOptifineInstalled) {
|
||||
Backend.LOGGER.info("Optifine detected.");
|
||||
|
||||
refresh();
|
||||
} else {
|
||||
Backend.LOGGER.info("Optifine not detected.");
|
||||
}
|
||||
|
||||
shadersEnabledSupplier = createShadersEnabledSupplier();
|
||||
shadowPassSupplier = createShadowPassSupplier();
|
||||
}
|
||||
|
||||
public static void refresh() {
|
||||
if (!isOptifineInstalled) return;
|
||||
|
||||
boolean shadersOff = areShadersDisabledInOptifineConfigFile();
|
||||
|
||||
isUsingShaders = !shadersOff;
|
||||
shadowFrustumConstructor = createShadowFrustumConstructor();
|
||||
}
|
||||
|
||||
public static boolean isOptifineInstalled() {
|
||||
|
@ -89,10 +92,26 @@ public final class OptifineHandler {
|
|||
}
|
||||
|
||||
public static boolean isUsingShaders() {
|
||||
return 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.jozufozu.flywheel.core.Contexts;
|
|||
import com.jozufozu.flywheel.core.shader.WorldProgram;
|
||||
import com.jozufozu.flywheel.event.BeginFrameEvent;
|
||||
import com.jozufozu.flywheel.event.RenderLayerEvent;
|
||||
import com.jozufozu.flywheel.util.ClientLevelExtension;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
|
@ -130,7 +131,8 @@ public class InstanceWorld {
|
|||
public void loadEntities(ClientLevel world) {
|
||||
// Block entities are loaded while chunks are baked.
|
||||
// Entities are loaded with the world, so when chunks are reloaded they need to be re-added.
|
||||
world.entitiesForRendering()
|
||||
ClientLevelExtension.cast(world)
|
||||
.flywheel$getAllLoadedEntities()
|
||||
.forEach(entityInstanceManager::add);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
package com.jozufozu.flywheel.mixin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Group;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
@Mixin(LevelRenderer.class)
|
||||
public class CancelEntityRenderMixin {
|
||||
|
||||
// TODO: Don't use redirect
|
||||
@Group(name = "entityFilter", min = 1, max = 1)
|
||||
@Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/multiplayer/ClientLevel;entitiesForRendering()Ljava/lang/Iterable;"))
|
||||
private Iterable<Entity> filterEntities(ClientLevel world) {
|
||||
Iterable<Entity> entities = world.entitiesForRendering();
|
||||
if (Backend.isOn()) {
|
||||
ArrayList<Entity> filtered = Lists.newArrayList(entities);
|
||||
|
||||
filtered.removeIf(InstancedRenderRegistry::shouldSkipRender);
|
||||
|
||||
return filtered;
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
// @Group(name = "entityFilter")
|
||||
// @Redirect(method = "renderLevel", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/ClassInstanceMultiMap;iterator()Ljava/util/Iterator;"))
|
||||
// private Iterator<Entity> filterEntitiesOF(ClassInstanceMultiMap<Entity> classInheritanceMultiMap) {
|
||||
// if (Backend.getInstance()
|
||||
// .canUseInstancing()) {
|
||||
//
|
||||
// ArrayList<Entity> filtered = Lists.newArrayList(classInheritanceMultiMap);
|
||||
//
|
||||
// InstancedRenderRegistry r = InstancedRenderRegistry.getInstance();
|
||||
// filtered.removeIf(r::shouldSkipRender);
|
||||
//
|
||||
// return filtered.iterator();
|
||||
// }
|
||||
// return classInheritanceMultiMap.iterator();
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.jozufozu.flywheel.mixin;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.jozufozu.flywheel.backend.Backend;
|
||||
import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry;
|
||||
import com.jozufozu.flywheel.util.ClientLevelExtension;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.level.entity.LevelEntityGetter;
|
||||
|
||||
@Mixin(ClientLevel.class)
|
||||
public abstract class ClientLevelMixin implements ClientLevelExtension {
|
||||
|
||||
@Shadow
|
||||
protected abstract LevelEntityGetter<Entity> getEntities();
|
||||
|
||||
@Override
|
||||
public Iterable<Entity> flywheel$getAllLoadedEntities() {
|
||||
return getEntities().getAll();
|
||||
}
|
||||
|
||||
@Inject(method = "entitiesForRendering", at = @At("RETURN"), cancellable = true)
|
||||
private void filterEntities(CallbackInfoReturnable<Iterable<Entity>> cir) {
|
||||
if (Backend.isOn()) {
|
||||
Iterable<Entity> entities = cir.getReturnValue();
|
||||
ArrayList<Entity> filtered = Lists.newArrayList(entities);
|
||||
|
||||
filtered.removeIf(InstancedRenderRegistry::shouldSkipRender);
|
||||
|
||||
cir.setReturnValue(filtered);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package com.jozufozu.flywheel.mixin;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
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 net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.gui.screens.VideoSettingsScreen;
|
||||
|
||||
@Mixin(Minecraft.class)
|
||||
public class ShaderCloseMixin {
|
||||
|
||||
@Shadow
|
||||
@Nullable
|
||||
public Screen screen;
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "setScreen")
|
||||
private void whenScreenChanges(Screen screen, CallbackInfo info) {
|
||||
if (OptifineHandler.isOptifineInstalled() && screen instanceof VideoSettingsScreen) {
|
||||
Screen old = this.screen;
|
||||
if (old != null && old.getClass()
|
||||
.getName()
|
||||
.startsWith(OptifineHandler.SHADER_PACKAGE)) {
|
||||
OptifineHandler.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.jozufozu.flywheel.util;
|
||||
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
public interface ClientLevelExtension {
|
||||
|
||||
/**
|
||||
* Get an iterator over all entities in this level.
|
||||
*
|
||||
* <p>
|
||||
* Normally, this would be accomplished by {@link ClientLevel#entitiesForRendering()}, but the output of that
|
||||
* method is filtered of entities that are rendered by flywheel. This interface provides a workaround.
|
||||
* </p>
|
||||
* @return An iterator over all entities in the level, including entities that are rendered by flywheel.
|
||||
*/
|
||||
Iterable<Entity> flywheel$getAllLoadedEntities();
|
||||
|
||||
static ClientLevelExtension cast(ClientLevel level) {
|
||||
return (ClientLevelExtension) level;
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
"BufferBuilderMixin",
|
||||
"BufferUploaderMixin",
|
||||
"CameraMixin",
|
||||
"CancelEntityRenderMixin",
|
||||
"ClientLevelMixin",
|
||||
"ChunkRebuildHooksMixin",
|
||||
"EntityTypeMixin",
|
||||
"FixFabulousDepthMixin",
|
||||
|
@ -23,7 +23,6 @@
|
|||
"PausedPartialTickAccessor",
|
||||
"RenderTexturesMixin",
|
||||
"RenderTypeMixin",
|
||||
"ShaderCloseMixin",
|
||||
"atlas.AtlasDataMixin",
|
||||
"atlas.SheetDataAccessor",
|
||||
"light.LightUpdateMixin",
|
||||
|
|
Loading…
Reference in a new issue