ProtocolLib

3M Downloads

Packet encoding of packet ID 82 threw (skippable? false)

MrClean1337 opened this issue ยท 6 comments

commented
  • This issue is not solved in a development build

Describe the bug
I try to send a ClientboundSetEntityDataPacket to attach some entitydata for a armorstand via mojangmappings.
protocollib.sendServerPacket(nearby, PacketContainer.fromPacket(new ClientboundSetEntityDataPacket(stand.getBukkitEntity().getEntityId(), stand.getEntityData().packDirty())));

But somehow all nearby players exept one player will be kicked from the server with error Packet encoding of packet ID 82 threw (skippable? false)
The players will be kicked randomly, only one player will stay online.
It worked smoothly before the 1.19.4 upgrade.

To Reproduce
Steps to reproduce the behavior:

  1. Use latest paper and protocollib
  2. Create a fake armorstand with 1.19.4 mojang mappings, with the ClientboundAddEntityPacket and ClientboundSetEntityDataPacket
  3. Go with two or more latest minecraft clients without mods on the server
  4. Spawn the client armorstand

Expected behavior
Spawn a client armorstand via ClientboundAddEntityPacket and attach entitydata via ClientboundSetEntityDataPacket.

Screenshots
none

My code to spawn the armorstands and some items
https://pastebin.com/zgd67BNj <-- mappings are 1.19.4-R0.1-SNAPSHOT

ERROR LOG
https://pastebin.com/5sL6xgRu

Version Info
Latest Paper version git-Paper-516 (MC: 1.19.4) and "lastStableBuild" of protocollib
https://pastebin.com/Rfug3Pt8

Additional context
Worked before upgrading my development servers to the latest builds of plugins and server version

commented

The packDirty method is marked as @Nullable which means it can return null by intention. The method only packs dirty metadata entries (e.g. data that has not been broadcasted to players). If no dirty metadata is available, it returns null. That' s also the reason why every player except for one will be kicked. The method only returns null for the first player that you process.

To fix this, introduce a new variable and store item.getEntityData().packDirty() in it before you enter the loop in line 65. And also check if the result is null. In this case, you should not be sending any Metadat Packet.

commented

The packDirty method is marked as @Nullable which means it can return null by intention. The method only packs dirty metadata entries (e.g. data that has not been broadcasted to players). If no dirty metadata is available, it returns null. That' s also the reason why every player except for one will be kicked. The method only returns null for the first player that you process.

To fix this, introduce a new variable and store item.getEntityData().packDirty() in it before you enter the loop in line 65. And also check if the result is null. In this case, you should not be sending any Metadat Packet.

Okay I updated my code.
Now it looks like this and I get the exact same error:

        ArmorStand holoTop = new ArmorStand(world, loc.getX(), loc.getY(), loc.getZ());
        holoTop.getBukkitEntity().setGravity(false);
        holoTop.getBukkitEntity().setCustomNameVisible(true);
        holoTop.setInvisible(true);


        ArmorStand holoBottom = new ArmorStand(world, loc.getX(), loc.getY()-0.25D, loc.getZ());
        holoBottom.getBukkitEntity().setGravity(false);
        holoBottom.getBukkitEntity().setCustomNameVisible(true);
        holoBottom.setInvisible(true);

        // Text part
        String txt = RewardManager.getTier_holoText(price.tier);
        holoTop.getBukkitEntity().setCustomName(LanguageManager.getString(LanguageKeys.holo_top));
        holoBottom.getBukkitEntity().setCustomName(txt);

        // Text message
        votecase.getPlayer().sendMessage(LanguageManager.getPrefix() + LanguageManager.getString(LanguageKeys.chat_msg_reward));
        votecase.getPlayer().sendMessage(txt);

        // pack dirty entitydata
        final List <SynchedEntityData.DataValue <?>> holoTop_entityData = holoTop.getEntityData().packDirty();
        final List <SynchedEntityData.DataValue <?>> holoBottom_entityData = holoBottom.getEntityData().packDirty();

        // Paket part
        ProtocolManager manager = ProtocolLibrary.getProtocolManager();
        try {
            for(Player nearby : votecase.getNearbyplayers()) {
                // Armorstand pakets

                // Top
                manager.sendServerPacket(nearby,
                        PacketContainer.fromPacket(new ClientboundAddEntityPacket(holoTop)));

                if(holoTop_entityData != null) manager.sendServerPacket(nearby,
                        PacketContainer.fromPacket(new ClientboundSetEntityDataPacket(holoTop.getBukkitEntity().getEntityId(),
                                holoTop_entityData)));

                // Bottom
                if(holoBottom_entityData != null) manager.sendServerPacket(nearby,
                        PacketContainer.fromPacket(new ClientboundAddEntityPacket(holoBottom)));
                manager.sendServerPacket(nearby,
                        PacketContainer.fromPacket(new ClientboundSetEntityDataPacket(holoBottom.getBukkitEntity().getEntityId(),
                                holoBottom_entityData)));

                // Despawn pakets
                toDestroyPakets.put(getLoc().add(0.5D, -0.25D, 0.5D), new int[]{holoBottom.getBukkitEntity().getEntityId()});
                toDestroyPakets.put(loc, new int[]{holoTop.getBukkitEntity().getEntityId()});
            }
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
commented

Please share the new stack trace @MrClean1337

commented

Please share the new stack trace @MrClean1337

Of course!
https://pastebin.com/YmQDHpyg

commented

You added the non-null checks to the wrong statement. Now, the ADD_ENTITY packet is not sent if the entity data is null. However, the intended behavior would be that the ENTITY_METADATA packet is not sent in this case.

commented

Following this, fixed the issue:

The packDirty method is marked as @Nullable which means it can return null by intention. The method only packs dirty metadata entries (e.g. data that has not been broadcasted to players). If no dirty metadata is available, it returns null. That' s also the reason why every player except for one will be kicked. The method only returns null for the first player that you process.

To fix this, introduce a new variable and store item.getEntityData().packDirty() in it before you enter the loop in line 65. And also check if the result is null. In this case, you should not be sending any Metadat Packet.

@lukalt Thank you for your help! I got it fixed now.
... I overlooked a another function, that has the same pakets, but for a another case.
Applying your suggestion fixed the bug now.