dmulloy2 / ProtocolLib

Provides read and write access to the Minecraft protocol with Bukkit.
GNU General Public License v2.0
997 stars 261 forks source link

Player disconnected when sending clientbound/minecraft:set_entity_data packet (Error sending packet clientbound/minecraft:set_entity_data (skippable? false)) #2987

Open Ghost-chu opened 1 month ago

Ghost-chu commented 1 month ago

Describe the bug A clear and concise description of what the bug is.

When plugin sending a series about spawn item entity packets to player, the player get disconnected due an ClassCastException.

Error sending packet clientbound/minecraft:set_entity_data (skippable? false)

[23:45:01 ERROR]: Error sending packet clientbound/minecraft:set_entity_data (skippable? false)
io.netty.handler.codec.EncoderException: Failed to encode packet 'clientbound/minecraft:set_entity_data'
        at net.minecraft.network.codec.IdDispatchCodec.encode(IdDispatchCodec.java:53) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.codec.IdDispatchCodec.encode(IdDispatchCodec.java:20) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.PacketEncoder.encode(PacketEncoder.java:26) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.PacketEncoder.encode(PacketEncoder.java:12) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        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.Connection$2.write(Connection.java:750) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        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.DefaultChannelPipeline.write(DefaultChannelPipeline.java:1015) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
        at io.netty.channel.AbstractChannel.write(AbstractChannel.java:301) ~[netty-transport-4.1.97.Final.jar:4.1.97.Final]
        at ProtocolLib (3).jar/com.comphenix.protocol.injector.netty.channel.NettyChannelProxy.write(NettyChannelProxy.java:210) ~[ProtocolLib (3).jar:?]
        at ProtocolLib (3).jar/com.comphenix.protocol.injector.netty.channel.NettyChannelProxy.write(NettyChannelProxy.java:199) ~[ProtocolLib (3).jar:?]
        at net.minecraft.network.Connection.doSendPacket(Connection.java:505) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.Connection.lambda$sendPacket$13(Connection.java:490) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at ProtocolLib (3).jar/com.comphenix.protocol.injector.netty.channel.NettyEventLoopProxy.lambda$proxyRunnable$2(NettyEventLoopProxy.java:48) ~[ProtocolLib (3).jar:?]
        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.nio.NioEventLoop.run(NioEventLoop.java:569) ~[netty-transport-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 org.bukkit.craftbukkit.inventory.CraftItemStack cannot be cast to class net.minecraft.world.item.ItemStack (org.bukkit.craftbukkit.inventory.CraftItemStack and net.minecraft.world.item.ItemStack are in unnamed module of loader java.net.URLClassLoader @484b61fc)
        at net.minecraft.world.item.ItemStack$1.encode(ItemStack.java:157) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.syncher.SynchedEntityData$DataValue.write(SynchedEntityData.java:226) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket.pack(ClientboundSetEntityDataPacket.java:24) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket.write(ClientboundSetEntityDataPacket.java:44) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.codec.StreamCodec$2.encode(StreamCodec.java:38) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.codec.StreamCodec$5.encode(StreamCodec.java:88) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        at net.minecraft.network.codec.StreamCodec$5.encode(StreamCodec.java:78) ~[paper-1.20.6.jar:1.20.6-137-bd5867a]
        ... 39 more
[23:45:01 INFO]: Ghost_chu lost connection: Internal Exception: io.netty.handler.codec.EncoderException: Failed to encode packet 'clientbound/minecraft:set_entity_data'

To Reproduce

        sendPacketToAll(fakeItemSpawnPacket);
        sendPacketToAll(fakeItemMetaPacket);
        sendPacketToAll(fakeItemVelocityPacket);
    @Override
    public @NotNull PacketContainer createFakeItemSpawnPacket(int entityID, @NotNull Location displayLocation) {
        //First, create a new packet to spawn item
        PacketContainer fakeItemPacket = manager.getProtocolManager().createPacket(PacketType.Play.Server.SPAWN_ENTITY);
        //and add data based on packet class in NMS  (global scope variable)
        //Reference: https://wiki.vg/Protocol#Spawn_Object
        fakeItemPacket.getIntegers()
                //Entity ID
                .write(0, entityID);
        //Velocity x
        fakeItemPacket.getEntityTypeModifier().write(0, EntityType.ITEM);
        //UUID
        fakeItemPacket.getUUIDs().write(0, UUID.randomUUID());
        //Location
        fakeItemPacket.getDoubles()
                //X
                .write(0, displayLocation.getX())
                //Y
                .write(1, displayLocation.getY())
                //Z
                .write(2, displayLocation.getZ());
        return fakeItemPacket;
    }

    @Override
    public @NotNull PacketContainer createFakeItemMetaPacket(int entityID, @NotNull ItemStack itemStack) {
        //Next, create a new packet to update item data (default is empty)
        PacketContainer fakeItemMetaPacket = manager.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_METADATA);
        //Entity ID
        fakeItemMetaPacket.getIntegers().write(0, entityID);

        //List<DataWatcher$Item> Type are more complex
        //Create a DataWatcher
        WrappedDataWatcher wpw = new WrappedDataWatcher();
        //https://wiki.vg/index.php?title=Entity_metadata#Entity
        if (plugin.getConfig().getBoolean("shop.display-item-use-name")) {
            String itemName = GsonComponentSerializer.gson().serialize(Util.getItemStackName(itemStack));
            wpw.setObject(2, WrappedDataWatcher.Registry.getChatComponentSerializer(true), Optional.of(WrappedChatComponent.fromJson(itemName).getHandle()));
            wpw.setObject(new WrappedDataWatcher.WrappedDataWatcherObject(3, WrappedDataWatcher.Registry.get(Boolean.class)), true);
        }

        //Must in the certain slot:https://wiki.vg/Entity_metadata#Item
        wpw.setObject(8, WrappedDataWatcher.Registry.getItemStackSerializer(false), itemStack);
        //Add it
        //For 1.19.2+, we need to use DataValue instead of WatchableObject
        //Check for new version protocolLib
        try {
            Class.forName("com.comphenix.protocol.wrappers.WrappedDataValue");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Unable to initialize packet, ProtocolLib update needed", e);
        }
        //Convert List<WrappedWatchableObject> to List<WrappedDataValue>
        List<WrappedWatchableObject> wrappedWatchableObjects = wpw.getWatchableObjects();
        List<WrappedDataValue> wrappedDataValues = new java.util.LinkedList<>();
        for (WrappedWatchableObject wrappedWatchableObject : wrappedWatchableObjects) {
            WrappedDataWatcher.WrappedDataWatcherObject watchableObject = wrappedWatchableObject.getWatcherObject();
            wrappedDataValues.add(new WrappedDataValue(watchableObject.getIndex(), watchableObject.getSerializer(), wrappedWatchableObject.getRawValue()));
        }
        fakeItemMetaPacket.getDataValueCollectionModifier().write(0, wrappedDataValues);
        return fakeItemMetaPacket;
    }

    @Override
    public @NotNull PacketContainer createFakeItemVelocityPacket(int entityID) {
        //And, create a entity velocity packet to make it at a proper location (otherwise it will fly randomly)
        PacketContainer fakeItemVelocityPacket = manager.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_VELOCITY);
        fakeItemVelocityPacket.getIntegers()
                //Entity ID
                .write(0, entityID)
                //Velocity x
                .write(1, 0)
                //Velocity y
                .write(2, 0)
                //Velocity z
                .write(3, 0);
        return fakeItemVelocityPacket;
    }

Expected behavior A clear and concise description of what you expected to happen.

The error shouldn't appears.

Screenshots If applicable, add screenshots to help explain your problem.

image

Version Info Provide your ProtocolLib install info with /protocol dump through pastebin.

[dump-2024-06-07_23.47.42.txt](https://github.com/user-attachments/files/15741983/dump-2024-06-07_23.47.42.txt)

Additional context Add any other context about the problem here.

[23:50:08 INFO]: This server is running Paper version 1.20.6-137-master@bd5867a (2024-06-04T21:04:28Z) (Implementing API version 1.20.6-R0.1-SNAPSHOT)
You are running the latest version
Previous version: git-Paper-49 (MC: 1.20.6)
>
dmulloy2 commented 1 month ago

Thank you for the detailed report. It seems like at some point, the Bukkit item stack is not being converted into a NMS stack. I will look into this further

dmulloy2 commented 1 month ago

Give build 710 a try. I also added some helper methods to clean things up a little bit. Probably won't be able to use those right away, but maybe something to look forward to

xtb7 commented 3 weeks ago

Give build 710 a try. I also added some helper methods to clean things up a little bit. Probably won't be able to use those right away, but maybe something to look forward to

I also experienced this error. Build 716 seems to work for me, but later ones don't.