Skip to content

Instantly share code, notes, and snippets.

@IllusionTheDev
Last active February 15, 2026 13:29
Show Gist options
  • Select an option

  • Save IllusionTheDev/dfca739a14ca9d32775a46dd8c47713e to your computer and use it in GitHub Desktop.

Select an option

Save IllusionTheDev/dfca739a14ca9d32775a46dd8c47713e to your computer and use it in GitHub Desktop.
Client-sided item lore (PacketEvents)
public interface ItemProcessor {
ItemStack processItem(ItemStack input);
ItemStack revertItem(ItemStack input); // Used for creative mode handling. Feel free to use PDC in processed items
}
public class SetCreativeItemListener implements PacketListener {
private final ItemProcessor processor;
public SetCreativeItemListener(ItemProcessor processor) {
this.processor = processor;
}
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (event.getPacketType() != Client.CREATIVE_INVENTORY_ACTION) {
return;
}
Player player = event.getPlayer();
WrapperPlayClientCreativeInventoryAction wrapper = new WrapperPlayClientCreativeInventoryAction(event);
ItemStack item = SpigotConversionUtil.toBukkitItemStack(wrapper.getItemStack()).clone();
if (item.isEmpty()) {
return;
}
ItemStack original = processor.revertItem(item);
ItemStack processed = processor.processItem(player, original);
wrapper.setItemStack(SpigotConversionUtil.fromBukkitItemStack(original));
event.markForReEncode(true);
// We need to convert slots to the correct index
int slot = wrapper.getSlot();
int adaptedSlot;
if (slot < 5) {
adaptedSlot = slot + 36;
}
else if (slot >= 36 && slot < 45) {
adaptedSlot = slot - 36;
}
else {
adaptedSlot = slot;
}
WrapperPlayServerSetPlayerInventory packet = new WrapperPlayServerSetPlayerInventory(adaptedSlot, SpigotConversionUtil.fromBukkitItemStack(processed));
PacketEvents.getAPI().getPlayerManager().sendPacket(event.getPlayer(), packet);
}
}
public class SetCursorItemListener implements PacketListener {
private final ItemProcessor processor;
public SetCursorItemListener(ItemProcessor processor) {
this.processor = processor;
}
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() != Server.SET_CURSOR_ITEM) {
return;
}
Player player = event.getPlayer();
WrapperPlayServerSetCursorItem wrapper = new WrapperPlayServerSetCursorItem(event);
ItemStack item = SpigotConversionUtil.toBukkitItemStack(wrapper.getStack());
ItemStack processed = processor.processItem(player, item);
if (item.equals(processed)) {
return;
}
wrapper.setStack(SpigotConversionUtil.fromBukkitItemStack(processed));
event.markForReEncode(true);
}
}
public class SetPlayerInventoryListener implements PacketListener {
private final ItemProcessor processor;
public SetPlayerInventoryListener(ItemProcessor processor) {
this.processor = processor;
}
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() != Server.SET_PLAYER_INVENTORY) {
return;
}
Player player = event.getPlayer();
WrapperPlayServerSetPlayerInventory wrapper = new WrapperPlayServerSetPlayerInventory(event);
ItemStack item = SpigotConversionUtil.toBukkitItemStack(wrapper.getStack());
ItemStack processed = processor.processItem(player, item);
if (item.equals(processed)) {
return;
}
wrapper.setStack(SpigotConversionUtil.fromBukkitItemStack(processed));
event.markForReEncode(true);
}
}
public class SetSlotListener implements PacketListener {
private final ItemProcessor processor;
public SetSlotListener(ItemProcessor processor) {
this.processor = processor;
}
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() != Server.SET_SLOT) {
return;
}
Player player = event.getPlayer();
WrapperPlayServerSetSlot wrapper = new WrapperPlayServerSetSlot(event);
ItemStack item = SpigotConversionUtil.toBukkitItemStack(wrapper.getItem());
ItemStack processed = processor.processItem(player, item);
if (item.equals(processed)) {
return;
}
wrapper.setItem(SpigotConversionUtil.fromBukkitItemStack(processed));
event.markForReEncode(true);
}
}
public class WindowItemsListener implements PacketListener {
private final ItemProcessor processor;
public WindowItemsListener(ItemProcessor processor) {
this.processor = processor;
}
@Override
public void onPacketSend(PacketSendEvent event) {
if (event.getPacketType() != Server.WINDOW_ITEMS) {
return;
}
Player player = event.getPlayer();
WrapperPlayServerWindowItems packet = new WrapperPlayServerWindowItems(event);
boolean replaced = false;
Optional<com.github.retrooper.packetevents.protocol.item.ItemStack> carriedItem = packet.getCarriedItem();
if (carriedItem.isPresent()) {
ItemStack bukkitItem = SpigotConversionUtil.toBukkitItemStack(carriedItem.get());
ItemStack processed = processor.processItem(player, bukkitItem);
if (!bukkitItem.equals(processed)) {
packet.setCarriedItem(SpigotConversionUtil.fromBukkitItemStack(processed));
replaced = true;
}
}
List<com.github.retrooper.packetevents.protocol.item.ItemStack> wrappedItems = packet.getItems();
for (int i = 0; i < wrappedItems.size(); i++) {
ItemStack bukkitItem = SpigotConversionUtil.toBukkitItemStack(wrappedItems.get(i));
ItemStack processed = processor.processItem(player, bukkitItem);
if (bukkitItem.equals(processed)) {
continue;
}
replaced = true;
wrappedItems.set(i, SpigotConversionUtil.fromBukkitItemStack(processed));
}
if (replaced) {
packet.setItems(wrappedItems);
event.markForReEncode(true);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment