-
Notifications
You must be signed in to change notification settings - Fork 0
v5 ItemBuilder
Available in spigot-utils and its inheritors (spigot-jar).
ItemBuilder wraps a Bukkit ItemStack and lets you describe changes to it. Most of KamiCommon takes
one: menus, icons, and the config loaders all speak ItemBuilder.
ItemStack stack = new ItemBuilder(XMaterial.DIAMOND_SWORD)
.setAmount(1)
.displayName(serializer.fromMiniMessage("<gold>Excalibur"))
.lore(serializer.fromMiniMessage("<gray>Sharper than most"))
.setEnchantment(XEnchantment.SHARPNESS, 5)
.setUnbreakable(true)
.build();v5 splits an ItemBuilder into a fixed prototype ItemStack and the changes you layer on top,
a design borrowed from Paper's Data Component API. You always supply the prototype up front:
new ItemBuilder(itemStack) // from an existing stack
new ItemBuilder(xMaterial)
new ItemBuilder(material) // new in v5Those are the only three constructors. build() clones the prototype, applies your changes, and returns
a fresh stack. It never mutates what you passed in.
⚠️ The prototype reference is final, theItemStackbehind it is not. The constructor stores the stack you pass without copying it, andgetPrototype()hands back that same instance rather than a copy. Anything done to it changes every item the builder produces from that point on. Treat it as read-only, and callgetPrototype().clone()when you need something you can modify.
The material cannot change after construction. To switch it, copy your changes onto a new prototype:
ItemBuilder gold = iron.cloneWithNewPrototype(XMaterial.GOLDEN_SWORD);Overloads exist for Material, XMaterial and ItemStack. clone() copies without changing the
prototype.
You do not construct or inspect the change objects themselves. The vocabulary is the setters:
| you want to | call |
|---|---|
| set a value |
setEnchantment(...), addItemFlag(...), setAmount(...)
|
| clear your change and let the prototype show through |
resetEnchantment(...), resetItemFlag(...), resetDamage()
|
| actively suppress a value the prototype has |
removeEnchantment(...), removeItemFlag(...)
|
reset and remove are different. reset forgets that you said anything; remove says "not this one",
even if the prototype had it.
addGlow() sets the glow patch, removeGlow() clears it, and setGlow(boolean) is the two as one
call. disableGlow() is an alias of removeGlow().
⚠️ setGlow(false)clears the patch, it does not force "no glow". There is no patch value meaning "suppress the prototype's glint", so an item whose prototype already carries enchantments still glints afterwards.
hasGlow() reports the effective value. With a patch set it returns the patch; with no patch it falls
through to the prototype, which glints exactly when it carries at least one enchantment. isAddGlow()
is an alias of it.
ItemBuilder icon = ItemBuilder.load(section);
ItemBuilder icon = ItemBuilder.load(xMaterial, section); // material fixed in code
ItemBuilder icon = ItemBuilderLoader.loadPatches(prototype, section); // ignore material keysor straight off a config section:
ItemBuilder icon = config.parseItemBuilder("myItem");| key | type | default | notes |
|---|---|---|---|
material / type
|
String | none | single-item form. material wins if both are present |
materials / types
|
list of String | none | menu icons only, see below |
data |
int | 0 |
legacy pre-1.13 variant, e.g. wool colour |
amount |
int | item default | |
damage |
int | none | durability damage; not the same as data
|
name |
String | none | format auto-detected |
lore |
list of String | none | format auto-detected per line |
unbreakable |
boolean | none | |
item-flags |
list of String | none |
XItemFlag names, case and space tolerant |
enchantments |
section | none | key is the enchantment name, value the level |
glow |
boolean | false |
addGlow is an accepted alias |
skull-owner |
String | none | |
hide-attributes |
boolean | nothing hidden | a global default applies on the menu path, see below |
excalibur:
material: DIAMOND_SWORD
name: "&6Excalibur"
lore:
- "&7Sharper than most"
amount: 1
damage: 50
enchantments:
SHARPNESS: 5
UNBREAKING: 3
item-flags:
- HIDE_ENCHANTSNames and lore go through format auto-detection. See Text and Components.
hide-attributes behaves differently depending on how the section is loaded. Through
ItemBuilder.load(...) or parseItemBuilder(...), an absent key means nothing is hidden. Through
MenuIconLoader, that is, when the section is a menu icon, an absent key falls back to
MenuIconLoader.Config.isHideIconAttributes(), which defaults to true.
The v4 spelling hideAttributes is no longer read on either path.
The list forms are read by MenuIconLoader only, so they work on a menu icon and not through
ItemBuilder.load(...) or parseItemBuilder(...). A section defining only materials: throws
IllegalArgumentException when loaded as a plain item.
Giving a list makes the icon rotate between materials. Accepted keys, in precedence order:
materials, material as a list, types, type as a list.
An invalid material name in a list is dropped with a warning naming the config path, where the
single form throws IllegalArgumentException.
| v4 | v5 |
|---|---|
new ItemBuilder(section) |
ItemBuilder.load(section) |
new ItemBuilder(section, offlinePlayer) |
ItemBuilder.load(section).setSkullOwner(player.getName()) |
new ItemBuilder(xMat, section) |
ItemBuilder.load(xMat, section) |
new ItemBuilder(xMat, section, offlinePlayer) |
ItemBuilder.load(xMat, section).setSkullOwner(...) |
new ItemBuilder(base, section) |
ItemBuilder.load(base, section) or ItemBuilderLoader.loadPatches(base, section)
|
new ItemBuilder(xMat, (short) dmg) |
new ItemBuilder(xMat).setDamage(dmg) |
new ItemBuilder(xMat, amount) |
new ItemBuilder(xMat).setAmount(amount) |
new ItemBuilder(xMat, amount, (short) dmg) |
new ItemBuilder(xMat).setAmount(amount).setDamage(dmg) |
new ItemBuilder(stack, false) |
new ItemBuilder(stack) |
new ItemBuilder(stack, true) |
new ItemBuilder(stack.clone()) |
new ItemBuilder(stack) |
new ItemBuilder(stack.clone()) to keep v4's cloning behaviour |
new IAItemBuilder("ns:id") |
new ItemBuilder(CustomStack.getInstance("ns:id").getItemStack()) |
any new IBuilder(...)
|
none. IBuilder is now an interface, not an abstract class |
| v4 | v5 |
|---|---|
getBase() |
getPrototype() |
setBase(ItemStack) |
cloneWithNewPrototype(ItemStack) |
setType / setMaterial(XMaterial) / setMaterial(Material)
|
cloneWithNewPrototype(...) |
addEnchant(XEnchantment, int) |
setEnchantment(XEnchantment, int) |
addEnchantments(Map) |
setEnchantments(Map) |
addFlag(ItemFlag) |
addItemFlag(XItemFlag) |
addGlow(boolean) |
setGlow(boolean) |
getUnbreakable() → TriState
|
isUnbreakable() → boolean
|
loadTypes(ConfigurationSection) |
ItemTypeLoader.loadType(section) |
parseMaterial / parseXMaterial
|
ItemTypeLoader.loadTypeByString(String, Integer) |
loadClone(IBuilder) |
clone() or cloneWithNewPrototype(...)
|
build(Player, int) |
none. Material cycling moved to MenuIcon
|
getNbtData() |
none |
ConfigurationSection#setItemBuilder(key, b) |
setItemStack(key, b.build()), or put(key, b)
|
ConfigurationSection#getItemBuilder(key) |
parseItemBuilder(key), which is not a drop-in. See below |
StringUtilP.p(player, s) |
SoftPlaceholderAPI.setPlaceholders(player, s) |
⚠️ Two methods kept their name and changed their type, so they break on recompile without an obvious error message:getDamage()wentshort→int, andgetItemFlags()wentList<ItemFlag>→Set<XItemFlag>.
⚠️ getItemBuilderandparseItemBuilderare different operations. The old one read a serializedItemStackat that key and returnednullif absent. The new one reads a YAML subsection and throwsIllegalArgumentExceptionif no valid material is defined.
-
setUnbreakable(true)no longer addsHIDE_UNBREAKABLEfor you. Add it yourself if you want it. -
hideAttributes()now namesHIDE_ADDITIONAL_TOOLTIPinstead ofHIDE_POTION_EFFECTS. XSeries maps these to the same flag, so behaviour is unchanged. -
NBT support was removed.
getNbtData()and thenbt:config section are gone. Annbt:block in an existing config is ignored, with a warning naming the config path. Apply NBT afterbuild()using the bundled NBT-API. -
Material-load failure throws
IllegalArgumentException, where v4 threwIllegalStateException. Update anycatchblock that named the old type.
Setup
Spigot
Text
Data
Migration
Other versions