Code Patterns

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

← Back to Patterns
ui

ui-event-binding

Different event binding types for UI interactions. Activating is most common (button clicks), but other types exist for hover, focus changes, and value changes.

Example Code

java
// Event binding in build() method
@Override
public void build(
    @Nonnull Ref<EntityStore> ref,
    @Nonnull UICommandBuilder cmd,
    @Nonnull UIEventBuilder evt,
    @Nonnull Store<EntityStore> store
) {
    cmd.append("Pages/MyPage.ui");

    // CustomUIEventBindingType.Activating - Most common
    // Triggered when: button clicked, checkbox toggled, enter pressed in text field
    evt.addEventBinding(CustomUIEventBindingType.Activating, "#MyButton");

    // With EventData - pass values when event fires
    evt.addEventBinding(
        CustomUIEventBindingType.Activating,
        "#SaveButton",
        new EventData()
            .append("Action", "Save")
            .append("@InputValue", "#TextInput.Value")  // Read input value
    );

    // Multiple buttons with different actions
    evt.addEventBinding(
        CustomUIEventBindingType.Activating,
        "#ConfirmButton",
        new EventData().append("Action", "Confirm")
    );

    evt.addEventBinding(
        CustomUIEventBindingType.Activating,
        "#CancelButton",
        new EventData().append("Action", "Cancel")
    );
}

// Handle different actions in handleDataEvent
@Override
public void handleDataEvent(
    @Nonnull Ref<EntityStore> ref,
    @Nonnull Store<EntityStore> store,
    @Nonnull MyEventData data
) {
    switch (data.action) {
        case "Save":
            // Handle save with data.inputValue
            break;
        case "Confirm":
            // Handle confirm
            break;
        case "Cancel":
            // Handle cancel
            break;
    }

    // Close page
    Player player = store.getComponent(ref, Player.getComponentType());
    player.getPageManager().setPage(ref, store, Page.None);
}

// EventData for above example
public static class MyEventData {
    public String action;
    public String inputValue;

    public static final BuilderCodec<MyEventData> CODEC = BuilderCodec.builder(MyEventData.class, MyEventData::new)
        .append(new KeyedCodec<>("Action", Codec.STRING), (o, v) -> o.action = v, o -> o.action).add()
        .append(new KeyedCodec<>("@InputValue", Codec.STRING), (o, v) -> o.inputValue = v, o -> o.inputValue).add()
        .build();
}

Thread Safety

Events are processed on server thread - handleDataEvent is thread-safe

Common Mistakes

Not including EventData when you need to distinguish between multiple buttons - all events call same handleDataEvent method