Loader hook
There is no register-a-callback API. Deferring work until Venus exists is a one-liner on the provider — this page explains why, and what to avoid.
The problem
Venus loads asynchronously relative to the Bukkit plugin sequence. Two things can be true at the moment your onEnable runs:
- Venus is installed but has not published its API yet.
- Venus classes are not resolvable yet, so a reference to one from your main class can makeyour plugin fail to load.
The first is handled by waiting; the second is handled by keeping API references out of the class that Bukkit instantiates.
The hook
@Override
public void onEnable() {
// Nothing Venus-specific happens in this class beyond this line.
VenusAPIProvider.getAsync().thenAccept(ApiHook::onApi);
}public final class ApiHook {
static void onApi(VenusApi api) {
api.subcommands().register(new MySubcommand("mystats"));
api.events().repository().register(ViolationEvent.class, MyListener::onViolation);
}
}Because ApiHook is only referenced from inside the callback, its constant pool is not resolved during plugin loading. That is what keeps the two class loaders from being mutually dependent.
What to declare
name: MyPlugin
version: 1.0.0
main: com.example.MyPlugin
# Venus is required
depend: [VenusLoader]
# or, if the plugin also runs without Venus
softdepend: [VenusLoader]Shutting down
Unregister what you registered. Handles make this precise:
private RegisteredListener<ViolationEvent> listener;
void onApi(VenusApi api) {
this.listener = api.events().repository().register(ViolationEvent.class, MyListener::onViolation);
}
@Override
public void onDisable() {
RegisteredListener<ViolationEvent> handle = this.listener;
if (handle != null) VenusAPIProvider.get().events().repository().unregister(handle);
}Events and EventListenerRepository cover the registration surface in full.