Java-to-Bedrock Conversion
ResourcePackManager can convert the merged Java resource pack into a Bedrock resource pack so GeyserMC clients see the same custom content as Java clients. This is on by default.
What Gets Converted
The converter is no longer FreeMinecraftModels-only. It runs two pipelines back-to-back over the merged Java pack:
- FreeMinecraftModels bone scanner — picks up FMM bone models under
assets/freeminecraftmodels/models/and converts each bone into a Bedrock attachable. - Generic items-definition pipeline — walks every
assets/<namespace>/items/*.jsonfile in the 1.21.4+ format (skipping theminecraftandfreeminecraftmodelsnamespaces). For each leaf model it either:- emits a flat Bedrock inventory icon (for plain
minecraft:item/generatedand similar flat-builtin parents), or - emits Bedrock geometry, an attachable, an animation file, and a software-rendered 2D inventory icon (for true 3D models).
- emits a flat Bedrock inventory icon (for plain
A unique Bedrock identifier is generated per (model × base item) pair, so e.g. a single sword model registered against multiple base items doesn't collide on the Geyser side.
Custom armor sets are detected when a sibling assets/<namespace>/equipment/<material>.json exists. The converter wires an armor attachable that combines the vanilla armor geometry with the Java texture as the visible layer, so Bedrock players see the right armor texture when wearing the item.
The Bedrock pack's manifest UUID is derived deterministically from the pack name, so it stays stable across rebuilds; only the version triplet is bumped per build (cache-bust token derived from build time).
Per-Session Live Serving
When Geyser-Spigot is detected, ResourcePackManager registers a SessionLoadResourcePacksEvent subscriber. Every Bedrock player who joins after a fresh mix gets the latest Bedrock pack served straight from disk, no server restart required for texture or model edits.
Geyser's custom-item mappings (the JSON in custom_mappings/) are still boot-frozen, so adding new custom items or removing existing ones requires a server restart before Bedrock clients see those changes. RSPM pre-deploys the previous run's mapping file early in startup so Geyser's boot-time custom-items registration picks it up automatically.
Currently connected Bedrock players keep whatever pack they received at their own join time — that's a Bedrock protocol constraint, not something the plugin can override mid-session.
Output Files
After a successful mix, the Bedrock files live in:
plugins/ResourcePackManager/output/ResourcePackManager_Bedrock.zip
plugins/ResourcePackManager/output/rspm_geyser_mappings.json
If auto-deploy is on and Geyser was detected, the mappings file is also copied to:
<geyser-folder>/custom_mappings/rspm_geyser_mappings.json
The Bedrock pack zip is not copied into <geyser-folder>/packs/ — it's served live per-session instead. RSPM also removes any legacy copy that older plugin versions left in that folder so Geyser doesn't end up serving the pack twice (duplicate UUIDs would confuse the Bedrock client).
config.yml Settings
# Toggles Java-to-Bedrock conversion altogether.
bedrockConversionEnabled: true
# Copies the Geyser custom mappings file into the detected Geyser folder's
# custom_mappings/ directory on each mix.
bedrockAutoDeployToGeyser: true
# Manual override for the Geyser data folder. Empty = auto-detect.
# Can be absolute or relative to the plugins/ directory.
bedrockGeyserFolder: ""
Auto-detection looks at, in order:
bedrockGeyserFolderif set (treated as absolute path first, then as a path relative toplugins/).plugins/Geyser-Spigot/plugins/Geyser-*/(any variant)config/Geyser-*/(for Fabric/NeoForge setups)
Tuning Held-Item Display: bedrock_display_offsets.yml
Bedrock renders the held item through a parent bone whose rest pose differs from Java's first-person/third-person transforms, so the algorithmic conversion has to apply a base offset on top of whatever the Java model's display transform specifies. The default offsets work for typical right-handed Java models, but odd cases can need tuning.
First-person and third-person are two completely separate Bedrock render passes (different parent bones, different rest poses), so each gets its own independent set of six knobs. Tuning one does not affect the other.
# ===== First-person (right hand, seen by the holder) =====
firstPersonBaseRotationX: -90.0 # pitch (tipping toward/away from camera). Default cancels parent rotation.
firstPersonBaseRotationY: 0.0 # yaw (spinning around vertical line)
firstPersonBaseRotationZ: 0.0 # roll (around camera-forward axis)
firstPersonBasePositionX: 0.0 # vertical on screen (positive = up)
firstPersonBasePositionY: 12.5 # depth (positive = further into the scene)
firstPersonBasePositionZ: 0.0 # horizontal on screen (positive = right)
# ===== Third-person (right hand, seen by other players / F5) =====
thirdPersonBaseRotationX: 90.0 # pitch as observers see it
thirdPersonBaseRotationY: 0.0 # yaw
thirdPersonBaseRotationZ: 0.0 # roll around the item's long axis
thirdPersonBasePositionX: 0.0 # horizontal across the holder's body (positive = outward)
thirdPersonBasePositionY: 12.5 # vertical (positive = raises the model)
thirdPersonBasePositionZ: 0.0 # depth relative to holder (positive = forward)
Position values are in pixels, where 1 pixel = 1/16 of a block. Rotations are in degrees.
The Bedrock client live-reloads attachable JSON without a relaunch. If a Bedrock test client is logged in, change the value, run /rspm reload, and the next Bedrock-join (or in some cases the same connected player after a small in-world action that re-binds the attachable) shows the new offset. Iterate until it looks right.
Limitations and Known Behaviour
- 3D inventory icons are software-rendered from the Java model's
display.guitransform. The render is reasonable but not pixel-perfect; if the icon looks wrong, the most common cause is a missing/misnamed texture file referenced by the model. - Flipbook textures used as item icons are cropped to frame 0 — Bedrock's
item_texture.jsondoesn't support animated icons, only animated block/terrain textures viaflipbook_textures.json. - Attachable geometry format version is fixed at
1.21.0(was1.16.0in older plugin versions); update Geyser if your installation can't parse it. - Vanilla item models (
shield.json,crossbow.json) are not recursively merged across packs to avoid cross-pack predicate-tree corruption; the highest-priority pack's copy wins for those two specifically. - If the converter cannot resolve a referenced texture or model file, that leaf is skipped and a
[BedrockConverter]warning is logged; the rest of the pipeline continues.