Describe the feature you'd like to have implemented
Add a public API method to LimboAPI that allows plugins to register themselves as PRE_LIMBO_PROFILE_REQUEST handlers, so their GameProfileRequestEvent listener runs before LimboAPI's hookLoginSession reads the event and sends LoginSuccess to the client.
Something like:
// In LimboAPI class
public void registerPreProfileRequestPlugin(String pluginId);
Plugins would call this in their initialization:
LimboAPI limboApi = (LimboAPI) ProxyServer.getInstance()
.getPluginManager().getPlugin("limboapi").orElseThrow();
limboApi.registerPreProfileRequestPlugin("qqauth");
Is your feature request related to an existing problem? Please describe.
Yes — it relates to Issue #143 ([BUG] LimboAPI causes "Chat validation error").
Auth plugins that replace the player UUID in GameProfileRequestEvent (e.g., JPremium, The QQAuth plugin I am currently developing, and similar "premium → offline UUID mapping" plugins) run into a race condition with LimboAPI's EventManagerHook:
- LimboAPI intercepts
GameProfileRequestEvent at @Subscribe(order = PostOrder.FIRST)
- It fires PRE_LIMBO plugins (
floodgate, geyser) via an internal FIRE_METHOD
- However, other GPR handlers (like auth plugins' UUID replacement) remain in the standard Velocity event chain
- Due to async interleaving,
hookLoginSession reads event.getGameProfile() — and sends LoginSuccess to the client — before the auth plugin's GPR handler has replaced the UUID
- The result: client receives
LoginSuccess(UUID=premiumUuid), the backend Paper server sees the replaced (offline) UUID → UUID mismatch → "Chat validation error" on the sending client
The current workaround is to manually add the auth plugin's ID to PRE_LIMBO_PROFILE_REQUEST_PLUGINS in LimboAPI's config.yml, but this requires users to know about this config option and manually maintain it. Many users are not aware of this configuration item, and self registration should be the responsibility of the plugin.
Additional context
The current code in EventManagerHook.reloadHandlers() (Settings.java line 97) hardcodes List.of("floodgate", "geyser") as defaults. A plugin can register itself at runtime via the proposed API, and reloadHandlers() would merge both sources:
// In reloadHandlers()
if (Settings.IMP.MAIN.PRE_LIMBO_PROFILE_REQUEST_PLUGINS.contains(id)
|| this.plugin.getRegisteredPreLimboPlugins().contains(id)) {
preEvents.add(handler);
newHandlers.remove(handler);
}
This is backward-compatible — users who already configured it manually via config.yml keep working, and plugins that call the new API get handled automatically.
Related discussion: Issue #143 — the bug report that this feature would help resolve.
Describe the feature you'd like to have implemented
Add a public API method to LimboAPI that allows plugins to register themselves as
PRE_LIMBO_PROFILE_REQUESThandlers, so theirGameProfileRequestEventlistener runs before LimboAPI'shookLoginSessionreads the event and sendsLoginSuccessto the client.Something like:
Plugins would call this in their initialization:
Is your feature request related to an existing problem? Please describe.
Yes — it relates to Issue #143 (
[BUG] LimboAPI causes "Chat validation error").Auth plugins that replace the player UUID in
GameProfileRequestEvent(e.g., JPremium, The QQAuth plugin I am currently developing, and similar "premium → offline UUID mapping" plugins) run into a race condition with LimboAPI'sEventManagerHook:GameProfileRequestEventat@Subscribe(order = PostOrder.FIRST)floodgate,geyser) via an internalFIRE_METHODhookLoginSessionreadsevent.getGameProfile()— and sendsLoginSuccessto the client — before the auth plugin's GPR handler has replaced the UUIDLoginSuccess(UUID=premiumUuid), the backend Paper server sees the replaced (offline) UUID → UUID mismatch → "Chat validation error" on the sending clientThe current workaround is to manually add the auth plugin's ID to
PRE_LIMBO_PROFILE_REQUEST_PLUGINSin LimboAPI'sconfig.yml, but this requires users to know about this config option and manually maintain it. Many users are not aware of this configuration item, and self registration should be the responsibility of the plugin.Additional context
The current code in
EventManagerHook.reloadHandlers()(Settings.java line 97) hardcodesList.of("floodgate", "geyser")as defaults. A plugin can register itself at runtime via the proposed API, andreloadHandlers()would merge both sources:This is backward-compatible — users who already configured it manually via
config.ymlkeep working, and plugins that call the new API get handled automatically.Related discussion: Issue #143 — the bug report that this feature would help resolve.