Geyser Extension & Custom Bedrock Entities
Converting the resource pack gets Bedrock players the right textures and models for items. Getting them true custom entities — a modeled boss that renders and animates instead of appearing as an armor stand — needs code running inside Geyser itself. That's what the RSPM Geyser extension does.
You do not download it separately. The same ResourcePackManager.jar you install as a plugin is the extension.
One Jar, Three Roles
ResourcePackManager.jar is simultaneously:
- the Bukkit/Paper backend plugin,
- the Velocity and BungeeCord/Waterfall proxy plugin,
- and a Geyser extension.
Whichever loader opens it picks the entry point that matches. Older releases shipped a separate ResourcePackManager-GeyserBridge.jar; that file is retired and RSPM cleans up leftovers automatically.
How It Gets Installed
RSPM installs the extension for you in the cases where it can. What happens depends on where Geyser lives:
| Your setup | What RSPM does |
|---|---|
| Geyser-Spigot on the same server | Copies the running jar into plugins/Geyser-Spigot/extensions/ResourcePackManager.jar. If a different version is already there, it stages the new one through Geyser's own update queue at extensions/update/ instead. Either way you get a console line asking you to restart once. |
| Geyser on the proxy (Geyser-Velocity / Geyser-BungeeCord) | The proxy role does the same thing into the proxy's Geyser-*/extensions/ folder. |
| Floodgate local, Geyser external (Geyser runs in a separate process) | RSPM cannot reach that process. It exports a copy to plugins/ResourcePackManager/geyser-extension/ and warns you to copy that exact jar into the external Geyser's extensions/ folder and restart Geyser. |
| Neither Geyser nor Floodgate present | Nothing to do — RSPM logs an informational line and skips installation. |
A newer version already sitting in extensions/ is never overwritten by an older one.
Installation always requires one restart. Geyser loads extensions at startup, so a freshly copied or staged jar does nothing until the server or proxy restarts.
Turning Auto-Install Off
Each role has its own switch, and they are independent:
| Where | Setting | Default |
|---|---|---|
Backend plugins/ResourcePackManager/config.yml | geyserExtensionAutoInstall | true |
Proxy config.yml | geyser-extension-auto-install | true |
Setting either to false stops that role from installing the extension or staging an update for it, and it logs a line saying so. Read the semantics carefully:
- It prevents future installation and update staging.
- It does not remove an extension jar that is already in
extensions/. Geyser has that file open. To actually disable the bridge, set the flag tofalse, stop Geyser, delete the RSPM jar fromextensions/by hand, and start it again. - Turning it off has no effect on pack conversion or pack delivery. Items, textures and models still convert and serve; only custom Bedrock entities stop working.
Disabling it on the backend also skips staging a downloaded RSPM update into a local Geyser-Spigot's update queue, so the extension and plugin can drift apart in version — which is the state the compatibility guard below exists to catch.
What the Extension Actually Does
- Registers RSPM's custom Bedrock entity definitions with Geyser at startup, reading the entity identifiers out of the generated Bedrock pack.
- Swaps the Bedrock definition of spawning entities, so a modeled entity spawns as its custom Bedrock entity rather than the vanilla fallback.
- Applies live entity data and property overrides while the entity exists.
- Primes Geyser's recipe network IDs early, which avoids a class of colliding-recipe-ID problems on Geyser 2.11.
The Bedrock-side assets those definitions refer to come from the entity bundles described in Bedrock conversion — a plugin ships native Bedrock entity files under assets/<namespace>/rspm_bedrock_pack/ and RSPM carries them into the generated pack.
Geyser Version Requirements
The extension targets Geyser 2.11+.
Its descriptor deliberately declares a lower Geyser API level (2.9.0), so an older Geyser will happily load it rather than refusing the jar outright. The real requirement is enforced at runtime: the extension probes for the classes it needs and disables itself when they're absent, which produces a clear message instead of a load-time rejection an operator can't interpret.
It is designed to fail closed on class/linkage incompatibility instead of taking Geyser down with it. The extension shell references only long-standing Geyser API types; version-sensitive classes are probed before the core starts. If your Geyser build doesn't ship a class the bridge needs, the bridge disables itself and says so:
Disabled the RSPM custom Bedrock entity bridge: this Geyser build does not ship
<class>. Geyser itself is unaffected, but custom Bedrock entities will not appear until a ResourcePackManager update matches this Geyser version.
Items, textures and models still convert and serve normally in that state — only custom entities are affected. The fix is to update Geyser, or wait for the RSPM release that matches your Geyser build.
Earlier RSPM versions achieved the same result by swapping a vendored copy of one of Geyser's internal packet translators into Geyser's registry. That translator replacement is gone: the extension now uses Geyser 2.11's public entity lifecycle/events for registration and spawn-definition replacement. The core still probes a limited set of Geyser internals used to build definition instances and receive downstream plugin messages, which is why the compatibility guard and exact RSPM/Geyser version matching still matter.
Ordering: Why a Restart Is Sometimes Needed
Geyser registers entity definitions during its own startup window. If RSPM finishes generating the Bedrock pack after that window closed — which is exactly what happens on a brand-new install, where there is no pack yet at boot — the definitions arrive too late to enter Geyser's frozen registries. RSPM retains them for the next startup and warns you:
RSPM custom Bedrock entity definitions became available after Geyser closed its startup registration windows ... restart the proxy once to activate the newly generated custom models.
Restart the server or proxy process that hosts Geyser once after the first successful pack generation. Reconnecting alone cannot activate definitions that missed the startup window. The ordering is correct on subsequent boots because the pack already exists when Geyser opens its registration windows.
Verifying It's Working
- Check the target
extensions/folder actually containsResourcePackManager.jar. - On boot, Geyser should list the extension as loaded, and RSPM logs how many custom Bedrock entity definitions it registered.
- Join on Bedrock and look at a modeled entity. Armor stands instead of models means either the extension isn't loaded, the pack didn't reach the client, or the definitions arrived late — check the warnings above in that order.
Troubleshooting
"Extension loaded, but entities are still armor stands." The pack and the extension are separate halves. Confirm the Bedrock pack itself reached the client first (see Bedrock conversion); without the pack's entity assets there is nothing for the definitions to render.
"It worked, then I updated Geyser and entities broke." Look for the self-disable message above. A Geyser update can move the API surface the bridge probes for.
"Nothing was ever installed into extensions/." Check the console for Automatic Geyser extension installation is disabled by geyserExtensionAutoInstall (backend) or ... by geyser-extension-auto-install (proxy). Someone turned the switch off. If Geyser and Floodgate are both absent locally, you'll instead see Geyser-Spigot and Floodgate were not detected locally; skipping automatic Geyser extension installation — that's RSPM correctly deciding there is nothing to install into.
"I updated RSPM but the extension is still the old version." The extension is only replaced at restart, and if RSPM staged it through Geyser's update queue it needs one restart to be swapped in. Keep the plugin jar and the extension jar on the same version — they're the same file, so re-copying the plugin is enough.
On Velocity, Geyser's automatic extension subscription doesn't fire the way it does on other platforms, so the proxy plugin relays the lifecycle events itself. This is handled internally and needs no configuration.
Where to Go Next
- Bedrock / Geyser conversion — what gets converted and how the pack is served
- Proxy networks — Geyser on a proxy
- Troubleshooting