Config Plugin (Paper/Velocity) when your plugin needs typed runtime configuration from the
Grounds Config System.
The plugin starts the shared config runtime, connects it to Config API and NATS, and exposes a
ConfigManager that other plugins can use to register and consume typed config documents.
Requirements
The plugin requires these environment variables at startup:| Variable | Required | Purpose |
|---|---|---|
CONFIG_GRPC_TARGET | Yes | gRPC target for Config API |
CONFIG_NATS_URL | Yes | NATS connection URL used for refresh triggers |
What the Plugin Provides
After startup, the plugin:- creates a
ConfigManager - connects the manager to
Config APIand NATS - creates a local snapshot cache under the plugin data directory in
runtime-config-cache - exposes
ConfigManagerto other plugins
ConfigManager through Bukkit services. Velocity exposes it through the
ConfigManagerService contract implemented by the plugin-config plugin instance.
Define a Typed Config
Create oneConfigDefinition<T> per config document. The definition declares the backend
namespace, the key, the Kotlin type, and the local default value.
Config API through
SyncDefaults.
Integrate the Manager
- Paper
- Velocity
Resolve
ConfigManager from Bukkit services:Register, Read, and Observe Config
Register your definitions
Register each definition for the The first registration for a given
(app, env) scope it belongs to.(app, env) scope creates the internal sync scope for that
pair.Choose the startup mode
Use
FAIL_CLOSED when the plugin cannot continue without a ready value. Use DEGRADED when the
plugin may continue with a cached snapshot if bootstrap cannot fetch a current one.FAIL_CLOSED: throwsConfigRegistrationExceptionif bootstrap cannot produce a ready valueDEGRADED: restores a persisted cached snapshot when possible, otherwise returnsNOT_READY
ConfigRegistrationResult when you allow degraded startup.Read the current value
Once a definition is registered and ready, read it through indexed access on
ConfigManager.Registration Outcomes
ConfigManager.register(...) returns a ConfigRegistrationResult with a status:
| Status | Meaning |
|---|---|
READY | A typed value is available immediately |
DEGRADED | A cached snapshot was restored and the value is usable |
NOT_READY | Registration succeeded, but no typed value is available yet |
ALREADY_REGISTERED | The same definition was already registered |
REJECTED | Another definition already owns the same config key |
Failure Modes
Accessing an unregistered definition
Accessing an unregistered definition
Reading or subscribing to a definition that was never registered throws
ConfigDefinitionNotRegisteredException.Accessing a definition before it becomes ready
Accessing a definition before it becomes ready
Reading a registered definition before a typed value exists throws
ConfigDefinitionNotReadyException.Conflicting registrations
Conflicting registrations
If a second definition tries to claim the same backend key in the same scope, registration is
rejected with status
REJECTED.Local Cache Behavior
The runtime stores cached snapshots inruntime-config-cache under the plugin data directory:
- Paper: inside the
plugin-configdata folder - Velocity: inside the
plugin-configdata directory
DEGRADED startup when the current snapshot cannot be fetched during
bootstrap.
Cached snapshots improve startup resilience. They do not replace reconciliation through the current
service snapshot.
Next Steps
- Read Config API to understand the backend service contract
- Read Runtime Behavior before you rely on event-driven updates