Items & Inventory
Items are the objects players collect, hold, and use - from swords and tools to food and custom items. Managing inventory is essential for any add-on with gear progression, economies, or loot systems. Understanding how to create, modify, and track items unlocks powerful gameplay mechanics.
Understanding Items & Inventory
An ItemStack is a single stack of items (like 64 diamonds in one slot). Every ItemStack has:
- Type: What kind of item it is (
diamond_sword,golden_apple, etc.) - Amount: How many of this item in the stack (1-64 usually)
- Enchantments: Magic upgrades on the item
- Lore: Custom text that displays when you hover over the item
- NameTag: The custom display name
Why this matters: Items drive progression, rewards, and crafting. A leveling system gives items as rewards, an economy trades items for currency, a PvP arena drops loot when players die.
How It Works
The player's container is their inventory. When you want to give items:
- Create an ItemStack with the item type and amount
- Optionally add enchantments, names, or lore
- Add it to the player's container
The container automatically handles inventory mechanics - stacking items, rejecting items if full, etc.
import { world } from "@minecraft/server";
// Create a simple item
const item = new ItemStack("diamond_sword", 1);
player.container.addItem(item);
// Customize the item
const magicalApple = new ItemStack("golden_apple", 1);
magicalApple.nameTag = "§6Magical Apple"; // Gold-colored name
magicalApple.lore = ["§7Restores 2 hearts", "§7Use wisely"]; // Hover text
// Add enchantment
const enchantedSword = new ItemStack("diamond_sword", 1);
enchantedSword.enchantments.addEnchantment("sharpness", 3); // Sharpness III
enchantedSword.nameTag = "§cLegendary Blade";
// Try to add item - might fail if inventory is full
const success = player.container.addItem(enchantedSword);
if (!success) {
player.sendMessage("§cYour inventory is full!");
}
Inventory Management
// **Count** how many of an item type a player has
function countItem(player, itemType) {
let count = 0;
for (let i = 0; i < player.container.size; i++) {
const item = player.container.getItem(i);
// item is null if slot is empty, use optional chaining (?.)
if (item?.typeId === itemType) {
count += item.amount; // Stack size (1-64)
}
}
return count;
}
// **Remove** items from inventory (e.g., for a shop that charges currency)
function removeItems(player, itemType, amount) {
let remaining = amount;
// Loop through each inventory slot
for (let i = 0; i < player.container.size && remaining > 0; i++) {
const item = player.container.getItem(i);
if (item?.typeId === itemType) {
// Remove up to the stack size (or whatever we need)
const toRemove = Math.min(item.amount, remaining);
item.amount -= toRemove;
remaining -= toRemove;
// If stack is empty, clear the slot
if (item.amount <= 0) {
player.container.setItem(i, null);
}
}
}
return remaining === 0; // true if we removed enough, false if not enough items
}
// **Get all items of a type** (useful for merging stacks)
function getItemStacks(player, itemType) {
const stacks = [];
for (let i = 0; i < player.container.size; i++) {
const item = player.container.getItem(i);
if (item?.typeId === itemType) {
stacks.push({ index: i, item });
}
}
return stacks;
}
Item Events
// When a player uses an item (right-click with it)
world.afterEvents.itemUse.subscribe((event) => {
const player = event.source;
const item = event.itemStack;
// Check if it's a special item
if (item.nameTag?.includes("Magical")) {
player.sendMessage(`§aYou used a magical item!`);
// Could trigger effects, teleport, heal, etc.
}
});
// When a player equips different armor
world.afterEvents.playerSpawn.subscribe((event) => {
const player = event.player;
const equippable = player.getComponent("equippable");
if (equippable) {
const helmet = equippable.getEquipment(EquipmentSlot.Head);
if (helmet?.typeId === "diamond_helmet") {
player.sendMessage("§bYou look fancy!");
}
}
});
Practical Examples
// Custom shop that charges currency (items as payment)
function buyItem(player, cost, itemToGive) {
const diamondsNeeded = cost;
const diamondCount = countItem(player, "diamond");
if (diamondCount < diamondsNeeded) {
player.sendMessage(`§cNeed ${diamondsNeeded} diamonds, you have ${diamondCount}`);
return false;
}
// Remove payment
removeItems(player, "diamond", diamondsNeeded);
// Give item
const item = new ItemStack(itemToGive, 1);
player.container.addItem(item);
player.sendMessage(`§aPurchased ${itemToGive}!`);
return true;
}
// Loot drop when entity dies (like a boss)
world.afterEvents.entityDie.subscribe((event) => {
const entity = event.deadEntity;
if (entity.typeId === "minecraft:zombie") {
const loot = new ItemStack("rotten_flesh", 2);
const rare = Math.random() < 0.1; // 10% chance
if (rare) {
const rareItem = new ItemStack("diamond", 1);
rareItem.nameTag = "§6Rare Drop";
entity.dimension.spawnItem(rareItem, entity.location);
} else {
entity.dimension.spawnItem(loot, entity.location);
}
}
});
// Gift system (send items to other players)
function giftItem(giver, recipient, itemType, amount) {
// Check giver has the item
if (countItem(giver, itemType) < amount) {
giver.sendMessage(`§cYou don't have enough!`);
return false;
}
// Remove from giver
removeItems(giver, itemType, amount);
// Add to recipient
const gift = new ItemStack(itemType, amount);
recipient.container.addItem(gift);
giver.sendMessage(`§aGifted ${amount}x ${itemType}`);
recipient.sendMessage(`§a${giver.nameTag} gifted you ${amount}x ${itemType}!`);
return true;
}
Best Practices
- Check container has space before giving items -
addItem()returns false if full - Use optional chaining (
item?.property) when accessing items - slots can be null/undefined - Stack sizes matter - most items max at 64, but some (like tools) are 1
- Always save to database if items should persist across server restarts
- Validate amounts - check before removing items to prevent negative counts