Port to 1.20.2

This commit is contained in:
Jonas Herzig
2023-11-27 18:34:19 +01:00
parent e8f9234bf0
commit b8ab7aa5a7
28 changed files with 526 additions and 60 deletions

View File

@@ -264,6 +264,7 @@ dependencies {
11903: '1.19.3-rc3', 11903: '1.19.3-rc3',
11904: '1.19.4', 11904: '1.19.4',
12001: '1.20.1', 12001: '1.20.1',
12002: '1.20.2',
][mcVersion] ][mcVersion]
mappings 'net.fabricmc:yarn:' + [ mappings 'net.fabricmc:yarn:' + [
11404: '1.14.4+build.16', 11404: '1.14.4+build.16',
@@ -281,6 +282,7 @@ dependencies {
11903: '1.19.3-rc3+build.1:v2', 11903: '1.19.3-rc3+build.1:v2',
11904: '1.19.4+build.1:v2', 11904: '1.19.4+build.1:v2',
12001: '1.20.1+build.2:v2', 12001: '1.20.1+build.2:v2',
12002: '1.20.2+build.4:v2',
][mcVersion] ][mcVersion]
modImplementation 'net.fabricmc:fabric-loader:0.14.11' modImplementation 'net.fabricmc:fabric-loader:0.14.11'
def fabricApiVersion = [ def fabricApiVersion = [
@@ -299,6 +301,7 @@ dependencies {
11903: '0.68.1+1.19.3', 11903: '0.68.1+1.19.3',
11904: '0.76.0+1.19.4', 11904: '0.76.0+1.19.4',
12001: '0.83.1+1.20.1', 12001: '0.83.1+1.20.1',
12002: '0.90.7+1.20.2',
][mcVersion] ][mcVersion]
def fabricApiModules = [ def fabricApiModules = [
"api-base", "api-base",
@@ -379,7 +382,7 @@ dependencies {
shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8' shadow 'com.github.ReplayMod.JavaBlend:2.79.0:a0696f8'
shadow "com.github.ReplayMod:ReplayStudio:a1e2b83", shadeExclusions shadow "com.github.ReplayMod:ReplayStudio:e7a8ff7", shadeExclusions
// FIXME this should be pulled in by ReplayStudio, and IntelliJ sees it, but javac for some reason does not // 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) implementation 'com.github.viaversion:opennbt:0a02214' // 2.0-SNAPSHOT (ViaVersion Edition)
@@ -390,7 +393,9 @@ dependencies {
shadow 'com.github.ReplayMod:lwjgl-utils:27dcd66' shadow 'com.github.ReplayMod:lwjgl-utils:27dcd66'
if (FABRIC) { if (FABRIC) {
if (mcVersion >= 12000) { if (mcVersion >= 12002) {
modImplementation 'com.terraformersmc:modmenu:8.0.0'
} else if (mcVersion >= 12000) {
modImplementation 'com.terraformersmc:modmenu:7.0.1' modImplementation 'com.terraformersmc:modmenu:7.0.1'
} else if (mcVersion >= 11904) { } else if (mcVersion >= 11904) {
modImplementation 'com.terraformersmc:modmenu:6.1.0-rc.4' modImplementation 'com.terraformersmc:modmenu:6.1.0-rc.4'

2
jGui

Submodule jGui updated: eb3297f5a6...d4f6bc60c9

View File

@@ -193,6 +193,7 @@ val doRelease by tasks.registering {
defaultTasks("bundleJar") defaultTasks("bundleJar")
preprocess { preprocess {
val mc12002 = createNode("1.20.2", 12002, "yarn")
val mc12001 = createNode("1.20.1", 12001, "yarn") val mc12001 = createNode("1.20.1", 12001, "yarn")
val mc11904 = createNode("1.19.4", 11904, "yarn") val mc11904 = createNode("1.19.4", 11904, "yarn")
val mc11903 = createNode("1.19.3", 11903, "yarn") val mc11903 = createNode("1.19.3", 11903, "yarn")
@@ -218,6 +219,7 @@ preprocess {
val mc10800 = createNode("1.8", 10800, "srg") val mc10800 = createNode("1.8", 10800, "srg")
val mc10710 = createNode("1.7.10", 10710, "srg") val mc10710 = createNode("1.7.10", 10710, "srg")
mc12002.link(mc12001)
mc12001.link(mc11904) mc12001.link(mc11904)
mc11904.link(mc11903) mc11904.link(mc11903)
mc11903.link(mc11902, file("versions/mapping-fabric-1.19.3-1.19.2.txt")) mc11903.link(mc11902, file("versions/mapping-fabric-1.19.3-1.19.2.txt"))

View File

@@ -38,6 +38,7 @@ val jGuiVersions = listOf(
"1.19.3", "1.19.3",
"1.19.4", "1.19.4",
"1.20.1", "1.20.1",
"1.20.2",
) )
val replayModVersions = listOf( val replayModVersions = listOf(
// "1.7.10", // "1.7.10",
@@ -64,6 +65,7 @@ val replayModVersions = listOf(
"1.19.3", "1.19.3",
"1.19.4", "1.19.4",
"1.20.1", "1.20.1",
"1.20.2",
) )
rootProject.buildFileName = "root.gradle.kts" rootProject.buildFileName = "root.gradle.kts"

View File

@@ -7,6 +7,7 @@ import com.replaymod.core.utils.Utils;
import com.replaymod.core.versions.MCVer; import com.replaymod.core.versions.MCVer;
import com.replaymod.replaystudio.io.ReplayInputStream; import com.replaymod.replaystudio.io.ReplayInputStream;
import com.replaymod.replaystudio.io.ReplayOutputStream; import com.replaymod.replaystudio.io.ReplayOutputStream;
import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ReplayMetaData; import com.replaymod.replaystudio.replay.ReplayMetaData;
import de.johni0702.minecraft.gui.container.AbstractGuiScreen; import de.johni0702.minecraft.gui.container.AbstractGuiScreen;
@@ -122,7 +123,7 @@ public class RestoreReplayGui extends AbstractGuiScreen<RestoreReplayGui> {
if (metaData != null && metaData.getDuration() == 0) { if (metaData != null && metaData.getDuration() == 0) {
// Try to restore replay duration // Try to restore replay duration
// We need to re-write the packet data in case there are any incomplete packets dangling at the end // We need to re-write the packet data in case there are any incomplete packets dangling at the end
try (ReplayInputStream in = replayFile.getPacketData(MCVer.getPacketTypeRegistry(true)); try (ReplayInputStream in = replayFile.getPacketData(MCVer.getPacketTypeRegistry(State.LOGIN));
ReplayOutputStream out = replayFile.writePacketData()) { ReplayOutputStream out = replayFile.writePacketData()) {
while (true) { while (true) {
// To prevent failing at un-parsable packets and to support recovery in minimal mode, // To prevent failing at un-parsable packets and to support recovery in minimal mode,

View File

@@ -6,7 +6,7 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
//#endif //#endif
//#if MC<=10710 //#if MC<=10710 || MC>=12002
//$$ import io.netty.buffer.Unpooled; //$$ import io.netty.buffer.Unpooled;
//#endif //#endif
@@ -26,7 +26,10 @@ public class Restrictions {
private boolean onlyRecordingPlayer; private boolean onlyRecordingPlayer;
public String handle(CustomPayloadS2CPacket packet) { public String handle(CustomPayloadS2CPacket packet) {
//#if MC>=10800 //#if MC>=12002
//$$ PacketByteBuf buffer = new PacketByteBuf(Unpooled.buffer());
//$$ packet.write(buffer);
//#elseif MC>=10800
PacketByteBuf buffer = packet.getData(); PacketByteBuf buffer = packet.getData();
//#else //#else
//$$ PacketBuffer buffer = new PacketBuffer(Unpooled.wrappedBuffer(packet.func_149168_d())); //$$ PacketBuffer buffer = new PacketBuffer(Unpooled.wrappedBuffer(packet.func_149168_d()));

View File

@@ -10,6 +10,7 @@ import de.johni0702.minecraft.gui.utils.lwjgl.vector.Vector3f;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.BufferBuilder;
import net.minecraft.network.NetworkState;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.Util; import net.minecraft.util.Util;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@@ -103,6 +104,40 @@ public class MCVer {
//#endif //#endif
} }
public static NetworkState asMc(State state) {
switch (state) {
case HANDSHAKE: return NetworkState.HANDSHAKING;
case STATUS: return NetworkState.STATUS;
case LOGIN: return NetworkState.LOGIN;
//#if MC>=12002
//$$ case CONFIGURATION: return NetworkState.CONFIGURATION;
//#endif
case PLAY: return NetworkState.PLAY;
}
throw new IllegalArgumentException("Unexpected value: " + state);
}
public static State fromMc(NetworkState mcState) {
switch (mcState) {
case HANDSHAKING: return State.HANDSHAKE;
case STATUS: return State.STATUS;
case LOGIN: return State.LOGIN;
//#if MC>=12002
//$$ case CONFIGURATION: return State.CONFIGURATION;
//#endif
case PLAY: return State.PLAY;
}
throw new IllegalArgumentException("Unexpected value: " + mcState);
}
public static PacketTypeRegistry getPacketTypeRegistry(NetworkState state) {
return getPacketTypeRegistry(fromMc(state));
}
public static PacketTypeRegistry getPacketTypeRegistry(State state) {
return PacketTypeRegistry.get(ProtocolVersion.getProtocol(getProtocolVersion()), state);
}
public static PacketTypeRegistry getPacketTypeRegistry(boolean loginPhase) { public static PacketTypeRegistry getPacketTypeRegistry(boolean loginPhase) {
return PacketTypeRegistry.get( return PacketTypeRegistry.get(
ProtocolVersion.getProtocol(getProtocolVersion()), ProtocolVersion.getProtocol(getProtocolVersion()),

View File

@@ -6,6 +6,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.replaymod.core.mixin.MinecraftAccessor; import com.replaymod.core.mixin.MinecraftAccessor;
import com.replaymod.gradle.remap.Pattern; import com.replaymod.gradle.remap.Pattern;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.AbstractClientPlayerEntity;
import net.minecraft.client.options.GameOptions; import net.minecraft.client.options.GameOptions;
import net.minecraft.client.options.KeyBinding; import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormat;
@@ -16,6 +17,10 @@ import net.minecraft.client.render.entity.EntityRenderDispatcher;
import net.minecraft.client.sound.PositionedSoundInstance; import net.minecraft.client.sound.PositionedSoundInstance;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
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.resource.Resource; import net.minecraft.resource.Resource;
import net.minecraft.resource.ResourceManager; import net.minecraft.resource.ResourceManager;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
@@ -59,6 +64,7 @@ import net.minecraft.util.collection.DefaultedList;
//#endif //#endif
//#if MC>=10904 //#if MC>=10904
import net.minecraft.network.packet.s2c.play.UnloadChunkS2CPacket;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.util.crash.CrashCallable; import net.minecraft.util.crash.CrashCallable;
//#else //#else
@@ -906,4 +912,64 @@ class Patterns {
return entity.world; return entity.world;
//#endif //#endif
} }
@Pattern
public Object channel(CustomPayloadS2CPacket packet) {
//#if MC>=12002
//$$ return packet.payload().id();
//#else
return packet.getChannel();
//#endif
}
//#if MC>=10904
@Pattern
public Integer getPacketId(NetworkState state, NetworkSide side, Packet<?> packet) throws Exception {
//#if MC>=12002
//$$ return state.getHandler(side).getId(packet);
//#else
return state.getPacketId(side, packet);
//#endif
}
@Pattern
public int UnloadChunkPacket_getX(UnloadChunkS2CPacket packet) {
//#if MC>=12002
//$$ return packet.pos().x;
//#else
return packet.getX();
//#endif
}
@Pattern
public int UnloadChunkPacket_getZ(UnloadChunkS2CPacket packet) {
//#if MC>=12002
//$$ return packet.pos().z;
//#else
return packet.getZ();
//#endif
}
//#else
//$$ @Pattern public void getPacketId() {}
//$$ @Pattern public void UnloadChunkPacket_getZ() {}
//$$ @Pattern public void UnloadChunkPacket_getX() {}
//#endif
@Pattern
public Identifier getSkinTexture(AbstractClientPlayerEntity player) {
//#if MC>=12002
//$$ return player.getSkinTextures().texture();
//#else
return player.getSkinTexture();
//#endif
}
@Pattern
public boolean isDebugHudEnabled(MinecraftClient mc) {
//#if MC>=12002
//$$ return mc.getDebugHud().shouldShowDebugHud();
//#else
return mc.options.debugEnabled;
//#endif
}
} }

View File

@@ -9,6 +9,7 @@ import com.replaymod.replaystudio.filter.SquashFilter;
import com.replaymod.replaystudio.filter.StreamFilter; import com.replaymod.replaystudio.filter.StreamFilter;
import com.replaymod.replaystudio.io.ReplayInputStream; import com.replaymod.replaystudio.io.ReplayInputStream;
import com.replaymod.replaystudio.io.ReplayOutputStream; import com.replaymod.replaystudio.io.ReplayOutputStream;
import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State;
import com.replaymod.replaystudio.protocol.PacketTypeRegistry; import com.replaymod.replaystudio.protocol.PacketTypeRegistry;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.replay.ReplayMetaData; import com.replaymod.replaystudio.replay.ReplayMetaData;
@@ -122,7 +123,7 @@ public class MarkerProcessor {
String replayName = FilenameUtils.getBaseName(path.getFileName().toString()); String replayName = FilenameUtils.getBaseName(path.getFileName().toString());
int splitCounter = 0; int splitCounter = 0;
PacketTypeRegistry registry = MCVer.getPacketTypeRegistry(true); PacketTypeRegistry registry = MCVer.getPacketTypeRegistry(State.LOGIN);
DimensionTracker dimensionTracker = new DimensionTracker(); DimensionTracker dimensionTracker = new DimensionTracker();
SquashFilter squashFilter = new SquashFilter(null, null, null); SquashFilter squashFilter = new SquashFilter(null, null, null);

View File

@@ -112,7 +112,11 @@ public class ConnectionEventHandler {
//#endif //#endif
serverName = worldName; serverName = worldName;
//#if MC>=11100 //#if MC>=11100
//#if MC>=12002
//$$ } else if (serverInfo != null && serverInfo.isRealm()) {
//#else
} else if (mc.isConnectedToRealms()) { } else if (mc.isConnectedToRealms()) {
//#endif
// we can't access the server name without tapping too deep in the Realms Library // we can't access the server name without tapping too deep in the Realms Library
worldName = "A Realms Server"; worldName = "A Realms Server";
//#endif //#endif

View File

@@ -16,7 +16,6 @@ import net.minecraft.network.packet.s2c.play.EntityPositionS2CPacket;
import net.minecraft.network.packet.s2c.play.EntityS2CPacket; import net.minecraft.network.packet.s2c.play.EntityS2CPacket;
import net.minecraft.network.packet.s2c.play.EntitySetHeadYawS2CPacket; import net.minecraft.network.packet.s2c.play.EntitySetHeadYawS2CPacket;
import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket; import net.minecraft.network.packet.s2c.play.EntityVelocityUpdateS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet; import net.minecraft.network.Packet;
@@ -30,6 +29,12 @@ import net.minecraft.server.integrated.IntegratedServer;
//$$ import net.minecraftforge.event.entity.player.PlayerEvent.ItemPickupEvent; //$$ import net.minecraftforge.event.entity.player.PlayerEvent.ItemPickupEvent;
//#endif //#endif
//#if MC>=12002
//$$ import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
//#else
import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
//#endif
//#if MC>=11600 //#if MC>=11600
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
//#endif //#endif
@@ -103,7 +108,11 @@ public class RecordingEventHandler extends EventRegistrations {
try { try {
ClientPlayerEntity player = mc.player; ClientPlayerEntity player = mc.player;
assert player != null; assert player != null;
//#if MC>=12002
//$$ packetListener.save(new EntitySpawnS2CPacket(player));
//#else
packetListener.save(new PlayerSpawnS2CPacket(player)); packetListener.save(new PlayerSpawnS2CPacket(player));
//#endif
//#if MC>=11903 //#if MC>=11903
//$$ packetListener.save(new EntityTrackerUpdateS2CPacket(player.getId(), player.getDataTracker().getChangedEntries())); //$$ packetListener.save(new EntityTrackerUpdateS2CPacket(player.getId(), player.getDataTracker().getChangedEntries()));
//#elseif MC>=11500 //#elseif MC>=11500

View File

@@ -32,6 +32,12 @@ public abstract class MixinMouseHelper {
private void handleReplayModScroll( private void handleReplayModScroll(
long _p0, double _p1, double _p2, long _p0, double _p1, double _p2,
CallbackInfo ci, CallbackInfo ci,
//#if MC>=12002
//$$ boolean discreteScroll,
//$$ double sensitivity,
//$$ double xOffsetAccumulated,
//$$ double yOffsetAccumulated
//#else
double _l1, double _l1,
//#if MC>=11802 //#if MC>=11802
//$$ int yOffsetAccumulated //$$ int yOffsetAccumulated
@@ -40,6 +46,7 @@ public abstract class MixinMouseHelper {
//#else //#else
//$$ double yOffsetAccumulated //$$ double yOffsetAccumulated
//#endif //#endif
//#endif
) { ) {
if (ReplayModReplay.instance.getReplayHandler() != null) { if (ReplayModReplay.instance.getReplayHandler() != null) {
InputReplayTimer.handleScroll((int) (yOffsetAccumulated * 120)); InputReplayTimer.handleScroll((int) (yOffsetAccumulated * 120));

View File

@@ -2,6 +2,7 @@ package com.replaymod.recording.mixin;
import com.replaymod.core.versions.MCVer; import com.replaymod.core.versions.MCVer;
import com.replaymod.recording.handler.RecordingEventHandler; import com.replaymod.recording.handler.RecordingEventHandler;
import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket;
@@ -78,7 +79,7 @@ public abstract class MixinNetHandlerPlayClient {
byteBuf.readBytes(array); byteBuf.readBytes(array);
for (PacketPlayerListEntry data : PacketPlayerListEntry.read(new Packet( for (PacketPlayerListEntry data : PacketPlayerListEntry.read(new Packet(
MCVer.getPacketTypeRegistry(false), 0, PacketType.PlayerListEntry, MCVer.getPacketTypeRegistry(State.PLAY), 0, PacketType.PlayerListEntry,
com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(array) com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(array)
))) { ))) {
if (data.getUuid() == null) continue; if (data.getUuid() == null) continue;

View File

@@ -30,7 +30,6 @@ import net.minecraft.client.MinecraftClient;
import net.minecraft.network.ClientConnection; import net.minecraft.network.ClientConnection;
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket; import net.minecraft.network.packet.s2c.play.DisconnectS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.network.NetworkState; import net.minecraft.network.NetworkState;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
@@ -41,6 +40,13 @@ import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
//#if MC>=12002
//$$ import net.minecraft.entity.EntityType;
//$$ import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
//#else
import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
//#endif
//#if MC>=10800 //#if MC>=10800
//#if MC<10904 //#if MC<10904
//$$ import net.minecraft.network.play.server.S46PacketSetCompressionLevel; //$$ import net.minecraft.network.play.server.S46PacketSetCompressionLevel;
@@ -93,6 +99,9 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
private static final int PACKET_ID_RESOURCE_PACK_SEND = getPacketId(NetworkState.PLAY, new ResourcePackSendS2CPacket()); private static final int PACKET_ID_RESOURCE_PACK_SEND = getPacketId(NetworkState.PLAY, new ResourcePackSendS2CPacket());
private static final int PACKET_ID_LOGIN_COMPRESSION = getPacketId(NetworkState.LOGIN, new LoginCompressionS2CPacket()); private static final int PACKET_ID_LOGIN_COMPRESSION = getPacketId(NetworkState.LOGIN, new LoginCompressionS2CPacket());
//#endif //#endif
//#if MC>=12002
//$$ private static final int PACKET_ID_CONFIG_RESOURCE_PACK_SEND = getPacketId(NetworkState.CONFIGURATION, new ResourcePackSendS2CPacket("", "", false, null));
//#endif
//#if MC<10904 //#if MC<10904
//$$ private static final int PACKET_ID_PLAY_COMPRESSION = getPacketId(EnumConnectionState.PLAY, new S46PacketSetCompressionLevel()); //$$ private static final int PACKET_ID_PLAY_COMPRESSION = getPacketId(EnumConnectionState.PLAY, new S46PacketSetCompressionLevel());
//#endif //#endif
@@ -152,7 +161,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
out.write(json.getBytes()); out.write(json.getBytes());
} }
} else { } else {
replayFile.writeMetaData(MCVer.getPacketTypeRegistry(true), metaData); replayFile.writeMetaData(MCVer.getPacketTypeRegistry(State.LOGIN), metaData);
} }
} }
} catch (IOException e) { } catch (IOException e) {
@@ -347,7 +356,11 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
// for integrated server connections MC is passing the packet objects directly, so we need to encode them // for integrated server connections MC is passing the packet objects directly, so we need to encode them
// ourselves to be able to store them // ourselves to be able to store them
//#if MC>=11904 //#if MC>=11904
//#if MC>=12002
//$$ PacketBundleHandler bundleHandler = ctx.channel().attr(ClientConnection.CLIENTBOUND_PROTOCOL_KEY).get().getBundler();
//#else
//$$ PacketBundleHandler bundleHandler = ctx.channel().attr(PacketBundleHandler.KEY).get().getBundler(NetworkSide.CLIENTBOUND); //$$ PacketBundleHandler bundleHandler = ctx.channel().attr(PacketBundleHandler.KEY).get().getBundler(NetworkSide.CLIENTBOUND);
//#endif
//$$ List<Packet> packets = new ArrayList<>(1); //$$ List<Packet> packets = new ArrayList<>(1);
//$$ bundleHandler.forEachPacket((net.minecraft.network.packet.Packet<?>) msg, unbundledPacket -> { //$$ bundleHandler.forEachPacket((net.minecraft.network.packet.Packet<?>) msg, unbundledPacket -> {
//$$ try { //$$ try {
@@ -368,7 +381,11 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
} }
if (packet != null) { if (packet != null) {
if (connectionState == NetworkState.PLAY && packet.getId() == PACKET_ID_RESOURCE_PACK_SEND) { if (connectionState == NetworkState.PLAY && packet.getId() == PACKET_ID_RESOURCE_PACK_SEND
//#if MC>=12002
//$$ || connectionState == NetworkState.CONFIGURATION && packet.getId() == PACKET_ID_CONFIG_RESOURCE_PACK_SEND
//#endif
) {
ClientConnection connection = ctx.pipeline().get(ClientConnection.class); ClientConnection connection = ctx.pipeline().get(ClientConnection.class);
save(resourcePackRecorder.handleResourcePack(connection, (ResourcePackSendS2CPacket) decodeMcPacket(packet))); save(resourcePackRecorder.handleResourcePack(connection, (ResourcePackSendS2CPacket) decodeMcPacket(packet)));
return; return;
@@ -385,8 +402,13 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
if (ctx == null) { if (ctx == null) {
return NetworkState.LOGIN; return NetworkState.LOGIN;
} }
//#if MC>=12002
//$$ AttributeKey<NetworkState.PacketHandler<?>> key = ClientConnection.CLIENTBOUND_PROTOCOL_KEY;
//$$ return ctx.channel().attr(key).get().getState();
//#else
AttributeKey<NetworkState> key = ClientConnection.ATTR_KEY_PROTOCOL; AttributeKey<NetworkState> key = ClientConnection.ATTR_KEY_PROTOCOL;
return ctx.channel().attr(key).get(); return ctx.channel().attr(key).get();
//#endif
} }
private static Packet encodeMcPacket(NetworkState connectionState, net.minecraft.network.Packet packet) throws Exception { private static Packet encodeMcPacket(NetworkState connectionState, net.minecraft.network.Packet packet) throws Exception {
@@ -402,7 +424,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
try { try {
packet.write(new PacketByteBuf(byteBuf)); packet.write(new PacketByteBuf(byteBuf));
return new Packet( return new Packet(
MCVer.getPacketTypeRegistry(connectionState == NetworkState.LOGIN), MCVer.getPacketTypeRegistry(connectionState),
packetId, packetId,
com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer( com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(
byteBuf.array(), byteBuf.array(),
@@ -416,11 +438,13 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
} }
private static net.minecraft.network.Packet decodeMcPacket(Packet packet) throws IOException, IllegalAccessException, InstantiationException { private static net.minecraft.network.Packet decodeMcPacket(Packet packet) throws IOException, IllegalAccessException, InstantiationException {
NetworkState connectionState = packet.getRegistry().getState() == State.LOGIN ? NetworkState.LOGIN : NetworkState.PLAY; NetworkState connectionState = asMc(packet.getRegistry().getState());
int packetId = packet.getId(); int packetId = packet.getId();
PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.wrappedBuffer(packet.getBuf().nioBuffer())); PacketByteBuf packetBuf = new PacketByteBuf(Unpooled.wrappedBuffer(packet.getBuf().nioBuffer()));
//#if MC>=11700 //#if MC>=12002
//$$ return connectionState.getHandler(NetworkSide.CLIENTBOUND).createPacket(packetId, packetBuf);
//#elseif MC>=11700
//$$ return connectionState.getPacketHandler(NetworkSide.CLIENTBOUND, packetId, packetBuf); //$$ return connectionState.getPacketHandler(NetworkSide.CLIENTBOUND, packetId, packetBuf);
//#else //#else
//#if MC>=10800 //#if MC>=10800
@@ -439,7 +463,7 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
byte[] bytes = new byte[packetBuf.readableBytes()]; byte[] bytes = new byte[packetBuf.readableBytes()];
packetBuf.readBytes(bytes); packetBuf.readBytes(bytes);
return new Packet( return new Packet(
MCVer.getPacketTypeRegistry(connectionState == NetworkState.LOGIN), MCVer.getPacketTypeRegistry(connectionState),
packetId, packetId,
com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(bytes) com.github.steveice10.netty.buffer.Unpooled.wrappedBuffer(bytes)
); );
@@ -503,12 +527,17 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
} }
} }
//#if MC>=12002
//$$ if (msg instanceof EntitySpawnS2CPacket packet && packet.getEntityType() == EntityType.PLAYER) {
//$$ UUID uuid = packet.getUuid();
//#else
if (msg instanceof PlayerSpawnS2CPacket) { if (msg instanceof PlayerSpawnS2CPacket) {
//#if MC>=10800 //#if MC>=10800
UUID uuid = ((PlayerSpawnS2CPacket) msg).getPlayerUuid(); UUID uuid = ((PlayerSpawnS2CPacket) msg).getPlayerUuid();
//#else //#else
//$$ UUID uuid = ((S0CPacketSpawnPlayer) msg).func_148948_e().getId(); //$$ UUID uuid = ((S0CPacketSpawnPlayer) msg).func_148948_e().getId();
//#endif //#endif
//#endif
Set<String> uuids = new HashSet<>(Arrays.asList(metaData.getPlayers())); Set<String> uuids = new HashSet<>(Arrays.asList(metaData.getPlayers()));
uuids.add(uuid.toString()); uuids.add(uuid.toString());
metaData.setPlayers(uuids.toArray(new String[uuids.size()])); metaData.setPlayers(uuids.toArray(new String[uuids.size()]));

View File

@@ -321,7 +321,11 @@ public class VideoRenderer implements RenderInfo {
//#endif //#endif
if (mc.options.debugEnabled) { if (mc.options.debugEnabled) {
debugInfoWasShown = true; debugInfoWasShown = true;
//#if MC>=12002
//$$ mc.getDebugHud().toggleDebugHud();
//#else
mc.options.debugEnabled = false; mc.options.debugEnabled = false;
//#endif
} }
//#if MC>=11400 //#if MC>=11400
if (mc.mouse.isCursorLocked()) { if (mc.mouse.isCursorLocked()) {
@@ -385,7 +389,13 @@ public class VideoRenderer implements RenderInfo {
//$$ Display.setResizable(true); //$$ Display.setResizable(true);
//$$ } //$$ }
//#endif //#endif
mc.options.debugEnabled = debugInfoWasShown; if (debugInfoWasShown) {
//#if MC>=12002
//$$ mc.getDebugHud().toggleDebugHud();
//#else
mc.options.debugEnabled = true;
//#endif
}
if (mouseWasGrabbed) { if (mouseWasGrabbed) {
//#if MC>=11400 //#if MC>=11400
mc.mouse.lockCursor(); mc.mouse.lockCursor();

View File

@@ -10,6 +10,8 @@ import com.replaymod.core.mixin.TimerAccessor;
import com.replaymod.core.utils.Restrictions; import com.replaymod.core.utils.Restrictions;
import com.replaymod.replay.camera.CameraEntity; import com.replaymod.replay.camera.CameraEntity;
import com.replaymod.replaystudio.io.ReplayInputStream; import com.replaymod.replaystudio.io.ReplayInputStream;
import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State;
import com.replaymod.replaystudio.protocol.PacketTypeRegistry;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import de.johni0702.minecraft.gui.utils.EventRegistrations; import de.johni0702.minecraft.gui.utils.EventRegistrations;
import de.johni0702.minecraft.gui.versions.callbacks.PreTickCallback; import de.johni0702.minecraft.gui.versions.callbacks.PreTickCallback;
@@ -48,7 +50,6 @@ import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerAbilitiesS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerAbilitiesS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket; import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket;
import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
import net.minecraft.network.packet.s2c.play.SignEditorOpenS2CPacket; import net.minecraft.network.packet.s2c.play.SignEditorOpenS2CPacket;
import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket; import net.minecraft.network.packet.s2c.play.StatisticsS2CPacket;
import net.minecraft.text.Text; import net.minecraft.text.Text;
@@ -57,6 +58,14 @@ import net.minecraft.util.math.Vec3d;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
//#if MC>=12002
//$$ import net.minecraft.network.packet.s2c.config.ReadyS2CPacket;
//$$ import net.minecraft.network.packet.s2c.play.CommonPlayerSpawnInfo;
//$$ import net.minecraft.network.packet.s2c.play.EnterReconfigurationS2CPacket;
//#else
import net.minecraft.network.packet.s2c.play.PlayerSpawnS2CPacket;
//#endif
//#if MC>=11904 //#if MC>=11904
//$$ import net.minecraft.network.packet.s2c.play.PositionFlag; //$$ import net.minecraft.network.packet.s2c.play.PositionFlag;
//#endif //#endif
@@ -238,9 +247,9 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
protected PacketData nextPacket; protected PacketData nextPacket;
/** /**
* Whether we're currently reading packets from the login phase. * Which protocol (state) we're currently in.
*/ */
private boolean loginPhase = true; private PacketTypeRegistry registry = getPacketTypeRegistry(State.LOGIN);
/** /**
* Whether we need to restart the current replay. E.g. when jumping backwards in time * Whether we need to restart the current replay. E.g. when jumping backwards in time
@@ -470,8 +479,10 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
int i = pb.readVarInt(); int i = pb.readVarInt();
NetworkState state = loginPhase ? NetworkState.LOGIN : NetworkState.PLAY; NetworkState state = asMc(registry.getState());
//#if MC>=11700 //#if MC>=12002
//$$ Packet p = state.getHandler(NetworkSide.CLIENTBOUND).createPacket(i, pb);
//#elseif MC>=11700
//$$ Packet p = state.getPacketHandler(NetworkSide.CLIENTBOUND, i, pb); //$$ Packet p = state.getPacketHandler(NetworkSide.CLIENTBOUND, i, pb);
//#else //#else
//#if MC>=10800 //#if MC>=10800
@@ -493,8 +504,10 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
return; // MC should have enough time to tick return; // MC should have enough time to tick
} }
boolean relevantPacket = packet instanceof PlayerSpawnS2CPacket boolean relevantPacket = packet instanceof EntitySpawnS2CPacket
|| packet instanceof EntitySpawnS2CPacket //#if MC<12002
|| packet instanceof PlayerSpawnS2CPacket
//#endif
//#if MC<11900 //#if MC<11900
|| packet instanceof MobSpawnS2CPacket || packet instanceof MobSpawnS2CPacket
|| packet instanceof PaintingSpawnS2CPacket || packet instanceof PaintingSpawnS2CPacket
@@ -557,9 +570,20 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
*/ */
protected Packet processPacket(Packet p) throws Exception { protected Packet processPacket(Packet p) throws Exception {
if (p instanceof LoginSuccessS2CPacket) { if (p instanceof LoginSuccessS2CPacket) {
loginPhase = false; registry = registry.withLoginSuccess();
return p; return p;
} }
//#if MC>=12002
//$$ if (p instanceof ReadyS2CPacket) {
//$$ registry = registry.withState(State.PLAY);
//$$ return p;
//$$ }
//$$ if (p instanceof EnterReconfigurationS2CPacket) {
//$$ registry = registry.withState(State.CONFIGURATION);
//$$ hasWorldLoaded = false;
//$$ return p;
//$$ }
//#endif
if (p instanceof CustomPayloadS2CPacket) { if (p instanceof CustomPayloadS2CPacket) {
CustomPayloadS2CPacket packet = (CustomPayloadS2CPacket) p; CustomPayloadS2CPacket packet = (CustomPayloadS2CPacket) p;
@@ -663,6 +687,17 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
//#if MC>=11400 //#if MC>=11400
p = new GameJoinS2CPacket( p = new GameJoinS2CPacket(
entId, entId,
//#if MC>=12002
//$$ packet.hardcore(),
//$$ packet.dimensionIds(),
//$$ packet.maxPlayers(),
//$$ packet.viewDistance(),
//$$ packet.simulationDistance(),
//$$ packet.reducedDebugInfo(),
//$$ packet.showDeathScreen(),
//$$ packet.doLimitedCrafting(),
//$$ withSpectatorMode(packet.commonPlayerSpawnInfo())
//#else
//#if MC>=11800 //#if MC>=11800
//$$ packet.hardcore(), //$$ packet.hardcore(),
//#endif //#endif
@@ -719,6 +754,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
//#if MC>=12000 //#if MC>=12000
//$$ , packet.portalCooldown() //$$ , packet.portalCooldown()
//#endif //#endif
//#endif
); );
//#else //#else
//#if MC>=10800 //#if MC>=10800
@@ -758,6 +794,10 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
PlayerRespawnS2CPacket respawn = (PlayerRespawnS2CPacket) p; PlayerRespawnS2CPacket respawn = (PlayerRespawnS2CPacket) p;
//#if MC>=11400 //#if MC>=11400
p = new PlayerRespawnS2CPacket( p = new PlayerRespawnS2CPacket(
//#if MC>=12002
//$$ withSpectatorMode(respawn.commonPlayerSpawnInfo()),
//$$ (byte) 0
//#else
//#if MC>=11600 //#if MC>=11600
respawn.method_29445(), respawn.method_29445(),
//#endif //#endif
@@ -785,6 +825,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
//#if MC>=12000 //#if MC>=12000
//$$ , respawn.getPortalCooldown() //$$ , respawn.getPortalCooldown()
//#endif //#endif
//#endif
); );
//#else //#else
//#if MC>=10809 //#if MC>=10809
@@ -916,6 +957,22 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
} }
} }
//#if MC>=12002
//$$ private CommonPlayerSpawnInfo withSpectatorMode(CommonPlayerSpawnInfo org) {
//$$ return new CommonPlayerSpawnInfo(
//$$ org.dimensionType(),
//$$ org.dimension(),
//$$ org.seed(),
//$$ GameMode.SPECTATOR,
//$$ GameMode.SPECTATOR,
//$$ org.isDebug(),
//$$ org.isFlat(),
//$$ org.lastDeathLocation(),
//$$ org.portalCooldown()
//$$ );
//$$ }
//#endif
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void channelActive(ChannelHandlerContext ctx) throws Exception { public void channelActive(ChannelHandlerContext ctx) throws Exception {
@@ -1010,7 +1067,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
while (!terminate) { while (!terminate) {
synchronized (FullReplaySender.this) { synchronized (FullReplaySender.this) {
if (replayIn == null) { if (replayIn == null) {
replayIn = replayFile.getPacketData(getPacketTypeRegistry(true)); replayIn = replayFile.getPacketData(getPacketTypeRegistry(State.LOGIN));
} }
// Packet loop // Packet loop
while (true) { while (true) {
@@ -1037,7 +1094,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
// Read the next packet if we don't already have one // Read the next packet if we don't already have one
if (nextPacket == null) { if (nextPacket == null) {
nextPacket = new PacketData(replayIn, loginPhase); nextPacket = new PacketData(replayIn);
} }
int nextTimeStamp = nextPacket.timestamp; int nextTimeStamp = nextPacket.timestamp;
@@ -1060,6 +1117,17 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
lastTimeStamp = nextTimeStamp; lastTimeStamp = nextTimeStamp;
// MC as of 1.20.2 relies on autoRead, so it can update the connection state on the main
// thread before the next packet is read. As such, we need to stall if that was just
// enabled.
// Might be safe to do the same on older versions too, but I'd rather not poke the
// monster that is Forge networking.
//#if MC>=12002
//$$ while (!ctx.channel().config().isAutoRead()) {
//$$ Thread.sleep(0, 100_000);
//$$ }
//#endif
// In case we finished jumping // In case we finished jumping
// We need to check that we aren't planing to restart so we don't accidentally run this // We need to check that we aren't planing to restart so we don't accidentally run this
// code before we actually restarted // code before we actually restarted
@@ -1092,7 +1160,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
// Restart the replay. // Restart the replay.
hasWorldLoaded = false; hasWorldLoaded = false;
lastTimeStamp = 0; lastTimeStamp = 0;
loginPhase = true; registry = getPacketTypeRegistry(State.LOGIN);
startFromBeginning = false; startFromBeginning = false;
nextPacket = null; nextPacket = null;
realTimeStart = System.currentTimeMillis(); realTimeStart = System.currentTimeMillis();
@@ -1232,14 +1300,14 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
replayIn.close(); replayIn.close();
replayIn = null; replayIn = null;
} }
loginPhase = true; registry = getPacketTypeRegistry(State.LOGIN);
startFromBeginning = false; startFromBeginning = false;
nextPacket = null; nextPacket = null;
ReplayMod.instance.runSync(replayHandler::restartedReplay); ReplayMod.instance.runSync(replayHandler::restartedReplay);
} }
if (replayIn == null) { if (replayIn == null) {
replayIn = replayFile.getPacketData(getPacketTypeRegistry(true)); replayIn = replayFile.getPacketData(getPacketTypeRegistry(State.LOGIN));
} }
while (true) { // Send packets while (true) { // Send packets
@@ -1251,7 +1319,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
nextPacket = null; nextPacket = null;
} else { } else {
// Otherwise read one from the input stream // Otherwise read one from the input stream
pd = new PacketData(replayIn, loginPhase); pd = new PacketData(replayIn);
} }
int nextTimeStamp = pd.timestamp; int nextTimeStamp = pd.timestamp;
@@ -1263,6 +1331,17 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
// Process packet // Process packet
channelRead(ctx, pd.bytes); channelRead(ctx, pd.bytes);
// MC as of 1.20.2 relies on autoRead, so it can update the connection state on the main
// thread before the next packet is read. As such, we need to stall if that was just
// enabled.
// Might be safe to do the same on older versions too, but I'd rather not poke the
// monster that is Forge networking.
//#if MC>=12002
//$$ while (!ctx.channel().config().isAutoRead()) {
//$$ Thread.sleep(0, 100_000);
//$$ }
//#endif
} catch (EOFException eof) { } catch (EOFException eof) {
// Shit! We hit the end before finishing our job! What shall we do now? // Shit! We hit the end before finishing our job! What shall we do now?
// well, let's just pretend we're done... // well, let's just pretend we're done...
@@ -1471,7 +1550,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend
private final int timestamp; private final int timestamp;
private final byte[] bytes; private final byte[] bytes;
PacketData(ReplayInputStream in, boolean loginPhase) throws IOException { PacketData(ReplayInputStream in) throws IOException {
if (ReplayMod.isMinimalMode()) { if (ReplayMod.isMinimalMode()) {
// Minimal mode, we can only read our exact protocol version and cannot use ReplayStudio // Minimal mode, we can only read our exact protocol version and cannot use ReplayStudio
timestamp = readInt(in); timestamp = readInt(in);

View File

@@ -7,6 +7,7 @@ import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture; import com.google.common.util.concurrent.SettableFuture;
import com.replaymod.core.mixin.MinecraftAccessor; import com.replaymod.core.mixin.MinecraftAccessor;
import com.replaymod.core.mixin.TimerAccessor; import com.replaymod.core.mixin.TimerAccessor;
import com.replaymod.replaystudio.lib.viaversion.api.protocol.packet.State;
import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ReplayFile;
import com.replaymod.replaystudio.rar.RandomAccessReplay; import com.replaymod.replaystudio.rar.RandomAccessReplay;
import de.johni0702.minecraft.gui.utils.EventRegistrations; import de.johni0702.minecraft.gui.utils.EventRegistrations;
@@ -30,6 +31,7 @@ import java.util.function.Consumer;
import com.replaymod.core.utils.WrappedTimer; import com.replaymod.core.utils.WrappedTimer;
//#endif //#endif
import static com.replaymod.core.versions.MCVer.asMc;
import static com.replaymod.core.versions.MCVer.getMinecraft; import static com.replaymod.core.versions.MCVer.getMinecraft;
import static com.replaymod.core.versions.MCVer.getPacketTypeRegistry; import static com.replaymod.core.versions.MCVer.getPacketTypeRegistry;
import static com.replaymod.replay.ReplayModReplay.LOGGER; import static com.replaymod.replay.ReplayModReplay.LOGGER;
@@ -63,7 +65,7 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe
public QuickReplaySender(ReplayModReplay mod, ReplayFile replayFile) { public QuickReplaySender(ReplayModReplay mod, ReplayFile replayFile) {
this.mod = mod; this.mod = mod;
this.replay = new RandomAccessReplay(replayFile, getPacketTypeRegistry(false)) { this.replay = new RandomAccessReplay(replayFile, getPacketTypeRegistry(State.PLAY)) {
private byte[] buf = new byte[0]; private byte[] buf = new byte[0];
@Override @Override
@@ -78,18 +80,21 @@ public class QuickReplaySender extends ChannelHandlerAdapter implements ReplaySe
wrappedBuf.writerIndex(size); wrappedBuf.writerIndex(size);
PacketByteBuf packetByteBuf = new PacketByteBuf(wrappedBuf); PacketByteBuf packetByteBuf = new PacketByteBuf(wrappedBuf);
NetworkState state = asMc(packet.getRegistry().getState());
//#if MC>=10809 //#if MC>=10809
Packet<?> mcPacket; Packet<?> mcPacket;
//#else //#else
//$$ Packet mcPacket; //$$ Packet mcPacket;
//#endif //#endif
//#if MC>=11700 //#if MC>=12002
//$$ mcPacket = NetworkState.PLAY.getPacketHandler(NetworkSide.CLIENTBOUND, packet.getId(), packetByteBuf); //$$ mcPacket = state.getHandler(NetworkSide.CLIENTBOUND).createPacket(packet.getId(), packetByteBuf);
//#elseif MC>=11700
//$$ mcPacket = state.getPacketHandler(NetworkSide.CLIENTBOUND, packet.getId(), packetByteBuf);
//#elseif MC>=11500 //#elseif MC>=11500
mcPacket = NetworkState.PLAY.getPacketHandler(NetworkSide.CLIENTBOUND, packet.getId()); mcPacket = state.getPacketHandler(NetworkSide.CLIENTBOUND, packet.getId());
//#else //#else
//$$ try { //$$ try {
//$$ mcPacket = NetworkState.PLAY.getPacketHandler(NetworkSide.CLIENTBOUND, packet.getId()); //$$ mcPacket = state.getPacketHandler(NetworkSide.CLIENTBOUND, packet.getId());
//$$ } catch (IllegalAccessException | InstantiationException e) { //$$ } catch (IllegalAccessException | InstantiationException e) {
//$$ e.printStackTrace(); //$$ e.printStackTrace();
//$$ return; //$$ return;

View File

@@ -42,6 +42,13 @@ import net.minecraft.network.ClientConnection;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.*;
//#if MC>=12002
//$$ import io.netty.channel.ChannelDuplexHandler;
//$$ import io.netty.channel.ChannelPromise;
//$$ import net.minecraft.network.handler.NetworkStateTransitionHandler;
//$$ import net.minecraft.network.packet.Packet;
//#endif
//#if MC>=12000 //#if MC>=12000
//$$ import com.mojang.blaze3d.systems.VertexSorter; //$$ import com.mojang.blaze3d.systems.VertexSorter;
//$$ import net.minecraft.client.gui.DrawContext; //$$ import net.minecraft.client.gui.DrawContext;
@@ -301,6 +308,36 @@ public class ReplayHandler {
//$$ FMLClientHandler.instance().connectToRealmsServer(null, 0); // just to init the playClientBlock latch //$$ FMLClientHandler.instance().connectToRealmsServer(null, 0); // just to init the playClientBlock latch
//#endif //#endif
//#if MC>=11200
channel = new EmbeddedChannel();
//#else
//$$ ChannelOutboundHandlerAdapter dummyHandler = new ChannelOutboundHandlerAdapter();
//$$ channel = new EmbeddedChannel(dummyHandler);
//$$ channel.pipeline().remove(dummyHandler);
//#endif
//#if MC>=10800
channel.pipeline().addLast("ReplayModReplay_quickReplaySender", quickReplaySender);
//#endif
channel.pipeline().addLast("ReplayModReplay_replaySender", fullReplaySender);
//#if MC>=12002
//$$ channel.pipeline().addLast("ReplayModReplay_transition", new DummyNetworkStateTransitionHandler());
//$$ channel.pipeline().addLast("bundler", new PacketBundler(ClientConnection.CLIENTBOUND_PROTOCOL_KEY));
//#elseif 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.
//#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));
//#else
networkManager.setState(NetworkState.LOGIN);
//#endif
networkManager.setPacketListener(new ClientLoginNetworkHandler( networkManager.setPacketListener(new ClientLoginNetworkHandler(
networkManager, networkManager,
mc, mc,
@@ -315,28 +352,6 @@ public class ReplayHandler {
//#endif //#endif
)); ));
//#if MC>=11200
channel = new EmbeddedChannel();
//#else
//$$ ChannelOutboundHandlerAdapter dummyHandler = new ChannelOutboundHandlerAdapter();
//$$ channel = new EmbeddedChannel(dummyHandler);
//$$ channel.pipeline().remove(dummyHandler);
//#endif
//#if MC>=10800
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 //#if MC>=11400
((MinecraftAccessor) mc).setConnection(networkManager); ((MinecraftAccessor) mc).setConnection(networkManager);
//#endif //#endif
@@ -787,4 +802,24 @@ public class ReplayHandler {
//$$ } //$$ }
//#endif //#endif
} }
//#if MC>=12002
//$$ private static class DummyNetworkStateTransitionHandler extends ChannelDuplexHandler {
//$$ @Override
//$$ public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//$$ if (msg instanceof Packet<?> packet) {
//$$ NetworkStateTransitionHandler.handle(ctx.channel().attr(ClientConnection.CLIENTBOUND_PROTOCOL_KEY), packet);
//$$ }
//$$ super.channelRead(ctx, msg);
//$$ }
//$$
//$$ @Override
//$$ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
//$$ if (msg instanceof Packet<?> packet) {
//$$ NetworkStateTransitionHandler.handle(ctx.channel().attr(ClientConnection.SERVERBOUND_PROTOCOL_KEY), packet);
//$$ }
//$$ super.write(ctx, msg, promise);
//$$ }
//$$ }
//#endif
} }

View File

@@ -40,6 +40,10 @@ import net.minecraft.util.math.Box;
//$$ import net.minecraftforge.eventbus.api.SubscribeEvent; //$$ import net.minecraftforge.eventbus.api.SubscribeEvent;
//#endif //#endif
//#if MC>=12002
//$$ import net.minecraft.client.util.SkinTextures;
//#endif
//#if MC>=11400 //#if MC>=11400
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluid;
@@ -475,6 +479,16 @@ public class CameraEntity
return super.isInvisible(); return super.isInvisible();
} }
//#if MC>=12002
//$$ @Override
//$$ public SkinTextures getSkinTextures() {
//$$ Entity view = this.client.getCameraEntity();
//$$ if (view != this && view instanceof AbstractClientPlayerEntity) {
//$$ return ((AbstractClientPlayerEntity) view).getSkinTextures();
//$$ }
//$$ return super.getSkinTextures();
//$$ }
//#else
@Override @Override
public Identifier getSkinTexture() { public Identifier getSkinTexture() {
Entity view = this.client.getCameraEntity(); Entity view = this.client.getCameraEntity();
@@ -493,7 +507,10 @@ public class CameraEntity
} }
return super.getModel(); return super.getModel();
} }
//#endif
//#endif
//#if MC>=10800
@Override @Override
public boolean isPartVisible(PlayerModelPart modelPart) { public boolean isPartVisible(PlayerModelPart modelPart) {
Entity view = this.client.getCameraEntity(); Entity view = this.client.getCameraEntity();

View File

@@ -5,8 +5,12 @@
"server": [], "server": [],
"client": [ "client": [
//#if MC>=11800 //#if MC>=11800
//#if MC>=12002
//$$ "ChunkRenderingDataPreparerAccessor",
//#else
//$$ "ChunkInfoAccessor", //$$ "ChunkInfoAccessor",
//#endif //#endif
//#endif
"Mixin_ChromaKeyColorSky", "Mixin_ChromaKeyColorSky",
"Mixin_ChromaKeyDisableFog", "Mixin_ChromaKeyDisableFog",
"Mixin_ChromaKeyForceSky", "Mixin_ChromaKeyForceSky",

View File

@@ -1,4 +1,4 @@
// 1.18+ // 1.18 - 1.20.1
package com.replaymod.render.mixin; package com.replaymod.render.mixin;
import net.minecraft.client.render.chunk.ChunkBuilder; import net.minecraft.client.render.chunk.ChunkBuilder;

View File

View File

@@ -0,0 +1 @@
// 1.18 - 1.20.1

View File

@@ -0,0 +1,21 @@
package com.replaymod.render.mixin;
import net.minecraft.client.render.BuiltChunkStorage;
import net.minecraft.client.render.ChunkRenderingDataPreparer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
@Mixin(ChunkRenderingDataPreparer.class)
public interface ChunkRenderingDataPreparerAccessor {
@Accessor("field_45623")
BuiltChunkStorage builtChunkStorage();
@Accessor("field_45621")
boolean shouldUpdate();
@Accessor("field_45622")
Future<?> fullUpdateFuture();
}

View File

@@ -0,0 +1,119 @@
package com.replaymod.render.mixin;
import com.replaymod.render.hooks.ForceChunkLoadingHook;
import com.replaymod.render.hooks.IForceChunkLoading;
import com.replaymod.render.utils.FlawlessFrames;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.ChunkRenderingDataPreparer;
import net.minecraft.client.render.Frustum;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.LightmapTextureManager;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.render.chunk.ChunkBuilder;
import net.minecraft.client.render.chunk.ChunkRendererRegionBuilder;
import net.minecraft.client.util.math.MatrixStack;
import org.joml.Matrix4f;
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;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@Mixin(WorldRenderer.class)
public abstract class Mixin_ForceChunkLoading implements IForceChunkLoading {
private ForceChunkLoadingHook replayModRender_hook;
@Override
public void replayModRender_setHook(ForceChunkLoadingHook hook) {
this.replayModRender_hook = hook;
}
@Shadow private ChunkBuilder field_45614;
@Shadow @Final private ChunkRenderingDataPreparer field_45615;
@Shadow protected abstract void setupTerrain(Camera par1, Frustum par2, boolean par3, boolean par4);
@Shadow private Frustum frustum;
@Shadow private Frustum capturedFrustum;
@Shadow @Final private MinecraftClient client;
@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) {
if (replayModRender_hook == null) {
return;
}
if (FlawlessFrames.hasSodium()) {
return;
}
assert this.client.player != null;
ChunkRenderingDataPreparer renderingData = this.field_45615;
ChunkRenderingDataPreparerAccessor renderingDataAcc = (ChunkRenderingDataPreparerAccessor) renderingData;
ChunkRendererRegionBuilder chunkRendererRegionBuilder = new ChunkRendererRegionBuilder();
do {
boolean areWeDoneYet = true;
// Determine which chunks shall be visible
setupTerrain(camera, this.frustum, this.capturedFrustum != null, this.client.player.isSpectator());
// Wait for async processing to be complete
Future<?> fullUpdateFuture = renderingDataAcc.fullUpdateFuture();
if (fullUpdateFuture != null) {
try {
fullUpdateFuture.get(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return;
} catch (ExecutionException e) {
throw new RuntimeException(e);
} catch (TimeoutException e) {
e.printStackTrace();
}
}
// If that async processing did change the chunk graph, we need to re-apply the frustum (otherwise this is
// only done in the next setupTerrain call, which not happen this frame)
if (renderingData.method_52836()) {
this.applyFrustum((new Frustum(frustum)).coverBoxAroundSetPosition(8)); // call based on the one in setupTerrain
}
// Schedule all chunks which need rebuilding (we schedule even important rebuilds because we wait for
// all of them anyway and this way we can take advantage of threading)
for (ChunkBuilder.BuiltChunk builtChunk : renderingDataAcc.builtChunkStorage().chunks) {
if (!builtChunk.needsRebuild()) {
continue;
}
// MC sometimes schedules invalid chunks when you're outside of loaded chunks (e.g. y > 256)
if (builtChunk.shouldBuild()) {
builtChunk.scheduleRebuild(this.field_45614, chunkRendererRegionBuilder);
areWeDoneYet = false;
}
builtChunk.cancelRebuild();
}
// Upload all chunks
if (((ForceChunkLoadingHook.IBlockOnChunkRebuilds) this.field_45614).uploadEverythingBlocking()) {
areWeDoneYet = false;
}
// Repeat until no more updates are needed
if (!areWeDoneYet) {
renderingData.method_52817(); // sets shouldUpdate to true
}
} while (renderingDataAcc.shouldUpdate());
}
}

View File

@@ -0,0 +1,9 @@
package com.replaymod.replay.mixin.entity_tracking;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import org.spongepowered.asm.mixin.Mixin;
@Mixin(ClientPlayNetworkHandler.class)
public class Mixin_FixPartialUpdates {
// Looks like this has finally been fixed in 1.20.2
}