Gui Controllers

A GuiController is a tubing bean which is annotated with the @GuiController annotation.

The controller class defines entry points for player interaction. Player interaction can be:

  • Executing a command

  • Clicking inside an inventory GUI

When a bean is annotated this way Tubing will register all methods of the class annotated with a @GuiAction annotation. A GuiAction is a unique identifier which can be compared to endpoints in web development.

A GuiAction method can return one of the following:

  • TubingGui

  • GuiTemplate

  • String

  • GuiActionReturnType

  • void

  • Any of the above wrapped in AsyncGui<T>

To explain the different types above we will implement a simple GuiAction: "Show all the active bans"

Option 1: Return a TubingGui

A TubingGui is a class which represents an inventory + actions that should be executed upon item click.

The BannedPlayersViewBuilder is a class which contains the logic to retrieve the bans and build the TubingGui class.

@GuiController
public class BanGuiController {

    private final BannedPlayersViewBuilder bannedPlayersViewBuilder;

    public BanGuiController(BannedPlayersViewBuilder bannedPlayersViewBuilder) {
        this.bannedPlayersViewBuilder = bannedPlayersViewBuilder;
    }

    @GuiAction("manage-bans/view/overview")
    public TubingGui getBannedPlayersOverview(
        @GuiParam(value = "page", defaultValue = "0") int page
    ) {
        return bannedPlayersViewBuilder.buildGui(page);
    }

}

Option 2: Return an AsyncGui

The above configuration will definitely work, but there is one problem with it. The BannedPlayersViewBuilder will retrieve all the banned players from the database. All Gui Actions are executed on the main thread by default. Retrieving database info on the main thread is not a good idea so we need to tell Tubing to execute this particular method on a separate thread.

We can easily do this by return a AsyncGui<TubingGui> instead of a TubingGui. The async method has a Producer as parameter. This should return the original TubingGui. The entire logic inside the lambda will be executed on a separate thread. The return value will be shown to the player on the main thread.

public class BanGuiController {

    private final BannedPlayersViewBuilder bannedPlayersViewBuilder;

    public BanGuiController(BannedPlayersViewBuilder bannedPlayersViewBuilder) {
        this.bannedPlayersViewBuilder = bannedPlayersViewBuilder;
    }

    @GuiAction("manage-bans/view/overview")
    public AsyncGui<TubingGui> getBannedPlayersOverview(
        @GuiParam(value = "page", defaultValue = "0") int page
    ) {
        return AsyncGui.async(() -> bannedPlayersViewBuilder.buildGui(page));
    }

}

Option 3: Return a template

Tubing supports using freemarker templates to build GUIs. This provides a cleaner separation and less Java code to create GUIs.

   @GuiAction("manage-bans/view/overview")
    public AsyncGui<TubingGui> getBannedPlayersOverview(
        @GuiParam(value = "page", defaultValue = "0") int page
    ) {
        return AsyncGui.async(() -> {
            List<Ban> bans = banRepository.retrieveAll();
            HashMap<String, Object> params = new HashMap();
            params.put("bans", bans);
            return GuiTemplate.template("gui/ban/overview.ftl", params);
        });
    }

When returning a template we have to pass all parameters you want to be available in the freemarker template.

Other return types

void

Returning void just closes any open GUIs.

String

When you return a String it means you are redirecting to another action. So the String should be a valid GuiAction.

GuiActionReturnType

There are 3 kind of return types.

  • BACK: tells Tubing to just go back to the GUI that was already open.

  • KEEP_OPEN: Keeps the existing GUI open from which the action was instantiated. The difference between BACK and KEEP_OPEN is that BACK will actually execute the previous action again, meaning close the GUI and execute the previous action reopening the same GUI. While KEEP_OPEN just never closes the GUI. In almost all cases you want to use BACK rather than KEEP_OPEN

Last updated