Skip to content

Getting Started

“Perrier” edited this page May 23, 2026 · 3 revisions

Getting Started

This page walks you through wiring the library into a Fabric mod and putting your first screen on screen.

1. Add the dependency

Three artifacts ship from this repo. Most mods only need the Fabric one; add the Spigot one separately if you're writing a Bukkit/Paper plugin that talks to the mod (see Networking).

GitHub Packages requires auth even for reads — drop a gpr.user / gpr.key pair in ~/.gradle/gradle.properties (a personal access token with read:packages is enough), and the repo declaration below will resolve.

In your Fabric mod's build.gradle:

repositories {
    maven {
        url = "https://maven.pkg.github.com/SAOFR-DEV/Modding-Lib"
        credentials {
            username = findProperty("gpr.user")
            password = findProperty("gpr.key")
        }
    }
}

dependencies {
    modImplementation "org.triggersstudio:moddinglib:<version>"
}

In a Spigot/Paper plugin's build.gradle (only needed if your plugin handles ModdingLib channel messages):

dependencies {
    compileOnly "org.triggersstudio:moddinglib-spigot:<version>"
}

…and in your plugin.yml:

depend: [ModdingLib]

(Replace the <version> with whatever's current on the releases page.)

2. Open a screen

Every screen built with this library is a UIScreen — a Minecraft Screen that renders a single UIComponent tree. Create one with Components.Screen(...) and pass it to MinecraftClient.setScreen(...).

import org.triggersstudio.moddinglib.client.ui.screen.UIScreen;
import static org.triggersstudio.moddinglib.client.ui.api.Components.*;
import static org.triggersstudio.moddinglib.client.ui.styling.Styles.*;

UIScreen screen = Screen(
        Column(
                padding(16).backgroundColor(0xFF_1A_1A_1A).build(),

                Text("Hello, world!", fontSize(20).textColor(WHITE).bold().build())
        ),
        "My Screen"  // window title
);

MinecraftClient.getInstance().setScreen(screen);

Screen(component) and Screen(component, title) are both valid; the title is just the Text.literal(...) passed to the parent Screen constructor.

3. React to user input

Use State<T> for any value that needs to drive the UI. Read it with state.get(), mutate it with state.set(...). Hand state.map(...) (or any Supplier<...>) to a component to make that component refresh whenever the state changes — no manual rerender, no init() resets.

State<Integer> counter = State.of(0);

UIScreen screen = Screen(Column(
        padding(20).backgroundColor(0xFF_1A_1A_1A).build(),

        // Reactive: the lambda is read every frame.
        Text(counter.map(v -> "Counter: " + v),
             fontSize(16).textColor(WHITE).build()),

        Button("+1",
                width(80).height(28)
                        .onClick((x, y, btn) -> counter.set(counter.get() + 1))
                        .build())
));

Static text (no live updates) uses the Text(String, Style) overload; reactive text uses Text(Supplier<String>, Style).

4. Run the demos

The library ships a /demomenu client command (registered in UICommands.register()):

  • /demomenu — opens a tooltip showcase
  • /demomenu playerrender — opens the player-render demo
  • /demomenu chart — opens the chart demo

You don't have to call this from your mod — it's a self-contained dev tool baked into the library. See Devmode & Examples for the full list of bundled ExampleScreens.create*Screen() factories you can open from your own keybind.

Where next

  • Concepts — how UIComponent lifecycle, State<T>, and focus management fit together.
  • Styling — the full Style.Builder surface and the Styles.* shortcut helpers.
  • Components — every component you can drop into a tree, organized by family.

Clone this wiki locally