Skip to content

feat(proxy): prefix-based player suggestions, and ship the plugin image#10

Merged
hbrombeer merged 1 commit into
mainfrom
feat/cross-proxy-lookup
Jul 12, 2026
Merged

feat(proxy): prefix-based player suggestions, and ship the plugin image#10
hbrombeer merged 1 commit into
mainfrom
feat/cross-proxy-lookup

Conversation

@hbrombeer

Copy link
Copy Markdown
Member

plugin-proxy is the piece that makes chat and social work across proxies: ProxyServiceImpl already resolves a player locally first and falls back to a PlayerSessionQuery, and delivers to remote players over NATS (proxy.system.<id>, proxy.transfer.<id>). Two things kept it from being usable.

It never shipped

No image, no maven release — so plugin-proxy could not be deployed, and nothing could compile against plugin-proxy-api (plugin-chat's build referenced local-SNAPSHOT, i.e. whatever was in the developer's mavenLocal). Adds the standard docker-gradle-build-push workflow (edge on main, semver on tag) and a Dockerfile carrying the shaded JAR at /jar/plugin.jar, the shape the plugin-velocity-jar chart expects.

getOnlinePlayerNames() does not scale

It asked for every online player on the network. That call feeds tab-complete, which Velocity fires on every keystroke — so at 10k players online it is a ~200 KB response, issued thousands of times a second, with a table scan behind each one.

Replaced with suggestPlayerNames(prefix, limit):

  • local players are filtered in memory (free, and the common case)
  • the network is only asked once the prefix is ≥ 2 characters — one letter matches most of the roster anyway
  • answers are cached for 2s, keyed by prefix, so a player typing an eight-letter name causes one lookup, not eight
  • the result is capped (default 20), and PlayerSessionQuery.suggestNames is contractually a prefix search, not a roster dump

PlayerSessionQuery.getOnlinePlayers() is gone from the API for the same reason — an unbounded list on a per-keystroke path is a footgun, not a feature.

Tests

SuggestionCacheTest: repeated prefixes hit the cache, prefixes are case-insensitive, stale entries are re-fetched, the cache evicts instead of growing forever, and merge puts local players first while de-duplicating and capping.

Image verified with a local docker build --secret id=github_token ….

Next

service-player implements the lookup RPCs (groundsgg/library-grpc-contracts#68, released as player 0.3.0); plugin-player registers a PlayerSessionQuery backed by them; chat and social then drop their local-only lookups and use ProxyService.

🤖 Generated with Claude Code

https://claude.ai/code/session_01E92vTegZqXd2HqjE7jnDJz

plugin-proxy already had the right shape — local-first lookups, NATS
delivery to whichever proxy holds the player — but two things kept it from
being usable.

It never shipped an artifact: no image, no maven release. So neither it nor
anything depending on it (chat, social) could be deployed. Add the standard
docker-gradle-build-push workflow and a Dockerfile carrying the shaded JAR
at /jar/plugin.jar.

And `getOnlinePlayerNames()` asked for every online player on the network.
That feeds tab-complete, which Velocity fires on every keystroke — at 10k
players online it is a ~200 KB response, thousands of times a second, plus a
table scan behind it. Replace it with `suggestPlayerNames(prefix, limit)`:
local players are answered from memory, the network is only asked once the
prefix is at least two characters, answers are cached for 2s, and the result
is capped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E92vTegZqXd2HqjE7jnDJz
@hbrombeer hbrombeer merged commit 7d78e55 into main Jul 12, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant