Skip to content

LDLib2 UI — Agent Guide

This document is for AI agents. It provides a structured workflow for building UIs with LDLib2. Follow the decision tree, use the minimal templates, then navigate to detailed pages as needed.


Step 1: Determine Language / Format

Ask the user which format they want. This determines syntax for all subsequent code.

FormatWhen to useLanguage-specific doc
KotlinMod development with Kotlin DSL (most concise)kotlin_support.md
JavaMod development with Javagetting_start.md
KubeJSModpack scripting, no compilation neededkjs_support.md
XMLDeclarative UI structure, visual editingxml.md + XSD schema

XML note: XML defines only the UI tree and styles. You still need Java/Kotlin/KubeJS code to load the XML, do data bindings, and wrap it in a ModularUI. Guide the agent to read the XSD file for available tags and attributes.


Step 2: Determine UI Type

Key rule: If the UI needs Player data or server-side state, it must be a Menu-based UI with ModularUI.of(ui, player).


Step 3: Minimal Templates

Each template is a complete, runnable starting point. Pick the one matching Step 2.

Client-only Screen

java
ModularUI createUI() {
    var root = new UIElement().addClass("panel_bg").addChildren(
        new Label().setText("Hello")
    );
    return ModularUI.of(UI.of(root, StylesheetManager.INSTANCE.getStylesheetSafe(StylesheetManager.GDP)));
}
// Open: Minecraft.getInstance().setScreen(new ModularUIScreen(createUI(), Component.empty()));

For Menu UIs, use the built-in factories. See factory.md for full details.

java
public class MyBlock extends Block implements BlockUIMenuType.BlockUI {
    @Override
    public ModularUI createUI(BlockUIMenuType.BlockUIHolder holder) {
        var root = new UIElement().addClass("panel_bg").addChildren(
            new Label().setText("Block UI"),
            new InventorySlots()
        );
        return ModularUI.of(
            UI.of(root, StylesheetManager.INSTANCE.getStylesheetSafe(StylesheetManager.GDP)),
            holder.player
        );
    }
    // Open: BlockUIMenuType.openUI((ServerPlayer) player, pos);
}

Other triggers: Replace BlockUIMenuType with HeldItemUIMenuType (item) or PlayerUIMenuType (arbitrary). See factory.md.

HUD Overlay

java
// Client-side only. Register in RegisterGuiLayersEvent.
var muiCache = Suppliers.memoize(() -> ModularUI.of(UI.of(
    new UIElement().layout(l -> l.widthPercent(100).heightPercent(100).paddingAll(10))
)));
event.registerAboveAll(MyMod.id("my_hud"), (ModularHudLayer) muiCache::get);

See hud.md for details.

XML-based UI

xml
<?xml version="1.0" encoding="UTF-8" ?>
<ldlib2-ui xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/Low-Drag-MC/LDLib2/refs/heads/1.21/ldlib2-ui.xsd">
    <stylesheet location="ldlib2:lss/mc.lss"/>
    <root class="panel_bg">
        <label text="Hello from XML"/>
        <button text="Click me"/>
    </root>
</ldlib2-ui>
java
// Load and use
var xml = XmlUtils.loadXml(ResourceLocation.parse("mymod:my_ui.xml"));
var ui = UI.of(xml);
// Query elements: ui.select("#my_id"), ui.select(".my_class > button")
return ModularUI.of(ui, player); // or ModularUI.of(ui) for client-only

For XML auto-completion and validation, read the XSD schema to know all available tags, attributes, and structure.


Step 4: Data Binding Patterns

This is the most critical knowledge for producing correct UI code. There are 3 patterns:

Pattern A: Client-only (no server sync)

Use bindDataSource / bindObserver or Kotlin's dataSource / observer. No network involved.

java
// Consumer: display dynamic data
new Label().bindDataSource(SupplierDataSource.of(() -> Component.literal("Value: " + myVar)));
// Producer: react to user input
new TextField().bindObserver(value -> myVar = value);

Pattern B: Bidirectional sync (Menu UI)

Use DataBindingBuilder + .bind(). Server getter/setter only — client side is automatic.

java
new Switch().bind(DataBindingBuilder.bool(() -> serverBool, v -> serverBool = v).build());
new TextField().bind(DataBindingBuilder.string(() -> serverStr, v -> serverStr = v).build());
new ItemSlot().bind(itemHandler, 0); // inventory shorthand
new FluidSlot().bind(fluidTank, 0);  // fluid shorthand

Kotlin shorthand: switch { bind(::serverBool) }, textField { bind(::serverStr) }

Pattern C: Server-to-client read-only

Use S2C variants. Client cannot modify the value.

java
new Label().bind(DataBindingBuilder.componentS2C(() -> Component.literal(serverData)).build());

Kotlin: label { bindS2C({ Component.literal(serverData) }) }

For complex bindings (custom types, RPCEvent, List sync, remote getter/setter): read data_bindings.md.


Step 5: Navigation Map

Use this table to find detailed documentation by need.

Core Concepts

NeedReadPath
How ModularUI worksModularUIdocs/ldlib2/ui/preliminary/modularui.md
Screen vs MenuScreen & Menudocs/ldlib2/ui/preliminary/screen_and_menu.md
UI Factories (Block/Item/Player)Factorydocs/ldlib2/ui/factory.md
Layout (flexbox, grid, size, padding)Layoutdocs/ldlib2/ui/preliminary/layout.md
Stylesheet / LSSStylesheetdocs/ldlib2/ui/preliminary/stylesheet.md
Events (mouse, keyboard, lifecycle)Eventsdocs/ldlib2/ui/preliminary/event.md
Data Bindings & RPCData Bindingsdocs/ldlib2/ui/preliminary/data_bindings.md
Style AnimationStyle Animationdocs/ldlib2/ui/preliminary/style_animation.md
HUD OverlaysHUDdocs/ldlib2/ui/hud.md
XEI (JEI/REI/EMI)XEIdocs/ldlib2/ui/xei_support.md
XML UIXMLdocs/ldlib2/ui/xml.md
Kotlin DSLKotlindocs/ldlib2/ui/kotlin_support.md
KubeJS bindingsKubeJSdocs/ldlib2/ui/kjs_support.md

Components Quick Reference

ComponentClassKey methodDoc
Base elementUIElement.layout(), .style(), .addClass()element.md
LabelLabel.setText(), .bind()label.md
ButtonButton.setText(), .setOnClick(), .setOnServerClick()button.md
Text fieldTextField.setText(), .bind(), .setNumbersOnlyInt()text-field.md
Text areaTextArea.setText(), .bind()text-area.md
ToggleToggle.setText(), .bind()toggle.md
SwitchSwitch.bind()switch.md
SelectorSelector.setCandidates(), .bind()selector.md
Progress barProgressBar.setProgress(), .bind(), .label()progress-bar.md
ScrollerScroller / Scroller.Horizontal.bind()scroller.md
Item slotItemSlot.bind(handler, slot), .setItem()item-slot.md
Fluid slotFluidSlot.bind(tank, slot), .setFluid()fluid-slot.md
Inventory slotsInventorySlots(auto player inventory)inventory-slots.md
Tab / TabViewTab, TabView.addTab()tab.md, tab-view.md
Toggle groupToggleGroup.addToggle()toggle-group.md
Scroller viewScrollerView(scrollable container)scroller-view.md
Split viewSplitView(resizable split)split-view.md
Color selectorColorSelector.bind()color-selector.md
Tag fieldTagField.bind()tag-field.md
SearchSearchComponent.bind()search-component.md
Tree listTreeListtree-list.md
Scene (3D)Scenescene.md
Graph viewGraphViewgraph-view.md
Code editorCodeEditorcode-editor.md
InspectorInspectorinspector.md
TemplateTemplate(load from XML)template.md
Bindable valueBindableValue&lt;T&gt;.bind() (hidden sync helper)bindable-value.md
Rich textText.setText()text.md

Textures Quick Reference

TextureClassDoc
Sprite (image)SpriteTexturesprite.md
Color rectangleColorRectTexturecolor-rect.md
Color borderColorBorderTexturecolor-border.md
SDF rectangleSDFRectTexturesdf-rect.md
Resource rectRectTexturerect.md
Item stackItemStackTextureitem-stack.md
Fluid stackFluidStackTexturefluid-stack.md
TextTextTexturetext.md
AnimationAnimationTextureanimation.md
GroupGroupTexturegroup.md
ShaderShaderTextureshader.md
UI ResourceUIResourceTextureui-resource.md
LSS texture syntaxlss.md

Step 6: Pre-completion Checklist

Before returning code to the user, verify:

  • [ ] UI type matches need: Client-only Screen has no player param; Menu UI has player param
  • [ ] Data bindings are correct: Server data uses DataBindingBuilder.xxx().build() + .bind(); client-only data uses bindDataSource/bindObserver
  • [ ] Factory is registered: Menu UIs need a factory registration (Block/Item/Player) or manual MenuType
  • [ ] KubeJS script placement: LDLib2UI.* handlers must run on both sides — prefer startup_scripts/
  • [ ] XML files are placed under assets/&lt;modid&gt;/ui/ and loaded via ResourceLocation
  • [ ] Stylesheet applied: Use StylesheetManager.GDP, .MC, or .MODERN for built-in themes, or provide custom LSS
  • [ ] Output format matches request: Return ModularUI for full UIs, UIElement for reusable components

Released under the MIT License.