Build on top of ItemsCore
ItemsCore ships a public Java API and an addon system. Read and give out custom items from your own plugin, or register an addon that extends the in-game editor with your own categories, methods, attributes, listeners and actions.
Introduction
There are two ways to build on ItemsCore, and you can use either or both:
- The API - call into ItemsCore from your plugin to look up a custom item by name, give it to a player, read the custom name off an ItemStack, or ask a player for typed input.
- Addons - register a PluginAddon that adds your own categories, methods, attributes, listeners and actions to the editor, and lets you modify items as they are created.
The video below walks through building a complete addon from scratch. The pages after it document each piece on its own.
Project setup
Drop ItemsCore.jar into a libs/ folder in your project and add it as a system-scoped dependency:
Copy<!-- pom.xml --><dependency><groupId>me.TastyCake</groupId><artifactId>ItemsCore</artifactId><version>1.0</version><systemPath>${project.basedir}/libs/ItemsCore.jar</systemPath><scope>system</scope></dependency>
Depend on ItemsCore in your plugin.yml so it always loads first:
Copy# plugin.ymldepend: [ItemsCore]
If you add custom methods, compile your addon classes with the -parameters flag and a Java 8+ target. That keeps the real argument names so they show up correctly in the editor instead of arg0, arg1:
Copy<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>8</source><target>8</target><compilerArgs><arg>-parameters</arg></compilerArgs></configuration></plugin>
The API
Grab the API instance once ItemsCore is enabled:
CopyItemsCoreAPI api = ItemsCore.getItemsCoreAPI();
| Method | Returns | What it does |
|---|---|---|
| getItemByName(String) | Item | Finds one of your custom items by its name, or null if none matches. |
| giveItem(Entity, Item) | void | Gives a player the custom item (ignored for non-players). |
| getItemName(ItemStack) | String | Reads the internal ItemsCore name stored on an item stack. |
| tryGetItemFromPlayerHand(Entity) | Item | Returns the custom item the player is holding, or null if it is not one. |
| isUsingVault() | boolean | Whether the Vault economy hook is active. |
| getInput() | PlayerInput | The helper used to ask a player for typed chat input. |
CopyItem sword = api.getItemByName("magic_sword");if (sword != null) {api.giveItem(player, sword);}Item held = api.tryGetItemFromPlayerHand(player);if (held != null) {player.sendMessage("You are holding " + api.getItemName(held));}
Addons
An addon is a PluginAddon you register with the AddonProvider. It can add editor categories and methods, attributes, listeners and actions, and modify items as they are built.
Get the provider and register your addon, usually in your plugin's onEnable:
CopyAddonProvider provider = AddonProvider.get();provider.addAddon(new PluginAddon("YourPluginName", XMaterial.WRITABLE_BOOK.get())// .addon(...) add a methods category// .attribute(...) add a toggle/value attribute// .listener(...) listen to item events// .action(...) add a custom action block// .onItemCreate(...) modify the built ItemStack);
You can look an addon up again later with provider.getAddonByName("YourPluginName").
Custom methods
An Addon<T> exposes a class whose public methods become a new category in the editor. The first argument is the identifier players call it by; the second builds the object per player.
CopyAddonProvider provider = AddonProvider.get();provider.addAddon(new PluginAddon("YourPluginName").addon(new Addon<>("myCategory", (Player player) -> new MyMethods())));
The class holding your methods:
Copypublic class MyMethods {public void greet(Player player) {player.sendMessage("Hello from my addon!");}public int doubled(int value) {return value * 2;}}
Inside an item action the methods are then called on the identifier, for example myCategory.greet(player) or myCategory.doubled(5).
Attributes
An attribute is a per-item value (often a boolean toggle) shown in the editor that your plugin can read back. It takes a name, a GUI material, a default value, an update callback, and lore lines.
Copyprovider.addAddon(new PluginAddon("PowerScrolls", XMaterial.WRITABLE_BOOK.get()).attribute(new AddonAttribute<>("Is a scroll", // attribute nameXMaterial.WRITTEN_BOOK.get(), // GUI materialfalse, // default value(player, gui, editor, callback) -> {Boolean current = (Boolean) editor.getAttributeSerializableByName("PowerScrolls_Is a scroll").getValue();callback.result(!current); // store the new valueeditor.createAddonGui(provider.getAddonByName("PowerScrolls")).openInventory(player); // reopen the addon GUI},"&7If true, the item will be used to upgrade","&7other items and add abilities to them.","","&aClick to toggle")));
Listeners
Implement ItemsCoreListener to react to item events. Return an ItemEventResult(boolean cancel, BukkitRunnable runnable) - set cancel to true to stop the item's ability from running. Leave the runnable null for now.
Copyprovider.addAddon(new PluginAddon("PowerScrolls", XMaterial.WRITABLE_BOOK.get()).listener(new MyListener()));public class MyListener implements ItemsCoreListener {@Overridepublic ItemEventResult itemEvent(Player player, Item item, String action, Event event) {// your logic here// return true to cancel the item's abilityreturn new ItemEventResult(false, null);}}
Actions
An AddonAction is a custom action block players can place on an item. You trigger it from your own code and pass in custom variables that become available inside the action's script.
CopyAddonAction action = new AddonAction("TestAction", // action nameMaterial.REDSTONE, // GUI materialnew String[] { "&7This is a test" } // lore);provider.addAddon(new PluginAddon("PluginName", XMaterial.WRITABLE_BOOK.get()).action(action));// run it for an item that has this action attachedaction.call(player, itemStack, new HashMap<String, Object>() {{put("exampleVariable", player.getDisplayName());}});
Modify item creation
onItemCreate lets you transform the ItemStack as it is built from an Item. Every addon runs in a chain - you receive the most recent stack and return your modified one, and later addons may still change it after you.
Copyprovider.addAddon(new PluginAddon("PluginName", XMaterial.WRITABLE_BOOK.get()).onItemCreate(new ItemCreationRunnable() {@Overridepublic ItemStack onCreate(Item used, ItemStack created) {// inspect "used", modify and return "created"return created;}}));
Annotate the runnable with @AddonModifier to set a priority. The chain runs from highest to lowest, so a higher priority gets the final say:
Copy.onItemCreate(new @AddonModifier(priority = AddonPriority.LOW) ItemCreationRunnable() {@Overridepublic ItemStack onCreate(Item used, ItemStack created) {return created;}})
Hooks
A hook is like a plugin dependency you can reach from item code. Put the other plugin's jar in the hooks folder inside the ItemsCore plugin folder, then register it once with core.setHook:
Copy// core.setHook(accessName, jarName, groupId, artifactId)// accessName - how you reference it from item code (e.g. "bla")// jarName - the file name you put in the hooks folder// groupId - the plugin's Maven groupId// artifactId - the plugin's Maven artifactIdcore.setHook("bla", "OtherPlugin", "com.example", "otherplugin");
Call a method on the hook by its access name with runMethod:
Copy// bla.runMethod(methodName, Class<?>[] argTypes, Object... values)// build the argument types with core.getClassByName(...)bla.runMethod("test", new Class[]{ core.getClassByName("String") }, "hello");