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

  1. Build with Bedrock export (Build & Deploy, or MCP build with bedrock: true) and apply the build (/draxgui applyedit <id>).
  2. Copy draxgui_<pack>_bedrock.mcpack from plugins/DraxGUI/builds/<build id>/ (or the editor's download) into Geyser's packs folder (§5) and restart Geyser. DraxGUI never copies packs.
  3. 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 status shows the same line.
  4. 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.
  1. 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. and Bedrock form bridge active (Floodgate <version>) ....
  2. 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.
  3. Mark each project whose buttons should show pictures on Bedrock with targets.bedrock: true in 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 reports bedrock_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 / tab change events 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 reason player.
  • 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 close and 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_version 2, one resources module, 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 use textures/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

  1. Download draxgui_<pack>_bedrock.mcpack from the build.

  2. 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 jar

    Replace an older DraxGUI .mcpack of the same pack name (same UUID) instead of adding a second copy.

  3. Run /geyser reload on the server (or proxy) that runs Geyser.

  4. 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.

  5. 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 reload was 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:

  1. Note the versions: Paper build, DraxGUI version, Geyser and Floodgate builds, Bedrock client version, device/OS and input mode for every run.
  2. 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.
  3. 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. Press Entry 3: chime plays, the form reopens with Clicks: 1 and Selected: Entry 3. Press Settings: 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 Action x and submit: the form does not reopen.
  4. Stale replies: open the form, run /draxgui applyedit of 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.
  5. 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.
  6. Mobile (touch) and controller: repeat steps 3–5 on Android or iOS and with a gamepad. Check button pictures, slider usability and text entry.
  7. Take screenshots or videos of what you see, so a problem can be reported together with the versions from step 1.