介绍
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.
常见问题
Gui Helper 支持哪些 Minecraft 版本?
Gui Helper 支持 Minecraft Java 版 1.20.6,可用的加载器:Fabric。下载时注意选择和你游戏版本一致的文件。
Gui Helper 怎么安装?
先用 PCL2 或 HMCL 启动器安装对应版本的 Fabric,再把下载的 .jar 文件放进游戏目录的 mods 文件夹,重新启动游戏即可。开启了版本隔离的,mods 文件夹在 versions/版本名 下面。
Hdi 的其他作品
查看全部 →
Custom Player Data
适用于Minecraft服务器的实用模组,也可作为模组开发者的框架。
Custom Item Data
一个对 Minecraft 服务器或模组开发者框架有用的模组,可轻松在物品上存储数据。
Star Wars Universe
Star Wars Roleplay Modpack for solo or Oldrilion Star Wars RP server
Star Wars Original Trilogy
Enter in the Star Wars original trilogy universe
评论
登录后评论和评分