Developer API
On this page(6)
SnGGWave exposes a public developer API for other plugins: custom events and a read-only query service. The API lives in the com.sn.ggwave.api package inside the plugin jar. There is no separate artifact.
Only com.sn.ggwave.api is a stable, kept contract. Everything else in the jar is obfuscated and internal. Do not call it.
The API is the same on Paper and on Velocity. It answers about the level SnGGWave runs on: one Paper server, or the whole network when it runs on the proxy.
Getting the jar
-
Download the latest release jar.
-
Install it into your local Maven repository:
mvn install:install-file -Dfile=SnGGWave-<version>.jar -DgroupId=com.sn \ -DartifactId=SnGGWave -Dversion=<version> -Dpackaging=jar -
Depend on it with
providedscope. Never shade it.
Quick start
On Paper, declare the dependency in your plugin.yml:
depend: [SnGGWave] # or softdepend if optionalOn Velocity, declare it in your velocity-plugin.json:
"dependencies": [{ "id": "snggwave" }]Resolve the API when you need it:
SnGGWaveAPI api = SnGGWaveProvider.get();
if (api != null) {
// use the api
}On Paper the same instance is also registered with the Bukkit ServicesManager.
Resolve the reference when you need it. Do not keep it past a SnGGWave disable or a proxy shutdown. SnGGWaveProvider.get() returns null while the plugin is absent, enabling or stopping.
Master switch
API events can be disabled by the server owner with api-events.enabled: false in config.yml. The query service stays available either way.
Events
Paper events live in com.sn.ggwave.api.event and extend the Bukkit Event. Velocity events live in com.sn.ggwave.api.velocity and use the Velocity event manager. The names are the same on both.
Cancellable events fire before the action. On Paper you cancel with setCancelled(true). On Velocity you deny the result with setResult(GenericResult.denied()).
| Event | Fired when | Cancel effect |
|---|---|---|
GGWaveStartEvent | A wave is about to register, from /ggwave start or from startWave. Carries the sponsor UUID and name, the amount and the duration in seconds. | No wave starts, nothing is announced and no sound plays. The staff member is told it was cancelled. |
GGWaveClaimEvent | A player's GG is about to claim the oldest wave they have not claimed. Carries the player UUID and name and the WaveView. | That GG claims nothing and no reward runs. The GG line is still shown and the original message stays hidden. |
Notification events fire after the fact. They cannot be cancelled.
| Event | Fired when | Thread |
|---|---|---|
GGWaveEndEvent | A wave ended, after its end line and sound. Carries the WaveView. It is not fired for waves still running at shutdown. | Paper: main. Velocity: delivered without waiting for listeners. |
On Paper, GGWaveStartEvent is fired on the thread that starts the wave. GGWaveClaimEvent is normally asynchronous, so hop to the main thread before touching the Bukkit API.
On Velocity, SnGGWave waits for the listeners of the two cancellable events. A listener that takes longer than a few seconds counts as allowed, so keep them fast.
Listen like any event on your platform:
// Paper
@EventHandler
public void on(GGWaveStartEvent event) {
// read the payload; event.setCancelled(true) aborts the wave
}
// Velocity
@Subscribe
public void on(GGWaveStartEvent event) {
// read the payload; event.setResult(ResultedEvent.GenericResult.denied()) aborts the wave
}Event payloads are read-only. Rewards are the configured reward-commands, and no event changes them.
GGWaveClaimEvent is a request, not proof of a claim. If one player sends two GGs at once, both may be offered the same wave. Call hasClaimed afterwards when you need certainty.
Query service
Queries are thread-safe, never block and return immutable values.
| Method | Returns | Notes |
|---|---|---|
getApiVersion() | String | The API contract version. |
getActiveWaves() | List<WaveView> | The waves claimable right now, oldest first. Empty when none is running. |
getWave(UUID waveId) | Optional<WaveView> | A wave is known from its start until its end announcement. Right after expiry it can still be returned, so compare expiresAt() with the current time. |
hasClaimed(UUID waveId, UUID player) | boolean | True when the player claimed that wave. Always false once the wave ended. |
startWave(UUID sponsor, String amount) | Optional<WaveView> | Starts a wave exactly like /ggwave start, with the same announcement, duration and rewards. |
startWave fires GGWaveStartEvent and waits for its listeners. It returns empty in three cases: the sponsor is not online in scope, a listener cancelled the start, or SnGGWave is shutting down. A blank amount throws IllegalArgumentException.
On Paper, call startWave from the server thread. From another thread the event is fired as an asynchronous event. On Velocity, never call it from a netty I/O thread.
A WaveView is an immutable snapshot of one wave:
| Field | Type | Meaning |
|---|---|---|
id() | UUID | The wave identity for every query. |
sponsorUuid() | UUID | The player the wave thanks. |
sponsorName() | String | The sponsor username when the wave started. |
amount() | String | The free-text amount label, shown as typed. |
durationSeconds() | int | How long the wave stays claimable, at least 1. |
startedAt() | Instant | When the wave was registered. |
expiresAt() | Instant | The last instant at which the wave is still claimable. |
Versioning
Call getApiVersion() for the API contract version. It is independent of the plugin version. Additions bump the minor component. Existing members are never removed or changed; deprecated members keep working.