A mechanic is a custom item property. There can be different variations of the same property on different items. For example, the durability property allows you to define a custom durability for an item, but not all items that have a durability mechanic have the same durability.
The durability mechanic works by storing the item's durability in its metadatas and uses the vanilla durability bar to display its custom durability and not its vanilla durability
So if a Mechanic is different for every Item, should I rewrite a different Durability everytime?
No, it would be far too long. Instead, Oraxen offers a MechanicFactory system. Basically you will have to create a Mechanics class that is configurable, and a MechanicsFactory class that will configure all the different versions of your Mechanic class. It will also manage the common code of all these versions.
Okay, but I want to modify the items which implement my Mechanic to store data in it, is it possible?
Of course, for this purpose Oraxen allows you to associate a list of ItemModifier to each mechanic. An ItemModifier is Function<ItemBuilder, ItemBuilder> which is basically a small piece of code that contains changes to be made to an item when it is generated by the server via its configuration. For example for durability mechanics I use an itemModifier that stores the durability chosen by the user in the item's metadatas.
For this tutorial I will take as an example the durability mechanic (because it is very simple to understand) but you can follow this tutorial to create the one you want.
First step: create our mechanic class
Start by creating a class inheriting from Mechanic, if you use you should get something like this:
class DurabilityMechanic extends Mechanic {
public DurabilityMechanic(MechanicFactory mechanicFactory,
ConfigurationSection section,
Function<ItemBuilder, ItemBuilder>... modifiers) {
super(mechanicFactory, section, modifiers);
}
}
The Mechanic constructor takes three arguments:
- An instance of the Factory which created the Mechanic
- The section used to configure the Mechanic
- The item modifier(s)
I want each variation of my mechanics to have a different durability, so I will read the configuration of the mechanics and store the value of the field value.
How the Mechanic configuration section will look like:
class DurabilityMechanic extends Mechanic {
private int itemDurability;
public DurabilityMechanic(MechanicFactory mechanicFactory,
ConfigurationSection section) {
/* We give:
- an instance of the Factory which created the mechanic
- the section used to configure the mechanic
- the item modifier(s)
*/
super(mechanicFactory, section, item ->
item.setCustomTag(NAMESPACED_KEY,
PersistentDataType.INTEGER, section.getInt("value")));
this.itemDurability = section.getInt("value");
}
public int getItemMaxDurability() {
return itemDurability;
}
}
So now we have a DurabilityMechanic class that is able to adapt to any item and that will call our DurabilityModifier class to tell to Oraxen which modifications to do before creating them (here we just add a data in the item which contains the wanted new durability).
Second step: create our mechanic factory class
As before, use your ide features to automatically create a class that extends MechanicFactory:
class DurabilityMechanicFactory extends MechanicFactory {
public DurabilityMechanicFactory(ConfigurationSection section) {
super(section);
}
@Override
public Mechanic parse(ConfigurationSection itemMechanicConfiguration) {
return null;
}
}
We rewrite the parse method to create a new Mechanic (via the DurabilityMechanic class created previously). We also want to tell to Oraxen that this mechanic is successfully implemented and can be loaded using addToImplemented method. So our class now looks like that:
public class DurabilityMechanicFactory extends MechanicFactory {
public DurabilityMechanicFactory(ConfigurationSection section) {
super(section);
}
@Override
public Mechanic parse(ConfigurationSection itemMechanicConfiguration) {
Mechanic mechanic = new DurabilityMechanic(this, itemMechanicConfiguration);
addToImplemented(mechanic);
return mechanic;
}
}
Third step: add our features (events)
In my case I need to use only one event to play with durability and I will create a DurabilityMechanicsManager class
that implements Listener to have a clean and tidy code but I could have done it directly in DurabilityMechanicFactory.
I tell to Bukkit which class manages the events when the factory is built:
public class DurabilityMechanicFactory extends MechanicFactory {
public DurabilityMechanicFactory(String mechanicId) {
super(mechanicId);
MechanicsManager.registerListeners(OraxenPlugin.get(),
new DurabilityMechanicsManager(this));
}
@Override
public Mechanic parse(ConfigurationSection itemMechanicConfiguration) {
Mechanic mechanic = new DurabilityMechanic(this, itemMechanicConfiguration);
addToImplemented(mechanic);
return mechanic;
}
}
In order to calculate the durability to display on the item according to the real durability managed by the plugin I use some simple maths:
To finish we need to register our MechanicFactory and reload the items to apply the new mechanic to them.
It is recommended to register it in an EventListener for OraxenNativeMechanicsRegisteredEvent, due to /oraxen reload all clearing this registry.
To do this we need to add these lines in the onEnable method of our plugin: