Fix ClassCastException for replay player equipment

PacketProcessor passes Bukkit EquipmentSlots to REntity#setItem, which cast
them to the NMS EquipmentSlot. Take the Bukkit slot and map it to the NMS
slot when building the equipment packet.
This commit is contained in:
2026-10-19 08:38:42 +02:00
parent 097df865e5
commit 69aef9dfb6
2 changed files with 16 additions and 5 deletions
@@ -89,7 +89,7 @@ public class REntity {
private final int objectData;
@Getter
private String displayName;
protected final Map<Object, ItemStack> itemSlots;
protected final Map<org.bukkit.inventory.EquipmentSlot, ItemStack> itemSlots;
public REntity(REntityServer server, EntityType entityType, Location location) {
this(server, entityType, location, 0);
@@ -220,7 +220,7 @@ public class REntity {
.add(nameVisibleWatcher, displayName != null).build());
}
public void setItem(Object slot, ItemStack stack) {
public void setItem(org.bukkit.inventory.EquipmentSlot slot, ItemStack stack) {
itemSlots.put(slot, stack);
server.updateEntity(this, getEquipmentPacket(slot, stack));
}
@@ -368,8 +368,19 @@ public class REntity {
return packet;
}
protected Object getEquipmentPacket(Object slot, ItemStack stack) {
return new ClientboundSetEquipmentPacket(entityId, Collections.singletonList(Pair.of((EquipmentSlot) slot, CraftItemStack.asNMSCopy(stack))));
protected Object getEquipmentPacket(org.bukkit.inventory.EquipmentSlot slot, ItemStack stack) {
return new ClientboundSetEquipmentPacket(entityId, Collections.singletonList(Pair.of(toNmsSlot(slot), CraftItemStack.asNMSCopy(stack))));
}
private static EquipmentSlot toNmsSlot(org.bukkit.inventory.EquipmentSlot slot) {
return switch (slot) {
case HEAD -> EquipmentSlot.HEAD;
case CHEST -> EquipmentSlot.CHEST;
case LEGS -> EquipmentSlot.LEGS;
case FEET -> EquipmentSlot.FEET;
case OFF_HAND -> EquipmentSlot.OFFHAND;
default -> EquipmentSlot.MAINHAND;
};
}
private byte rotToByte(float rot) {
@@ -98,7 +98,7 @@ public class RPlayer extends REntity implements RInteractableEntity<RPlayer> {
packetSink.accept(getNamedSpawnPacket());
entityDataPacket().add(skinPartsDataWatcher, (byte) 0x7F).send(packetSink);
for (Map.Entry<Object, ItemStack> entry : itemSlots.entrySet()) {
for (Map.Entry<org.bukkit.inventory.EquipmentSlot, ItemStack> entry : itemSlots.entrySet()) {
packetSink.accept(getEquipmentPacket(entry.getKey(), entry.getValue()));
}