Paper Plugin Guide
File mode0

Paper essentials

Items and ItemStacks

Create items with names, lore, enchantments and custom looks, the 26.3 way.

Beginner51 min read

Every sword, apple and diamond in Minecraft is an item, and nearly every plugin hands one out, checks one or changes one. On this page you will create items, give them names, lore and enchantments, compare them safely, and build a /kit command that gives new players a starter kit.

What is an item?

When you hold a diamond sword, that is one slot of your inventory with something in it. In Java, "something in a slot" is an object of the class ItemStack. An ItemStack bundles three things together:

  • A Material: which kind of item it is, such as Material.DIAMOND_SWORD. Material is a long list of every block and item type in the game.
  • An amount: how many items are in the stack. A stack of 32 arrows is one ItemStack with an amount of 32.
  • Data components: everything else about the item, such as its custom name, its description lines, its enchantments and how much damage it has taken.
One ItemStack = one slot's worth of stuff ItemStack sword = ItemStack.of(Material.DIAMOND_SWORD); Material which kind of item DIAMOND_SWORD Amount how many in the stack 1 Data components everything else about it name, lore, enchantments... CUSTOM_NAME the title LORE story lines ENCHANTMENTS Sharpness V MAX_STACK_SIZE and many more
An ItemStack is a material, an amount and a set of data components.

Making your first ItemStack

You create an item with ItemStack.of. Give it a material, and optionally an amount. Here are three ways to make items:

ItemBasics.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemBasics.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javayou are hereHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

8ItemStack singleDiamond() {9    return ItemStack.of(Material.DIAMOND);10}
  1. This method makes one diamond. Its return type, ItemStack, says "calling me gives you an item".
  2. The modern way to create an item. With no amount, you get exactly one.
ItemBasics.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemBasics.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javayou are hereHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

12ItemStack stackOfArrows() {13    return ItemStack.of(Material.ARROW, 32);14}
  1. The second argument is the amount. A stack of 32 arrows is one ItemStack.
ItemBasics.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemBasics.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javayou are hereHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

16ItemStack oldWayToMakeBread() {17    return new ItemStack(Material.BREAD, 5);18}
  1. The older way. You will see it in most tutorials, and it still works. ItemStack.of(...) does the same job and reads a little better.

When you type Material. in IntelliJ, autocomplete lists every material. Names are always written in capital letters with underscores: DIAMOND_SWORD, GOLDEN_APPLE, OAK_PLANKS. The Names Lookup tool helps you find the exact name for something you can see in the game.

Reading an item

An item answers questions about itself. This method builds a short description of any item it is given:

ItemBasics.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemBasics.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javayou are hereHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

20String describe(ItemStack item) {21    if (item.isEmpty()) {22        return "nothing";23    }24    return item.getAmount() + " x " + item.getType() + " (a stack holds up to " + item.getMaxStackSize() + ")";25}
  1. The method receives an item as a parameter, so it works for any item you hand it.
  2. True for air (an empty slot) or a stack with amount 0. Check it first so you never treat "nothing" as a real item.
  3. How many items are in the stack.
  4. The Material. Joining it to text with + prints its name, like ARROW.
  5. The most this kind of item can stack to: 64 for most things, 16 for ender pearls, 1 for swords.

Called with the arrows from above, it returns 32 x ARROW (a stack holds up to 64).

Items are objects you can change

An ItemStack is not a frozen snapshot: calling setAmount on it changes that very object. If two variables point at the same item, a change through one shows up in the other. When you want a separate copy to change, call clone() first:

ItemBasics.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemBasics.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javayou are hereHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

27ItemStack doubled(ItemStack item) {28    ItemStack copy = item.clone();29    copy.setAmount(Math.min(item.getAmount() * 2, item.getMaxStackSize()));30    return copy;31}
  1. Makes a separate, identical item. Changing copy leaves the original alone.
  2. Takes the smaller of two numbers. It stops the amount from going over the stack limit, because 128 arrows in one stack is not allowed.

Names, lore and enchantments: data components

A plain ItemStack.of(Material.DIAMOND_SWORD) is just a diamond sword. To make it special, you give it data components. A data component is one named piece of information stored on the item: CUSTOM_NAME holds its name, LORE holds its description lines, ENCHANTMENTS holds its enchantments, and so on. The list of all of them is in the class DataComponentTypes.

The pattern is always the same: item.setData(WHICH_COMPONENT, the value). This is the modern way to change items in Paper 26.3.

A custom name

ItemComponents.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComponents.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javayou are hereHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

19ItemStack namedSword() {20    ItemStack sword = ItemStack.of(Material.DIAMOND_SWORD);21    sword.setData(DataComponentTypes.CUSTOM_NAME, MINI.deserialize("<gold>Dragon Slayer"));22    return sword;23}
  1. First make the plain item you want to decorate.
  2. Stores a name on the sword. The value must be a Component (Paper's formatted text), not a plain String.
  3. Turns MiniMessage text such as <gold>Dragon Slayer into a component. MiniMessage is the easy way to write colors.
  4. Hands the finished item back to whoever called the method.

In the game, the name looks like this:

Dragon Slayer

The name is slanted. Minecraft draws anything in CUSTOM_NAME in italics, exactly like a name you typed into an anvil. Most plugins do not want that, and you turn it off by setting the italic decoration to false:

ItemComponents.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComponents.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javayou are hereHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

25ItemStack namedSwordWithoutItalics() {26    ItemStack sword = ItemStack.of(Material.DIAMOND_SWORD);27    Component name = MINI.deserialize("<gold>Dragon Slayer").decoration(TextDecoration.ITALIC, false);28    sword.setData(DataComponentTypes.CUSTOM_NAME, name);29    return sword;30}
  1. Says "this text is explicitly not italic". Without this call, the game adds its own italics.
  2. Saving the finished component in a variable keeps the setData line short and readable.
Dragon Slayer

You can also write <!italic> at the start of the MiniMessage text instead of calling .decoration(...). Both do the same thing.

CUSTOM_NAME or ITEM_NAME?

There are two components for names, and the difference matters:

Which name component should you use? CUSTOM_NAME Same slot an anvil rename uses Shown in italics unless you turn italics off Players can change it in an anvil Best for: items players may rename ITEM_NAME The item's base name Never italic An anvil cannot change or remove it Best for: fixed custom item names
CUSTOM_NAME behaves like an anvil rename. ITEM_NAME is the item's own name.

Use CUSTOM_NAME for items players are allowed to rename. Use ITEM_NAME for items with a fixed name, such as quest items, because players cannot remove or change it in an anvil, and it is never italic. The starter kit later on this page uses both.

Lore: description lines

Lore is the gray text under an item's name that describes it. It is a list of lines, wrapped in an ItemLore object:

ItemComponents.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComponents.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javayou are hereHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

32ItemStack swordWithLore() {33    ItemStack sword = ItemStack.of(Material.DIAMOND_SWORD);34    List<Component> lines = List.of(35        plain("<gray>Forged in the End."),36        plain("<dark_purple>Deals extra damage to dragons."));37    sword.setData(DataComponentTypes.LORE, ItemLore.lore(lines));38    return sword;39}
  1. A list of components, one per line of lore. List.of(...) builds a list from the values you give it.
  2. The plain helper at the bottom of the file turns MiniMessage text into a component with italics off.
  3. Wraps the list in the type the LORE component expects.
ItemComponents.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComponents.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javayou are hereHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

76private static Component plain(String miniMessage) {77    return MINI.deserialize(miniMessage).decoration(TextDecoration.ITALIC, false);78}
  1. A tiny helper used by the other methods. static means you can call it without an object, and private keeps it inside this class.
Diamond Sword

Lore text is also purple and italic by default, which is why the helper switches italics off. If you do not want a certain line to be gray, just give it another color tag.

Enchantments

An enchantment is a magical bonus such as Sharpness or Efficiency. Every enchantment is a constant on the Enchantment class: Enchantment.SHARPNESS, Enchantment.UNBREAKING, Enchantment.MENDING. Autocomplete lists them all. Add them with an ItemEnchantments builder, passing each enchantment with its level:

ItemComponents.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComponents.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javayou are hereHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

41ItemStack enchantedSword() {42    ItemStack sword = ItemStack.of(Material.DIAMOND_SWORD);43    sword.setData(DataComponentTypes.ENCHANTMENTS, ItemEnchantments.itemEnchantments()44        .add(Enchantment.SHARPNESS, 5)45        .add(Enchantment.LOOTING, 3)46        .build());47    return sword;48}
  1. Starts a builder, a helper object that collects settings one by one.
  2. Adds Sharpness at level 5. Each add returns the builder, so calls chain together.
  3. Finishes the builder and gives you the finished ItemEnchantments value.

The builder does not check levels or items. You could add Sharpness 100 to a stick. That is sometimes what you want (plugins often create "over-enchanted" items), but when you want Minecraft's normal rules, the older helper methods on ItemStack do check them:

ItemEnchanting.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemEnchanting.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javayou are hereHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

9ItemStack safeEnchant() {10    ItemStack sword = ItemStack.of(Material.DIAMOND_SWORD);11    sword.addEnchantment(Enchantment.SHARPNESS, 5);12    return sword;13}
  1. The safe version. It throws an IllegalArgumentException if the level is above the maximum or the enchantment does not fit this item.
ItemEnchanting.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemEnchanting.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javayou are hereHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

15ItemStack unsafeEnchant() {16    ItemStack sword = ItemStack.of(Material.DIAMOND_SWORD);17    sword.addUnsafeEnchantment(Enchantment.SHARPNESS, 10);18    return sword;19}
  1. The "I know what I am doing" version. It ignores level limits and item types, so Sharpness 10 works.

You can ask an item about its enchantments too:

ItemEnchanting.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemEnchanting.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javayou are hereHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

21boolean hasSharpness(ItemStack item) {22    return item.containsEnchantment(Enchantment.SHARPNESS);23}
  1. True if the item has that enchantment at any level.
ItemEnchanting.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemEnchanting.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javayou are hereHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

25int sharpnessLevel(ItemStack item) {26    return item.getEnchantmentLevel(Enchantment.SHARPNESS);27}
  1. The level of that enchantment, or 0 when the item does not have it.

Glint, stack size, rarity and more

Many small settings are data components too, and they all follow the same setData pattern:

ItemComponents.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComponents.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javayou are hereHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

50ItemStack shinyStick() {51    ItemStack stick = ItemStack.of(Material.STICK);52    stick.setData(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true);53    return stick;54}
  1. True makes the item shimmer like an enchanted item, even with no enchantments. False hides the shimmer on an item that has enchantments.
ItemComponents.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComponents.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javayou are hereHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

56ItemStack tinyStackOfApples() {57    ItemStack apples = ItemStack.of(Material.APPLE, 3);58    apples.setData(DataComponentTypes.MAX_STACK_SIZE, 4);59    apples.setData(DataComponentTypes.RARITY, ItemRarity.EPIC);60    return apples;61}
  1. The most this item can stack to. Here apples stop at 4 instead of 64.
  2. The rarity changes the color of the item's name: common is white, uncommon yellow, rare aqua and epic light purple.
ItemComponents.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComponents.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javayou are hereHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

63ItemStack unbreakablePickaxe() {64    ItemStack pickaxe = ItemStack.of(Material.IRON_PICKAXE);65    pickaxe.setData(DataComponentTypes.UNBREAKABLE);66    return pickaxe;67}
  1. Some components have no value, they are either on or off. For those you call setData with just the component, and it means "turn this on".

Two more components are worth knowing about now, even though you will use them later. ITEM_MODEL and CUSTOM_MODEL_DATA change how an item looks, by pointing at models in a resource pack. You can read about the data component system in more depth on Registries, keys and data components.

Reading and removing components

ItemComponents.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComponents.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javayou are hereHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

69void readAndReset(ItemStack item) {70    Component customName = item.getData(DataComponentTypes.CUSTOM_NAME);71    boolean hasName = item.hasData(DataComponentTypes.CUSTOM_NAME);72    item.resetData(DataComponentTypes.CUSTOM_NAME);73    item.unsetData(DataComponentTypes.LORE);74}
  1. Reads a component. The result can be null when the item does not have that component, so check before you use it.
  2. Asks "does this item have this component?" without reading it.
  3. Puts the component back to the default for that kind of item, as if you never changed it.
  4. Marks the component as removed. Use it when you want the item to have none at all, even if its default would have one.

The ItemMeta way

Before data components existed, every item change went through a helper object called ItemMeta. You will see it in nearly every older tutorial, and it still works. Paper gives you a safe way to use it, editMeta:

ItemMetaWay.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemMetaWay.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javayou are hereHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

15ItemStack miningPick() {16    ItemStack pickaxe = ItemStack.of(Material.DIAMOND_PICKAXE);17    pickaxe.editMeta(meta -> {18        meta.displayName(MINI.deserialize("<aqua>Miner's Friend").decoration(TextDecoration.ITALIC, false));19        meta.lore(List.of(Component.text("Digs faster than you do.")));20        meta.addEnchant(Enchantment.EFFICIENCY, 5, true);21        meta.setUnbreakable(true);22    });23    return pickaxe;24}
  1. You pass a block of code that receives the item's ItemMeta. This arrow syntax is a lambda: a small piece of code handed to a method. Lambdas are explained in the Java chapters.
  2. Sets the item's name, like CUSTOM_NAME does. It takes a component, not a plain string.
  3. Sets the lore lines. It takes a list of components.
  4. Adds the enchantment. The last argument true means "ignore the normal level limit".
  5. The item never loses durability.

Both styles change the same underlying item. Components read more consistently, and they can do things the meta cannot, so this guide uses them for new code. editMeta is still handy, because plenty of older code and tutorials hand you an ItemMeta, and you now know how to read it. Do not call other item methods, such as getItemMeta(), from inside the editMeta block: the block should only touch the meta it was given.

Be careful with tutorials that use strings for names and lore. Those methods are deprecated, so the compiler complains about them, and old-style color codes are on their way out:

Old way you will see onlineOld way
1ItemMeta meta = item.getItemMeta();2meta.setDisplayName(ChatColor.GREEN + "Hello");3item.setItemMeta(meta);
  1. Takes a plain String and is deprecated. Use displayName(Component) or the CUSTOM_NAME component instead.
  2. Old-style color codes. Use MiniMessage tags like <green> instead.

Comparing items

You will often need to ask "is this the item I am looking for?". Java gives you several ways to ask, and they answer different questions:

CheckWhat it comparesUse it when
item.getType() == Material.XOnly the materialYou do not care about names or enchantments: "is this any diamond sword?"
a.isSimilar(b)Material and data, but not the amountYou want to know if two stacks are the same kind of item, for example to merge them
a.equals(b)Material, data and the amountYou need two stacks to be identical in every way
ItemComparing.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemComparing.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javayou are hereHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javaHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

1package com.example.itemssnippets;2 3import org.bukkit.Material;4import org.bukkit.NamespacedKey;5import org.bukkit.inventory.ItemStack;6 7final class ItemComparing {8 9    boolean sameKindOfItem(ItemStack first, ItemStack second) {10        return first.isSimilar(second);11    }12 13    boolean exactlyTheSame(ItemStack first, ItemStack second) {14        return first.equals(second);15    }16 17    boolean isDiamondSword(ItemStack item) {18        return item.getType() == Material.DIAMOND_SWORD;19    }20 21    boolean isKitItem(ItemStack item, NamespacedKey kitKey) {22        return item.getPersistentDataContainer().has(kitKey);23    }24}
  1. Ignores how many are in each stack. Three apples and thirty apples named the same way are similar.
  2. Amount counts here: three apples and thirty apples are not equal.
  3. Compare materials with ==, because Material is an enum: every constant exists exactly once.
  4. The safe way to recognize your own custom items. Stamp a secret key on the item when you create it, and look for that key later.

Giving items to players

The obvious way to give a player an item is player.getInventory().addItem(item). It puts the item in the first spot that has room and tops up partial stacks. But the inventory may be full, so addItem does not just return nothing: it returns a map of the items that did not fit. When everything fit, the map is empty.

ItemGiving.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemGiving.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javayou are hereHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

9void giveOrDrop(Player player, ItemStack item) {10    Map<Integer, ItemStack> leftovers = player.getInventory().addItem(item);11    for (ItemStack leftover : leftovers.values()) {12        player.getWorld().dropItemNaturally(player.getLocation(), leftover);13    }14}
  1. The leftovers. The number is the position of the item you passed in, and the value is the part that did not fit.
  2. Tries to put the item in the player's inventory. Whatever does not fit comes back in the map.
  3. Goes through every leftover stack, one at a time. If the map is empty, the loop body never runs.
  4. Drops the leftover at the player's feet with a little random toss, like an item dropped from a broken block, so nothing is lost.

If you would rather refuse than drop items on the floor, check whether the map is empty:

ItemGiving.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-snippetssrcmainjavacomexampleitemssnippetsItemGiving.java

The package com.example.itemssnippets is the folder path com/example/itemssnippets inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-snippets/
    • src/main/java/com/example/itemssnippets/Package com.example.itemssnippets
      • ItemBasics.javaHelper class
      • ItemComparing.javaHelper class
      • ItemComponents.javaHelper class
      • ItemEnchanting.javaHelper class
      • ItemGiving.javayou are hereHelper class
      • ItemMetaWay.javaHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

16boolean giveOnlyIfItFits(Player player, ItemStack item) {17    Map<Integer, ItemStack> leftovers = player.getInventory().addItem(item);18    return leftovers.isEmpty();19}
  1. True when everything fit. Note that part of the item may already be in the inventory when this is false.

Example plugin: a /kit command

Let us build something players can use. The /kit command gives a named, enchanted starter kit: a sword, a pickaxe and some bread. The plugin has three small classes.

  • items-demo/
    • src/
      • main/
        • java/
          • com/example/itemsdemo/
            • ItemsDemoPlugin.javaRegisters the /kit command when the plugin starts
            • KitCommand.javaGives the kit to the player who typed /kit
            • KitItems.javaBuilds each item of the kit
        • resources/
          • plugin.ymlPlugin name, main class and the itemsdemo.kit permission

The KitItems class builds the items. Each item uses a different technique from this page:

KitItems.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-demosrcmainjavacomexampleitemsdemoKitItems.java

The package com.example.itemsdemo is the folder path com/example/itemsdemo inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-demo/
    • src/main/
      • java/com/example/itemsdemo/Package com.example.itemsdemo
        • ItemsDemoPlugin.javaMain class: Paper starts here (named as main in plugin.yml)
        • KitCommand.javaCommand (BasicCommand)
        • KitItems.javayou are hereHelper class
      • resources/Files copied into the jar as they are
        • plugin.ymlTells Paper the plugin's name, version and main class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

26static ItemStack starterSword() {27    ItemStack sword = ItemStack.of(Material.IRON_SWORD);28    sword.setData(DataComponentTypes.CUSTOM_NAME, text("<gold>Rookie's Blade"));29    sword.setData(DataComponentTypes.LORE, ItemLore.lore(List.of(30        text("<gray>Your first real weapon."),31        text("<dark_gray>Handed out by /kit"))));32    sword.setData(DataComponentTypes.ENCHANTMENTS, ItemEnchantments.itemEnchantments()33        .add(Enchantment.SHARPNESS, 2)34        .add(Enchantment.UNBREAKING, 3)35        .build());36    sword.setData(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true);37    sword.setData(DataComponentTypes.RARITY, ItemRarity.UNCOMMON);38    return sword;39}
  1. Start with a plain iron sword.
  2. A custom name. The text helper (bottom of the file) converts MiniMessage into a component with italics off.
  3. Two lines of lore, wrapped in an ItemLore.
  4. Sharpness 2 and Unbreaking 3, added with the builder.
  5. Makes the sword shine. The enchantments already do that, but this guarantees it even if you remove them later.
  6. Rarity colors the name yellow unless the custom name has its own color, and this one does.
KitItems.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-demosrcmainjavacomexampleitemsdemoKitItems.java

The package com.example.itemsdemo is the folder path com/example/itemsdemo inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-demo/
    • src/main/
      • java/com/example/itemsdemo/Package com.example.itemsdemo
        • ItemsDemoPlugin.javaMain class: Paper starts here (named as main in plugin.yml)
        • KitCommand.javaCommand (BasicCommand)
        • KitItems.javayou are hereHelper class
      • resources/Files copied into the jar as they are
        • plugin.ymlTells Paper the plugin's name, version and main class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

41static ItemStack starterPickaxe() {42    ItemStack pickaxe = ItemStack.of(Material.STONE_PICKAXE);43    pickaxe.editMeta(meta -> {44        meta.displayName(text("<aqua>Rookie's Pick"));45        meta.lore(List.of(text("<gray>Never breaks. Digs quickly.")));46        meta.addEnchant(Enchantment.EFFICIENCY, 3, true);47        meta.setUnbreakable(true);48    });49    return pickaxe;50}
  1. This item uses the ItemMeta way, so you can compare both styles side by side.
  2. Efficiency 3. The true allows levels over the normal limit.
KitItems.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-demosrcmainjavacomexampleitemsdemoKitItems.java

The package com.example.itemsdemo is the folder path com/example/itemsdemo inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-demo/
    • src/main/
      • java/com/example/itemsdemo/Package com.example.itemsdemo
        • ItemsDemoPlugin.javaMain class: Paper starts here (named as main in plugin.yml)
        • KitCommand.javaCommand (BasicCommand)
        • KitItems.javayou are hereHelper class
      • resources/Files copied into the jar as they are
        • plugin.ymlTells Paper the plugin's name, version and main class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

52static ItemStack starterSnack() {53    ItemStack bread = ItemStack.of(Material.BREAD, 16);54    bread.setData(DataComponentTypes.ITEM_NAME, text("<yellow>Trail Bread"));55    return bread;56}
  1. Sixteen loaves in one stack.
  2. A fixed, non-italic name that players cannot change in an anvil.
KitItems.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-demosrcmainjavacomexampleitemsdemoKitItems.java

The package com.example.itemsdemo is the folder path com/example/itemsdemo inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-demo/
    • src/main/
      • java/com/example/itemsdemo/Package com.example.itemsdemo
        • ItemsDemoPlugin.javaMain class: Paper starts here (named as main in plugin.yml)
        • KitCommand.javaCommand (BasicCommand)
        • KitItems.javayou are hereHelper class
      • resources/Files copied into the jar as they are
        • plugin.ymlTells Paper the plugin's name, version and main class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

22static List<ItemStack> starterKit() {23    return List.of(starterSword(), starterPickaxe(), starterSnack());24}
  1. Collects all three items in a list, so the command can hand them out in a loop.

Now the command. It gives every item with addItem and drops any leftovers, like the giving example above:

KitCommand.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-demosrcmainjavacomexampleitemsdemoKitCommand.java

The package com.example.itemsdemo is the folder path com/example/itemsdemo inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-demo/
    • src/main/
      • java/com/example/itemsdemo/Package com.example.itemsdemo
        • ItemsDemoPlugin.javaMain class: Paper starts here (named as main in plugin.yml)
        • KitCommand.javayou are hereCommand (BasicCommand)
        • KitItems.javaHelper class
      • resources/Files copied into the jar as they are
        • plugin.ymlTells Paper the plugin's name, version and main class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

1package com.example.itemsdemo;2 3import io.papermc.paper.command.brigadier.BasicCommand;4import io.papermc.paper.command.brigadier.CommandSourceStack;5import java.util.Map;6import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;7import org.bukkit.entity.Player;8import org.bukkit.inventory.ItemStack;9 10final class KitCommand implements BasicCommand {11 12    @Override13    public void execute(CommandSourceStack source, String[] args) {14        if (!(source.getExecutor() instanceof Player player)) {15            source.getSender().sendRichMessage("<red>Only players can use /kit.");16            return;17        }18        int dropped = 0;19        for (ItemStack item : KitItems.starterKit()) {20            Map<Integer, ItemStack> leftovers = player.getInventory().addItem(item);21            for (ItemStack leftover : leftovers.values()) {22                player.getWorld().dropItemNaturally(player.getLocation(), leftover);23                dropped += leftover.getAmount();24            }25        }26        player.sendRichMessage("<green>Starter kit delivered!");27        if (dropped > 0) {28            player.sendRichMessage("<yellow><count> item(s) did not fit and were dropped at your feet.",29                Placeholder.unparsed("count", String.valueOf(dropped)));30        }31    }32 33    @Override34    public String permission() {35        return "itemsdemo.kit";36    }37}
  1. The simplest kind of Paper command. See Commands, part 1 for how it works.
  2. Checks that the one running the command is a Player, and if so names it player so the lines below can use it. Only players have inventories, so if the console runs /kit, the command stops with a message.
  3. Handles the kit's items one by one.
  4. Counts how many individual items did not fit, so the message can say so.
  5. Fills the <count> tag with the number. See MiniMessage.
  6. Who may use the command. Players have itemsdemo.kit by default because plugin.yml says so.
ItemsDemoPlugin.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-demosrcmainjavacomexampleitemsdemoItemsDemoPlugin.java

The package com.example.itemsdemo is the folder path com/example/itemsdemo inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-demo/
    • src/main/
      • java/com/example/itemsdemo/Package com.example.itemsdemo
        • ItemsDemoPlugin.javayou are hereMain class: Paper starts here (named as main in plugin.yml)
        • KitCommand.javaCommand (BasicCommand)
        • KitItems.javaHelper class
      • resources/Files copied into the jar as they are
        • plugin.ymlTells Paper the plugin's name, version and main class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

1package com.example.itemsdemo;2 3import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents;4import org.bukkit.plugin.java.JavaPlugin;5 6public final class ItemsDemoPlugin extends JavaPlugin {7 8    @Override9    public void onEnable() {10        getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, event ->11            event.registrar().register("kit", "Gives you the starter kit", new KitCommand()));12    }13}
  1. Paper asks plugins to register their commands at a special moment during startup. This line says "when that moment comes, run my code".
  2. Creates the /kit command and connects it to KitCommand.
plugin.ymlCompiles on Paper 26.3Compile Lab
Where this file livesitems-demosrcmainresourcesplugin.yml

Files in src/main/resources are copied into the jar exactly as they are. Paper looks for plugin.yml at the top of the jar.

  • items-demo/
    • src/main/
      • java/com/example/itemsdemo/Package com.example.itemsdemo
        • ItemsDemoPlugin.javaMain class: Paper starts here (named as main in plugin.yml)
        • KitCommand.javaCommand (BasicCommand)
        • KitItems.javaHelper class
      • resources/Files copied into the jar as they are
        • plugin.ymlyou are hereTells Paper the plugin's name, version and main class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

1name: ItemsDemo2version: '1.0.0'3main: com.example.itemsdemo.ItemsDemoPlugin4api-version: '26.3'5description: A /kit command that hands out a named, enchanted starter kit.6permissions:7  itemsdemo.kit:8    description: Lets a player use /kit.9    default: true
  1. The permission behind the command. default: true means every player has it.

When a player types /kit, they get this in chat, and the first three hotbar slots fill up:

Starter kit delivered!
0: iron_sword, 1: stone_pickaxe, 2: bread

If the player's inventory was already full, the rest would land on the ground at their feet, and a second message tells them how many items were dropped.

You can download this plugin as a Gradle project, run it, or open it in the Compile Lab.

Mistakes to avoid

  • Passing a String where a Component is needed. setData(DataComponentTypes.CUSTOM_NAME, "Hello") does not compile. Wrap the text with MiniMessage.miniMessage().deserialize(...) or use Component.text(...).
  • Forgetting to turn italics off. Custom names and lore are italic by default. Add <!italic> or .decoration(TextDecoration.ITALIC, false).
  • Changing an item and expecting the player's slot to change. If you get a copy of an item or make a new one, giving it to the player is a separate step (addItem, setItem).
  • Ignoring the leftovers from addItem. When the inventory is full, items silently vanish from your plugin's point of view. Always handle the returned map.
  • Identifying items by name. Use a persistent data marker instead.
  • Using equals when you meant isSimilar. The two stacks have different amounts, so equals says false even though they are the same kind of item.
Try it

Healer's Apple

Write a method that returns three golden apples named "Healer's Apple" in red, with the lore line "Tastes like a second chance.", a maximum stack size of 8, and a shimmer. Neither the name nor the lore should be italic.

Hint 1

Start with ItemStack.of(Material.GOLDEN_APPLE, 3), then call setData once for each of the four settings.

Hint 2

The four components are CUSTOM_NAME, LORE, MAX_STACK_SIZE and ENCHANTMENT_GLINT_OVERRIDE. Build the components with a small helper that turns italics off.

Show the solution

Each setting is one setData call. The helper at the bottom takes MiniMessage text and returns a component with italics off, so the name and the lore line share the same trick.

HealersApple.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-exercisesrcmainjavacomexampleitemsexerciseHealersApple.java

The package com.example.itemsexercise is the folder path com/example/itemsexercise inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-exercise/
    • src/main/java/com/example/itemsexercise/Package com.example.itemsexercise
      • HealersApple.javayou are hereHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

16ItemStack create() {17    ItemStack apple = ItemStack.of(Material.GOLDEN_APPLE, 3);18    apple.setData(DataComponentTypes.CUSTOM_NAME, noItalics("<red>Healer's Apple"));19    apple.setData(DataComponentTypes.LORE, ItemLore.lore(List.of(noItalics("<gray>Tastes like a second chance."))));20    apple.setData(DataComponentTypes.MAX_STACK_SIZE, 8);21    apple.setData(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE, true);22    return apple;23}
  1. Three apples to start with.
  2. Stacks of up to 8 instead of 64.
  3. Adds the shimmer.
HealersApple.javaCompiles on Paper 26.3Compile Lab
Where this file livesitems-exercisesrcmainjavacomexampleitemsexerciseHealersApple.java

The package com.example.itemsexercise is the folder path com/example/itemsexercise inside src/main/java: every dot in the package name is one folder. IntelliJ creates these folders for you when you make a new package.

  • items-exercise/
    • src/main/java/com/example/itemsexercise/Package com.example.itemsexercise
      • HealersApple.javayou are hereHelper class
    • build.gradle.ktsThe build recipe: Paper 26.3 API, Java 25, how the jar is made
    • gradle.propertiesVersion numbers used by the build
    • gradlew.batRuns Gradle on Windows without installing it
    • settings.gradle.ktsThe project's name

Gray files come with the project template; you rarely edit them. Open the whole project in the Compile Lab, or download it from the project page.

25private static Component noItalics(String miniMessage) {26    return MINI.deserialize(miniMessage).decoration(TextDecoration.ITALIC, false);27}
Try it

Count the leftovers

The /kit command tells the player how many items were dropped. Change it so that it also tells the player when nothing was dropped, with a message such as "Everything fit in your inventory."

Hint

The command already has an if (dropped > 0) check. What would you put in an else branch?

Show the solution

Add an else to the existing if, so one of the two messages is always sent:

KitCommand.java (changed lines)
1if (dropped > 0) {2    player.sendRichMessage("<yellow><count> item(s) did not fit and were dropped at your feet.",3        Placeholder.unparsed("count", String.valueOf(dropped)));4} else {5    player.sendRichMessage("<gray>Everything fit in your inventory.");6}

Recap

  • An ItemStack is a material, an amount and data components. Make one with ItemStack.of(Material.X) or ItemStack.of(Material.X, amount).
  • Change an item with item.setData(DataComponentTypes.SOMETHING, value): CUSTOM_NAME, ITEM_NAME, LORE, ENCHANTMENTS, ENCHANTMENT_GLINT_OVERRIDE, MAX_STACK_SIZE, RARITY and UNBREAKABLE.
  • Names and lore take Component values and are italic by default. Turn italics off with <!italic> or .decoration(TextDecoration.ITALIC, false).
  • editMeta is the older, still useful way to change an item through its ItemMeta.
  • Compare with getType(), isSimilar or equals, and never trust an item's name. Mark your own items with persistent data.
  • addItem returns the items that did not fit. Drop them or tell the player.

Quick quiz

  1. Which line gives a sword a custom name?

  2. Your custom item name shows up slanted in the game. Why, and how do you fix it?

  3. What does inventory.addItem(item) return?

  4. You want to know whether two stacks are the same kind of item even though one has 3 apples and the other 30. Which check fits?

  5. Why should a plugin not decide "this is my special sword" by reading the item's name?

Next steps