diff --git a/build.gradle.kts b/build.gradle.kts index e3a4794e..66d57726 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -85,6 +85,7 @@ dependencies { 12001 -> "0.83.1+1.20.1" 12002 -> "0.91.2+1.20.2" 12004 -> "0.91.2+1.20.4" + 12006 -> "0.98.0+1.20.6" else -> throw UnsupportedOperationException() } val fabricApiModules = mutableListOf( @@ -154,7 +155,7 @@ dependencies { implementation(shadow("com.github.ReplayMod.JavaBlend:2.79.0:a0696f8")!!) - implementation(shadow("com.github.ReplayMod:ReplayStudio:d9f7c11")!!) + implementation(shadow("com.github.ReplayMod:ReplayStudio:6d59510")!!) // 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) @@ -163,6 +164,7 @@ dependencies { if (platform.isFabric) { val modMenuVersion = when { + mcVersion >= 12006 -> "10.0.0-beta.1" mcVersion >= 12003 -> "9.0.0-pre.1" mcVersion >= 12002 -> "8.0.0" mcVersion >= 12000 -> "7.0.1" @@ -179,11 +181,15 @@ dependencies { else -> null } if (modMenuVersion != null) { - modImplementation("com.terraformersmc:modmenu:$modMenuVersion") + modCompileOnly("com.terraformersmc:modmenu:$modMenuVersion") } else { // Oldest modmenu on their maven is 1.10.5 for MC 1.15.2; for older versions we won't run it in dev modCompileOnly("com.terraformersmc:modmenu:1.10.6") } + // Lacks maven dependencies + if (mcVersion == 12006) { + //modRuntimeOnly("net.fabricmc.fabric-api:fabric-api:0.98.0+1.20.6") + } } if (mcVersion >= 11600) { diff --git a/jGui b/jGui index 9b5b2104..1a9b23d0 160000 --- a/jGui +++ b/jGui @@ -1 +1 @@ -Subproject commit 9b5b2104aad687949ac4138efecd6866a4582241 +Subproject commit 1a9b23d0c92223bf3e6859452854066e841e0eb2 diff --git a/root.gradle.kts b/root.gradle.kts index 18c2e7a0..b97e261f 100755 --- a/root.gradle.kts +++ b/root.gradle.kts @@ -203,6 +203,7 @@ val doRelease by tasks.registering { defaultTasks("bundleJar") preprocess { + val mc12006 = createNode("1.20.6", 12006, "yarn") val mc12004 = createNode("1.20.4", 12004, "yarn") val mc12002 = createNode("1.20.2", 12002, "yarn") val mc12001 = createNode("1.20.1", 12001, "yarn") @@ -230,6 +231,7 @@ preprocess { val mc10800 = createNode("1.8", 10800, "srg") val mc10710 = createNode("1.7.10", 10710, "srg") + mc12006.link(mc12004) mc12004.link(mc12002, file("versions/mapping-fabric-1.20.4-1.20.2.txt")) mc12002.link(mc12001) mc12001.link(mc11904) diff --git a/settings.gradle.kts b/settings.gradle.kts index b332765d..c38a151c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -38,6 +38,7 @@ val jGuiVersions = listOf( "1.20.1", "1.20.2", "1.20.4", + "1.20.6", ) val replayModVersions = listOf( // "1.7.10", @@ -66,6 +67,7 @@ val replayModVersions = listOf( "1.20.1", "1.20.2", "1.20.4", + "1.20.6", ) rootProject.buildFileName = "root.gradle.kts" diff --git a/src/main/java/com/replaymod/core/ReplayMod.java b/src/main/java/com/replaymod/core/ReplayMod.java index d31a57f7..add813c7 100644 --- a/src/main/java/com/replaymod/core/ReplayMod.java +++ b/src/main/java/com/replaymod/core/ReplayMod.java @@ -36,6 +36,13 @@ import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; +//#if MC>=12006 +//$$ import net.minecraft.resource.ResourcePackInfo; +//$$ import net.minecraft.resource.ResourcePackSource; +//$$ import net.minecraft.text.Text; +//$$ import java.util.Optional; +//#endif + //#if MC>=11900 //#else import net.minecraft.client.options.Option; @@ -120,7 +127,9 @@ public class ReplayMod implements Module, Scheduler { return null; } } - //#if MC>=11903 + //#if MC>=12006 + //$$ return new DirectoryResourcePack(new ResourcePackInfo(JGUI_RESOURCE_PACK_NAME, Text.literal("jGui"), ResourcePackSource.NONE, Optional.empty()), folder.toPath()) { + //#elseif MC>=11903 //$$ return new DirectoryResourcePack(JGUI_RESOURCE_PACK_NAME, folder.toPath(), true) { //#else return new DirectoryResourcePack(folder) { diff --git a/src/main/java/com/replaymod/core/mixin/Mixin_PostRenderWorldCalback.java b/src/main/java/com/replaymod/core/mixin/Mixin_PostRenderWorldCalback.java index 24561031..641749c5 100644 --- a/src/main/java/com/replaymod/core/mixin/Mixin_PostRenderWorldCalback.java +++ b/src/main/java/com/replaymod/core/mixin/Mixin_PostRenderWorldCalback.java @@ -15,12 +15,18 @@ import com.llamalad7.mixinextras.sugar.Local; @Mixin(WorldRenderer.class) public class Mixin_PostRenderWorldCalback { + //#if MC>=12005 + //$$ @Inject(method = "render", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4fStack;popMatrix()Lorg/joml/Matrix4fStack;")) + //$$ private void postRenderWorld(CallbackInfo ci) { + //$$ MatrixStack matrixStack = new MatrixStack(); + //#else @Inject(method = "render", at = @At("RETURN")) //#if MC>=11500 private void postRenderWorld(CallbackInfo ci, @Local(argsOnly = true) MatrixStack matrixStack) { //#else //$$ private void postRenderWorld(CallbackInfo ci) { //$$ MatrixStack matrixStack = new MatrixStack(); + //#endif //#endif PostRenderWorldCallback.EVENT.invoker().postRenderWorld(matrixStack); } diff --git a/src/main/java/com/replaymod/core/mixin/Mixin_PreRenderHandCallback.java b/src/main/java/com/replaymod/core/mixin/Mixin_PreRenderHandCallback.java index e52b713f..012c93eb 100644 --- a/src/main/java/com/replaymod/core/mixin/Mixin_PreRenderHandCallback.java +++ b/src/main/java/com/replaymod/core/mixin/Mixin_PreRenderHandCallback.java @@ -10,15 +10,23 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//#if MC>=12005 +//$$ import org.joml.Matrix4f; +//#else +//#endif + @Mixin(GameRenderer.class) public class Mixin_PreRenderHandCallback { @Inject(method = "renderHand", at = @At("HEAD"), cancellable = true) private void preRenderHand( - //#if MC>=11500 + //#if MC>=11500 && MC<12005 MatrixStack matrixStack, //#endif Camera camera, float partialTicks, + //#if MC>=12005 + //$$ Matrix4f matrixStack, + //#endif CallbackInfo ci) { if (PreRenderHandCallback.EVENT.invoker().preRenderHand()) { ci.cancel(); diff --git a/src/main/java/com/replaymod/core/utils/Restrictions.java b/src/main/java/com/replaymod/core/utils/Restrictions.java index 0fc0e9f2..c1543e83 100644 --- a/src/main/java/com/replaymod/core/utils/Restrictions.java +++ b/src/main/java/com/replaymod/core/utils/Restrictions.java @@ -2,6 +2,12 @@ package com.replaymod.core.utils; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; import net.minecraft.network.PacketByteBuf; + +//#if MC>=12006 +//$$ import net.minecraft.network.codec.PacketCodec; +//$$ import net.minecraft.network.packet.CustomPayload; +//#endif + //#if MC>=10904 import net.minecraft.util.Identifier; //#endif @@ -26,7 +32,9 @@ public class Restrictions { private boolean onlyRecordingPlayer; public String handle(CustomPayloadS2CPacket packet) { - //#if MC>=12002 + //#if MC>=12006 + //$$ PacketByteBuf buffer = new PacketByteBuf(Unpooled.wrappedBuffer(((Payload) packet.payload()).bytes())); + //#elseif MC>=12002 //$$ PacketByteBuf buffer = new PacketByteBuf(Unpooled.buffer()); //$$ packet.write(buffer); //#elseif MC>=10800 @@ -67,4 +75,22 @@ public class Restrictions { public boolean isOnlyRecordingPlayer() { return onlyRecordingPlayer; } + + //#if MC>=12006 + //$$ public static final CustomPayload.Id ID = CustomPayload.id(PLUGIN_CHANNEL.toString()); + //$$ public static final PacketCodec CODEC = PacketCodec.ofStatic( + //$$ (buf, payload) -> buf.writeBytes(payload.bytes()), + //$$ buf -> { + //$$ byte[] bytes = new byte[buf.readableBytes()]; + //$$ buf.readBytes(bytes); + //$$ return new Payload(bytes); + //$$ } + //$$ ); + //$$ public record Payload(byte[] bytes) implements CustomPayload { + //$$ @Override + //$$ public Id getId() { + //$$ return ID; + //$$ } + //$$ } + //#endif } diff --git a/src/main/java/com/replaymod/core/versions/LangResourcePack.java b/src/main/java/com/replaymod/core/versions/LangResourcePack.java index 41fa3e14..5e988552 100644 --- a/src/main/java/com/replaymod/core/versions/LangResourcePack.java +++ b/src/main/java/com/replaymod/core/versions/LangResourcePack.java @@ -34,6 +34,13 @@ import net.fabricmc.loader.api.ModContainer; //#else //#endif +//#if MC>=12006 +//$$ import net.minecraft.resource.ResourcePackInfo; +//$$ import net.minecraft.resource.ResourcePackSource; +//$$ import net.minecraft.text.Text; +//$$ import java.util.Optional; +//#endif + //#if MC>=11903 //$$ import java.util.Objects; //$$ import net.minecraft.resource.InputSupplier; @@ -64,7 +71,9 @@ public class LangResourcePack extends AbstractFileResourcePack { private final Path basePath; public LangResourcePack() { - //#if MC>=11903 + //#if MC>=12006 + //$$ super(new ResourcePackInfo(NAME, Text.literal("ReplayMod Translations"), ResourcePackSource.NONE, Optional.empty())); + //#elseif MC>=11903 //$$ super(NAME, true); //#else super(new File(NAME)); diff --git a/src/main/java/com/replaymod/core/versions/MCVer.java b/src/main/java/com/replaymod/core/versions/MCVer.java index 44e64f14..806b5f3c 100644 --- a/src/main/java/com/replaymod/core/versions/MCVer.java +++ b/src/main/java/com/replaymod/core/versions/MCVer.java @@ -397,7 +397,9 @@ public class MCVer { } public static void pushMatrix() { - //#if MC>=11700 + //#if MC>=12006 + //$$ RenderSystem.getModelViewStack().pushMatrix(); + //#elseif MC>=11700 //$$ RenderSystem.getModelViewStack().push(); //#else GlStateManager.pushMatrix(); @@ -406,7 +408,11 @@ public class MCVer { public static void popMatrix() { //#if MC>=11700 + //#if MC>=12006 + //$$ RenderSystem.getModelViewStack().popMatrix(); + //#else //$$ RenderSystem.getModelViewStack().pop(); + //#endif //$$ RenderSystem.applyModelViewMatrix(); //#else GlStateManager.popMatrix(); diff --git a/src/main/java/com/replaymod/core/versions/Patterns.java b/src/main/java/com/replaymod/core/versions/Patterns.java index 3475551c..1d7e7aec 100644 --- a/src/main/java/com/replaymod/core/versions/Patterns.java +++ b/src/main/java/com/replaymod/core/versions/Patterns.java @@ -21,6 +21,7 @@ import net.minecraft.network.NetworkSide; import net.minecraft.network.NetworkState; import net.minecraft.network.Packet; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; +import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerListS2CPacket; import net.minecraft.resource.Resource; import net.minecraft.resource.ResourceManager; @@ -576,7 +577,9 @@ class Patterns { @Pattern private static void GL11_glRotatef(float angle, float x, float y, float z) { - //#if MC>=11700 + //#if MC>=12006 + //$$ com.mojang.blaze3d.systems.RenderSystem.getModelViewStack().rotate(com.replaymod.core.versions.MCVer.quaternion(angle, new org.joml.Vector3f(x, y, z))); + //#elseif MC>=11700 //$$ com.mojang.blaze3d.systems.RenderSystem.getModelViewStack().multiply(com.replaymod.core.versions.MCVer.quaternion(angle, new net.minecraft.util.math.Vec3f(x, y, z))); //#else GL11.glRotatef(angle, x, y, z); @@ -917,7 +920,9 @@ class Patterns { @Pattern public Object channel(CustomPayloadS2CPacket packet) { - //#if MC>=12002 + //#if MC>=12006 + //$$ return packet.payload().getId().id(); + //#elseif MC>=12002 //$$ return packet.payload().id(); //#else return packet.getChannel(); @@ -925,6 +930,9 @@ class Patterns { } //#if MC>=10904 + //#if MC>=12006 + //$$ @Pattern public void getPacketId() {} + //#else @Pattern public Integer getPacketId(NetworkState state, NetworkSide side, Packet packet) throws Exception { //#if MC>=12002 @@ -933,6 +941,7 @@ class Patterns { return state.getPacketId(side, packet); //#endif } + //#endif @Pattern public int UnloadChunkPacket_getX(UnloadChunkS2CPacket packet) { @@ -983,4 +992,13 @@ class Patterns { return mc.options.debugEnabled; //#endif } + + @Pattern + public Text getMessage(DisconnectS2CPacket packet) { + //#if MC>=12006 + //$$ return packet.reason(); + //#else + return packet.getReason(); + //#endif + } } diff --git a/src/main/java/com/replaymod/recording/ReplayModRecording.java b/src/main/java/com/replaymod/recording/ReplayModRecording.java index ee8fbaac..edbba5fe 100644 --- a/src/main/java/com/replaymod/recording/ReplayModRecording.java +++ b/src/main/java/com/replaymod/recording/ReplayModRecording.java @@ -16,6 +16,10 @@ import net.minecraft.network.ClientConnection; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +//#if MC>=12006 +//$$ import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry; +//#endif + //#if FABRIC>=1 //#if MC>=11700 //$$ import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; @@ -73,7 +77,11 @@ public class ReplayModRecording implements Module { new GuiHandler(core).register(); //#if FABRIC>=1 - //#if MC>=11700 + //#if MC>=12006 + //$$ PayloadTypeRegistry.configurationS2C().register(Restrictions.ID, Restrictions.CODEC); + //$$ PayloadTypeRegistry.playS2C().register(Restrictions.ID, Restrictions.CODEC); + //$$ ClientPlayNetworking.registerGlobalReceiver(Restrictions.ID, (payload, context) -> {}); + //#elseif MC>=11700 //$$ ClientPlayNetworking.registerGlobalReceiver(Restrictions.PLUGIN_CHANNEL, (client, handler, buf, resp) -> {}); //#else ClientSidePacketRegistry.INSTANCE.register(Restrictions.PLUGIN_CHANNEL, (packetContext, packetByteBuf) -> {}); diff --git a/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java b/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java index 2635860b..23814307 100644 --- a/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java +++ b/src/main/java/com/replaymod/recording/handler/ConnectionEventHandler.java @@ -156,6 +156,11 @@ public class ConnectionEventHandler { Channel channel = ((NetworkManagerAccessor) networkManager).getChannel(); packetListener = new PacketListener(core, channel, outputPath, replayFile, metaData); + + //#if MC>=12005 + //$$ channel.pipeline().addBefore("inbound_config", PacketListener.RAW_RECORDER_KEY, packetListener); + //$$ channel.pipeline().addAfter("inbound_config", PacketListener.DECODED_RECORDER_KEY, packetListener.new DecodedPacketListener()); + //#else if (channel.pipeline().get(PacketListener.DECODER_KEY) != null) { // Regular channel, we'll inject our recorder directly before the decoder channel.pipeline().addBefore(PacketListener.DECODER_KEY, PacketListener.RAW_RECORDER_KEY, packetListener); @@ -165,6 +170,7 @@ public class ConnectionEventHandler { channel.pipeline().addFirst(PacketListener.RAW_RECORDER_KEY, packetListener); channel.pipeline().addAfter(PacketListener.RAW_RECORDER_KEY, PacketListener.DECODED_RECORDER_KEY, packetListener.new DecodedPacketListener()); } + //#endif recordingEventHandler = new RecordingEventHandler(packetListener); recordingEventHandler.register(); diff --git a/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java b/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java index 8d948069..93596d7a 100644 --- a/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java +++ b/src/main/java/com/replaymod/recording/handler/RecordingEventHandler.java @@ -73,7 +73,12 @@ public class RecordingEventHandler extends EventRegistrations { private final PacketListener packetListener; private Double lastX, lastY, lastZ; - private final List playerItems = DefaultedList.ofSize(6, ItemStack.EMPTY); + //#if MC>=10904 + private static final int EQUIPMENT_SLOTS = EquipmentSlot.values().length; + //#else + //$$ private static final int EQUIPMENT_SLOTS = 5; + //#endif + private final List playerItems = DefaultedList.ofSize(EQUIPMENT_SLOTS, ItemStack.EMPTY); private int ticksSinceLastCorrection; private boolean wasSleeping; private int lastRiding = -1; @@ -279,7 +284,7 @@ public class RecordingEventHandler extends EventRegistrations { ItemStack stack = player.getEquippedStack(slot); int index = slot.ordinal(); //#else - //$$ for (int slot = 0; slot < 5; slot++) { + //$$ for (int slot = 0; slot < EQUIPMENT_SLOTS; slot++) { //$$ ItemStack stack = player.getEquipmentInSlot(slot); //$$ int index = slot; //#endif diff --git a/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerConfigClient.java b/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerConfigClient.java new file mode 100644 index 00000000..b40cfd98 --- /dev/null +++ b/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerConfigClient.java @@ -0,0 +1 @@ +// 1.20.6 and above diff --git a/src/main/java/com/replaymod/recording/packet/PacketListener.java b/src/main/java/com/replaymod/recording/packet/PacketListener.java index 07027547..ca4b47ae 100644 --- a/src/main/java/com/replaymod/recording/packet/PacketListener.java +++ b/src/main/java/com/replaymod/recording/packet/PacketListener.java @@ -23,9 +23,11 @@ import de.johni0702.minecraft.gui.container.VanillaGuiScreen; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; +import io.netty.channel.ChannelDuplexHandler; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.channel.ChannelPromise; import io.netty.util.AttributeKey; import net.minecraft.client.MinecraftClient; import net.minecraft.network.ClientConnection; @@ -41,6 +43,15 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +//#if MC>=12006 +//$$ import com.replaymod.recording.mixin.DecoderHandlerAccessor; +//$$ import net.minecraft.network.NetworkState; +//$$ import net.minecraft.network.handler.DecoderHandler; +//$$ import net.minecraft.network.handler.NetworkStateTransitions; +//$$ import net.minecraft.network.packet.s2c.config.ReadyS2CPacket; +//$$ import net.minecraft.network.state.LoginStates; +//#endif + //#if MC>=12002 //$$ import net.minecraft.entity.EntityType; //$$ import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket; @@ -307,6 +318,9 @@ 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>=12006 + //$$ // No longer applies. MC now encodes packets even for the integrated server connection. + //#else //#if MC>=11904 //#if MC>=12002 //$$ PacketBundleHandler bundleHandler = ctx.channel().attr(ClientConnection.CLIENTBOUND_PROTOCOL_KEY).get().getBundler(); @@ -330,6 +344,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter { //#else packet = encodeMcPacket(connectionState, (net.minecraft.network.Packet) msg); //#endif + //#endif } currentRawPacket = packet; @@ -344,7 +359,13 @@ public class PacketListener extends ChannelInboundHandlerAdapter { } private NetworkState getConnectionState() { - //#if MC>=12002 + //#if MC>=12006 + //$$ var decoderHandler = (DecoderHandlerAccessor) channel.pipeline().get(DecoderHandler.class); + //$$ if (decoderHandler == null) { + //$$ return NetworkPhase.LOGIN; + //$$ } + //$$ return decoderHandler.getState().id(); + //#elseif MC>=12002 //$$ AttributeKey> key = ClientConnection.CLIENTBOUND_PROTOCOL_KEY; //$$ return channel.attr(key).get().getState(); //#else @@ -353,7 +374,25 @@ public class PacketListener extends ChannelInboundHandlerAdapter { //#endif } - private static Packet encodeMcPacket(NetworkState connectionState, net.minecraft.network.Packet packet) throws Exception { + private Packet encodeMcPacket(NetworkState connectionState, net.minecraft.network.Packet packet) throws Exception { + //#if MC>=12006 + //$$ var byteBuf = Unpooled.buffer(); + //$$ try { + //$$ NetworkState state; + //$$ if (connectionState == NetworkPhase.LOGIN) { + //$$ // Special case for our initial LoginSuccess packet which we only save after the pipeline has already + //$$ // started to transition to the next phase, so we can't just use its DecoderHandler (and luckily we + //$$ // also don't need it). + //$$ state = LoginStates.S2C; + //$$ } else { + //$$ state = ((DecoderHandlerAccessor) channel.pipeline().get(DecoderHandler.class)).getState(); + //$$ } + //$$ state.codec().encode(byteBuf, packet); + //$$ return decodePacket(state.id(), byteBuf); + //$$ } finally { + //$$ byteBuf.release(); + //$$ } + //#else //#if MC>=10800 Integer packetId = connectionState.getPacketId(NetworkSide.CLIENTBOUND, packet); //#else @@ -377,6 +416,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter { } finally { byteBuf.release(); } + //#endif } private static Packet decodePacket(NetworkState connectionState, ByteBuf buf) { @@ -434,7 +474,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter { return resourcePackRecorder; } - public class DecodedPacketListener extends ChannelInboundHandlerAdapter { + public class DecodedPacketListener extends ChannelDuplexHandler { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { @@ -482,6 +522,17 @@ public class PacketListener extends ChannelInboundHandlerAdapter { return; } + //#if MC>=12006 + //$$ // Special case: We need to inject another packet before this one, and we can only construct that + //$$ // packet on the main thread, so we'll skip saving this packet here and then manually re-add it after + //$$ // that other packet has been injected. + //$$ // See MixinNetHandlerConfigClient. + //$$ if (msg instanceof ReadyS2CPacket) { + //$$ super.channelRead(ctx, msg); + //$$ return; + //$$ } + //#endif + if (currentRawPacket != null) { save(currentRawPacket); currentRawPacket = null; @@ -489,5 +540,21 @@ public class PacketListener extends ChannelInboundHandlerAdapter { super.channelRead(ctx, msg); } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + //#if MC>=12006 + //$$ if (msg instanceof NetworkStateTransitions.DecoderTransitioner) { + //$$ // We need our DecodedPacketListener to stay right behind the decoder, however MC will on network state + //$$ // transitions insert the bundler in the middle, so we need to re-position our handler in that case. + //$$ msg = ((NetworkStateTransitions.DecoderTransitioner) msg).andThen(context -> { + //$$ context.pipeline().remove(this); + //$$ context.pipeline().addAfter(DECODER_KEY, DECODED_RECORDER_KEY, new DecodedPacketListener()); + //$$ }); + //$$ } + //#endif + + super.write(ctx, msg, promise); + } } } diff --git a/src/main/java/com/replaymod/render/blend/Util.java b/src/main/java/com/replaymod/render/blend/Util.java index 78138995..64f33b27 100644 --- a/src/main/java/com/replaymod/render/blend/Util.java +++ b/src/main/java/com/replaymod/render/blend/Util.java @@ -183,6 +183,9 @@ public class Util { } public static String getTileEntityId(BlockEntity tileEntity) { + //#if MC>=12006 + //$$ return net.minecraft.block.entity.BlockEntityType.getId(tileEntity.getType()).toString(); + //#else //#if MC>=11800 //$$ NbtCompound nbt = tileEntity.createNbt(); //#else @@ -194,6 +197,7 @@ public class Util { //#endif //#endif return nbt.getString("id"); + //#endif } public interface IOCallable { diff --git a/src/main/java/com/replaymod/render/gui/GuiVideoRenderer.java b/src/main/java/com/replaymod/render/gui/GuiVideoRenderer.java index 448cf5d0..72d5a9d3 100644 --- a/src/main/java/com/replaymod/render/gui/GuiVideoRenderer.java +++ b/src/main/java/com/replaymod/render/gui/GuiVideoRenderer.java @@ -112,7 +112,13 @@ public class GuiVideoRenderer extends GuiScreen implements Tickable { size(contentPanel, width - 10, height - 10); } }); + // FIXME default background doesn't work during rendering because the blur effect relies on the framebuffer + //#if MC>=12006 + //$$ setBackground(Background.NONE); + //$$ setBackgroundColor(new de.johni0702.minecraft.gui.utils.lwjgl.Color(32, 32, 32)); + //#else setBackground(Background.DIRT); + //#endif } public GuiVideoRenderer(VideoRenderer renderer) { diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyColorSky.java b/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyColorSky.java index 28872496..a98c4ff4 100644 --- a/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyColorSky.java +++ b/src/main/java/com/replaymod/render/mixin/Mixin_ChromaKeyColorSky.java @@ -22,7 +22,9 @@ public abstract class Mixin_ChromaKeyColorSky { //#if MC>=11800 //$$ @Inject( - //#if MC>=11802 + //#if MC>=12005 + //$$ method = "renderSky(Lorg/joml/Matrix4f;Lorg/joml/Matrix4f;FLnet/minecraft/client/render/Camera;ZLjava/lang/Runnable;)V", + //#elseif MC>=11802 //$$ method = "renderSky(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/util/math/Matrix4f;FLnet/minecraft/client/render/Camera;ZLjava/lang/Runnable;)V", //#else //$$ method = "renderSky(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/util/math/Matrix4f;FLjava/lang/Runnable;)V", diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Camera.java b/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Camera.java index b9726a4c..ae6feff1 100644 --- a/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Camera.java +++ b/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Camera.java @@ -11,7 +11,11 @@ import org.spongepowered.asm.mixin.injection.ModifyArg; public abstract class Mixin_Omnidirectional_Camera implements EntityRendererHandler.IEntityRenderer { private static final String METHOD = "getBasicProjectionMatrix"; //#if MC>=11903 + //#if MC>=12005 + //$$ private static final String TARGET = "Lorg/joml/Matrix4f;perspective(FFFF)Lorg/joml/Matrix4f;"; + //#else //$$ private static final String TARGET = "Lorg/joml/Matrix4f;setPerspective(FFFF)Lorg/joml/Matrix4f;"; + //#endif //$$ private static final boolean TARGET_REMAP = false; //$$ private static final float OMNIDIRECTIONAL_FOV = (float) Math.PI / 2; //#else diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Rotation.java b/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Rotation.java index e7d567c7..f318342f 100644 --- a/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Rotation.java +++ b/src/main/java/com/replaymod/render/mixin/Mixin_Omnidirectional_Rotation.java @@ -7,6 +7,11 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//#if MC>=12005 +//$$ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +//$$ import org.joml.Matrix4f; +//#endif + //#if MC>=11500 import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.Vector3f; @@ -30,6 +35,10 @@ public abstract class Mixin_Omnidirectional_Rotation { return ((EntityRendererHandler.IEntityRenderer) getMinecraft().gameRenderer).replayModRender_getHandler(); } + //#if MC>=12005 + //$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotationXYZ(FFF)Lorg/joml/Matrix4f;")) + //$$ private Matrix4f replayModRender_setupCubicFrameRotation(Matrix4f matrix) { + //#else //#if MC>=11500 @Inject(method = "renderWorld", at = @At("HEAD")) //#else @@ -47,6 +56,7 @@ public abstract class Mixin_Omnidirectional_Rotation { //#endif CallbackInfo ci ) { + //#endif if (getHandler() != null && getHandler().data instanceof CubicOpenGlFrameCapturer.Data) { CubicOpenGlFrameCapturer.Data data = (CubicOpenGlFrameCapturer.Data) getHandler().data; float angle = 0; @@ -78,7 +88,9 @@ public abstract class Mixin_Omnidirectional_Rotation { x = 1; break; } - //#if MC>=11500 + //#if MC>=12005 + //$$ matrix.rotateLocal(angle * (float) Math.PI / 180f, x, y, 0); + //#elseif MC>=11500 matrixStack.multiply(new Vector3f(x, y, 0).getDegreesQuaternion(angle)); //#else //$$ GL11.glRotatef(angle, x, y, 0); @@ -96,5 +108,8 @@ public abstract class Mixin_Omnidirectional_Rotation { //#endif //$$ } //#endif + //#if MC>=12005 + //$$ return matrix; + //#endif } } diff --git a/src/main/java/com/replaymod/render/mixin/Mixin_Stereoscopic_Camera.java b/src/main/java/com/replaymod/render/mixin/Mixin_Stereoscopic_Camera.java index 885608e3..2b744a8e 100644 --- a/src/main/java/com/replaymod/render/mixin/Mixin_Stereoscopic_Camera.java +++ b/src/main/java/com/replaymod/render/mixin/Mixin_Stereoscopic_Camera.java @@ -11,6 +11,11 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +//#if MC>=12005 +//$$ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +//$$ import org.joml.Matrix4f; +//#endif + @Mixin(GameRenderer.class) public abstract class Mixin_Stereoscopic_Camera implements EntityRendererHandler.IEntityRenderer { @Inject(method = "getBasicProjectionMatrix", at = @At("RETURN"), cancellable = true) @@ -29,14 +34,30 @@ public abstract class Mixin_Stereoscopic_Camera implements EntityRendererHandler } } + //#if MC>=12005 + //$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotationXYZ(FFF)Lorg/joml/Matrix4f;")) + //$$ private Matrix4f replayModRender_setupStereoscopicProjection(Matrix4f matrix) { + //#else @Inject(method = "renderWorld", at = @At("HEAD")) private void replayModRender_setupStereoscopicProjection(float partialTicks, long frameStartNano, MatrixStack matrixStack, CallbackInfo ci) { + //#endif if (replayModRender_getHandler() != null) { if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.LEFT_EYE) { - matrixStack.translate(0.1, 0, 0); + //#if MC>=12005 + //$$ matrix.translateLocal(0.1f, 0, 0); + //#else + matrixStack.translate(0.1f, 0, 0); + //#endif } else if (replayModRender_getHandler().data == StereoscopicOpenGlFrameCapturer.Data.RIGHT_EYE) { - matrixStack.translate(-0.1, 0, 0); + //#if MC>=12005 + //$$ matrix.translateLocal(-0.1f, 0, 0); + //#else + matrixStack.translate(-0.1f, 0, 0); + //#endif } } + //#if MC>=12005 + //$$ return matrix; + //#endif } } diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index 09743225..5d508dc6 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -512,9 +512,14 @@ public class VideoRenderer implements RenderInfo { //$$ , VertexSorter.BY_Z //#endif //$$ ); + //#if MC>=12006 + //$$ org.joml.Matrix4fStack matrixStack = RenderSystem.getModelViewStack(); + //$$ matrixStack.translation(0, 0, -2000); + //#else //$$ MatrixStack matrixStack = RenderSystem.getModelViewStack(); //$$ matrixStack.loadIdentity(); //$$ matrixStack.translate(0, 0, -2000); + //#endif //$$ RenderSystem.applyModelViewMatrix(); //$$ DiffuseLighting.enableGuiDepthLighting(); //#else @@ -558,13 +563,17 @@ public class VideoRenderer implements RenderInfo { int mouseX = (int) mc.mouse.getX() * window.getScaledWidth() / Math.max(window.getWidth(), 1); int mouseY = (int) mc.mouse.getY() * window.getScaledHeight() / Math.max(window.getHeight(), 1); + //#if MC>=12000 + //$$ DrawContext drawContext = new DrawContext(mc, mc.getBufferBuilders().getEntityVertexConsumers()); + //#endif + if (mc.getOverlay() != null) { Screen orgScreen = mc.currentScreen; try { mc.currentScreen = gui.toMinecraft(); mc.getOverlay().render( //#if MC>=12000 - //$$ new DrawContext(mc, mc.getBufferBuilders().getEntityVertexConsumers()), + //$$ drawContext, //#elseif MC>=11600 new MatrixStack(), //#endif @@ -582,6 +591,9 @@ public class VideoRenderer implements RenderInfo { //#endif mouseX, mouseY, 0); } + //#if MC>=12000 + //$$ drawContext.draw(); + //#endif //#else //$$ int mouseX = Mouse.getX() * window.getScaledWidth() / mc.displayWidth; //$$ int mouseY = window.getScaledHeight() - Mouse.getY() * window.getScaledHeight() / mc.displayHeight - 1; diff --git a/src/main/java/com/replaymod/replay/FullReplaySender.java b/src/main/java/com/replaymod/replay/FullReplaySender.java index 2ee44132..ca89ee9d 100644 --- a/src/main/java/com/replaymod/replay/FullReplaySender.java +++ b/src/main/java/com/replaymod/replay/FullReplaySender.java @@ -675,6 +675,9 @@ public class FullReplaySender extends ChannelInboundHandlerAdapter implements Re //$$ packet.showDeathScreen(), //$$ packet.doLimitedCrafting(), //$$ withSpectatorMode(packet.commonPlayerSpawnInfo()) + //#if MC>=12006 + //$$ , packet.enforcesSecureChat() + //#endif //#else //#if MC>=11800 //$$ packet.hardcore(), diff --git a/src/main/java/com/replaymod/replay/NoGuiScreenshot.java b/src/main/java/com/replaymod/replay/NoGuiScreenshot.java index 69a995b6..04a659da 100644 --- a/src/main/java/com/replaymod/replay/NoGuiScreenshot.java +++ b/src/main/java/com/replaymod/replay/NoGuiScreenshot.java @@ -74,7 +74,9 @@ public class NoGuiScreenshot { //#endif float tickDelta = mc.getTickDelta(); - //#if MC>=11500 + //#if MC>=12006 + //$$ mc.gameRenderer.renderWorld(tickDelta, System.nanoTime()); + //#elseif MC>=11500 mc.gameRenderer.renderWorld(tickDelta, System.nanoTime(), new MatrixStack()); //#else //#if MC>=11400 diff --git a/src/main/java/com/replaymod/replay/ReplayHandler.java b/src/main/java/com/replaymod/replay/ReplayHandler.java index dcd259bd..bf638b00 100644 --- a/src/main/java/com/replaymod/replay/ReplayHandler.java +++ b/src/main/java/com/replaymod/replay/ReplayHandler.java @@ -46,6 +46,11 @@ import net.minecraft.network.ClientConnection; import java.io.IOException; import java.util.*; +//#if MC>=12006 +//$$ import net.minecraft.network.handler.NetworkStateTransitions; +//$$ import net.minecraft.network.state.LoginStates; +//#endif + //#if MC>=12003 //$$ import net.minecraft.client.resource.server.ServerResourcePackManager; //#endif @@ -325,6 +330,10 @@ public class ReplayHandler { quickReplaySender.setChannel(channel); fullReplaySender.setChannel(channel); + //#if MC>=12006 + //$$ channel.pipeline().addLast("inbound_config", new NetworkStateTransitions.InboundConfigurer()); + //$$ channel.pipeline().addLast("outbound_config", new NetworkStateTransitions.OutboundConfigurer()); + //#else //#if MC>=12002 //$$ channel.pipeline().addLast("decoder", new DecoderHandler(ClientConnection.CLIENTBOUND_PROTOCOL_KEY)); //$$ channel.pipeline().addLast("encoder", new PacketEncoder(ClientConnection.SERVERBOUND_PROTOCOL_KEY)); @@ -337,12 +346,19 @@ public class ReplayHandler { //#elseif MC>=11904 //$$ channel.pipeline().addLast("bundler", new PacketBundler(NetworkSide.CLIENTBOUND)); //#endif + //#endif channel.pipeline().addLast(PACKET_HANDLER_NAME, quickMode ? quickReplaySender : fullReplaySender); 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. + //#if MC>=12006 + //$$ networkManager.transitionInbound(LoginStates.S2C, new ClientLoginNetworkHandler( + //$$ networkManager, mc, null, null, false, null, it -> {}, null + //$$ )); + //$$ networkManager.transitionOutbound(LoginStates.C2S); + //#else //#if MC>=12002 //$$ channel.attr(ClientConnection.CLIENTBOUND_PROTOCOL_KEY).set(NetworkState.LOGIN.getHandler(NetworkSide.CLIENTBOUND)); //$$ channel.attr(ClientConnection.SERVERBOUND_PROTOCOL_KEY).set(NetworkState.LOGIN.getHandler(NetworkSide.SERVERBOUND)); @@ -363,6 +379,7 @@ public class ReplayHandler { , it -> {} //#endif )); + //#endif //#if MC>=11400 ((MinecraftAccessor) mc).setConnection(networkManager); @@ -657,7 +674,28 @@ public class ReplayHandler { long diff = targetTime - (replaySender.isHurrying() ? replaySender.getDesiredTimestamp() : replaySender.currentTimeStamp()); if (diff != 0) { if (diff > 0 && diff < 5000) { // Small difference and no time travel - replaySender.jumpToTime(targetTime); + if (replaySender.paused()) { + replaySender.setSyncModeAndWait(); + do { + replaySender.sendPacketsTill(targetTime); + targetTime += 500; + } while (mc.player == null || mc.currentScreen instanceof DownloadingTerrainScreen); + replaySender.setAsyncMode(true); + + for (int i = 0; i < Math.min(diff / 50, 3); i++) { + //#if MC>=10800 && MC<11400 + //$$ try { + //$$ mc.runTick(); + //$$ } catch (IOException e) { + //$$ e.printStackTrace(); // This should never be thrown but whatever + //$$ } + //#else + mc.tick(); + //#endif + } + } else { + replaySender.jumpToTime(targetTime); + } } else { // We either have to restart the replay or send a significant amount of packets // Render our please-wait-screen GuiScreen guiScreen = new GuiScreen(); @@ -696,9 +734,14 @@ public class ReplayHandler { //$$ , VertexSorter.BY_Z //#endif //$$ ); + //#if MC>=12006 + //$$ org.joml.Matrix4fStack matrixStack = RenderSystem.getModelViewStack(); + //$$ matrixStack.translation(0, 0, -2000); + //#else //$$ MatrixStack matrixStack = RenderSystem.getModelViewStack(); //$$ matrixStack.loadIdentity(); //$$ matrixStack.translate(0, 0, -2000); + //#endif //$$ RenderSystem.applyModelViewMatrix(); //$$ DiffuseLighting.enableGuiDepthLighting(); //#else @@ -719,7 +762,9 @@ public class ReplayHandler { guiScreen.toMinecraft().init(mc, window.getScaledWidth(), window.getScaledHeight()); //#if MC>=12000 - //$$ guiScreen.toMinecraft().render(new DrawContext(mc, mc.getBufferBuilders().getEntityVertexConsumers()), 0, 0, 0); + //$$ DrawContext drawContext = new DrawContext(mc, mc.getBufferBuilders().getEntityVertexConsumers()); + //$$ guiScreen.toMinecraft().render(drawContext, 0, 0, 0); + //$$ drawContext.draw(); //#elseif MC>=11600 guiScreen.toMinecraft().render(new MatrixStack(), 0, 0, 0); //#else diff --git a/src/main/java/com/replaymod/replay/mixin/MixinCamera.java b/src/main/java/com/replaymod/replay/mixin/MixinCamera.java index 7c1166d6..501b15ab 100644 --- a/src/main/java/com/replaymod/replay/mixin/MixinCamera.java +++ b/src/main/java/com/replaymod/replay/mixin/MixinCamera.java @@ -13,9 +13,18 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//#if MC>=12005 +//$$ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +//$$ import org.joml.Matrix4f; +//#endif + @Mixin(GameRenderer.class) public class MixinCamera { @Shadow @Final private MinecraftClient client; + //#if MC>=12005 + //$$ @ModifyExpressionValue(method = "renderWorld", at = @At(value = "INVOKE", target = "Lorg/joml/Matrix4f;rotationXYZ(FFF)Lorg/joml/Matrix4f;")) + //$$ private Matrix4f applyRoll(Matrix4f matrix) { + //#else @Inject( method = "renderWorld", at = @At( @@ -24,9 +33,17 @@ public class MixinCamera { ) ) private void applyRoll(float float_1, long long_1, MatrixStack matrixStack, CallbackInfo ci) { + //#endif Entity entity = this.client.getCameraEntity() == null ? this.client.player : this.client.getCameraEntity(); if (entity instanceof CameraEntity) { + //#if MC>=12005 + //$$ matrix.rotateLocal(((CameraEntity) entity).roll * (float) Math.PI / 180f, 0f, 0f, 1f); + //#else matrixStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(((CameraEntity) entity).roll)); + //#endif } + //#if MC>=12005 + //$$ return matrix; + //#endif } } diff --git a/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java b/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java index 50782934..d8eb78e6 100644 --- a/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java +++ b/src/main/java/com/replaymod/simplepathing/preview/PathPreviewRenderer.java @@ -108,7 +108,11 @@ public class PathPreviewRenderer extends EventRegistrations { //#endif //#if MC>=11700 + //#if MC>=12006 + //$$ RenderSystem.getModelViewStack().mul(matrixStack.peek().getPositionMatrix()); + //#else //$$ RenderSystem.getModelViewStack().method_34425(matrixStack.peek().getModel()); + //#endif //$$ RenderSystem.applyModelViewMatrix(); //#elseif MC>=11500 RenderSystem.multMatrix(matrixStack.peek().getModel()); diff --git a/src/main/resources/mixins.recording.replaymod.json b/src/main/resources/mixins.recording.replaymod.json index df7f09ea..db885b0f 100644 --- a/src/main/resources/mixins.recording.replaymod.json +++ b/src/main/resources/mixins.recording.replaymod.json @@ -6,6 +6,9 @@ "client": [ "AddServerScreenAccessor", "ClientLoginNetworkHandlerAccessor", + //#if MC>=12006 + //$$ "DecoderHandlerAccessor", + //#endif "EntityLivingBaseAccessor", "IntegratedServerAccessor", "NetworkManagerAccessor", @@ -31,6 +34,9 @@ //$$ "MixinGuiScreen", //$$ "MixinS26PacketMapChunkBulk", //#endif + //#if MC>=12006 + //$$ "MixinNetHandlerConfigClient", + //#endif "MixinNetHandlerLoginClient", "MixinNetHandlerPlayClient", //#if MC<11400 diff --git a/versions/1.20.2/src/main/java/com/replaymod/render/mixin/Mixin_ForceChunkLoading.java b/versions/1.20.2/src/main/java/com/replaymod/render/mixin/Mixin_ForceChunkLoading.java index 4843023e..50b4c372 100644 --- a/versions/1.20.2/src/main/java/com/replaymod/render/mixin/Mixin_ForceChunkLoading.java +++ b/versions/1.20.2/src/main/java/com/replaymod/render/mixin/Mixin_ForceChunkLoading.java @@ -1,5 +1,6 @@ package com.replaymod.render.mixin; +import com.llamalad7.mixinextras.sugar.Local; import com.replaymod.render.hooks.ForceChunkLoadingHook; import com.replaymod.render.hooks.IForceChunkLoading; import com.replaymod.render.utils.FlawlessFrames; @@ -50,7 +51,7 @@ public abstract class Mixin_ForceChunkLoading implements IForceChunkLoading { @Shadow protected abstract void applyFrustum(Frustum par1); @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;setupTerrain(Lnet/minecraft/client/render/Camera;Lnet/minecraft/client/render/Frustum;ZZ)V")) - private void forceAllChunks(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) { + private void forceAllChunks(CallbackInfo ci, @Local(argsOnly = true) Camera camera) { if (replayModRender_hook == null) { return; } diff --git a/versions/1.20.6/.gitkeep b/versions/1.20.6/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/versions/1.20.6/src/main/java/com/replaymod/recording/mixin/DecoderHandlerAccessor.java b/versions/1.20.6/src/main/java/com/replaymod/recording/mixin/DecoderHandlerAccessor.java new file mode 100644 index 00000000..5fd091a4 --- /dev/null +++ b/versions/1.20.6/src/main/java/com/replaymod/recording/mixin/DecoderHandlerAccessor.java @@ -0,0 +1,16 @@ +package com.replaymod.recording.mixin; + +import net.minecraft.network.NetworkState; +import net.minecraft.network.handler.DecoderHandler; +import net.minecraft.network.listener.PacketListener; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import javax.annotation.Nonnull; + +@Mixin(DecoderHandler.class) +public interface DecoderHandlerAccessor { + @Accessor + @Nonnull + NetworkState getState(); +} diff --git a/versions/1.20.6/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerConfigClient.java b/versions/1.20.6/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerConfigClient.java new file mode 100644 index 00000000..58edc597 --- /dev/null +++ b/versions/1.20.6/src/main/java/com/replaymod/recording/mixin/MixinNetHandlerConfigClient.java @@ -0,0 +1,62 @@ +package com.replaymod.recording.mixin; + +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.serialization.Codec; +import com.replaymod.core.versions.MCVer; +import com.replaymod.recording.ReplayModRecording; +import com.replaymod.recording.packet.PacketListener; +import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State; +import com.replaymod.replaystudio.protocol.Packet; +import com.replaymod.replaystudio.protocol.PacketType; +import com.replaymod.replaystudio.protocol.PacketTypeRegistry; +import com.replaymod.replaystudio.protocol.packets.PacketEnabledPacksData; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.minecraft.client.network.ClientConfigurationNetworkHandler; +import net.minecraft.nbt.NbtOps; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.registry.DynamicRegistryManager; +import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.world.dimension.DimensionType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Map; + +@Mixin(ClientConfigurationNetworkHandler.class) +public abstract class MixinNetHandlerConfigClient { + @Inject(method = "onReady", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;transitionInbound(Lnet/minecraft/network/NetworkState;Lnet/minecraft/network/listener/PacketListener;)V")) + public void recordEnabledPackData(CallbackInfo ci, @Local DynamicRegistryManager.Immutable registryManager) { + PacketListener packetListener = ReplayModRecording.instance.getConnectionEventHandler().getPacketListener(); + if (packetListener == null) return; + + ByteBuf byteBuf = Unpooled.buffer(); + PacketByteBuf buf = new PacketByteBuf(byteBuf); + buf.writeString(PacketEnabledPacksData.ID); + buf.writeVarInt(1); + write(buf, registryManager.get(RegistryKeys.DIMENSION_TYPE), DimensionType.CODEC); + + byte[] bytes = new byte[byteBuf.readableBytes()]; + byteBuf.readBytes(bytes); + byteBuf.release(); + + PacketTypeRegistry registry = MCVer.getPacketTypeRegistry(State.CONFIGURATION); + packetListener.save(new Packet(registry, PacketType.ConfigCustomPayload, com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(bytes))); + packetListener.save(new Packet(registry, PacketType.ConfigFinish)); + } + + @Unique + private void write(PacketByteBuf buf, Registry registry, Codec codec) { + buf.writeString(registry.getKey().getValue().toString()); + buf.writeVarInt(registry.size()); + for (Map.Entry, T> entry : registry.getEntrySet()) { + buf.writeString(entry.getKey().getValue().toString()); + buf.writeNbt(codec.encodeStart(NbtOps.INSTANCE, entry.getValue()).getOrThrow()); + } + } +}