Skip to content

[ENHANCEMENT] Public API for plugins to register as PRE_LIMBO GPR handler #272

Description

@xfy2412

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:

  1. LimboAPI intercepts GameProfileRequestEvent at @Subscribe(order = PostOrder.FIRST)
  2. It fires PRE_LIMBO plugins (floodgate, geyser) via an internal FIRE_METHOD
  3. However, other GPR handlers (like auth plugins' UUID replacement) remain in the standard Velocity event chain
  4. 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
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions