Re-add firm autocomplete in commands, in two forms: (1) all online/active firms (e.g. for paying into them), and (2) the firms the player is a proprietor or employee of.
Technical notes — FirmPlayerResolver exists and is wired in CommanderModule, but it resolves players (FirmPlayer), not firms. Firm args are plain @Arg("firm") String resolved at runtime via FirmService.getFirmByNameOrId, so firms get no tab-completion. Add a FirmResolver implements ParameterResolver<Firm> (mirroring FirmPlayerResolver), bound in CommanderModule, with sender-aware suggestions() — all firms for pay-into, listOwnedOrMemberFirms(sender) for owned-firm contexts.
Design (per the requested approach). Mirror FirmPlayerResolver but cache-backed. Hibernia resolves suggestions by parameter type (@Arg has no per-arg suggestion hook), so the "two forms" become two resolver types over one shared in-memory FirmSuggestionCache:
FirmName (default) → suggestions = firms the sender owns or is employed by (FirmService.listOwnedOrMemberFirms(uuid), cached per-player with a short TTL).OnlineFirmName → suggestions = firms with an employee/proprietor online (union the cached firm-lists of Bukkit.getOnlinePlayers()).resolve() accept any token (thin record FirmName(String value)), so a firm that matches neither form but still exists is usable — existence is checked downstream by the command's getFirmByNameOrId.Cache: a @Singleton holding allFirmNames (refreshed on an interval from listAllActiveFirms) + a per-player firm-name cache (TTL ~30s via listOwnedOrMemberFirms); JDK ConcurrentHashMap (no Guava collections per repo rules). Register both resolvers in CommanderModule; migrate the relevant firm commands' String firmName args to FirmName/OnlineFirmName and call .value(). Tests for the cache + resolvers to hold the ≥95% gate. (Bonus: the resolver naturally prefers active firms, dovetailing with PAR-87.)
Implemented on develop (commit 3162fc9).
Design — two firm-name argument types backed by a short-TTL (30s) in-memory cache (FirmSuggestionCache) so tab-completion never hits the DB per keystroke:
FirmName (default): suggests firms the sender owns or is employed by; console falls back to all active firms.OnlineFirmName (cross-firm targets): suggests firms with an employee or proprietor currently online — the union of each online player's firms, composed in the resolver so Bukkit stays out of the cache (keeps it unit-testable).Either resolver still accepts any existing firm on resolve — suggestions are hints, not a whitelist, matching the requested third form.
Wiring — every firm-name command arg across Account / Misc / Firm / Request / Role / Staff / Tax now uses the right type. OnlineFirmName is used for pay business <firm> <target> and account pay business <firm> <accountId> <target> targets. firm create <name> left raw (completing existing names for a new firm would be wrong).
Bonus fix — caught a latent overflow in activeFirmNames(): the MIN_VALUE sentinel made now - activeAt overflow negative, so the first load never triggered (would have shipped an always-empty active-firm pool). Now guarded explicitly; covered by FirmSuggestionCacheTest.
Coverage gate (≥95%) green; 325 unit tests pass. Resolvers/commands are coverage-excluded by design; FirmSuggestionCache (in services/) is fully tested.
Code context —
FirmPlayerResolverexists and is wired inCommanderModule, but it resolves players (FirmPlayer), not firms. Firm args are plain@Arg("firm") Stringresolved at runtime viaFirmService.getFirmByNameOrId, so firms currently get no tab-completion.Approach: add a
FirmResolver implements ParameterResolver<Firm>(mirroringFirmPlayerResolver), bound inCommanderModule, with sender-awaresuggestions()— all firms for pay-into contexts,listOwnedOrMemberFirms(sender)for owned-firm contexts (the two forms the description asks for).