From 463b947c2b13cf8490942a59821ef5d4469e728e Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 13:35:20 +0200 Subject: [PATCH 01/14] Suppress fabric-screen-handler-api during playback (fixes #713) --- src/main/java/com/replaymod/replay/FullReplaySender.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/replaymod/replay/FullReplaySender.java b/src/main/java/com/replaymod/replay/FullReplaySender.java index b44febe9..d03c7362 100644 --- a/src/main/java/com/replaymod/replay/FullReplaySender.java +++ b/src/main/java/com/replaymod/replay/FullReplaySender.java @@ -585,6 +585,12 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend //#else //$$ String channelName = packet.getChannelName(); //#endif + String channelNameStr = channelName.toString(); + + if (channelNameStr.startsWith("fabric-screen-handler-api-v")) { + return null; // we do not want to show modded screens which got opened for the recording player + } + // On 1.14+ there's a dedicated OpenWrittenBookS2CPacket now //#if MC<11400 //#if MC>=11400 From d6c6220bdd1781a2cf5bfd3de629d42bc358a634 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 13:48:47 +0200 Subject: [PATCH 02/14] Fix invalid characters in replay name on Windows (fixes #715) --- src/main/java/com/replaymod/core/utils/Utils.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/replaymod/core/utils/Utils.java b/src/main/java/com/replaymod/core/utils/Utils.java index 688edc7c..39634262 100644 --- a/src/main/java/com/replaymod/core/utils/Utils.java +++ b/src/main/java/com/replaymod/core/utils/Utils.java @@ -59,6 +59,7 @@ import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.nio.file.Files; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.nio.file.attribute.FileAttribute; @@ -185,7 +186,12 @@ public class Utils { * Checks whether a given file name is actually usable with the file system / operating system at the given folder. */ private static boolean isUsable(Path folder, String fileName) { - Path path = folder.resolve(fileName); + Path path; + try { + path = folder.resolve(fileName); + } catch (InvalidPathException e) { + return false; // file name contains invalid characters, definitely not usable + } if (Files.exists(path)) { return true; // if it already exits, it's definitely usable } From fb38a20465e3a6ae8413a4d30152261131ad814d Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 13:49:32 +0200 Subject: [PATCH 03/14] Fix path separator in replay name Would probably have been caught by the write check as well, except in the specific case where the folder exists, e.g. `../` --- src/main/java/com/replaymod/core/utils/Utils.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/replaymod/core/utils/Utils.java b/src/main/java/com/replaymod/core/utils/Utils.java index 39634262..1b518534 100644 --- a/src/main/java/com/replaymod/core/utils/Utils.java +++ b/src/main/java/com/replaymod/core/utils/Utils.java @@ -186,6 +186,10 @@ public class Utils { * Checks whether a given file name is actually usable with the file system / operating system at the given folder. */ private static boolean isUsable(Path folder, String fileName) { + if (fileName.contains(folder.getFileSystem().getSeparator())) { + return false; // file name contains the name separator, definitely not usable + } + Path path; try { path = folder.resolve(fileName); From a6c09bcb8ab46e83f918f36d3e3aec9f7183600b Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 15:33:42 +0200 Subject: [PATCH 04/14] Fix crash when window is minimized on Windows --- .../java/com/replaymod/render/rendering/VideoRenderer.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index 56d1daf6..846daecc 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -641,6 +641,11 @@ public class VideoRenderer implements RenderInfo { private boolean displaySizeChanged() { int realWidth = mc.getWindow().getWidth(); int realHeight = mc.getWindow().getHeight(); + if (realWidth == 0 || realHeight == 0) { + // These can be zero on Windows if minimized. + // Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values. + return false; + } return displayWidth != realWidth || displayHeight != realHeight; } From 01d37ab2cb9fa29b5d33b13aaec6b0ffd7c5e2b8 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 16:27:38 +0200 Subject: [PATCH 05/14] Split gui window/framebuffer management code from VideoRenderer --- .../render/gui/progress/VirtualWindow.java | 150 ++++++++++++++++++ .../render/rendering/VideoRenderer.java | 116 ++------------ 2 files changed, 161 insertions(+), 105 deletions(-) create mode 100644 src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java diff --git a/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java new file mode 100644 index 00000000..5f2ef91d --- /dev/null +++ b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java @@ -0,0 +1,150 @@ +package com.replaymod.render.gui.progress; + +import com.replaymod.render.mixin.MainWindowAccessor; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.util.Window; + +//#if MC>=11700 +//$$ import net.minecraft.client.gl.WindowFramebuffer; +//#endif + +public class VirtualWindow { + private final MinecraftClient mc; + private final Window window; + private final MainWindowAccessor acc; + + private final Framebuffer guiFramebuffer; + private int displayWidth, displayHeight; + private int framebufferWidth, framebufferHeight; + + private int gameWidth, gameHeight; + + + public VirtualWindow(MinecraftClient mc) { + this.mc = mc; + this.window = mc.getWindow(); + this.acc = (MainWindowAccessor) (Object) this.window; + + updateDisplaySize(); + updateFramebufferSize(); + + //#if MC>=11700 + //$$ guiFramebuffer = new WindowFramebuffer(framebufferWidth, framebufferHeight); + //#else + guiFramebuffer = new Framebuffer(framebufferWidth, framebufferHeight, true + //#if MC>=11400 + , false + //#endif + ); + //#endif + } + + public void bind() { + gameWidth = acc.getFramebufferWidth(); + gameHeight = acc.getFramebufferHeight(); + acc.setFramebufferWidth(framebufferWidth); + acc.setFramebufferHeight(framebufferHeight); + } + + public void unbind() { + acc.setFramebufferWidth(gameWidth); + acc.setFramebufferHeight(gameHeight); + } + + public void beginWrite() { + guiFramebuffer.beginWrite(true); + } + + public void endWrite() { + guiFramebuffer.endWrite(); + } + + public void flip() { + guiFramebuffer.draw(framebufferWidth, framebufferHeight); + + //#if MC>=11500 + window.swapBuffers(); + //#else + //#if MC>=11400 + //$$ window.setFullscreen(false); + //#else + //#if MC>=10800 + //$$ mc.updateDisplay(); + //#else + //$$ mc.resetSize(); + //#endif + //#endif + //#endif + } + + public void updateSize() { + // Check if display size has changes and force recalculate GUI framebuffer size. + if (displaySizeChanged()) { + updateDisplaySize(); + acc.invokeUpdateFramebufferSize(); + } + + // Resize the GUI framebuffer if the display size changed + if (framebufferSizeChanged()) { + updateFramebufferSize(); + //#if MC>=11400 + guiFramebuffer.resize(framebufferWidth, framebufferHeight + //#if MC>=11400 + , false + //#endif + ); + //#else + //$$ guiFramebuffer.createBindFramebuffer(framebufferWidth, framebufferHeight); + //#endif + } + } + + private boolean displaySizeChanged() { + int realWidth = mc.getWindow().getWidth(); + int realHeight = mc.getWindow().getHeight(); + if (realWidth == 0 || realHeight == 0) { + // These can be zero on Windows if minimized. + // Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values. + return false; + } + return displayWidth != realWidth || displayHeight != realHeight; + } + + private boolean framebufferSizeChanged() { + int realWidth = mc.getWindow().getFramebufferWidth(); + int realHeight = mc.getWindow().getFramebufferHeight(); + if (realWidth == 0 || realHeight == 0) { + // These can be zero on Windows if minimized. + // Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values. + return false; + } + return framebufferWidth != realWidth || framebufferHeight != realHeight; + } + + private void updateDisplaySize() { + displayWidth = mc.getWindow().getWidth(); + displayHeight = mc.getWindow().getHeight(); + } + + private void updateFramebufferSize() { + framebufferWidth = mc.getWindow().getFramebufferWidth(); + framebufferHeight = mc.getWindow().getFramebufferHeight(); + } + + public int getDisplayWidth() { + return displayWidth; + } + + public int getDisplayHeight() { + return displayHeight; + } + + public int getFramebufferWidth() { + return framebufferWidth; + } + + public int getFramebufferHeight() { + return framebufferHeight; + } +} diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index 846daecc..2ea98438 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -6,7 +6,6 @@ import com.replaymod.core.mixin.TimerAccessor; import com.replaymod.core.utils.WrappedTimer; import com.replaymod.core.versions.MCVer; import com.replaymod.pathing.player.AbstractTimelinePlayer; -import com.replaymod.pathing.player.ReplayTimer; import com.replaymod.pathing.properties.TimestampProperty; import com.replaymod.render.CameraPathExporter; import com.replaymod.render.PNGWriter; @@ -19,9 +18,9 @@ import com.replaymod.render.events.ReplayRenderCallback; import com.replaymod.render.frame.BitmapFrame; import com.replaymod.render.gui.GuiRenderingDone; import com.replaymod.render.gui.GuiVideoRenderer; +import com.replaymod.render.gui.progress.VirtualWindow; import com.replaymod.render.hooks.ForceChunkLoadingHook; import com.replaymod.render.metadata.MetadataInjector; -import com.replaymod.render.mixin.MainWindowAccessor; import com.replaymod.render.mixin.WorldRendererAccessor; import com.replaymod.render.utils.FlawlessFrames; import com.replaymod.replay.ReplayHandler; @@ -32,7 +31,6 @@ import de.johni0702.minecraft.gui.utils.lwjgl.Dimension; import de.johni0702.minecraft.gui.utils.lwjgl.ReadableDimension; import net.minecraft.client.MinecraftClient; import com.mojang.blaze3d.platform.GLX; -import net.minecraft.client.gl.Framebuffer; import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.client.util.Window; import net.minecraft.sound.SoundEvent; @@ -43,7 +41,6 @@ import net.minecraft.client.render.RenderTickCounter; import org.lwjgl.glfw.GLFW; //#if MC>=11700 -//$$ import net.minecraft.client.gl.WindowFramebuffer; //$$ import net.minecraft.client.render.DiffuseLighting; //$$ import net.minecraft.util.math.Matrix4f; //#endif @@ -113,15 +110,12 @@ public class VideoRenderer implements RenderInfo { private int framesDone; private int totalFrames; + private final VirtualWindow guiWindow = new VirtualWindow(mc); private final GuiVideoRenderer gui; private boolean paused; private boolean cancelled; private volatile Throwable failureCause; - private Framebuffer guiFramebuffer; - private int displayWidth, displayHeight; - private int framebufferWidth, framebufferHeight; - public VideoRenderer(RenderSettings settings, ReplayHandler replayHandler, Timeline timeline) throws IOException { this.settings = settings; this.replayHandler = replayHandler; @@ -245,11 +239,7 @@ public class VideoRenderer implements RenderInfo { @Override public float updateForNextFrame() { // because the jGui lib uses Minecraft's displayWidth and displayHeight values, update these temporarily - MainWindowAccessor acc = (MainWindowAccessor) (Object) mc.getWindow(); - int framebufferWidthBefore = acc.getFramebufferWidth(); - int framebufferHeightBefore = acc.getFramebufferHeight(); - acc.setFramebufferWidth(framebufferWidth); - acc.setFramebufferHeight(framebufferHeight); + guiWindow.bind(); if (!settings.isHighPerformance() || framesDone % fps == 0) { while (drawGui() && paused) { @@ -290,8 +280,7 @@ public class VideoRenderer implements RenderInfo { } // change Minecraft's display size back - acc.setFramebufferWidth(framebufferWidthBefore); - acc.setFramebufferHeight(framebufferHeightBefore); + guiWindow.unbind(); if (cameraPathExporter != null) { cameraPathExporter.recordFrame(timer.tickDelta); @@ -362,23 +351,9 @@ public class VideoRenderer implements RenderInfo { cameraPathExporter.setup(totalFrames); } - updateDisplaySize(); - updateFramebufferSize(); - gui.toMinecraft().init(mc, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); forceChunkLoadingHook = new ForceChunkLoadingHook(mc.worldRenderer); - - // Set up our own framebuffer to render the GUI to - //#if MC>=11700 - //$$ guiFramebuffer = new WindowFramebuffer(framebufferWidth, framebufferHeight); - //#else - guiFramebuffer = new Framebuffer(framebufferWidth, framebufferHeight, true - //#if MC>=11400 - , false - //#endif - ); - //#endif } private void finish() { @@ -427,7 +402,7 @@ public class VideoRenderer implements RenderInfo { } // Finally, resize the Minecraft framebuffer to the actual width/height of the window - resizeMainWindow(mc, framebufferWidth, framebufferHeight); + resizeMainWindow(mc, guiWindow.getFramebufferWidth(), guiWindow.getFramebufferHeight()); } private void executeTaskQueue() { @@ -485,25 +460,7 @@ public class VideoRenderer implements RenderInfo { return false; } - // Check if display size has changes and force recalculate GUI framebuffer size. - if (displaySizeChanged()) { - updateDisplaySize(); - ((MainWindowAccessor) (Object) window).invokeUpdateFramebufferSize(); - } - - // Resize the GUI framebuffer if the display size changed - if (framebufferSizeChanged()) { - updateFramebufferSize(); - //#if MC>=11400 - guiFramebuffer.resize(framebufferWidth, framebufferHeight - //#if MC>=11400 - , false - //#endif - ); - //#else - //$$ guiFramebuffer.createBindFramebuffer(framebufferWidth, framebufferHeight); - //#endif - } + guiWindow.updateSize(); pushMatrix(); GlStateManager.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT @@ -512,7 +469,7 @@ public class VideoRenderer implements RenderInfo { //#endif ); GlStateManager.enableTexture(); - guiFramebuffer.beginWrite(true); + guiWindow.beginWrite(); //#if MC>=11500 RenderSystem.clear(256, MinecraftClient.IS_SYSTEM_MAC); @@ -568,8 +525,8 @@ public class VideoRenderer implements RenderInfo { //#endif //#if MC>=11400 - int mouseX = (int) mc.mouse.getX() * window.getScaledWidth() / displayWidth; - int mouseY = (int) mc.mouse.getY() * window.getScaledHeight() / displayHeight; + int mouseX = (int) mc.mouse.getX() * window.getScaledWidth() / guiWindow.getDisplayWidth(); + int mouseY = (int) mc.mouse.getY() * window.getScaledHeight() / guiWindow.getDisplayHeight(); if (mc.getOverlay() != null) { Screen orgScreen = mc.currentScreen; @@ -599,31 +556,12 @@ public class VideoRenderer implements RenderInfo { //$$ gui.toMinecraft().drawScreen(mouseX, mouseY, 0); //#endif - guiFramebuffer.endWrite(); + guiWindow.endWrite(); popMatrix(); pushMatrix(); - guiFramebuffer.draw(framebufferWidth, framebufferHeight); + guiWindow.flip(); popMatrix(); - //#if MC>=11500 - window.swapBuffers(); - //#else - //#if MC>=11400 - //$$ window.setFullscreen(false); - //#else - //$$ // if not in high performance mode, update the gui size if screen size changed - //$$ // otherwise just swap the progress gui to screen - //$$ if (settings.isHighPerformance()) { - //$$ Display.update(); - //$$ } else { - //#if MC>=10800 - //$$ mc.updateDisplay(); - //#else - //$$ mc.resetSize(); - //#endif - //$$ } - //#endif - //#endif //#if MC>=11400 if (mc.mouse.isCursorLocked()) { mc.mouse.unlockCursor(); @@ -638,38 +576,6 @@ public class VideoRenderer implements RenderInfo { } while (true); } - private boolean displaySizeChanged() { - int realWidth = mc.getWindow().getWidth(); - int realHeight = mc.getWindow().getHeight(); - if (realWidth == 0 || realHeight == 0) { - // These can be zero on Windows if minimized. - // Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values. - return false; - } - return displayWidth != realWidth || displayHeight != realHeight; - } - - private boolean framebufferSizeChanged() { - int realWidth = mc.getWindow().getFramebufferWidth(); - int realHeight = mc.getWindow().getFramebufferHeight(); - if (realWidth == 0 || realHeight == 0) { - // These can be zero on Windows if minimized. - // Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values. - return false; - } - return framebufferWidth != realWidth || framebufferHeight != realHeight; - } - - private void updateDisplaySize() { - displayWidth = mc.getWindow().getWidth(); - displayHeight = mc.getWindow().getHeight(); - } - - private void updateFramebufferSize() { - framebufferWidth = mc.getWindow().getFramebufferWidth(); - framebufferHeight = mc.getWindow().getFramebufferHeight(); - } - public int getFramesDone() { return framesDone; } From fb36fc2ba86835ba04980310ec87336d40d0567c Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 17:07:08 +0200 Subject: [PATCH 06/14] Fix render progress framebuffer never being deleted --- .../com/replaymod/render/gui/progress/VirtualWindow.java | 8 +++++++- .../com/replaymod/render/rendering/VideoRenderer.java | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java index 5f2ef91d..c9d5769e 100644 --- a/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java +++ b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java @@ -1,6 +1,7 @@ package com.replaymod.render.gui.progress; import com.replaymod.render.mixin.MainWindowAccessor; +import de.johni0702.minecraft.gui.function.Closeable; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.Framebuffer; import net.minecraft.client.util.Window; @@ -9,7 +10,7 @@ import net.minecraft.client.util.Window; //$$ import net.minecraft.client.gl.WindowFramebuffer; //#endif -public class VirtualWindow { +public class VirtualWindow implements Closeable { private final MinecraftClient mc; private final Window window; private final MainWindowAccessor acc; @@ -40,6 +41,11 @@ public class VirtualWindow { //#endif } + @Override + public void close() { + guiFramebuffer.delete(); + } + public void bind() { gameWidth = acc.getFramebufferWidth(); gameHeight = acc.getFramebufferHeight(); diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index 2ea98438..c7a5720c 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -363,6 +363,8 @@ public class VideoRenderer implements RenderInfo { // Tear down of the timeline player might only happen the next tick after it was cancelled timelinePlayer.onTick(); + guiWindow.close(); + // FBOs are always used in 1.14+ //#if MC<11400 //$$ if (!OpenGlHelper.isFramebufferEnabled()) { From 45587930301869697d55bee280549f564a0fc586 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 17:53:38 +0200 Subject: [PATCH 07/14] Remove unless window size tracking The only thing we care about is the framebuffer size, cause that will differ between game and progress gui rendering. The window size will be the same (real) size for both. --- .../render/gui/progress/VirtualWindow.java | 32 ------------------- .../render/rendering/VideoRenderer.java | 4 +-- 2 files changed, 2 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java index c9d5769e..8dd8617b 100644 --- a/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java +++ b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java @@ -16,7 +16,6 @@ public class VirtualWindow implements Closeable { private final MainWindowAccessor acc; private final Framebuffer guiFramebuffer; - private int displayWidth, displayHeight; private int framebufferWidth, framebufferHeight; private int gameWidth, gameHeight; @@ -27,7 +26,6 @@ public class VirtualWindow implements Closeable { this.window = mc.getWindow(); this.acc = (MainWindowAccessor) (Object) this.window; - updateDisplaySize(); updateFramebufferSize(); //#if MC>=11700 @@ -85,12 +83,6 @@ public class VirtualWindow implements Closeable { } public void updateSize() { - // Check if display size has changes and force recalculate GUI framebuffer size. - if (displaySizeChanged()) { - updateDisplaySize(); - acc.invokeUpdateFramebufferSize(); - } - // Resize the GUI framebuffer if the display size changed if (framebufferSizeChanged()) { updateFramebufferSize(); @@ -106,17 +98,6 @@ public class VirtualWindow implements Closeable { } } - private boolean displaySizeChanged() { - int realWidth = mc.getWindow().getWidth(); - int realHeight = mc.getWindow().getHeight(); - if (realWidth == 0 || realHeight == 0) { - // These can be zero on Windows if minimized. - // Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values. - return false; - } - return displayWidth != realWidth || displayHeight != realHeight; - } - private boolean framebufferSizeChanged() { int realWidth = mc.getWindow().getFramebufferWidth(); int realHeight = mc.getWindow().getFramebufferHeight(); @@ -128,24 +109,11 @@ public class VirtualWindow implements Closeable { return framebufferWidth != realWidth || framebufferHeight != realHeight; } - private void updateDisplaySize() { - displayWidth = mc.getWindow().getWidth(); - displayHeight = mc.getWindow().getHeight(); - } - private void updateFramebufferSize() { framebufferWidth = mc.getWindow().getFramebufferWidth(); framebufferHeight = mc.getWindow().getFramebufferHeight(); } - public int getDisplayWidth() { - return displayWidth; - } - - public int getDisplayHeight() { - return displayHeight; - } - public int getFramebufferWidth() { return framebufferWidth; } diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index c7a5720c..d51cc04b 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -527,8 +527,8 @@ public class VideoRenderer implements RenderInfo { //#endif //#if MC>=11400 - int mouseX = (int) mc.mouse.getX() * window.getScaledWidth() / guiWindow.getDisplayWidth(); - int mouseY = (int) mc.mouse.getY() * window.getScaledHeight() / guiWindow.getDisplayHeight(); + int mouseX = (int) mc.mouse.getX() * window.getScaledWidth() / Math.max(window.getWidth(), 1); + int mouseY = (int) mc.mouse.getY() * window.getScaledHeight() / Math.max(window.getHeight(), 1); if (mc.getOverlay() != null) { Screen orgScreen = mc.currentScreen; From fd9be55f7918c62fa0fc9a919c6b1aede89ab8e2 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 18:58:34 +0200 Subject: [PATCH 08/14] Remove caching of ScaledResolution from Window shim It'll become stale if the code holds on to the Window shim object for a longer duration, and there's no reliable mechanism to invalidate it. --- .../java/com/replaymod/core/versions/Window.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java b/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java index 26d697d2..40e2278f 100644 --- a/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java +++ b/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java @@ -8,7 +8,6 @@ import org.lwjgl.opengl.Display; public class Window implements MainWindowAccessor { private final Minecraft mc; - private ScaledResolution scaledResolution; public Window(Minecraft mc) { this.mc = mc; @@ -52,16 +51,11 @@ public class Window implements MainWindowAccessor { } private ScaledResolution scaledResolution() { - ScaledResolution scaledResolution = this.scaledResolution; - if (scaledResolution == null) { - //#if MC>=10809 - scaledResolution = new ScaledResolution(mc); - //#else - //$$ scaledResolution = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); - //#endif - this.scaledResolution = scaledResolution; - } - return scaledResolution; + //#if MC>=10809 + return new ScaledResolution(mc); + //#else + //$$ return new ScaledResolution(mc, mc.displayWidth, mc.displayHeight); + //#endif } public int getScaledWidth() { From 5be57681afd2e6d36c2e203379e68dd000710512 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 18:36:36 +0200 Subject: [PATCH 09/14] Completely bypass Minecraft when window is resized during rendering Should fix issues where resizing affects the render result. --- .../render/gui/progress/VirtualWindow.java | 74 ++++++++++++------- .../render/hooks/MinecraftClientExt.java | 12 +++ .../render/mixin/MainWindowAccessor.java | 8 -- ...SuppressFramebufferResizeDuringRender.java | 39 ++++++++++ .../render/rendering/VideoRenderer.java | 2 - .../resources/mixins.render.replaymod.json | 1 + .../com/replaymod/core/versions/Window.java | 5 -- .../render/mixin/MainWindowAccessor.java | 2 - versions/1.14.4-forge/mapping.txt | 1 + versions/1.8.9/mapping.txt | 1 + 10 files changed, 102 insertions(+), 43 deletions(-) create mode 100644 src/main/java/com/replaymod/render/hooks/MinecraftClientExt.java create mode 100644 src/main/java/com/replaymod/render/mixin/Mixin_SuppressFramebufferResizeDuringRender.java diff --git a/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java index 8dd8617b..82977526 100644 --- a/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java +++ b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java @@ -1,5 +1,6 @@ package com.replaymod.render.gui.progress; +import com.replaymod.render.hooks.MinecraftClientExt; import com.replaymod.render.mixin.MainWindowAccessor; import de.johni0702.minecraft.gui.function.Closeable; import net.minecraft.client.MinecraftClient; @@ -16,6 +17,7 @@ public class VirtualWindow implements Closeable { private final MainWindowAccessor acc; private final Framebuffer guiFramebuffer; + private boolean isBound; private int framebufferWidth, framebufferHeight; private int gameWidth, gameHeight; @@ -26,7 +28,8 @@ public class VirtualWindow implements Closeable { this.window = mc.getWindow(); this.acc = (MainWindowAccessor) (Object) this.window; - updateFramebufferSize(); + framebufferWidth = acc.getFramebufferWidth(); + framebufferHeight = acc.getFramebufferHeight(); //#if MC>=11700 //$$ guiFramebuffer = new WindowFramebuffer(framebufferWidth, framebufferHeight); @@ -37,11 +40,15 @@ public class VirtualWindow implements Closeable { //#endif ); //#endif + + MinecraftClientExt.get(mc).setWindowDelegate(this); } @Override public void close() { guiFramebuffer.delete(); + + MinecraftClientExt.get(mc).setWindowDelegate(null); } public void bind() { @@ -49,11 +56,13 @@ public class VirtualWindow implements Closeable { gameHeight = acc.getFramebufferHeight(); acc.setFramebufferWidth(framebufferWidth); acc.setFramebufferHeight(framebufferHeight); + isBound = true; } public void unbind() { acc.setFramebufferWidth(gameWidth); acc.setFramebufferHeight(gameHeight); + isBound = false; } public void beginWrite() { @@ -82,36 +91,45 @@ public class VirtualWindow implements Closeable { //#endif } - public void updateSize() { - // Resize the GUI framebuffer if the display size changed - if (framebufferSizeChanged()) { - updateFramebufferSize(); - //#if MC>=11400 - guiFramebuffer.resize(framebufferWidth, framebufferHeight - //#if MC>=11400 - , false - //#endif - ); - //#else - //$$ guiFramebuffer.createBindFramebuffer(framebufferWidth, framebufferHeight); - //#endif - } - } - - private boolean framebufferSizeChanged() { - int realWidth = mc.getWindow().getFramebufferWidth(); - int realHeight = mc.getWindow().getFramebufferHeight(); - if (realWidth == 0 || realHeight == 0) { + /** + * Updates the size of the window's framebuffer. Must only be called while this window is bound. + */ + public void onResolutionChanged(int newWidth, int newHeight) { + if (newWidth == 0 || newHeight == 0) { // These can be zero on Windows if minimized. // Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values. - return false; + return; + } + + if (framebufferWidth == newWidth && framebufferHeight == newHeight) { + return; // size is unchanged, nothing to do + } + + framebufferWidth = newWidth; + framebufferHeight = newHeight; + + //#if MC>=11400 + guiFramebuffer.resize(newWidth, newHeight + //#if MC>=11400 + , false + //#endif + ); + //#else + //$$ guiFramebuffer.createBindFramebuffer(newWidth, newHeight); + //#endif + + applyScaleFactor(); + if (mc.currentScreen != null) { + mc.currentScreen.resize(mc, window.getScaledWidth(), window.getScaledHeight()); } - return framebufferWidth != realWidth || framebufferHeight != realHeight; } - private void updateFramebufferSize() { - framebufferWidth = mc.getWindow().getFramebufferWidth(); - framebufferHeight = mc.getWindow().getFramebufferHeight(); + private void applyScaleFactor() { + //#if MC>=11400 + window.setScaleFactor(window.calculateScaleFactor(mc.options.guiScale, mc.forcesUnicodeFont())); + //#else + //$$ // Nothing to do, ScaledResolution re-computes the scale factor every time it is created + //#endif } public int getFramebufferWidth() { @@ -121,4 +139,8 @@ public class VirtualWindow implements Closeable { public int getFramebufferHeight() { return framebufferHeight; } + + public boolean isBound() { + return isBound; + } } diff --git a/src/main/java/com/replaymod/render/hooks/MinecraftClientExt.java b/src/main/java/com/replaymod/render/hooks/MinecraftClientExt.java new file mode 100644 index 00000000..6b4295bb --- /dev/null +++ b/src/main/java/com/replaymod/render/hooks/MinecraftClientExt.java @@ -0,0 +1,12 @@ +package com.replaymod.render.hooks; + +import com.replaymod.render.gui.progress.VirtualWindow; +import net.minecraft.client.MinecraftClient; + +public interface MinecraftClientExt { + void setWindowDelegate(VirtualWindow window); + + static MinecraftClientExt get(MinecraftClient mc) { + return (MinecraftClientExt) mc; + } +} diff --git a/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java b/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java index a54dd178..c24af52b 100644 --- a/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java +++ b/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java @@ -15,12 +15,4 @@ public interface MainWindowAccessor { int getFramebufferHeight(); @Accessor void setFramebufferHeight(int value); - // FIXME preprocessor should be able to infer this mapping - // FIXME preprocessor should be able to remap this one when the mapping is given manually - //#if MC>=11500 - @Invoker - //#else - //$$ @Invoker("method_4483") - //#endif - void invokeUpdateFramebufferSize(); } diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_SuppressFramebufferResizeDuringRender.java b/src/main/java/com/replaymod/render/mixin/Mixin_SuppressFramebufferResizeDuringRender.java new file mode 100644 index 00000000..707f6952 --- /dev/null +++ b/src/main/java/com/replaymod/render/mixin/Mixin_SuppressFramebufferResizeDuringRender.java @@ -0,0 +1,39 @@ +package com.replaymod.render.mixin; + +import com.replaymod.render.gui.progress.VirtualWindow; +import com.replaymod.render.hooks.MinecraftClientExt; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.util.Window; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class Mixin_SuppressFramebufferResizeDuringRender implements MinecraftClientExt { + + @Unique + private VirtualWindow windowDelegate; + + @Override + public void setWindowDelegate(VirtualWindow window) { + this.windowDelegate = window; + } + + //#if MC>=11400 + @Inject(method = "onResolutionChanged", at = @At("HEAD"), cancellable = true) + //#else + //$$ @Inject(method = "resize", at = @At("HEAD"), cancellable = true) + //#endif + private void suppressResizeDuringRender(CallbackInfo ci) { + VirtualWindow delegate = this.windowDelegate; + if (delegate != null && delegate.isBound()) { + Window window = ((MinecraftClient) (Object) this).getWindow(); + delegate.onResolutionChanged(window.getFramebufferWidth(), window.getFramebufferHeight()); + ci.cancel(); + } + } +} diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index d51cc04b..a6b31504 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -462,8 +462,6 @@ public class VideoRenderer implements RenderInfo { return false; } - guiWindow.updateSize(); - pushMatrix(); GlStateManager.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT //#if MC>=11400 diff --git a/src/main/resources/mixins.render.replaymod.json b/src/main/resources/mixins.render.replaymod.json index 092aa958..ff833a38 100644 --- a/src/main/resources/mixins.render.replaymod.json +++ b/src/main/resources/mixins.render.replaymod.json @@ -21,6 +21,7 @@ "Mixin_StabilizeCamera", "Mixin_Stereoscopic_Camera", "Mixin_Stereoscopic_HandRenderPass", + "Mixin_SuppressFramebufferResizeDuringRender", //#if MC>=11600 "Mixin_AddIrisOdsShaderUniforms", "Mixin_LoadIrisOdsShaderPack", diff --git a/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java b/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java index 40e2278f..3f620619 100644 --- a/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java +++ b/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java @@ -33,11 +33,6 @@ public class Window implements MainWindowAccessor { mc.displayHeight = value; } - @Override - public void invokeUpdateFramebufferSize() { - // no-op, pre-LWJGL3 MC doesn't differentiate between window and framebuffer size - } - public long getHandle() { return 0; } diff --git a/versions/1.12.2/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java b/versions/1.12.2/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java index a6166095..697dd601 100644 --- a/versions/1.12.2/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java +++ b/versions/1.12.2/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java @@ -15,6 +15,4 @@ public interface MainWindowAccessor { int getFramebufferHeight(); @Accessor("displayHeight") void setFramebufferHeight(int value); - @Invoker - void invokeUpdateFramebufferSize(); } diff --git a/versions/1.14.4-forge/mapping.txt b/versions/1.14.4-forge/mapping.txt index 2096663b..52a22ceb 100644 --- a/versions/1.14.4-forge/mapping.txt +++ b/versions/1.14.4-forge/mapping.txt @@ -181,6 +181,7 @@ net.minecraft.client.gui.screen.Screen hasShiftDown() isShiftKeyDown() net.minecraft.client.gui.screen.Screen init() setWorldAndResolution() net.minecraft.client.gui.screen.Screen minecraft mc net.minecraft.client.gui.screen.Screen net.minecraft.client.gui.GuiScreen +net.minecraft.client.gui.screen.Screen resize() onResize() net.minecraft.client.gui.screen.Screen passEvents allowUserInput net.minecraft.client.gui.screen.Screen removed() onGuiClosed() net.minecraft.client.gui.screen.Screen renderBackground() drawDefaultBackground() diff --git a/versions/1.8.9/mapping.txt b/versions/1.8.9/mapping.txt index 43123ad0..2dfdbda5 100644 --- a/versions/1.8.9/mapping.txt +++ b/versions/1.8.9/mapping.txt @@ -1,3 +1,4 @@ +net.minecraft.client.gui.GuiScreen onResize() func_175273_b() net.minecraft.entity.player.EntityPlayer isWearing() func_175148_a() net.minecraft.client.renderer.WorldRenderer begin() startDrawing() net.minecraft.network.play.server.S38PacketPlayerListItem getAction() func_179768_b() From 497b8440cad0c1da2069d99c59d171e12be22afd Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 10 Apr 2022 19:53:15 +0200 Subject: [PATCH 10/14] Call Window.onFramebufferSizeChanged to resize (fixes #705) Instead of setting the the values via accessor and calling the handler directly. This allows mods like ResolutionControl+ to properly resize its internal framebuffers as well. --- .../java/com/replaymod/core/versions/MCVer.java | 15 ++++----------- .../render/gui/progress/VirtualWindow.java | 2 ++ .../render/mixin/MainWindowAccessor.java | 2 ++ 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/replaymod/core/versions/MCVer.java b/src/main/java/com/replaymod/core/versions/MCVer.java index c239d9b0..e53ed093 100644 --- a/src/main/java/com/replaymod/core/versions/MCVer.java +++ b/src/main/java/com/replaymod/core/versions/MCVer.java @@ -27,9 +27,9 @@ import net.minecraft.resource.ResourcePackSource; //#if MC>=11400 import com.replaymod.render.mixin.MainWindowAccessor; import net.minecraft.SharedConstants; -import net.minecraft.client.gl.Framebuffer; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.AbstractButtonWidget; +import net.minecraft.client.util.Window; import java.util.concurrent.CompletableFuture; @@ -106,17 +106,10 @@ public class MCVer { public static void resizeMainWindow(MinecraftClient mc, int width, int height) { //#if MC>=11400 - Framebuffer fb = mc.getFramebuffer(); - if (fb.viewportWidth != width || fb.viewportHeight != height) { - fb.resize(width, height, false); - } + Window window = mc.getWindow(); + MainWindowAccessor mainWindow = (MainWindowAccessor) (Object) window; //noinspection ConstantConditions - MainWindowAccessor mainWindow = (MainWindowAccessor) (Object) mc.getWindow(); - mainWindow.setFramebufferWidth(width); - mainWindow.setFramebufferHeight(height); - //#if MC>=11500 - mc.gameRenderer.onResized(width, height); - //#endif + mainWindow.invokeOnFramebufferSizeChanged(window.getHandle(), width, height); //#else //$$ if (width != mc.displayWidth || height != mc.displayHeight) { //$$ mc.resize(width, height); diff --git a/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java index 82977526..6f2b2bc0 100644 --- a/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java +++ b/src/main/java/com/replaymod/render/gui/progress/VirtualWindow.java @@ -56,12 +56,14 @@ public class VirtualWindow implements Closeable { gameHeight = acc.getFramebufferHeight(); acc.setFramebufferWidth(framebufferWidth); acc.setFramebufferHeight(framebufferHeight); + applyScaleFactor(); isBound = true; } public void unbind() { acc.setFramebufferWidth(gameWidth); acc.setFramebufferHeight(gameHeight); + applyScaleFactor(); isBound = false; } diff --git a/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java b/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java index c24af52b..6bfa8e67 100644 --- a/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java +++ b/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java @@ -15,4 +15,6 @@ public interface MainWindowAccessor { int getFramebufferHeight(); @Accessor void setFramebufferHeight(int value); + @Invoker + void invokeOnFramebufferSizeChanged(long window, int width, int height); } From f2c96174bc44115725220451759eedf0bf3a984b Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 17 Apr 2022 11:20:58 +0200 Subject: [PATCH 11/14] Fix terrain culling not being updated for omnidirectional rendering Terrain culling is only updated when the camera position or rotation changes. For omnidirectional rendering, we don't change the camera directly though, we rotate way earlier so we can consistently get before any other effects. As a result, the terrain frustum culling wasn't updated between render passes resulting in missing terrain. This was largely masked by the fact that we used to call GameRenderer.onResize every pass (even when the size hadn't changed) but fixing that made this issue become apparent. --- .../replaymod/render/mixin/Mixin_Omnidirectional_Rotation.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Rotation.java b/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Rotation.java index 6107028e..e7d567c7 100644 --- a/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Rotation.java +++ b/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Rotation.java @@ -83,6 +83,8 @@ public abstract class Mixin_Omnidirectional_Rotation { //#else //$$ GL11.glRotatef(angle, x, y, 0); //#endif + + getMinecraft().worldRenderer.scheduleTerrainUpdate(); } //#if MC<11500 //$$ if (getHandler() != null && getHandler().omnidirectional) { From 8b2d42f801ec9ef50f5bfbcbd7132a9ab95827f3 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 1 May 2022 20:05:00 +0200 Subject: [PATCH 12/14] Fix broken fog when using Chroma Key with Sodium (fixes #726) --- .../render/mixin/Mixin_ChromaKeyDisableFog.java | 12 ++++++++++++ versions/mapping-fabric-1.17-1.16.4.txt | 2 ++ 2 files changed, 14 insertions(+) diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyDisableFog.java b/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyDisableFog.java index 48719c54..948038e9 100644 --- a/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyDisableFog.java +++ b/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyDisableFog.java @@ -1,5 +1,6 @@ package com.replaymod.render.mixin; +import com.mojang.blaze3d.platform.GlStateManager; import com.replaymod.core.versions.MCVer; import com.replaymod.render.hooks.EntityRendererHandler; import net.minecraft.client.render.BackgroundRenderer; @@ -20,6 +21,17 @@ public abstract class Mixin_ChromaKeyDisableFog { ((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().gameRenderer).replayModRender_getHandler(); if (handler == null) return; if (handler.getSettings().getChromaKeyingColor() != null) { + // Starting with 1.15, fog is no longer enabled in this method but is instead managed by the RenderLayer + // system (and with 1.17, they are enabled permanently / depend only on the shader). Therefore, cancelling + // this method is no longer sufficient, and we additionally also need to set the start value to get rid of + // fog (this doesn't hurt on 1.14 either). + // Note: This only becomes noticeable with Sodium because Vanilla would already set the start to max for + // unrelated reasons. But Sodium does some math which gives wrong results if end isn't greater than + // start, as would be the case in these cases. Sodium doing math is also the reason we don't set start + // equal to end (that'll result in undefined behavior because it sticks those into a smoothstep on old + // versions), and we don't set it to MAX_VALUE because that also gives wrong results. + GlStateManager.fogStart(1E10F); + GlStateManager.fogEnd(2E10F); ci.cancel(); } } diff --git a/versions/mapping-fabric-1.17-1.16.4.txt b/versions/mapping-fabric-1.17-1.16.4.txt index 300a639a..193eb19b 100644 --- a/versions/mapping-fabric-1.17-1.16.4.txt +++ b/versions/mapping-fabric-1.17-1.16.4.txt @@ -1,4 +1,6 @@ com.mojang.blaze3d.systems.RenderSystem com.mojang.blaze3d.platform.GlStateManager +com.mojang.blaze3d.systems.RenderSystem setShaderFogStart() fogStart() +com.mojang.blaze3d.systems.RenderSystem setShaderFogEnd() fogEnd() net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket getDimensionType() method_29445() net.minecraft.entity.Entity getId() getEntityId() net.minecraft.client.network.ClientPlayerEntity init() net.minecraft.entity.player.PlayerEntity afterSpawn() From 4364347a19a1ca96f33e0cc086e17d02305479e9 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 1 May 2022 20:34:26 +0200 Subject: [PATCH 13/14] Update ReplayStudio 6fc8e20 Fix incorrect relative packet order in squash filter (fixes #718) --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index e9ba988b..c57fc62f 100644 --- a/build.gradle +++ b/build.gradle @@ -341,7 +341,7 @@ dependencies { shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8' - shadow "com.github.ReplayMod:ReplayStudio:b5539d1", shadeExclusions + shadow "com.github.ReplayMod:ReplayStudio:6fc8e20", shadeExclusions implementation(FABRIC ? dependencies.project(path: jGui.path, configuration: "namedElements") : jGui) { transitive = false // FG 1.2 puts all MC deps into the compile configuration and we don't want to shade those From 716df74893d7c1f7f626d6133ab4bffd923e724e Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 1 May 2022 21:06:24 +0200 Subject: [PATCH 14/14] Fix first person (cross)bow model animation on 1.9+ (fixes #708) --- src/main/java/com/replaymod/replay/camera/CameraEntity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/replaymod/replay/camera/CameraEntity.java b/src/main/java/com/replaymod/replay/camera/CameraEntity.java index 35bd016c..d990240e 100644 --- a/src/main/java/com/replaymod/replay/camera/CameraEntity.java +++ b/src/main/java/com/replaymod/replay/camera/CameraEntity.java @@ -688,6 +688,7 @@ public class CameraEntity //#if MC>=10904 cameraA.setItemStackMainHand(viewPlayerA != null ? viewPlayerA.getItemStackMainHand() : empty); this.preferredHand = viewPlayer != null ? viewPlayer.preferredHand : Hand.MAIN_HAND; + this.activeItemStack = viewPlayer != null ? viewPlayer.getActiveItem() : empty; cameraA.setActiveItemStackUseCount(viewPlayerA != null ? viewPlayerA.getActiveItemStackUseCount() : 0); //#else //$$ cameraA.setItemInUse(viewPlayerA != null ? viewPlayerA.getItemInUse() : empty);