Bug related to entity metadata packet
GoodestEnglish opened this issue · 2 comments
- This issue is not solved in a development build
Describe the bug
I did 3 hours of research in google but no luck on finding a solution. So I assume this is a bug related to the 1.19.3 or above.
I was trying to create a 'corpse' in 1.20 paper which a fake player sleep on the bed. Here's my code:
public void createCorpse(Player player, Location location) {
int fakeEntityID = ID--;
//Get the skin of the player
WrappedGameProfile playerGameProfile = WrappedGameProfile.fromPlayer(player);
Collection<WrappedSignedProperty> textureProperty = playerGameProfile.getProperties().get("textures");
//Create fake player data
String name = "看什麼看";
PlayerInfoData infoData = new PlayerInfoData(new WrappedGameProfile(UUID.randomUUID(), name), 0, EnumWrappers.NativeGameMode.CREATIVE, WrappedChatComponent.fromText(name));
infoData.getProfile().getProperties().replaceValues("textures", textureProperty);
//Create fake player data info packet
PacketContainer infoPacket = protocolManager.createPacket(PacketType.Play.Server.PLAYER_INFO);
infoPacket.getPlayerInfoActions().write(0, EnumSet.of(EnumWrappers.PlayerInfoAction.ADD_PLAYER));
infoPacket.getPlayerInfoDataLists().write(1, Collections.singletonList(infoData));
//Create fake player spawn packet
PacketContainer spawnPacket = protocolManager.createPacket(PacketType.Play.Server.NAMED_ENTITY_SPAWN);
spawnPacket.getIntegers().write(0, fakeEntityID);
spawnPacket.getUUIDs().write(0, infoData.getProfileId());
spawnPacket.getDoubles().write(0, player.getLocation().getX());
spawnPacket.getDoubles().write(1, player.getLocation().getY());
spawnPacket.getDoubles().write(2, player.getLocation().getZ());
spawnPacket.getBytes().write(0, (byte) 0);
spawnPacket.getBytes().write(1, (byte) 0);
//Create fake player sleep packet
PacketContainer sleepPacket = protocolManager.createPacket(PacketType.Play.Server.ENTITY_METADATA);
sleepPacket.getIntegers().write(0, fakeEntityID);
WrappedDataWatcher watcher = new WrappedDataWatcher();
watcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(6, WrappedDataWatcher.Registry.get(EnumWrappers.getEntityPoseClass())), EnumWrappers.EntityPose.SLEEPING);
watcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(14, WrappedDataWatcher.Registry.getBlockPositionSerializer(false)), new BlockPosition(location.toVector()));
sleepPacket.getWatchableCollectionModifier().write(0, watcher.getWatchableObjects());
//Finally, send packet
sendPacketGlobal(infoPacket);
sendPacketGlobal(spawnPacket);
sendPacketGlobal(sleepPacket);
}
These code however crashes the client when the entity metadata packet is sent. Her's the crash log:
[08:33:44 ERROR]: Packet encoding of packet ID 82 threw (skippable? false)
java.lang.ClassCastException: class net.minecraft.network.syncher.DataWatcher$Item cannot be cast to class net.minecraft.network.syncher.DataWatcher$b (net.minecraft.network.syncher.DataWatcher$Item and net.minecraft.network.syncher.DataWatcher$b are in unnamed module of loader java.net.URLClassLoader @6bf2d08e)
at net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket.pack(ClientboundSetEntityDataPacket.java:17) ~[?:?]
at net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket.write(ClientboundSetEntityDataPacket.java:38) ~[?:?]
at net.minecraft.network.PacketEncoder.encode(PacketEncoder.java:41) ~[paper-1.20.jar:git-Paper-17]
at net.minecraft.network.PacketEncoder.encode(PacketEncoder.java:14) ~[paper-1.20.jar:git-Paper-17]
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107) ~[netty-codec-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:881) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:863) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:968) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:856) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:120) ~[netty-codec-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:881) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:863) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:968) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:856) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:113) ~[netty-codec-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:881) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:940) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:966) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:934) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1020) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:311) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at com.comphenix.protocol.injector.netty.channel.NettyChannelProxy.writeAndFlush(NettyChannelProxy.java:227) ~[ProtocolLib (4).jar:?]
at com.comphenix.protocol.injector.netty.channel.NettyChannelProxy.writeAndFlush(NettyChannelProxy.java:233) ~[ProtocolLib (4).jar:?]
at net.minecraft.network.Connection.doSendPacket(Connection.java:467) ~[?:?]
at net.minecraft.network.Connection.lambda$sendPacket$11(Connection.java:441) ~[?:?]
at com.comphenix.protocol.injector.netty.channel.NettyEventLoopProxy.lambda$proxyRunnable$2(NettyEventLoopProxy.java:48) ~[ProtocolLib (4).jar:?]
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174) ~[netty-common-4.1.87.Final.jar:4.1.87.Final]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167) ~[netty-common-4.1.87.Final.jar:4.1.87.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) ~[netty-common-4.1.87.Final.jar:4.1.87.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:569) ~[netty-transport-4.1.87.Final.jar:4.1.87.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.87.Final.jar:4.1.87.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.87.Final.jar:4.1.87.Final]
at java.lang.Thread.run(Thread.java:833) ~[?:?]
And here's the client crash message:
I've also tested these code with 1.19.2 paper with some player info packet changed (Well, some fields are in 1.20 but not in 1.19.2). And the code work successfully.
To Reproduce
Steps to reproduce the behavior:
- Paste the createCorpse method in somewhere and trigger it by using a command
- The above error occurred
Version Info
https://pastebin.com/NwEDzrvS
In MC 1.19, WrappedDataWatcherObject was replaced by WrappedDataValue.
Instead of
WrappedDataWatcher watcher = new WrappedDataWatcher();
watcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(6, WrappedDataWatcher.Registry.get(EnumWrappers.getEntityPoseClass())), EnumWrappers.EntityPose.SLEEPING);
watcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(14, WrappedDataWatcher.Registry.getBlockPositionSerializer(false)), new BlockPosition(location.toVector()));
sleepPacket.getWatchableCollectionModifier().write(0, watcher.getWatchableObjects());
you will have to do something like this:
sleepPacket.getDataValueCollectionModifier().write(0, List.of(
new WrappedDataValue(6, WrappedDataWatcher.Registry.get(EnumWrappers.getEntityPoseClass()), EnumWrappers.EntityPose.SLEEPING)),
new WrappedDataValue(14, WrappedDataWatcher.Registry.getBlockPositionSerializer(false), new BlockPosition(location.toVector()))
))
Please note that the third parameter of the constructor takes the value as an unwrapped, NMS object. So you either provide the NMS value in the constructor or you use the setValue
method of WrappedDataValue
that automatically unwraps the provided value if necessary.