Code Patterns

Copy-paste examples for common plugin tasks. Commands, events, ECS, GUI, and more.

← Back to Patterns
gui

Custom UI Page

Create custom UI pages by extending InteractiveCustomUIPage. Define data codec for event handling.

Example Code

java
public class MyGui extends InteractiveCustomUIPage<MyGui.GuiData> {

    public MyGui(@Nonnull PlayerRef playerRef, @Nonnull CustomPageLifetime lifetime) {
        super(playerRef, lifetime, GuiData.CODEC);
    }

    @Override
    public void build(@Nonnull Ref<EntityStore> ref, @Nonnull UICommandBuilder ui,
                      @Nonnull UIEventBuilder events, @Nonnull Store<EntityStore> store) {
        // Load UI file
        ui.append("Pages/MyPage.ui");

        // Set text
        ui.set("#Title.Text", "Hello World!");

        // Bind button event
        events.addEventBinding(
            CustomUIEventBindingType.Activating,
            "#MyButton",
            EventData.of("Action", "button_clicked")
        );
    }

    @Override
    public void handleDataEvent(@Nonnull Ref<EntityStore> ref,
                                @Nonnull Store<EntityStore> store,
                                @Nonnull GuiData data) {
        super.handleDataEvent(ref, store, data);
        if ("button_clicked".equals(data.action)) {
            // Handle button click
            var player = store.getComponent(ref, Player.getComponentType());
            player.sendMessage(Message.raw("Button clicked!"));
        }
        this.sendUpdate();
    }

    public static class GuiData {
        public static final BuilderCodec<GuiData> CODEC = BuilderCodec.<GuiData>builder(GuiData.class, GuiData::new)
            .addField(new KeyedCodec<>("Action", Codec.STRING), (d, s) -> d.action = s, d -> d.action)
            .build();
        private String action;
    }
}

// Open the page:
player.getPageManager().openCustomPage(ref, store, new MyGui(playerRef, CustomPageLifetime.CanDismiss));

Thread Safety

build() and handleDataEvent() run on world thread.

Common Mistakes

Forgetting to call sendUpdate() after handling events. Not defining CODEC for data class.