ProtocolLib

3M Downloads

Error sending packet clientbound/minecraft:set_entity_data

SenaxxZz opened this issue · 5 comments

commented

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        
commented

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

commented

another example that will produce the same error using Wrappers instead
https://paste.md-5.net/ojojudaqih.coffeescript

commented
2024-12-13.23-56-05.mp4
commented

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
image

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