API overview
Voxen ships a separate api module with no dependency on the plugin’s internals. Every
type in it is stable; everything else is not.
Depending on it
Section titled “Depending on it”-
Add the repository and the API as a
compileOnlydependency:build.gradle.kts repositories {maven("https://repo.vao.zone/releases")}dependencies {compileOnly("zone.vao:voxen-api:1.0")}build.gradle repositories {maven { url 'https://repo.vao.zone/releases' }}dependencies {compileOnly 'zone.vao:voxen-api:1.0'}pom.xml <repositories><repository><id>vao</id><url>https://repo.vao.zone/releases</url></repository></repositories><dependencies><dependency><groupId>zone.vao</groupId><artifactId>voxen-api</artifactId><version>1.0</version><scope>provided</scope></dependency></dependencies>The plugin jar works as a dependency too, but the API module is smaller and pulls in nothing else.
-
Declare Voxen in your plugin descriptor:
plugin.yml depend: [Voxen]Use
softdependinstead if your plugin should still load without it.
Getting the service
Section titled “Getting the service”// static facadeCollection<ChannelInfo> channels = VoxenApi.channels();
// or through Bukkit's ServicesManagerVoxenService voxen = getServer().getServicesManager().load(VoxenService.class);val channels = VoxenApi.channels()
val voxen = server.servicesManager.load(VoxenService::class.java)The facade throws if Voxen is not loaded yet, so in a softdepend plugin either ask first
or take the ServicesManager route, which returns null instead:
if (VoxenApi.isAvailable()) { // safe from here}What you can do
Section titled “What you can do”Read channels
Section titled “Read channels”Collection<ChannelInfo> all = VoxenApi.channels();ChannelInfo global = VoxenApi.channel("global");ChannelInfo current = VoxenApi.activeChannel(player);ChannelInfo is an immutable snapshot: id, displayName, type, enabled,
readOnly, crossServer, radius, worlds.
Send chat
Section titled “Send chat”// as the player, through the whole pipeline: permissions, mutes, cooldown, filterboolean sent = VoxenApi.sendChannelMessage(player, "global", "hello");
// raw component, skips the pipeline entirelyVoxenApi.broadcastToChannel("global", Component.text("Server restarting"));Check moderation state
Section titled “Check moderation state”VoxenApi.isMuted(uuid);VoxenApi.isMuted(uuid, "global");VoxenApi.isIgnoring(source, target);Private messages, nicknames, parties
Section titled “Private messages, nicknames, parties”VoxenApi.sendPrivateMessage(sender, target, "hi"); // PM toggle, ignores, tag permissionsString nick = VoxenApi.nickname(player);VoxenApi.setNickname(player, "<gold>Steve"); // length limits apply, permissions do notPartyInfo party = VoxenApi.party(uuid);Add a format placeholder
Section titled “Add a format placeholder”VoxenApi.registerPlaceholder("level", p -> Component.text(getLevel(p)));<level> is now usable in any chat format. Return null to render nothing. Unregister on
disable.
Register your own channel
Section titled “Register your own channel”VoxenApi.registerChannel( "auction", "<gold>Auction", "<gold>[A] <player> <dark_gray>» <white><message>", sender -> Bukkit.getOnlinePlayers().stream() .filter(this::wantsAuctions) .toList());The RecipientProvider is optional; without one the channel behaves like a normal global
channel. registerRecipients does the same thing for a channel that already exists in
channels/, which is how you bolt a custom audience onto the bundled ones.
Runtime channels are not written to disk and disappear on restart. Register them in
onEnable.
Events
Section titled “Events”Two events cover the message lifecycle. See Events.