Skip to main content
The InventoryListener intercepts inventory-related packets to format both inventory titles and the items displayed within them. This allows custom GUI titles and item display names/lore to use MiniMessage formatting and placeholders.

Packet Types

Intercepts two packet types:
  • PacketType.Play.Server.OPEN_WINDOW - Sent when an inventory GUI is opened (for title formatting)
  • PacketType.Play.Server.WINDOW_ITEMS - Sent when inventory contents are updated (for item formatting)

Configuration

listeners:
  inventory:
    titles: true  # Format inventory window titles
    items: true   # Format items in inventories
Each aspect can be individually enabled or disabled.

Class Structure

public class InventoryListener extends AbstractListener {

    public InventoryListener(ProcessHandler processHandler, ConfigManager configManager) {
        super(processHandler, configManager);
    }

    @Override
    public void onPacketPlaySend(PacketPlaySendEvent e) {
        // Implementation
    }
}
Source: InventoryListener.java:12-36

Implementation Details

1. Packet Type Validation

PacketTypeCommon type = e.getPacketType();
if (type != PacketType.Play.Server.OPEN_WINDOW &&
    type != PacketType.Play.Server.WINDOW_ITEMS) return;
Source: InventoryListener.java:20-22 The listener only processes OPEN_WINDOW and WINDOW_ITEMS packets. Other packets are ignored.

2. Configuration Checks

Player player = e.getPlayer();
boolean titles = config.getOrDefault("listeners.inventory.titles", true);
boolean items = config.getOrDefault("listeners.inventory.items", true);
Source: InventoryListener.java:24-26 Retrieves separate configuration values for title and item formatting, allowing fine-grained control.

3. Inventory Title Processing

if (titles && type == PacketType.Play.Server.OPEN_WINDOW) {
    WrapperPlayServerOpenWindow packet = new WrapperPlayServerOpenWindow(e);
    packet.setTitle(handler.processComponent(packet.getTitle(), player));
}
Source: InventoryListener.java:28-31 When an inventory opens:
  1. Checks if title formatting is enabled
  2. Wraps the packet in WrapperPlayServerOpenWindow
  3. Processes the title component through ProcessHandler
  4. Updates the packet with the formatted title

4. Inventory Items Processing

else if (items && type == PacketType.Play.Server.WINDOW_ITEMS) {
    WrapperPlayServerWindowItems packet = new WrapperPlayServerWindowItems(e);
    packet.setItems(handler.processItems(packet.getItems(), player));
}
Source: InventoryListener.java:31-34 When inventory contents are updated:
  1. Checks if item formatting is enabled
  2. Wraps the packet in WrapperPlayServerWindowItems
  3. Processes all items through ProcessHandler.processItems()
  4. Updates the packet with the formatted items

Usage Examples

Custom GUI Title

When creating a custom inventory:
Inventory inv = Bukkit.createInventory(null, 27, "<gradient:blue:purple>Shop Menu</gradient>");
player.openInventory(inv);
The listener will:
  1. Intercept the OPEN_WINDOW packet
  2. Parse the MiniMessage gradient formatting
  3. Display “Shop Menu” with a blue-to-purple gradient

Item Display Names

When setting item metadata:
ItemStack item = new ItemStack(Material.DIAMOND_SWORD);
ItemMeta meta = item.getItemMeta();
meta.displayName(Component.text("<rainbow>Legendary Sword</rainbow>"));
meta.lore(List.of(
    Component.text("Damage: %player_strength%"),
    Component.text("<italic:false><gray>Epic Weapon")
));
item.setItemMeta(meta);
The listener will:
  1. Intercept the WINDOW_ITEMS packet
  2. Process the rainbow formatting in the display name
  3. Resolve the %player_strength% placeholder in the lore
  4. Apply the italic formatting to the description

Processing Flow

1

Inventory Opened

Server sends an OPEN_WINDOW packet
2

Interception

InventoryListener intercepts the packet
3

Title Extraction

Extracts the title component from the packet
4

Processing

Resolves placeholders and MiniMessage formatting
5

Update

Sets the formatted title back to the packet
6

Display

Player sees the inventory with formatted title

Per-Player Item Data

Since processing includes the player parameter, items can show personalized information:
meta.lore(List.of(
    Component.text("Owner: %player_name%"),
    Component.text("Value: $%player_balance%")
));
Each player sees their own name and balance in the item lore.

Dependencies

  • PacketEvents: For packet interception
  • WrapperPlayServerOpenWindow: Packet wrapper for inventory opening
  • WrapperPlayServerWindowItems: Packet wrapper for inventory contents
  • ProcessHandler: For placeholder resolution and formatting
    • processComponent() - For inventory titles
    • processItems() - For item collections

Common Use Cases

  1. Custom Shop Menus
    • Formatted shop titles with gradients
    • Item prices with placeholders
    • Dynamic item descriptions
  2. Player Statistics GUIs
    • Personalized stat displays
    • Real-time data in lore
    • Formatted category headers
  3. Quest/Achievement Menus
    • Colorful quest titles
    • Progress indicators in lore
    • Reward previews
  4. Administrative Panels
    • Formatted control panel titles
    • Option descriptions with player data
    • Status indicators

Build docs developers (and LLMs) love