Developer API: Making an Ability Trigger - BoBoBalloon/InnovativeItemsDOCS GitHub Wiki

Intro

For this example, I will demonstrate below an ability trigger that fires every time a player picks up the custom item.

Make a new Ability Trigger

First make a new class that extends the AbilityTrigger class. Keep in mind that this class has two generic types.

public class PickupItemTrigger extends AbilityTrigger<Event, RuntimeContext> {
    public PickupItemTrigger() {
        super();
    }

    @NotNull
    public Player fromEvent(@NotNull Event event) {

    }

    @Nullable
    public RuntimeContext trigger(@NotNull Event event, @NotNull CustomItem item, @NotNull Ability ability) {

    }
}

The ability trigger class header looks like so: AbilityTrigger<T extends Event, S extends RuntimeContext>

  • The type T represents the class of the bukkit event you want to listen for (because of that, the provided event class MUST have a static getHandlers method as shown on the spigot javadocs)

  • The type S represents the runtime context that you will initialize and will be passed to all the conditions and keywords in the ability that uses this trigger

Because of that we can change our class header a look a little something like this:

public class PickupItemTrigger extends AbilityTrigger<EntityPickupItemEvent, RuntimeContext> {
    public PickupItemTrigger() {
        super();
    }

    @NotNull
    public Player fromEvent(@NotNull EntityPickupItemEvent event) {

    }

    @Nullable
    public RuntimeContext trigger(@NotNull EntityPickupItemEvent event, @NotNull CustomItem item, @NotNull Ability ability) {

    }
}

Make a new Ability Trigger: Constructor

The constructor signature of an ability trigger looks a little something like this:

public AbilityTrigger(@NotNull String identifier, @Nullable String regex, @NotNull Class<T> eventClass, @NotNull Class<S> contextClass, @NotNull InventoryIterator<T> iterator, @Nullable Predicate<T> predicate, @NotNull FunctionTargeter... targeters)

Let's break each parameter down:

  • identifier - the identifier of the ability trigger, used for internal references and error messages, will be used for parsing if the regex parameter is null (identifier's must only use normal characters with the exception of "-", numbers and other characters are not allowed in the identifier)
  • regex - a nullable regular expression that will be used to parse your ability trigger, it will take priority over the identifier
  • eventClass - the class of the type T
  • contextClass - the class of the type S
  • iterator - a functional interface used to inform the api how to iterate over multiple items and convert them to their custom item equivalent (will be explained in more detail later in the tutorial)
  • predicate - a nullable predicate that must be true for the underlying ability trigger to be called from the bukkit event
  • targeters - a vararg of FunctionTargeters that represent all the targeters that can be used on an ability while this is the trigger. (You do not have to provide FunctionTargeter.PLAYER as that is given as a default and you cannot provide an array where any of the elements are null)

Lets update our constructor to pass these into the superclass's constructor:

public PickupItemTrigger() {
    super("item-pickup", null, EntityPickupItemEvent.class, RuntimeContext.class, InventoryIterator.fromFunctionSingleton((event, inventory) -> event.getItem().getItemstack()), event -> event.getEntity() instanceof Player);
}

We could skip the targeters parameter because if you leave a vararg empty it becomes an empty array and the api will add the player targeter for you.

Make a new Ability Trigger: fromEvent() Method

The fromEvent() method is a simple method that should be used to return a player from type T. Keep in mind that this will only be called if the predicate in the constructor is null or returned true.

Lets update our fromEvent() method to match this:

@NotNull
public Player fromEvent(@NotNull EntityPickupItemEvent event) {
   return (Player) event.getEntity(); //we can cast this safely because the predicate in the constructor already did an instanceof check
}

Make a new Ability Trigger: trigger() Method

The trigger method will be called every time a custom item with an ability with your ability trigger is found in the collection your InventoryIterator found. It will pass you the instance of the event, with the instance of the custom item, an the instance of the ability. With that you are required to return an instance of the type S that will be used for ability execution.

Do NOT execute the provided ability inside of the trigger method, it will be handled for you.

Since this trigger is pretty elementary, the trigger method will be pretty straightforward. Keep in mind that this method is nullable and if you choose to return null the trigger will cancel it's current execution for that given item.

@Nullable
public RuntimeContext trigger(@NotNull EntityPickupItemEvent event, @NotNull CustomItem item, @NotNull Ability ability) {
    return new RuntimeContext(this.fromEvent(event), ability);
}

Make a new Ability Trigger: All Together

We have already covered all the basic elements of an ability trigger, the final product is below:

public class PickupItemTrigger extends AbilityTrigger<EntityPickupItemEvent, RuntimeContext> {
    public PickupItemTrigger() {
        super("item-pickup", null, EntityPickupItemEvent.class, RuntimeContext.class, InventoryIterator.fromFunctionSingleton((event, inventory) -> event.getItem().getItemstack()), event -> event.getEntity() instanceof Player);
    }

    @NotNull
    public Player fromEvent(@NotNull EntityPickupItemEvent event) {
        return (Player) event.getEntity(); //we can cast this safely because the predicate in the constructor already did an instanceof check
    }

    @Nullable
    public RuntimeContext trigger(@NotNull EntityPickupItemEvent event, @NotNull CustomItem item, @NotNull Ability ability) {
        return new RuntimeContext(this.fromEvent(event), ability);
    }
}

Registering the Ability Trigger

Just like with functions, ability triggers must be registered via the FunctionManager that can be obtained using the InnovativeItemsAPI utility class. Please remember that like functions, ability triggers must be registered on the onLoad() method, it will not work if you register on the onEnable() method of your main class. Also, don't worry about registering the bukkit event listener, that is handled in the backend for you.

@Override
public void onLoad() {
    FunctionManager functionManager = InnovativeItemsAPI.getFunctionManager();

    functionManager.registerTriggers(new PickupItemTrigger());
}