IOOBE with ReplayMod in Singleplayer as of FAPI 0.91+1.20.2
Johni0702 opened this issue ยท 0 comments
Trying to run ReplayMod (not yet released 1.20.2 version) alongside FAPI 0.91 (or 0.91.1) results in the following IOOBE and corresponding Connection Lost
/Internal Exception: ...
screen when opening a Singleplayer world:
[21:39:34] [Netty Local Client IO #0/ERROR]: Encountered exception while handling in channel with name "c:version"
java.lang.IndexOutOfBoundsException: readerIndex(2) + length(1) exceeds writerIndex(2): UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 2, widx: 2, cap: 256)
at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1442) ~[netty-buffer-4.1.97.Final.jar:?]
at io.netty.buffer.AbstractByteBuf.readByte(AbstractByteBuf.java:730) ~[netty-buffer-4.1.97.Final.jar:?]
at net.minecraft.class_8703.method_53016(class_8703.java:28) ~[client-intermediary.jar:?]
at net.minecraft.class_2540.method_10816(class_2540.java:525) ~[client-intermediary.jar:?]
at net.minecraft.class_2540.method_10799(class_2540.java:374) ~[client-intermediary.jar:?]
at net.minecraft.class_2540.method_10787(class_2540.java:370) ~[client-intermediary.jar:?]
at net.fabricmc.fabric.impl.networking.CommonVersionPayload.<init>(CommonVersionPayload.java:27) ~[fabric-networking-api-v1-3.1.1+e3b69503a0-628d589b36e3c75a.jar:?]
at net.fabricmc.fabric.impl.networking.client.ClientNetworkingImpl.lambda$clientInit$2(ClientNetworkingImpl.java:157) ~[fabric-networking-api-v1-3.1.1+e3b69503a0-628d589b36e3c75a.jar:?]
[...]
Full stacktrace
[21:39:34] [Netty Local Client IO #0/ERROR]: Encountered exception while handling in channel with name "c:version"
java.lang.IndexOutOfBoundsException: readerIndex(2) + length(1) exceeds writerIndex(2): UnpooledByteBufAllocator$InstrumentedUnpooledUnsafeHeapByteBuf(ridx: 2, widx: 2, cap: 256)
at io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1442) ~[netty-buffer-4.1.97.Final.jar:?]
at io.netty.buffer.AbstractByteBuf.readByte(AbstractByteBuf.java:730) ~[netty-buffer-4.1.97.Final.jar:?]
at net.minecraft.class_8703.method_53016(class_8703.java:28) ~[client-intermediary.jar:?]
at net.minecraft.class_2540.method_10816(class_2540.java:525) ~[client-intermediary.jar:?]
at net.minecraft.class_2540.method_10799(class_2540.java:374) ~[client-intermediary.jar:?]
at net.minecraft.class_2540.method_10787(class_2540.java:370) ~[client-intermediary.jar:?]
at net.fabricmc.fabric.impl.networking.CommonVersionPayload.<init>(CommonVersionPayload.java:27) ~[fabric-networking-api-v1-3.1.1+e3b69503a0-628d589b36e3c75a.jar:?]
at net.fabricmc.fabric.impl.networking.client.ClientNetworkingImpl.lambda$clientInit$2(ClientNetworkingImpl.java:157) ~[fabric-networking-api-v1-3.1.1+e3b69503a0-628d589b36e3c75a.jar:?]
at net.fabricmc.fabric.api.client.networking.v1.ClientConfigurationNetworking.lambda$wrapUntyped$0(ClientConfigurationNetworking.java:365) ~[fabric-networking-api-v1-3.1.1+e3b69503a0-628d589b36e3c75a.jar:?]
at net.fabricmc.fabric.impl.networking.client.ClientConfigurationNetworkAddon.receive(ClientConfigurationNetworkAddon.java:77) ~[fabric-networking-api-v1-3.1.1+e3b69503a0-628d589b36e3c75a.jar:?]
at net.fabricmc.fabric.impl.networking.client.ClientConfigurationNetworkAddon.receive(ClientConfigurationNetworkAddon.java:42) ~[fabric-networking-api-v1-3.1.1+e3b69503a0-628d589b36e3c75a.jar:?]
at net.fabricmc.fabric.impl.networking.AbstractChanneledNetworkAddon.handle(AbstractChanneledNetworkAddon.java:99) ~[fabric-networking-api-v1-3.1.1+e3b69503a0-628d589b36e3c75a.jar:?]
at net.minecraft.class_8673.handler$zgj000$fabric-networking-api-v1$onCustomPayload(class_8673.java:1043) ~[client-intermediary.jar:?]
at net.minecraft.class_8673.method_52780(class_8673.java) ~[client-intermediary.jar:?]
at net.minecraft.class_2658.method_53024(class_2658.java:92) ~[client-intermediary.jar:?]
at net.minecraft.class_2658.method_11054(class_2658.java:31) ~[client-intermediary.jar:?]
at net.minecraft.class_2535.method_10759(class_2535.java:196) ~[client-intermediary.jar:?]
at net.minecraft.class_2535.method_10770(class_2535.java:181) ~[client-intermediary.jar:?]
at net.minecraft.class_2535.channelRead0(class_2535.java:60) ~[client-intermediary.jar:?]
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.handler.flow.FlowControlHandler.dequeue(FlowControlHandler.java:202) ~[netty-handler-4.1.97.Final.jar:?]
at io.netty.handler.flow.FlowControlHandler.channelRead(FlowControlHandler.java:164) ~[netty-handler-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103) ~[netty-codec-4.1.97.Final.jar:?]
at io.netty.handler.codec.MessageToMessageCodec.channelRead(MessageToMessageCodec.java:111) ~[netty-codec-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:442) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93) ~[netty-transport-4.1.97.Final.jar:?]
at com.replaymod.recording.packet.PacketListener$DecodedPacketListener.channelRead(PacketListener.java:547) ~[replaymod-1.20.2-2.6.13-5-gb8ab7aa.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93) ~[netty-transport-4.1.97.Final.jar:?]
at com.replaymod.recording.packet.PacketListener.channelRead(PacketListener.java:397) ~[replaymod-1.20.2-2.6.13-5-gb8ab7aa.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.local.LocalChannel.readInbound(LocalChannel.java:299) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.local.LocalChannel.doBeginRead(LocalChannel.java:322) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannel$AbstractUnsafe.beginRead(AbstractChannel.java:834) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline$HeadContext.read(DefaultChannelPipeline.java:1362) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeRead(AbstractChannelHandlerContext.java:835) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.read(AbstractChannelHandlerContext.java:814) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.handler.flow.FlowControlHandler.read(FlowControlHandler.java:144) ~[netty-handler-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeRead(AbstractChannelHandlerContext.java:837) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.read(AbstractChannelHandlerContext.java:814) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline.read(DefaultChannelPipeline.java:1004) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannel.read(AbstractChannel.java:290) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline$HeadContext.readIfIsAutoRead(DefaultChannelPipeline.java:1422) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelReadComplete(DefaultChannelPipeline.java:1417) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelReadComplete(AbstractChannelHandlerContext.java:482) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelReadComplete(AbstractChannelHandlerContext.java:463) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelReadComplete(DefaultChannelPipeline.java:925) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.local.LocalChannel.readInbound(LocalChannel.java:302) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.local.LocalChannel.doBeginRead(LocalChannel.java:322) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannel$AbstractUnsafe.beginRead(AbstractChannel.java:834) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline$HeadContext.read(DefaultChannelPipeline.java:1362) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeRead(AbstractChannelHandlerContext.java:835) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.read(AbstractChannelHandlerContext.java:814) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.handler.flow.FlowControlHandler.read(FlowControlHandler.java:144) ~[netty-handler-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeRead(AbstractChannelHandlerContext.java:837) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.read(AbstractChannelHandlerContext.java:814) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline.read(DefaultChannelPipeline.java:1004) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannel.read(AbstractChannel.java:290) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline$HeadContext.readIfIsAutoRead(DefaultChannelPipeline.java:1422) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelReadComplete(DefaultChannelPipeline.java:1417) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelReadComplete(AbstractChannelHandlerContext.java:482) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelReadComplete(AbstractChannelHandlerContext.java:463) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.DefaultChannelPipeline.fireChannelReadComplete(DefaultChannelPipeline.java:925) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.local.LocalChannel.readInbound(LocalChannel.java:302) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.local.LocalChannel.finishPeerRead0(LocalChannel.java:445) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.local.LocalChannel.access$400(LocalChannel.java:50) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.channel.local.LocalChannel$5.run(LocalChannel.java:403) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174) ~[netty-common-4.1.97.Final.jar:?]
at io.netty.channel.DefaultEventLoop.run(DefaultEventLoop.java:54) ~[netty-transport-4.1.97.Final.jar:?]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.97.Final.jar:?]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.97.Final.jar:?]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
ReplayMod, when recording Singleplayer where packets are passed between server and client as Packet
objects, needs to serialize Packet
objects so it can write them to the recording file. The serialization works by calling Packet.write
on the packet. It does so on the netty thread before MC's packet handler, you can see the PacketListener.channelRead
method in the full stacktrace.
FAPI's UntypedPayload.write
however seems to consume its internal buffer when it is called, and so subsequent accesses to that buffer (in above case by FAPI's regular packet handler) will see an empty buffer.
If there's no deeper reason behind this, then the issue can be easily fixed by replacing the writeBytes
call with one which does not advance the readerIndex
of the source ByteBuf:
diff --git a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/UntypedPayload.java b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/UntypedPayload.java
index 028734a4..84bf92f3 100644
--- a/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/UntypedPayload.java
+++ b/fabric-networking-api-v1/src/main/java/net/fabricmc/fabric/impl/networking/payload/UntypedPayload.java
@@ -42,6 +42,6 @@ public record UntypedPayload(Identifier id, PacketByteBuf buffer) implements Res
@Override
public void write(PacketByteBuf buf) {
- buf.writeBytes(buffer);
+ buf.writeBytes(buffer, buffer.readerIndex(), buffer.readableBytes());
}
}
Side note: If FAPI provides a way to broadcast custom packets (I'm not familiar with it, so idk), then that may cause similar issues because the same packet may need to be serialized multiple times, once for each receiver, in that scenario as well, and so all but the first receiver would just get an empty packet.