Code Patterns

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

← Back to Patterns
ui

ui-interactive-dialog

Dialog pattern using InteractiveCustomUIPage with button click event handling. Demonstrates event binding, dynamic text setting with cmd.set(), and closing the page programmatically.

Example Code

java
// StyledDialog.ui
@PrimaryButtonStyle = TextButtonStyle(
    Default: (Background: #3a7bd5, LabelStyle: (FontSize: 16, TextColor: #ffffff, RenderBold: true, HorizontalAlignment: Center)),
    Hovered: (Background: #4a8be5, LabelStyle: (FontSize: 16, TextColor: #ffffff, RenderBold: true, HorizontalAlignment: Center)),
    Pressed: (Background: #2a6bc5, LabelStyle: (FontSize: 16, TextColor: #ffffff, RenderBold: true, HorizontalAlignment: Center))
);

Group {
    Anchor: (Width: 500, Height: 350);
    Background: #141c26(0.98);
    LayoutMode: Top;
    Padding: (Full: 24);

    Label #Headline {
        Text: "Welcome!";
        Anchor: (Height: 55);
        Style: (FontSize: 32, TextColor: #ffffff, HorizontalAlignment: Center, RenderBold: true);
    }

    Label #Message {
        Text: "This is a styled dialog!";
        Anchor: (Height: 50);
        Style: (FontSize: 16, TextColor: #96a9be, HorizontalAlignment: Center);
    }

    Group { FlexWeight: 1; }  // Spacer pushes buttons to bottom

    Group {
        LayoutMode: Center;
        Anchor: (Height: 50);

        TextButton #ActionButton {
            Text: "OK";
            Anchor: (Width: 140, Height: 44);
            Style: @PrimaryButtonStyle;
        }
    }
}

// StyledDialogPage.java
public class StyledDialogPage extends InteractiveCustomUIPage<StyledDialogPage.DialogEventData> {

    private final String headline;
    private final String message;

    // Empty EventData - just need to know button was clicked
    public static class DialogEventData {
        public static final BuilderCodec<DialogEventData> CODEC =
            BuilderCodec.builder(DialogEventData.class, DialogEventData::new).build();
    }

    public StyledDialogPage(@Nonnull PlayerRef playerRef, String headline, String message) {
        super(playerRef, CustomPageLifetime.CanDismissOrCloseThroughInteraction, DialogEventData.CODEC);
        this.headline = headline;
        this.message = message;
    }

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

        // Set dynamic text values
        cmd.set("#Headline.Text", headline);
        cmd.set("#Message.Text", message);

        // Bind button click - triggers handleDataEvent when clicked
        evt.addEventBinding(CustomUIEventBindingType.Activating, "#ActionButton");
    }

    @Override
    public void handleDataEvent(
        @Nonnull Ref<EntityStore> ref,
        @Nonnull Store<EntityStore> store,
        @Nonnull DialogEventData data
    ) {
        Player player = store.getComponent(ref, Player.getComponentType());
        player.getPageManager().setPage(ref, store, Page.None);  // Close
    }
}

Thread Safety

InteractiveCustomUIPage handles events on the server thread

Common Mistakes

Forgetting to create the CODEC for EventData class - required even if empty