BitAspire Wiki
SIR+SIR+

Addons API

Use the SIR API, wire it into your project, and create real addon jars for the SIR+ runtime.

Use the current SIR API from Maven

SIR+ addon projects now use the SIR api module through the published Maven coordinate com.bitaspire.sir:api. You do not need to download the API jar manually for normal Gradle, Maven, SBT, or Maven-compatible builds.

SIR API Dependency

Use SIR API from the Maven repository

Do not download the API jar for normal addon projects. Add the repository and depend on the published coordinate.

Latest ReleaseVersion 2.1.1

Repository

https://croabeast.github.io/repo/

Coordinate

com.bitaspire.sir:api:2.1.1

Generated from the SIR `api` module and used as the public addon compile contract for SIR and SIR+.

Normal addon projects should use the Maven repository instead of downloading a local API jar.

Add To Project

Choose your build tool

The snippet below updates instantly for SIR API 2.1.1.

Gradle Kotlin DSL

Use this if your addon uses `build.gradle.kts`.

build.gradle.kts

val sirVersion = "2.1.1"

repositories {
    maven("https://croabeast.github.io/repo/")
}

dependencies {
    implementation("com.bitaspire.sir:api:$sirVersion")
}

This is the recommended format for Gradle Kotlin DSL projects.

If you use Shadow, avoid shading or relocating SIR API into the final addon jar unless you are doing that intentionally.

The runtime loader expects addon.yml at the root of your jar. If that file is missing, SIR+ skips the addon.


What the API is for

SIRApi is the public API shared by modern SIR and SIR+. It exists so you can extend SIR+ without forking the base plugin. The API gives you access to:

  • the SIR+ plugin instance and managers
  • addon lifecycle hooks
  • command-provider integration
  • user data wrappers
  • helper utilities for listeners, files, placeholders, and chat toggles

The normal addon workflow is:

  1. add https://croabeast.github.io/repo/ as a Maven repository
  2. depend on com.bitaspire.sir:api with your build tool
  3. implement a class that extends SIRAddon
  4. ship addon.yml
  5. optionally ship commands.yml
  6. drop the jar into plugins/SIR-Plus/addons

Add the API to your project

Use the build-tool selector above to switch between Gradle Kotlin, Gradle Groovy, Maven, Version Catalog, SBT, and a generic Maven-compatible setup. The snippets use the selected SIR API version.

Suggested project layout

my-addon/
  src/main/java/...
  src/main/resources/
    addon.yml
    commands.yml
    config.yml

Only addon.yml is mandatory. The rest depends on what your addon does.


addon.yml reference

Typical addon descriptor:

main: com.example.sirplus.ExampleAddon
name: example-addon
title: Example Addon
description:
  - Adds custom behavior on top of SIR+.
depend: []
soft-depend:
  - PlaceholderAPI

Field meaning

FieldRequiredMeaning
mainYesFully qualified entrypoint class
nameNo but recommendedStable addon key used by the runtime
titleNo but recommendedFriendly display name
descriptionNoDescription lines for menus or metadata
dependNoHard dependency on other addons
soft-dependNoSoft dependency on other addons

Remember that depend and soft-depend here refer to addons, not Bukkit plugins. Bukkit plugin dependencies are better represented with PluginDependant.


Minimal addon class

package com.example.sirplus;

import com.bitaspire.sir.SIRApi;
import com.bitaspire.sir.addon.SIRAddon;

public final class ExampleAddon extends SIRAddon {

    @Override
    public boolean register() {
        saveResource("config.yml", false);
        SIRApi.instance().getPlugin().getLogger().info(getName() + " loaded successfully.");
        return true;
    }

    @Override
    public boolean unregister() {
        SIRApi.instance().getPlugin().getLogger().info(getName() + " unloaded.");
        return true;
    }
}

This is enough for SIR+ to:

  • instantiate the addon
  • create its data folder
  • extract resources you save with saveResource(...)
  • register the addon in the addon manager

Addon commands with CommandProvider

If your addon should contribute commands, implement CommandProvider and ship a commands.yml descriptor in the jar root.

Minimal provider example:

import com.bitaspire.sir.addon.SIRAddon;
import com.bitaspire.sir.command.CommandProvider;
import com.bitaspire.sir.command.SIRCommand;

import java.util.Collections;
import java.util.Set;

public final class ExampleAddon extends SIRAddon implements CommandProvider {
    @Override
    public Set<SIRCommand> getCommands() {
        return Collections.singleton(new ExampleCommand());
    }
}

commands.yml reference

main: com.example.sirplus.ExampleAddon
name: ExampleAddon
title: Example Addon
description:
  - Example addon command provider.

commands:
  example:
    permission: sir.example
    aliases: [ex]
    description: "Example command"
    usage: "/example <arg>"
    permission-message: "You do not have permission"
    sub-commands:
      reload: sir.example.reload
    depends:
      enabled: false
      parent: "other"

What SIR+ reads from commands.yml

FieldMeaning
commands.{name}.permissionBase permission node
aliasesAlternative labels
descriptionHelp and metadata text
usageUsage string
permission-messageFallback denial message
sub-commandsDerived or explicit subcommand permissions
depends.enabled and depends.parentDeclares child commands that depend on a parent command

This is the same command model used by the built-in providers, so addon commands can feel native to the platform.


Useful API types

The public API jar includes much more than SIRAddon. These are the types you will reach for most often.

TypeWhy you would use it
SIRApiGlobal entrypoint for managers, plugin instance, scheduler, and shared services
SIRAddonBase class for addon lifecycle
AddonManagerRuntime addon lookup and addon-facing integration points
com.bitaspire.sir.channel.ChatChannelThe current channel contract used by SIR+ for routing, audience, formatting, and logging
Access, Audience, Style, Logging, and ClickBreak a channel into readable subcontracts instead of forcing one flat interface
CommandProviderLets the addon expose SIR-aware commands
SIRCommandBase class for commands with permission and completion helpers
SettingsServicePer-user toggle state backing features such as chat toggles
PluginDependantDeclares Bukkit plugin dependencies
ListenerSafer listener registration and unregistration helper
PAPIExpansionHelper base for PlaceholderAPI expansions
UserFormatter<T>Formatter contract for user-aware text processing
ExtensionFile and ConfigFile and config helper abstractions
SIRUser and UserManagerUser data wrappers for mute, ignore, channels, and related state
ChatToggleablePer-user toggle contract for chat-like features

Package map

The current API jar exposes classes under:

  • com.bitaspire.sir.*
  • com.bitaspire.sir.channel.*
  • com.bitaspire.sir.addon.*
  • com.bitaspire.sir.command.*
  • com.bitaspire.sir.module.*
  • com.bitaspire.sir.user.*

That means addon code can interact with addon management, command management, module metadata, and user data without reflecting into the main plugin jar.

Current ChatChannel model

The current SIR API formalizes the channel model used by the modern channels module and by SIR+:

  • the canonical interface is now com.bitaspire.sir.channel.ChatChannel
  • channel behavior is grouped into Access, Audience, Style, Logging, and Click
  • channel routing is no longer exposed as one giant flat interface
  • the old com.bitaspire.sir.ChatChannel still exists only as a deprecated compatibility bridge for older addons

If you are writing a new addon, import the new package directly.

import com.bitaspire.sir.channel.ChatChannel;
import com.bitaspire.sir.channel.Access;
import com.bitaspire.sir.channel.Audience;
import com.bitaspire.sir.channel.Style;
import com.bitaspire.sir.channel.Logging;

Typical migration examples:

  • old channel.getLocalAccess() -> new channel.getAccess()
  • old channel.getRadius() -> new channel.getAudience().getRadius()
  • old channel.getChatFormat() -> new channel.getStyle().getFormat()
  • old channel.getLogFormat() -> new channel.getLogging().getFormat()
  • old channel.getClickAction() -> new channel.getStyle().getClick()

This is the main API change you need to account for when upgrading addon code from previous public builds.


Common extension patterns

Plugin-aware loading

Implement PluginDependant when your addon expects a plugin such as PlaceholderAPI or Vault.

That lets SIR+ defer or validate loading around external plugin availability.

Per-user toggles

Implement ChatToggleable when your addon owns a user toggle and you want to store that state through SIR's settings flow.

Placeholder expansions

Extend PAPIExpansion if your addon also ships placeholders.

Custom formatting

Implement UserFormatter<T> when your addon should expose formatter behavior that other addon-aware code can resolve through the addon manager.

Event listeners

Extend com.bitaspire.sir.Listener when you want the convenience registration helpers instead of raw Bukkit boilerplate.


Build and deploy

  1. Compile the addon jar against the selected SIR API version, currently com.bitaspire.sir:api:2.1.1.
  2. Make sure addon.yml is at the jar root.
  3. If the addon exposes commands, include commands.yml too.
  4. Copy the jar into plugins/SIR-Plus/addons/.
  5. Start the server.
  6. Use /sir addons to verify that the addon is visible.
  7. Enable or disable it with /sir addons [name] [enable/disable/toggle] as needed.

If the jar loads but its commands do not appear, the usual culprit is a missing or malformed commands.yml.

If your build uses a fat-jar or shading plugin, review its output before release. The normal addon jar should depend on SIR API for compilation, not bundle a second private copy of the API classes.


Troubleshooting

Check these first when an addon does not behave as expected:

  1. addon.yml exists at the jar root
  2. the main class extends SIRAddon
  3. addon hard dependencies in depend are present
  4. plugin dependencies declared through PluginDependant are installed
  5. the addon is enabled in addons/states.yml
  6. if commands are missing, commands.yml exists and the addon implements CommandProvider

For the runtime side of loading and state persistence, continue with Addon Runtime.

Last updated on

On this page