From 78bd06024964ca84d0a23a3d5774415f407629e1 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 26 Mar 2023 18:58:49 +0200 Subject: [PATCH 1/3] Port to MC 1.19.4 --- build.gradle | 9 +- jGui | 2 +- root.gradle.kts | 2 + settings.gradle.kts | 2 + .../com/replaymod/core/ReplayModBackend.java | 3 +- .../recording/mixin/MixinWorldClient.java | 88 +++---------------- .../recording/packet/PacketListener.java | 23 +++++ .../render/capturer/OpenGlFrameCapturer.java | 2 + .../render/rendering/VideoRenderer.java | 2 + .../replaymod/replay/FullReplaySender.java | 9 +- .../com/replaymod/replay/NoGuiScreenshot.java | 2 + .../com/replaymod/replay/ReplayHandler.java | 14 +++ versions/1.19.4/.gitkeep | 0 13 files changed, 78 insertions(+), 80 deletions(-) create mode 100644 versions/1.19.4/.gitkeep diff --git a/build.gradle b/build.gradle index 6055b10f..bd4894a1 100644 --- a/build.gradle +++ b/build.gradle @@ -252,6 +252,7 @@ dependencies { 11901: '1.19.1', 11902: '1.19.2', 11903: '1.19.3-rc3', + 11904: '1.19.4', ][mcVersion] mappings 'net.fabricmc:yarn:' + [ 11404: '1.14.4+build.16', @@ -268,6 +269,7 @@ dependencies { 11901: '1.19.1+build.5:v2', 11902: '1.19.2+build.28:v2', 11903: '1.19.3-rc3+build.1:v2', + 11904: '1.19.4+build.1:v2', ][mcVersion] modImplementation 'net.fabricmc:fabric-loader:0.14.11' def fabricApiVersion = [ @@ -285,6 +287,7 @@ dependencies { 11901: '0.58.5+1.19.1', 11902: '0.68.0+1.19.2', 11903: '0.68.1+1.19.3', + 11904: '0.76.0+1.19.4', ][mcVersion] def fabricApiModules = [ "api-base", @@ -357,7 +360,7 @@ dependencies { shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8' - shadow "com.github.ReplayMod:ReplayStudio:21ef505", shadeExclusions + shadow "com.github.ReplayMod:ReplayStudio:b5cc75a", shadeExclusions // FIXME this should be pulled in by ReplayStudio, and IntelliJ sees it, but javac for some reason does not implementation 'com.github.viaversion:opennbt:0a02214' // 2.0-SNAPSHOT (ViaVersion Edition) @@ -368,7 +371,9 @@ dependencies { shadow 'com.github.ReplayMod:lwjgl-utils:27dcd66' if (FABRIC) { - if (mcVersion >= 11903) { + if (mcVersion >= 11904) { + modImplementation 'com.terraformersmc:modmenu:6.1.0-rc.4' + } else if (mcVersion >= 11903) { modImplementation 'com.terraformersmc:modmenu:5.0.0-alpha.4' } else if (mcVersion >= 11901) { modImplementation 'com.terraformersmc:modmenu:4.0.5' diff --git a/jGui b/jGui index 7a80b50c..34d9d6bb 160000 --- a/jGui +++ b/jGui @@ -1 +1 @@ -Subproject commit 7a80b50c2e7cd0557c5ab670c59b46b256c0434c +Subproject commit 34d9d6bb1531a425c4a4906920c6e235b24a8031 diff --git a/root.gradle.kts b/root.gradle.kts index 511e29e6..6f78706d 100755 --- a/root.gradle.kts +++ b/root.gradle.kts @@ -193,6 +193,7 @@ val doRelease by tasks.registering { defaultTasks("bundleJar") preprocess { + val mc11904 = createNode("1.19.4", 11904, "yarn") val mc11903 = createNode("1.19.3", 11903, "yarn") val mc11902 = createNode("1.19.2", 11902, "yarn") val mc11901 = createNode("1.19.1", 11901, "yarn") @@ -217,6 +218,7 @@ preprocess { val mc10800 = createNode("1.8", 10800, "srg") val mc10710 = createNode("1.7.10", 10710, "srg") + mc11904.link(mc11903) mc11903.link(mc11902, file("versions/mapping-fabric-1.19.3-1.19.2.txt")) mc11902.link(mc11901) mc11901.link(mc11900) diff --git a/settings.gradle.kts b/settings.gradle.kts index fa478e0a..ea849bd8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,6 +37,7 @@ val jGuiVersions = listOf( "1.19.1", "1.19.2", "1.19.3", + "1.19.4", ) val replayModVersions = listOf( // "1.7.10", @@ -62,6 +63,7 @@ val replayModVersions = listOf( "1.19.1", "1.19.2", "1.19.3", + "1.19.4", ) rootProject.buildFileName = "root.gradle.kts" diff --git a/src/main/java/com/replaymod/core/ReplayModBackend.java b/src/main/java/com/replaymod/core/ReplayModBackend.java index d6313852..2e120df9 100644 --- a/src/main/java/com/replaymod/core/ReplayModBackend.java +++ b/src/main/java/com/replaymod/core/ReplayModBackend.java @@ -2,6 +2,7 @@ package com.replaymod.core; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.SharedConstants; import static com.replaymod.core.ReplayMod.MOD_ID; @@ -20,7 +21,7 @@ public class ReplayModBackend implements ClientModInitializer { } public String getMinecraftVersion() { - return mod.getMinecraft().getGame().getVersion().getName(); + return SharedConstants.getGameVersion().getName(); } public boolean isModLoaded(String id) { diff --git a/src/main/java/com/replaymod/recording/mixin/MixinWorldClient.java b/src/main/java/com/replaymod/recording/mixin/MixinWorldClient.java index e859e2a3..b33c0436 100644 --- a/src/main/java/com/replaymod/recording/mixin/MixinWorldClient.java +++ b/src/main/java/com/replaymod/recording/mixin/MixinWorldClient.java @@ -6,7 +6,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.packet.s2c.play.PlaySoundS2CPacket; -import net.minecraft.util.profiler.Profiler; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvent; import net.minecraft.util.math.BlockPos; @@ -21,87 +20,26 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //$$ import net.minecraft.util.registry.RegistryEntry; //#endif -//#if MC>=11600 -import net.minecraft.util.registry.RegistryKey; -import net.minecraft.world.MutableWorldProperties; -import java.util.function.Supplier; -//#else -//$$ import net.minecraft.world.level.LevelProperties; -//#endif - -//#if MC>=11400 -import net.minecraft.world.chunk.ChunkManager; -//#if MC<11600 -//$$ import net.minecraft.world.dimension.Dimension; -//#endif -import net.minecraft.world.dimension.DimensionType; -import java.util.function.BiFunction; -//#else -//$$ import net.minecraft.world.storage.ISaveHandler; -//#if MC>=11400 -//$$ import net.minecraft.world.dimension.Dimension; -//$$ import net.minecraft.world.storage.WorldSavedDataStorage; -//#else -//$$ import net.minecraft.world.WorldProvider; -//#endif -//#endif - @Mixin(ClientWorld.class) public abstract class MixinWorldClient extends World implements RecordingEventHandler.RecordingEventSender { @Shadow private MinecraftClient client; - //#if MC>=11600 - protected MixinWorldClient(MutableWorldProperties mutableWorldProperties, RegistryKey registryKey, - //#if MC<11602 - //$$ RegistryKey registryKey2, - //#endif - //#if MC>=11802 - //$$ RegistryEntry dimensionType, - //#else - DimensionType dimensionType, - //#endif - Supplier profiler, boolean bl, boolean bl2, long l - //#if MC>=11900 - //$$ , int maxChainedNeighborUpdates - //#endif - ) { - super(mutableWorldProperties, registryKey, - //#if MC<11602 - //$$ registryKey2, - //#endif - dimensionType, profiler, bl, bl2, l - //#if MC>=11900 - //$$ , maxChainedNeighborUpdates - //#endif - ); + @SuppressWarnings("ConstantConditions") + protected MixinWorldClient() { + //#if MC>=11904 + //$$ super(null, null, null, null, null, false, false, 0, 0); + //#elseif MC>=11900 + //$$ super(null, null, null, null, false, false, 0, 0); + //#elseif MC>=11602 + super(null, null, null, null, false, false, 0); + //#elseif MC>=11600 + //$$ super(null, null, null, null, null, false, false, 0); + //#else + //$$ super(null, null, null, null, false); + //#endif } - //#else - //#if MC>=11400 - //$$ protected MixinWorldClient(LevelProperties levelProperties_1, DimensionType dimensionType_1, BiFunction biFunction_1, Profiler profiler_1, boolean boolean_1) { - //$$ super(levelProperties_1, dimensionType_1, biFunction_1, profiler_1, boolean_1); - //$$ } - //#else - //$$ protected MixinWorldClient(ISaveHandler saveHandlerIn, - //#if MC>=11400 - //$$ WorldSavedDataStorage mapStorage, - //#endif - //$$ WorldInfo info, - //#if MC>=11400 - //$$ Dimension providerIn, - //#else - //$$ WorldProvider providerIn, - //#endif - //$$ Profiler profilerIn, boolean client) { - //$$ super(saveHandlerIn, - //#if MC>=11400 - //$$ mapStorage, - //#endif - //$$ info, providerIn, profilerIn, client); - //$$ } - //#endif - //#endif private RecordingEventHandler replayModRecording_getRecordingEventHandler() { return ((RecordingEventHandler.RecordingEventSender) this.client.worldRenderer).getRecordingEventHandler(); diff --git a/src/main/java/com/replaymod/recording/packet/PacketListener.java b/src/main/java/com/replaymod/recording/packet/PacketListener.java index 677673ad..be72bedb 100644 --- a/src/main/java/com/replaymod/recording/packet/PacketListener.java +++ b/src/main/java/com/replaymod/recording/packet/PacketListener.java @@ -69,6 +69,11 @@ import static com.replaymod.core.versions.MCVer.*; import static com.replaymod.replaystudio.util.Utils.writeInt; import static java.util.Objects.requireNonNull; +//#if MC>=11904 +//$$ import net.minecraft.network.PacketBundleHandler; +//$$ import java.util.ArrayList; +//#endif + @ChannelHandler.Sharable // so we can re-order it public class PacketListener extends ChannelInboundHandlerAdapter { @@ -341,7 +346,25 @@ public class PacketListener extends ChannelInboundHandlerAdapter { } else if (msg instanceof net.minecraft.network.Packet) { // for integrated server connections MC is passing the packet objects directly, so we need to encode them // ourselves to be able to store them + //#if MC>=11904 + //$$ PacketBundleHandler bundleHandler = ctx.channel().attr(PacketBundleHandler.KEY).get().getBundler(NetworkSide.CLIENTBOUND); + //$$ List packets = new ArrayList<>(1); + //$$ bundleHandler.forEachPacket((net.minecraft.network.packet.Packet) msg, unbundledPacket -> { + //$$ try { + //$$ packets.add(encodeMcPacket(connectionState, unbundledPacket)); + //$$ } catch (Exception e) { + //$$ throw new RuntimeException(e); + //$$ } + //$$ }); + //$$ if (packets.size() > 1) { + //$$ packets.forEach(this::save); + //$$ super.channelRead(ctx, msg); + //$$ return; + //$$ } + //$$ packet = packets.isEmpty() ? null : packets.get(0); + //#else packet = encodeMcPacket(connectionState, (net.minecraft.network.Packet) msg); + //#endif } if (packet != null) { diff --git a/src/main/java/com/replaymod/render/capturer/OpenGlFrameCapturer.java b/src/main/java/com/replaymod/render/capturer/OpenGlFrameCapturer.java index eb26e0bc..bc9bdad5 100644 --- a/src/main/java/com/replaymod/render/capturer/OpenGlFrameCapturer.java +++ b/src/main/java/com/replaymod/render/capturer/OpenGlFrameCapturer.java @@ -88,7 +88,9 @@ public abstract class OpenGlFrameCapturer=11500 diff --git a/src/main/java/com/replaymod/replay/FullReplaySender.java b/src/main/java/com/replaymod/replay/FullReplaySender.java index 9c9621e0..5eab0b60 100644 --- a/src/main/java/com/replaymod/replay/FullReplaySender.java +++ b/src/main/java/com/replaymod/replay/FullReplaySender.java @@ -57,6 +57,10 @@ import net.minecraft.util.math.Vec3d; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; +//#if MC>=11904 +//$$ import net.minecraft.network.packet.s2c.play.PositionFlag; +//#endif + //#if MC>=11903 //$$ import net.minecraft.network.packet.s2c.play.ProfilelessChatMessageS2CPacket; //#endif @@ -804,7 +808,10 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend if(replayHandler.shouldSuppressCameraMovements()) return null; //#if MC>=10800 - //#if MC>=11400 + //#if MC>=11904 + //$$ for (PositionFlag relative : ppl.getFlags()) { + //$$ if (relative == PositionFlag.X || relative == PositionFlag.Y || relative == PositionFlag.Z) { + //#elseif MC>=11400 for (PlayerPositionLookS2CPacket.Flag relative : ppl.getFlags()) { if (relative == PlayerPositionLookS2CPacket.Flag.X || relative == PlayerPositionLookS2CPacket.Flag.Y diff --git a/src/main/java/com/replaymod/replay/NoGuiScreenshot.java b/src/main/java/com/replaymod/replay/NoGuiScreenshot.java index a3cd6d56..69a995b6 100644 --- a/src/main/java/com/replaymod/replay/NoGuiScreenshot.java +++ b/src/main/java/com/replaymod/replay/NoGuiScreenshot.java @@ -69,7 +69,9 @@ public class NoGuiScreenshot { //#endif ); mc.getFramebuffer().beginWrite(true); + //#if MC<11904 GlStateManager.enableTexture(); + //#endif float tickDelta = mc.getTickDelta(); //#if MC>=11500 diff --git a/src/main/java/com/replaymod/replay/ReplayHandler.java b/src/main/java/com/replaymod/replay/ReplayHandler.java index 800377b6..1e9278d6 100644 --- a/src/main/java/com/replaymod/replay/ReplayHandler.java +++ b/src/main/java/com/replaymod/replay/ReplayHandler.java @@ -33,6 +33,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.DownloadingTerrainScreen; import net.minecraft.client.network.ClientLoginNetworkHandler; import net.minecraft.client.util.Window; +import net.minecraft.network.NetworkState; import net.minecraft.util.crash.CrashReport; import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; @@ -41,6 +42,10 @@ import net.minecraft.network.ClientConnection; import java.io.IOException; import java.util.*; +//#if MC>=11904 +//$$ import net.minecraft.network.PacketBundler; +//#endif + //#if MC>=11700 //$$ import net.minecraft.client.render.DiffuseLighting; //$$ import net.minecraft.util.math.Matrix4f; @@ -317,9 +322,16 @@ public class ReplayHandler { channel.pipeline().addLast("ReplayModReplay_quickReplaySender", quickReplaySender); //#endif channel.pipeline().addLast("ReplayModReplay_replaySender", fullReplaySender); + //#if MC>=11904 + //$$ channel.pipeline().addLast("bundler", new PacketBundler(NetworkSide.CLIENTBOUND)); + //#endif channel.pipeline().addLast("packet_handler", networkManager); channel.pipeline().fireChannelActive(); + // MC usually transitions from handshake to login via the packets it sends. + // We don't send any packets (there is no server to receive them), so we need to switch manually. + networkManager.setState(NetworkState.LOGIN); + //#if MC>=11400 ((MinecraftAccessor) mc).setConnection(networkManager); //#endif @@ -626,7 +638,9 @@ public class ReplayHandler { , true //#endif ); + //#if MC<11904 GlStateManager.enableTexture(); + //#endif mc.getFramebuffer().beginWrite(true); Window window = mc.getWindow(); //#if MC>=11500 diff --git a/versions/1.19.4/.gitkeep b/versions/1.19.4/.gitkeep new file mode 100644 index 00000000..e69de29b From 8037a9ad30c5eac101c11fc70ce5dcc2b10fd3be Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 26 Mar 2023 18:59:14 +0200 Subject: [PATCH 2/3] Fix ridden boat missing when joining 1.18+ Spigot server --- .../replay/mixin/Mixin_FixEntityNotTracking.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/versions/1.18.1/src/main/java/com/replaymod/replay/mixin/Mixin_FixEntityNotTracking.java b/versions/1.18.1/src/main/java/com/replaymod/replay/mixin/Mixin_FixEntityNotTracking.java index 1d95dd1b..1c497b25 100644 --- a/versions/1.18.1/src/main/java/com/replaymod/replay/mixin/Mixin_FixEntityNotTracking.java +++ b/versions/1.18.1/src/main/java/com/replaymod/replay/mixin/Mixin_FixEntityNotTracking.java @@ -20,6 +20,14 @@ public class Mixin_FixEntityNotTracking { private void updatePositionIfNotTracked(Entity entity) { if (entity != null && entity.world instanceof ClientWorldAccessor world) { if (!world.getEntityList().has(entity)) { + // This only applies to entities that are server-controlled. + // You wouldn't think this check is necessary but for some stupid reason Spigot sends entities before + // chunks, so we must not update the entity if it is being ridden by the client player because those + // will fall into the void and die (client-side only ofc). + if (entity.isLogicalSideForUpdatingMovement()) { + return; + } + // Skip interpolation of position updates coming from server // (See: newX in EntityLivingBase or otherPlayerMPX in EntityOtherPlayerMP) int ticks = 0; From bf32672536d275e5125cd11d094fb91fd5190c6c Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sun, 26 Mar 2023 19:21:30 +0200 Subject: [PATCH 3/3] Fix active timeline changes affecting render queue (fixes #814) The `Timeline` type is mutable, so we need to create a copy before we pass it to GuiKeyframeRepository because we don't want anything stored in there (or more specifically in render queue which can also be added to from that gui) to be affected by subsequent changes. --- .../java/com/replaymod/simplepathing/gui/GuiPathing.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java b/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java index d2117cf8..560d5d4b 100644 --- a/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java +++ b/src/main/java/com/replaymod/simplepathing/gui/GuiPathing.java @@ -395,8 +395,11 @@ public class GuiPathing { public void keyframeRepoButtonPressed() { abortPathPlayback(); try { + TimelineSerialization serialization = new TimelineSerialization(mod.getCurrentTimeline(), null); + String serialized = serialization.serialize(Collections.singletonMap("", mod.getCurrentTimeline().getTimeline())); + Timeline currentTimeline = serialization.deserialize(serialized).get(""); GuiKeyframeRepository gui = new GuiKeyframeRepository( - mod.getCurrentTimeline(), replayHandler.getReplayFile(), mod.getCurrentTimeline().getTimeline()); + mod.getCurrentTimeline(), replayHandler.getReplayFile(), currentTimeline); Futures.addCallback(gui.getFuture(), new FutureCallback() { @Override public void onSuccess(Timeline result) {