# Table of Contents - [HyUI](#hyui) - [Item Grid Event Data | HyUI](#item-grid-event-data-hyui) - [Getting Started | HyUI](#getting-started-hyui) - [Changelog | HyUI](#changelog-hyui) - [Tutorial: Tab Navigation | HyUI](#tutorial-tab-navigation-hyui) - [Identifying Elements | HyUI](#identifying-elements-hyui) - [Loading HYUIML From File | HyUI](#loading-hyuiml-from-file-hyui) - [Installation | HyUI](#installation-hyui) - [Opening a Page | HyUI](#opening-a-page-hyui) - [Layout Modes | HyUI](#layout-modes-hyui) - [Runtime Editing | HyUI](#runtime-editing-hyui) - [Page Interactions | HyUI](#page-interactions-hyui) - [HUD Building | HyUI](#hud-building-hyui) - [Template Processor Basics | HyUI](#template-processor-basics-hyui) - [Add Bounty (Child) at Runtime | HyUI](#add-bounty-child-at-runtime-hyui) - [Variables and Filters | HyUI](#variables-and-filters-hyui) - [Element Examples | HyUI](#element-examples-hyui) - [Template Processor | HyUI](#template-processor-hyui) - [HYUIML - HTMLish in Hytale | HyUI](#hyuiml-htmlish-in-hytale-hyui) - [Tutorial: Advanced Page Building | HyUI](#tutorial-advanced-page-building-hyui) - [Tutorial: Working with Item Grids | HyUI](#tutorial-working-with-item-grids-hyui) - [Interactivity and Page Control | HyUI](#interactivity-and-page-control-hyui) - [Tutorial: Page Building | HyUI](#tutorial-page-building-hyui) - [Runtime Template Updates | HyUI](#runtime-template-updates-hyui) - [Loops and Conditionals | HyUI](#loops-and-conditionals-hyui) - [Tutorial: Template Processor | HyUI](#tutorial-template-processor-hyui) - [Using Tabs | HyUI](#using-tabs-hyui) - [Editing Tabs at Runtime | HyUI](#editing-tabs-at-runtime-hyui) - [Components | HyUI](#components-hyui) - [Multiple Tab Navigators | HyUI](#multiple-tab-navigators-hyui) - [Tab Styles | HyUI](#tab-styles-hyui) - [Element Validation | HyUI](#element-validation-hyui) --- # HyUI **HyUI** is a powerful, developer-friendly Java library designed to simplify the creation and management of custom User Interfaces for Hytale servers. By bridging Hytale's raw UI protocol with high-level abstractions, HyUI allows you to build complex, interactive, and high-performance UIs using either a fluent **Java Builder API** or **HYUIML**, a declarative HTML/CSS-like syntax. Whether you are building a simple admin panel, a persistent HUD, or a full-scale RPG menu system, HyUI provides the tools and "escape hatches" needed to get the job done efficiently. Features * **HYUIML (HTML/CSS):** Build interfaces using a familiar, declarative HTML-like syntax with CSS styling, plus templating and reusable components. * **Fluent Builder API:** Construct nested UI hierarchies (Groups, Buttons, Labels, etc.) using a clean, readable chain of methods. * **Multi-HUD System:** Coexist with other mods effortlessly. HyUI automatically manages Hytale's single HUD slot to allow multiple independent HUD elements to be displayed simultaneously. * **Dynamic Element Injection:** Load base `.ui` files and inject dynamic elements into specific selectors at runtime. * **Event Handling Simplified:** Bind server-side logic directly to UI events using simple lambda expressions and access UI state via `UIContext`. * **Periodic UI Refresh:** Built-in support for batched, periodic HUD updates with low performance overhead. * **Specialized Builders:** Includes ready-to-use builders for: * **Buttons:** Standardized game-themed text buttons and back buttons. * **Input Fields:** Text, Numbers, Sliders, Checkboxes, and Color Pickers. * **Progress Bars:** Dynamic progress indicators with customizable textures and effects. * **Item Icons:** Display item icons with asset-backed textures. * **Containers:** Flexible Group builders with various layout modes and window frames. * **Images:** Easy asset-backed images, plus runtime-downloaded dynamic images. * **Advanced Logic (Escape Hatches):** Access raw `UICommandBuilder` instances at any point for properties not natively covered by the API. Quick Start 1 ### [hashtag](https://hyui.gitbook.io/docs#installation-gradle) Installation (Gradle) To use HyUI in your Hytale project, you can get started quickly by using the example project: https://github.com/Elliesaur/Hytale-Example-UI-Project Otherwise, add HyUI to your project via Cursemaven: 2 ### [hashtag](https://hyui.gitbook.io/docs#creating-a-page-with-hyuiml-html) Creating a Page with HYUIML (HTML) For most use cases, HYUIML is the fastest way to build layouts: 3 ### [hashtag](https://hyui.gitbook.io/docs#creating-a-hud) Creating a HUD HUDs are persistent on-screen elements: Components Builder Purpose `PageBuilder` Entry point for full-screen UIs; manages file loading and lifecycle. `HudBuilder` Entry point for HUD creation; manages multi-HUD coexistence and refreshes. `GroupBuilder` A container used to organize and layout child elements. `ContainerBuilder` Provides the standard Hytale window frame. `PageOverlayBuilder` Full-screen overlay container. `TabNavigationBuilder` Tabbed navigation bar. `TabContentBuilder` Tab content container. `ButtonBuilder` For interactive buttons; supports standard Hytale aesthetics. `LabelBuilder` For displaying dynamic text with style and anchor support. `ImageBuilder` For displaying asset-backed images (`.png`). `DynamicImageBuilder` Runtime-downloaded PNG images. `TextFieldBuilder` Captures string input from the player. `NumberFieldBuilder` Captures numeric input from the player. `DropdownBoxBuilder` Dropdown selection control. `CheckBoxBuilder` Checkbox input control. `ColorPickerBuilder` Provides a Hex color selection interface. `SliderBuilder` Provides support for number sliders. `ProgressBarBuilder` Provides support for progress bars. `TimerLabelBuilder` Timer labels with formatting. `SpriteBuilder` Animated sprite rendering. `ItemIconBuilder` Provides support for item icons. `ItemSlotBuilder` Item slot UI elements. `ItemGridBuilder` Scrollable item grid. Documentation & Examples Detailed documentation for installation, page building, HUD building, and HYUIML can be found in the `docs` folder. Requirements: * Hytale Server added as a dependency * Java 25 (or current Hytale-compatible version) * jsoup (embedded in the JAR under MIT license) * MultipleHUD - optional requirement - included source in JAR (not embedded) under MIT license. Licenses All open source licenses can be found within the JAR and GitHub repo. Help and Support Feel free to join the Discord: https://discord.gg/NYeK9JqmNB - happy to help! [NextChangelogchevron-right](https://hyui.gitbook.io/docs/home/changelog) * [Installation (Gradle)](https://hyui.gitbook.io/docs#installation-gradle) * [Creating a Page with HYUIML (HTML)](https://hyui.gitbook.io/docs#creating-a-page-with-hyuiml-html) * [Creating a HUD](https://hyui.gitbook.io/docs#creating-a-hud) sun-brightdesktopmoon Copy repositories { maven { url "https://www.cursemaven.com" } } dependencies { // Project ID: 1431415 implementation "curse.maven:hyui-1431415:" } Copy String html = """

Welcome to the menu!

"""; PageBuilder.pageForPlayer(playerRef) .fromHtml(html) .addEventListener("myBtn", CustomUIEventBindingType.Activating, (ctx) -> { playerRef.sendMessage(Message.raw("Clicked!")); }) .open(store); Copy HudBuilder.hudForPlayer(playerRef) .fromHtml("

Health: 100

") .show(store); sun-brightdesktopmoon --- # Item Grid Event Data | HyUI Below is a list of the event payloads passed to event listeners for particular events associated with Item Grids. These are useful to know which item is being dragged, from where it came and where it is going. This page documents the event data classes used for item grids. Each payload is only passed to listeners registered for the matching `CustomUIEventBindingType` value. ### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#mapping-event-type-greater-than-payload) Mapping: Event Type -> Payload CustomUIEventBindingType Payload Class `SlotClicking` `SlotClickingEventData` `SlotDoubleClicking` `SlotDoubleClickingEventData` `SlotMouseEntered` `SlotMouseEnteredEventData` `SlotMouseExited` `SlotMouseExitedEventData` `DragCancelled` `DragCancelledEventData` `Dropped` `DroppedEventData` `SlotMouseDragCompleted` `SlotMouseDragCompletedEventData` `SlotMouseDragExited` `SlotMouseDragExitedEventData` `SlotClickReleaseWhileDragging` `SlotClickReleaseWhileDraggingEventData` `SlotClickPressWhileDragging` `SlotClickPressWhileDraggingEventData` ### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#payload-details) Payload Details #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#slotclickingeventdata) `SlotClickingEventData` * Passed only to listeners registered for `CustomUIEventBindingType.SlotClicking`. * Fields: * `slotIndex` from `SlotIndex`. #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#slotdoubleclickingeventdata) `SlotDoubleClickingEventData` * Passed only to listeners registered for `CustomUIEventBindingType.SlotDoubleClicking`. * Fields: * `slotIndex` from `SlotIndex`. #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#slotmouseenteredeventdata) `SlotMouseEnteredEventData` * Passed only to listeners registered for `CustomUIEventBindingType.SlotMouseEntered`. * Fields: * `slotIndex` from `SlotIndex`. #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#slotmouseexitedeventdata) `SlotMouseExitedEventData` * Passed only to listeners registered for `CustomUIEventBindingType.SlotMouseExited`. * Fields: * `slotIndex` from `SlotIndex`. #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#dragcancelledeventdata) `DragCancelledEventData` * Passed only to listeners registered for `CustomUIEventBindingType.DragCancelled`. * Fields: * none. #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#droppedeventdata) `DroppedEventData` * Passed only to listeners registered for `CustomUIEventBindingType.Dropped`. * Fields: * `sourceItemGridIndex` from `SourceItemGridIndex`. * `sourceSlotId` from `SourceSlotId`. * `itemStackQuantity` from `ItemStackQuantity`. * `pressedMouseButton` from `PressedMouseButton`. * `itemStackId` from `ItemStackId`. * `sourceInventorySectionId` from `SourceInventorySectionId`. #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#slotmousedragcompletedeventdata) `SlotMouseDragCompletedEventData` * Passed only to listeners registered for `CustomUIEventBindingType.SlotMouseDragCompleted`. * Fields: * `sourceItemGridIndex` from `SourceItemGridIndex`. * `sourceSlotId` from `SourceSlotId`. * `itemStackQuantity` from `ItemStackQuantity`. * `pressedMouseButton` from `PressedMouseButton`. * `itemStackId` from `ItemStackId`. * `sourceInventorySectionId` from `SourceInventorySectionId`. #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#slotmousedragexitedeventdata) `SlotMouseDragExitedEventData` * Passed only to listeners registered for `CustomUIEventBindingType.SlotMouseDragExited`. * Fields: * `mouseOverIndex` from `MouseOverIndex`. #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#slotclickreleasewhiledraggingeventdata) `SlotClickReleaseWhileDraggingEventData` * Passed only to listeners registered for `CustomUIEventBindingType.SlotClickReleaseWhileDragging`. * Fields: * `slotIndex` from `SlotIndex`. * `clickMouseButton` from `ClickMouseButton`. * `clickCount` from `ClickCount`. #### [hashtag](https://hyui.gitbook.io/docs/home/item-grid-event-data#slotclickpresswhiledraggingeventdata) `SlotClickPressWhileDraggingEventData` * Passed only to listeners registered for `CustomUIEventBindingType.SlotClickPressWhileDragging`. * Fields: * `slotIndex` from `SlotIndex`. * `dragItemStackId` from `DragItemStackId`. * `dragItemStackQuantity` from `DragItemStackQuantity`. * `dragSourceInventorySectionId` from `DragSourceInventorySectionId`. * `dragSourceItemGridIndex` from `DragSourceItemGridIndex`. * `dragSourceSlotId` from `DragSourceSlotId`. * `dragPressedMouseButton` from `DragPressedMouseButton`. * `clickMouseButton` from `ClickMouseButton`. * `clickCount` from `ClickCount`. [PreviousHUD Buildingchevron-left](https://hyui.gitbook.io/docs/home/getting-started/hud-building) [NextHYUIML - HTMLish in Hytalechevron-right](https://hyui.gitbook.io/docs/home/hyuiml-htmlish-in-hytale) Last updated 1 day ago * [Mapping: Event Type -> Payload](https://hyui.gitbook.io/docs/home/item-grid-event-data#mapping-event-type-greater-than-payload) * [Payload Details](https://hyui.gitbook.io/docs/home/item-grid-event-data#payload-details) sun-brightdesktopmoon sun-brightdesktopmoon --- # Getting Started | HyUI HyUI is a fluent, builder-based library for creating and managing custom user interfaces in Hytale. It simplifies the process of building pages and HUD elements by providing a high-level Java API and a lightweight markup language. What would you like to do? * [**Install HyUI**](https://hyui.gitbook.io/docs/home/getting-started/installation) : Set up HyUI in your Hytale project. * [**Build a HUD**](https://hyui.gitbook.io/docs/home/getting-started/hud-building) : Create persistent on-screen elements like maps, health bars, or notifications. * [**Build a Page**](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building) : Create full-screen interactive menus and settings pages. * [**Use HYUIML (HTML/CSS)**](https://hyui.gitbook.io/docs/home/hyuiml-htmlish-in-hytale) : Learn how to define your UIs using a familiar markup syntax. * [**Template Processor**](https://hyui.gitbook.io/docs/home/template-processor) : Reusable HYUIML components and variables. * [**UI Elements**](https://hyui.gitbook.io/docs/home/element-examples) : Common UI element examples and patterns. * [**Element Validation**](https://hyui.gitbook.io/docs/home/element-validation) : How we validate your UI. * [**Changelog**](https://hyui.gitbook.io/docs/home/changelog) : Version updates and breaking changes. * * * Quick Start: Opening your first Page This example uses the PageBuilder to load a UI from HTML. Example.java Copy String html = "

Hello Hytale!

"; PageBuilder.pageForPlayer(playerRef) .fromHtml(html) .open(store); Concepts 1 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started#builders) Builders Everything in HyUI is built using fluent builders (e.g., `ButtonBuilder`, `LabelBuilder`). 2 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started#detached-builders) Detached Builders You can prepare your UI configurations (using `detachedPage()` or `detachedHud()`) before you even have a player reference. 3 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started#selectors-and-ids) Selectors and IDs Use `.withId("my-id")` to reference elements later for event listeners or updates. 4 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started#automatic-management) Automatic Management HyUI handles Hytale's single HUD slot limitation and complex event binding for you. [PreviousChangelogchevron-left](https://hyui.gitbook.io/docs/home/changelog) [NextInstallationchevron-right](https://hyui.gitbook.io/docs/home/getting-started/installation) Last updated 1 day ago * [Builders](https://hyui.gitbook.io/docs/home/getting-started#builders) * [Detached Builders](https://hyui.gitbook.io/docs/home/getting-started#detached-builders) * [Selectors and IDs](https://hyui.gitbook.io/docs/home/getting-started#selectors-and-ids) * [Automatic Management](https://hyui.gitbook.io/docs/home/getting-started#automatic-management) sun-brightdesktopmoon sun-brightdesktopmoon --- # Changelog | HyUI chevron-right**0.5.8 - 29 Jan 2026**[hashtag](https://hyui.gitbook.io/docs/home/changelog#id-0.5.8-29-jan-2026) * Rework internally how logging occurs, it is now enabled in releases, at Finest level only. * Add helper methods to ItemGridBuilder to update/remove/get all slots, the tutorial has also been updated to showcase this. * Add support for replacing button builders for tab navigation - this complements the existing selected/unselected styling. Use `TabNavigationBuilder.addTab(id, label, contentId, buttonBuilder)` , this means every tab's button can have its own builder. By default, tabs are built with secondary/primary button builders. You can of course update/remove tabs as well. * Add support for `CustomButtonBuilder` for tab navigation. * Add [tutorial](https://hyui.gitbook.io/docs/tutorials/tutorial-tab-navigation) for Tab Navigation. chevron-right**0.5.7 - 29 Jan 2026**[hashtag](https://hyui.gitbook.io/docs/home/changelog#id-0.5.7-29-jan-2026) * Add events for ItemGrid. See tutorial: [here](https://hyui.gitbook.io/docs/tutorials/tutorial-working-with-item-grids) . * Add Multi-Line Text Field (textarea). * Ensure store in HUDs is always called with a 'fresh' store. This means there is no need to pass a store to a HUD on creation, or opening. These are marked as deprecated. Thanks to Willem for this! chevron-right**0.5.6 - 28 Jan 2026**[hashtag](https://hyui.gitbook.io/docs/home/changelog#id-0.5.6-28-jan-2026) * Fix button text not being set. * Fix progressbar texture paths not working as expected. chevron-right**0.5.5 - 27 Jan 2026**[hashtag](https://hyui.gitbook.io/docs/home/changelog#id-0.5.5-27-jan-2026) * Update validation rules according to schema. * Add helper method to cast a value to a particular type (UIContext.getValueAs). * Optimize jar size. * Add custom button support. chevron-right**0.5.4 - 26 Jan 2026**[hashtag](https://hyui.gitbook.io/docs/home/changelog#id-0.5.4-26-jan-2026) * Add template runtime evaluation. * Add helper method to get a builder as a casted type. * CHANGE: Do not force clearing a page when reloading an image, allow caller to decide: `reloadImage(String dynamicImageElementId, boolean shouldClearPage)` chevron-right**0.5.3 - 25 Jan 2026**[hashtag](https://hyui.gitbook.io/docs/home/changelog#id-0.5.3-25-jan-2026) * Add decorated container. * Add a per-player image limit of 10. * Add Hyvatar.io component. * Add small secondary and tertiary buttons. * Fix text alignment issues. * Remove support for font size on buttons (client crash). chevron-right**0.5.2 - 24 Jan 2026**[hashtag](https://hyui.gitbook.io/docs/home/changelog#id-0.5.2-24-jan-2026) * Add access to custom styles from HYUIML. * Add dynamic images from remote sources. * Add circular progress bar support. chevron-right**0.5.1 - 24 Jan 2026**[hashtag](https://hyui.gitbook.io/docs/home/changelog#id-0.5.1-24-jan-2026) * Add default events to all elements that handle value changes, this allows us to always capture data updates. * Add numberfield support for MinValue, MaxValue, Step, MaxDecimalPlaces. * Fix bug with padding not being applied. * Add conditionals, logical operators and string comparison to template. * Add loops to template processor. chevron-right**0.5.0 - 23 Jan 2026**[hashtag](https://hyui.gitbook.io/docs/home/changelog#id-0.5.0-23-jan-2026) * Added `ItemGrid`. * Added `ItemSlot`. * Added `TabNavigation`. * Added timer label builder (multiple formats). * Added `TemplateProcessor` for HYUIML, including reusable components with variables/default values. * BREAKING CHANGE: `flex-weight` now applies to the outer wrapping group (all elements except `Group`/`Label` are wrapped). This can change layout behavior compared to earlier versions. [PreviousHyUIchevron-left](https://hyui.gitbook.io/docs) [NextGetting Startedchevron-right](https://hyui.gitbook.io/docs/home/getting-started) Last updated 9 hours ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Tutorial: Tab Navigation | HyUI In this tutorial, we will use the custom tab navigation component made for HyUI: [Using Tabs](https://hyui.gitbook.io/docs/tutorials/tutorial-tab-navigation/using-tabs) [Editing Tabs at Runtime](https://hyui.gitbook.io/docs/tutorials/tutorial-tab-navigation/editing-tabs-at-runtime) [Multiple Tab Navigators](https://hyui.gitbook.io/docs/tutorials/tutorial-tab-navigation/multiple-tab-navigators) [Tab Styles](https://hyui.gitbook.io/docs/tutorials/tutorial-tab-navigation/tab-styles) [PreviousRuntime Template Updateschevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-template-processor/runtime-template-updates) [NextUsing Tabschevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-tab-navigation/using-tabs) Last updated 9 hours ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Identifying Elements | HyUI Selectors in UI files are how we can identify elements. In HYUIML these are called "IDs" and are treated as such in the HTML we write. Any element with an ID attribute is able to be called, or changed during runtime of the plugin. Copy

Hello, World!

Let's edit our HTML a little bit. Let's add an ID to our paragraph tag: Copy

Hello, World!

Now we can change this before the page is built. What does it mean to be "built"? Built is a part of the lifecycle of Hytale's UI and HyUI itself. PageBuilder -> Open for Player -> Build to CommandBuilder steps -> Send to CommandBuilder -> Sent to Client -> Rendered on Client Once we have built the page, the PageBuilder has done its job it is finished! It hands control over to the HyUIInterface class, and events begin to trigger for interactions. Events in HyUI are handled internally, and you receive events through the event listeners added to the builder. In the next page, we'll look at how to listen for events. [PreviousOpening a Pagechevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building/opening-a-page) [NextPage Interactionschevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building/page-interactions) Last updated 1 day ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Loading HYUIML From File | HyUI It is possible and encouraged for you to load your HTML from a file stored in your resources directory. As your page gets larger, you will want to have more control over the contents of it, and IDEs often support HTML syntax highlighting. A bonus! Copy PageBuilder builder = PageBuilder.detachedPage() .loadHtml("Pages/HyUIHtmlTest.html") We can use the `loadHtml(filePath)` to load HTML from the resources of your project. Your HTML file should be formatted for HYUIML to parse correctly. The code above loads from the `Common/UI/Custom/Pages` directory, the file `HyUIHtmlTest.html` If it does not find the file, it will raise an IllegalArgumentException, or a RuntimeException if something else fails. Once you have loaded your HYUIML from file, you can use the various builder methods to load your page. ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building/loading-hyuiml-from-file#tutorial) Tutorial Create a "Pages" folder within your Common/UI/Custom directory of your plugin. Within that folder, create a new HTML file, give it the name "MyPage.html" Add in the following content to it: Copy

Hello, World!

[PreviousTutorial: Page Buildingchevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building) [NextOpening a Pagechevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building/opening-a-page) Last updated 1 day ago sun-brightdesktopmoon sun-brightdesktopmoon --- # Installation | HyUI HyUI is designed to be easily integrated into your Hytale modding project. Quick Start: Example Project To use HyUI in your Hytale project, you can get started quickly by using the example project: https://github.com/Elliesaur/Hytale-Example-UI-Project 1 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started/installation#add-the-dependency) Add the Dependency Otherwise, you can either include the JAR file directly or use Cursemaven if you are using Gradle. #### [hashtag](https://hyui.gitbook.io/docs/home/getting-started/installation#using-the-jar-file) Using the JAR file 1 Download the latest `HyUI-0.X.0.jar` (replace `X` with version) from the CurseForge page (see README). 2 Place the JAR in your project's `libs` folder. 3 Add the following to your `build.gradle` (replace `X` with version): build.gradle Copy dependencies { implementation files('libs/HyUI-0.X.0.jar') } #### [hashtag](https://hyui.gitbook.io/docs/home/getting-started/installation#using-cursemaven-gradle) Using Cursemaven (Gradle) You can use Cursemaven to easily add it as a dependency: build.gradle Copy repositories { maven { url "https://www.cursemaven.com" } } dependencies { // Replace with the actual ID from CurseForge // Link to CurseForge Files: https://www.curseforge.com/hytale/mods/hyui/files/all?page=1&pageSize=20&showAlphaFiles=hide // Project ID: 1431415 implementation "curse.maven:hyui-1431415:" } 2 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started/installation#resource-setup) Resource Setup HyUI requires certain folders in your project. Ensure your `src/main/resources` folder contains the `Common/UI/Custom` directory. The basic directory structure should look like this: * `src/main/resources/Common/UI/Custom/Pages/` * `src/main/resources/Common/UI/Custom/Huds/` * `src/main/resources/Common/UI/Custom/` These folders are good practice for pages you load from `.ui` files. These folders are also where you will store images, which are relative to the `Common/UI/Custom` folder itself. 3 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started/installation#verification) Verification To verify that HyUI is correctly installed, try opening a simple page in your mod: Example Java Copy PageBuilder.pageForPlayer(playerRef) .fromHtml("

HyUI is working!

") .open(store); [PreviousGetting Startedchevron-left](https://hyui.gitbook.io/docs/home/getting-started) [NextHUD Buildingchevron-right](https://hyui.gitbook.io/docs/home/getting-started/hud-building) * [Add the Dependency](https://hyui.gitbook.io/docs/home/getting-started/installation#add-the-dependency) * [Resource Setup](https://hyui.gitbook.io/docs/home/getting-started/installation#resource-setup) * [Verification](https://hyui.gitbook.io/docs/home/getting-started/installation#verification) sun-brightdesktopmoon sun-brightdesktopmoon --- # Opening a Page | HyUI Let's continue with our HYUIML from last time: Copy

Hello, World!

This is a cool page, but it ... does nothing? How do we get this to show? We know we "load" it into a PageBuilder, but how do we make that show for players when they do something? If you're in the example project, you'll already see an example command made for you. We'll use that for this tutorial, if you can't see it, check out the example project: [https://github.com/Elliesaur/Hytale-Example-UI-Projectarrow-up-right](https://github.com/Elliesaur/Hytale-Example-UI-Project) and find the Commands package with the ExampleCommand within it. The first thing to do is to adjust the code in the constructor, let's change it to `.loadHtml(filePath)`, and provide it the location of your example: `Pages/MyPage.html` Copy page = PageBuilder.detachedPage() .withLifetime(CustomPageLifetime.CanDismiss) .loadHtml("Pages/MyPage.html"); Now, to open that page, look inside the executeCommand method which already opens our page for us! Copy PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType()); if (playerRef != null) { // Set up our button for this player specifically. page.getById("exampleBtn", ButtonBuilder.class).ifPresent(button -> { button.addEventListener(CustomUIEventBindingType.Activating, event -> { commandContext.sendMessage(Message.raw("Button clicked!")); }); }); page.open(playerRef, store); } We will need to adjust this, let's remove the `getById` method entirely. All finished, the open method takes in a reference to a player, and the entity store and opens the page when they type the /test command in chat. ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building/opening-a-page#challenge) Challenge Edit the HYUIML page in resources and add in a button, which once clicked tells the player `Hello, World!` [PreviousLoading HYUIML From Filechevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building/loading-hyuiml-from-file) [NextIdentifying Elementschevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building/identifying-elements) Last updated 1 day ago sun-brightdesktopmoon Copy PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType()); if (playerRef != null) { page.open(playerRef, store); } sun-brightdesktopmoon --- # Layout Modes | HyUI In the previous page, we toggled layouts at runtime. Now we will slow down and actually understand what those layouts _do_. Our Bounty Board example continues. If you skipped the previous page, no judgment. But some side-eye. [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#layout-modes) Layout Modes ----------------------------------------------------------------------------------------------------------------------------- Layout modes are how Hytale arranges children inside a group/container. In HYUIML you set them with `layout-mode`, `layout`, or `text-align` on a `
`. Supported `LayoutMode` values (case-insensitive): * `Top`, `Bottom`, `Left`, `Right`, `Center`, `Full`, `Middle` * `TopScrolling`, `BottomScrolling` * `MiddleCenter` or `CenterMiddle` (same idea, different order) * `LeftCenterWrap` Think of them like pre-baked layout rules rather than full CSS. circle-info This is a mental model, not exact CSS behavior. Use it to reason about how children will be placed inside groups. [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#but...-what-are-they) But... What are they? ---------------------------------------------------------------------------------------------------------------------------------------------- Here is the mental model (rough, but useful): * `Top` / `Bottom` / `Left` / `Right`: stack children in that direction. * `Center`: center each child, still stacked. * `Full`: stretch children to fill the container as much as possible. * `Middle` / `MiddleCenter`: center content vertically, and often horizontally. * `TopScrolling` / `BottomScrolling`: like `Top` / `Bottom` but allows scroll. * `LeftCenterWrap`: wraps children into rows, centered on each row. Great for grids. [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#hyuiml-layout-modes) HYUIML Layout Modes ------------------------------------------------------------------------------------------------------------------------------------------- Let us use the Bounty Board list container and swap layout modes. In practice: * `Top` gives the classic bounty list. * `LeftCenterWrap` gives you a tile grid (useful for cards). * `TopScrolling` keeps your layout sane when the list grows past the container height. [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#using-flex-weights-because-we-are-not-savages) Using Flex Weights (Because We Are Not Savages) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When you stack items, you usually want predictable widths. Use `flex-weight` to do it. It is not full flexbox, but it is good enough to keep text from colliding. If the title gets longer, it will take more space, the level stays readable, and the button keeps its size. This is the kind of tiny detail that makes UIs feel deliberate. circle-exclamation `flex-weight` is a lightweight sizing tool - it behaves like a simple proportional allocator, not a full flexbox implementation. [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#layout-modes-for-the-outer-shell) Layout Modes for the Outer Shell --------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can also set layout modes on: * `page-overlay` * `container` / `decorated-container` * any `
` that compiles to a `GroupBuilder` A common pattern for pages: Next: we will **add new bounty cards at runtime**, because the board should evolve while the page is open. [PreviousRuntime Editingchevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/runtime-editing) [NextAdd Bounty (Child) at Runtimechevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime) Last updated 1 day ago * [Layout Modes](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#layout-modes) * [But... What are they?](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#but...-what-are-they) * [HYUIML Layout Modes](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#hyuiml-layout-modes) * [Using Flex Weights (Because We Are Not Savages)](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#using-flex-weights-because-we-are-not-savages) * [Layout Modes for the Outer Shell](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes#layout-modes-for-the-outer-shell) sun-brightdesktopmoon Copy
Copy

Slime Cleanup

Lvl 1

Copy
sun-brightdesktopmoon --- # Runtime Editing | HyUI 1 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/runtime-editing#base-hyuiml-for-the-bounty-board) Base HYUIML for the Bounty Board We will load this as a string for now. Use the standard `page-overlay` and `container` structure so the page looks like a proper HyUI page. Optionally, load it from file! Copy String html = """

Showing 3 bounties

Slime Cleanup

Lvl 1

Bandit Camp

Lvl 4

Wisp Hunt

Lvl 7

"""; 2 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/runtime-editing#runtime-editing-toggle-layout--update-summary) Runtime Editing: Toggle Layout + Update Summary We want the **Compact View** button to flip the list between `Top` and `LeftCenterWrap` layouts, and update the summary text. We also want the number field to change the summary as you type. The trick is: * Use `ctx.getById("list", GroupBuilder.class)` to grab the list container. * Change its layout mode. * Update the summary label. * Call `ctx.updatePage(true)`. Copy AtomicBoolean compact = new AtomicBoolean(false); PageBuilder.pageForPlayer(playerRef) .fromHtml(html) .addEventListener("toggle-mode", CustomUIEventBindingType.Activating, (ignored, ctx) -> { boolean newState = !compact.get(); compact.set(newState); ctx.getById("list", GroupBuilder.class).ifPresent(list -> { list.withLayoutMode(newState ? "LeftCenterWrap" : "Top"); }); ctx.getById("summary", LabelBuilder.class).ifPresent(label -> { label.withText(newState ? "Compact view: 3 bounties" : "Showing 3 bounties"); }); ctx.getById("toggle-mode", ButtonBuilder.class).ifPresent(btn -> { btn.withText(newState ? "Comfy View" : "Compact View"); }); ctx.updatePage(true); }) .addEventListener("minLevel", CustomUIEventBindingType.ValueChanged, (data, ctx) -> { String level = String.valueOf(data); ctx.getById("summary", LabelBuilder.class).ifPresent(label -> { label.withText("Min level: " + level + " (still 3 bounties)"); }); ctx.updatePage(true); }) .open(store); Yes, we edited three builders in one click. We are unstoppable. 3 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/runtime-editing#a-few-runtime-editing-tips) A Few Runtime Editing Tips circle-info * `ctx.updatePage(true)` rebuilds the whole page client-side. It is the simplest approach for runtime edits, but it is a rebuild, not a surgical patch. * For text inputs, a `ValueChanged` event fires on every change. That is great for sliders, but can be noisy for text fields. Prefer `FocusLost` for those. * If you are editing layout or visibility, expect the whole layout to reflow. Next: we dive into layout modes so you can deliberately control how this page flows instead of hoping the UI engine feels merciful. [PreviousTutorial: Advanced Page Buildingchevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building) [NextLayout Modeschevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes) Last updated 1 day ago * [Base HYUIML for the Bounty Board](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/runtime-editing#base-hyuiml-for-the-bounty-board) * [Runtime Editing: Toggle Layout + Update Summary](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/runtime-editing#runtime-editing-toggle-layout--update-summary) * [A Few Runtime Editing Tips](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/runtime-editing#a-few-runtime-editing-tips) sun-brightdesktopmoon sun-brightdesktopmoon --- # Page Interactions | HyUI We've got this far, our HTML is looking like this: Copy

Hello, World!

Let's now listen for events in our code. If you remember, our code is split between the constructor, and the `executeCommand` method. Let's focus on the `executeCommand` Method: Copy PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType()); if (playerRef != null) { page.open(playerRef, store); } We're going to add in some events before we open the page. Copy page.addEventListener("my-button", CustomUIEventBindingType.Activating, (data, ctx) -> { playerRef.sendMessage(Message.raw("Button was pressed!")); var labelText = ctx.getValueAs("my-label", String.class).orElse("N/A"); ctx.getById("my-label", LabelBuilder.class).ifPresent(labelBuilder -> { labelBuilder.withText("Woah, I changed!"); ctx.updatePage(true); }); }); Read the annotations (hover your mouse) and... try the code! Well, if you tried it (did you??? Go back!), it would fail and spit an error out at you at runtime. It can't find the "my-button" to add an event for! Duh, we forgot to add the button. Now try the code. See what happens! It should have updated the label contents and the page refreshed in front of your eyes. You probably didn't see it refresh at all. This is how we add a basic button interaction. There are different events, most likely you'll want to use ValueChanged when dealing with elements such as NumberFields, and so on. ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building/page-interactions#builder-mappings) Builder Mappings One last thing, how did we know it would be a label builder? Check out the complete reference for HYUIML [here](https://hyui.gitbook.io/docs/home/hyuiml-htmlish-in-hytale#supported-tags-and-mappings) and read how each tag is converted to builders. [PreviousIdentifying Elementschevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building/identifying-elements) [NextTutorial: Working with Item Gridschevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-working-with-item-grids) Last updated 1 day ago sun-brightdesktopmoon Copy

Hello, World!

sun-brightdesktopmoon --- # HUD Building | HyUI HUDs (Heads-Up Displays) in HyUI are persistent UI elements that stay on the player's screen. They are managed via the `HudBuilder`. [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#content-sources) Content Sources -------------------------------------------------------------------------------------------------------------- There are multiple ways to define the content of your HUD: 1 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#loading-from-ui-files) Loading from UI Files You can use an existing Hytale `.ui` file as the base for your HUD. Java Copy HudBuilder.hudForPlayer(playerRef) .fromFile("Pages/MyHud.ui") .show(store); 2 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#loading-from-hyuiml-html) Loading from HYUIML (HTML) You can define your HUD using HTML-like syntax. Java Copy HudBuilder.hudForPlayer(playerRef) .fromHtml("

Hello World!

") .show(store); 3 ### [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#manual-building) Manual Building You can manually add elements using builders. Note: `addElement(...)` only attaches elements to the root. To nest elements, use `.addChild(...)` or element-specific child helpers. Java Copy HudBuilder.hudForPlayer(playerRef) .addElement(LabelBuilder.label() .withText("Manual HUD") .withAnchor(new HyUIAnchor().setTop(10).setLeft(10))) .show(store); [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#detached-huds) Detached HUDs ---------------------------------------------------------------------------------------------------------- Sometimes you may want to prepare a HUD configuration before you have a player reference, or reuse the same configuration for multiple players. You can use `.detachedHud()` for this. Java Copy // Pre-make the HUD configuration HudBuilder builder = HudBuilder.detachedHud() .fromHtml("

Shared HUD

"); // Later, show it for a specific player builder.show(playerRef, store); [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#multi-hud-system) Multi-HUD System ---------------------------------------------------------------------------------------------------------------- One of the most powerful features of HyUI is the **Multi-HUD system**. By default, Hytale only allows a single "Custom UI HUD" to be active for a player at any given time. This usually means that if two different mods try to show a HUD, they will overwrite each other. HyUI takes care of this for you. When you call `.show()`, HyUI automatically checks if the player already has a HUD. If they do, and it's managed by HyUI (or a compatible "Multiple HUD" mod), it simply adds your new HUD to the existing stack. If not, it creates a `MultiHud` container that can host many independent HUD instances. This means: * You can have multiple independent HUD elements (e.g., a minimap, a quest tracker, and a notification bar) all running at once. * Each HUD has its own refresh rate, its own elements, and its own event listeners. * They won't interfere with each other or with other HyUI-based mods. * It's completely transparent — you just build your HUD and call `.show()`, and HyUI handles the composition. [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#running-on-the-world-thread) Running on the World Thread -------------------------------------------------------------------------------------------------------------------------------------- triangle-exclamation It is critical that calls to `.show()` are made on the world thread. If you are inside an async command or another thread, schedule the HUD opening with `world.execute()`. Failing to run `.show()` on the world thread will lead to an exception and the client disconnecting. [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#periodic-refreshing) Periodic Refreshing ---------------------------------------------------------------------------------------------------------------------- If your HUD needs to update regularly (e.g., a timer or player stats), you can set a refresh rate. HyUI optimizes these refreshes by batching updates for all HUDs belonging to the same player. [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#toggling-visibility) Toggling Visibility ---------------------------------------------------------------------------------------------------------------------- You can hide or show specific HUD instances within the multi-hud system: [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#removing-and-re-adding) Removing and Re-adding ---------------------------------------------------------------------------------------------------------------------------- If you want to completely remove a HUD from the screen (and stop its periodic refreshes), you can use `.remove()`. You can later re-add it using `.readd()`. [hashtag](https://hyui.gitbook.io/docs/home/getting-started/hud-building#showing-a-hud-on-player-join) Showing a HUD on Player Join ---------------------------------------------------------------------------------------------------------------------------------------- A common requirement is to show a HUD (like a scoreboard or player info) as soon as a player joins the world. In Hytale, this is best handled using the `PlayerReadyEvent`. When the player is ready, obtain their `PlayerRef` and `Store` to show the HUD. Remember that `.show()` must be called on the world thread. For a complete implementation of registering this event in a plugin, see `HyUIPlugin.java`. [PreviousInstallationchevron-left](https://hyui.gitbook.io/docs/home/getting-started/installation) [NextItem Grid Event Datachevron-right](https://hyui.gitbook.io/docs/home/item-grid-event-data) * [Content Sources](https://hyui.gitbook.io/docs/home/getting-started/hud-building#content-sources) * [Loading from UI Files](https://hyui.gitbook.io/docs/home/getting-started/hud-building#loading-from-ui-files) * [Loading from HYUIML (HTML)](https://hyui.gitbook.io/docs/home/getting-started/hud-building#loading-from-hyuiml-html) * [Manual Building](https://hyui.gitbook.io/docs/home/getting-started/hud-building#manual-building) * [Detached HUDs](https://hyui.gitbook.io/docs/home/getting-started/hud-building#detached-huds) * [Multi-HUD System](https://hyui.gitbook.io/docs/home/getting-started/hud-building#multi-hud-system) * [Running on the World Thread](https://hyui.gitbook.io/docs/home/getting-started/hud-building#running-on-the-world-thread) * [Periodic Refreshing](https://hyui.gitbook.io/docs/home/getting-started/hud-building#periodic-refreshing) * [Toggling Visibility](https://hyui.gitbook.io/docs/home/getting-started/hud-building#toggling-visibility) * [Removing and Re-adding](https://hyui.gitbook.io/docs/home/getting-started/hud-building#removing-and-re-adding) * [Showing a HUD on Player Join](https://hyui.gitbook.io/docs/home/getting-started/hud-building#showing-a-hud-on-player-join) sun-brightdesktopmoon Java Copy world.execute(() -> { HudBuilder.hudForPlayer(playerRef) .fromHtml("
Welcome!
") .show(store); }); Java Copy HudBuilder.hudForPlayer(playerRef) // Refresh every 1 second .withRefreshRate(1000) .onRefresh(hud -> { hud.getById("timer", LabelBuilder.class).ifPresent(label -> { label.withText("Time: " + System.currentTimeMillis()); }); }) .show(store); Java Copy // Hides the root element of this specific HUD hud.hide(); // Shows it again hud.unhide(); Java Copy // Removes the HUD from the multi-hud manager hud.remove(); // Re-adds it to the same multi-hud manager later hud.readd(); Java Copy public void onPlayerReady(PlayerReadyEvent event) { var player = event.getPlayer(); if (player == null) return; Ref ref = player.getReference(); if (ref == null || !ref.isValid()) return; Store store = ref.getStore(); World world = store.getExternalData().getWorld(); // Ensure we are on the world thread world.execute(() -> { PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType()); HudBuilder.detachedHud() .fromHtml("

Welcome!

") .show(playerRef, store); }); } sun-brightdesktopmoon --- # Template Processor Basics | HyUI 1 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/template-processor-basics#define-a-simple-data-model) Define a Simple Data Model Keep it boring. Boring is good when it is 2 a.m. Bounty.java Copy public record Bounty(String name, int level) {} 2 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/template-processor-basics#build-the-template-html) Build the Template HTML We will use `{{#each}}` to render the list. No runtime editing yet... (shh). template.html (string) Copy

{{$summary}}

{{#each bounties}}

{{$name}}

Lvl {{$level}}

{{/each}}
3 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/template-processor-basics#bind-variables-and-render) Bind Variables and Render Copy List bounties = List.of( new Bounty("Slime Cleanup", 1), new Bounty("Bandit Camp", 4), new Bounty("Wisp Hunt", 7) ); TemplateProcessor template = new TemplateProcessor() .setVariable("title", "Bounty Board") .setVariable("summary", "Showing " + bounties.size() + " bounties") .setVariable("bounties", bounties); PageBuilder.pageForPlayer(playerRef) .fromTemplate(html, template) .open(store); 4 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/template-processor-basics#advantages) Advantages circle-info * Your HYUIML stays clean, even with repeated UI blocks. * You can centralize the data shape in Java, where you already live. * You avoid copy-paste UI cards. Nobody wants that job. That is the end of the four-part arc. Feel free to go back and have a look at the previous pages. They can help! [PreviousAdd Bounty (Child) at Runtimechevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime) [NextTutorial: Template Processorchevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-template-processor) Last updated 1 day ago * [Define a Simple Data Model](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/template-processor-basics#define-a-simple-data-model) * [Build the Template HTML](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/template-processor-basics#build-the-template-html) * [Bind Variables and Render](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/template-processor-basics#bind-variables-and-render) * [Advantages](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/template-processor-basics#advantages) sun-brightdesktopmoon sun-brightdesktopmoon --- # Add Bounty (Child) at Runtime | HyUI Now we are going to mutate the page while it is open by adding a new bounty card. This is the step where your UI starts feeling alive instead of static. We will: * Add an "Add Bounty" button. * Create a `GroupBuilder` card on click. * Append it with `.addChild(...)`. * Rebuild with `ctx.updatePage(true)`. 1 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime#add-the-button-in-hyuiml) Add the Button in HYUIML Add a button next to the filters. This makes the runtime change feel intentional (and chaotic). Edit your filters layout, add some horizontal padding (the second number). Or you could just make a style class for this... (if you know how to!) Copy
2 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime#build-a-card-programmatically) Build a Card Programmatically We will create a helper method so each new bounty card looks the same. Copy private static GroupBuilder buildBountyCard(String title, int level) { return GroupBuilder.group() .withLayoutMode("Left") .addChild(LabelBuilder.label() .withText(title) .withFlexWeight(2) ) .addChild(LabelBuilder.label() .withText("Lvl " + level) .withFlexWeight(1) ) .addChild(ButtonBuilder.smallTertiaryTextButton() .withText("Track") ); } 3 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime#add-the-child-and-update-the-page) Add the Child and Update the Page Copy AtomicInteger counter = new AtomicInteger(3); PageBuilder.pageForPlayer(playerRef) .fromHtml(html) .addEventListener("add-bounty", CustomUIEventBindingType.Activating, (ignored, ctx) -> { int next = counter.incrementAndGet(); String title = "Urgent Bounty #" + next; int level = 2 + (next % 6); ctx.getById("list", GroupBuilder.class).ifPresent(list -> { list.addChild(buildBountyCard(title, level)); }); ctx.getById("summary", LabelBuilder.class).ifPresent(label -> { label.withText("Showing " + next + " bounties"); }); ctx.updatePage(true); }) .open(store); Yes, we just changed the structure of the page after it opened. No, you are not dreaming. 4 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime#a-couple-of-gotchas) A Couple of Gotchas * If you add a lot of elements, the page rebuild can get heavier. Keep the list in a scrollable container (`TopScrolling`) if it grows big. * If you need to _remove_ elements, you should... not, because HyUI doesn't have that quite yet. Use the template processor (more on that later!). Next: we will switch gears and learn how to use the **Template Processor** to generate the same page from data. No runtime editing in that one; pure setup basics. [PreviousLayout Modeschevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/layout-modes) [NextTemplate Processor Basicschevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/template-processor-basics) Last updated 1 day ago * [Add the Button in HYUIML](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime#add-the-button-in-hyuiml) * [Build a Card Programmatically](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime#build-a-card-programmatically) * [Add the Child and Update the Page](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime#add-the-child-and-update-the-page) * [A Couple of Gotchas](https://hyui.gitbook.io/docs/tutorials/tutorial-advanced-page-building/add-bounty-child-at-runtime#a-couple-of-gotchas) sun-brightdesktopmoon sun-brightdesktopmoon --- # Variables and Filters | HyUI Variables are the fuel. Without them, your template is a static napkin. With them, it becomes a Bounty Board with opinions. We will cover: * Defining variables in Java. * Using them in HYUIML. * Defaults and filters. * Dot paths for nested data. 1 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-template-processor/variables-and-filters#defining-variables) Defining Variables You can set variables one at a time: Java Copy TemplateProcessor template = new TemplateProcessor() .setVariable("title", "Bounty Board") .setVariable("summary", "Showing 3 bounties") .setVariable("region", "Forest"); Or set them in a map: Java Copy Map vars = Map.of( "title", "Bounty Board", "summary", "Showing 3 bounties", "region", "Forest" ); TemplateProcessor template = new TemplateProcessor().setVariables(vars); 2 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-template-processor/variables-and-filters#using-variables-in-hyuiml) Using Variables in HYUIML Copy

{{$summary}}

Region: {{$region}}

If the variable exists, it is replaced. If it does not exist, you can provide a default: Copy

Region: {{$region|Unknown}}

3 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-template-processor/variables-and-filters#filters) Filters Filters are tiny helpers you can apply after the variable: Copy

Shouting: {{$title|upper}}

Gold: {{$reward|number}}

If you hand the template a number, `number` will format it. If you hand it a string, it will do its best not to cry. 4 ### [hashtag](https://hyui.gitbook.io/docs/tutorials/tutorial-template-processor/variables-and-filters#dot-paths) Dot Paths If your data has nested fields, you can access them with dot paths. Java Copy public record BountyMeta(String region, String giver) {} public record Bounty(String title, int level, BountyMeta meta) {} Bounty bounty = new Bounty("Wisp Hunt", 7, new BountyMeta("Tundra", "Warden")); Copy

Region: {{$meta.region}}

Given by: {{$meta.giver}}

You can also do array or list indexing like `{{$bounties.0.title}}`, but do that only when you really, really mean it. Next: loops and conditionals, where the Bounty Board starts to feel alive. [PreviousTutorial: Template Processorchevron-left](https://hyui.gitbook.io/docs/tutorials/tutorial-template-processor) [NextLoops and Conditionalschevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-template-processor/loops-and-conditionals) --- # Element Examples | HyUI #### [hashtag](https://hyui.gitbook.io/docs/home/element-examples#ui-elements) UI Elements This page provides examples of common UI element combinations and configurations in HyUI. #### [hashtag](https://hyui.gitbook.io/docs/home/element-examples#dropdown-box-example) Dropdown Box Example A `DropdownBox` allows players to select one or more options from a list. **HYUIML Example** Copy circle-exclamation When setting the `value` attribute on a ` In this example, `other` resolves to the runtime value of the `other` dropdown (from `UIContext.getValue("other")`), allowing the selected option in `canMove` to update when the template is reprocessed. circle-info Notes: * For text inputs, prefer `FocusLost`/`FocusGained` over `ValueChanged` to avoid rebuilding on every keystroke. * See `src/main/java/au/ellie/hyui/commands/HyUITemplateRuntimeCommand.java` for a complete form example that uses runtime updates. [hashtag](https://hyui.gitbook.io/docs/home/template-processor#components-reusable-blocks) Components (Reusable Blocks) ---------------------------------------------------------------------------------------------------------------------------- Register a component template and inject parameters when you use it. Copy TemplateProcessor template = new TemplateProcessor() .registerComponent("statCard", """

{{$label}}

{{$value}}

"""); Copy {{@statCard:label=Blocks Placed,value=12.847}} {{@statCard:label=Creatures Found,value=23}} circle-info Notes: * Component parameters replace `{{$paramName}}` placeholders inside the component template. * Component templates can include normal `{{$variable}}` placeholders, which are processed after component inclusion. [hashtag](https://hyui.gitbook.io/docs/home/template-processor#combining-components-with-loops--models) Combining Components with Loops + Models ----------------------------------------------------------------------------------------------------------------------------------------------------- Components can be used inside `{{#each}}` blocks, and they can also include their own `{{#if}}` blocks. Items in a loop expose fields and getters directly, so models are straightforward to use. Copy TemplateProcessor template = new TemplateProcessor() .setVariable("items", items) .setVariable("minPower", 10) .registerComponent("showcaseItem", """

{{$name}} (Tier: {{$meta.tier}})

{{#if power >= minPower && rarity != Common}}

Power {{$power}}

{{else}}

Power {{$power}}

{{/if}}
"""); Copy {{#each items}} {{@showcaseItem:name={{$name}},meta.tier={{$meta.tier}},power={{$power}},rarity={{$rarity}}}} {{/each}} circle-info Model support: * Public fields and getters (`getX()` / `isX()`). * Nested models via dot paths (`{{$meta.tier}}`). * Lists/arrays via index (`{{$items.0.name}}`). [hashtag](https://hyui.gitbook.io/docs/home/template-processor#how-the-showcase-uses-it) How the Showcase Uses It ---------------------------------------------------------------------------------------------------------------------- In `HyUIShowcaseCommand`, the `TemplateProcessor` is used to: * Define player stats (variables) like `playerName`, `playerLevel`, and `playerGold`. * Register reusable blocks such as `statCard` and `featureItem`. * Render the final HYUIML string with `PageBuilder.fromTemplate(...)`. This keeps the HYUIML readable while avoiding duplicated markup for repeated UI patterns. [PreviousElement Exampleschevron-left](https://hyui.gitbook.io/docs/home/element-examples) [NextTutorial: Page Buildingchevron-right](https://hyui.gitbook.io/docs/tutorials/tutorial-page-building) --- # HYUIML - HTMLish in Hytale | HyUI HYUIML is an HTML-like markup language for defining Hytale UIs using a familiar syntax. It is parsed by HyUI and converted into the fluent builder API calls under the hood. [hashtag](https://hyui.gitbook.io/docs/home/hyuiml-htmlish-in-hytale#basic-usage) Basic Usage -------------------------------------------------------------------------------------------------- You can load HYUIML directly into a `PageBuilder`: Copy String html = """

Hello from HYUIML!

"""; PageBuilder.pageForPlayer(playerRef) .fromHtml(html) .open(store); [hashtag](https://hyui.gitbook.io/docs/home/hyuiml-htmlish-in-hytale#supported-tags-and-mappings) Supported Tags and Mappings ---------------------------------------------------------------------------------------------------------------------------------- HTML Tag HyUI Builder Notes `
` `GroupBuilder` Use for layout and containers. `
` `TabContentBuilder` Tab content container linked to a tab ID. `
` `ContainerBuilder` Uses the decorated container UI file for a styled frame. `
` `ContainerBuilder` Uses the container UI file for a frame with minimal style. `

` `LabelBuilder` Standard text labels. `

`, often used for form field descriptions. `