CurseForge · Minecraft mod
Gui Helper
Useful framework for mod developpers
Quick answer
Which Gui Helper release matches Fabric?
Gui Helper gui-helper-1.14.0.jar targets 1.20.6 with Fabric. The project page does not say whether this file belongs on the client, dedicated server, or both. No extra mods listed for this file.
Where it goes
Is Gui Helper required on the client, server, or both?
The project page does not say whether this file belongs on the client, dedicated server, or both.
The source does not explicitly classify this release as client-only or server-only.
What else does Gui Helper gui-helper-1.14.0.jar need?
gui-helper-1.14.0.jar on Fabric. Every mod below is checked against that same setup.
This file does not list any required mods. Do not add a library just because a different file uses it.
This file does not list any required or optional mods.
Before you install it
Add Gui Helper without breaking your instance.
Built for Gui Helper gui-helper-1.14.0.jar on Fabric. Pick another file and the loader, install side or required mods may change.
- 01
Stick to this file
Use gui-helper-1.14.0.jar. It targets 1.20.6 with Fabric; another release may have different loader, side or dependency requirements.
- 02
Bring the mods it needs
This file does not list any required mods. Do not add a library just because a different file uses it.
- 03
Put it on the correct side
The project page does not say whether this file belongs on the client, dedicated server, or both.
- 04
Pick the file you checked
Use the “Get this file” button beside gui-helper-1.14.0.jar. It opens that exact file at the source.
About this project
What does Gui Helper add?
Gui Helper
A Fabric 1.20.6 framework for building Minecraft GUIs from a single Gui object that holds every object and its data.
You describe a screen once, register it under an Identifier, and the server opens it by that id. Values come back the same way.
Quick start
// client — build and register
Gui shop = GuiRegistry.register(GuiHelper.id("shop"), new Gui()
.setTitle(Text.literal("Shop"))
.setBackground(new Texture(GuiHelper.id("textures/gui/shop.png"), 0, 0, 176, 166, 256, 256))
.setDarkBackground(true));
shop.addObject(new TextObject("price", new TextWithDetail(Text.literal("0"), ColorHelper.WHITE, 0.5f),
8, 20, 60, 10, Align.CENTER));
// server — open it
GuiNetwork.open(player, GuiHelper.id("shop"), new GuiData().set("price", 2000));
Every object takes a String id first. That id is the key for lookup, for server-sent data, and for values sent back — so it must be unique within a Gui (addObject throws otherwise).
Objects
All extend GuiObject. Coordinates are relative to the GUI's top-left corner.
| Object | Purpose | Value type |
|---|---|---|
TextObject |
Text, with Align / VerticalAlign inside a box |
— |
TextureObject |
A texture | — |
ItemRenderObject |
An ItemStack with count, optional vanilla item tooltip |
— |
ModelItemRenderObject |
An item's 3D model, spinning, with a fixed tilt | — |
EntityGuiObject |
A live entity, scaled to fit, optionally cursor-tracking | — |
ButtonObject |
Clickable, Runnable onPress |
— |
ToggleObject |
On/off, two textures | boolean |
RadioButtonObject |
One group, exclusive options | String |
StepperObject |
Arrows and ticks to pick a step | int |
DropdownObject |
Vector-drawn expanding list, wheel or draggable indicator, optional search | String |
TextFieldObject |
Text input | String |
IntegerFieldObject / DecimalFieldObject |
Validated numeric input, optional setRange(min, max) |
String (getIntValue() / getNumber()) |
PercentFieldObject |
Decimal 0–100, drawn as 65 % |
String (getNumber()) |
TextAreaObject |
Multi-line text input | String |
BoxObject |
Container, clips and scrolls its children | — |
ScrollBarObject |
Bar owned by a BoxObject |
— |
SlotGridObject |
Client proxy placing a server slot grid inside a BoxObject |
— |
Shared by every object
object.setLabel(new TextWithDetail(Text.literal("Name"), 0.5f)); // drawn above, left-aligned
object.setTooltip(Text.literal("Line one"), Text.literal("Line two"));
object.setShowWhen(toggle::getValue); // re-evaluated every frame
object.setDisabledWhen(() -> !toggle.getValue()); // 50% opacity, input blocked
setShowWhen / setDisabledWhen return GuiObject, so call them last in a chain.
Dropdown search
dropdown.setSearchable(true).setSearchPlaceholder(Text.literal("Search..."));
A search row filters options by label (case-insensitive contains); Enter picks the first match. Cleared on close.
Reading values
gui.getObject("sound", ToggleObject.class).getValue();
gui.collectValues(); // GuiData of every stateful object, boxes included
getObject recurses into boxes.
State
Values live on the object, not the widget, which decides when they reset:
| Event | Result |
|---|---|
| Window resize | Preserved — widgets rebuild and re-read the object |
| Reopening the GUI | Reset to defaults |
A Gui is a singleton once registered, so resetState() runs from the GuiRenderer constructor — one per screen instance, not per init(). Set your own baseline with setDefaultValue(...).
Data flow
GuiData is a String -> String map with typed accessors, used in both directions.
// server -> client, on open
GuiNetwork.open(player, id, new GuiData().set("price", 2000).set("sound", true));
// client -> server, on demand
ClientPlayNetworking.send(new GuiValuesPayload(id, gui.collectValues()));
An object picks up the entry matching its own id via applyData, and writes it back via collectData. ItemRenderObject and ModelItemRenderObject also read <id>.count.
Defaults are applied first, then server data — so an id absent from the payload leaves the default alone.
Receiving values
GuiValuesRegistry.register(GuiHelper.id("shop"), (player, values) -> {
// runs on the server thread
});
The receiver rejects a payload unless the player has that GUI open (GuiSessions) and a listener is registered. The wire format is capped at 64 entries, 64-char keys, 256-char values.
GuiData is untrusted. The server cannot validate ids or types — Gui is client-only — so re-check everything against server state.
Handler GUIs (inventories)
Slots are the sync protocol: index, order and count must match on both sides. So the layout is common (src/main) and the look is client (src/client), keyed by the same Identifier.
// common — onInitialize, both sides
GuiHandlerRegistry.register(GuiHelper.id("forge"), new GuiHandler()
.setTitle(Text.literal("Forge"))
.addSlotGrid("input", 0, 8, 18, 3, 3) // idPrefix, startIndex, x, y, columns, rows
.addSlot(new SlotObject("output", 9, 120, 35))
.setPlayerInventory(8, 84));
// client — a Gui under the same id
GuiRegistry.register(GuiHelper.id("forge"), buildForgeGui());
// server
GuiNetwork.openHandler(player, GuiHelper.id("forge"), data, inventory);
getInventorySize() is derived from the highest slot index, so size is never declared twice. To decorate slots, read their positions back rather than repeating them:
for (SlotObject slot : GuiHandlerRegistry.get(id).getSlots()) {
gui.addObject(new TextureObject(slot.getId(), Textures.TEXTURE_SLOT,
slot.getObjectStartX() - 1, slot.getObjectStartY() - 1));
}
Slots inside a box
// common: the grid's coordinates only define its shape
new GuiHandler().addSlotGrid("storage", 9, 0, 0, 3, 6);
// client: id = the grid prefix
box.addObject(new SlotGridObject("storage", GuiHelper.id("forge"), 0, 0));
The server keeps the slots and the sync; the client places them. Scrolling is smooth — partly visible slots are clipped and only their visible part takes hover and clicks (HandledScreenMixin + an access widener making Slot.x/y mutable). box.setScrollSnap(18) scrolls row by row instead.
One ExtendedScreenHandlerType<CustomScreenHandler, GuiOpenData> carries the id and data in the vanilla open packet, so handlers can be registered at any time.
Textures
new Texture(id, drawStartX, drawStartY, drawSizeX, drawSizeY, textureSizeX, textureSizeY)
drawStart + drawSize select a region of a sheet; textureSize is the file's dimensions. The region stretches to whatever size the object declares.
Nine-slice keeps corners crisp at any size — it works on sub-regions, unlike vanilla's GUI sprite atlas:
new Texture(...).setNineSlice(3); // all sides
new Texture(...).setNineSlice(6, 3, 6, 3); // left, top, right, bottom
Scaling
gui.setSizeMultiplicator(2) renders everything twice as big. Mouse coordinates are divided to match, and slot hit-testing follows. Tooltips stay at normal size at the real cursor.
Overlays
A DropdownObject's open list floats above everything and takes input first — clicks, wheel and ESC — so a widget underneath can't steal a click or show its tooltip. Implement OverlayRenderer for anything else that needs to escape draw order and clipping; BoxWidget forwards all five members with its scroll offset, so overlays work inside boxes.
Debug
GuiHelper.DEBUG follows FabricLoader.isDevelopmentEnvironment(), so these exist under runClient and not in a built jar:
| Command | Opens |
|---|---|
/testGui [id] |
a registered Gui as a plain screen (default debug) |
/testHandler [id] |
a registered GuiHandler (default debug_handler, tab-completes) |
Known limits
- A registered
Guiis a shared instance — one screen at a time on the client, which is fine, but it is not re-entrant. SlotObject.backgroundSpritegoes throughGuiSlot, so the identifier must be a sprite stitched into the block atlas, not a loosetextures/gui/*.png.- Shift-click can insert into slots scrolled out of a box;
setDisabledWhenon aSlotGridObjectonly dims it — lock slots server-side. SlotGridObjectonly works in a handler GUI, and only claims slots named<id>_<digits>.- The dropdown search text uses the first labelled option's style and needs rows at least 9px tall.
GuiObjectstill carriestexture/text/onPressfields that most subclasses leave null.
Project description from CurseForge.
Pick your setup
Gui Helper by Minecraft version and loader
Choose the version and loader you play, then open the matching release.
Check the dependencies, then try the file in a copied instance before changing a world you care about.
Recent files
Gui Helper versions and loaders
gui-helper-1.14.0.jar
15 Nov 2026
gui-helper-1.12.0.jar
25 Oct 2026
Looking for an older file? The official CurseForge project page is in Resources.