Skip to Content
PluginsAquaCoreDeveloper API

Developer API

AquaCore exposes a small, stable façade. Everything public lives under com.aquaticstudios.aquacore.api — anything outside that package can change in a patch release.

Groupcom.github.aquatic-studios
ArtifactAquaCore
RepositoryJitPack
Java17+
ScopecompileOnly / provided

Installation

build.gradle.kts
repositories { maven("https://jitpack.io") } dependencies { compileOnly("com.github.aquatic-studios:AquaCore:2.0.0") }

Declare the dependency in your plugin descriptor so load order is correct:

plugin.yml
name: MyPlugin main: com.example.MyPlugin api-version: "1.16" depend: [AquaCore]

Use compileOnly / provided. Shading AquaCore into your jar puts two copies of the API on the classpath and every instanceof check against our classes silently fails.

Getting the API

import com.aquaticstudios.aquacore.api.AquaCoreAPI; public final class MyPlugin extends JavaPlugin { private AquaCoreAPI aqua; @Override public void onEnable() { this.aqua = AquaCoreAPI.get(); getLogger().info("Hooked into AquaCore " + aqua.version()); } }

AquaCoreAPI.get() throws IllegalStateException if AquaCore is not enabled yet. With depend: [AquaCore] in your plugin.yml that cannot happen inside onEnable.

Sending a broadcast

import com.aquaticstudios.aquacore.api.broadcast.BroadcastRequest; aqua.broadcasts().send( BroadcastRequest.template("welcome") .arg("player", player.getName()) .arg("rank", "VIP") .arg("price", "$10") .silent(false) .build() );

send returns a BroadcastResult:

MethodReturns
isSuccess()boolean
failureReason()Optional<String>
receivers()int — players that actually got it
elapsedNanos()long

Events

All events live in com.aquaticstudios.aquacore.api.event.

EventCancellableFired
AquaBroadcastPreEventYesBefore anything is sent
AquaBroadcastPostEventNoAfter every output finished
AquaTemplateReloadEventNoAfter /aqua reload
AquaModuleToggleEventYesWhen a module is enabled or disabled
@EventHandler public void onBroadcast(AquaBroadcastPreEvent event) { if (event.template().name().equals("vip")) { event.arg("rank", "VIP+"); // rewrite an argument event.receivers().removeIf(Player::isSleeping); } if (Bukkit.getOnlinePlayers().size() < 5) { event.setCancelled(true); // too few players, skip it } }

AquaBroadcastPreEvent is fired on the main thread even when the broadcast was requested async, so it is always safe to touch the Bukkit API inside the handler.

Rendering a head

aqua.heads().render(player.getUniqueId(), 8).thenAccept(lines -> { for (Component line : lines) { player.sendMessage(line); } });

Returns a CompletableFuture<List<Component>>. Skins are fetched off the main thread and cached for heads.cache-minutes.

Never call .join() or .get() on that future from the main thread. Skin fetching hits Mojang’s session server — blocking on it freezes the whole server for as long as the request takes.

Folia

Every scheduled task inside AquaCore goes through an internal scheduler abstraction, so the API behaves identically on Paper and Folia. When you receive a callback, you are already on the correct thread for the entity or region involved.

Versioning

The API follows semantic versioning:

  • Patch (2.0.02.0.1) — no API change.
  • Minor (2.02.1) — additions only, safe to update.
  • Major (2.x3.x) — may remove or rename. Announced in the changelog with a migration table.

Deprecated methods stay for at least one full minor cycle and always carry a @Deprecated(forRemoval) annotation pointing at the replacement.

Last updated on