Skip to content

Prefab children

ScreenChild and LabelLine are the JSON-authorable children of a prefab’s Screen and Label elements. They’re flat records — every variant uses the same shape and a kind field picks which fields matter at render time — kept that way so the JSON stays lightweight and agent-readable, and so a prefab editor can add a new row without changing the codec layout.

  • You’re authoring a prefab that includes an in-world panel (lobby info screen, leaderboard).
  • You’re authoring a multi-row floating label (hub hologram, podium sign).
  • You’re writing a tool that emits prefab JSON and needs the child schemas.
package me.zlex.conduit.prefab;
public record ScreenChild(Kind kind, Region region, String text, String buttonId) {
public enum Kind { TITLE, BODY, CAPTION, BUTTON, PANEL, DIVIDER }
public static final Codec<Kind> KIND_CODEC;
public static final Codec<ScreenChild> CODEC;
}
public record LabelLine(String text, WorldLabel.RowKind kind, int argbColor) {
public static final MapCodec<LabelLine> MAP_CODEC;
public static final Codec<LabelLine> CODEC;
}

ScreenChild.Kind maps to widget kinds at render time: TITLE/BODY/CAPTION → LabelWidget, BUTTON → ActionWidget(PRIMARY), PANEL → PanelWidget, DIVIDER → DividerWidget.

A label and screen authored inside a prefab JSON:

{
"elements": [
{
"type": "label",
"anchor": "header",
"yaw": 0,
"argbColor": 4294967295,
"lines": [
{ "text": "SPRINT RACE", "kind": "header", "color": 4294943232 },
{ "text": "Solo", "kind": "subheader", "color": 4286611584 },
{ "text": "Run to win.", "kind": "text", "color": 4291611852 }
]
},
{
"type": "screen",
"anchor": "panel",
"yaw": 90,
"width": 4.5, "height": 4.0,
"children": [
{ "kind": "panel", "region": { "x": 0, "y": 0, "w": 1, "h": 1 } },
{ "kind": "title", "region": { "x": 0.05, "y": 0.04, "w": 0.9, "h": 0.1 }, "text": "Lobby" },
{ "kind": "divider", "region": { "x": 0.05, "y": 0.16, "w": 0.9, "h": 0.01 } },
{ "kind": "body", "region": { "x": 0.06, "y": 0.20, "w": 0.88, "h": 0.04 }, "text": "Walk in to ready up" },
{ "kind": "button", "region": { "x": 0.32, "y": 0.84, "w": 0.36, "h": 0.10 }, "text": "START", "button": "start" }
]
}
]
}
  • For ScreenChild, text is the visible string for label-like kinds and the button label for BUTTON. buttonId is the click handler key — only meaningful for BUTTON.
  • LabelLine.color is an ARGB integer. The MapCodec keeps each line compact; the prefab editor can edit one row at a time without rewriting the whole element.
  • Both record types are deliberately flat — adding a new variant means a new Kind value, not a new sealed class.