Skip to content

Item For Developers

Fulminazzo edited this page Dec 8, 2024 · 25 revisions

This section is dedicated to developers. If you are looking for the server admins' page, click here

Many of the fields referenced on this page might be or require platform-specific values. Check the glossary


The item module aims to ease and improve the QoL of both server admins and developers by adding common, intuitive methods for creating and customizing objects.

It does so by providing a comprehensive API with method chaining and basic constructors that reduces the overhead introduced by ItemMeta.

NOTE: the item module automatically imports the corresponding wrappers module (when working with the item-base module, the wrappers-base will be imported, with the item-serializer, the wrappers-serializer is and so on). This is required for features like enchantments to work properly and across different versions.

All the objects described on this page are part of the base module, which is totally independent of any platform. If you want to store or load data on files, you will need to import the serializer module and use ItemYAGLParser#addAllParsers() JUST ONCE before starting any IO operation (it also includes calls to WrappersYAGLParser#addAllParsers() so you are not required to specify that). Any reference to bukkit requires the bukkit module imported.

Table of contents
Items
Recipes

Items

The core class of this module is Item. This interface introduces various methods to add, edit or remove attributes in the current item.

In this section, we will go over every implementation of Item, how they can be used and what are their capabilities. Before proceeding, the reader must know the two most important functions:

  • Item#newItem(): allows creating a new empty implementation of Item. This will create an empty item ready to be used;

  • Item#copy(Class): allows copying the current Item to another implementation of it. This is extremely useful for converting items, but be aware that in some cases it may cause information loss. For example, converting a RecipeItem to an Item will discard every previous configured recipe.

    Every time in this Wiki the copy keyword is present, it means that the item in question should invoke the copy() function.

Item implementations
Item
RecipeItem
PersistentItem

Item

Item is the parent of all other items. As previously anticipated, it provides a huge number of utilities to facilitate the developer in the creation and declaration of items. It does so by allowing method chaining for every setter, adder or remover method, thus keeping alive the coding flow.

The following is a list of the remarkable ones with their usages:

  • setDurability(int): allows setting the durability of the item. In Minecraft older versions, the durability changed the color of the object. For example, dyes were identified by the dye material and the durability set to a certain value:
    Item.newItem().setMaterial("dye").setDurability(4).setDisplayName("&9Custom Lapis Lazuli");
  • addEnchantments(Enchantment[]): adds all the given enchantments;
  • removeEnchantments(String[]): removes the enchantments based on their name;
  • setCustomModelData(int): for Minecraft 1.14+, this value allows setting custom texture packs for the item in question;
  • isSimilar(Item, ItemField[]): compares the current item with the given one. They match only if all the ItemFields not specified in the second parameter are equal.
    Item i1 = Item.newItem().setMaterial("stone_sword").addEnchantments("sharpness", "unbreaking");
    Item i2 = Item.newItem().setMaterial("stone_sword").addEnchantments("sharpness", "mending");
    i1.isSimilar(i2); // false, different enchantments
    i1.isSimilar(i2, ItemField.ENCHANTMENTS); // true, enchantments are ignored

BukkitItem

When using the item-bukkit module, the developer will be able to convert the item in ItemStacks. To do so, it is required to copy the current item to a BukkitItem and then invoke the BukkitItem#create method:

ItemStack stack = Item.newItem("diamond_sword").setAmount(1).copy(BukkitItem.class).create();

NOTE: you can also use BukkitItem#newItem to immediately have access to the create method, without calling copy.

In case the developer wants more control, or requires a feature in the moment of the creation that YAGL does not introduce, a BukkitItem#create(Class, Consumer) is provided: this allows changing the final item stack meta before returning it. As an example, let's go over the creation of a skull with the skin of a player:

// The Material enum can be used as well!
ItemStack skull = BukkitItem.newItem(Material.PLAYER_HEAD).create(SkullMeta.class, skullMeta -> {
    OfflinePlayer player = Bukkit.getOfflinePlayer(uuid);
    if (player != null) skullMeta.setOwningPlayer(player);
});

RecipeItem

RecipeItem, which directly inherits from Item, introduces only one feature: custom crafting recipes. While we will look later at how to create different recipes, it is worth nothing that this special implementation allows specifying as many recipes as the user desires, thanks to the setRecipes(Recipe[]) and addRecipes(Recipe[]) methods. There is also the possibility to use it in an enhanced for-loop to go over every current recipe:

RecipeItem item;
/* ... */
for (Recipe recipe : item)
    /* ... */

A RecipeItem can be created by copying the current item or by using Item#newRecipeItem.

WARNING: by default, the added recipes will not be registered. To actually add them in the server, an instance of BukkitRecipeItem is required.

BukkitRecipeItem

BukkitRecipeItem is an implementation fusion of RecipeItem and BukkitItem; it supplies real functionality for the methods registerRecipes and unregisterRecipes.

NOTE: a clearRecipes method is also present, which will delete all the previously set recipes. Doing so will NOT unregister them, so it is advised to manually unsubscribe all of them before proceeding.

RecipeItem recipeItem = BukkitItem.newRecipeItem("diamond_block").setRecipes(/* ... */);
recipeItem.registerRecipes();
/* ... */
recipeItem.unregisterRecipes();
recipeItem.clearRecipes();

PersistentItem

WARNING: this section requires the bukkit module to be imported.

The PersistentItem is a special type of item that, once in the player inventory, it cannot be moved, dropped or given. Instead, the developer can choose actions for click or interact events, as well as behaviours in the player's inventory and upon death.

A PersistentItem can be directly created using its constructor, or by copying it from an Item (useful when loading from configuration files). Once created, it can always be retrieved by its corresponding ItemStack using PersistentItem#getPersistentItem(ItemStack).

Here is a list of important methods provided by this implementation:

NOTE: in order for the PersistentItem to work properly, it is mandatory to register PersistentListener in the onEnable plugin method.

class MockPlugin extends JavaPlugin {
    
    @Override
    public void onEnable() {
        /* ... */
        Bukkit.getPluginManager().registerEvents(new PersistentListener(), this);
        /* ... */
    }
    
}

Recipes

When using RecipeItem and derivatives, you will have access to the item crafting recipe. You are enabled to add different recipes that will be later loaded in the server and used by players to create your custom items.

Recipe is the core interface for each one of the implementations that provides the most important methods:

  • setOutput(Item): sets the result in the crafting table (not necessary when using RecipeItem);
  • size(): shows the number of ingredients currently added;
  • iterator() (and more generally, it extends Iterable): allows using the recipe in an enhanced for-loop where the elements are the ingredients:
    for (Item ingredient : recipe)
        /* ... */
  • getIngredients(): gets a copy of the current ingredients list.

Every recipe can be automatically loaded and saved using the serializer module.

As per Minecraft specification, there are three types of recipes:

ShapedRecipe

A ShapedRecipe requires a certain order for which the ingredients are inserted in the crafting table. This is the typical case for swords, tools, armors and similar items.

You can create one by stating its id (used only in Minecraft 1.13+) and shape (has to be between 1 and 3):

ShapedRecipe recipe = new ShapedRecipe("gem-shaped-recipe").setShape(3, 2);

After setting the shape, every ingredient can be added using setIngredient(int, Item), where the index is limited by the chosen shape.

Here are some examples:

  • 1x1 shape:
    | 0 | x | x |
    | x | x | x |
    | x | x | x |
    
  • 1x3 shape:
    | 0 | 1 | 2 |
    | x | x | x |
    | x | x | x |
    
  • 2x2 shape:
    | 0 | 1 | x |
    | 2 | 3 | x |
    | x | x | x |
    
  • 3x1 shape:
    | 0 | x | x |
    | 1 | x | x |
    | 2 | x | x |
    
  • 3x3 shape:
    | 0 | 1 | 2 |
    | 3 | 4 | 5 |
    | 6 | 7 | 8 |
    

ShapelessRecipe

Contrary to ShapedRecipe, ShapelessRecipe allows to define a recipe where the order of the ingredients does not matter. An example is every Minecraft dye or every mineral block converted to its corresponding mineral.

You can create one by stating its id (used only in Minecraft 1.13+):

ShapelessRecipe recipe = new ShapelessRecipe("gem-shapeless-recipe");

Then, every ingredient can be added using addIngredient(Item) up to 9 ingredients.

FurnaceRecipe

A FurnaceRecipe is a particular type of recipe, as it does not work in the crafting table, but rather in the furnace.

It allows three fields to be specified:

  • ingredient: the ingredient (only one) that should be smelted;

  • experience: the resulting experience of the smelting;

  • cookingTime: the time (in seconds) for completing the smelting.

    You can create one by stating its id (used only in Minecraft 1.13+):

FurnaceRecipe recipe = new FurnaceRecipe("gem-furnace-recipe");
recipe.setIngredient(Item.newItem("redstone_ore")).setExperience(10.0f).setCookingTime(0.5);