DraxGUI for Bedrock players (Geyser + Floodgate)
Updated 28 October 2026
Bedrock players who join through Geyser cannot use DraxGUI's Java renderer: Java resource packs, core shaders and the mouse-pointer capture do not carry across Geyser. DraxGUI shows them the same screens in one of two ways:
- Custom Bedrock screens (recommended): the build's Bedrock resource pack (
.mcpack) redraws each screen with the Java design: the same pictures, colours and positions, hover and pressed looks, tabs, scrolling lists, toggles and bars. See Custom Bedrock screens. - Plain forms (fallback, no pack needed): native Bedrock forms with the screen's texts, buttons and controls (§2).
HUDs and popups are drawn by the same pack (Bedrock HUDs and popups); without it Bedrock players get no DraxGUI HUD.
Verification status (read first). All of this was run on Minecraft Bedrock 26.52 for Windows with mouse and keyboard through Geyser 2.12.0 + Floodgate 2.2.5 on Paper 26.3. Phones, touch and controllers have not been tested; check them on your own devices before promising them to players (§8).
Custom Bedrock screens
A build with Bedrock export writes every screen of every project with targets.bedrock: true into
the .mcpack as a Bedrock UI layout (JSON-UI). The pack replaces one part of Bedrock's server-form
screen (server_form.main_screen_content) with a router: a form that DraxGUI sends for a screen
with a layout is drawn as that layout; every other form, including other plugins' forms, keeps
Bedrock's normal look. Nothing changes in how forms travel: Floodgate still carries an ordinary
form and DraxGUI still checks every reply on the server.
Turning it on
- Build with Bedrock export (Build & Deploy, or MCP
buildwithbedrock: true) and apply the build (/draxgui applyedit <id>). - Copy
draxgui_<pack>_bedrock.mcpackfromplugins/DraxGUI/builds/<build id>/(or the editor's download) into Geyser's packs folder (§5) and restart Geyser. DraxGUI never copies packs. - DraxGUI logs
Bedrock screens: custom screens for N screen(s) (... found in Geyser-Spigot/packs)once Geyser's folder holds exactly that build's.mcpack; until then it sends plain forms and the log line says what is missing./draxgui statusshows the same line. - Players reconnect to download the new pack. Keep Geyser's
force-resource-packs: true(its default): a player who declines the pack sees Bedrock's plain button list with every text as a button.
bedrock.layouts in config.yml: auto (default, the check above), on (always send custom
screens: use it when Geyser runs on a proxy, where DraxGUI cannot see its packs folder, and keep the
proxy's pack current yourself), off (always plain forms).
What players get
| Screen content | Custom Bedrock screen |
|---|---|
| Shapes, images, icons, backgrounds of groups and texts | The Java pack's pictures at the same size and place (2 texture pixels per GUI pixel, bedrockOptions.layoutScale) |
| Text | Bedrock text in the Minecraft font with the element's colour, alignment, wrapping, bold/italic and shadow; templates and bindings show their current value |
| Anything with a click handler | A button with the element's normal, hover and pressed looks (hover with a mouse; touch and controllers press directly) |
| Tab view | The tab bar with the active tab drawn active; each page shows only its own content |
| Scroll list | A scrolling area (mouse wheel, drag, touch) with Bedrock's scroll bar |
| Toggle / checkbox | Switches in place on click |
| Slider, input box | Drawn like Java; a click opens a small native editor (slider or text field) that returns to the screen on Submit or close |
| Progress bar | Filled to the current value (one step per GUI pixel, up to 64 steps) |
| Animated pictures | Play on the client at the picture's average frame rate |
visibleWhen, show/hide, enabledWhen |
Hidden elements are not drawn; disabled controls are greyed and do nothing |
| Pulse / bob effects | Played on the client |
Checked on a Bedrock client (Windows, mouse): pictures, texts, buttons with hover looks, clicks, tabs, wheel scrolling, toggles, the slider and text editors, bars, wrapped text, animated pictures and closing. Not yet checked on a client: pulse/bob, disabled controls, drag/touch scrolling and anything on phones or controllers.
Limits: a screen is a snapshot like any form: it refreshes after every choice and, with
reopenOnValueChange, when values change. Imported fonts are drawn in the Minecraft font; tooltips,
hover enter/leave events, right-click and scroll events do not exist on Bedrock; open animations are
not played (every refresh reopens the screen); rotated texts are drawn unrotated. After each refresh
the first button shows Bedrock's keyboard/controller focus highlight, as in Bedrock's own forms.
Screens with more than 256 form entries (buttons plus texts) keep plain forms. Layouts use the Java
canvas size in Bedrock UI pixels; very small phone screens are untested. Another resource pack that
also replaces server_form.main_screen_content conflicts with DraxGUI's: only the top pack's version
is used.
Bedrock HUDs and popups
The same .mcpack also draws every HUD and popup of every project with targets.bedrock: true:
pictures, shapes, bars and texts at their anchors, popups stacked like on Java, and the HUD chosen by
your HUD rules (including per-player overrides). Turning it on is the same as for custom screens:
build with Bedrock, apply, put the .mcpack in Geyser's packs folder; the console line then says
custom screens for N screen(s) and HUDs/popups.
How it reaches the player (nothing to configure): an invisible title made only of formatting codes tells the pack which HUDs and popups are active and what state their elements are in, and every text that can change travels as a boss bar that the pack hides from the boss list and draws where the text belongs. Texts that never change are written into the pack. Other plugins' titles and subtitles still show: DraxGUI sends them again with its state appended. Other plugins' boss bars still show in the boss list.
Limits: at most 32 changing texts per player at a time (more stay hidden until others go) and at most 4 visible copies of one popup (stack positions). Popup enter/exit animations are not played. Imported fonts are drawn in the Minecraft font. HUD texts and bars update on the server tick after a value changes (and are re-checked every half second), not every client frame. Pulse/bob effects on HUDs are generated like on screens but were not checked on a client. A plugin that sends titles many times per second makes DraxGUI re-send its state just as often.
1. Requirements and setup
| Component | Where | Notes |
|---|---|---|
| Paper server with DraxGUI | backend | Same server that runs DraxGUI. |
| Floodgate | the backend Paper server (and the proxy, when Geyser runs on a proxy) | DraxGUI detects Bedrock players only through the Floodgate API (FloodgateApi.isFloodgatePlayer), never by name prefix. Compiled against Floodgate API 2.2.5 / Cumulus 1.1.2. |
| Geyser | same server (Geyser-Spigot) or a proxy (Geyser-Velocity, Geyser-BungeeCord, standalone) |
Translates the Bedrock connection. Floodgate's key.pem must match on all servers in proxy setups. |
- Install Geyser and Floodgate following GeyserMC's own instructions. When Floodgate runs on
the Paper server, DraxGUI logs at startup:
Floodgate detected: Bedrock players use the Bedrock profile.andBedrock form bridge active (Floodgate <version>) .... - Geyser without Floodgate on the Paper server: DraxGUI cannot tell Bedrock players apart and treats everyone as a Java player (logged as a warning). Bedrock players then cannot use DraxGUI screens. Install Floodgate on the backend.
- Mark each project whose buttons should show pictures on Bedrock with
targets.bedrock: truein the project document (the bundled Control Panel template already has it; the editor has no toggle for this flag yet). Only those projects get pictures in the.mcpack, and only their forms reference pack pictures. Every screen of every project still opens as a form for Bedrock players; projects without the flag simply have buttons without pictures (the build reportsbedrock_project_not_targeted).
DraxGUI never changes Geyser's configuration or pack routing and never sends packs itself.
2. How a screen becomes a form
Bedrock offers two useful form types: a simple form (text + a list of buttons, each with an optional picture) and a custom form (labels, toggles, sliders, text fields and dropdowns with one Submit button). Forms cannot position, layer, clip, animate or rotate anything; DraxGUI keeps the content and the controls and drops or approximates the rest, with a diagnostic for each.
Reading order. Elements are visited depth-first (a group before its children). Siblings are ordered top-to-bottom, then left-to-right, by the top-left corner of their layout box (whole GUI pixels); ties keep the layer order. Scroll lists are flattened: every row appears, no clipping.
| Screen content | Bedrock form |
|---|---|
| Text | A content line (simple form) or a label (custom form). Minecraft font only; bold and italic are kept; underline and strikethrough are dropped; § codes from text or player values are removed. |
| Anything with a click handler (groups, images, icons, text, shapes) | A button. Label: bedrock.label, else the element's accessible label, else its first text, else its name. Picture: the element itself if it is a picture, else its first picture descendant, taken from the .mcpack. |
| Toggle / checkbox | Custom-form toggle. |
| Slider | Custom-form slider with the same min/max/step (a continuous slider uses 100 steps). |
| Input box | Custom-form text field with the placeholder; the length limit (maxLength, default 50, counted in Unicode code points) and character rules are enforced by the server. |
| Tab view | Simple form: the current page is shown as [Page] and the other pages become buttons. Custom form: a "Page" dropdown. Only the active page's content is shown. |
| Progress bar | A line such as Volume bar: 70%. |
| Pictures/shapes without a click handler | Not shown (forms can only put pictures on buttons). |
| Text right next to a control | Becomes the control's label if it has none, and is not repeated. |
Disabled controls/buttons (enabledWhen) |
Shown as text (Buy (unavailable), Frozen: on) because forms cannot grey out a control. |
Elements hidden by show/hide or visibleWhen |
Not shown, exactly like Java. |
If a screen has at least one enabled toggle/slider/input on the visible page, it becomes a
custom form and its buttons are collected into one Action dropdown at the end
(option - = no action). Otherwise it is a simple form.
Example (bundled Control Panel template): the Overview page becomes a simple form with the
buttons x, Settings, Help, Entry 1 … Entry 20, Show reward; the Settings page becomes a
custom form [Page dropdown, "Volume: 70", slider "UI sound volume", "Volume bar: 70%", toggle "Reward notifications", toggle "Compact mode", text field "Nickname", "Hello <name>!", Action].
Author controls (Inspector -> Bedrock)
| Field | Effect |
|---|---|
screen.bedrock.title |
Form title (default: screen name). |
screen.bedrock.reopenOnValueChange |
While the form is open, re-send it when shown values change (see §3). |
element.bedrock.hidden |
Leave this element (and its children) out of the Bedrock form. |
element.bedrock.label |
Text used on Bedrock instead of the element's label (e.g. turn a Java x close button into Close). |
3. Runtime behaviour
- Opening.
/draxgui open <project:screen> [player], screen commands and Open-screen nodes work the same for Bedrock players. The screen's When the menu opens handler runs, then the current values are snapshotted into the form. - Replies. A button, a toggle change, a slider change, a submitted text field or a page
change fire the same
click/change/submit/ tabchangeevents and the same node graphs as on Java, and two-way bindings write the variables. Order: value changes (form order), then the chosen action, then a page switch. Unchanged values fire nothing. After a reply the form is sent again with fresh values, so the menu "stays open" like on Java, unless a handler closed the menu or opened another screen. Closing the form (X / back) closes the menu and runs When the menu closes with reasonplayer. - Validation. Replies are checked against the exact form that was sent and applied all or nothing. Slider values must be in range and on a step, dropdown/button indexes must exist and value types must match; anything else is logged as a malformed reply. Text longer than the limit or containing control/formatting characters is refused with a message and the form is reopened with the player's entries kept. More than three invalid replies in a row close the menu. Before each event the element is re-checked (still visible, enabled, on the active page).
- Stale replies. Each form carries a ticket; a reply is used only if the player is online, it belongs to the current screen session and deployment generation, it answers the newest form and it has not been answered before. Replies after a close, a re-deploy, a refresh or a disconnect, and duplicated deliveries, are ignored (no double rewards). Replies arrive on Floodgate's network threads and are moved to the main server thread before anything runs.
- Reopen on value change. With
reopenOnValueChange, the open form's content is recomputed every 0.5 s. When it differs, the refresh waits for 0.5 s without further changes (at most 2 s while values keep changing) and at least 1.5 s after the previous send; then the form is closed (FloodgateApi.closeForm) and re-sent with the same pre-filled entries. Entries typed into an open custom form are lost by a refresh, so keep this off for screens with text fields. - Every X seconds handlers do not run for Bedrock players. Wait continues: delayed commands, messages and sounds still run; menu changes made later appear the next time the form is shown. Move / scale is refused (Java only) and open animations are not played.
- Teardown. Quit, death, world change, a new deployment (players are told to reopen),
menu.close//draxgui closeand plugin disable end the form session and cancel pending refreshes. - Hover events, right-click events and tooltips do not exist in forms; authored hover/press styles and transitions are Java-only (Bedrock uses its own button highlight, which also works for touch and controllers).
4. Exporting the .mcpack
In Build & Deploy enable Bedrock export (build option "bedrock": true). Optional
"bedrockOptions":
| Option | Default | Meaning |
|---|---|---|
imageSize |
64 | Edge of baked button pictures in px (16–256). An asset may override it with import.bedrockMaxSize. |
maxFrames |
120 | Frames kept per animated picture (assets: import.bedrockMaxFrames). |
maxSheetSide |
2048 | Longest side of an animation sheet (256–4096). |
maxSheetBytes |
8388608 | Decoded RGBA bytes of one sheet (mobile memory budget). |
maxPackBytes |
67108864 | Upper limit for the finished .mcpack; larger builds fail. |
version |
content hash | Pin [major, minor, patch] instead of the content-derived version. |
A successful build adds two artifacts next to the Java pack:
draxgui_<pack>_bedrock.mcpack— the Bedrock resource pack.draxgui_<pack>_bedrock_forms.json— the form-resource index: every baked picture (project:screen:element→ path, size, frozen-value marker, animation sheet layout) and a per-screen summary. Tools and a future custom Bedrock UI use it; the runtime itself derives the same paths from element ids.
Contents of the .mcpack:
manifest.json(format_version2, oneresourcesmodule,min_engine_version[1, 20, 0]).pack_icon.png(generated).textures/draxgui/<project>/<screen>/<element>.png— button pictures rendered with the same rasterizers as the Java pack (images, icons, shapes, QR codes), unrotated. Very long ids usetextures/draxgui/<project>/h/<hash>.png.- Player heads:
%player%heads cannot be baked per viewer, so they show a Steve-style placeholder generated locally (never downloaded); named heads also use it unless a skin was supplied to the build (reported as a warning). Player models are baked as the placeholder head. - QR codes with fixed content are baked; QR content with
${...}cannot be baked and the button has no picture (warning). - Animated pictures: forms show the first frame. A frame sheet
(
<element>_sheet.png) within the size/memory budget is exported for a custom Bedrock UI that does not exist yet; frames dropped to fit the budget are reported and their time is added to the kept frames.
Identity and version. The header and module UUIDs are UUID v5 values derived from the pack
name in a fixed DraxGUI namespace, so every rebuild of the same pack keeps its identity and
Geyser/clients replace it instead of keeping two copies. Bedrock caches packs by UUID +
version, so the version [1, a, b] is derived from a SHA-256 of the pack contents: new pictures
give a new version (clients download again), identical contents give identical bytes and the
same version. The ZIP is deterministic (sorted entries, fixed timestamps independent of the
time zone, fixed compression).
The build report section bedrock lists the artifact, SHA-256, UUIDs, version, picture and
sheet counts and limits, plus diagnostics for every screen checked in its authored state and on
every tab page (rotation, dropped pictures, placeholders, frame reductions, Java-only nodes).
5. Installing the pack on Geyser
-
Download
draxgui_<pack>_bedrock.mcpackfrom the build. -
Copy it into Geyser's packs folder for your platform:
Geyser platform Packs folder Paper/Spigot plugin ( Geyser-Spigot)plugins/Geyser-Spigot/packs/Velocity plugin plugins/Geyser-Velocity/packs/BungeeCord/Waterfall plugin plugins/Geyser-BungeeCord/packs/Standalone packs/next to the Geyser jarReplace an older DraxGUI
.mcpackof the same pack name (same UUID) instead of adding a second copy. -
Run
/geyser reloadon the server (or proxy) that runs Geyser. -
Bedrock players must disconnect and reconnect to receive the new pack. If players may decline packs (Geyser
force-resource-packs: false), forms still work but button pictures are missing. -
HUD changes need a full server restart. Keep restarting the server (not only
/geyser reload) after changes that affect HUDs, as recommended for this project. In the test runs/geyser reloadwas enough for the HUD pack to load, but it kicks every Bedrock player; a restart is the safe default. DraxGUI notices the new pack within 30 seconds either way.
/draxgui applyedit <id> activates new screens and logic for Bedrock players immediately; only
new or changed pictures need the pack steps above.
6. Bedrock behaviour table
Tested means seen on Bedrock 26.52 for Windows with mouse and keyboard; anything else says what was not tested.
| Feature | Required behaviour | What DraxGUI does | Status |
|---|---|---|---|
| Detection | Floodgate; without it Java + report | Floodgate API detector; bridge installs only with Floodgate; warning when Geyser runs without Floodgate | Tested with Floodgate (Bedrock 26.52 joined, screens opened as forms); the no-Floodgate fallback is server-side only |
| Text | Minecraft font; no underline/strikethrough | Form text: § stripped, bold/italic kept, underline/strikethrough dropped with a diagnostic |
Tested (bold title kept, underlined/struck text shown plain) |
| Live values | Snapshot on open; optional debounced reopen | Snapshot per send; reopenOnValueChange with bounded debounce + closeForm |
Tested (server-side change reopened the open form with the new value) |
| Heads, models, QR | Baked; %player% → Steve |
Baked in the .mcpack; local Steve placeholder; dynamic QR reported |
Tested (head as Steve and QR shown as button pictures from the .mcpack) |
| Rotation | Unrotated + warning | Pictures baked unrotated; warning in build and runtime diagnostics | Tested (rotated text shown unrotated; rotation_profile warning on import) |
| Hover/click | Appearance states; Java-only animations; usable touch | Custom screens: the element's own normal/hover/pressed pictures; plain forms: Bedrock's button highlight. No hover needed to use any control | Tested on custom screens with a mouse (row turns to its hover style); touch/controller not tested |
| Animated pictures | Image sheets with size/frame limits | Custom screens: client-side flip book; plain forms: frame 1 on the button | Tested (12-frame GIF plays on a custom screen; frame 1 on plain forms) |
| Wait | Delayed effects run; visuals next open | Shared interpreter; view state persists across re-sends | Tested (message after a 2 s Wait delivered; counter shown on the next open) |
| Every X seconds | Not run; explained | Never scheduled for Bedrock; diagnostic + node catalogue note | Tested (a 1 s timer did not run for the Bedrock player) |
| Move/scale, open animation | Java-only with diagnostics | Refused at runtime; diagnostics | Tested (Move refused and logged; slide_up not played) |
| Input box | Native text field; server-side length/character validation | Custom-form text field; code-point length and character checks | Tested on Windows (typed value stored; 57/50 characters rejected with a banner, value kept) |
.mcpack export |
Deterministic, deliberate UUID/version | Done (see §4) | Tested (loaded by Geyser and downloaded by the client) |
| Custom screens | Real Bedrock pack path | JSON-UI layouts in the .mcpack (see the section above) |
Tested on Windows (Control Panel: layout, hover, clicks, tabs, scroll, toggle, slider and input editors, close) |
| Bedrock HUDs/popups | Real Bedrock pack path | HUD layouts in the .mcpack: state title + hidden boss bars for texts (see the section above) |
Tested on Windows (Player HUD with boss bar and scoreboard, kill/quest/reward popups stacked, other plugins' titles kept) |
| Device/input profiles | Windows + mobile; mouse, touch, controller | Windows 11 with mouse and keyboard tested | Mobile, touch and controller not tested (no device) |
7. Known limitations
- Plain forms cannot reproduce DraxGUI layouts: no positioning, layering, clipping, pictures outside buttons, live updates while open, hover, tooltips or animation. Custom screens can (see their limits above); check the build report's Bedrock diagnostics for each screen.
- HUDs and popups need the
.mcpack(see above); without it DraxGUI sends Bedrock players no HUD at all (Java action-bar glyphs would show as boxes), so other plugins' action bars always reach Bedrock players unchanged. - Chat that arrives while a form is open is not flashed on screen afterwards; it is in the chat history (seen with delayed messages after a Wait).
- A refresh (
reopenOnValueChange) discards text typed into an open custom form. - Bedrock form sessions are not listed by the Java session views.
- Floodgate publishes its API only as snapshots; DraxGUI compiles against one pinned build (2026-09-17). A future Floodgate that changes the form API makes the bridge log a warning and stay disabled instead of failing.
8. Testing on a real Bedrock device
First run (2026-10-21): Minecraft Bedrock 26.52 (package 1.26.5203.0) on Windows 11, mouse and keyboard, through Geyser 2.12.0-b1267 and Floodgate 2.2.5-b141 on Paper 26.3-209 (loopback, no loopback exemption needed). Three defects were found and fixed in that run: Java HUD glyphs sent to Bedrock players, a bound slider that kept the player's last submitted value after the variable changed elsewhere, and a clickable text labelled with its id.
Custom screens (2026-10-21): same client and server; the generated Control Panel matched the Java design and every control worked with a mouse.
To test on your own devices, especially phones and controllers:
- Note the versions: Paper build, DraxGUI version, Geyser and Floodgate builds, Bedrock client version, device/OS and input mode for every run.
- Server: Paper + DraxGUI + Geyser-Spigot + Floodgate on a disposable test server. Check the
startup log for the bridge line. Create a project from the Control Panel template, enable
the Bedrock target, add one button with an icon child and one
%player%head button, build with Bedrock export,applyedit, install the.mcpack(§5),/geyser reload. - Windows (mouse + keyboard): join, accept the pack,
/draxgui open <project>:home. Expect a simple form with the buttons listed in §2; the icon/head buttons show their pictures. PressEntry 3: chime plays, the form reopens withClicks: 1andSelected: Entry 3. PressSettings: the custom form appears. Move the slider to 40 and submit:/draxgui var get <project>:volume <player>shows 40 and the form reopens with 40. Type 51 characters into Nickname and submit: the form reopens with the error line and the first 50 characters. Choose Actionxand submit: the form does not reopen. - Stale replies: open the form, run
/draxgui applyeditof a new build from the console, then submit: the player is told menus were updated and nothing is applied. Open, then disconnect while the form is open: no errors in the log. - Reopen on change: with
reopenOnValueChange, keep the Overview form open and run/draxgui var add <project>:clicks 1 <player>twice within a second: one refresh after about 0.5 s showing the new count. - Mobile (touch) and controller: repeat steps 3–5 on Android or iOS and with a gamepad. Check button pictures, slider usability and text entry.
- Take screenshots or videos of what you see, so a problem can be reported together with the versions from step 1.