Events - ParzivalExe/guiapi GitHub Wiki

Generally, Events are of course handled over the Bukkit-EventHandler and it is therefore not difficult to use these Events, but there are some additions with GuiAPI that are interesting to talk about, so: Lets go

Bukkit-Events

I will demonstrate the BukkitEvent-Implementation by using the EventComponentClickedEvent but you would use what is shown here with most GuiAPI Events. So, first we will create a small Gui to test this on:

Gui eventGui = new Gui("Event-Gui");

ComponentMeta eventMeta = new ComponentMeta("Event", new ItemStack(Material.COMMAND));
EventComponent eventComponent = new EventComponent(eventMeta);

eventGui.setComponent(eventComponent, 4);

eventGui.openGui(player);

Obviously you should create this Gui through a Command, but I will not explain how to create a new Command in this Tutorial anymore.

Next, you also have to implement Listener and register this Class as a EventListener so that we are then able to implement BukkitEvents.

@EventHandler
public void eventComponentClicked(EventComponentClickedEvent event) {
    //Content
}

Now, that should be familiar to you. But here the problems start, because this Method is now called every time any EventComponent in any Gui is clicked, not just the EventComponent(s) in your Gui we created in this Class. Well, there are several ways to check if the right EventComponent has been clicked. One of them is to look at the title of this EventComponent and the title of the Gui

if(event.getGui().getTitle().Equals("Event-Gui") && event.getClickedEventComponent().getMeta().getTitle().Equals("Event")) {
    //Content
}

But as you can see, this isn't a very good looking and accurate way to test this as this wouldn't work the Moment we changed the title of either the Gui or the EventComponent.

So, let's tackle the Gui first. Here, there is actually a very good way to check if it's the Gui right now. We can simply write:

if(event.isGuiOpenedInThisClass()) {
    //Content
}

As you might already guess from the name of this Method, this always returns true if the Gui that this Event is originating from has been opened in this Class and because we only open one Gui in this class (eventGui for player), we can simply rely on this Method. This would by the way also work for XML-Guis that are opened in this Class and even with Guis that are opened inside the Gui we opened in this Class (for example through a Folder).

There is also a Method isGuiOpenedInClass(Class) which can be used if the Gui was opened in another class than the EventHandlers.

When it comes to checking if the Component is right, there unfortunately isn't a perfect way to check this right now but a good way to at least minimize the risk of title in creation and event not being the same is to make this title a variable:

public static final string EVENT_COMPONENT_TITLE = "Event";

Then change the creation of the EventComponent to

ComponentMeta eventMeta = new ComponentMeta(EVENT_COMPONENT_TITLE, new ItemStack(Material.COMMAND));
EventComponent eventComponent = new EventComponent(eventMeta);

and then add this to the if-statement in EventComponentClickedEvent

if(event.isGuiOpenedInThisClass() && event.getClickedEventComponent().getMeta().getTitle().Equals(EVENT_COMPONENT_TITLE)) {
    //Content
}

ComponentClickAction

Now, if we want to simplify this a bit, we must leave Bukkit-Events behind us and use a custom interface from the GuiAPI.

For this we can use the method eventComponent.addClickListener(ComponentClickAction). There are two ways to use this Method.

The first one is for the whole class in which case we first have to implement ComponentClickAction for this class and therefore also add the following method to your class:

@Override
public boolean onClick(Component component, Player whoClicked, Gui gui, InventoryAction action, ClickType clickType) {
    //Content
    return true;
}

The return must always be true when you have performed some action and false if this method has done nothing.

Now we only need to call...

eventComponent.addClickListener(this);

...and it will work.


The second way to implement ComponentClickAction is for every Component separately, either directly in the function or through a variable. To implement it directly into the function would look like this:

eventComponent.addClickListener(new ComponentClickAction() {
    @Override
    public boolean onClick(Component component, Player whoClicked, Gui gui, InventoryAction action, ClickType clickType) {
        //Content
        return true;
    }
});

This is especially useful for very small actions that don't need to be implemented to complicated because they don't take up a lot of space.


If you still want to use a different ComponentClickAction for different Components but not implement them at the same position in code where you are also building your inventory (is pretty useful because it keeps UI and Logic separate), you can implement ComponentClickAction as one or more fields inside your class:

private ComponentClickAction eventComponentClickAction = new ComponentClickAction() {
    @Override
    public boolean onClick(Component component, Player player, Gui gui, InventoryAction inventoryAction, ClickType clickType) {
        //Content
        return true;
    }
};

and then add this ComponentClickAction to your component like this:

eventComponent.addClickListener(eventComponentClickAction);

Now, that were many different ways to implement ComponentClickAction. As you can probably see by how much I talked about ComponentClickAction, in my opinion this is probably the superior way of handling ClickEvents for a Component as every Component can easily have it's own Listener and we don't have to check first, if this is actually the right component that has thrown this event.

But, if you are already fully invested in the Bukkit-Event System, you have also seen that it is not very difficult to use this System as well.

Resources

BukkitEvent-Classes: io.github.parzivalExe.guiApi.events.*
ClickAction-Interface: io.github.parzivalExe.guiApi.components.ComponentClickAction


For an complete overview about all the events and what they do, you can check out what events are thrown by the different Components by looking at their own chapters under the Events-Section.