Packet encoding of packet ID 82 threw (skippable? false)
MrClean1337 opened this issue ยท 6 comments
- 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:
- Use latest paper and protocollib
- Create a fake armorstand with 1.19.4 mojang mappings, with the ClientboundAddEntityPacket and ClientboundSetEntityDataPacket
- Go with two or more latest minecraft clients without mods on the server
- 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
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.
The
packDirty
method is marked as@Nullable
which means it can returnnull
by intention. The method only packsdirty
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();
}
Please share the new stack trace @MrClean1337
Please share the new stack trace @MrClean1337
Of course!
https://pastebin.com/YmQDHpyg
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.
Following this, fixed the issue:
The
packDirty
method is marked as@Nullable
which means it can returnnull
by intention. The method only packsdirty
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.