Inventory Types
Minestom provides various inventory types matching Minecraft’s container types.Available Inventory Types
import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.InventoryType;
import net.kyori.adventure.text.Component;
// Chest inventories (9-54 slots)
Inventory chest = new Inventory(InventoryType.CHEST_1_ROW, Component.text("Small Chest"));
Inventory largeChest = new Inventory(InventoryType.CHEST_6_ROWS, Component.text("Large Chest"));
// Other container types
Inventory furnace = new Inventory(InventoryType.FURNACE, Component.text("Furnace"));
Inventory crafting = new Inventory(InventoryType.CRAFTING, Component.text("Crafting Table"));
Inventory hopper = new Inventory(InventoryType.HOPPER, Component.text("Hopper"));
Inventory anvil = new Inventory(InventoryType.ANVIL, Component.text("Anvil"));
Inventory beacon = new Inventory(InventoryType.BEACON, Component.text("Beacon"));
Creating Inventories
// With Component title
Inventory inventory = new Inventory(
InventoryType.CHEST_3_ROWS,
Component.text("My Inventory")
);
// With String title (auto-converted to Component)
Inventory simpleInventory = new Inventory(
InventoryType.CHEST_1_ROW,
"Simple Inventory"
);
Managing Items
Setting Items
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
// Set item at specific slot
inventory.setItemStack(0, ItemStack.of(Material.DIAMOND, 64));
// Set multiple items
inventory.setItemStack(1, ItemStack.of(Material.EMERALD, 32));
inventory.setItemStack(2, ItemStack.of(Material.GOLD_INGOT, 16));
// Clear slot
inventory.setItemStack(3, ItemStack.AIR);
Getting Items
// Get item at slot
ItemStack item = inventory.getItemStack(0);
// Check if slot is empty
if (item.isAir()) {
System.out.println("Slot is empty");
}
// Get all items
ItemStack[] items = inventory.getItemStacks();
Adding Items
// Try to add item to inventory
boolean added = inventory.addItemStack(ItemStack.of(Material.DIAMOND));
if (!added) {
player.sendMessage(Component.text("Inventory full!"));
}
Opening Inventories
For Players
import net.minestom.server.entity.Player;
// Open inventory for player
player.openInventory(inventory);
// Close player's current inventory
player.closeInventory();
// Check current inventory
Inventory current = player.getOpenInventory();
if (current != null) {
System.out.println("Player has inventory open");
}
Inventory Viewers
// Get all viewers
Set<Player> viewers = inventory.getViewers();
// Check if player is viewing
if (inventory.getViewers().contains(player)) {
System.out.println("Player is viewing inventory");
}
// Send message to all viewers
for (Player viewer : inventory.getViewers()) {
viewer.sendMessage(Component.text("Inventory updated!"));
}
Inventory Events
Click Events
import net.minestom.server.event.inventory.InventoryPreClickEvent;
import net.minestom.server.inventory.click.ClickType;
eventNode.addListener(InventoryPreClickEvent.class, event -> {
Player player = event.getPlayer();
Inventory inventory = event.getInventory();
int slot = event.getSlot();
ClickType clickType = event.getClickType();
ItemStack clicked = event.getClickedItem();
ItemStack cursor = event.getCursorItem();
// Cancel click
if (clicked.material() == Material.DIAMOND) {
event.setCancelled(true);
player.sendMessage(Component.text("You can't take this!"));
return;
}
// Log click
System.out.println("Slot " + slot + " clicked with " + clickType);
});
Open and Close Events
import net.minestom.server.event.inventory.InventoryOpenEvent;
import net.minestom.server.event.inventory.InventoryCloseEvent;
// Inventory opened
eventNode.addListener(InventoryOpenEvent.class, event -> {
Player player = event.getPlayer();
Inventory inventory = event.getInventory();
player.sendMessage(Component.text("Welcome to the shop!"));
});
// Inventory closed
eventNode.addListener(InventoryCloseEvent.class, event -> {
Player player = event.getPlayer();
Inventory inventory = event.getInventory();
// Clean up or save data
System.out.println(player.getUsername() + " closed inventory");
});
Player Inventory
Every player has aPlayerInventory for their personal items.
Accessing Player Inventory
import net.minestom.server.inventory.PlayerInventory;
PlayerInventory inventory = player.getInventory();
// Add items
inventory.addItemStack(ItemStack.of(Material.STONE, 64));
// Set hotbar slot
inventory.setItemStack(0, ItemStack.of(Material.DIAMOND_SWORD));
// Set armor
inventory.setHelmet(ItemStack.of(Material.DIAMOND_HELMET));
inventory.setChestplate(ItemStack.of(Material.DIAMOND_CHESTPLATE));
inventory.setLeggings(ItemStack.of(Material.DIAMOND_LEGGINGS));
inventory.setBoots(ItemStack.of(Material.DIAMOND_BOOTS));
// Set offhand
inventory.setItemInOffHand(ItemStack.of(Material.SHIELD));
Cursor Item
// Get item on cursor
ItemStack cursor = inventory.getCursorItem();
// Set cursor item
inventory.setCursorItem(ItemStack.of(Material.DIAMOND));
Custom Inventory GUIs
Simple Shop Example
public class ShopInventory {
public static Inventory createShop() {
Inventory shop = new Inventory(
InventoryType.CHEST_3_ROWS,
Component.text("Shop", NamedTextColor.GOLD)
);
// Add items for sale
shop.setItemStack(10, ItemStack.builder(Material.DIAMOND_SWORD)
.set(DataComponents.CUSTOM_NAME, Component.text("Legendary Sword"))
.set(DataComponents.LORE, List.of(
Component.text("Price: 100 Gold", NamedTextColor.YELLOW)
))
.build());
shop.setItemStack(12, ItemStack.builder(Material.DIAMOND_HELMET)
.set(DataComponents.CUSTOM_NAME, Component.text("Hero's Helmet"))
.set(DataComponents.LORE, List.of(
Component.text("Price: 75 Gold", NamedTextColor.YELLOW)
))
.build());
shop.setItemStack(14, ItemStack.builder(Material.GOLDEN_APPLE)
.amount(5)
.set(DataComponents.CUSTOM_NAME, Component.text("Golden Apples x5"))
.set(DataComponents.LORE, List.of(
Component.text("Price: 50 Gold", NamedTextColor.YELLOW)
))
.build());
return shop;
}
public static void setupShopHandlers(EventNode<Event> eventNode) {
eventNode.addListener(InventoryPreClickEvent.class, event -> {
if (event.getInventory() == null) return;
Component title = event.getInventory().getTitle();
if (!PlainTextComponentSerializer.plainText().serialize(title).equals("Shop")) {
return;
}
// Cancel all clicks in shop
event.setCancelled(true);
Player player = event.getPlayer();
ItemStack clicked = event.getClickedItem();
if (clicked.isAir()) return;
// Handle purchase
player.sendMessage(Component.text("You purchased: ")
.append(clicked.get(DataComponents.CUSTOM_NAME)));
player.closeInventory();
});
}
}
Paginated Inventory
public class PaginatedInventory {
private final List<ItemStack> items;
private int page = 0;
private final Inventory inventory;
public PaginatedInventory(List<ItemStack> items) {
this.items = items;
this.inventory = new Inventory(
InventoryType.CHEST_6_ROWS,
Component.text("Items - Page 1")
);
updatePage();
}
private void updatePage() {
// Clear inventory
for (int i = 0; i < 45; i++) {
inventory.setItemStack(i, ItemStack.AIR);
}
// Add items for current page (45 items per page)
int start = page * 45;
int end = Math.min(start + 45, items.size());
for (int i = start; i < end; i++) {
inventory.setItemStack(i - start, items.get(i));
}
// Navigation buttons
if (page > 0) {
inventory.setItemStack(45, ItemStack.builder(Material.ARROW)
.set(DataComponents.CUSTOM_NAME, Component.text("Previous Page"))
.build());
}
if (end < items.size()) {
inventory.setItemStack(53, ItemStack.builder(Material.ARROW)
.set(DataComponents.CUSTOM_NAME, Component.text("Next Page"))
.build());
}
// Update title
inventory.setTitle(Component.text("Items - Page " + (page + 1)));
}
public void nextPage() {
if ((page + 1) * 45 < items.size()) {
page++;
updatePage();
}
}
public void previousPage() {
if (page > 0) {
page--;
updatePage();
}
}
public Inventory getInventory() {
return inventory;
}
}
Inventory Properties
Some inventory types have special properties:// Window properties (for furnaces, brewing stands, etc.)
inventory.sendProperty(InventoryProperty.FURNACE_FIRE_ICON, (short) 200);
inventory.sendProperty(InventoryProperty.FURNACE_MAXIMUM_FUEL_BURN_TIME, (short) 200);
Complete Example: Block Interaction
Open inventory when player clicks a crafting table:import net.minestom.server.event.player.PlayerBlockInteractEvent;
eventNode.addListener(PlayerBlockInteractEvent.class, event -> {
Block block = event.getBlock();
if (block.id() == Block.CRAFTING_TABLE.id()) {
Player player = event.getPlayer();
Inventory crafting = new Inventory(
InventoryType.CRAFTING,
Component.text("Crafting")
);
player.openInventory(crafting);
}
});
Item Drop and Pickup
Handle item drops and pickups:import net.minestom.server.event.item.ItemDropEvent;
import net.minestom.server.event.item.PickupItemEvent;
import net.minestom.server.entity.ItemEntity;
// Item drop
eventNode.addListener(ItemDropEvent.class, event -> {
Player player = event.getPlayer();
ItemStack droppedItem = event.getItemStack();
Pos playerPos = player.getPosition();
ItemEntity itemEntity = new ItemEntity(droppedItem);
itemEntity.setPickupDelay(Duration.of(500, TimeUnit.MILLISECOND));
itemEntity.setInstance(player.getInstance(), playerPos.withY(y -> y + 1.5));
Vec velocity = playerPos.direction().mul(6);
itemEntity.setVelocity(velocity);
});
// Item pickup
eventNode.addListener(PickupItemEvent.class, event -> {
Entity entity = event.getLivingEntity();
if (entity instanceof Player player) {
ItemStack itemStack = event.getItemEntity().getItemStack();
// Cancel if inventory is full
event.setCancelled(!player.getInventory().addItemStack(itemStack));
}
});
Next Steps
Commands
Create commands to give items and manage inventories
Entities
Learn about entity equipment and items
