diff --git a/build.gradle b/build.gradle index d9682793..b4f8a64b 100755 --- a/build.gradle +++ b/build.gradle @@ -23,6 +23,11 @@ version = "0.6" group= "eu.crushedpixel.replaymod" archivesBaseName = "replaymod" +ext { + mixinSrg = new File(project.buildDir, 'tmp/mixins/mixins.srg') + mixinRefMap = new File(project.buildDir, 'tmp/mixins/mixins.replaymod.refmap.json') +} + minecraft { version = "1.8-11.14.1.1402" runDir = "eclipse" @@ -35,6 +40,13 @@ minecraft { mappings = "snapshot_nodoc_20141130" } +repositories { + maven { + name = "SpongePowered Repo" + url = "http://repo.spongepowered.org/maven/" + } +} + configurations { shade compile.extendsFrom shade @@ -43,6 +55,7 @@ configurations { dependencies { compile 'org.projectlombok:lombok:1.16.4' + shade 'org.spongepowered:mixin:0.4.3' shade fileTree(dir: 'libs', includes: ['*.jar']) // you may put jars on which you depend on in ./libs // or you may define them like so.. @@ -61,6 +74,9 @@ dependencies { jar { dependsOn configurations.shade + + from project.mixinRefMap + def noticeDir = file("$buildDir/NOTICE") doFirst { noticeDir.deleteDir() @@ -97,8 +113,10 @@ jar { } manifest { - attributes 'FMLCorePlugin': 'eu.crushedpixel.replaymod.coremod.LoadingPlugin', - 'FMLCorePluginContainsFMLMod': 'false', + attributes 'TweakClass': 'org.spongepowered.asm.launch.MixinTweaker', + 'TweakOrder': '0', + 'MixinConfigs': 'mixins.replaymod.json', + 'FMLCorePlugin': 'eu.crushedpixel.replaymod.coremod.LoadingPlugin', 'FMLAT': 'replaymod_at.cfg' } } @@ -140,4 +158,29 @@ sourceSets { main { output.resourcesDir = output.classesDir } } +reobf.doFirst { + if (project.mixinSrg.exists()) { + addExtraSrgFile project.mixinSrg + } +} + +task copySrgs(type: Copy, dependsOn: 'genSrgs') { + from plugins.getPlugin('forge').delayedFile('{SRG_DIR}') + + include '**/*.srg' + into 'build/srgs' +} + +setupDecompWorkspace.dependsOn copySrgs +setupDevWorkspace.dependsOn copySrgs +compileJava.dependsOn copySrgs + +compileJava { + options.compilerArgs += [ + "-AoutSrgFile=${project.mixinSrg.canonicalPath}", + "-AoutRefMapFile=${project.mixinRefMap.canonicalPath}", + "-AreobfSrgFile=${project.file('build/srgs/mcp-srg.srg').canonicalPath}" + ] +} + defaultTasks 'build' \ No newline at end of file diff --git a/src/main/java/eu/crushedpixel/replaymod/coremod/EntityRendererCT.java b/src/main/java/eu/crushedpixel/replaymod/coremod/EntityRendererCT.java deleted file mode 100644 index d8959020..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/coremod/EntityRendererCT.java +++ /dev/null @@ -1,128 +0,0 @@ -package eu.crushedpixel.replaymod.coremod; - -import net.minecraft.launchwrapper.IClassTransformer; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.tree.*; - -import static org.objectweb.asm.Opcodes.*; - -/** - * Transforms the EntityRenderer class: - * - Adds a new field 'CustomEntityRenderer hook' - * - Moves code of 'loadShader' into 'loadShader$Original' - * - Creates 'loadShader' method (see {@link #createLoadShader(ClassNode, MethodNode)} ()} - * - * Transforms the CustomEntityRenderer class: - * - Method 'original_loadShader' calls 'loadShader$Original' - */ -public class EntityRendererCT implements IClassTransformer { - - private static final String HOOK = "eu.crushedpixel.replaymod.video.entity.CustomEntityRenderer"; - private static final String HOOK_JVM = HOOK.replace('.', '/'); - private static final String HOOK_TYPE = "L" + HOOK_JVM + ";"; - private static final String ENTITY_RENDERER = "net.minecraft.client.renderer.EntityRenderer"; - private static final String ENTITY_RENDERER_JVM = ENTITY_RENDERER.replace('.', '/'); - private static final String ENTITY_RENDERER_TYPE = "L" + ENTITY_RENDERER_JVM + ";"; - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - if (ENTITY_RENDERER.equals(transformedName)) { - if (name.equals(transformedName)) { - return transformEntityRenderer(bytes, "loadShader", "(Lnet/minecraft/util/ResourceLocation;)V"); - } else { - return transformEntityRenderer(bytes, "a", "(Loa;)V"); - } - } else if (HOOK.equals(transformedName)) { - return transformHook(bytes); - } - return bytes; - } - - private byte[] transformHook(byte[] bytes) { - ClassReader classReader = new ClassReader(bytes); - ClassNode classNode = new ClassNode(); - classReader.accept(classNode, 0); - - // Find method - for (MethodNode m : classNode.methods) { - if ("original_loadShader".equals(m.name)) { - m.instructions.clear(); - InsnList iter = m.instructions; - iter.add(new VarInsnNode(ALOAD, 0)); // this - iter.add(new FieldInsnNode(GETFIELD, classNode.name, "proxied", ENTITY_RENDERER_TYPE)); - iter.add(new VarInsnNode(ALOAD, 1)); // resourceLocation - iter.add(new MethodInsnNode(INVOKEVIRTUAL, ENTITY_RENDERER_JVM, "loadShader$Original", m.desc, false)); - iter.add(new InsnNode(RETURN)); - } - } - - ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); - classNode.accept(classWriter); - return classWriter.toByteArray(); - } - - private byte[] transformEntityRenderer(byte[] bytes, String name_loadShader, String desc_loadShader) { - ClassReader classReader = new ClassReader(bytes); - ClassNode classNode = new ClassNode(); - classReader.accept(classNode, 0); - - // Add field - classNode.visitField(ACC_PUBLIC, "hook", HOOK_TYPE, null, null); - - // Find method - MethodNode setupTerrain = null; - for (MethodNode m : classNode.methods) { - if (name_loadShader.equals(m.name) && desc_loadShader.equals(m.desc)) { - setupTerrain = m; - } - } - if (setupTerrain == null) { - throw new NoSuchMethodError("loadShader"); - } - - // Generate new method - classNode.methods.add(createLoadShader(classNode, setupTerrain)); - - // Rename original method - setupTerrain.name = "loadShader$Original"; - setupTerrain.access = ACC_PUBLIC; - - ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); - classNode.accept(classWriter); - return classWriter.toByteArray(); - } - - /** - * public void loadShader(ResourceLocation resourceLocation) { - * if (this.hook == null) { - * loadShader$Original(resourceLocation); - * return; - * } - * hook.loadShader(resourceLocation); - * } - */ - private MethodNode createLoadShader(ClassNode classNode, MethodNode org) { - MethodNode method = new MethodNode(org.access, org.name, org.desc, org.signature, new String[0]); - InsnList list = method.instructions; - list.add(new VarInsnNode(ALOAD, 0)); - list.add(new FieldInsnNode(GETFIELD, classNode.name, "hook", HOOK_TYPE)); - LabelNode labelNotNull = new LabelNode(); - list.add(new JumpInsnNode(IFNONNULL, labelNotNull)); - - list.add(new VarInsnNode(ALOAD, 0)); // this - list.add(new VarInsnNode(ALOAD, 1)); // resourceLocation - list.add(new MethodInsnNode(INVOKEVIRTUAL, classNode.name, "loadShader$Original", org.desc, false)); - list.add(new InsnNode(RETURN)); - - list.add(labelNotNull); - list.add(new FrameNode(F_SAME, 0, null, 0, null)); - list.add(new VarInsnNode(ALOAD, 0)); // this - list.add(new FieldInsnNode(GETFIELD, classNode.name, "hook", HOOK_TYPE)); - list.add(new VarInsnNode(ALOAD, 1)); // resourceLocation - list.add(new MethodInsnNode(INVOKEVIRTUAL, HOOK_JVM, "loadShader", org.desc, false)); - list.add(new InsnNode(RETURN)); - - return method; - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java b/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java index 79bb6223..cb3d61b8 100755 --- a/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java +++ b/src/main/java/eu/crushedpixel/replaymod/coremod/LoadingPlugin.java @@ -1,19 +1,48 @@ package eu.crushedpixel.replaymod.coremod; +import net.minecraftforge.fml.relauncher.CoreModManager; import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; +import org.apache.logging.log4j.LogManager; +import org.spongepowered.asm.launch.MixinBootstrap; +import org.spongepowered.asm.mixin.MixinEnvironment; +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.security.CodeSource; import java.util.Map; public class LoadingPlugin implements IFMLLoadingPlugin { + public LoadingPlugin() { + MixinBootstrap.init(); + MixinEnvironment.getDefaultEnvironment().addConfiguration("mixins.replaymod.json"); + + CodeSource codeSource = getClass().getProtectionDomain().getCodeSource(); + if (codeSource != null) { + URL location = codeSource.getLocation(); + try { + File file = new File(location.toURI()); + if (file.isFile()) { + // This forces forge to reexamine the jar file for FML mods + // Should eventually be handled by Mixin itself, maybe? + CoreModManager.getLoadedCoremods().remove(file.getName()); + } + } catch (URISyntaxException e) { + e.printStackTrace(); + } + } else { + LogManager.getLogger().warn("No CodeSource, if this is not a development environment we might run into problems!"); + LogManager.getLogger().warn(getClass().getProtectionDomain()); + } + } + @Override public String[] getASMTransformerClass() { return new String[]{ CameraRollCT.class.getName(), ForceChunkLoadingCT.class.getName(), - EntityRendererCT.class.getName(), NoNameTagCT.class.getName(), - RenderManagerCT.class.getName(), SoundManagerCT.class.getName(), EnchantmentTimerCT.class.getName() }; diff --git a/src/main/java/eu/crushedpixel/replaymod/coremod/RenderManagerCT.java b/src/main/java/eu/crushedpixel/replaymod/coremod/RenderManagerCT.java deleted file mode 100644 index b1f11c99..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/coremod/RenderManagerCT.java +++ /dev/null @@ -1,81 +0,0 @@ -package eu.crushedpixel.replaymod.coremod; - -import net.minecraft.launchwrapper.IClassTransformer; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.tree.*; - -import java.util.ListIterator; - -import static org.objectweb.asm.Opcodes.*; - -/** - * Transforms the RenderManager class: - * - Adds a new field 'CubicEntityRenderer hook' - * - Injects CubicEntityRenderer.beforeEntityRender(dx, dy, dz) call at beginning of 'doRenderEntity' - */ -public class RenderManagerCT implements IClassTransformer { - - private static final String HOOK = "eu.crushedpixel.replaymod.video.entity.CubicEntityRenderer"; - private static final String HOOK_JVM = HOOK.replace('.', '/'); - private static final String HOOK_TYPE = "L" + HOOK_JVM + ";"; - private static final String RENDER_MANAGER = "net.minecraft.client.renderer.entity.RenderManager"; - - @Override - public byte[] transform(String name, String transformedName, byte[] bytes) { - if (RENDER_MANAGER.equals(transformedName)) { - if (name.equals(transformedName)) { - return transformRenderManager(bytes, "doRenderEntity", "(Lnet/minecraft/entity/Entity;DDDFFZ)Z"); - } else { - return transformRenderManager(bytes, "a", "(Lwv;DDDFFZ)Z"); - } - } - return bytes; - } - - private byte[] transformRenderManager(byte[] bytes, String name_doRenderEntity, String desc_doRenderEntity) { - ClassReader classReader = new ClassReader(bytes); - ClassNode classNode = new ClassNode(); - classReader.accept(classNode, 0); - - // Add field - classNode.visitField(ACC_PUBLIC, "hook", HOOK_TYPE, null, null); - - // Find method - MethodNode doRenderEntity = null; - for (MethodNode m : classNode.methods) { - if (name_doRenderEntity.equals(m.name) && desc_doRenderEntity.equals(m.desc)) { - doRenderEntity = m; - } - } - if (doRenderEntity == null) { - throw new NoSuchMethodError("doRenderEntity"); - } - - injectDoRenderEntity(classNode, doRenderEntity); - - ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS); - classNode.accept(classWriter); - return classWriter.toByteArray(); - } - - private MethodNode injectDoRenderEntity(ClassNode classNode, MethodNode method) { - ListIterator list = method.instructions.iterator(); - list.add(new VarInsnNode(ALOAD, 0)); - list.add(new FieldInsnNode(GETFIELD, classNode.name, "hook", HOOK_TYPE)); - LabelNode labelNull = new LabelNode(); - list.add(new JumpInsnNode(IFNULL, labelNull)); - - list.add(new VarInsnNode(ALOAD, 0)); // this - list.add(new FieldInsnNode(GETFIELD, classNode.name, "hook", HOOK_TYPE)); - list.add(new VarInsnNode(DLOAD, 2)); // x - list.add(new VarInsnNode(DLOAD, 4)); // y - list.add(new VarInsnNode(DLOAD, 6)); // z - list.add(new MethodInsnNode(INVOKEVIRTUAL, HOOK_JVM, "beforeEntityRender", "(DDD)V", false)); - - list.add(labelNull); - list.add(new FrameNode(F_SAME, 0, null, 0, null)); - - return method; - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEffectRenderer.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEffectRenderer.java new file mode 100644 index 00000000..a72d7513 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEffectRenderer.java @@ -0,0 +1,48 @@ +package eu.crushedpixel.replaymod.mixin; + +import eu.crushedpixel.replaymod.video.EntityRendererHandler; +import eu.crushedpixel.replaymod.video.capturer.CubicOpenGlFrameCapturer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.particle.EffectRenderer; +import net.minecraft.client.particle.EntityFX; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(EffectRenderer.class) +public class MixinEffectRenderer { + @Redirect(method = "renderParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/EntityFX;func_180434_a(Lnet/minecraft/client/renderer/WorldRenderer;Lnet/minecraft/entity/Entity;FFFFFF)V")) + private void renderNormalParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks, + float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { + renderParticle(fx, worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); + } + + @Redirect(method = "renderLitParticles", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/particle/EntityFX;func_180434_a(Lnet/minecraft/client/renderer/WorldRenderer;Lnet/minecraft/entity/Entity;FFFFFF)V")) + private void renderLitParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks, + float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { + renderParticle(fx, worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); + } + + private void renderParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks, + float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { + EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).getHandler(); + if (handler != null && handler.data instanceof CubicOpenGlFrameCapturer.Data) { + // Align all particles towards the camera + double dx = fx.prevPosX + (fx.posX - fx.prevPosX) * partialTicks - view.posX; + double dy = fx.prevPosY + (fx.posY - fx.prevPosY) * partialTicks - view.posY; + double dz = fx.prevPosZ + (fx.posZ - fx.prevPosZ) * partialTicks - view.posZ; + double pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz)); + double yaw = -Math.atan2(dx, dz); + + rotX = (float) Math.cos(yaw); + rotZ = (float) Math.sin(yaw); + rotXZ = (float) Math.cos(pitch); + + rotYZ = (float) (-rotZ * Math.sin(pitch)); + rotXY = (float) (rotX * Math.sin(pitch)); + } + fx.func_180434_a(worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java new file mode 100644 index 00000000..6a8072e9 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinEntityRenderer.java @@ -0,0 +1,237 @@ +package eu.crushedpixel.replaymod.mixin; + +import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; +import eu.crushedpixel.replaymod.replay.ReplayHandler; +import eu.crushedpixel.replaymod.settings.RenderOptions; +import eu.crushedpixel.replaymod.video.EntityRendererHandler; +import eu.crushedpixel.replaymod.video.capturer.CubicOpenGlFrameCapturer; +import eu.crushedpixel.replaymod.video.capturer.StereoscopicOpenGlFrameCapturer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.EntityRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.RenderGlobal; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.MovingObjectPosition; +import org.lwjgl.opengl.GL11; +import org.lwjgl.util.glu.Project; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(EntityRenderer.class) +public abstract class MixinEntityRenderer implements EntityRendererHandler.IEntityRenderer, EntityRendererHandler.GluPerspective { + private EntityRendererHandler handler; + private SpectatorRenderer spectatorRenderer; + + @Override + public void setHandler(EntityRendererHandler handler) { + this.handler = handler; + if (spectatorRenderer != null) { + spectatorRenderer.cleanup(); + spectatorRenderer = null; + } + if (handler != null) { + spectatorRenderer = new SpectatorRenderer(); + } + } + + @Override + public EntityRendererHandler getHandler() { + return handler; + } + + @Inject(method = "setupFog", at = @At("HEAD"), cancellable = true) + private void onSetupFog(int fogDistanceFlag, float partialTicks, CallbackInfo ci) { + if (handler == null) return; + if (!handler.getOptions().isDefaultSky()) { + ci.cancel(); + } + } + + @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/culling/Frustum;setPosition(DDD)V")) + public void createNoCullingFrustum(Frustum frustum, double x, double y, double z) { + if (handler != null) { + frustum.clippingHelper = new EntityRendererHandler.NoCullingClippingHelper(); + } + frustum.setPosition(x, y, z); + } + + @Inject(method = "orientCamera", at = @At("HEAD")) + private void resetRotationIfNeeded(float partialTicks, CallbackInfo ci) { + if (handler != null) { + Entity entity = Minecraft.getMinecraft().getRenderViewEntity(); + RenderOptions options = handler.getOptions(); + if (options.getIgnoreCameraRotation()[0]) { + entity.prevRotationYaw = entity.rotationYaw = 0; + } + if (options.getIgnoreCameraRotation()[1]) { + entity.prevRotationPitch = entity.rotationPitch = 0; + } + if (options.getIgnoreCameraRotation()[2]) { + ReplayHandler.setCameraTilt(0); + } + } + } + + private float orgYaw; + private float orgPitch; + private float orgPrevYaw; + private float orgPrevPitch; + private float orgRoll; + + @Inject(method = "setupCameraTransform", at = @At("HEAD")) + private void beforeSetupCameraTransform(float partialTicks, int renderPass, CallbackInfo ci) { + if (handler != null) { + Entity entity = Minecraft.getMinecraft().getRenderViewEntity(); + orgYaw = entity.rotationYaw; + orgPitch = entity.rotationPitch; + orgPrevYaw = entity.prevRotationYaw; + orgPrevPitch = entity.prevRotationPitch; + orgRoll = ReplayHandler.getCameraTilt(); + } + } + + @Inject(method = "setupCameraTransform", at = @At("RETURN")) + private void afterSetupCameraTransform(float partialTicks, int renderPass, CallbackInfo ci) { + if (handler != null) { + Entity entity = Minecraft.getMinecraft().getRenderViewEntity(); + entity.rotationYaw = orgYaw; + entity.rotationPitch = orgPitch; + entity.prevRotationYaw = orgPrevYaw; + entity.prevRotationPitch = orgPrevPitch; + ReplayHandler.setCameraTilt(orgRoll); + } + } + + @Inject(method = "renderHand", at = @At("HEAD"), cancellable = true) + private void renderSpectatorHand(float partialTicks, int renderPass, CallbackInfo ci) { + if (handler != null) { + if (handler.data instanceof CubicOpenGlFrameCapturer.Data) { + return; // No spectator hands during 360° view, we wouldn't even know where to put it + } + Entity currentEntity = ReplayHandler.getCurrentEntity(); + if (!ReplayHandler.isCamera() && currentEntity instanceof EntityPlayer) { + renderPass = handler.data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0; + spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass); + } + } + } + + @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/MovingObjectPosition;IF)V")) + private void drawSelectionBox(RenderGlobal instance, EntityPlayer player, MovingObjectPosition mop, int alwaysZero, float partialTicks) { + if (handler == null) { + instance.drawSelectionBox(player, mop, alwaysZero, partialTicks); + } + } + + private int orgRenderDistanceChunks; + + @Inject(method = "renderWorldPass", at = @At(value = "JUMP", ordinal = 0)) + private void beforeRenderSky(CallbackInfo ci) { + if (handler != null && !handler.getOptions().isDefaultSky()) { + GameSettings settings = Minecraft.getMinecraft().gameSettings; + orgRenderDistanceChunks = settings.renderDistanceChunks; + settings.renderDistanceChunks = 5; // Set render distance to 5 so we're always rendering sky when chroma keying + } + } + + @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;renderSky(FI)V")) + private void renderSky(RenderGlobal instance, float partialTicks, int renderPass) { + if (handler != null && !handler.getOptions().isDefaultSky()) { + Minecraft.getMinecraft().gameSettings.renderDistanceChunks = orgRenderDistanceChunks; + int c = handler.getOptions().getSkyColor(); + GlStateManager.clearColor((c >> 16 & 0xff) / (float) 0xff, (c >> 8 & 0xff) / (float) 0xff, (c & 0xff) / (float) 0xff, 1); + GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT); + } else { + instance.renderSky(partialTicks, renderPass); + } + } + + /* + * Cubic Renderer + */ + + @Inject(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;loadIdentity()V", shift = At.Shift.AFTER, ordinal = 0)) + private void setupStereoscopicProjection(float partialTicks, int renderPass, CallbackInfo ci) { + if (getHandler() != null) { + if (getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) { + GlStateManager.translate(0.07, 0, 0); + } else if (getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) { + GlStateManager.translate(-0.07, 0, 0); + } + } + } + + @Inject(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GlStateManager;loadIdentity()V", shift = At.Shift.AFTER, ordinal = 1)) + private void setupStereoscopicModelView(float partialTicks, int renderPass, CallbackInfo ci) { + if (getHandler() != null) { + if (getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) { + GlStateManager.translate(0.1, 0, 0); + } else if (getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) { + GlStateManager.translate(-0.1, 0, 0); + } + } + } + + /* + * Cubic Renderer + */ + + @Redirect(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false)) + private void gluPerspective$0(float fovY, float aspect, float zNear, float zFar) { + gluPerspective(fovY, aspect, zNear, zFar); + } + + @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false)) + private void gluPerspective$1(float fovY, float aspect, float zNear, float zFar) { + gluPerspective(fovY, aspect, zNear, zFar); + } + + @Redirect(method = "renderCloudsCheck", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V", remap = false)) + private void gluPerspective$2(float fovY, float aspect, float zNear, float zFar) { + gluPerspective(fovY, aspect, zNear, zFar); + } + + @Override + public void gluPerspective(float fovY, float aspect, float zNear, float zFar) { + if (getHandler() != null && getHandler().data instanceof CubicOpenGlFrameCapturer.Data) { + fovY = 90; + aspect = 1; + } + Project.gluPerspective(fovY, aspect, zNear, zFar); + } + + @Inject(method = "orientCamera", at = @At("HEAD")) + private void setupCubicFrameRotation(float partialTicks, CallbackInfo ci) { + if (getHandler() != null && getHandler().data instanceof CubicOpenGlFrameCapturer.Data) { + switch ((CubicOpenGlFrameCapturer.Data) getHandler().data) { + case FRONT: + GlStateManager.rotate(0, 0.0F, 1.0F, 0.0F); + break; + case RIGHT: + GlStateManager.rotate(90, 0.0F, 1.0F, 0.0F); + break; + case BACK: + GlStateManager.rotate(180, 0.0F, 1.0F, 0.0F); + break; + case LEFT: + GlStateManager.rotate(-90, 0.0F, 1.0F, 0.0F); + break; + case BOTTOM: + GlStateManager.rotate(90, 1.0F, 0.0F, 0.0F); + break; + case TOP: + GlStateManager.rotate(-90, 1.0F, 0.0F, 0.0F); + break; + } + + // Minecraft goes back a little so we have to invert that + GlStateManager.translate(0.0F, 0.0F, 0.1F); + } + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderManager.java b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderManager.java new file mode 100644 index 00000000..49b4e525 --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/mixin/MixinRenderManager.java @@ -0,0 +1,32 @@ +package eu.crushedpixel.replaymod.mixin; + +import eu.crushedpixel.replaymod.video.EntityRendererHandler; +import eu.crushedpixel.replaymod.video.capturer.CubicOpenGlFrameCapturer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.entity.Entity; +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; + +@Mixin(RenderManager.class) +public class MixinRenderManager { + @Shadow + private float playerViewX; + + @Shadow + private float playerViewY; + + @Inject(method = "doRenderEntity", at = @At("HEAD")) + private void reorientForCubicRendering(Entity entity, double dx, double dy, double dz, float iDoNotKnow, float partialTicks, boolean iDoNotCare, CallbackInfoReturnable ci) { + EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) Minecraft.getMinecraft().entityRenderer).getHandler(); + if (handler != null && handler.data instanceof CubicOpenGlFrameCapturer.Data) { + double pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz)); + double yaw = -Math.atan2(dx, dz); + playerViewX = (float) Math.toDegrees(pitch); + playerViewY = (float) Math.toDegrees(yaw); + } + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/renderer/SpectatorRenderer.java b/src/main/java/eu/crushedpixel/replaymod/renderer/SpectatorRenderer.java index 529e58da..e168c6ce 100644 --- a/src/main/java/eu/crushedpixel/replaymod/renderer/SpectatorRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/renderer/SpectatorRenderer.java @@ -2,6 +2,7 @@ package eu.crushedpixel.replaymod.renderer; import eu.crushedpixel.replaymod.replay.ReplayHandler; import eu.crushedpixel.replaymod.utils.SkinProvider; +import eu.crushedpixel.replaymod.video.EntityRendererHandler; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -25,7 +26,6 @@ import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import org.lwjgl.opengl.GL11; -import org.lwjgl.util.glu.Project; public class SpectatorRenderer { @@ -43,10 +43,6 @@ public class SpectatorRenderer { return (EntityPlayer)current; } - protected void gluPerspective(float fovY, float aspect, float zNear, float zFar) { - Project.gluPerspective(fovY, aspect, zNear, zFar); - } - public void renderSpectatorHand(EntityPlayer entityPlayer, float partialTicks, int renderPass) { if(entityPlayer.isInvisible()) return; @@ -65,7 +61,7 @@ public class SpectatorRenderer { GlStateManager.translate((float)(-(renderPass * 2 - 1)) * f1, 0.0F, 0.0F); } - gluPerspective(mc.entityRenderer.getFOVModifier(partialTicks, false), + ((EntityRendererHandler.GluPerspective) mc.entityRenderer).gluPerspective(mc.entityRenderer.getFOVModifier(partialTicks, false), (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, mc.entityRenderer.farPlaneDistance * 2.0F); GlStateManager.matrixMode(GL11.GL_MODELVIEW); diff --git a/src/main/java/eu/crushedpixel/replaymod/video/EntityRendererHandler.java b/src/main/java/eu/crushedpixel/replaymod/video/EntityRendererHandler.java new file mode 100644 index 00000000..216ca14f --- /dev/null +++ b/src/main/java/eu/crushedpixel/replaymod/video/EntityRendererHandler.java @@ -0,0 +1,89 @@ +package eu.crushedpixel.replaymod.video; + +import eu.crushedpixel.replaymod.coremod.asm_Hooks; +import eu.crushedpixel.replaymod.settings.RenderOptions; +import eu.crushedpixel.replaymod.video.capturer.CaptureData; +import eu.crushedpixel.replaymod.video.capturer.WorldRenderer; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.culling.ClippingHelper; +import org.lwjgl.util.ReadableDimension; + +import java.io.IOException; + +import static net.minecraft.client.renderer.GlStateManager.*; + +public class EntityRendererHandler implements WorldRenderer { + public final Minecraft mc = Minecraft.getMinecraft(); + + @Getter + protected final RenderOptions options; + + public CaptureData data; + + public EntityRendererHandler(RenderOptions options) { + this.options = options; + + if (options.isHideNameTags()) { + asm_Hooks.DO_NOT_RENDER_NAME_TAGS = true; + } + + ((IEntityRenderer) mc.entityRenderer).setHandler(this); + } + + public void withDisplaySize(int displayWidth, int displayHeight, Runnable runnable) { + final int prevWidth = mc.displayWidth; + final int prevHeight = mc.displayHeight; + mc.displayWidth = displayWidth; + mc.displayHeight = displayHeight; + + runnable.run(); + + mc.displayWidth = prevWidth; + mc.displayHeight = prevHeight; + } + + @Override + public void renderWorld(ReadableDimension displaySize, final float partialTicks, CaptureData data) { + this.data = data; + withDisplaySize(displaySize.getWidth(), displaySize.getHeight(), new Runnable() { + @Override + public void run() { + renderWorld(partialTicks, 0); + } + }); + } + + public void renderWorld(float partialTicks, long finishTimeNano) { + mc.entityRenderer.updateLightmap(partialTicks); + + enableDepth(); + enableAlpha(); + alphaFunc(516, 0.5F); + + mc.entityRenderer.renderWorldPass(2, partialTicks, finishTimeNano); + } + + @Override + public void close() throws IOException { + ((IEntityRenderer) mc.entityRenderer).setHandler(null); + + asm_Hooks.DO_NOT_RENDER_NAME_TAGS = false; + } + + public static final class NoCullingClippingHelper extends ClippingHelper { + @Override + public boolean isBoxInFrustum(double p_78553_1_, double p_78553_3_, double p_78553_5_, double p_78553_7_, double p_78553_9_, double p_78553_11_) { + return true; + } + } + + public interface GluPerspective { + void gluPerspective(float fovY, float aspect, float zNear, float zFar); + } + + public interface IEntityRenderer { + void setHandler(EntityRendererHandler handler); + EntityRendererHandler getHandler(); + } +} diff --git a/src/main/java/eu/crushedpixel/replaymod/video/capturer/CubicOpenGlFrameCapturer.java b/src/main/java/eu/crushedpixel/replaymod/video/capturer/CubicOpenGlFrameCapturer.java index c8f8c3d1..fce13bbc 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/capturer/CubicOpenGlFrameCapturer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/capturer/CubicOpenGlFrameCapturer.java @@ -8,7 +8,7 @@ public class CubicOpenGlFrameCapturer extends OpenGlFrameCapturer worldRenderer, RenderInfo renderInfo, int frameSize) { + public CubicOpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo, int frameSize) { super(worldRenderer, renderInfo); this.frameSize = frameSize; } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/capturer/CubicPboOpenGlFrameCapturer.java b/src/main/java/eu/crushedpixel/replaymod/video/capturer/CubicPboOpenGlFrameCapturer.java index 193d5496..8fb1a03a 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/capturer/CubicPboOpenGlFrameCapturer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/capturer/CubicPboOpenGlFrameCapturer.java @@ -7,8 +7,7 @@ public class CubicPboOpenGlFrameCapturer extends MultiFramePboOpenGlFrameCapturer { private final int frameSize; - public CubicPboOpenGlFrameCapturer(WorldRenderer worldRenderer, - RenderInfo renderInfo, int frameSize) { + public CubicPboOpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo, int frameSize) { super(worldRenderer, renderInfo, CubicOpenGlFrameCapturer.Data.class, frameSize * frameSize); this.frameSize = frameSize; } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/capturer/MultiFramePboOpenGlFrameCapturer.java b/src/main/java/eu/crushedpixel/replaymod/video/capturer/MultiFramePboOpenGlFrameCapturer.java index 1673a26e..683a21f3 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/capturer/MultiFramePboOpenGlFrameCapturer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/capturer/MultiFramePboOpenGlFrameCapturer.java @@ -15,7 +15,7 @@ public abstract class MultiFramePboOpenGlFrameCapturer worldRenderer, RenderInfo renderInfo, Class type, int framePixels) { + public MultiFramePboOpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo, Class type, int framePixels) { super(worldRenderer, renderInfo); data = type.getEnumConstants(); @@ -97,6 +97,7 @@ public abstract class MultiFramePboOpenGlFrameCapturer implements FrameCapturer { - protected final WorldRenderer worldRenderer; + protected final WorldRenderer worldRenderer; protected final RenderInfo renderInfo; protected int framesDone; private Framebuffer frameBuffer; - public OpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo) { + public OpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo) { this.worldRenderer = worldRenderer; this.renderInfo = renderInfo; } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/capturer/SimpleOpenGlFrameCapturer.java b/src/main/java/eu/crushedpixel/replaymod/video/capturer/SimpleOpenGlFrameCapturer.java index bf5ac060..29f6bd0c 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/capturer/SimpleOpenGlFrameCapturer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/capturer/SimpleOpenGlFrameCapturer.java @@ -4,7 +4,7 @@ import eu.crushedpixel.replaymod.video.frame.OpenGlFrame; public class SimpleOpenGlFrameCapturer extends OpenGlFrameCapturer { - public SimpleOpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo) { + public SimpleOpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo) { super(worldRenderer, renderInfo); } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/capturer/SimplePboOpenGlFrameCapturer.java b/src/main/java/eu/crushedpixel/replaymod/video/capturer/SimplePboOpenGlFrameCapturer.java index c07dfd4e..39806adc 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/capturer/SimplePboOpenGlFrameCapturer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/capturer/SimplePboOpenGlFrameCapturer.java @@ -14,7 +14,7 @@ public class SimplePboOpenGlFrameCapturer extends OpenGlFrameCapturer worldRenderer, RenderInfo renderInfo) { + public SimplePboOpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo) { super(worldRenderer, renderInfo); ReadableDimension size = renderInfo.getFrameSize(); @@ -81,6 +81,7 @@ public class SimplePboOpenGlFrameCapturer extends OpenGlFrameCapturer worldRenderer, RenderInfo renderInfo) { + public StereoscopicOpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo) { super(worldRenderer, renderInfo); } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/capturer/StereoscopicPboOpenGlFrameCapturer.java b/src/main/java/eu/crushedpixel/replaymod/video/capturer/StereoscopicPboOpenGlFrameCapturer.java index d4cd3cab..f4a5d632 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/capturer/StereoscopicPboOpenGlFrameCapturer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/capturer/StereoscopicPboOpenGlFrameCapturer.java @@ -6,8 +6,7 @@ import eu.crushedpixel.replaymod.video.frame.StereoscopicOpenGlFrame; public class StereoscopicPboOpenGlFrameCapturer extends MultiFramePboOpenGlFrameCapturer { - public StereoscopicPboOpenGlFrameCapturer(WorldRenderer worldRenderer, - RenderInfo renderInfo) { + public StereoscopicPboOpenGlFrameCapturer(WorldRenderer worldRenderer, RenderInfo renderInfo) { super(worldRenderer, renderInfo, StereoscopicOpenGlFrameCapturer.Data.class, renderInfo.getFrameSize().getWidth() / 2 * renderInfo.getFrameSize().getHeight()); } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/capturer/WorldRenderer.java b/src/main/java/eu/crushedpixel/replaymod/video/capturer/WorldRenderer.java index 295b3a4a..6eb74cf9 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/capturer/WorldRenderer.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/capturer/WorldRenderer.java @@ -4,6 +4,6 @@ import org.lwjgl.util.ReadableDimension; import java.io.Closeable; -public interface WorldRenderer extends Closeable { - void renderWorld(ReadableDimension displaySize, float partialTicks, D data); +public interface WorldRenderer extends Closeable { + void renderWorld(ReadableDimension displaySize, float partialTicks, CaptureData data); } diff --git a/src/main/java/eu/crushedpixel/replaymod/video/entity/CubicEntityRenderer.java b/src/main/java/eu/crushedpixel/replaymod/video/entity/CubicEntityRenderer.java deleted file mode 100644 index 82a9698e..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/video/entity/CubicEntityRenderer.java +++ /dev/null @@ -1,117 +0,0 @@ -package eu.crushedpixel.replaymod.video.entity; - -import eu.crushedpixel.replaymod.settings.RenderOptions; -import eu.crushedpixel.replaymod.video.capturer.CubicOpenGlFrameCapturer; -import net.minecraft.client.particle.EntityFX; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.renderer.entity.RenderManager; -import net.minecraft.entity.Entity; -import net.minecraft.util.ResourceLocation; - -import java.io.IOException; -import java.lang.reflect.Field; - -public class CubicEntityRenderer extends CustomEntityRenderer { - - public CubicEntityRenderer(RenderOptions options) { - super(options); - - try { - Field hookField = RenderManager.class.getField("hook"); - hookField.set(mc.getRenderManager(), this); - } catch (NoSuchFieldException e) { - throw new Error(e); - } catch (IllegalAccessException e) { - throw new Error(e); - } - } - - @Override - public void close() throws IOException{ - super.close(); - try { - Field hookField = RenderManager.class.getField("hook"); - hookField.set(mc.getRenderManager(), null); - } catch (NoSuchFieldException e) { - throw new Error(e); - } catch (IllegalAccessException e) { - throw new Error(e); - } - } - - @Override - protected void gluPerspective(float fovY, float aspect, float zNear, float zFar) { - super.gluPerspective(90, 1, zNear, zFar); - } - - @Override - public void loadShader(ResourceLocation resourceLocation) { - if (proxied.theShaderGroup != null) { - proxied.theShaderGroup.deleteShaderGroup(); - proxied.theShaderGroup = null; - } - proxied.useShader = false; - } - - @Override - protected void orientCamera(float partialTicks) { - // Rotate - switch (data) { - case FRONT: - GlStateManager.rotate(0, 0.0F, 1.0F, 0.0F); - break; - case RIGHT: - GlStateManager.rotate(90, 0.0F, 1.0F, 0.0F); - break; - case BACK: - GlStateManager.rotate(180, 0.0F, 1.0F, 0.0F); - break; - case LEFT: - GlStateManager.rotate(-90, 0.0F, 1.0F, 0.0F); - break; - case BOTTOM: - GlStateManager.rotate(90, 1.0F, 0.0F, 0.0F); - break; - case TOP: - GlStateManager.rotate(-90, 1.0F, 0.0F, 0.0F); - break; - } - - // Minecraft goes back a little so we have to invert that - GlStateManager.translate(0.0F, 0.0F, 0.1F); - super.orientCamera(partialTicks); - } - - @Override - protected void renderSpectatorHand(float partialTicks, int renderPass) { - // No spectator hands during 360° view - } - - @Override - protected void renderParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks, float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { - // Align all particles towards the camera - double dx = fx.prevPosX + (fx.posX - fx.prevPosX) * partialTicks - view.posX; - double dy = fx.prevPosY + (fx.posY - fx.prevPosY) * partialTicks - view.posY; - double dz = fx.prevPosZ + (fx.posZ - fx.prevPosZ) * partialTicks - view.posZ; - double pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz)); - double yaw = -Math.atan2(dx, dz); - - rotX = (float) Math.cos(yaw); - rotZ = (float) Math.sin(yaw); - rotXZ = (float) Math.cos(pitch); - - rotYZ = (float) (-rotZ * Math.sin(pitch)); - rotXY = (float) (rotX * Math.sin(pitch)); - - super.renderParticle(fx, worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); - } - - @SuppressWarnings("unused") // Called by ASM - public void beforeEntityRender(double dx, double dy, double dz) { - double pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz)); - double yaw = -Math.atan2(dx, dz); - mc.getRenderManager().playerViewX = (float) Math.toDegrees(pitch); - mc.getRenderManager().playerViewY = (float) Math.toDegrees(yaw); - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/video/entity/CustomEntityRenderer.java b/src/main/java/eu/crushedpixel/replaymod/video/entity/CustomEntityRenderer.java deleted file mode 100644 index fb246c94..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/video/entity/CustomEntityRenderer.java +++ /dev/null @@ -1,465 +0,0 @@ -package eu.crushedpixel.replaymod.video.entity; - -import eu.crushedpixel.replaymod.coremod.asm_Hooks; -import eu.crushedpixel.replaymod.renderer.SpectatorRenderer; -import eu.crushedpixel.replaymod.replay.ReplayHandler; -import eu.crushedpixel.replaymod.settings.RenderOptions; -import eu.crushedpixel.replaymod.video.capturer.CaptureData; -import net.minecraft.client.Minecraft; -import net.minecraft.client.particle.EffectRenderer; -import net.minecraft.client.particle.EntityFX; -import net.minecraft.client.renderer.*; -import net.minecraft.client.renderer.culling.ClippingHelperImpl; -import net.minecraft.client.renderer.culling.ICamera; -import net.minecraft.client.renderer.texture.TextureManager; -import net.minecraft.client.renderer.texture.TextureMap; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.AxisAlignedBB; -import net.minecraft.util.EnumWorldBlockLayer; -import net.minecraft.util.MathHelper; -import net.minecraft.util.ResourceLocation; -import org.lwjgl.util.ReadableDimension; -import org.lwjgl.util.glu.Project; - -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.List; - -import static net.minecraft.client.renderer.GlStateManager.*; -import static org.lwjgl.opengl.GL11.*; - -public class CustomEntityRenderer implements eu.crushedpixel.replaymod.video.capturer.WorldRenderer { - public final Minecraft mc = Minecraft.getMinecraft(); - public final EntityRenderer proxied = mc.entityRenderer; - protected final SpectatorRenderer spectatorRenderer = new SpectatorRenderer(){ - @Override - protected void gluPerspective(float fovY, float aspect, float zNear, float zFar) { - CustomEntityRenderer.this.gluPerspective(fovY, aspect, zNear, zFar); - } - }; - - public GluPerspectiveHook gluPerspectiveHook; - public LoadShaderHook loadShaderHook; - protected int frameCount; - - protected D data; - - protected final RenderOptions options; - - - public CustomEntityRenderer(RenderOptions options) { - this.options = options; - - // Install entity renderer hooks - try { - Field hookField = EntityRenderer.class.getField("hook"); - hookField.set(proxied, this); - } catch (NoSuchFieldException e) { - throw new Error(e); - } catch (IllegalAccessException e) { - throw new Error(e); - } - - if (options.isHideNameTags()) { - asm_Hooks.DO_NOT_RENDER_NAME_TAGS = true; - } - } - - @SuppressWarnings("unused") // Method called by ASM hook - public void loadShader(ResourceLocation resourceLocation) { - if (loadShaderHook != null) { - loadShaderHook.loadShader(resourceLocation); - } else { - original_loadShader(resourceLocation); - } - } - - @SuppressWarnings("unused") - protected final void original_loadShader(ResourceLocation resourceLocation) { - // Method body generated by ASM - } - - protected void gluPerspective(float fovY, float aspect, float zNear, float zFar) { - if (gluPerspectiveHook == null) { - Project.gluPerspective(fovY, aspect, zNear, zFar); - } else { - gluPerspectiveHook.gluPerspective(fovY, aspect, zNear, zFar); - } - } - - public void withDisplaySize(int displayWidth, int displayHeight, Runnable runnable) { - final int prevWidth = mc.displayWidth; - final int prevHeight = mc.displayHeight; - mc.displayWidth = displayWidth; - mc.displayHeight = displayHeight; - - runnable.run(); - - mc.displayWidth = prevWidth; - mc.displayHeight = prevHeight; - } - - public void renderWorld(float partialTicks, long finishTimeNano) { - proxied.updateLightmap(partialTicks); - - enableDepth(); - enableAlpha(); - alphaFunc(516, 0.5F); - - renderWorldPass(partialTicks, finishTimeNano, 2); - } - - protected void renderWorldPass(float partialTicks, long finishTimeNano, int renderPass) { - RenderGlobal renderglobal = mc.renderGlobal; - Entity entity = mc.getRenderViewEntity(); - enableCull(); - viewport(0, 0, mc.displayWidth, mc.displayHeight); - proxied.updateFogColor(partialTicks); - clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - setupCameraTransform(partialTicks); - ActiveRenderInfo.updateRenderInfo(mc.thePlayer, mc.gameSettings.thirdPersonView == 2); - ClippingHelperImpl.getInstance(); - ICamera camera = new NoCullingCamera(); - - if (this.mc.gameSettings.renderDistanceChunks >= 4 || !options.isDefaultSky() ) { - setupFog(-1, partialTicks); - matrixMode(GL_PROJECTION); - loadIdentity(); - gluPerspective(proxied.getFOVModifier(partialTicks, true), (float) mc.displayWidth / mc.displayHeight, 0.05F, proxied.farPlaneDistance * 2.0F); - matrixMode(GL_MODELVIEW); - if (options.isDefaultSky()) { - renderglobal.renderSky(partialTicks, renderPass); - } else { - int c = options.getSkyColor(); - clearColor((c >> 16 & 0xff) / (float) 0xff, (c >> 8 & 0xff) / (float) 0xff, (c & 0xff) / (float) 0xff, 1); - clear(GL_COLOR_BUFFER_BIT); - } - matrixMode(GL_PROJECTION); - loadIdentity(); - gluPerspective(proxied.getFOVModifier(partialTicks, true), (float) mc.displayWidth / mc.displayHeight, 0.05F, proxied.farPlaneDistance * MathHelper.SQRT_2); - matrixMode(GL_MODELVIEW); - } - - setupFog(0, partialTicks); - shadeModel(GL_SMOOTH); - - if (entity.posY + entity.getEyeHeight() < 128) { - renderCloudsCheck(renderglobal, partialTicks, renderPass); - } - - setupFog(0, partialTicks); - mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); - RenderHelper.disableStandardItemLighting(); - renderglobal.setupTerrain(entity, partialTicks, camera, frameCount++, mc.thePlayer.isSpectator()); - - renderglobal.updateChunks(finishTimeNano); - - matrixMode(GL_MODELVIEW); - pushMatrix(); - disableAlpha(); - renderglobal.renderBlockLayer(EnumWorldBlockLayer.SOLID, partialTicks, renderPass, entity); - enableAlpha(); - renderglobal.renderBlockLayer(EnumWorldBlockLayer.CUTOUT_MIPPED, partialTicks, renderPass, entity); - mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(false, false); - renderglobal.renderBlockLayer(EnumWorldBlockLayer.CUTOUT, partialTicks, renderPass, entity); - mc.getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap(); - shadeModel(GL_FLAT); - alphaFunc(516, 0.1F); - - matrixMode(GL_MODELVIEW); - popMatrix(); - pushMatrix(); - RenderHelper.enableStandardItemLighting(); - - net.minecraftforge.client.ForgeHooksClient.setRenderPass(0); - renderglobal.renderEntities(entity, camera, partialTicks); - net.minecraftforge.client.ForgeHooksClient.setRenderPass(0); - RenderHelper.disableStandardItemLighting(); - proxied.disableLightmap(); - matrixMode(GL_MODELVIEW); - popMatrix(); - - enableBlend(); - tryBlendFuncSeparate(770, 1, 1, 0); - renderglobal.drawBlockDamageTexture(Tessellator.getInstance(), Tessellator.getInstance().getWorldRenderer(), entity, partialTicks); - disableBlend(); - - renderParticles(entity, partialTicks); - - depthMask(false); - enableCull(); - proxied.renderRainSnow(partialTicks); - depthMask(true); - renderglobal.renderWorldBorder(entity, partialTicks); - disableBlend(); - enableCull(); - tryBlendFuncSeparate(770, 771, 1, 0); - alphaFunc(516, 0.1F); - setupFog(0, partialTicks); - enableBlend(); - depthMask(false); - mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); - shadeModel(GL_SMOOTH); - - if (mc.gameSettings.fancyGraphics) { - enableBlend(); - tryBlendFuncSeparate(770, 771, 1, 0); - renderglobal.renderBlockLayer(EnumWorldBlockLayer.TRANSLUCENT, partialTicks, renderPass, entity); - disableBlend(); - } else { - renderglobal.renderBlockLayer(EnumWorldBlockLayer.TRANSLUCENT, partialTicks, renderPass, entity); - } - - RenderHelper.enableStandardItemLighting(); - net.minecraftforge.client.ForgeHooksClient.setRenderPass(1); - renderglobal.renderEntities(entity, camera, partialTicks); - net.minecraftforge.client.ForgeHooksClient.setRenderPass(-1); - RenderHelper.disableStandardItemLighting(); - - shadeModel(GL_FLAT); - depthMask(true); - enableCull(); - disableBlend(); - disableFog(); - - if (entity.posY + entity.getEyeHeight() >= 128) { - renderCloudsCheck(renderglobal, partialTicks, renderPass); - } - - net.minecraftforge.client.ForgeHooksClient.dispatchRenderLast(renderglobal, partialTicks); - - renderSpectatorHand(partialTicks, renderPass); - } - - protected void renderParticles(Entity entity, float partialTicks) { - proxied.enableLightmap(); - renderLitParticles(entity, partialTicks); - RenderHelper.disableStandardItemLighting(); - setupFog(0, partialTicks); - renderNormalParticles(entity, partialTicks); - proxied.disableLightmap(); - } - - protected void renderLitParticles(Entity entity, float partialTicks) { - EffectRenderer effectRenderer = mc.effectRenderer; - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldrenderer = tessellator.getWorldRenderer(); - - double yaw = Math.toRadians(entity.rotationYaw); - double pitch = Math.toRadians(entity.rotationPitch); - - float rotX = (float) Math.cos(yaw); - float rotZ = (float) Math.sin(yaw); - float rotXZ = (float) Math.cos(pitch); - - float rotYZ = (float) (-rotZ * Math.sin(pitch)); - float rotXY = (float) (rotX * Math.sin(pitch)); - - for (int i = 0; i < 2; i++) { - @SuppressWarnings("unchecked") - List list = (List) effectRenderer.fxLayers[3][i]; - for (EntityFX fx : list) { - worldrenderer.setBrightness(fx.getBrightnessForRender(partialTicks)); - renderParticle(fx, worldrenderer, entity, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); - } - } - } - - protected void renderNormalParticles(Entity entity, float partialTicks) { - EffectRenderer effectRenderer = mc.effectRenderer; - TextureManager textureManager = mc.getTextureManager(); - Tessellator tessellator = Tessellator.getInstance(); - WorldRenderer worldRenderer = tessellator.getWorldRenderer(); - - double yaw = Math.toRadians(entity.rotationYaw); - double pitch = Math.toRadians(entity.rotationPitch); - - float rotX = (float) Math.cos(yaw); - float rotZ = (float) Math.sin(yaw); - float rotXZ = (float) Math.cos(pitch); - - float rotYZ = (float) (-rotZ * Math.sin(pitch)); - float rotXY = (float) (rotX * Math.sin(pitch)); - - EntityFX.interpPosX = entity.posX; - EntityFX.interpPosY = entity.posY; - EntityFX.interpPosZ = entity.posZ; - - enableBlend(); - blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - alphaFunc(GL_GREATER, 0.003921569F); - - for (int texture = 0; texture < 3; texture++) { - for (int depthMask = 0; depthMask < 2; depthMask++) { - if (effectRenderer.fxLayers[texture][depthMask].isEmpty()) { - continue; - } - - if (depthMask == 0) { - GlStateManager.depthMask(false); - } else { - GlStateManager.depthMask(true); - } - - if (texture == 1) { - textureManager.bindTexture(TextureMap.locationBlocksTexture); - } else { - textureManager.bindTexture(EffectRenderer.particleTextures); - } - - color(1, 1, 1, 1); - worldRenderer.startDrawingQuads(); - - @SuppressWarnings("unchecked") - List list = (List) effectRenderer.fxLayers[texture][depthMask]; - for (final EntityFX fx : list) { - worldRenderer.setBrightness(fx.getBrightnessForRender(partialTicks)); - renderParticle(fx, worldRenderer, entity, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); - } - - tessellator.draw(); - } - } - - depthMask(true); - disableBlend(); - alphaFunc(516, 0.1F); - } - - protected void renderParticle(EntityFX fx, WorldRenderer worldRenderer, Entity view, float partialTicks, - float rotX, float rotXZ, float rotZ, float rotYZ, float rotXY) { - fx.func_180434_a(worldRenderer, view, partialTicks, rotX, rotXZ, rotZ, rotYZ, rotXY); - } - - protected void renderSpectatorHand(float partialTicks, int renderPass) { - Entity currentEntity = ReplayHandler.getCurrentEntity(); - if(!ReplayHandler.isCamera() && currentEntity instanceof EntityPlayer) { - spectatorRenderer.renderSpectatorHand((EntityPlayer) currentEntity, partialTicks, renderPass); - } - } - - protected void setupCameraTransform(float partialTicks) { - Entity entity = mc.getRenderViewEntity(); - float orgYaw = entity.rotationYaw; - float orgPitch = entity.rotationPitch; - float orgPrevYaw = entity.prevRotationYaw; - float orgPrevPitch = entity.prevRotationPitch; - float orgRoll = ReplayHandler.getCameraTilt(); - - proxied.farPlaneDistance = (float)(this.mc.gameSettings.renderDistanceChunks * 16); - - matrixMode(GL_PROJECTION); - loadIdentity(); - - gluPerspective(proxied.getFOVModifier(partialTicks, true), (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, proxied.farPlaneDistance * MathHelper.SQRT_2); - - matrixMode(GL_MODELVIEW); - loadIdentity(); - - orientCamera(partialTicks); - - entity.rotationYaw = orgYaw; - entity.rotationPitch = orgPitch; - entity.prevRotationYaw = orgPrevYaw; - entity.prevRotationPitch = orgPrevPitch; - ReplayHandler.setCameraTilt(orgRoll); - } - - protected void setupFog(int fogDistanceFlag, float partialTicks) { - if (options.isDefaultSky()) { - proxied.setupFog(fogDistanceFlag, partialTicks); - } - } - - protected void orientCamera(float partialTicks) { - Entity entity = mc.getRenderViewEntity(); - if (options.getIgnoreCameraRotation()[0]) { - entity.prevRotationYaw = entity.rotationYaw = 0; - } - if (options.getIgnoreCameraRotation()[1]) { - entity.prevRotationPitch = entity.rotationPitch = 0; - } - if (options.getIgnoreCameraRotation()[2]) { - ReplayHandler.setCameraTilt(0); - } - - proxied.orientCamera(partialTicks); - } - - protected void renderCloudsCheck(RenderGlobal renderglobal, float partialTicks, int renderPass) { - if (this.mc.gameSettings.shouldRenderClouds()) { - matrixMode(GL_PROJECTION); - loadIdentity(); - gluPerspective(proxied.getFOVModifier(partialTicks, true), (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, proxied.farPlaneDistance * 4.0F); - matrixMode(GL_MODELVIEW); - pushMatrix(); - setupFog(0, partialTicks); - renderglobal.renderClouds(partialTicks, renderPass); - disableFog(); - popMatrix(); - matrixMode(GL_PROJECTION); - loadIdentity(); - gluPerspective(proxied.getFOVModifier(partialTicks, true), (float)this.mc.displayWidth / (float)this.mc.displayHeight, 0.05F, proxied.farPlaneDistance * MathHelper.SQRT_2); - matrixMode(GL_MODELVIEW); - } - } - - @Override - public void close() throws IOException { - try { - Field hookField = EntityRenderer.class.getField("hook"); - hookField.set(proxied, null); - } catch (NoSuchFieldException e) { - throw new Error(e); - } catch (IllegalAccessException e) { - throw new Error(e); - } - - asm_Hooks.DO_NOT_RENDER_NAME_TAGS = false; - - spectatorRenderer.cleanup(); - } - - @Override - public void renderWorld(ReadableDimension displaySize, final float partialTicks, D data) { - this.data = data; - withDisplaySize(displaySize.getWidth(), displaySize.getHeight(), new Runnable() { - @Override - public void run() { - renderWorld(partialTicks, 0); - if (OpenGlHelper.shadersSupported) { - if (proxied.theShaderGroup != null && proxied.useShader) { - matrixMode(GL_TEXTURE); - - pushMatrix(); - loadIdentity(); - proxied.theShaderGroup.loadShaderGroup(partialTicks); - popMatrix(); - } - } - } - }); - } - - public static final class NoCullingCamera implements ICamera { - - @Override - public boolean isBoundingBoxInFrustum(AxisAlignedBB p_78546_1_) { - return true; - } - - @Override - public void setPosition(double p_78547_1_, double p_78547_3_, double p_78547_5_) { - - } - } - - public interface GluPerspectiveHook { - void gluPerspective(float fovY, float aspect, float zNear, float zFar); - } - - public interface LoadShaderHook { - void loadShader(ResourceLocation resourceLocation); - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/video/entity/StereoscopicEntityRenderer.java b/src/main/java/eu/crushedpixel/replaymod/video/entity/StereoscopicEntityRenderer.java deleted file mode 100644 index d2587a65..00000000 --- a/src/main/java/eu/crushedpixel/replaymod/video/entity/StereoscopicEntityRenderer.java +++ /dev/null @@ -1,54 +0,0 @@ -package eu.crushedpixel.replaymod.video.entity; - -import eu.crushedpixel.replaymod.settings.RenderOptions; -import eu.crushedpixel.replaymod.video.capturer.StereoscopicOpenGlFrameCapturer; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.util.MathHelper; -import net.minecraft.util.ResourceLocation; - -import static net.minecraft.client.renderer.GlStateManager.loadIdentity; -import static net.minecraft.client.renderer.GlStateManager.matrixMode; -import static org.lwjgl.opengl.GL11.GL_MODELVIEW; -import static org.lwjgl.opengl.GL11.GL_PROJECTION; - -public class StereoscopicEntityRenderer extends CustomEntityRenderer { - - public StereoscopicEntityRenderer(RenderOptions options) { - super(options); - } - - @Override - public void loadShader(ResourceLocation resourceLocation) { - if (proxied.theShaderGroup != null) { - proxied.theShaderGroup.deleteShaderGroup(); - proxied.theShaderGroup = null; - } - proxied.useShader = false; - } - - protected void translateStereoscopic() { - GlStateManager.translate(data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 0.07 : -0.07, 0, 0); - } - - @Override - protected void setupCameraTransform(float partialTicks) { - proxied.farPlaneDistance = (float)(this.mc.gameSettings.renderDistanceChunks * 16); - - matrixMode(GL_PROJECTION); - loadIdentity(); - translateStereoscopic(); - - gluPerspective(proxied.getFOVModifier(partialTicks, true), (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, proxied.farPlaneDistance * MathHelper.SQRT_2); - - matrixMode(GL_MODELVIEW); - loadIdentity(); - translateStereoscopic(); - - orientCamera(partialTicks); - } - - @Override - protected void renderSpectatorHand(float partialTicks, int renderPass) { - super.renderSpectatorHand(partialTicks, data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE ? 1 : 0); - } -} diff --git a/src/main/java/eu/crushedpixel/replaymod/video/rendering/Pipelines.java b/src/main/java/eu/crushedpixel/replaymod/video/rendering/Pipelines.java index a212c605..91d12aa0 100644 --- a/src/main/java/eu/crushedpixel/replaymod/video/rendering/Pipelines.java +++ b/src/main/java/eu/crushedpixel/replaymod/video/rendering/Pipelines.java @@ -2,10 +2,8 @@ package eu.crushedpixel.replaymod.video.rendering; import eu.crushedpixel.replaymod.opengl.PixelBufferObject; import eu.crushedpixel.replaymod.settings.RenderOptions; +import eu.crushedpixel.replaymod.video.EntityRendererHandler; import eu.crushedpixel.replaymod.video.capturer.*; -import eu.crushedpixel.replaymod.video.entity.CubicEntityRenderer; -import eu.crushedpixel.replaymod.video.entity.CustomEntityRenderer; -import eu.crushedpixel.replaymod.video.entity.StereoscopicEntityRenderer; import eu.crushedpixel.replaymod.video.frame.CubicOpenGlFrame; import eu.crushedpixel.replaymod.video.frame.OpenGlFrame; import eu.crushedpixel.replaymod.video.frame.RGBFrame; @@ -40,9 +38,9 @@ public class Pipelines { RenderOptions options = renderInfo.getRenderOptions(); FrameCapturer capturer; if (PixelBufferObject.SUPPORTED) { - capturer = new SimplePboOpenGlFrameCapturer(new CustomEntityRenderer(options), renderInfo); + capturer = new SimplePboOpenGlFrameCapturer(new EntityRendererHandler(options), renderInfo); } else { - capturer = new SimpleOpenGlFrameCapturer(new CustomEntityRenderer(options), renderInfo); + capturer = new SimpleOpenGlFrameCapturer(new EntityRendererHandler(options), renderInfo); } return new Pipeline(capturer, new OpenGlToRGBProcessor(), consumer); } @@ -51,9 +49,9 @@ public class Pipelines { RenderOptions options = renderInfo.getRenderOptions(); FrameCapturer capturer; if (PixelBufferObject.SUPPORTED) { - capturer = new StereoscopicPboOpenGlFrameCapturer(new StereoscopicEntityRenderer(options), renderInfo); + capturer = new StereoscopicPboOpenGlFrameCapturer(new EntityRendererHandler(options), renderInfo); } else { - capturer = new StereoscopicOpenGlFrameCapturer(new StereoscopicEntityRenderer(options), renderInfo); + capturer = new StereoscopicOpenGlFrameCapturer(new EntityRendererHandler(options), renderInfo); } return new Pipeline(capturer, new StereoscopicToRGBProcessor(), consumer); } @@ -62,9 +60,9 @@ public class Pipelines { RenderOptions options = renderInfo.getRenderOptions(); FrameCapturer capturer; if (PixelBufferObject.SUPPORTED) { - capturer = new CubicPboOpenGlFrameCapturer(new CubicEntityRenderer(options), renderInfo, options.getWidth() / 4); + capturer = new CubicPboOpenGlFrameCapturer(new EntityRendererHandler(options), renderInfo, options.getWidth() / 4); } else { - capturer = new CubicOpenGlFrameCapturer(new CubicEntityRenderer(options), renderInfo, options.getWidth() / 4); + capturer = new CubicOpenGlFrameCapturer(new EntityRendererHandler(options), renderInfo, options.getWidth() / 4); } return new Pipeline(capturer, new CubicToRGBProcessor(), consumer); } @@ -73,9 +71,9 @@ public class Pipelines { RenderOptions options = renderInfo.getRenderOptions(); FrameCapturer capturer; if (PixelBufferObject.SUPPORTED) { - capturer = new CubicPboOpenGlFrameCapturer(new CubicEntityRenderer(options), renderInfo, options.getWidth() / 4); + capturer = new CubicPboOpenGlFrameCapturer(new EntityRendererHandler(options), renderInfo, options.getWidth() / 4); } else { - capturer = new CubicOpenGlFrameCapturer(new CubicEntityRenderer(options), renderInfo, options.getWidth() / 4); + capturer = new CubicOpenGlFrameCapturer(new EntityRendererHandler(options), renderInfo, options.getWidth() / 4); } return new Pipeline(capturer, new EquirectangularToRGBProcessor(options.getWidth() / 4), consumer); } diff --git a/src/main/resources/META-INF/replaymod_at.cfg b/src/main/resources/META-INF/replaymod_at.cfg index 223cde53..0c0ffcf2 100644 --- a/src/main/resources/META-INF/replaymod_at.cfg +++ b/src/main/resources/META-INF/replaymod_at.cfg @@ -43,24 +43,8 @@ public net.minecraft.client.resources.ResourcePackRepository field_177321_h # lo public net.minecraft.client.resources.ResourcePackRepository field_177322_i # httpRequest # EntityRenderer -public net.minecraft.client.renderer.EntityRenderer field_147711_ac # resourceManager -public net.minecraft.client.renderer.EntityRenderer field_147707_d # theShaderGroup -public net.minecraft.client.renderer.EntityRenderer field_175083_ad # useShader -public net.minecraft.client.renderer.EntityRenderer field_78530_s # farPlaneDistance -public net.minecraft.client.renderer.EntityRenderer field_78507_R # fovModifierHand -public net.minecraft.client.renderer.EntityRenderer field_78506_S # fovModifierHandPrev -public net.minecraft.client.renderer.EntityRenderer field_78536_aa # lightmapUpdateNeeded - -public net.minecraft.client.renderer.EntityRenderer func_78467_g(F)V # orientCamera -public net.minecraft.client.renderer.EntityRenderer func_78474_d(F)V # renderRainSnow -public net.minecraft.client.renderer.EntityRenderer func_78481_a(FZ)F # getFOVModifier -public net.minecraft.client.renderer.EntityRenderer func_78468_a(IF)V # setupFog -public net.minecraft.client.renderer.EntityRenderer func_78466_h(F)V # updateFogColor -public net.minecraft.client.renderer.EntityRenderer func_78472_g(F)V # updateLightmap - -public net.minecraft.client.renderer.EntityRenderer func_78482_e(F)V # hurtCameraEffect -public net.minecraft.client.renderer.EntityRenderer func_78475_f(F)V # setupViewBobbing -public net.minecraft.client.renderer.EntityRenderer func_78476_b(FI)V # renderHand +public net.minecraft.client.renderer.EntityRenderer * +public net.minecraft.client.renderer.EntityRenderer *() # RenderGlobal public net.minecraft.client.renderer.RenderGlobal field_174995_M # renderDispatcher @@ -102,5 +86,8 @@ public net.minecraft.server.integrated.IntegratedServer field_71348_o # isGamePa # GameSettings public net.minecraft.client.settings.GameSettings field_151446_aD # mapSoundLevels +# Frustum +public net.minecraft.client.renderer.culling.Frustum field_78552_a # clippingHelper + # Example # public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName diff --git a/src/main/resources/mixins.replaymod.json b/src/main/resources/mixins.replaymod.json new file mode 100644 index 00000000..13f69de5 --- /dev/null +++ b/src/main/resources/mixins.replaymod.json @@ -0,0 +1,12 @@ +{ + "required": true, + "package": "eu.crushedpixel.replaymod.mixin", + "mixins": [ + "MixinEffectRenderer", + "MixinEntityRenderer", + "MixinRenderManager" + ], + "server": [], + "client": [], + "refmap": "mixins.replaymod.refmap.json" +} \ No newline at end of file