Skip to main content

Geyser Extension & Custom Bedrock Entities

Pack conversion supplies supported item textures and models. Custom entities, such as a modeled boss with its own appearance and animations, also need code running inside Geyser. The RSPM Geyser extension provides that integration for compatible producer plugins and their Bedrock entity assets.

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 proxy plugin,
  • and a Geyser extension.

Each loader uses its matching entry point. Older releases shipped a separate ResourcePackManager-GeyserBridge.jar. That file is retired. When the installer finds it, it stages the universal jar through Geyser's update queue for replacement at restart.

How It Gets Installed​

RSPM installs the extension for you in the cases where it can. What happens depends on where Geyser lives:

Your setupWhat RSPM does
Geyser-Spigot on the same serverCopies the running jar into plugins/Geyser-Spigot/extensions/ResourcePackManager.jar on first installation. If the existing jar has different bytes, it stages a replacement through extensions/update/, subject to downgrade protection. A new installation or staged replacement logs a restart request; an identical current jar needs no copy.
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 exports a copy under plugins/ResourcePackManager/geyser-extension/. Follow the exact console path, which can point into its update/ subfolder when an older export exists. Copy that jar into the external Geyser's extensions/ folder and restart Geyser. Exporting the extension alone does not configure external pack delivery or startup definition loading.
Neither Geyser nor Floodgate presentNothing to do — RSPM logs an informational line and skips installation.

The installer preserves a newer valid version found in the installed universal jar, legacy bridge jar or staged update. It compares checksums as well as versions, so changed bytes with the same version can still need replacement.

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:

WhereSettingDefault
Backend plugins/ResourcePackManager/config.ymlgeyserExtensionAutoInstalltrue
Proxy config.ymlgeyser-extension-auto-installtrue

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 installed jar or cancel an already staged update. To disable the bridge, set the relevant flags to false and fully stop Geyser. Remove ResourcePackManager.jar from both extensions/ and extensions/update/, plus any retired ResourcePackManager-GeyserBridge.jar in those folders, then start Geyser. A queued copy left behind can restore the extension on startup. Remove only these RSPM files.
  • Turning the setting off has no effect on pack conversion, pack delivery, or an already installed extension. Removing the extension disables custom Bedrock entity integration; item conversion and pack delivery remain separate.

Disabling it on the backend also skips staging a downloaded RSPM update into local Geyser-Spigot's update queue. The extension and plugin can then drift apart. Keep their artifacts aligned manually; the compatibility guard below checks required Geyser classes and binary compatibility, not equality between the plugin and extension versions.

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. Each entity's properties are collected from the animation and render controllers its client entity file references, matched by controller identifier, so bundles whose long file paths were shortened still register their properties and animations.
  • 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 assets come from the entity bundles described in Bedrock conversion. A plugin supplies native Bedrock entity files under assets/<namespace>/rspm_bedrock_pack/, and RSPM imports them into the generated pack. The producer must also mark the corresponding Java entities through the bridge; a resource bundle alone does not turn arbitrary entities into custom models.

At startup, the extension scans entity/*.entity.json entries in RSPM's local generated pack for identifiers. It checks the conventional proxy output paths plugins/resourcepackmanager/work/merged/Bedrock.zip and plugins/ResourcePackManager/work/merged/Bedrock.zip, then the backend output plugins/ResourcePackManager/output/ResourcePackManager_Bedrock.zip, relative to Geyser's working directory. An external Geyser process cannot read a different machine's output automatically. Confirm which pack was preloaded in the log instead of assuming that copying the extension supplies the definitions.

Geyser Version Requirements​

The extension targets Geyser 2.11+.

Its descriptor declares Geyser API level 2.9.0. That lower descriptor level does not establish compatibility with an older Geyser. At runtime, the extension probes for the classes it needs and disables the bridge when they are absent.

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.

Disabling the bridge does not disable the separate item converter or pack provider. Those still need their own compatible Geyser APIs and successful pack delivery. Use a compatible RSPM/Geyser pair to restore custom entities.

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 startup window. If RSPM generates the first Bedrock pack after that window closes, its definitions arrive too late for the running registries. RSPM warns you to restart so it can preload the generated pack on the next startup:

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.

The warning is emitted for a new entity identifier or a new/changed property type after registration closes. Re-exporting the same definitions and property types does not require a restart.

Restart the server or proxy process that hosts Geyser after the first successful pack generation. Reconnecting alone cannot activate definitions that missed the startup window. On the next boot, the generated pack must be available at the local path the extension reads, and both definition-registration windows must be observed. The startup health line reports whether that happened.

Verifying It's Working​

  1. Check the target extensions/ folder actually contains ResourcePackManager.jar.
  2. On boot, check the RSPM Geyser bridge health line. It includes the extension version, artifactSha256, activationRoute, loadedDefinitions, packUuid and definitionWindows. For a pack containing custom entities, expect registered definitions, the intended pack UUID and definitionWindows=observed. MISSED or RSPM GEYSER BRIDGE UNHEALTHY means a startup registration window was missed; an extension marked loaded is insufficient.
  3. Join on Bedrock and inspect a modeled entity's appearance and animation. If it remains a vanilla carrier such as an armor stand, check bridge activation, client pack delivery, registered definitions and producer integration. A successful startup log alone does not prove the client rendered the entity.

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.

The extension installs early programmatic lifecycle subscriptions alongside its annotated handlers. On Velocity, the proxy plugin also relays lifecycle and session events to cover startup paths where automatic subscriptions were missed. This needs no configuration. Use the startup health line and any registrar or relay warnings to diagnose activation failures.

Where to Go Next​