Skip to main content

Modules & packages

Maven modules​

ModuleArtifact idContents
Lib/APILib-APIPublic interfaces and abstractions
Lib/srcpaper-dispatchImplementation, bundles Lib-API
Exemple-Plugin—Example plugin, not published

Depend on paper-dispatch. See Add the dependency for the coordinates — note the group id differs from the single-module default.

Packages​

Everything lives under fr.robie.paperdispatch.

PackageKey types
commandBaseCommand, SubCommand, CommandDispatch, CommandResultType
managerICommandManager, CommandManager
flagFlags, Flag, BoolFlag, ValueFlag, FlagContext
argumentEnumArgument, OfflinePlayerArgument
requirementCommandRequirement, PermissionRequirement, PlayerOnlyRequirement
cacheOfflinePlayerCache
loggerPluginLogger

ICommandManager​

The contract, minus deprecated members:

<Y extends Plugin> void trackCommand(BaseCommand<Y> command);
<U extends Plugin> BaseCommand<U> trackCommand(BaseCommand.BaseCommandBuilder<U> builder);
void flushRegistrations();

<Y extends Plugin> void unregisterCommand(BaseCommand<Y> command);
void unregisterCommands(Collection<? extends BaseCommand<?>> toRemove);
void unregisterReloadableCommands();
void unregisterAll(Plugin plugin);
void unregisterAll();

boolean isRegistered(Plugin plugin, String name);
boolean isRegistered(BaseCommand<?> command);
List<BaseCommand<?>> getCommands(Plugin plugin);

CommandManager is safe to call from async contexts — it uses a ConcurrentHashMap plus CopyOnWriteArrayList, and hops onto the global region scheduler for the server-global command refresh, which must run on the main thread.

Requirements​

CommandRequirement<T extends Plugin> has a single method:

boolean isMet(T plugin, CommandSourceStack source);

Two implementations ship: PermissionRequirement and PlayerOnlyRequirement. Add your own with addRequirement(...) on the builder.

Offline player cache​

Optional UUID ↔ name cache backing OfflinePlayerArgument's tab-completion.

OfflinePlayerCache.install(this); // onEnable
OfflinePlayerCache.uninstall(this); // onDisable — shuts down its HttpClient

Or own the lifecycle yourself:

OfflinePlayerCache cache = OfflinePlayerCache.builder(this)
.maximumSize(5000)
.maxSuggestions(50)
.expireAfterAccess(Duration.ofMinutes(10))
.buildAndRegister();

cache.close(); // onDisable

Everything degrades gracefully without a cache installed: commands still work, they just do not complete player names.

Two reasons to close it

Each cache owns an HttpClient with its own selector and executor threads, so a reload-heavy server leaks a thread pool per reload if you never close it.

Its global instance is also static — which is why relocation is mandatory when you shade the library.

Suggestions are capped​

The name index is unbounded, so an empty prefix would otherwise serialise every known player name on every keystroke. maxSuggestions bounds it.