Error sending packet clientbound/minecraft:set_entity_data
SenaxxZz opened this issue · 5 comments
This issue is not solved in a development build
Describe the bug
When sending an entity metadata packet for an NPC, the server throws a ClassCastException caused by an incorrect type conversion between DataWatcher$Item and DataWatcher$c. This occurs when attempting to encode the clientbound/minecraft:set_entity_data packet.
To Reproduce
Steps to reproduce the behavior:
Create an NPC using ProtocolLib and send a spawn packet.
Send metadata (e.g., custom name, entity flags) to a viewer.
Encounter the ClassCastException.
Expected behavior
The NPC should spawn and have the custom metadata applied correctly without causing a ClassCastException.
Screenshots
N/A
Version Info
ProtocolLib version: 5.3.0
Server version: Spigot 1.20.6
Additional context
This issue may be related to a compatibility issue between ProtocolLib and Spigot 1.20.6. The error prevents the correct application of entity metadata to NPCs.
My code :
try {
PacketContainer metadataPacket = protocolManager.createPacket(PacketType.Play.Server.ENTITY_METADATA);
int entityId = npcUUID.hashCode();
metadataPacket.getIntegers().write(0, entityId);
// Création de WrappedDataWatcher
WrappedDataWatcher watcher = new WrappedDataWatcher();
WrappedDataWatcher.WrappedDataWatcherObject entityFlags =
new WrappedDataWatcher.WrappedDataWatcherObject(0, WrappedDataWatcher.Registry.get(Byte.class));
watcher.setObject(entityFlags, (byte) 0x00);
WrappedDataWatcher.WrappedDataWatcherObject customName =
new WrappedDataWatcher.WrappedDataWatcherObject(2, WrappedDataWatcher.Registry.getChatComponentSerializer(true));
watcher.setObject(customName, Optional.of(WrappedChatComponent.fromText("§eMon NPC").getHandle()));
WrappedDataWatcher.WrappedDataWatcherObject customNameVisible =
new WrappedDataWatcher.WrappedDataWatcherObject(3, WrappedDataWatcher.Registry.get(Boolean.class));
watcher.setObject(customNameVisible, true);
List<WrappedWatchableObject> watchableObjects = watcher.getWatchableObjects();
metadataPacket.getWatchableCollectionModifier().write(0, watchableObjects);
protocolManager.sendServerPacket(viewer, metadataPacket);
logInfo("Metadata packet successfully sent to " + viewer.getName() + " for NPC with ID " + entityId);
} catch (Exception e) {
logError("Error sending metadata packet: " + e.getMessage(), e);
}
My error :
[12:40:27] [Netty Epoll Server IO #1/ERROR]: Error sending packet clientbound/minecraft:set_entity_data
io.netty.handler.codec.EncoderException: Failed to encode packet 'clientbound/minecraft:set_entity_data'
at net.minecraft.network.codec.IdDispatchCodec.a(SourceFile:55) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at net.minecraft.network.codec.IdDispatchCodec.encode(SourceFile:14) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at net.minecraft.network.PacketEncoder.a(SourceFile:26) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at net.minecraft.network.PacketEncoder.encode(SourceFile:12) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:107) ~[netty-codec-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:881) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:863) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:968) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:856) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:113) ~[netty-codec-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:881) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:863) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:968) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:856) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:120) ~[netty-codec-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:881) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:863) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:968) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:856) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.ChannelOutboundHandlerAdapter.write(ChannelOutboundHandlerAdapter.java:113) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at net.minecraft.network.NetworkManager$2.write(NetworkManager.java:543) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:881) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:940) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.write(AbstractChannelHandlerContext.java:966) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannelHandlerContext.writeAndFlush(AbstractChannelHandlerContext.java:934) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.DefaultChannelPipeline.writeAndFlush(DefaultChannelPipeline.java:1020) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.AbstractChannel.writeAndFlush(AbstractChannel.java:311) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
at com.comphenix.protocol.injector.netty.channel.NettyChannelProxy.writeAndFlush(NettyChannelProxy.java:227) ~[?:?]
at com.comphenix.protocol.injector.netty.channel.NettyChannelProxy.writeAndFlush(NettyChannelProxy.java:233) ~[?:?]
at net.minecraft.network.NetworkManager.c(NetworkManager.java:366) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at net.minecraft.network.NetworkManager.lambda$sendPacket$12(NetworkManager.java:359) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at com.comphenix.protocol.injector.netty.channel.NettyEventLoopProxy.lambda$proxyRunnable$2(NettyEventLoopProxy.java:49) ~[?:?]
at io.netty.util.concurrent.AbstractEventExecutor.runTask(AbstractEventExecutor.java:174) ~[netty-common-4.1.97.Final.jar:4.1.97.Final]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:167) ~[netty-common-4.1.97.Final.jar:4.1.97.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:470) ~[netty-common-4.1.97.Final.jar:4.1.97.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:413) ~[netty-transport-classes-epoll-4.1.97.Final.jar:4.1.97.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997) ~[netty-common-4.1.97.Final.jar:4.1.97.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.97.Final.jar:4.1.97.Final]
at java.base/java.lang.Thread.run(Thread.java:1583) [?:?]
Caused by: java.lang.ClassCastException: class net.minecraft.network.syncher.DataWatcher$Item cannot be cast to class net.minecraft.network.syncher.DataWatcher$c (net.minecraft.network.syncher.DataWatcher$Item and net.minecraft.network.syncher.DataWatcher$c are in unnamed module of loader java.net.URLClassLoader @65b3120a)
at net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata.a(SourceFile:25) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at net.minecraft.network.protocol.game.PacketPlayOutEntityMetadata.b(SourceFile:44) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at net.minecraft.network.codec.StreamCodec$6.encode(SourceFile:42) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at net.minecraft.network.codec.StreamCodec$9.a(SourceFile:97) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at net.minecraft.network.codec.StreamCodec$9.encode(SourceFile:87) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
at net.minecraft.network.codec.IdDispatchCodec.a(SourceFile:53) ~[spigot-1.20.6-R0.1-SNAPSHOT.jar:4149-Spigot-e2c1eee-4e7d749]
... 38 more
im having the exact same issue with this code
https://paste.md-5.net/isulumuyel.cs
server spigot 1.21 (tested paper and both on 1.21.1 and 1.21.3)
tested with various different versions of protocol lib and seems to be an issue with 1.20
same code was fine on 1.16.5
dependencies {
compileOnly "org.spigotmc:spigot-api:1.21.1-R0.1-SNAPSHOT"
compileOnly "org.spigotmc:spigot:1.21.1-R0.1-SNAPSHOT"
compileOnly group: "com.comphenix.protocol", name: "ProtocolLib", version: "4.8.0";
}
the problem is specifically at
watcher.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(16, boolSerializer), true);
without that, even sending the packet, it wont error: https://paste.md-5.net/alazotiyis.pl
another example that will produce the same error using Wrappers instead
https://paste.md-5.net/ojojudaqih.coffeescript
for SenaxxZz and those in the future:
Credits: Flo504 on discord spigotmc
Basically, you are using DataItem where you should use DataValue
https://mappings.dev/1.21.4/net/minecraft/network/syncher/SynchedEntityData$DataItem.html
https://mappings.dev/1.21.4/net/minecraft/network/syncher/SynchedEntityData$DataValue.html
The set metadata packet changed (around the 1.20 iirc). I don't use ProtocolLib but here are some examples that use raw nms:
Before:
https://github.com/Flowsqy/ShopChest/blob/master/nms/v1_19_R1/src/main/java/de/epiceric/shopchest/nms/v1_19_R1/FakeEntityImpl.java#L101
Now:
https://github.com/Flowsqy/ShopChest/blob/master/nms/v1_20_R1/src/main/java/de/epiceric/shopchest/nms/v1_20_R1/FakeEntityImpl.java#L97
Given that i managed to come up with this: https://paste.md-5.net/hunaviveju.cs
it results on an item display client side packet that will update its form on each request
you will need:
wiki:
https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol#Set_Entity_Metadata
https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Entity_metadata#Display
mappings:
https://mappings.dev/1.21.1/net/minecraft/world/entity/Display$ItemDisplay.html
build tools:
https://www.spigotmc.org/wiki/buildtools/ -> open the project and look into the remapped source code to see how the class you are trying to operate with is structured, you want to look for things like:
"DATA_..." are the "bridges" you use to interact with the actual final values, i.e.
item = Display.ItemDisplay.class.getDeclaredField("r");
"FLAG_..." are the int values of the indexed on an 8 bit number, i.e.
String binaryRepresentation = String.format("%8s", Integer.toBinaryString((byte) (0x40 + 0x01) & 0xFF)).replace(' ', '0');
each bit represents a flag, "flag 0" represents bit 0 in the byte
update your build.gradle to remap your classes that you use from remapped-mojang dependency
https://paste.md-5.net/ejapaxujuz.rb
and a fuck load of patience and attention to detail