From af8803d6b5fb1db1c3cc72b999239070678e750a Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Fri, 13 Mar 2020 14:18:19 +0100 Subject: [PATCH] WIP 1.15 and ReplayStudio v2 update --- build.gradle.kts | 26 +- jGui | 2 +- settings.gradle.kts | 6 +- .../java/com/replaymod/core/ReplayMod.java | 26 +- .../replaymod/core/gui/RestoreReplayGui.java | 5 +- .../core/mixin/MinecraftAccessor.java | 3 - .../core/mixin/MixinGameRenderer.java | 20 +- .../java/com/replaymod/core/utils/Utils.java | 12 +- .../core/versions/LangResourcePack.java | 10 +- .../com/replaymod/core/versions/MCVer.java | 83 +- .../replaymod/editor/gui/MarkerProcessor.java | 9 +- .../ScreenshotRenderer.java | 13 +- .../replaymod/extras/urischeme/UriScheme.java | 7 + .../replaymod/online/gui/GuiUploadReplay.java | 2 +- .../handler/RecordingEventHandler.java | 18 +- .../mixin/MixinNetHandlerPlayClient.java | 32 +- .../mixin/SPacketSpawnMobAccessor.java | 2 + .../mixin/SPacketSpawnPlayerAccessor.java | 2 + .../recording/packet/PacketListener.java | 12 +- .../com/replaymod/render/RenderSettings.java | 10 + .../render/blend/BlendMeshBuilder.java | 17 + .../replaymod/render/blend/BlendState.java | 6 + .../render/blend/exporters/ChunkExporter.java | 3 +- .../render/blend/exporters/ItemExporter.java | 4 + .../exporters/ModelRendererExporter.java | 8 + .../blend/exporters/ParticlesExporter.java | 19 +- ...ntainerLocalRenderInformationAccessor.java | 4 + .../blend/mixin/MixinChunkRenderWorker.java | 3 +- .../blend/mixin/MixinEffectRenderer.java | 2 +- .../blend/mixin/MixinModelRenderer.java | 3 +- .../blend/mixin/MixinRenderManager.java | 31 +- .../MixinTileEntityRendererDispatcher.java | 3 +- .../blend/mixin/WorldRendererAccessor.java | 3 +- .../render/capturer/OpenGlFrameCapturer.java | 3 +- .../render/gui/GuiVideoRenderer.java | 2 +- .../hooks/ChunkLoadingRenderGlobal.java | 3 +- .../render/hooks/EntityRendererHandler.java | 12 +- .../mixin/ChunkRenderDispatcherAccessor.java | 2 +- .../replaymod/render/mixin/MixinCamera.java | 49 - .../render/mixin/MixinChunkRenderWorker.java | 2 +- .../render/mixin/MixinEntityRenderer.java | 134 +-- .../render/mixin/MixinFogRenderer.java | 15 +- .../render/mixin/MixinParticleManager.java | 3 +- .../replaymod/render/mixin/MixinRender.java | 7 +- .../render/mixin/MixinRenderGlobal.java | 2 +- .../render/mixin/MixinRenderManager.java | 38 +- .../render/mixin/Mixin_ChromaKeyColorSky.java | 39 + .../render/mixin/Mixin_ChromaKeyForceSky.java | 45 + .../render/mixin/Mixin_CubicRotation.java | 98 ++ .../Mixin_SkipBlockOutlinesDuringRender.java | 23 + .../render/mixin/WorldRendererAccessor.java | 2 + .../replaymod/render/rendering/Pipeline.java | 6 +- .../render/rendering/VideoRenderer.java | 66 +- .../replaymod/replay/FullReplaySender.java | 50 +- .../com/replaymod/replay/NoGuiScreenshot.java | 18 +- .../replaymod/replay/QuickReplaySender.java | 999 +----------------- .../com/replaymod/replay/ReplayHandler.java | 44 +- .../com/replaymod/replay/ReplayModReplay.java | 8 +- .../replaymod/replay/camera/CameraEntity.java | 17 +- .../simplepathing/gui/GuiPathing.java | 2 +- .../preview/PathPreviewRenderer.java | 22 +- .../mixins.render.blend.replaymod.json | 14 +- .../resources/mixins.render.replaymod.json | 10 +- versions/common.gradle | 8 +- versions/mapping-fabric-1.15.1-1.14.4.txt | 28 + 65 files changed, 874 insertions(+), 1303 deletions(-) create mode 100644 src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyColorSky.java create mode 100644 src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyForceSky.java create mode 100644 src/main/java/com/replaymod/render/mixin/Mixin_CubicRotation.java create mode 100644 src/main/java/com/replaymod/render/mixin/Mixin_SkipBlockOutlinesDuringRender.java create mode 100644 versions/mapping-fabric-1.15.1-1.14.4.txt diff --git a/build.gradle.kts b/build.gradle.kts index 0f216d34..631ddbc3 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -174,18 +174,20 @@ val doRelease by tasks.registering { defaultTasks("shadowJar") preprocess { - "1.14.4"(11404, "yarn") { - "1.14.4-forge"(11404, "srg", file("versions/mapping-1.14.4-fabric-forge.txt")) { - "1.12.2"(11202, "srg", file("versions/1.14.4-forge/mapping.txt")) { - "1.12.1"(11201, "srg") { - "1.12"(11200, "srg") { - "1.11.2"(11102, "srg", file("versions/1.12/mapping.txt")) { - "1.11"(11100, "srg", file("versions/1.11.2/mapping.txt")) { - "1.10.2"(11002, "srg", file("versions/1.11/mapping.txt")) { - "1.9.4"(10904, "srg") { - "1.8.9"(10809, "srg", file("versions/1.9.4/mapping.txt")) { - "1.8"(10800, "srg", file("versions/1.8.9/mapping.txt")) { - "1.7.10"(10710, "srg", file("versions/1.8/mapping.txt")) + "1.15.1"(11501, "yarn") { + "1.14.4"(11404, "yarn", file("versions/mapping-fabric-1.15.1-1.14.4.txt")) { + "1.14.4-forge"(11404, "srg", file("versions/mapping-1.14.4-fabric-forge.txt")) { + "1.12.2"(11202, "srg", file("versions/1.14.4-forge/mapping.txt")) { + "1.12.1"(11201, "srg") { + "1.12"(11200, "srg") { + "1.11.2"(11102, "srg", file("versions/1.12/mapping.txt")) { + "1.11"(11100, "srg", file("versions/1.11.2/mapping.txt")) { + "1.10.2"(11002, "srg", file("versions/1.11/mapping.txt")) { + "1.9.4"(10904, "srg") { + "1.8.9"(10809, "srg", file("versions/1.9.4/mapping.txt")) { + "1.8"(10800, "srg", file("versions/1.8.9/mapping.txt")) { + "1.7.10"(10710, "srg", file("versions/1.8/mapping.txt")) + } } } } diff --git a/jGui b/jGui index 36fd2eb4..b434c785 160000 --- a/jGui +++ b/jGui @@ -1 +1 @@ -Subproject commit 36fd2eb40214e457803cb5ab9e27dfcc003b413a +Subproject commit b434c785291baca42307c6584f3abe99938ca6cf diff --git a/settings.gradle.kts b/settings.gradle.kts index 68234031..767950ce 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,7 +26,8 @@ val jGuiVersions = listOf( "1.9.4", "1.12", "1.14.4-forge", - "1.14.4" + "1.14.4", + "1.15.1" ) val replayModVersions = listOf( "1.7.10", @@ -40,7 +41,8 @@ val replayModVersions = listOf( "1.12.1", "1.12.2", "1.14.4-forge", - "1.14.4" + "1.14.4", + "1.15.1" ) include(":jGui") diff --git a/src/main/java/com/replaymod/core/ReplayMod.java b/src/main/java/com/replaymod/core/ReplayMod.java index 3a18c894..8a0ce753 100755 --- a/src/main/java/com/replaymod/core/ReplayMod.java +++ b/src/main/java/com/replaymod/core/ReplayMod.java @@ -15,7 +15,9 @@ import com.replaymod.recording.ReplayModRecording; import com.replaymod.render.ReplayModRender; import com.replaymod.replay.ReplayModReplay; import com.replaymod.replaystudio.studio.ReplayStudio; +import com.replaymod.replaystudio.us.myles.ViaVersion.api.protocol.ProtocolVersion; import com.replaymod.replaystudio.util.I18n; +import com.replaymod.replaystudio.viaversion.ViaVersionPacketConverter; import com.replaymod.simplepathing.ReplayModSimplePathing; import de.johni0702.minecraft.gui.container.GuiScreen; import lombok.Getter; @@ -30,8 +32,6 @@ import net.minecraft.util.Formatting; import org.apache.commons.io.FileUtils; //#if MC>=11400 -import com.github.steveice10.mc.protocol.MinecraftConstants; -import net.minecraft.SharedConstants; import net.minecraft.client.options.Option; import net.minecraft.resource.ResourcePackCreator; import net.minecraft.resource.ResourcePackContainer; @@ -99,8 +99,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import static com.replaymod.core.versions.MCVer.*; - //#if FABRIC<=0 //#if MC>=11300 //$$ @Mod(ReplayMod.MOD_ID) @@ -180,19 +178,8 @@ public class ReplayMod implements //#if MC>=11400 // Check Minecraft protocol version for compatibility - int supportedProtocol = MinecraftConstants.PROTOCOL_VERSION; - int actualProtocol = SharedConstants.getGameVersion().getProtocolVersion(); - if (supportedProtocol != actualProtocol && !Boolean.parseBoolean(System.getProperty("replaymod.skipversioncheck", "false"))) { + if (!ProtocolVersion.isRegistered(MCVer.getProtocolVersion()) && !Boolean.parseBoolean(System.getProperty("replaymod.skipversioncheck", "false"))) { minimalMode = true; - // Only allow use of older RM on newer (e.g. snapshot, pre-release) versions. - // The other way around is almost certainly user error. - if (actualProtocol < supportedProtocol && !Boolean.parseBoolean(System.getProperty("replaymod.allowoldsnapshot", "false"))) { - throw new UnsupportedOperationException(String.format( - "Unsupported Minecraft version, supporting protocol version %s (%s) but actual version is %s (%s).", - supportedProtocol, MinecraftConstants.GAME_VERSION, - actualProtocol, SharedConstants.getGameVersion().getName() - )); - } } //#endif @@ -453,7 +440,10 @@ public class ReplayMod implements public static class ReplayModExecutor extends NonBlockingThreadExecutor { private final Thread mcThread = Thread.currentThread(); // Fail-fast in case we ever switch to async loading and forget to change this + // (except for fabric 1.15+ because it loads the mod before the client thread is set) + //#if FABRIC<1 || MC<11500 { if (!MinecraftClient.getInstance().isOnThread()) throw new RuntimeException(); } + //#endif private ReplayModExecutor(String string_1) { super(string_1); @@ -474,7 +464,7 @@ public class ReplayMod implements return mcThread; } - //#if FABRIC>=1 + //#if FABRIC>=1 && MC<11500 @Override public void send(Runnable runnable) { method_18858(runnable); @@ -649,7 +639,7 @@ public class ReplayMod implements if (isMinimalMode()) { return protocolVersion == MCVer.getProtocolVersion(); } else { - return new ReplayStudio().isCompatible(fileFormatVersion, protocolVersion); + return new ReplayStudio().isCompatible(fileFormatVersion, protocolVersion, MCVer.getProtocolVersion()); } } } diff --git a/src/main/java/com/replaymod/core/gui/RestoreReplayGui.java b/src/main/java/com/replaymod/core/gui/RestoreReplayGui.java index d15b7af0..73b56e12 100644 --- a/src/main/java/com/replaymod/core/gui/RestoreReplayGui.java +++ b/src/main/java/com/replaymod/core/gui/RestoreReplayGui.java @@ -2,6 +2,7 @@ package com.replaymod.core.gui; import com.google.common.io.Files; import com.google.gson.Gson; +import com.replaymod.core.versions.MCVer; import com.replaymod.replaystudio.io.ReplayInputStream; import com.replaymod.replaystudio.io.ReplayOutputStream; import com.replaymod.replaystudio.replay.ReplayFile; @@ -56,8 +57,8 @@ public class RestoreReplayGui extends AbstractGuiScreen { if (metaData != null && metaData.getDuration() == 0) { // Try to restore replay duration // We need to re-write the packet data in case there are any incomplete packets dangling at the end - try (ReplayInputStream in = replayFile.getPacketData(studio, true); - ReplayOutputStream out = replayFile.writePacketData(true)) { + try (ReplayInputStream in = replayFile.getPacketData(MCVer.getPacketTypeRegistry(true)); + ReplayOutputStream out = replayFile.writePacketData()) { while (true) { // To prevent failing at un-parsable packets and to support recovery in minimal mode, // we do not use the ReplayIn/OutputStream methods but instead parse the packets ourselves. diff --git a/src/main/java/com/replaymod/core/mixin/MinecraftAccessor.java b/src/main/java/com/replaymod/core/mixin/MinecraftAccessor.java index d1b884ab..2ab12595 100644 --- a/src/main/java/com/replaymod/core/mixin/MinecraftAccessor.java +++ b/src/main/java/com/replaymod/core/mixin/MinecraftAccessor.java @@ -32,9 +32,6 @@ public interface MinecraftAccessor { //$$ Queue> getScheduledTasks(); //#endif - @Accessor("crashed") - boolean hasCrashed(); - @Accessor("crashReport") CrashReport getCrashReporter(); diff --git a/src/main/java/com/replaymod/core/mixin/MixinGameRenderer.java b/src/main/java/com/replaymod/core/mixin/MixinGameRenderer.java index cb095cf8..7f62367d 100644 --- a/src/main/java/com/replaymod/core/mixin/MixinGameRenderer.java +++ b/src/main/java/com/replaymod/core/mixin/MixinGameRenderer.java @@ -10,6 +10,10 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//#if MC>=11500 +//$$ import net.minecraft.client.util.math.MatrixStack; +//#endif + @Mixin(GameRenderer.class) public class MixinGameRenderer { @Inject( @@ -19,12 +23,24 @@ public class MixinGameRenderer { target = "Lnet/minecraft/client/render/GameRenderer;renderHand:Z" ) ) - private void postRenderWorld(float partialTicks, long nanoTime, CallbackInfo ci) { + private void postRenderWorld( + float partialTicks, + long nanoTime, + //#if MC>=11500 + //$$ MatrixStack matrixStack, + //#endif + CallbackInfo ci) { PostRenderWorldCallback.EVENT.invoker().postRenderWorld(); } @Inject(method = "renderHand", at = @At("HEAD"), cancellable = true) - private void preRenderHand(Camera camera, float partialTicks, CallbackInfo ci) { + private void preRenderHand( + //#if MC>=11500 + //$$ MatrixStack matrixStack, + //#endif + Camera camera, + float partialTicks, + CallbackInfo ci) { if (PreRenderHandCallback.EVENT.invoker().preRenderHand()) { ci.cancel(); } diff --git a/src/main/java/com/replaymod/core/utils/Utils.java b/src/main/java/com/replaymod/core/utils/Utils.java index 3a55c329..81c3973d 100644 --- a/src/main/java/com/replaymod/core/utils/Utils.java +++ b/src/main/java/com/replaymod/core/utils/Utils.java @@ -1,11 +1,13 @@ package com.replaymod.core.utils; import com.google.common.base.Throwables; +import com.google.common.collect.Iterables; import com.google.common.net.PercentEscaper; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.replaymod.core.ReplayMod; +import com.replaymod.replaystudio.us.myles.ViaVersion.api.protocol.ProtocolVersion; import de.johni0702.minecraft.gui.GuiRenderer; import de.johni0702.minecraft.gui.RenderInfo; import de.johni0702.minecraft.gui.container.AbstractGuiScrollable; @@ -37,11 +39,9 @@ import org.apache.logging.log4j.Logger; //#endif //#if MC>=10800 -import com.github.steveice10.mc.protocol.MinecraftConstants; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.client.util.DefaultSkinHelper; //#else -//$$ import com.github.steveice10.mc.protocol.ProtocolConstants; //$$ import net.minecraft.client.Minecraft; //$$ import net.minecraft.client.entity.AbstractClientPlayer; //$$ import net.minecraft.entity.player.EntityPlayer; @@ -366,11 +366,9 @@ public class Utils { new GuiLabel() .setColor(Colors.BLACK) .setI18nText("replaymod.gui.minimalmode.supportedversion", - //#if MC>=10800 - MinecraftConstants.GAME_VERSION - //#else - //$$ ProtocolConstants.GAME_VERSION - //#endif + ProtocolVersion.v1_7_6.getName() + + " - " + + Iterables.getLast(ProtocolVersion.getProtocols()).getName() )); open(); diff --git a/src/main/java/com/replaymod/core/versions/LangResourcePack.java b/src/main/java/com/replaymod/core/versions/LangResourcePack.java index 5be4e7e4..874a7689 100644 --- a/src/main/java/com/replaymod/core/versions/LangResourcePack.java +++ b/src/main/java/com/replaymod/core/versions/LangResourcePack.java @@ -137,7 +137,15 @@ public class LangResourcePack extends AbstractFileResourcePack { @Override - public Collection findResources(ResourceType resourcePackType, String path, int maxDepth, Predicate filter) { + public Collection findResources( + ResourceType resourcePackType, + //#if MC>=11500 + //$$ String namespace, + //#endif + String path, + int maxDepth, + Predicate filter + ) { if (resourcePackType == ResourceType.CLIENT_RESOURCES && "lang".equals(path)) { Path base = baseLangPath(); //#if MC<11400 diff --git a/src/main/java/com/replaymod/core/versions/MCVer.java b/src/main/java/com/replaymod/core/versions/MCVer.java index 322fbd85..0e7f8583 100644 --- a/src/main/java/com/replaymod/core/versions/MCVer.java +++ b/src/main/java/com/replaymod/core/versions/MCVer.java @@ -2,6 +2,9 @@ package com.replaymod.core.versions; import com.replaymod.core.mixin.GuiScreenAccessor; import com.replaymod.core.mixin.MinecraftAccessor; +import com.replaymod.replaystudio.protocol.PacketTypeRegistry; +import com.replaymod.replaystudio.us.myles.ViaVersion.api.protocol.ProtocolVersion; +import com.replaymod.replaystudio.us.myles.ViaVersion.packets.State; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.world.ClientWorld; @@ -27,6 +30,8 @@ import net.minecraft.SharedConstants; import net.minecraft.client.gui.screen.TitleScreen; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.AbstractButtonWidget; + +import java.util.ArrayList; import java.util.concurrent.CompletableFuture; //#else //$$ import com.google.common.util.concurrent.FutureCallback; @@ -76,7 +81,9 @@ import net.minecraft.client.render.BufferBuilder; import com.mojang.blaze3d.platform.GlStateManager; import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormatElement; +//#if MC<11500 import net.minecraft.client.render.chunk.ChunkRenderTask; +//#endif //#else //$$ import com.replaymod.core.mixin.ResourcePackRepositoryAccessor; //$$ import com.google.common.util.concurrent.Futures; @@ -134,10 +141,18 @@ public class MCVer { //#if MC>=11400 return SharedConstants.getGameVersion().getProtocolVersion(); //#else + // FIXME //$$ throw new UnsupportedOperationException("Minimal mode not supported pre-1.14"); //#endif } + public static PacketTypeRegistry getPacketTypeRegistry(boolean loginPhase) { + return PacketTypeRegistry.get( + ProtocolVersion.getProtocol(getProtocolVersion()), + loginPhase ? State.LOGIN : State.PLAY + ); + } + public static void addDetail(CrashReportSection category, String name, Callable callable) { //#if MC>=10904 //#if MC>=11200 @@ -150,6 +165,40 @@ public class MCVer { //#endif } + public static double Entity_getX(Entity entity) { + //#if MC>=11500 + //$$ return entity.getX(); + //#else + return entity.x; + //#endif + } + + public static double Entity_getY(Entity entity) { + //#if MC>=11500 + //$$ return entity.getY(); + //#else + return entity.y; + //#endif + } + + public static double Entity_getZ(Entity entity) { + //#if MC>=11500 + //$$ return entity.getZ(); + //#else + return entity.z; + //#endif + } + + public static void Entity_setPos(Entity entity, double x, double y, double z) { + //#if MC>=11500 + //$$ entity.setPos(x, y, z); + //#else + entity.x = x; + entity.y = y; + entity.z = z; + //#endif + } + //#if MC>=11400 public static void width(AbstractButtonWidget button, int value) { button.setWidth(value); @@ -314,7 +363,11 @@ public class MCVer { @SuppressWarnings("unchecked") public static List cubeList(Cuboid modelRenderer) { + //#if MC>=11400 + //$$ return new ArrayList<>(); // FIXME 1.15 + //#else return modelRenderer.boxes; + //#endif } @SuppressWarnings("unchecked") @@ -335,8 +388,18 @@ public class MCVer { } //#if MC>=11300 - public static Window newScaledResolution(MinecraftClient mc) { + public static Window getWindow(MinecraftClient mc) { + //#if MC>=11500 + //$$ return mc.getWindow(); + //#else return mc.window; + //#endif + } + //#endif + + //#if MC>=11300 + public static Window newScaledResolution(MinecraftClient mc) { + return getWindow(mc); } //#else //$$ public static ScaledResolution newScaledResolution(Minecraft mc) { @@ -410,10 +473,6 @@ public class MCVer { //$$ } //#endif - public static void BufferBuilder_setTranslation(double x, double y, double z) { - Tessellator_getBufferBuilder().setOffset(x, y, z); - } - public static void BufferBuilder_beginPosCol(int mode) { Tessellator_getBufferBuilder().begin( mode @@ -441,7 +500,7 @@ public class MCVer { ); } - public static void BufferBuilder_addPosTex(double x, double y, double z, double u, double v) { + public static void BufferBuilder_addPosTex(double x, double y, double z, float u, float v) { //#if MC>=10809 Tessellator_getBufferBuilder().vertex(x, y, z).texture(u, v).next(); //#else @@ -458,7 +517,7 @@ public class MCVer { ); } - public static void BufferBuilder_addPosTexCol(double x, double y, double z, double u, double v, int r, int g, int b, int a) { + public static void BufferBuilder_addPosTexCol(double x, double y, double z, float u, float v, int r, int g, int b, int a) { //#if MC>=10809 Tessellator_getBufferBuilder().vertex(x, y, z).texture(u, v).color(r, g, b, a).next(); //#else @@ -542,7 +601,7 @@ public class MCVer { //#endif } - //#if MC>=10800 + //#if MC>=10800 && MC<11500 public interface ChunkRenderWorkerAccessor { void doRunTask(ChunkRenderTask task) throws InterruptedException; } @@ -557,11 +616,15 @@ public class MCVer { } public static void bindTexture(Identifier texture) { + //#if MC>=11500 + //$$ getMinecraft().getTextureManager().bindTexture(texture); + //#else //#if MC>=11300 getMinecraft().getTextureManager().bindTexture(texture); //#else //$$ getMinecraft().renderEngine.bindTexture(texture); //#endif + //#endif } public static float cos(float val) { @@ -751,6 +814,9 @@ public class MCVer { //#endif public static boolean isKeyDown(int keyCode) { + //#if MC>=11500 + //$$ return InputUtil.isKeyPressed(getMinecraft().getWindow().getHandle(), keyCode); + //#else //#if MC>=11400 return InputUtil.isKeyPressed(getMinecraft().window.getHandle(), keyCode); //#else @@ -760,6 +826,7 @@ public class MCVer { //$$ return org.lwjgl.input.Keyboard.isKeyDown(keyCode); //#endif //#endif + //#endif } //#if MC<11300 diff --git a/src/main/java/com/replaymod/editor/gui/MarkerProcessor.java b/src/main/java/com/replaymod/editor/gui/MarkerProcessor.java index c0fe5cdf..b96eb158 100644 --- a/src/main/java/com/replaymod/editor/gui/MarkerProcessor.java +++ b/src/main/java/com/replaymod/editor/gui/MarkerProcessor.java @@ -1,5 +1,6 @@ package com.replaymod.editor.gui; +import com.replaymod.core.versions.MCVer; import com.replaymod.replaystudio.PacketData; import com.replaymod.replaystudio.Studio; import com.replaymod.replaystudio.data.Marker; @@ -7,6 +8,7 @@ import com.replaymod.replaystudio.filter.SquashFilter; import com.replaymod.replaystudio.filter.StreamFilter; import com.replaymod.replaystudio.io.ReplayInputStream; import com.replaymod.replaystudio.io.ReplayOutputStream; +import com.replaymod.replaystudio.protocol.PacketTypeRegistry; import com.replaymod.replaystudio.replay.ReplayMetaData; import com.replaymod.replaystudio.replay.ZipReplayFile; import com.replaymod.replaystudio.stream.IteratorStream; @@ -58,6 +60,7 @@ public class MarkerProcessor { String replayName = FilenameUtils.getBaseName(path.getFileName().toString()); int splitCounter = 0; + PacketTypeRegistry registry = MCVer.getPacketTypeRegistry(true); Studio studio = new ReplayStudio(); SquashFilter squashFilter = new SquashFilter(); squashFilter.init(studio, null); @@ -73,7 +76,7 @@ public class MarkerProcessor { boolean anySplit = markers.stream().anyMatch(m -> MARKER_NAME_SPLIT.equals(m.getName())); int inputDuration = inputReplayFile.getMetaData().getDuration(); - ReplayInputStream replayInputStream = inputReplayFile.getPacketData(studio, true); + ReplayInputStream replayInputStream = inputReplayFile.getPacketData(registry); int timeOffset = 0; SquashFilter cutFilter = null; int startCutOffset = 0; @@ -88,7 +91,7 @@ public class MarkerProcessor { ReplayMetaData metaData = inputReplayFile.getMetaData(); metaData.setDate(metaData.getDate() + timeOffset); - try (ReplayOutputStream replayOutputStream = outputReplayFile.writePacketData(true)) { + try (ReplayOutputStream replayOutputStream = outputReplayFile.writePacketData()) { if (cutFilter != null) { cutFilter = squashFilter; } else if (splitCounter > 0) { @@ -153,7 +156,7 @@ public class MarkerProcessor { } metaData.setDuration((int) duration); - outputReplayFile.writeMetaData(metaData); + outputReplayFile.writeMetaData(registry, metaData); outputReplayFile.writeMarkers(outputMarkers); diff --git a/src/main/java/com/replaymod/extras/advancedscreenshots/ScreenshotRenderer.java b/src/main/java/com/replaymod/extras/advancedscreenshots/ScreenshotRenderer.java index 835dce2b..68cfb2ab 100644 --- a/src/main/java/com/replaymod/extras/advancedscreenshots/ScreenshotRenderer.java +++ b/src/main/java/com/replaymod/extras/advancedscreenshots/ScreenshotRenderer.java @@ -13,9 +13,10 @@ import net.minecraft.util.crash.CrashReport; //#if MC>=11300 import com.replaymod.render.mixin.MainWindowAccessor; +import static com.replaymod.core.versions.MCVer.getWindow; //#endif -//#if MC>=10800 +//#if MC>=10800 && MC<11500 import com.replaymod.render.hooks.ChunkLoadingRenderGlobal; //#endif @@ -33,8 +34,8 @@ public class ScreenshotRenderer implements RenderInfo { public boolean renderScreenshot() throws Throwable { try { //#if MC>=11300 - int displayWidthBefore = mc.window.getFramebufferWidth(); - int displayHeightBefore = mc.window.getFramebufferHeight(); + int displayWidthBefore = getWindow(mc).getFramebufferWidth(); + int displayHeightBefore = getWindow(mc).getFramebufferHeight(); //#else //$$ int displayWidthBefore = mc.displayWidth; //$$ int displayHeightBefore = mc.displayHeight; @@ -43,7 +44,7 @@ public class ScreenshotRenderer implements RenderInfo { boolean hideGUIBefore = mc.options.hudHidden; mc.options.hudHidden = true; - //#if MC>=10800 + //#if MC>=10800 && MC<11500 ChunkLoadingRenderGlobal clrg = new ChunkLoadingRenderGlobal(mc.worldRenderer); //#endif @@ -55,14 +56,14 @@ public class ScreenshotRenderer implements RenderInfo { new ScreenshotWriter(settings.getOutputFile())).run(); } - //#if MC>=10800 + //#if MC>=10800 && MC<11500 clrg.uninstall(); //#endif mc.options.hudHidden = hideGUIBefore; //#if MC>=11300 //noinspection ConstantConditions - MainWindowAccessor acc = (MainWindowAccessor) (Object) mc.window; + MainWindowAccessor acc = (MainWindowAccessor) (Object) getWindow(mc); acc.setFramebufferWidth(displayWidthBefore); acc.setFramebufferHeight(displayHeightBefore); mc.getFramebuffer().resize(displayWidthBefore, displayHeightBefore diff --git a/src/main/java/com/replaymod/extras/urischeme/UriScheme.java b/src/main/java/com/replaymod/extras/urischeme/UriScheme.java index bcf040d1..eddf816d 100644 --- a/src/main/java/com/replaymod/extras/urischeme/UriScheme.java +++ b/src/main/java/com/replaymod/extras/urischeme/UriScheme.java @@ -73,10 +73,17 @@ public abstract class UriScheme { switch (SystemUtil.getOperatingSystem()) { case LINUX: return new LinuxUriScheme(); + //#if MC>=11500 + //$$ case WINDOWS: + //$$ return new WindowsUriScheme(); + //$$ case OSX: + //$$ return new OSXUriScheme(); + //#else case field_1133: return new WindowsUriScheme(); case field_1137: return new OSXUriScheme(); + //#endif case SOLARIS: case UNKNOWN: default: diff --git a/src/main/java/com/replaymod/online/gui/GuiUploadReplay.java b/src/main/java/com/replaymod/online/gui/GuiUploadReplay.java index d2486deb..20a05e9b 100644 --- a/src/main/java/com/replaymod/online/gui/GuiUploadReplay.java +++ b/src/main/java/com/replaymod/online/gui/GuiUploadReplay.java @@ -201,7 +201,7 @@ public class GuiUploadReplay extends GuiScreen { try (ReplayFile replay = new ZipReplayFile(new ReplayStudio(), file)) { ReplayMetaData newMetaData = new ReplayMetaData(metaData); newMetaData.setServerName(null); - replay.writeMetaData(newMetaData); + replay.writeMetaData(null, newMetaData); replay.saveTo(tmp); } diff --git a/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java b/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java index efbabc29..6626e527 100755 --- a/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java +++ b/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java @@ -152,9 +152,9 @@ public class RecordingEventHandler extends EventRegistrations { boolean force = false; if(lastX == null || lastY == null || lastZ == null) { force = true; - lastX = player.x; - lastY = player.y; - lastZ = player.z; + lastX = Entity_getX(player); + lastY = Entity_getY(player); + lastZ = Entity_getZ(player); } ticksSinceLastCorrection++; @@ -163,13 +163,13 @@ public class RecordingEventHandler extends EventRegistrations { force = true; } - double dx = player.x - lastX; - double dy = player.y - lastY; - double dz = player.z - lastZ; + double dx = Entity_getX(player) - lastX; + double dy = Entity_getY(player) - lastY; + double dz = Entity_getZ(player) - lastZ; - lastX = player.x; - lastY = player.y; - lastZ = player.z; + lastX = Entity_getX(player); + lastY = Entity_getY(player); + lastZ = Entity_getZ(player); Packet packet; if (force || Math.abs(dx) > 8.0 || Math.abs(dy) > 8.0 || Math.abs(dz) > 8.0) { diff --git a/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerPlayClient.java b/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerPlayClient.java index 35b23afb..7ef10cd2 100644 --- a/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerPlayClient.java +++ b/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerPlayClient.java @@ -12,8 +12,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //#if MC>=10800 -import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPlayerListEntryPacket; -import com.github.steveice10.packetlib.io.buffer.ByteBufferNetInput; +import com.replaymod.replaystudio.protocol.Packet; +import com.replaymod.replaystudio.protocol.PacketType; +import com.replaymod.replaystudio.protocol.packets.PacketPlayerListEntry; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import net.minecraft.util.PacketByteBuf; @@ -21,7 +22,6 @@ import net.minecraft.client.network.packet.PlayerListS2CPacket; import net.minecraft.client.network.PlayerListEntry; import java.io.IOException; -import java.nio.ByteBuffer; import java.util.Map; import java.util.UUID; //#else @@ -62,10 +62,9 @@ public abstract class MixinNetHandlerPlayClient { RecordingEventHandler handler = getRecordingEventHandler(); if (handler != null && packet.getAction() == PlayerListS2CPacket.Action.ADD_PLAYER) { // We cannot reference SPacketPlayerListItem.AddPlayerData directly for complicated (and yet to be - // resolved) reasons (see https://github.com/MinecraftForge/ForgeGradle/issues/472), so we "simply" convert - // the back to the MCProtocolLib equivalent and deal with that one. + // resolved) reasons (see https://github.com/MinecraftForge/ForgeGradle/issues/472), so we use ReplayStudio + // to parse it instead. ByteBuf byteBuf = Unpooled.buffer(); - ServerPlayerListEntryPacket mcpl = new ServerPlayerListEntryPacket(null, null); try { packet.write(new PacketByteBuf(byteBuf)); @@ -73,21 +72,22 @@ public abstract class MixinNetHandlerPlayClient { byte[] array = new byte[byteBuf.readableBytes()]; byteBuf.readBytes(array); - mcpl.read(new ByteBufferNetInput(ByteBuffer.wrap(array))); + for (PacketPlayerListEntry data : PacketPlayerListEntry.read(new Packet( + MCVer.getPacketTypeRegistry(false), 0, PacketType.PlayerListEntry, + com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(array) + ))) { + if (data.getUuid() == null) continue; + // Only add spawn packet for our own player and only if he isn't known yet + if (data.getUuid().equals(mcStatic.player.getGameProfile().getId()) + && !this.playerListEntries.containsKey(data.getUuid())) { + handler.onPlayerJoin(); + } + } } catch (IOException e) { throw new RuntimeException(e); // we just parsed this? } finally { byteBuf.release(); } - - for (com.github.steveice10.mc.protocol.data.game.PlayerListEntry data : mcpl.getEntries()) { - if (data.getProfile() == null || data.getProfile().getId() == null) continue; - // Only add spawn packet for our own player and only if he isn't known yet - if (data.getProfile().getId().equals(mcStatic.player.getGameProfile().getId()) - && !this.playerListEntries.containsKey(data.getProfile().getId())) { - handler.onPlayerJoin(); - } - } } } //#else diff --git a/src/main/java/com/replaymod/recording/mixin/SPacketSpawnMobAccessor.java b/src/main/java/com/replaymod/recording/mixin/SPacketSpawnMobAccessor.java index e0a65717..a518467b 100644 --- a/src/main/java/com/replaymod/recording/mixin/SPacketSpawnMobAccessor.java +++ b/src/main/java/com/replaymod/recording/mixin/SPacketSpawnMobAccessor.java @@ -7,8 +7,10 @@ import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(MobSpawnS2CPacket.class) public interface SPacketSpawnMobAccessor { + //#if MC<11500 @Accessor("dataTracker") DataTracker getDataManager(); @Accessor("dataTracker") void setDataManager(DataTracker value); + //#endif } diff --git a/src/main/java/com/replaymod/recording/mixin/SPacketSpawnPlayerAccessor.java b/src/main/java/com/replaymod/recording/mixin/SPacketSpawnPlayerAccessor.java index 10af34f3..dde911ff 100644 --- a/src/main/java/com/replaymod/recording/mixin/SPacketSpawnPlayerAccessor.java +++ b/src/main/java/com/replaymod/recording/mixin/SPacketSpawnPlayerAccessor.java @@ -7,8 +7,10 @@ import org.spongepowered.asm.mixin.gen.Accessor; @Mixin(PlayerSpawnS2CPacket.class) public interface SPacketSpawnPlayerAccessor { + //#if MC<11500 @Accessor("dataTracker") DataTracker getDataManager(); @Accessor("dataTracker") void setDataManager(DataTracker value); + //#endif } diff --git a/src/main/java/com/replaymod/recording/packet/PacketListener.java b/src/main/java/com/replaymod/recording/packet/PacketListener.java index 69e589e7..1cd3be9b 100755 --- a/src/main/java/com/replaymod/recording/packet/PacketListener.java +++ b/src/main/java/com/replaymod/recording/packet/PacketListener.java @@ -114,7 +114,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter { this.metaData = metaData; this.resourcePackRecorder = new ResourcePackRecorder(replayFile); // Note: doesn't actually always include the login phase, see `connectionState` field instead. - this.packetOutputStream = new DataOutputStream(replayFile.writePacketData(true)); + this.packetOutputStream = new DataOutputStream(replayFile.writePacketData()); this.startTime = metaData.getDate(); saveMetaData(); @@ -139,7 +139,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter { out.write(json.getBytes()); } } else { - replayFile.writeMetaData(metaData); + replayFile.writeMetaData(MCVer.getPacketTypeRegistry(true), metaData); } } } catch (IOException e) { @@ -325,6 +325,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter { @SuppressWarnings("unchecked") private byte[] getPacketData(Packet packet) throws Exception { + //#if MC<11500 if (packet instanceof MobSpawnS2CPacket) { MobSpawnS2CPacket p = (MobSpawnS2CPacket) packet; SPacketSpawnMobAccessor pa = (SPacketSpawnMobAccessor) p; @@ -368,6 +369,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter { } } } + //#endif //#if MC>=10800 Integer packetId = connectionState.getPacketId(NetworkSide.CLIENTBOUND, packet); @@ -401,9 +403,9 @@ public class PacketListener extends ChannelInboundHandlerAdapter { marker.setName(name); marker.setTime(timestamp); if (view != null) { - marker.setX(view.x); - marker.setY(view.y); - marker.setZ(view.z); + marker.setX(Entity_getX(view)); + marker.setY(Entity_getY(view)); + marker.setZ(Entity_getZ(view)); marker.setYaw(view.yaw); marker.setPitch(view.pitch); } diff --git a/src/main/java/com/replaymod/render/RenderSettings.java b/src/main/java/com/replaymod/render/RenderSettings.java index 5b40302b..01fdb1b6 100644 --- a/src/main/java/com/replaymod/render/RenderSettings.java +++ b/src/main/java/com/replaymod/render/RenderSettings.java @@ -174,7 +174,12 @@ public class RenderSettings { private static String findFFmpeg() { switch (SystemUtil.getOperatingSystem()) { + // TODO not sure why remap fails to remap this (even when manually added to mappings) + //#if MC>=11500 + //$$ case WINDOWS: + //#else case field_1133: + //#endif // Allow windows users to unpack the ffmpeg archive into a sub-folder of their .minecraft folder File inDotMinecraft = new File(MCVer.getMinecraft().runDirectory, "ffmpeg/bin/ffmpeg.exe"); if (inDotMinecraft.exists()) { @@ -182,7 +187,12 @@ public class RenderSettings { return inDotMinecraft.getAbsolutePath(); } break; + // TODO not sure why remap fails to remap this (even when manually added to mappings) + //#if MC>=11500 + //$$ case OSX: + //#else case field_1137: + //#endif // The PATH doesn't seem to be set as expected on OSX, therefore we check some common locations ourselves for (String path : new String[]{"/usr/local/bin/ffmpeg", "/usr/bin/ffmpeg"}) { File file = new File(path); diff --git a/src/main/java/com/replaymod/render/blend/BlendMeshBuilder.java b/src/main/java/com/replaymod/render/blend/BlendMeshBuilder.java index 2c3c4d1b..09b2e29b 100644 --- a/src/main/java/com/replaymod/render/blend/BlendMeshBuilder.java +++ b/src/main/java/com/replaymod/render/blend/BlendMeshBuilder.java @@ -11,6 +11,10 @@ import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormatElement; import org.lwjgl.opengl.GL11; +//#if MC>=11500 +//$$ import com.mojang.datafixers.util.Pair; +//#endif + //#if MC>=10904 //#if MC>=11200 import net.minecraft.client.render.BufferBuilder; @@ -135,7 +139,12 @@ public class BlendMeshBuilder //#else //$$ public static DMesh addBufferToMesh(WorldRenderer bufferBuilder, DMesh mesh, Vector3f vertOffset) { //#endif + //#if MC>=11500 + //$$ Pair data = bufferBuilder.popData(); + //$$ return addBufferToMesh(data.getSecond(), data.getFirst().getMode(), data.getFirst().getVertexFormat(), mesh, vertOffset); + //#else return addBufferToMesh(bufferBuilder.getByteBuffer(), bufferBuilder.getDrawMode(), bufferBuilder.getVertexFormat(), mesh, vertOffset); + //#endif } public static DMesh addBufferToMesh(ByteBuffer buffer, int mode, VertexFormat vertexFormat, DMesh mesh, ReadableVector3f vertOffset) { @@ -158,12 +167,20 @@ public class BlendMeshBuilder // Determine offset of vertex components int posOffset = -1, colorOffset = -1, uvOffset = -1; int index = 0; + //#if MC>=11500 + int elementOffset = 0; + //#endif for (VertexFormatElement element : getElements(vertexFormat)) { + //#if MC>=11500 + //$$ int offset = elementOffset; + //$$ elementOffset += element.getSize(); + //#else //#if MC>=10809 int offset = vertexFormat.getElementOffset(index); //#else //$$ int offset = element.getOffset(); //#endif + //#endif switch (element.getType()) { case POSITION: //#if MC>=11400 diff --git a/src/main/java/com/replaymod/render/blend/BlendState.java b/src/main/java/com/replaymod/render/blend/BlendState.java index dfe810cb..5d2d2a7b 100644 --- a/src/main/java/com/replaymod/render/blend/BlendState.java +++ b/src/main/java/com/replaymod/render/blend/BlendState.java @@ -3,7 +3,10 @@ package com.replaymod.render.blend; import com.replaymod.render.blend.data.DScene; import com.replaymod.render.blend.data.Serializer; //#if MC>=10800 +// FIXME 1.15 +//#if MC<11500 import com.replaymod.render.blend.exporters.ChunkExporter; +//#endif import com.replaymod.render.blend.exporters.EntityExporter; import com.replaymod.render.blend.exporters.ItemExporter; import com.replaymod.render.blend.exporters.ParticlesExporter; @@ -53,7 +56,10 @@ public class BlendState implements Exporter { //#if MC>=10800 RenderState renderState = new RenderState(this); register(renderState); + // FIXME 1.15 + //#if MC<11500 register(new ChunkExporter()); + //#endif register(new EntityExporter(renderState)); register(new TileEntityExporter(renderState)); register(new ParticlesExporter(renderState)); diff --git a/src/main/java/com/replaymod/render/blend/exporters/ChunkExporter.java b/src/main/java/com/replaymod/render/blend/exporters/ChunkExporter.java index eb6f9bae..e1a4d10f 100644 --- a/src/main/java/com/replaymod/render/blend/exporters/ChunkExporter.java +++ b/src/main/java/com/replaymod/render/blend/exporters/ChunkExporter.java @@ -1,4 +1,5 @@ -//#if MC>=10800 +// FIXME 1.15 +//#if MC>=10800 && MC<11500 package com.replaymod.render.blend.exporters; import com.replaymod.core.versions.MCVer; diff --git a/src/main/java/com/replaymod/render/blend/exporters/ItemExporter.java b/src/main/java/com/replaymod/render/blend/exporters/ItemExporter.java index 7a8ef2aa..09d83c99 100644 --- a/src/main/java/com/replaymod/render/blend/exporters/ItemExporter.java +++ b/src/main/java/com/replaymod/render/blend/exporters/ItemExporter.java @@ -124,6 +124,9 @@ public class ItemExporter implements Exporter { //$$ ? stack.getItem().getColorFromItemStack(stack, quad.getTintIndex()) | 0xff000000 //#endif : 0xffffffff; + //#if MC>=11500 + //$$ // FIXME 1.15 + //#else //#if MC>=11400 buffer.putVertexData(quad.getVertexData()); buffer.setQuadColor(color); @@ -132,6 +135,7 @@ public class ItemExporter implements Exporter { //#else //$$ LightUtil.renderQuadColor(buffer, quad, color); //#endif + //#endif } } diff --git a/src/main/java/com/replaymod/render/blend/exporters/ModelRendererExporter.java b/src/main/java/com/replaymod/render/blend/exporters/ModelRendererExporter.java index 643ee0df..dcae0558 100644 --- a/src/main/java/com/replaymod/render/blend/exporters/ModelRendererExporter.java +++ b/src/main/java/com/replaymod/render/blend/exporters/ModelRendererExporter.java @@ -67,7 +67,11 @@ public class ModelRendererExporter implements Exporter { } if (object == null) { object = new ModelBasedDObject(model, scale); + //#if MC>=11500 + //$$ object.id.name = "???"; // FIXME 1.15 can we somehow nicely derive this? + //#else object.id.name = model.name; + //#endif object.setParent(parent); } object.lastFrame = frame; @@ -78,7 +82,11 @@ public class ModelRendererExporter implements Exporter { DMesh mesh = new DMesh(); BlendMeshBuilder builder = new BlendMeshBuilder(mesh); for (Box box : cubeList(model)) { + //#if MC>=11500 + //$$ // FIXME 1.15 + //#else box.render(builder, scale); + //#endif } builder.maybeFinishDrawing(); return mesh; diff --git a/src/main/java/com/replaymod/render/blend/exporters/ParticlesExporter.java b/src/main/java/com/replaymod/render/blend/exporters/ParticlesExporter.java index 70e037fd..d5db02f9 100644 --- a/src/main/java/com/replaymod/render/blend/exporters/ParticlesExporter.java +++ b/src/main/java/com/replaymod/render/blend/exporters/ParticlesExporter.java @@ -113,9 +113,16 @@ public class ParticlesExporter implements Exporter { // Instead of actually translating, we just add the translation on the current model-view-matrix. Matrix4f modelView = getGlModelViewMatrix(); ParticleAccessor acc = (ParticleAccessor) particle; - double dx = acc.getPrevPosX() + (acc.getPosX() - acc.getPrevPosX()) * renderPartialTicks - Particle.cameraX; - double dy = acc.getPrevPosY() + (acc.getPosY() - acc.getPrevPosY()) * renderPartialTicks - Particle.cameraY; - double dz = acc.getPrevPosZ() + (acc.getPosZ() - acc.getPrevPosZ()) * renderPartialTicks - Particle.cameraZ; + double dx = acc.getPrevPosX() + (acc.getPosX() - acc.getPrevPosX()) * renderPartialTicks; + double dy = acc.getPrevPosY() + (acc.getPosY() - acc.getPrevPosY()) * renderPartialTicks; + double dz = acc.getPrevPosZ() + (acc.getPosZ() - acc.getPrevPosZ()) * renderPartialTicks; + //#if MC>=11500 + //$$ // FIXME 1.15 is this still required? + //#else + dx -= Particle.cameraX; + dy -= Particle.cameraY; + dz -= Particle.cameraZ; + //#endif Vector3f offset = new Vector3f((float) dx, (float) dy, (float) dz); Matrix4f.translate(offset, modelView, modelView); renderState.pushModelView(modelView); @@ -173,7 +180,11 @@ public class ParticlesExporter implements Exporter { //#else //$$ MCVer.getMinecraft().getRenderViewEntity(), //#endif - 0, 1, 1, 0, 0, 0); + 0 + //#if MC<11500 + , 1, 1, 0, 0, 0 + //#endif + ); //#else //$$ particle.func_180434_a(builder, Minecraft.getMinecraft().getRenderViewEntity(), 0, 1, 1, 0, 0, 0); //#endif diff --git a/src/main/java/com/replaymod/render/blend/mixin/ContainerLocalRenderInformationAccessor.java b/src/main/java/com/replaymod/render/blend/mixin/ContainerLocalRenderInformationAccessor.java index f8d75b8a..81958585 100644 --- a/src/main/java/com/replaymod/render/blend/mixin/ContainerLocalRenderInformationAccessor.java +++ b/src/main/java/com/replaymod/render/blend/mixin/ContainerLocalRenderInformationAccessor.java @@ -15,11 +15,15 @@ import org.spongepowered.asm.mixin.gen.Accessor; //#endif //#endif public interface ContainerLocalRenderInformationAccessor { + //#if MC>=11500 + //$$ @Accessor("chunk") + //#else //#if MC>=11400 @Accessor("renderer") //#else //$$ @Accessor //#endif + //#endif ChunkRenderer getRenderChunk(); } //#endif diff --git a/src/main/java/com/replaymod/render/blend/mixin/MixinChunkRenderWorker.java b/src/main/java/com/replaymod/render/blend/mixin/MixinChunkRenderWorker.java index e2002298..32543f99 100644 --- a/src/main/java/com/replaymod/render/blend/mixin/MixinChunkRenderWorker.java +++ b/src/main/java/com/replaymod/render/blend/mixin/MixinChunkRenderWorker.java @@ -1,4 +1,5 @@ -//#if MC>=10800 +// FIXME 1.15 +//#if MC>=10800 && MC<11500 package com.replaymod.render.blend.mixin; import com.replaymod.render.blend.BlendState; diff --git a/src/main/java/com/replaymod/render/blend/mixin/MixinEffectRenderer.java b/src/main/java/com/replaymod/render/blend/mixin/MixinEffectRenderer.java index f0355c54..6512a91f 100644 --- a/src/main/java/com/replaymod/render/blend/mixin/MixinEffectRenderer.java +++ b/src/main/java/com/replaymod/render/blend/mixin/MixinEffectRenderer.java @@ -1,4 +1,4 @@ -//#if MC>=10800 +//#if MC>=10800 && MC<11500 package com.replaymod.render.blend.mixin; import com.replaymod.render.blend.BlendState; diff --git a/src/main/java/com/replaymod/render/blend/mixin/MixinModelRenderer.java b/src/main/java/com/replaymod/render/blend/mixin/MixinModelRenderer.java index afd1c82b..5c863aa0 100644 --- a/src/main/java/com/replaymod/render/blend/mixin/MixinModelRenderer.java +++ b/src/main/java/com/replaymod/render/blend/mixin/MixinModelRenderer.java @@ -1,4 +1,5 @@ -//#if MC>=10800 +// FIXME 1.15 +//#if MC>=10800 && MC<11500 package com.replaymod.render.blend.mixin; import com.replaymod.render.blend.BlendState; diff --git a/src/main/java/com/replaymod/render/blend/mixin/MixinRenderManager.java b/src/main/java/com/replaymod/render/blend/mixin/MixinRenderManager.java index e6084995..80d095d0 100644 --- a/src/main/java/com/replaymod/render/blend/mixin/MixinRenderManager.java +++ b/src/main/java/com/replaymod/render/blend/mixin/MixinRenderManager.java @@ -9,6 +9,11 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +//#if MC>=11500 +//$$ import net.minecraft.client.render.VertexConsumerProvider; +//$$ import net.minecraft.client.util.math.MatrixStack; +//#endif + //#if MC>=10904 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //#else @@ -19,6 +24,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; public abstract class MixinRenderManager { @Inject( + //#if MC>=11500 + //$$ method = "render", + //#else //#if MC>=11400 method = "render(Lnet/minecraft/entity/Entity;DDDFFZ)V", //#else @@ -28,9 +36,17 @@ public abstract class MixinRenderManager { //$$ method = "doRenderEntity", //#endif //#endif + //#endif at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/EntityRenderer;render(Lnet/minecraft/entity/Entity;DDDFF)V")) - public void preRender(Entity entity, double x, double y, double z, float yaw, float renderPartialTicks, boolean box, + public void preRender(Entity entity, double x, double y, double z, float yaw, float renderPartialTicks, + //#if MC>=11500 + //$$ MatrixStack matrixStack, + //$$ VertexConsumerProvider vertexConsumerProvider, + //$$ int int_1, + //#else + boolean box, + //#endif //#if MC>=10904 CallbackInfo ci) { //#else @@ -43,6 +59,9 @@ public abstract class MixinRenderManager { } @Inject( + //#if MC>=11500 + //$$ method = "render", + //#else //#if MC>=11400 method = "render(Lnet/minecraft/entity/Entity;DDDFFZ)V", //#else @@ -52,10 +71,18 @@ public abstract class MixinRenderManager { //$$ method = "doRenderEntity", //#endif //#endif + //#endif at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/EntityRenderer;render(Lnet/minecraft/entity/Entity;DDDFF)V", shift = At.Shift.AFTER)) - public void postRender(Entity entity, double x, double y, double z, float yaw, float renderPartialTicks, boolean box, + public void postRender(Entity entity, double x, double y, double z, float yaw, float renderPartialTicks, + //#if MC>=11500 + //$$ MatrixStack matrixStack, + //$$ VertexConsumerProvider vertexConsumerProvider, + //$$ int int_1, + //#else + boolean box, + //#endif //#if MC>=10904 CallbackInfo ci) { //#else diff --git a/src/main/java/com/replaymod/render/blend/mixin/MixinTileEntityRendererDispatcher.java b/src/main/java/com/replaymod/render/blend/mixin/MixinTileEntityRendererDispatcher.java index f21e4cda..5c7a57da 100644 --- a/src/main/java/com/replaymod/render/blend/mixin/MixinTileEntityRendererDispatcher.java +++ b/src/main/java/com/replaymod/render/blend/mixin/MixinTileEntityRendererDispatcher.java @@ -1,4 +1,5 @@ -//#if MC>=10800 +// FIXME 1.15 +//#if MC>=10800 && MC<11500 package com.replaymod.render.blend.mixin; import com.replaymod.render.blend.BlendState; diff --git a/src/main/java/com/replaymod/render/blend/mixin/WorldRendererAccessor.java b/src/main/java/com/replaymod/render/blend/mixin/WorldRendererAccessor.java index 1ac1271d..8972362b 100644 --- a/src/main/java/com/replaymod/render/blend/mixin/WorldRendererAccessor.java +++ b/src/main/java/com/replaymod/render/blend/mixin/WorldRendererAccessor.java @@ -1,4 +1,5 @@ -//#if MC>=10800 +// FIXME 1.15 +//#if MC>=10800 && MC<11500 package com.replaymod.render.blend.mixin; import net.minecraft.client.render.WorldRenderer; diff --git a/src/main/java/com/replaymod/render/capturer/OpenGlFrameCapturer.java b/src/main/java/com/replaymod/render/capturer/OpenGlFrameCapturer.java index 1819ea21..8367f684 100644 --- a/src/main/java/com/replaymod/render/capturer/OpenGlFrameCapturer.java +++ b/src/main/java/com/replaymod/render/capturer/OpenGlFrameCapturer.java @@ -18,6 +18,7 @@ import java.nio.ByteBuffer; //#if MC>=11300 import com.replaymod.render.mixin.MainWindowAccessor; +import static com.replaymod.core.versions.MCVer.getWindow; //#endif //#if MC>=10800 @@ -125,7 +126,7 @@ public abstract class OpenGlFrameCapturer=10800 +// FIXME 1.15 chunk rendering has changed significantly, ignoring this feature for now +//#if MC>=10800 && MC<11500 package com.replaymod.render.hooks; import com.replaymod.render.mixin.ChunkRenderDispatcherAccessor; diff --git a/src/main/java/com/replaymod/render/hooks/EntityRendererHandler.java b/src/main/java/com/replaymod/render/hooks/EntityRendererHandler.java index d2932dd9..f92c3005 100644 --- a/src/main/java/com/replaymod/render/hooks/EntityRendererHandler.java +++ b/src/main/java/com/replaymod/render/hooks/EntityRendererHandler.java @@ -8,6 +8,10 @@ import com.replaymod.render.capturer.WorldRenderer; import lombok.Getter; import net.minecraft.client.MinecraftClient; +//#if MC>=11500 +//$$ import net.minecraft.client.util.math.MatrixStack; +//#endif + //#if MC>=11400 import com.replaymod.core.events.PostRenderCallback; import com.replaymod.core.events.PreRenderCallback; @@ -59,7 +63,13 @@ public class EntityRendererHandler implements WorldRenderer { //#endif if (mc.world != null && mc.player != null) { - mc.gameRenderer.renderWorld(partialTicks, finishTimeNano); + mc.gameRenderer.renderWorld( + partialTicks, + finishTimeNano + //#if MC>=11500 + //$$ , new MatrixStack() + //#endif + ); } //#if MC>=11400 diff --git a/src/main/java/com/replaymod/render/mixin/ChunkRenderDispatcherAccessor.java b/src/main/java/com/replaymod/render/mixin/ChunkRenderDispatcherAccessor.java index 10a6cf1b..458441fb 100644 --- a/src/main/java/com/replaymod/render/mixin/ChunkRenderDispatcherAccessor.java +++ b/src/main/java/com/replaymod/render/mixin/ChunkRenderDispatcherAccessor.java @@ -1,4 +1,4 @@ -//#if MC>=10800 +//#if MC>=10800 && MC<11500 package com.replaymod.render.mixin; import net.minecraft.client.render.chunk.ChunkBatcher; diff --git a/src/main/java/com/replaymod/render/mixin/MixinCamera.java b/src/main/java/com/replaymod/render/mixin/MixinCamera.java index b66b7283..245d6441 100644 --- a/src/main/java/com/replaymod/render/mixin/MixinCamera.java +++ b/src/main/java/com/replaymod/render/mixin/MixinCamera.java @@ -1,12 +1,10 @@ package com.replaymod.render.mixin; import com.replaymod.render.RenderSettings; -import com.replaymod.render.capturer.CubicOpenGlFrameCapturer; import com.replaymod.render.hooks.EntityRendererHandler; import com.replaymod.replay.camera.CameraEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; -import org.lwjgl.opengl.GL11; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -134,51 +132,4 @@ public abstract class MixinCamera { } } } - - //#if MC>=11400 - @Inject(method = "update", at = @At("HEAD")) - //#else - //$$ @Inject(method = "orientCamera", at = @At("HEAD")) - //#endif - private void replayModRender_setupCubicFrameRotation( - //#if MC>=11400 - BlockView blockView, - Entity entity, - boolean thirdPerson, - boolean inverseView, - //#endif - float partialTicks, - CallbackInfo ci - ) { - if (getHandler() != null && getHandler().data instanceof CubicOpenGlFrameCapturer.Data) { - switch ((CubicOpenGlFrameCapturer.Data) getHandler().data) { - case FRONT: - GL11.glRotatef(0, 0.0F, 1.0F, 0.0F); - break; - case RIGHT: - GL11.glRotatef(90, 0.0F, 1.0F, 0.0F); - break; - case BACK: - GL11.glRotatef(180, 0.0F, 1.0F, 0.0F); - break; - case LEFT: - GL11.glRotatef(-90, 0.0F, 1.0F, 0.0F); - break; - case BOTTOM: - GL11.glRotatef(90, 1.0F, 0.0F, 0.0F); - break; - case TOP: - GL11.glRotatef(-90, 1.0F, 0.0F, 0.0F); - break; - } - } - if (getHandler() != null && getHandler().omnidirectional) { - // Minecraft goes back a little so we have to revert that - //#if MC>=11300 - GL11.glTranslatef(0.0F, 0.0F, -0.05F); - //#else - //$$ GL11.glTranslatef(0.0F, 0.0F, 0.1F); - //#endif - } - } } diff --git a/src/main/java/com/replaymod/render/mixin/MixinChunkRenderWorker.java b/src/main/java/com/replaymod/render/mixin/MixinChunkRenderWorker.java index c901d0d7..796a3c2c 100644 --- a/src/main/java/com/replaymod/render/mixin/MixinChunkRenderWorker.java +++ b/src/main/java/com/replaymod/render/mixin/MixinChunkRenderWorker.java @@ -1,6 +1,6 @@ package com.replaymod.render.mixin; -//#if MC>=10800 +//#if MC>=10800 && MC<11500 import com.replaymod.core.versions.MCVer; import net.minecraft.client.render.chunk.ChunkRenderTask; diff --git a/src/main/java/com/replaymod/render/mixin/MixinEntityRenderer.java b/src/main/java/com/replaymod/render/mixin/MixinEntityRenderer.java index 5ae72030..81898561 100644 --- a/src/main/java/com/replaymod/render/mixin/MixinEntityRenderer.java +++ b/src/main/java/com/replaymod/render/mixin/MixinEntityRenderer.java @@ -3,7 +3,6 @@ package com.replaymod.render.mixin; import com.replaymod.core.versions.MCVer; import com.replaymod.render.capturer.StereoscopicOpenGlFrameCapturer; import com.replaymod.render.hooks.EntityRendererHandler; -import de.johni0702.minecraft.gui.utils.lwjgl.ReadableColor; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.PlayerEntity; import org.lwjgl.opengl.GL11; @@ -14,6 +13,11 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//#if MC>=11500 +//$$ import net.minecraft.client.util.math.MatrixStack; +//$$ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +//#endif + //#if MC>=11400 import net.minecraft.client.render.Camera; import net.minecraft.util.hit.HitResult; @@ -93,6 +97,9 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti @Inject(method = "renderHand", at = @At("HEAD"), cancellable = true) private void replayModRender_renderSpectatorHand( + //#if MC>=11500 + //$$ MatrixStack matrixStack, + //#endif //#if MC>=11400 Camera camera, //#endif @@ -128,102 +135,27 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti //$$ public abstract void renderHand(float partialTicks, int renderPass); //#endif - //#if MC>=11400 - @Redirect(method = "renderCenter", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;drawHighlightedBlockOutline(Lnet/minecraft/client/render/Camera;Lnet/minecraft/util/hit/HitResult;I)V")) - private void replayModRender_drawSelectionBox(WorldRenderer instance, Camera camera, HitResult hitResult, int something) { - if (replayModRender_handler == null) { - instance.drawHighlightedBlockOutline(camera, hitResult, something); - } - } - //#else - //#if MC>=11300 - //$$ @Redirect(method = "updateCameraAndRender(FJ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/WorldRenderer;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/math/RayTraceResult;IF)V")) - //$$ private void replayModRender_drawSelectionBox(WorldRenderer instance, EntityPlayer player, RayTraceResult rtr, int alwaysZero, float partialTicks) { - //#else - //#if MC>=10904 - //$$ @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/math/RayTraceResult;IF)V")) - //$$ private void replayModRender_drawSelectionBox(RenderGlobal instance, EntityPlayer player, RayTraceResult rtr, int alwaysZero, float partialTicks) { - //#else - //#if MC>=10800 - //$$ @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")) - //#else - //$$ @Redirect(method = "renderWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;drawSelectionBox(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/util/MovingObjectPosition;IF)V")) - //#endif - //$$ private void replayModRender_drawSelectionBox(RenderGlobal instance, EntityPlayer player, MovingObjectPosition rtr, int alwaysZero, float partialTicks) { - //#endif - //#endif - //$$ if (replayModRender_handler == null) { - //$$ instance.drawSelectionBox(player, rtr, alwaysZero, partialTicks); - //$$ } - //$$ } - //#endif - - private int orgRenderDistanceChunks; - - //#if MC>=11300 - //#if MC>=11400 - @Inject(method = "renderCenter", at = @At(value = "JUMP", ordinal = 0)) - //#else - //$$ @Inject(method = "updateCameraAndRender(FJ)V", at = @At(value = "JUMP", ordinal = 0)) - //#endif - //#else - //#if MC>=10800 - //$$ @Inject(method = "renderWorldPass", at = @At(value = "JUMP", ordinal = 0)) - //#else - //$$ @Inject(method = "renderWorld", at = @At(value = "INVOKE", ordinal = 0, shift = At.Shift.AFTER, - //$$ target = "Lnet/minecraft/client/renderer/culling/ClippingHelperImpl;getInstance()Lnet/minecraft/client/renderer/culling/ClippingHelper;")) - //#endif - //#endif - private void replayModRender_beforeRenderSky(CallbackInfo ci) { - if (replayModRender_handler != null && replayModRender_handler.getSettings().getChromaKeyingColor() != null) { - GameOptions settings = MCVer.getMinecraft().options; - orgRenderDistanceChunks = settings.viewDistance; - settings.viewDistance = 5; // Set render distance to 5 so we're always rendering sky when chroma keying - } - } - - //#if MC>=11300 - //#if MC>=11400 - @Redirect(method = "renderCenter", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;renderSky(F)V")) - //#else - //$$ @Redirect(method = "updateCameraAndRender(FJ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/WorldRenderer;renderSky(F)V")) - //#endif - private void replayModRender_renderSky(WorldRenderer instance, float partialTicks) { - //#else - //#if MC>=10800 - //$$ @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;renderSky(FI)V")) - //$$ private void replayModRender_renderSky(RenderGlobal instance, float partialTicks, int renderPass) { - //#else - //$$ @Redirect(method = "renderWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;renderSky(F)V")) - //$$ private void replayModRender_renderSky(RenderGlobal instance, float partialTicks) { - //#endif - //#endif - if (replayModRender_handler != null && replayModRender_handler.getSettings().getChromaKeyingColor() != null) { - MCVer.getMinecraft().options.viewDistance = orgRenderDistanceChunks; - ReadableColor color = replayModRender_handler.getSettings().getChromaKeyingColor(); - GlStateManager.clearColor(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1); - GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT - //#if MC>=11400 - , false - //#endif - ); - } else { - //#if MC>=11300 - instance.renderSky(partialTicks); - //#else - //#if MC>=10800 - //$$ instance.renderSky(partialTicks, renderPass); - //#else - //$$ instance.renderSky(partialTicks); - //#endif - //#endif - } - } - /* * Stereoscopic Renderer */ + //#if MC>=11500 + //$$ @Inject(method = "method_22973", at = @At("RETURN"), cancellable = true) + //$$ private void replayModRender_setupStereoscopicProjection(CallbackInfoReturnable ci) { + //$$ if (replayModRender_getHandler() != null) { + //$$ Matrix4f offset; + //$$ if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) { + //$$ offset = Matrix4f.translate(0.07f, 0, 0); + //$$ } else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) { + //$$ offset = Matrix4f.translate(-0.07f, 0, 0); + //$$ } else { + //$$ return; + //$$ } + //$$ offset.multiply(ci.getReturnValue()); + //$$ ci.setReturnValue(offset); + //$$ } + //$$ } + //#else //#if MC>=10800 @Inject(method = "applyCameraTransformations", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;loadIdentity()V", shift = At.Shift.AFTER, ordinal = 0)) //#else @@ -244,7 +176,20 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti } } } + //#endif + //#if MC>=11500 + //$$ @Inject(method = "renderWorld", at = @At("HEAD")) + //$$ private void replayModRender_setupStereoscopicProjection(float partialTicks, long frameStartNano, MatrixStack matrixStack, CallbackInfo ci) { + //$$ if (replayModRender_getHandler() != null) { + //$$ if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) { + //$$ matrixStack.translate(0.1, 0, 0); + //$$ } else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) { + //$$ matrixStack.translate(-0.1, 0, 0); + //$$ } + //$$ } + //$$ } + //#else //#if MC>=10800 @Inject(method = "applyCameraTransformations", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;loadIdentity()V", shift = At.Shift.AFTER, ordinal = 1)) //#else @@ -265,6 +210,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti } } } + //#endif /* * Cubic Renderer @@ -276,6 +222,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti return replayModRender_perspective((float) fovY, aspect, zNear, zFar); } + //#if MC<11500 //#if MC>=11400 @Redirect(method = "renderCenter", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/Matrix4f;method_4929(DFFF)Lnet/minecraft/client/util/math/Matrix4f;")) //#else @@ -289,6 +236,7 @@ public abstract class MixinEntityRenderer implements EntityRendererHandler.IEnti private Matrix4f replayModRender_perspective$2(double fovY, float aspect, float zNear, float zFar) { return replayModRender_perspective((float) fovY, aspect, zNear, zFar); } + //#endif private Matrix4f replayModRender_perspective(float fovY, float aspect, float zNear, float zFar) { if (replayModRender_getHandler() != null && replayModRender_getHandler().omnidirectional) { diff --git a/src/main/java/com/replaymod/render/mixin/MixinFogRenderer.java b/src/main/java/com/replaymod/render/mixin/MixinFogRenderer.java index 2923d239..e5450e61 100644 --- a/src/main/java/com/replaymod/render/mixin/MixinFogRenderer.java +++ b/src/main/java/com/replaymod/render/mixin/MixinFogRenderer.java @@ -16,16 +16,11 @@ import net.minecraft.client.render.Camera; @Mixin(BackgroundRenderer.class) public abstract class MixinFogRenderer { @Inject(method = "applyFog", at = @At("HEAD"), cancellable = true) - private void replayModRender_onSetupFog( - //#if MC>=11400 - Camera camera, - int something, - //#else - //$$ int fogDistanceFlag, - //$$ float partialTicks, - //#endif - CallbackInfo ci - ) { + private + //#if MC>=11500 + //$$ static + //#endif + void replayModRender_onSetupFog(CallbackInfo ci) { EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().gameRenderer).replayModRender_getHandler(); if (handler == null) return; diff --git a/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java b/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java index 623159fa..1f4955f9 100644 --- a/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java +++ b/src/main/java/com/replaymod/render/mixin/MixinParticleManager.java @@ -1,6 +1,7 @@ package com.replaymod.render.mixin; -//#if MC>=10904 +// FIXME 1.15 seems like the way orientation is passed to particles has changed significantly +//#if MC>=10904 && MC<11500 import com.replaymod.core.versions.MCVer; import com.replaymod.render.blend.BlendState; import com.replaymod.render.blend.exporters.ParticlesExporter; diff --git a/src/main/java/com/replaymod/render/mixin/MixinRender.java b/src/main/java/com/replaymod/render/mixin/MixinRender.java index e0dffe1a..b2fbae6a 100644 --- a/src/main/java/com/replaymod/render/mixin/MixinRender.java +++ b/src/main/java/com/replaymod/render/mixin/MixinRender.java @@ -3,7 +3,6 @@ package com.replaymod.render.mixin; import com.replaymod.core.versions.MCVer; import com.replaymod.render.hooks.EntityRendererHandler; import net.minecraft.client.render.entity.EntityRenderer; -import net.minecraft.entity.Entity; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -11,12 +10,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EntityRenderer.class) public abstract class MixinRender { + //#if MC>=11500 + //$$ @Inject(method = "renderLabelIfPresent", at = @At("HEAD"), cancellable = true) + //#else //#if MC>=11400 @Inject(method = "renderLabel(Lnet/minecraft/entity/Entity;Ljava/lang/String;DDDI)V", at = @At("HEAD"), cancellable = true) //#else //$$ @Inject(method = "renderLivingLabel", at = @At("HEAD"), cancellable = true) //#endif - private void replayModRender_areAllNamesHidden(Entity entityIn, String str, double x, double y, double z, int maxDistance, CallbackInfo ci) { + //#endif + private void replayModRender_areAllNamesHidden(CallbackInfo ci) { EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) MCVer.getMinecraft().gameRenderer).replayModRender_getHandler(); if (handler != null && !handler.getSettings().isRenderNameTags()) { ci.cancel(); diff --git a/src/main/java/com/replaymod/render/mixin/MixinRenderGlobal.java b/src/main/java/com/replaymod/render/mixin/MixinRenderGlobal.java index 0add952a..921d1809 100644 --- a/src/main/java/com/replaymod/render/mixin/MixinRenderGlobal.java +++ b/src/main/java/com/replaymod/render/mixin/MixinRenderGlobal.java @@ -1,4 +1,4 @@ -//#if MC>=10800 +//#if MC>=10800 && MC<11500 package com.replaymod.render.mixin; import com.replaymod.render.hooks.ChunkLoadingRenderGlobal; diff --git a/src/main/java/com/replaymod/render/mixin/MixinRenderManager.java b/src/main/java/com/replaymod/render/mixin/MixinRenderManager.java index 0a3af042..e7619737 100644 --- a/src/main/java/com/replaymod/render/mixin/MixinRenderManager.java +++ b/src/main/java/com/replaymod/render/mixin/MixinRenderManager.java @@ -9,6 +9,13 @@ import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +//#if MC>=11500 +//$$ import net.minecraft.client.render.VertexConsumerProvider; +//$$ import net.minecraft.client.util.math.MatrixStack; +//$$ import net.minecraft.client.util.math.Vector3f; +//$$ import net.minecraft.util.math.Quaternion; +//#endif + //#if MC>=10904 import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //#else @@ -17,12 +24,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EntityRenderDispatcher.class) public abstract class MixinRenderManager { - @Shadow - private float cameraPitch; - - @Shadow - private float cameraYaw; + //#if MC>=11500 + //$$ @Shadow private Quaternion rotation; + //#else + @Shadow private float cameraPitch; + @Shadow private float cameraYaw; + //#endif + //#if MC>=11400 + //$$ @Inject(method = "render", at = @At("HEAD")) + //#else //#if MC>=11400 @Inject(method = "render(Lnet/minecraft/entity/Entity;DDDFFZ)V", at = @At("HEAD")) //#else @@ -32,8 +43,17 @@ public abstract class MixinRenderManager { //$$ @Inject(method = "doRenderEntity", at = @At("HEAD")) //#endif //#endif + //#endif //#if MC>=10904 - private void replayModRender_reorientForCubicRendering(Entity entity, double dx, double dy, double dz, float iDoNotKnow, float partialTicks, boolean iDoNotCare, CallbackInfo ci) { + private void replayModRender_reorientForCubicRendering(Entity entity, double dx, double dy, double dz, float iDoNotKnow, float partialTicks, + //#if MC>=11500 + //$$ MatrixStack matrixStack, + //$$ VertexConsumerProvider vertexConsumerProvider, + //$$ int int_1, + //#else + boolean iDoNotCare, + //#endif + CallbackInfo ci) { //#else //$$ private void replayModRender_reorientForCubicRendering(Entity entity, double dx, double dy, double dz, float iDoNotKnow, float partialTicks, boolean iDoNotCare, CallbackInfoReturnable ci) { //#endif @@ -41,8 +61,14 @@ public abstract class MixinRenderManager { if (handler != null && handler.omnidirectional) { double pitch = -Math.atan2(dy, Math.sqrt(dx * dx + dz * dz)); double yaw = -Math.atan2(dx, dz); + //#if MC>=11500 + //$$ this.rotation = new Quaternion(0.0F, 0.0F, 0.0F, 1.0F); + //$$ this.rotation.hamiltonProduct(Vector3f.POSITIVE_Y.getDegreesQuaternion((float) -yaw)); + //$$ this.rotation.hamiltonProduct(Vector3f.POSITIVE_X.getDegreesQuaternion((float) pitch)); + //#else this.cameraPitch = (float) Math.toDegrees(pitch); this.cameraYaw = (float) Math.toDegrees(yaw); + //#endif } } } diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyColorSky.java b/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyColorSky.java new file mode 100644 index 00000000..e25c2b62 --- /dev/null +++ b/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyColorSky.java @@ -0,0 +1,39 @@ +package com.replaymod.render.mixin; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.replaymod.render.hooks.EntityRendererHandler; +import de.johni0702.minecraft.gui.utils.lwjgl.ReadableColor; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.WorldRenderer; +import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * Instead of rendering the normal sky, clears the screen with a uniform color for use with chroma keying. + */ +@Mixin(WorldRenderer.class) +public abstract class Mixin_ChromaKeyColorSky { + @Shadow @Final private MinecraftClient client; + + @Inject(method = "renderSky", at = @At("HEAD"), cancellable = true) + private void chromaKeyingSky(CallbackInfo ci) { + EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) client.gameRenderer).replayModRender_getHandler(); + if (handler != null) { + ReadableColor color = handler.getSettings().getChromaKeyingColor(); + if (color != null) { + GlStateManager.clearColor(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1); + GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT + //#if MC>=11400 + , false + //#endif + ); + ci.cancel(); + } + } + } +} diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyForceSky.java b/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyForceSky.java new file mode 100644 index 00000000..877ca74e --- /dev/null +++ b/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyForceSky.java @@ -0,0 +1,45 @@ +package com.replaymod.render.mixin; + +import com.replaymod.render.hooks.EntityRendererHandler; +import de.johni0702.minecraft.gui.utils.lwjgl.ReadableColor; +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; + +//#if MC>=11500 +//$$ import net.minecraft.client.render.WorldRenderer; +//#else +import net.minecraft.client.render.GameRenderer; +//#endif + +/** + * Forces the sky to always render when chroma keying is active. Ordinarily it only renders when the render distance is + * at 4 or greater. + */ +//#if MC>=11500 +//$$ @Mixin(WorldRenderer.class) +//#else +@Mixin(GameRenderer.class) +//#endif +public abstract class Mixin_ChromaKeyForceSky { + @Shadow @Final private MinecraftClient client; + + //#if MC>=11500 + //$$ @ModifyConstant(method = "render", constant = @Constant(intValue = 4)) + //#else + @ModifyConstant(method = "renderCenter", constant = @Constant(intValue = 4)) + //#endif + private int forceSkyWhenChromaKeying(int value) { + EntityRendererHandler handler = ((EntityRendererHandler.IEntityRenderer) client.gameRenderer).replayModRender_getHandler(); + if (handler != null) { + ReadableColor color = handler.getSettings().getChromaKeyingColor(); + if (color != null) { + return 0; + } + } + return value; + } +} diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_CubicRotation.java b/src/main/java/com/replaymod/render/mixin/Mixin_CubicRotation.java new file mode 100644 index 00000000..6d69b662 --- /dev/null +++ b/src/main/java/com/replaymod/render/mixin/Mixin_CubicRotation.java @@ -0,0 +1,98 @@ +package com.replaymod.render.mixin; + +import com.replaymod.render.capturer.CubicOpenGlFrameCapturer; +import com.replaymod.render.hooks.EntityRendererHandler; +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.callback.CallbackInfo; + +//#if MC>=11500 +//$$ import net.minecraft.client.util.math.MatrixStack; +//$$ import net.minecraft.client.util.math.Vector3f; +//#else +import org.lwjgl.opengl.GL11; +//#endif + +import static com.replaymod.core.versions.MCVer.getMinecraft; + +//#if MC>=11500 +//$$ @Mixin(value = net.minecraft.client.render.GameRenderer.class) +//#else +//#if MC>=11400 +@Mixin(value = net.minecraft.client.render.Camera.class) +//#else +//$$ @Mixin(value = net.minecraft.client.renderer.EntityRenderer.class) +//#endif +//#endif +public abstract class Mixin_CubicRotation { + private EntityRendererHandler getHandler() { + return ((EntityRendererHandler.IEntityRenderer) getMinecraft().gameRenderer).replayModRender_getHandler(); + } + + //#if MC>=11500 + //$$ @Inject(method = "renderWorld", at = @At("HEAD")) + //#else + //#if MC>=11400 + @Inject(method = "update", at = @At("HEAD")) + //#else + //$$ @Inject(method = "orientCamera", at = @At("HEAD")) + //#endif + //#endif + private void replayModRender_setupCubicFrameRotation( + //#if MC>=11500 + //$$ float partialTicks, + //$$ long frameStartNano, + //$$ MatrixStack matrixStack, + //#endif + CallbackInfo ci + ) { + if (getHandler() != null && getHandler().data instanceof CubicOpenGlFrameCapturer.Data) { + CubicOpenGlFrameCapturer.Data data = (CubicOpenGlFrameCapturer.Data) getHandler().data; + float angle = 0; + float x = 0; + float y = 0; + switch (data) { + case FRONT: + angle = 0; + x = 1; + break; + case RIGHT: + angle = 90; + x = 1; + break; + case BACK: + angle = 180; + x = 1; + break; + case LEFT: + angle = -90; + x = 1; + break; + case TOP: + angle = -90; + y = 1; + break; + case BOTTOM: + angle = 90; + y = 1; + break; + } + //#if MC>=11400 + //$$ matrixStack.multiply(new Vector3f(x, y, 0).getDegreesQuaternion(angle)); + //#else + GL11.glRotatef(angle, x, y, 0); + //#endif + } + //#if MC<11500 + if (getHandler() != null && getHandler().omnidirectional) { + // Minecraft goes back a little so we have to revert that + //#if MC>=11300 + GL11.glTranslatef(0.0F, 0.0F, -0.05F); + //#else + //$$ GL11.glTranslatef(0.0F, 0.0F, 0.1F); + //#endif + } + //#endif + } +} diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_SkipBlockOutlinesDuringRender.java b/src/main/java/com/replaymod/render/mixin/Mixin_SkipBlockOutlinesDuringRender.java new file mode 100644 index 00000000..c86f6730 --- /dev/null +++ b/src/main/java/com/replaymod/render/mixin/Mixin_SkipBlockOutlinesDuringRender.java @@ -0,0 +1,23 @@ +package com.replaymod.render.mixin; + +import com.replaymod.render.hooks.EntityRendererHandler; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.render.WorldRenderer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(WorldRenderer.class) +public abstract class Mixin_SkipBlockOutlinesDuringRender { + @Shadow @Final private MinecraftClient client; + + @Inject(method = "drawHighlightedBlockOutline", at = @At("HEAD"), cancellable = true) + private void replayModRender_drawSelectionBox(CallbackInfo ci) { + if (((EntityRendererHandler.IEntityRenderer) client.gameRenderer).replayModRender_getHandler() != null) { + ci.cancel(); + } + } +} diff --git a/src/main/java/com/replaymod/render/mixin/WorldRendererAccessor.java b/src/main/java/com/replaymod/render/mixin/WorldRendererAccessor.java index 1a6f9b33..347363e6 100644 --- a/src/main/java/com/replaymod/render/mixin/WorldRendererAccessor.java +++ b/src/main/java/com/replaymod/render/mixin/WorldRendererAccessor.java @@ -13,6 +13,7 @@ import net.minecraft.client.render.chunk.ChunkRenderer; @Mixin(WorldRenderer.class) public interface WorldRendererAccessor { + //#if MC<11500 @Accessor("field_4076") void setRenderEntitiesStartupCounter(int value); @@ -26,4 +27,5 @@ public interface WorldRendererAccessor { @Accessor("chunkRenderers") Set getChunksToUpdate(); //#endif + //#endif } diff --git a/src/main/java/com/replaymod/render/rendering/Pipeline.java b/src/main/java/com/replaymod/render/rendering/Pipeline.java index 15cf72b7..6427d42f 100644 --- a/src/main/java/com/replaymod/render/rendering/Pipeline.java +++ b/src/main/java/com/replaymod/render/rendering/Pipeline.java @@ -18,6 +18,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import static com.replaymod.core.versions.MCVer.getWindow; + public class Pipeline implements Runnable { private final FrameCapturer capturer; @@ -58,9 +60,9 @@ public class Pipeline implements Runnable { MinecraftClient mc = MCVer.getMinecraft(); while (!capturer.isDone() && !Thread.currentThread().isInterrupted()) { //#if MC>=11300 - if (GLFW.glfwWindowShouldClose(mc.window.getHandle()) || ((MinecraftAccessor) mc).hasCrashed()) { + if (GLFW.glfwWindowShouldClose(getWindow(mc).getHandle()) || ((MinecraftAccessor) mc).getCrashReporter() != null) { //#else - //$$ if (Display.isCloseRequested() || ((MinecraftAccessor) mc).hasCrashed()) { + //$$ if (Display.isCloseRequested() || ((MinecraftAccessor) mc).getCrashReporter() != null) { //#endif Thread.currentThread().interrupt(); return; diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index aaf5623e..1afe2079 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -32,6 +32,12 @@ import net.minecraft.util.crash.CrashException; import net.minecraft.sound.SoundCategory; import net.minecraft.client.render.RenderTickCounter; +//#if MC>=11500 +//$$ import com.mojang.blaze3d.systems.RenderSystem; +//$$ import net.minecraft.client.util.Window; +//$$ import org.lwjgl.opengl.GL11; +//#endif + //#if MC>=11300 import com.replaymod.render.mixin.MainWindowAccessor; import org.lwjgl.glfw.GLFW; @@ -43,7 +49,9 @@ import org.lwjgl.glfw.GLFW; //#endif //#if MC>=10800 +//#if MC<11500 import com.replaymod.render.hooks.ChunkLoadingRenderGlobal; +//#endif import static com.mojang.blaze3d.platform.GlStateManager.*; //#else //$$ import com.replaymod.replay.gui.screen.GuiOpeningReplay; @@ -60,6 +68,7 @@ import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import static com.google.common.collect.Iterables.getLast; +import static com.replaymod.core.versions.MCVer.*; import static com.replaymod.render.ReplayModRender.LOGGER; import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT; import static org.lwjgl.opengl.GL11.GL_DEPTH_BUFFER_BIT; @@ -79,7 +88,7 @@ public class VideoRenderer implements RenderInfo { private TimelinePlayer timelinePlayer; private Future timelinePlayerFuture; - //#if MC>=10800 + //#if MC>=10800 && MC<11500 private ChunkLoadingRenderGlobal chunkLoadingRenderGlobal; //#endif //#if MC<10800 @@ -161,11 +170,13 @@ public class VideoRenderer implements RenderInfo { } } + //#if MC<11500 ((WorldRendererAccessor) mc.worldRenderer).setRenderEntitiesStartupCounter(0); + //#endif renderingPipeline.run(); - if (((MinecraftAccessor) mc).hasCrashed()) { + if (((MinecraftAccessor) mc).getCrashReporter() != null) { throw new CrashException(((MinecraftAccessor) mc).getCrashReporter()); } @@ -190,10 +201,10 @@ public class VideoRenderer implements RenderInfo { public float updateForNextFrame() { // because the jGui lib uses Minecraft's displayWidth and displayHeight values, update these temporarily //#if MC>=11300 - int displayWidthBefore = mc.window.getFramebufferWidth(); - int displayHeightBefore = mc.window.getFramebufferHeight(); + int displayWidthBefore = getWindow(mc).getFramebufferWidth(); + int displayHeightBefore = getWindow(mc).getFramebufferHeight(); //noinspection ConstantConditions - MainWindowAccessor acc = (MainWindowAccessor) (Object) mc.window; + MainWindowAccessor acc = (MainWindowAccessor) (Object) getWindow(mc); acc.setFramebufferWidth(displayWidth); acc.setFramebufferHeight(displayHeight); //#else @@ -248,13 +259,16 @@ public class VideoRenderer implements RenderInfo { timelinePlayer = new TimelinePlayer(replayHandler); timelinePlayerFuture = timelinePlayer.start(timeline); + // FBOs are always used in 1.14+ + //#if MC<11400 if (!GLX.isUsingFBOs()) { //#if MC>=11300 - GLFW.glfwSetWindowAttrib(mc.window.getHandle(), GLFW.GLFW_RESIZABLE, 1); + GLFW.glfwSetWindowAttrib(getWindow(mc).getHandle(), GLFW.GLFW_RESIZABLE, 1); //#else //$$ Display.setResizable(false); //#endif } + //#endif if (mc.options.debugEnabled) { debugInfoWasShown = true; mc.options.debugEnabled = false; @@ -304,7 +318,7 @@ public class VideoRenderer implements RenderInfo { //$$ gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight()); //#endif - //#if MC>=10800 + //#if MC>=10800 && MC<11500 chunkLoadingRenderGlobal = new ChunkLoadingRenderGlobal(mc.worldRenderer); //#endif @@ -323,13 +337,16 @@ public class VideoRenderer implements RenderInfo { // Tear down of the timeline player might only happen the next tick after it was cancelled timelinePlayer.onTick(); + // FBOs are always used in 1.14+ + //#if MC<11400 if (!GLX.isUsingFBOs()) { //#if MC>=11300 - GLFW.glfwSetWindowAttrib(mc.window.getHandle(), GLFW.GLFW_RESIZABLE, 0); + GLFW.glfwSetWindowAttrib(getWindow(mc).getHandle(), GLFW.GLFW_RESIZABLE, 0); //#else //$$ Display.setResizable(true); //#endif } + //#endif mc.options.debugEnabled = debugInfoWasShown; if (mouseWasGrabbed) { //#if MC>=11300 @@ -342,7 +359,7 @@ public class VideoRenderer implements RenderInfo { mc.options.setSoundVolume(entry.getKey(), entry.getValue()); } mc.openScreen(null); - //#if MC>=10800 + //#if MC>=10800 && MC<11500 if (chunkLoadingRenderGlobal != null) { chunkLoadingRenderGlobal.uninstall(); } @@ -366,7 +383,7 @@ public class VideoRenderer implements RenderInfo { //#endif ); //noinspection ConstantConditions - MainWindowAccessor acc = (MainWindowAccessor) (Object) mc.window; + MainWindowAccessor acc = (MainWindowAccessor) (Object) getWindow(mc); acc.setFramebufferWidth(displayWidth); acc.setFramebufferHeight(displayHeight); //#else @@ -411,7 +428,7 @@ public class VideoRenderer implements RenderInfo { if (!settings.isHighPerformance() && displaySizeChanged()) { updateDisplaySize(); //#if MC>=11300 - guiFramebuffer.resize(mc.window.getFramebufferWidth(), mc.window.getFramebufferHeight() + guiFramebuffer.resize(getWindow(mc).getFramebufferWidth(), getWindow(mc).getFramebufferHeight() //#if MC>=11400 , false //#endif @@ -430,8 +447,18 @@ public class VideoRenderer implements RenderInfo { enableTexture(); guiFramebuffer.beginWrite(true); + //#if MC>=11500 + //$$ Window window = getWindow(mc); + //$$ RenderSystem.clear(256, MinecraftClient.IS_SYSTEM_MAC); + //$$ RenderSystem.matrixMode(GL11.GL_PROJECTION); + //$$ RenderSystem.loadIdentity(); + //$$ RenderSystem.ortho(0, window.getFramebufferWidth() / window.getScaleFactor(), window.getFramebufferHeight() / window.getScaleFactor(), 0, 1000, 3000); + //$$ RenderSystem.matrixMode(GL11.GL_MODELVIEW); + //$$ RenderSystem.loadIdentity(); + //$$ RenderSystem.translatef(0, 0, -2000); + //#else //#if MC>=11300 - mc.window.method_4493( + getWindow(mc).method_4493( //#if MC>=11400 false //#endif @@ -439,9 +466,10 @@ public class VideoRenderer implements RenderInfo { //#else //$$ mc.entityRenderer.setupOverlayRendering(); //#endif + //#endif //#if MC>=11300 - gui.toMinecraft().init(mc, mc.window.getScaledWidth(), mc.window.getScaledHeight()); + gui.toMinecraft().init(mc, getWindow(mc).getScaledWidth(), getWindow(mc).getScaledHeight()); //#else //$$ ScaledResolution scaled = newScaledResolution(mc); //$$ gui.toMinecraft().setWorldAndResolution(mc, scaled.getScaledWidth(), scaled.getScaledHeight()); @@ -482,8 +510,11 @@ public class VideoRenderer implements RenderInfo { guiFramebuffer.draw(displayWidth, displayHeight); popMatrix(); + //#if MC>=11500 + //$$ getWindow(mc).swapBuffers(); + //#else //#if MC>=11300 - mc.window.setFullscreen(false); + getWindow(mc).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 @@ -497,6 +528,7 @@ public class VideoRenderer implements RenderInfo { //#endif //$$ } //#endif + //#endif //#if MC>=11300 if (mc.mouse.isCursorLocked()) { mc.mouse.unlockCursor(); @@ -519,7 +551,7 @@ public class VideoRenderer implements RenderInfo { private boolean displaySizeChanged() { //#if MC>=11300 - return displayWidth != mc.window.getWidth() || displayHeight != mc.window.getHeight(); + return displayWidth != getWindow(mc).getWidth() || displayHeight != getWindow(mc).getHeight(); //#else //$$ return displayWidth != Display.getWidth() || displayHeight != Display.getHeight(); //#endif @@ -527,8 +559,8 @@ public class VideoRenderer implements RenderInfo { private void updateDisplaySize() { //#if MC>=11300 - displayWidth = mc.window.getWidth(); - displayHeight = mc.window.getHeight(); + displayWidth = getWindow(mc).getWidth(); + displayHeight = getWindow(mc).getHeight(); //#else //$$ displayWidth = Display.getWidth(); //$$ displayHeight = Display.getHeight(); diff --git a/src/main/java/com/replaymod/replay/FullReplaySender.java b/src/main/java/com/replaymod/replay/FullReplaySender.java index 1b0cc471..fa84bd5f 100755 --- a/src/main/java/com/replaymod/replay/FullReplaySender.java +++ b/src/main/java/com/replaymod/replay/FullReplaySender.java @@ -1,5 +1,7 @@ package com.replaymod.replay; +import com.github.steveice10.packetlib.io.NetOutput; +import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; import com.google.common.base.Preconditions; import com.google.common.io.Files; import com.replaymod.core.ReplayMod; @@ -9,9 +11,6 @@ import com.replaymod.core.utils.Restrictions; import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replaystudio.io.ReplayInputStream; import com.replaymod.replaystudio.replay.ReplayFile; -import com.replaymod.replaystudio.studio.ReplayStudio; -import com.replaymod.replaystudio.studio.protocol.StudioCodec; -import com.replaymod.replaystudio.studio.protocol.StudioSession; import de.johni0702.minecraft.gui.utils.EventRegistrations; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -26,7 +25,6 @@ import net.minecraft.client.gui.screen.NoticeScreen; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.NetworkState; -import net.minecraft.network.ClientConnection; import net.minecraft.network.Packet; import net.minecraft.util.PacketByteBuf; import net.minecraft.client.network.packet.ChatMessageS2CPacket; @@ -586,12 +584,18 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend p = new GameJoinS2CPacket( entId, GameMode.SPECTATOR, + //#if MC>=11500 + //$$ packet.getSeed(), + //#endif false, packet.getDimension(), 0, // max players (has no getter -> never actually used) packet.getGeneratorType(), packet.getChunkLoadDistance(), packet.hasReducedDebugInfo() + //#if MC>=11500 + //$$ , packet.showsDeathScreen() + //#endif ); //#else //#if MC>=10800 @@ -630,7 +634,14 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend if(p instanceof PlayerRespawnS2CPacket) { PlayerRespawnS2CPacket respawn = (PlayerRespawnS2CPacket) p; //#if MC>=11400 - p = new PlayerRespawnS2CPacket(respawn.getDimension(), respawn.getGeneratorType(), GameMode.SPECTATOR); + p = new PlayerRespawnS2CPacket( + respawn.getDimension(), + //#if MC>=11500 + //$$ respawn.method_22425(), + //#endif + respawn.getGeneratorType(), + GameMode.SPECTATOR + ); //#else //#if MC>=10809 //$$ p = new SPacketRespawn(respawn.getDimensionID(), @@ -684,8 +695,8 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend //#endif if(cent != null) { - if(!allowMovement && !((Math.abs(cent.x - ppl.getX()) > TP_DISTANCE_LIMIT) || - (Math.abs(cent.z - ppl.getZ()) > TP_DISTANCE_LIMIT))) { + if(!allowMovement && !((Math.abs(Entity_getX(cent) - ppl.getX()) > TP_DISTANCE_LIMIT) || + (Math.abs(Entity_getZ(cent) - ppl.getZ()) > TP_DISTANCE_LIMIT))) { return null; } else { allowMovement = false; @@ -813,7 +824,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend while (!terminate) { synchronized (FullReplaySender.this) { if (replayIn == null) { - replayIn = replayFile.getPacketData(new ReplayStudio(), true); + replayIn = replayFile.getPacketData(getPacketTypeRegistry(true)); } // Packet loop while (true) { @@ -1010,7 +1021,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend } if (replayIn == null) { - replayIn = replayFile.getPacketData(new ReplayStudio(), true); + replayIn = replayFile.getPacketData(getPacketTypeRegistry(true)); } while (true) { // Send packets @@ -1153,8 +1164,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend private static final class PacketData { private static final com.github.steveice10.netty.buffer.ByteBuf byteBuf = com.github.steveice10.netty.buffer.Unpooled.buffer(); - private static final StudioCodec codecLoginPhase = new StudioCodec(new StudioSession(new ReplayStudio(), false, true)); - private static final StudioCodec codecPlayPhase = new StudioCodec(new StudioSession(new ReplayStudio(), false, false)); + private static final NetOutput netOutput = new ByteBufNetOutput(byteBuf); private final int timestamp; private final byte[] bytes; @@ -1175,25 +1185,25 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend throw new EOFException(); } timestamp = (int) data.getTime(); - // We need to re-encode MCProtocolLib packets, so we can later decode them as NMS packets + com.replaymod.replaystudio.protocol.Packet packet = data.getPacket(); + // We need to re-encode ReplayStudio packets, so we can later decode them as NMS packets // The main reason we aren't reading them as NMS packets is that we want ReplayStudio to be able // to apply ViaVersion (and potentially other magic) to it. synchronized (byteBuf) { byteBuf.markReaderIndex(); // Mark the current reader and writer index (should be at start) byteBuf.markWriterIndex(); - try { - (loginPhase ? codecLoginPhase : codecPlayPhase).encode(null, data.getPacket(), byteBuf); - } catch (Exception e) { - throw new IOException(e); - } - - bytes = new byte[byteBuf.readableBytes()]; // Create bytes array of sufficient size - byteBuf.readBytes(bytes); // Read all data into bytes + netOutput.writeVarInt(packet.getId()); + int idSize = byteBuf.readableBytes(); + int contentSize = packet.getBuf().readableBytes(); + bytes = new byte[idSize + contentSize]; // Create bytes array of sufficient size + byteBuf.readBytes(bytes, 0, idSize); + packet.getBuf().readBytes(bytes, idSize, contentSize); byteBuf.resetReaderIndex(); // Reset reader & writer index for next use byteBuf.resetWriterIndex(); } + packet.getBuf().release(); } } } diff --git a/src/main/java/com/replaymod/replay/NoGuiScreenshot.java b/src/main/java/com/replaymod/replay/NoGuiScreenshot.java index 630f4bae..d32c9b9d 100644 --- a/src/main/java/com/replaymod/replay/NoGuiScreenshot.java +++ b/src/main/java/com/replaymod/replay/NoGuiScreenshot.java @@ -12,6 +12,14 @@ import net.minecraft.client.MinecraftClient; import com.mojang.blaze3d.platform.GlStateManager; import net.minecraft.client.util.ScreenshotUtils; +//#if MC>=11500 +//$$ import net.minecraft.client.util.math.MatrixStack; +//#endif + +//#if MC>=11300 +import static com.replaymod.core.versions.MCVer.getWindow; +//#endif + //#if MC<11300 //$$ import com.google.common.io.Files; //$$ import org.apache.commons.io.FileUtils; @@ -35,7 +43,7 @@ public class NoGuiScreenshot { } //#if MC>=11300 - int frameWidth = mc.window.getFramebufferWidth(), frameHeight = mc.window.getFramebufferHeight(); + int frameWidth = getWindow(mc).getFramebufferWidth(), frameHeight = getWindow(mc).getFramebufferHeight(); //#else //$$ int frameWidth = mc.displayWidth, frameHeight = mc.displayHeight; //#endif @@ -56,7 +64,13 @@ public class NoGuiScreenshot { GlStateManager.enableTexture(); //#if MC>=11300 - mc.gameRenderer.renderWorld(MCVer.getRenderPartialTicks(), System.nanoTime()); + mc.gameRenderer.renderWorld( + MCVer.getRenderPartialTicks(), + System.nanoTime() + //#if MC>=11500 + //$$ , new MatrixStack() + //#endif + ); //#else //#if MC>=10809 //$$ mc.entityRenderer.updateCameraAndRender(MCVer.getRenderPartialTicks(), System.nanoTime()); diff --git a/src/main/java/com/replaymod/replay/QuickReplaySender.java b/src/main/java/com/replaymod/replay/QuickReplaySender.java index 1ea76a2b..1d30fcf8 100644 --- a/src/main/java/com/replaymod/replay/QuickReplaySender.java +++ b/src/main/java/com/replaymod/replay/QuickReplaySender.java @@ -1,64 +1,25 @@ //#if MC>=10904 package com.replaymod.replay; -import com.github.steveice10.mc.protocol.data.game.PlayerListEntry; -import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction; -import com.github.steveice10.mc.protocol.data.game.chunk.BlockStorage; -import com.github.steveice10.mc.protocol.data.game.chunk.Column; -import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; -import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; -import com.github.steveice10.mc.protocol.data.game.world.WorldType; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockChangeRecord; -import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; -import com.github.steveice10.mc.protocol.data.game.world.notify.ClientNotification; -import com.github.steveice10.mc.protocol.packet.ingame.server.ServerPlayerListEntryPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityDestroyPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityHeadLookPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.ServerEntityTeleportPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnMobPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnObjectPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPaintingPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.ServerSpawnPlayerPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerBlockChangePacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerChunkDataPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerMultiBlockChangePacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerNotifyClientPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUnloadChunkPacket; -import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTimePacket; -import com.github.steveice10.mc.protocol.util.NetUtil; import com.github.steveice10.packetlib.io.NetInput; -import com.github.steveice10.packetlib.io.NetOutput; -import com.github.steveice10.packetlib.io.stream.StreamNetInput; -import com.github.steveice10.packetlib.io.stream.StreamNetOutput; import com.github.steveice10.packetlib.tcp.io.ByteBufNetInput; -import com.github.steveice10.packetlib.tcp.io.ByteBufNetOutput; -import com.google.common.base.Optional; -import com.google.common.collect.ListMultimap; -import com.google.common.collect.Multimaps; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.SettableFuture; import com.replaymod.core.mixin.MinecraftAccessor; import com.replaymod.core.mixin.TimerAccessor; -import com.replaymod.core.utils.Utils; -import com.replaymod.replaystudio.PacketData; -import com.replaymod.replaystudio.io.ReplayInputStream; -import com.replaymod.replaystudio.io.ReplayOutputStream; import com.replaymod.replaystudio.replay.ReplayFile; -import com.replaymod.replaystudio.studio.ReplayStudio; -import com.replaymod.replaystudio.util.Location; -import com.replaymod.replaystudio.util.PacketUtils; +import com.replaymod.replaystudio.util.RandomAccessReplay; import de.johni0702.minecraft.gui.utils.EventRegistrations; import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.packet.PlayerPositionLookS2CPacket; +import net.minecraft.client.network.packet.PlayerRespawnS2CPacket; import net.minecraft.network.NetworkState; import net.minecraft.network.NetworkSide; import net.minecraft.network.Packet; @@ -79,31 +40,19 @@ import de.johni0702.minecraft.gui.versions.callbacks.PreTickCallback; //#endif import javax.annotation.Nullable; -import java.io.EOFException; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.NavigableMap; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.UUID; import java.util.function.Consumer; -import java.util.zip.Deflater; -import java.util.zip.Inflater; //#if MC>=11200 import com.replaymod.core.utils.WrappedTimer; +import net.minecraft.world.GameMode; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.level.LevelGeneratorType; //#endif import static com.replaymod.core.versions.MCVer.getMinecraft; +import static com.replaymod.core.versions.MCVer.getPacketTypeRegistry; import static com.replaymod.replay.ReplayModReplay.LOGGER; /** @@ -114,14 +63,10 @@ import static com.replaymod.replay.ReplayModReplay.LOGGER; */ @ChannelHandler.Sharable public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySender { - private static final String CACHE_ENTRY = "quickModeCache.bin"; - private static final String CACHE_INDEX_ENTRY = "quickModeCacheIndex.bin"; - private static final int CACHE_VERSION = 0; - private final MinecraftClient mc = getMinecraft(); private final ReplayModReplay mod; - private final ReplayFile replayFile; + private final RandomAccessReplay> replay; private final EventHandler eventHandler = new EventHandler(); private ChannelHandlerContext ctx; @@ -139,17 +84,43 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe private com.github.steveice10.netty.buffer.ByteBuf buf; private NetInput bufInput; - private TreeMap> thingSpawnsT = new TreeMap<>(); - private ListMultimap thingSpawns = Multimaps.newListMultimap(thingSpawnsT, ArrayList::new); - private TreeMap> thingDespawnsT = new TreeMap<>(); - private ListMultimap thingDespawns = Multimaps.newListMultimap(thingDespawnsT, ArrayList::new); - private List activeThings = new LinkedList<>(); - private TreeMap> worldTimes = new TreeMap<>(); - private TreeMap> thunderStrengths = new TreeMap<>(); // For some reason, this isn't tied to Weather public QuickReplaySender(ReplayModReplay mod, ReplayFile replayFile) { this.mod = mod; - this.replayFile = replayFile; + this.replay = new RandomAccessReplay>(replayFile, getPacketTypeRegistry(false)) { + private byte[] buf = new byte[0]; + + @Override + protected Packet decode(com.github.steveice10.netty.buffer.ByteBuf byteBuf) throws IOException { + int packetId = new ByteBufNetInput(byteBuf).readVarInt(); + //#if MC>=11500 + //$$ Packet mcPacket = NetworkState.PLAY.getPacketHandler(NetworkSide.CLIENTBOUND, packetId); + //#else + Packet mcPacket; + try { + mcPacket = NetworkState.field_11690.getPacketHandler(NetworkSide.CLIENTBOUND, packetId); + } catch (IllegalAccessException | InstantiationException e) { + throw new IOException(e); + } + //#endif + if (mcPacket != null) { + int size = byteBuf.readableBytes(); + if (buf.length < size) { + buf = new byte[size]; + } + byteBuf.readBytes(buf, 0, size); + ByteBuf wrappedBuf = Unpooled.wrappedBuffer(buf); + wrappedBuf.writerIndex(size); + mcPacket.read(new PacketByteBuf(wrappedBuf)); + } + return mcPacket; + } + + @Override + protected void dispatch(Packet packet) { + ctx.fireChannelRead(packet); + } + }; } public void register() { @@ -178,11 +149,7 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe new Thread(() -> { try { long start = System.currentTimeMillis(); - if (!tryLoadFromCache(progress)) { - double progressSplit = 0.9; // 90% of progress time for analysing, 10% for loading - analyseReplay(replayFile, d -> progress.accept(d * progressSplit)); - tryLoadFromCache(d -> progress.accept(d * (1 - progressSplit) + progressSplit)); - } + replay.load(progress); LOGGER.info("Initialized quick replay sender in " + (System.currentTimeMillis() - start) + "ms"); } catch (Throwable e) { LOGGER.error("Initializing quick replay sender:", e); @@ -216,17 +183,19 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe } public void restart() { - activeThings.clear(); - currentTimeStamp = 0; - ctx.fireChannelRead(toMC(new ServerRespawnPacket( - 0, + replay.reset(); + ctx.fireChannelRead(new PlayerRespawnS2CPacket( + DimensionType.OVERWORLD, + //#if MC>=11500 + //$$ 0, + //#endif //#if MC<11400 //$$ Difficulty.NORMAL, //#endif - GameMode.SPECTATOR, - WorldType.DEFAULT - ))); - ctx.fireChannelRead(toMC(new ServerPlayerPositionRotationPacket(0, 0, 0, 0, 0, 0))); + LevelGeneratorType.DEFAULT, + GameMode.SPECTATOR + )); + ctx.fireChannelRead(new PlayerPositionLookS2CPacket(0, 0, 0, 0, 0, Collections.emptySet(), 0)); } @Override @@ -301,870 +270,16 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe } } - private boolean tryLoadFromCache(Consumer progress) throws IOException { - boolean success = false; - - Optional cacheIndexOpt = replayFile.getCache(CACHE_INDEX_ENTRY); - if (!cacheIndexOpt.isPresent()) return false; - try (InputStream indexIn = cacheIndexOpt.get()) { - Optional cacheOpt = replayFile.getCache(CACHE_ENTRY); - if (!cacheOpt.isPresent()) return false; - try (InputStream cacheIn = cacheOpt.get()) { - success = loadFromCache(cacheIn, indexIn, progress); - } - } catch (EOFException e) { - LOGGER.error("Re-analysing replay due to premature EOF while loading the cache:", e); - } finally { - if (!success) { - buf = null; - bufInput = null; - thingSpawnsT.clear(); - thingDespawnsT.clear(); - worldTimes.clear(); - thunderStrengths.clear(); - } - } - - return success; - } - - private boolean loadFromCache(InputStream cacheIn, InputStream rawIndexIn, Consumer progress) throws IOException { - long sysTimeStart = System.currentTimeMillis(); - - NetInput in = new StreamNetInput(rawIndexIn); - if (in.readVarInt() != CACHE_VERSION) return false; // Incompatible cache version - if (new StreamNetInput(cacheIn).readVarInt() != CACHE_VERSION) return false; // Incompatible cache version - - things: while (true) { - BakedTrackedThing trackedThing; - switch (in.readVarInt()) { - case 0: break things; - case 1: trackedThing = new BakedEntity(in); break; - case 2: trackedThing = new BakedChunk(in); break; - case 3: trackedThing = new BakedWeather(in); break; - default: return false; - } - thingSpawns.put(trackedThing.spawnTime, trackedThing); - thingDespawns.put(trackedThing.despawnTime, trackedThing); - } - - readFromCache(in, worldTimes); - readFromCache(in, thunderStrengths); - int size = in.readVarInt(); - - LOGGER.info("Creating quick mode buffer of size: {}KB", size / 1024); - buf = com.github.steveice10.netty.buffer.Unpooled.buffer(size); - int read = 0; - while (true) { - int len = buf.writeBytes(cacheIn, Math.min(size - read, 4096)); - if (len <= 0) break; - read += len; - progress.accept((double) read / size); - } - bufInput = new ByteBufNetInput(buf); - - LOGGER.info("Loaded quick replay from cache in " + (System.currentTimeMillis() - sysTimeStart) + "ms"); - return true; - } - - private static void analyseReplay(ReplayFile replayFile, Consumer progress) throws IOException { - ReplayStudio studio = new ReplayStudio(); - PacketUtils.registerAllMovementRelated(studio); - studio.setParsing(ServerSpawnMobPacket.class, true); - studio.setParsing(ServerSpawnObjectPacket.class, true); - studio.setParsing(ServerSpawnPaintingPacket.class, true); - studio.setParsing(ServerSpawnPlayerPacket.class, true); - studio.setParsing(ServerEntityDestroyPacket.class, true); - studio.setParsing(ServerChunkDataPacket.class, true); - studio.setParsing(ServerUnloadChunkPacket.class, true); - studio.setParsing(ServerBlockChangePacket.class, true); - studio.setParsing(ServerMultiBlockChangePacket.class, true); - studio.setParsing(ServerPlayerListEntryPacket.class, true); - studio.setParsing(ServerUpdateTimePacket.class, true); - studio.setParsing(ServerNotifyClientPacket.class, true); - - TreeMap worldTimes = new TreeMap<>(); - TreeMap thunderStrengths = new TreeMap<>(); - Map playerListEntries = new HashMap<>(); - Map activeEntities = new HashMap<>(); - Map activeChunks = new HashMap<>(); - Weather activeWeather = null; - - double sysTimeStart = System.currentTimeMillis(); - double duration; - try (ReplayInputStream in = replayFile.getPacketData(studio, false); - OutputStream cacheOut = replayFile.writeCache(CACHE_ENTRY); - OutputStream cacheIndexOut = replayFile.writeCache(CACHE_INDEX_ENTRY)) { - NetOutput out = new StreamNetOutput(cacheOut); - out.writeVarInt(CACHE_VERSION); - NetOutput indexOut = new StreamNetOutput(cacheIndexOut); - indexOut.writeVarInt(CACHE_VERSION); - - int index = 0; - int time = 0; - duration = replayFile.getMetaData().getDuration(); - PacketData packetData; - while ((packetData = in.readPacket()) != null) { - com.github.steveice10.packetlib.packet.Packet packet = packetData.getPacket(); - time = (int) packetData.getTime(); - progress.accept(time / duration); - Integer entityId = PacketUtils.getEntityId(packet); - if (packet instanceof ServerSpawnMobPacket - || packet instanceof ServerSpawnObjectPacket - || packet instanceof ServerSpawnPaintingPacket) { - Entity entity = new Entity(entityId, Collections.singletonList(packet)); - entity.spawnTime = time; - Entity prev = activeEntities.put(entityId, entity); - if (prev != null) { - index = prev.writeToCache(indexOut, out, time, index); - } - } else if (packet instanceof ServerSpawnPlayerPacket) { - ServerPlayerListEntryPacket listEntryPacket = new ServerPlayerListEntryPacket( - PlayerListEntryAction.ADD_PLAYER, - new PlayerListEntry[]{ - playerListEntries.get(((ServerSpawnPlayerPacket) packet).getUUID()) - } - ); - Entity entity = new Entity(entityId, Arrays.asList(listEntryPacket, packet)); - entity.spawnTime = time; - Entity prev = activeEntities.put(entityId, entity); - if (prev != null) { - index = prev.writeToCache(indexOut, out, time, index); - } - } else if (packet instanceof ServerEntityDestroyPacket) { - for (int id : ((ServerEntityDestroyPacket) packet).getEntityIds()) { - Entity entity = activeEntities.remove(id); - if (entity != null) { - index = entity.writeToCache(indexOut, out, time, index); - } - } - } else if (packet instanceof ServerChunkDataPacket) { - Column column = ((ServerChunkDataPacket) packet).getColumn(); - if (column.hasBiomeData()) { - Chunk chunk = new Chunk(column); - chunk.spawnTime = time; - Chunk prev = activeChunks.put(coordToLong(column.getX(), column.getZ()), chunk); - if (prev != null) { - index = prev.writeToCache(indexOut, out, time, index); - } - } else { - Chunk chunk = activeChunks.get(coordToLong(column.getX(), column.getZ())); - if (chunk != null) { - int sectionY = 0; - for (com.github.steveice10.mc.protocol.data.game.chunk.Chunk section : column.getChunks()) { - if (section == null) { - sectionY++; - continue; - } - BlockStorage toBlocks = section.getBlocks(); - BlockStorage fromBlocks = chunk.currentBlockState[sectionY]; - for (int y = 0; y < 16; y++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - BlockState fromState = fromBlocks.get(x, y, z); - BlockState toState = toBlocks.get(x, y, z); - if (!fromState.equals(toState)) { - Position pos = new Position(column.getX() << 4 | x, sectionY << 4 | y, column.getZ() << 4 | z); - chunk.blocks.put(time, new BlockChange(pos, fromState, toState)); - } - } - } - } - chunk.currentBlockState[sectionY] = toBlocks; - sectionY++; - } - } - } - } else if (packet instanceof ServerUnloadChunkPacket) { - ServerUnloadChunkPacket p = (ServerUnloadChunkPacket) packet; - Chunk prev = activeChunks.remove(coordToLong(p.getX(), p.getZ())); - if (prev != null) { - index = prev.writeToCache(indexOut, out, time, index); - } - } else if (packet instanceof ServerBlockChangePacket || packet instanceof ServerMultiBlockChangePacket) { - for (BlockChangeRecord record : - packet instanceof ServerBlockChangePacket - ? new BlockChangeRecord[]{ ((ServerBlockChangePacket) packet).getRecord() } - : ((ServerMultiBlockChangePacket) packet).getRecords()) { - Position pos = record.getPosition(); - Chunk chunk = activeChunks.get(coordToLong(pos.getX() >> 4, pos.getZ() >> 4)); - if (chunk != null) { - BlockStorage blockStorage = chunk.currentBlockState[pos.getY() >> 4]; - int x = pos.getX() & 15, y = pos.getY() & 15, z = pos.getZ() & 15; - BlockState prevState = blockStorage.get(x, y, z); - BlockState newState = record.getBlock(); - blockStorage.set(x, y, z, newState); - chunk.blocks.put(time, new BlockChange(pos, prevState, newState)); - } - } - } else if (packet instanceof ServerPlayerListEntryPacket) { - ServerPlayerListEntryPacket p = (ServerPlayerListEntryPacket) packet; - if (p.getAction() == PlayerListEntryAction.ADD_PLAYER) { - for (PlayerListEntry entry : p.getEntries()) { - playerListEntries.put(entry.getProfile().getId(), entry); - } - } - } else if (packet instanceof ServerRespawnPacket) { - for (Entity entity : activeEntities.values()) { - index = entity.writeToCache(indexOut, out, time, index); - } - activeEntities.clear(); - for (Chunk chunk : activeChunks.values()) { - index = chunk.writeToCache(indexOut, out, time, index); - } - activeChunks.clear(); - if (activeWeather != null) { - index = activeWeather.writeToCache(indexOut, out, time, index); - } - activeWeather = null; - } else if (packet instanceof ServerUpdateTimePacket) { - worldTimes.put(time, packet); - } else if (packet instanceof ServerNotifyClientPacket) { - ServerNotifyClientPacket p = (ServerNotifyClientPacket) packet; - switch (p.getNotification()) { - case START_RAIN: - if (activeWeather != null) { - index = activeWeather.writeToCache(indexOut, out, time, index); - } - activeWeather = new Weather(); - activeWeather.spawnTime = time; - break; - case STOP_RAIN: - if (activeWeather != null) { - index = activeWeather.writeToCache(indexOut, out, time, index); - activeWeather = null; - } - break; - case RAIN_STRENGTH: - if (activeWeather != null) { - activeWeather.rainStrengths.put(time, packet); - } - break; - case THUNDER_STRENGTH: - thunderStrengths.put(time, packet); - break; - default: break; - } - } - if (entityId != null) { - Entity entity = activeEntities.get(entityId); - if (entity != null) { - Location current = entity.locations.isEmpty() ? null : entity.locations.lastEntry().getValue(); - Location updated = PacketUtils.updateLocation(current, packet); - if (updated != null) { - entity.locations.put(time, updated); - } - } - } - } - - for (Entity entity : activeEntities.values()) { - index = entity.writeToCache(indexOut, out, time, index); - } - for (Chunk chunk : activeChunks.values()) { - index = chunk.writeToCache(indexOut, out, time, index); - } - if (activeWeather != null) { - index = activeWeather.writeToCache(indexOut, out, time, index); - } - - indexOut.writeByte(0); - writeToCache(indexOut, worldTimes); - writeToCache(indexOut, thunderStrengths); - - indexOut.writeVarInt(index); - } - LOGGER.info("Analysed replay in " + (System.currentTimeMillis() - sysTimeStart) + "ms"); - } - @Override public void sendPacketsTill(int replayTime) { ensureInitialized(() -> { - if (replayTime > currentTimeStamp) { - activeThings.removeIf(thing -> { - if (thing.despawnTime <= replayTime) { - try { - thing.despawn(this, ctx::fireChannelRead); - } catch (IOException e) { - throw new RuntimeException(e); - } - return true; - } else { - return false; - } - }); - thingSpawnsT.subMap(currentTimeStamp, false, replayTime, true).values() - .forEach(things -> things.forEach(thing -> { - if (thing.despawnTime > replayTime) { - try { - thing.spawn(this, ctx::fireChannelRead); - } catch (IOException e) { - throw new RuntimeException(e); - } - activeThings.add(thing); - } - })); - activeThings.forEach(thing -> thing.play(currentTimeStamp, replayTime, ctx::fireChannelRead)); - playMap(worldTimes, currentTimeStamp, replayTime, ctx::fireChannelRead); - playMap(thunderStrengths, currentTimeStamp, replayTime, ctx::fireChannelRead); - } else { - activeThings.removeIf(thing -> { - if (thing.spawnTime > replayTime) { - try { - thing.despawn(this, ctx::fireChannelRead); - } catch (IOException e) { - throw new RuntimeException(e); - } - return true; - } else { - return false; - } - }); - thingDespawnsT.subMap(replayTime, false, currentTimeStamp, true).values() - .forEach(things -> things.forEach(thing -> { - if (thing.spawnTime <= replayTime) { - try { - thing.spawn(this, ctx::fireChannelRead); - } catch (IOException e) { - throw new RuntimeException(e); - } - activeThings.add(thing); - } - })); - activeThings.forEach(thing -> thing.rewind(currentTimeStamp, replayTime, ctx::fireChannelRead)); - rewindMap(worldTimes, currentTimeStamp, replayTime, ctx::fireChannelRead); - rewindMap(thunderStrengths, currentTimeStamp, replayTime, ctx::fireChannelRead); + try { + replay.seek(replayTime); + } catch (IOException e) { + e.printStackTrace(); } currentTimeStamp = replayTime; }); } - - private static final com.github.steveice10.netty.buffer.ByteBuf mcplByteBuf = com.github.steveice10.netty.buffer.Unpooled.buffer(); - private static final ByteBufNetInput byteBufNetInput = new ByteBufNetInput(mcplByteBuf); - private static final ByteBufNetOutput byteBufNetOutput = new ByteBufNetOutput(mcplByteBuf); - - private static BlockStorage copy(BlockStorage of) { - int readerIndex = byteBuf.readerIndex(); // Mark the current reader and writer index (should be at start) - int writerIndex = byteBuf.writerIndex(); - try { - of.write(byteBufNetOutput); - return new BlockStorage(byteBufNetInput); - } catch (Exception e) { - Utils.throwIfUnchecked(e); - throw new RuntimeException(e); - } finally { - byteBuf.readerIndex(readerIndex); // Reset reader & writer index for next use - byteBuf.writerIndex(writerIndex); - } - } - - private static final ByteBuf byteBuf = Unpooled.buffer(); - private static final ByteBufOutputStream byteBufOut = new ByteBufOutputStream(byteBuf); - private static final PacketByteBuf packetBuf = new PacketByteBuf(byteBuf); - private static final ReplayOutputStream encoder = new ReplayOutputStream(new ReplayStudio(), byteBufOut); - private static final Inflater inflater = new Inflater(); - private static final Deflater deflater = new Deflater(); - - private static Packet toMC(com.github.steveice10.packetlib.packet.Packet packet) { - return toMC(packet, NetworkState.field_11690); - } - - private static Packet toMC(com.github.steveice10.packetlib.packet.Packet packet, NetworkState state) { - // We need to re-encode MCProtocolLib packets, so we can then decode them as NMS packets - // The main reason we aren't reading them as NMS packets is that we want ReplayStudio to be able - // to apply ViaVersion (and potentially other magic) to it. - synchronized (encoder) { - int readerIndex = byteBuf.readerIndex(); // Mark the current reader and writer index (should be at start) - int writerIndex = byteBuf.writerIndex(); - try { - encoder.write(0, packet); // Re-encode packet, data will end up in byteBuf - encoder.flush(); - - byteBuf.skipBytes(8); // Skip packet length & timestamp - - int packetId = packetBuf.readVarInt(); - Packet mcPacket = state.getPacketHandler(NetworkSide.CLIENTBOUND, packetId); - mcPacket.read(packetBuf); - return mcPacket; - } catch (Exception e) { - Utils.throwIfUnchecked(e); - throw new RuntimeException(e); - } finally { - byteBuf.readerIndex(readerIndex); // Reset reader & writer index for next use - byteBuf.writerIndex(writerIndex); - } - } - } - - private static Packet readPacketFromCache(NetInput in) throws IOException { - int readerIndex = byteBuf.readerIndex(); // Mark the current reader and writer index (should be at start) - int writerIndex = byteBuf.writerIndex(); - try { - int prefix = in.readVarInt(); - int len = prefix >> 1; - if ((prefix & 1) == 1) { - int fullLen = in.readVarInt(); - byteBuf.writeBytes(in.readBytes(len)); - byteBuf.capacity(byteBuf.writerIndex() + fullLen); - - inflater.setInput(byteBuf.array(), byteBuf.arrayOffset() + byteBuf.readerIndex(), len); - inflater.inflate(byteBuf.array(), byteBuf.arrayOffset() + byteBuf.writerIndex(), fullLen); - - byteBuf.readerIndex(byteBuf.readerIndex() + len); - byteBuf.writerIndex(byteBuf.writerIndex() + fullLen); - } else { - byteBuf.writeBytes(in.readBytes(len)); - } - - int packetId = packetBuf.readVarInt(); - Packet mcPacket = NetworkState.field_11690.getPacketHandler(NetworkSide.CLIENTBOUND, packetId); - mcPacket.read(packetBuf); - return mcPacket; - } catch (Exception e) { - Utils.throwIfInstanceOf(e, IOException.class); - Utils.throwIfUnchecked(e); - throw new RuntimeException(e); - } finally { - byteBuf.readerIndex(readerIndex); // Reset reader & writer index for next use - byteBuf.writerIndex(writerIndex); - inflater.reset(); - } - } - - private static List> readPacketsFromCache(NetInput in) throws IOException { - int size = in.readVarInt(); - List> packets = new ArrayList<>(size); - for (int i = 0; i < size; i++) { - packets.add(readPacketFromCache(in)); - } - return packets; - } - - private static void readFromCache(NetInput in, SortedMap> packets) throws IOException { - int time = 0; - for (int i = in.readVarInt(); i > 0; i--) { - time += in.readVarInt(); - packets.put(time, readPacketFromCache(in)); - } - } - - private static int writeToCache(NetOutput out, com.github.steveice10.packetlib.packet.Packet packet) throws IOException { - int readerIndex = byteBuf.readerIndex(); // Mark the current reader and writer index (should be at start) - int writerIndex = byteBuf.writerIndex(); - try { - encoder.write(0, packet); // Re-encode packet, data will end up in byteBuf - encoder.flush(); - - byteBuf.skipBytes(8); // Skip packet length & timestamp - - int rawIndex = byteBuf.readerIndex(); - int size = byteBuf.readableBytes(); - - byteBuf.ensureWritable(size); - deflater.setInput(byteBuf.array(), byteBuf.arrayOffset() + byteBuf.readerIndex(), size); - deflater.finish(); - int compressedSize = 0; - while (!deflater.finished() && compressedSize < size) { - compressedSize += deflater.deflate( - byteBuf.array(), - byteBuf.arrayOffset() + byteBuf.writerIndex() + compressedSize, - size - compressedSize - ); - } - - int len = 0; - if (compressedSize < size) { - byteBuf.readerIndex(rawIndex + size); - byteBuf.writerIndex(rawIndex + size + compressedSize); - len += writeVarInt(out, compressedSize << 1 | 1); - len += writeVarInt(out, size); - } else { - byteBuf.readerIndex(rawIndex); - byteBuf.writerIndex(rawIndex + size); - len += writeVarInt(out, size << 1); - } - while (byteBuf.isReadable()) { - out.writeByte(byteBuf.readByte()); - len += 1; - } - return len; - } catch (Exception e) { - Utils.throwIfInstanceOf(e, IOException.class); - Utils.throwIfUnchecked(e); - throw new RuntimeException(e); - } finally { - byteBuf.readerIndex(readerIndex); // Reset reader & writer index for next use - byteBuf.writerIndex(writerIndex); - deflater.reset(); - } - } - - private static int writeToCache(NetOutput out, Collection packets) throws IOException { - int len = writeVarInt(out, packets.size()); - for (com.github.steveice10.packetlib.packet.Packet packet : packets) { - len += writeToCache(out, packet); - } - return len; - } - - private static int writeToCache(NetOutput out, SortedMap packets) throws IOException { - int len = 0; - len += writeVarInt(out, packets.size()); - int lastTime = 0; - for (Map.Entry entry : packets.entrySet()) { - int time = entry.getKey(); - len += writeVarInt(out, time - lastTime); - lastTime = time; - - len += writeToCache(out, entry.getValue()); - } - return len; - } - - private static int writeVarInt(NetOutput out, int i) throws IOException { - int len = 1; - while ((i & -128) != 0) { - out.writeByte(i & 127 | 128); - i >>>= 7; - len++; - } - out.writeByte(i); - return len; - } - - private static long coordToLong(int x, int z) { - return (long)x << 32 | (long)z & 0xFFFFFFFFL; - } - - private static void playMap(NavigableMap updates, int currentTimeStamp, int replayTime, Consumer update) { - Map.Entry lastUpdate = updates.floorEntry(replayTime); - if (lastUpdate != null && lastUpdate.getKey() > currentTimeStamp) { - update.accept(lastUpdate.getValue()); - } - } - - private static void rewindMap(NavigableMap updates, int currentTimeStamp, int replayTime, Consumer update) { - Map.Entry lastUpdate = updates.floorEntry(replayTime); - if (lastUpdate != null && !lastUpdate.getKey().equals(updates.floorKey(currentTimeStamp))) { - update.accept(lastUpdate.getValue()); - } - } - - private static abstract class TrackedThing { - List spawnPackets; - List despawnPackets; - int spawnTime; - - private TrackedThing(List spawnPackets, - List despawnPackets) { - this.spawnPackets = spawnPackets; - this.despawnPackets = despawnPackets; - } - - public int writeToCache(NetOutput indexOut, NetOutput cacheOut, int despawnTime, int index) throws IOException { - indexOut.writeVarInt(spawnTime); - indexOut.writeVarInt(despawnTime); - indexOut.writeVarInt(index); - index += QuickReplaySender.writeToCache(cacheOut, spawnPackets); - indexOut.writeVarInt(index); - index += QuickReplaySender.writeToCache(cacheOut, despawnPackets); - return index; - } - } - - // For memory efficiency we store raw packets (we might even want to consider compression or memory mapped files). - // During analysis we use TrackedThing which we then serialize (we'd have to do that anyway for caching) - // and afterwards deserialize in BakedTrackedThing as MC packets on demand for replaying. - private static abstract class BakedTrackedThing { - int indexSpawnPackets; - int indexDespawnPackets; - int spawnTime; - int despawnTime; - - private BakedTrackedThing(NetInput in) throws IOException { - spawnTime = in.readVarInt(); - despawnTime = in.readVarInt(); - indexSpawnPackets = in.readVarInt(); - indexDespawnPackets = in.readVarInt(); - } - - public void spawn(QuickReplaySender sender, Consumer> send) throws IOException { - sender.buf.readerIndex(indexSpawnPackets); - readPacketsFromCache(sender.bufInput).forEach(send); - } - - public void despawn(QuickReplaySender sender, Consumer> send) throws IOException { - sender.buf.readerIndex(indexDespawnPackets); - readPacketsFromCache(sender.bufInput).forEach(send); - } - - public abstract void play(int currentTimeStamp, int replayTime, Consumer> send); - public abstract void rewind(int currentTimeStamp, int replayTime, Consumer> send); - } - - private static class Entity extends TrackedThing { - private int id; - private NavigableMap locations = new TreeMap<>(); - - private Entity(int entityId, List spawnPackets) { - super(spawnPackets, Collections.singletonList(new ServerEntityDestroyPacket(entityId))); - this.id = entityId; - } - - @Override - public int writeToCache(NetOutput indexOut, NetOutput cacheOut, int despawnTime, int index) throws IOException { - indexOut.writeByte(1); - index = super.writeToCache(indexOut, cacheOut, despawnTime, index); - - indexOut.writeVarInt(id); - indexOut.writeVarInt(index); - index += writeVarInt(cacheOut, locations.size()); - int lastTime = 0; - for (Map.Entry entry : locations.entrySet()) { - int time = entry.getKey(); - Location loc = entry.getValue(); - index += writeVarInt(cacheOut, time - lastTime); - lastTime = time; - cacheOut.writeDouble(loc.getX()); - cacheOut.writeDouble(loc.getY()); - cacheOut.writeDouble(loc.getZ()); - cacheOut.writeFloat(loc.getYaw()); - cacheOut.writeFloat(loc.getPitch()); - index += 32; - } - - return index; - } - } - - private static class BakedEntity extends BakedTrackedThing { - private int id; - private int index; - private NavigableMap locations; - - private BakedEntity(NetInput in) throws IOException { - super(in); - - id = in.readVarInt(); - index = in.readVarInt(); - } - - @Override - public void spawn(QuickReplaySender sender, Consumer> send) throws IOException { - super.spawn(sender, send); - - sender.buf.readerIndex(index); - NetInput in = sender.bufInput; - - locations = new TreeMap<>(); - - int time = 0; - for (int i = in.readVarInt(); i > 0; i--) { - time += in.readVarInt(); - locations.put(time, new Location(in.readDouble(), in.readDouble(), in.readDouble(), in.readFloat(), in.readFloat())); - } - } - - @Override - public void despawn(QuickReplaySender sender, Consumer> send) throws IOException { - super.despawn(sender, send); - locations = null; - } - - @Override - public void play(int currentTimeStamp, int replayTime, Consumer> send) { - playMap(locations, currentTimeStamp, replayTime, l -> { - send.accept(toMC(new ServerEntityTeleportPacket(id, l.getX(), l.getY(), l.getZ(), l.getYaw(), l.getPitch(), false))); - send.accept(toMC(new ServerEntityHeadLookPacket(id, l.getYaw()))); - }); - } - - @Override - public void rewind(int currentTimeStamp, int replayTime, Consumer> send) { - rewindMap(locations, currentTimeStamp, replayTime, l -> { - send.accept(toMC(new ServerEntityTeleportPacket(id, l.getX(), l.getY(), l.getZ(), l.getYaw(), l.getPitch(), false))); - send.accept(toMC(new ServerEntityHeadLookPacket(id, l.getYaw()))); - }); - } - } - - private static class Chunk extends TrackedThing { - private TreeMap> blocksT = new TreeMap<>(); - private ListMultimap blocks = Multimaps.newListMultimap(blocksT, LinkedList::new); // LinkedList to allow .descendingIterator - private BlockStorage[] currentBlockState = new BlockStorage[16]; - - private Chunk(Column column) { - super(Collections.singletonList(new ServerChunkDataPacket(column)), - Collections.singletonList(new ServerUnloadChunkPacket(column.getX(), column.getZ()))); - com.github.steveice10.mc.protocol.data.game.chunk.Chunk[] chunks = column.getChunks(); - for (int i = 0; i < currentBlockState.length; i++) { - currentBlockState[i] = chunks[i] == null ? new BlockStorage() : copy(chunks[i].getBlocks()); - } - } - - @Override - public int writeToCache(NetOutput indexOut, NetOutput cacheOut, int despawnTime, int index) throws IOException { - indexOut.writeByte(2); - index = super.writeToCache(indexOut, cacheOut, despawnTime, index); - - indexOut.writeVarInt(index); - index += writeVarInt(cacheOut, blocksT.size()); - int lastTime = 0; - for (Map.Entry> entry : blocksT.entrySet()) { - int time = entry.getKey(); - index += writeVarInt(cacheOut, time - lastTime); - lastTime = time; - - Collection blockChanges = entry.getValue(); - index += writeVarInt(cacheOut, blockChanges.size()); - for (BlockChange blockChange : blockChanges) { - NetUtil.writePosition(cacheOut, blockChange.pos); - index += 8; - //#if MC>=11300 - index += writeVarInt(cacheOut, blockChange.from.getId()); - index += writeVarInt(cacheOut, blockChange.to.getId()); - //#else - //$$ index += writeVarInt(cacheOut, blockChange.from.getId() << 4 | blockChange.from.getData() & 15); - //$$ index += writeVarInt(cacheOut, blockChange.to.getId() << 4 | blockChange.to.getData() & 15); - //#endif - } - } - - return index; - } - } - - private static class BakedChunk extends BakedTrackedThing { - private int index; - private TreeMap> blocksT; - - private BakedChunk(NetInput in) throws IOException { - super(in); - - index = in.readVarInt(); - } - - @Override - public void spawn(QuickReplaySender sender, Consumer> send) throws IOException { - super.spawn(sender, send); - - sender.buf.readerIndex(index); - NetInput in = sender.bufInput; - - blocksT = new TreeMap<>(); - ListMultimap blocks = Multimaps.newListMultimap(blocksT, LinkedList::new); // LinkedList to allow .descendingIterator - - int time = 0; - for (int i = in.readVarInt(); i > 0; i--) { - time += in.readVarInt(); - - for (int j = in.readVarInt(); j > 0; j--) { - blocks.put(time, new BlockChange( - NetUtil.readPosition(in), - NetUtil.readBlockState(in), - NetUtil.readBlockState(in) - )); - } - } - } - - @Override - public void despawn(QuickReplaySender sender, Consumer> send) throws IOException { - super.despawn(sender, send); - - blocksT = null; - } - - @Override - public void play(int currentTimeStamp, int replayTime, Consumer> send) { - blocksT.subMap(currentTimeStamp, false, replayTime, true).values() - .forEach(updates -> updates.forEach(update -> { - send.accept(toMC(new ServerBlockChangePacket(new BlockChangeRecord(update.pos, update.to)))); - })); - } - - @Override - public void rewind(int currentTimeStamp, int replayTime, Consumer> send) { - if (currentTimeStamp >= despawnTime) { - play(spawnTime, replayTime, send); - return; - } - blocksT.subMap(replayTime, false, currentTimeStamp, true).descendingMap().values() - .forEach(updates -> - ((LinkedList) updates).descendingIterator().forEachRemaining(update -> - send.accept(toMC(new ServerBlockChangePacket(new BlockChangeRecord(update.pos, update.from)))))); - } - } - - private static class BlockChange { - private Position pos; - private BlockState from; - private BlockState to; - - private BlockChange(Position pos, BlockState from, BlockState to) { - this.pos = pos; - this.from = from; - this.to = to; - } - } - - private static class Weather extends TrackedThing { - private TreeMap rainStrengths = new TreeMap<>(); - - private Weather() { - super(Collections.singletonList(new ServerNotifyClientPacket(ClientNotification.START_RAIN, null)), - Collections.singletonList(new ServerNotifyClientPacket(ClientNotification.STOP_RAIN, null))); - } - - @Override - public int writeToCache(NetOutput indexOut, NetOutput cacheOut, int despawnTime, int index) throws IOException { - indexOut.writeByte(3); - index = super.writeToCache(indexOut, cacheOut, despawnTime, index); - - indexOut.writeVarInt(index); - index += QuickReplaySender.writeToCache(cacheOut, rainStrengths); - - return index; - } - } - - private static class BakedWeather extends BakedTrackedThing { - private int index; - private TreeMap> rainStrengths; - - private BakedWeather(NetInput in) throws IOException { - super(in); - - index = in.readVarInt(); - } - - @Override - public void spawn(QuickReplaySender sender, Consumer> send) throws IOException { - super.spawn(sender, send); - - sender.buf.readerIndex(index); - - rainStrengths = new TreeMap<>(); - - readFromCache(sender.bufInput, rainStrengths); - } - - @Override - public void despawn(QuickReplaySender sender, Consumer> send) throws IOException { - super.despawn(sender, send); - - rainStrengths = null; - } - - @Override - public void play(int currentTimeStamp, int replayTime, Consumer> send) { - playMap(rainStrengths, currentTimeStamp, replayTime, send); - } - - @Override - public void rewind(int currentTimeStamp, int replayTime, Consumer> send) { - rewindMap(rainStrengths, currentTimeStamp, replayTime, send); - } - } } //#endif diff --git a/src/main/java/com/replaymod/replay/ReplayHandler.java b/src/main/java/com/replaymod/replay/ReplayHandler.java index fbcfed85..183cedfc 100755 --- a/src/main/java/com/replaymod/replay/ReplayHandler.java +++ b/src/main/java/com/replaymod/replay/ReplayHandler.java @@ -35,8 +35,11 @@ import net.minecraft.network.ClientConnection; import java.io.IOException; import java.util.*; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; + +//#if MC>=11500 +//$$ import com.mojang.blaze3d.systems.RenderSystem; +//$$ import org.lwjgl.opengl.GL11; +//#endif //#if MC>=11300 import com.replaymod.replay.mixin.EntityLivingBaseAccessor; @@ -393,7 +396,7 @@ public class ReplayHandler { CameraEntity cam = getCameraEntity(); if (cam != null) { - targetCameraPosition = new Location(cam.x, cam.y, cam.z, cam.yaw, cam.pitch); + targetCameraPosition = new Location(Entity_getX(cam), Entity_getY(cam), Entity_getZ(cam), cam.yaw, cam.pitch); } else { targetCameraPosition = null; } @@ -535,9 +538,9 @@ public class ReplayHandler { // Update all entity positions (especially prev/lastTick values) for (Entity entity : loadedEntityList(mc.world)) { skipTeleportInterpolation(entity); - entity.prevRenderX = entity.prevX = entity.x; - entity.prevRenderY = entity.prevY = entity.y; - entity.prevRenderZ = entity.prevZ = entity.z; + entity.prevRenderX = entity.prevX = Entity_getX(entity); + entity.prevRenderY = entity.prevY = Entity_getY(entity); + entity.prevRenderZ = entity.prevZ = Entity_getZ(entity); entity.prevYaw = entity.yaw; entity.prevPitch = entity.pitch; } @@ -576,7 +579,7 @@ public class ReplayHandler { if (retainCameraPosition) { CameraEntity cam = getCameraEntity(); if (cam != null) { - targetCameraPosition = new Location(cam.x, cam.y, cam.z, + targetCameraPosition = new Location(Entity_getX(cam), Entity_getY(cam), Entity_getZ(cam), cam.yaw, cam.pitch); } else { targetCameraPosition = null; @@ -618,8 +621,18 @@ public class ReplayHandler { ); enableTexture(); mc.getFramebuffer().beginWrite(true); + //#if MC>=11500 + //$$ Window window = getWindow(mc); + //$$ RenderSystem.clear(256, MinecraftClient.IS_SYSTEM_MAC); + //$$ RenderSystem.matrixMode(GL11.GL_PROJECTION); + //$$ RenderSystem.loadIdentity(); + //$$ RenderSystem.ortho(0, window.getFramebufferWidth() / window.getScaleFactor(), window.getFramebufferHeight() / window.getScaleFactor(), 0, 1000, 3000); + //$$ RenderSystem.matrixMode(GL11.GL_MODELVIEW); + //$$ RenderSystem.loadIdentity(); + //$$ RenderSystem.translatef(0, 0, -2000); + //#else //#if MC>=11400 - mc.window.method_4493(true); + getWindow(mc).method_4493(true); //#else //#if MC>=11300 //$$ mc.mainWindow.setupOverlayRendering(); @@ -627,6 +640,7 @@ public class ReplayHandler { //$$ mc.entityRenderer.setupOverlayRendering(); //#endif //#endif + //#endif //#if MC>=11300 Window @@ -645,17 +659,21 @@ public class ReplayHandler { popMatrix(); pushMatrix(); //#if MC>=11300 - mc.getFramebuffer().draw(mc.window.getFramebufferWidth(), mc.window.getFramebufferHeight()); + mc.getFramebuffer().draw(getWindow(mc).getFramebufferWidth(), getWindow(mc).getFramebufferHeight()); //#else //$$ mc.getFramebuffer().framebufferRender(mc.displayWidth, mc.displayHeight); //#endif popMatrix(); + //#if MC>=11500 + //$$ getWindow(mc).swapBuffers(); + //#else //#if MC>=11300 - mc.window.setFullscreen(true); + getWindow(mc).setFullscreen(true); //#else //$$ Display.update(); //#endif + //#endif // Send the packets replaySender.sendPacketsTill(targetTime); @@ -676,9 +694,9 @@ public class ReplayHandler { //#endif for (Entity entity : loadedEntityList(mc.world)) { skipTeleportInterpolation(entity); - entity.prevRenderX = entity.prevX = entity.x; - entity.prevRenderY = entity.prevY = entity.y; - entity.prevRenderZ = entity.prevZ = entity.z; + entity.prevRenderX = entity.prevX = Entity_getX(entity); + entity.prevRenderY = entity.prevY = Entity_getY(entity); + entity.prevRenderZ = entity.prevZ = Entity_getZ(entity); entity.prevYaw = entity.yaw; entity.prevPitch = entity.pitch; } diff --git a/src/main/java/com/replaymod/replay/ReplayModReplay.java b/src/main/java/com/replaymod/replay/ReplayModReplay.java index f565ebe4..da416ae3 100644 --- a/src/main/java/com/replaymod/replay/ReplayModReplay.java +++ b/src/main/java/com/replaymod/replay/ReplayModReplay.java @@ -33,6 +33,8 @@ import java.io.File; import java.io.IOException; import java.util.Optional; +import static com.replaymod.core.versions.MCVer.*; + public class ReplayModReplay implements Module { { instance = this; } @@ -66,9 +68,9 @@ public class ReplayModReplay implements Module { if (camera != null) { Marker marker = new Marker(); marker.setTime(replayHandler.getReplaySender().currentTimeStamp()); - marker.setX(camera.x); - marker.setY(camera.y); - marker.setZ(camera.z); + marker.setX(Entity_getX(camera)); + marker.setY(Entity_getY(camera)); + marker.setZ(Entity_getZ(camera)); marker.setYaw(camera.yaw); marker.setPitch(camera.pitch); marker.setRoll(camera.roll); diff --git a/src/main/java/com/replaymod/replay/camera/CameraEntity.java b/src/main/java/com/replaymod/replay/camera/CameraEntity.java index c4a56a35..9ff5fbb4 100755 --- a/src/main/java/com/replaymod/replay/camera/CameraEntity.java +++ b/src/main/java/com/replaymod/replay/camera/CameraEntity.java @@ -169,7 +169,7 @@ public class CameraEntity * @param z Delta in Z direction */ public void moveCamera(double x, double y, double z) { - setCameraPosition(this.x + x, this.y + y, this.z + z); + setCameraPosition(Entity_getX(this) + x, Entity_getY(this) + y, Entity_getZ(this) + z); } /** @@ -179,9 +179,10 @@ public class CameraEntity * @param z Z coordinate */ public void setCameraPosition(double x, double y, double z) { - this.prevRenderX = this.prevX = this.x = x; - this.prevRenderY = this.prevY = this.y = y; - this.prevRenderZ = this.prevZ = this.z = z; + this.prevRenderX = this.prevX = x; + this.prevRenderY = this.prevY = y; + this.prevRenderZ = this.prevZ = z; + Entity_setPos(this, x, y, z); updateBoundingBox(); } @@ -222,9 +223,7 @@ public class CameraEntity this.prevZ = to.prevZ; this.prevYaw = to.prevYaw; this.prevPitch = to.prevPitch; - this.x = to.x; - this.y = to.y + yOffset; - this.z = to.z; + Entity_setPos(this, Entity_getX(to), Entity_getY(to), Entity_getZ(to)); this.yaw = to.yaw; this.pitch = to.pitch; this.prevRenderX = to.prevRenderX; @@ -243,8 +242,8 @@ public class CameraEntity //#else //$$ this.boundingBox.setBB(AxisAlignedBB.getBoundingBox( //#endif - this.x - width / 2, this.y, this.z - width / 2, - this.x + width / 2, this.y + height, this.z + width / 2)); + Entity_getX(this) - width / 2, Entity_getY(this), Entity_getZ(this) - width / 2, + Entity_getX(this) + width / 2, Entity_getY(this) + height, Entity_getZ(this) + width / 2)); } @Override diff --git a/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java b/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java index 05673e69..a8057eeb 100644 --- a/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java +++ b/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java @@ -633,7 +633,7 @@ public class GuiPathing { if (!replayHandler.isCameraView()) { spectatedId = getRenderViewEntity(replayHandler.getOverlay().getMinecraft()).getEntityId(); } - timeline.addPositionKeyframe(time, camera.x, camera.y, camera.z, + timeline.addPositionKeyframe(time, Entity_getX(camera), Entity_getY(camera), Entity_getZ(camera), camera.yaw, camera.pitch, camera.roll, spectatedId); mod.setSelected(path, time); } diff --git a/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java b/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java index c881ac52..66a66522 100644 --- a/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java +++ b/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java @@ -82,7 +82,7 @@ public class PathPreviewRenderer extends EventRegistrations { //#if MC>=10800 // Eye height is subtracted to make path appear higher (at eye height) than it actually is (at foot height) - Triple viewPos = Triple.of(view.x, view.y - view.getStandingEyeHeight(), view.z); + Triple viewPos = Triple.of(Entity_getX(view), Entity_getY(view) - view.getStandingEyeHeight(), Entity_getZ(view)); //#else //$$ Triple viewPos = Triple.of(view.posX, view.posY, view.posZ); //#endif @@ -208,17 +208,21 @@ public class PathPreviewRenderer extends EventRegistrations { if (distanceSquared(view, pos1) > renderDistanceSquared) return; if (distanceSquared(view, pos2) > renderDistanceSquared) return; - BufferBuilder_setTranslation(-view.getLeft(), -view.getMiddle(), -view.getRight()); - BufferBuilder_beginPosCol(GL11.GL_LINES); - BufferBuilder_addPosCol(pos1.getLeft(), pos1.getMiddle(), pos1.getRight(), + BufferBuilder_addPosCol( + pos1.getLeft() - view.getLeft(), + pos1.getMiddle() - view.getMiddle(), + pos1.getRight() - view.getRight(), color >> 16 & 0xff, color >> 8 & 0xff, color & 0xff, 255 ); - BufferBuilder_addPosCol(pos2.getLeft(), pos2.getMiddle(), pos2.getRight(), + BufferBuilder_addPosCol( + pos2.getLeft() - view.getLeft(), + pos2.getMiddle() - view.getMiddle(), + pos2.getRight() - view.getRight(), color >> 16 & 0xff, color >> 8 & 0xff, color & 0xff, @@ -227,13 +231,11 @@ public class PathPreviewRenderer extends EventRegistrations { GL11.glLineWidth(3); Tessellator_getInstance().draw(); - BufferBuilder_setTranslation(0, 0, 0); } private void drawPoint(Triple view, Triple pos, Keyframe keyframe) { - BufferBuilder_setTranslation(0, 0, 0); MCVer.bindTexture(TEXTURE); @@ -269,8 +271,13 @@ public class PathPreviewRenderer extends EventRegistrations { pos.getRight() - view.getRight() ); GL11.glNormal3f(0, 1, 0); + //#if MC>=11500 + //$$ GL11.glRotatef(-getRenderManager().camera.getYaw(), 0, 1, 0); + //$$ GL11.glRotatef(getRenderManager().camera.getPitch(), 1, 0, 0); + //#else GL11.glRotatef(-getRenderManager().cameraYaw, 0, 1, 0); GL11.glRotatef(getRenderManager().cameraPitch, 1, 0, 0); + //#endif Tessellator_getInstance().draw(); @@ -280,7 +287,6 @@ public class PathPreviewRenderer extends EventRegistrations { private void drawCamera(Triple view, Triple pos, Triple rot) { - BufferBuilder_setTranslation(0, 0, 0); MCVer.bindTexture(CAMERA_HEAD); diff --git a/src/main/resources/mixins.render.blend.replaymod.json b/src/main/resources/mixins.render.blend.replaymod.json index 1576cfdd..3cef6a39 100644 --- a/src/main/resources/mixins.render.blend.replaymod.json +++ b/src/main/resources/mixins.render.blend.replaymod.json @@ -5,6 +5,13 @@ "server": [], "client": [ //#if MC>=10800 + //#if MC<11500 + "WorldRendererAccessor", + "MixinChunkRenderWorker", + "MixinEffectRenderer", + "MixinModelRenderer", + "MixinTileEntityRendererDispatcher", + //#endif "ContainerLocalRenderInformationAccessor", //#if MC<10904 //$$ "EntityAccessor", @@ -13,15 +20,10 @@ "ItemRendererAccessor", //#endif "ParticleAccessor", - "WorldRendererAccessor", - "MixinChunkRenderWorker", - "MixinEffectRenderer", - "MixinModelRenderer", "MixinRenderGlobal", "MixinRenderItem", "MixinRenderLivingBase", - "MixinRenderManager", - "MixinTileEntityRendererDispatcher" + "MixinRenderManager" //#endif ], "compatibilityLevel": "JAVA_8", diff --git a/src/main/resources/mixins.render.replaymod.json b/src/main/resources/mixins.render.replaymod.json index 8be9afe2..1fd3ffbc 100644 --- a/src/main/resources/mixins.render.replaymod.json +++ b/src/main/resources/mixins.render.replaymod.json @@ -4,7 +4,11 @@ "mixins": [], "server": [], "client": [ - //#if MC>=10800 + "Mixin_ChromaKeyColorSky", + "Mixin_ChromaKeyForceSky", + "Mixin_CubicRotation", + "Mixin_SkipBlockOutlinesDuringRender", + //#if MC>=10800 && MC<11500 "ChunkRenderDispatcherAccessor", "MixinChunkRenderWorker", //#endif @@ -13,7 +17,9 @@ //#endif "WorldRendererAccessor", //#if MC>=10904 + //#if MC<11500 "MixinParticleManager", + //#endif //#else //$$ "MixinEffectRenderer", //$$ "MixinRendererLivingEntity", @@ -29,7 +35,9 @@ "MixinFrustum", "MixinRender", //#if MC>=10800 + //#if MC<11500 "MixinRenderGlobal", + //#endif //#else //$$ "MixinOpenGlHelper", //#endif diff --git a/versions/common.gradle b/versions/common.gradle index 4cc58eb2..f8a3c066 100644 --- a/versions/common.gradle +++ b/versions/common.gradle @@ -216,15 +216,19 @@ dependencies { if (FABRIC) { minecraft 'com.mojang:minecraft:' + [ 11404: '1.14.4', + 11501: '1.15.1', ][mcVersion] mappings 'net.fabricmc:yarn:' + [ 11404: '1.14.4+build.1', + 11501: '1.15.1+build.37', ][mcVersion] modCompile 'net.fabricmc:fabric-loader:' + [ 11404: '0.4.8+build.155', + 11501: '0.7.4+build.177', ][mcVersion] modCompile 'net.fabricmc.fabric-api:fabric-api:' + [ 11404: '0.3.0+build.200', + 11501: '0.4.27+build.286-1.15', ][mcVersion] } @@ -258,9 +262,7 @@ dependencies { shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8' - def studioVersion = mcVersionStr - if (studioVersion == '1.8.9') studioVersion = '1.8' - shadow "com.github.ReplayMod.ReplayStudio:$studioVersion:e657fe8", shadeExclusions + shadow "com.replaymod.replaystudio:ReplayStudio:120feb9", shadeExclusions shadowReobf(project(":jGui:$jGuiVersion")){ transitive = false // FG 1.2 puts all MC deps into the compile configuration and we don't want to shade those diff --git a/versions/mapping-fabric-1.15.1-1.14.4.txt b/versions/mapping-fabric-1.15.1-1.14.4.txt new file mode 100644 index 00000000..5c8c91de --- /dev/null +++ b/versions/mapping-fabric-1.15.1-1.14.4.txt @@ -0,0 +1,28 @@ +net.minecraft.client.model.ModelPart.Cuboid net.minecraft.client.model.Box +net.minecraft.client.render.chunk.ChunkBuilder net.minecraft.client.render.chunk.ChunkRenderWorker +net.minecraft.client.render.chunk.ChunkBuilder.BuiltChunk net.minecraft.client.render.chunk.ChunkRenderer +net.minecraft.client.render.chunk.ChunkBuilder.BuiltChunk.Task net.minecraft.client.render.chunk.ChunkRenderTask +net.minecraft.client.network.packet.PlayerActionResponseS2CPacket net.minecraft.class_4463 +net.minecraft.network.NetworkState LOGIN field_11688 +net.minecraft.network.NetworkState PLAY field_11690 +net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil net.fabricmc.fabric.impl.resources.ModResourcePackUtil +net.minecraft.client.render.entity.EntityRenderer shouldRender() isVisible() +net.minecraft.client.render.Frustum net.minecraft.client.render.VisibleRegion +net.minecraft.client.render.GameRenderer renderWorld() renderCenter() +net.minecraft.entity.LivingEntity serverX field_6224 +net.minecraft.entity.LivingEntity serverY field_6245 +net.minecraft.entity.LivingEntity serverZ field_6263 +net.minecraft.entity.LivingEntity serverYaw field_6284 +net.minecraft.entity.LivingEntity serverPitch field_6221 +net.minecraft.client.render.WorldRenderer drawBlockOutline() drawHighlightedBlockOutline() +net.minecraft.client.render.GameRenderer method_22973() applyCameraTransformations() +net.minecraft.client.util.math.Matrix4f viewboxMatrix() method_4929() +net.minecraft.util.ThreadExecutor send() method_18858() +net.minecraft.util.ThreadExecutor createTask() prepareRunnable() +net.minecraft.util.ThreadExecutor canExecute() canRun() +net.minecraft.util.ThreadExecutor runTasks() executeTaskQueue() +net.minecraft.util.ThreadExecutor submit() executeFuture() +net.minecraft.client.util.Window method_4493() +net.minecraft.util.SystemUtil.OperatingSystem WINDOWS field_1133 +net.minecraft.util.SystemUtil.OperatingSystem OSX field_1137 +net.minecraft.client.util.ScreenshotUtils takeScreenshot() method_1663()