Skip to content

Java API

Complete reference for every public Java API surface exposed by DonutSMPCore for other Bukkit/Paper plugins.

For the HTTP public API (/v1/..., player tokens, webhooks config), see Public HTTP API.


Setup

plugin.yml

depend: [DonutSMPCore]
# or
softdepend: [DonutSMPCore, PlaceholderAPI, Vault]

Availability check

All DonutSMPApi module accessors return Optional.empty() when DonutSMPCore is not loaded, the module is disabled in config.yml, or the service failed to initialize.

import net.donutsmp.donutcore.api.DonutSMPApi;

if (DonutSMPApi.getPlugin() == null) {
    // DonutSMPCore not loaded
    return;
}

DonutSMPApi.auction().ifPresent(api -> {
    // auction module is enabled and ready
});

Module toggles

Each DonutSMPApi.*() accessor maps to a module name in plugins/DonutSMPCore/config.yml under Modules.<name>.enabled.

Accessor Module key Notes
teams() team
homes() home Requires team module
crates() crates
settings() settings
tpa() tpa
billford() billford
stats() stats Required for leaderboard placeholders
punishments() punishments
spawner() spawner
worthSell() worth
orderMarket() order
auction() auction
publicApi() / publicApiWebhooks() publicapi
shards() / shardsEconomy() shards
economy() economy Via Vault; not a Donut module accessor

NetworkApi and NetworkPlayers are available when the network bridge is active (see Network API).


DonutSMPApi — main entry point

Package: net.donutsmp.donutcore.api.DonutSMPApi

Service accessors

DonutSMPApi.teams()              // Optional<TeamService>
DonutSMPApi.homes()              // Optional<HomeService>
DonutSMPApi.crates()             // Optional<CratesService>
DonutSMPApi.settings()           // Optional<SettingsService>
DonutSMPApi.tpa()                // Optional<TpaService>
DonutSMPApi.billford()           // Optional<BillfordService>
DonutSMPApi.stats()              // Optional<StatsService>
DonutSMPApi.punishments()        // Optional<PunishmentsApi>
DonutSMPApi.spawner()            // Optional<SpawnerApi>
DonutSMPApi.worthSell()          // Optional<WorthSellApi>
DonutSMPApi.orderMarket()        // Optional<OrderMarketApi>
DonutSMPApi.auction()            // Optional<AuctionApi>
DonutSMPApi.publicApi()          // Optional<DonutSMPPublicApi>
DonutSMPApi.publicApiWebhooks()  // Optional<DonutSmpWebhookPublisher>
DonutSMPApi.shards()             // Optional<ShardsApi>
DonutSMPApi.shardsEconomy()      // Optional<ShardsEconomy>
DonutSMPApi.economy()            // Optional<net.milkbowl.vault.economy.Economy>
DonutSMPCore plugin = DonutSMPApi.getPlugin(); // nullable

Shards API

Module: shards

ShardsApi interface

DonutSMPApi.shards().ifPresent(api -> {
    long balance = api.getBalance(player.getUniqueId());
    api.setBalance(uuid, 1000);
    api.give(uuid, 50);
    boolean removed = api.take(uuid, 25);
    boolean transferred = api.transfer(from, to, 100);
    boolean inRegion = api.isInShardRegion(uuid);

    ShardsTopEntry entry = api.lookupByName("Notch");
    List<ShardsTopEntry> top = api.top(10);
});

ShardsTopEntry record: (UUID uuid, String username, long shards)

UUID uuid = player.getUniqueId();

long balance = DonutSMPApi.getShards(uuid);
DonutSMPApi.setShards(uuid, 1000);
DonutSMPApi.giveShards(uuid, 50);   // alias: addShards
boolean ok = DonutSMPApi.takeShards(uuid, 25); // alias: removeShards

// Player overloads
DonutSMPApi.getShards(player);
DonutSMPApi.setShards(player, 500);
DonutSMPApi.addShards(player, 40);
DonutSMPApi.removeShards(player, 10);

ShardsEconomy (double-based, separate from Vault $)

DonutSMPApi.shardsEconomy().ifPresent(econ -> {
    double bal = econ.getBalance(player);
    econ.deposit(uuid, 100);
    boolean withdrawn = econ.withdraw(uuid, 25);
});

Shard events

Both events are cancellable and allow changing the amount before it is applied.

@EventHandler
public void onShardGain(net.donutsmp.donutcore.api.shards.event.ShardGainEvent event) {
    Player player = event.getPlayer();
    long amount = event.getAmount();       // mutable via setAmount
    ShardGainEvent.GainReason reason = event.getReason();
    // OTHER, PAY, ADMIN, KILL, PASSIVE_REGION, PASSIVE_ALWAYS_EARN
    event.setCancelled(true);
}

@EventHandler
public void onShardLose(net.donutsmp.donutcore.api.shards.event.ShardLoseEvent event) {
    // OTHER, PAY, ADMIN, SHOP
}

Economy (Vault)

Module: economy (registers Vault provider)

DonutSMPApi.economy().ifPresent(econ -> {
    double balance = econ.getBalance(player);
    econ.depositPlayer(player, 100);
    econ.withdrawPlayer(player, 50);
});

DonutEconomy (native provider)

Package: net.donutsmp.donutcore.module.economy.api.DonutEconomyProvider

Use when you need Donut-specific behavior (silent deposit, balance top, formatting):

if (DonutEconomyProvider.isReady()) {
    DonutEconomy econ = DonutEconomyProvider.require();
    double bal = econ.getBalance(uuid);
    econ.deposit(uuid, 100);
    econ.depositSilent(uuid, 50);
    econ.setBalance(uuid, 1000);
    List<BalanceTopEntry> top = econ.balanceTop(10);
    String formatted = econ.format(1234.56);
}

Stats API

Module: stats

Static helper

PlayerStats stats = DonutSMPApi.getPlayerStats(player);
// or DonutSMPApi.getPlayerStats(uuid)

int kills = stats.kills();
int deaths = stats.deaths();
int blocksBroken = stats.blocksBroken();
int blocksPlaced = stats.blocksPlaced();
int mobsKilled = stats.mobsKilled();
long playtimeSeconds = stats.playtimeSeconds();

Returns PlayerStats.empty() when the stats module is disabled.

StatsService

DonutSMPApi.stats().ifPresent(service -> {
    PlayerStatistics raw = service.getPlayerStats(uuid);
    CompletableFuture<PlayerStatistics> async = service.loadPlayerStatsAsync(uuid);
    double numeric = service.getNumericStat(uuid, "kills");
    String formatted = service.formatPlaytime(3600);
    String rank = service.formatRank(3);
    String placeholder = service.resolvePlaceholder(player, "kills");
    StatisticRepository repo = service.getRepository();
});

Teams API

Module: team

Static helpers

boolean sameTeam = DonutSMPApi.areOnSameTeam(playerA, playerB);
boolean inTeam = DonutSMPApi.isInTeam(player);
boolean pvpOn = DonutSMPApi.isTeamPvpEnabled(player);

TeamService

DonutSMPApi.teams().ifPresent(teams -> {
    Optional<TeamRepository.TeamData> team = teams.getTeam(uuid);
    boolean inTeam = teams.isInTeam(uuid);
    boolean same = teams.areOnSameTeam(uuidA, uuidB);
    boolean canDamage = teams.canDamage(attacker, victim);
    boolean pvp = teams.isPvpEnabled(uuid);

    teams.createTeam(leader, "MyTeam");
    teams.invitePlayer(inviter, target);
    teams.joinTeam(player, "MyTeam");
    teams.leaveTeam(player);
    teams.kickMember(actor, target);
    teams.promoteMember(leader, target);
    teams.disbandTeam(leader);
    teams.togglePvp(player);

    teams.setTeamHome(player, location);
    teams.deleteTeamHome(player);
    teams.teleportToTeamHome(player, teleportManager);

    teams.sendTeamMessage(sender, "Hello team");
    teams.broadcastToTeam(teamData, "&7message");
    teams.setTeamChatEnabled(uuid, true);
    teams.isTeamChatEnabled(uuid);

    teams.openTeamGui(player);
    TeamRepository repo = teams.repository();
});

Homes API

Module: home (requires team)

DonutSMPApi.homes().ifPresent(homes -> {
    int max = homes.getMaxHomes(player);
    List<HomeService.HomeData> list = homes.getHomes(uuid);
    // HomeData: (int slot, String name, Location location)

    homes.setHome(player, slot, "base");
    homes.setHomeAuto(player);
    homes.deleteHome(player, slot);
    homes.teleportHome(player, slot);
    homes.teleportTeamHome(player);
    homes.updateHomeName(player, slot, "new name");
    int nextSlot = homes.findNextAvailableSlot(player);
});

Crates API

Module: crates

Static helpers

int keys = DonutSMPApi.getCrateKeys(uuid, "common");
Map<String, Integer> all = DonutSMPApi.getAllCrateKeys(uuid);
DonutSMPApi.giveCrateKeys(uuid, "common", 5);
boolean ok = DonutSMPApi.giveCrateKeysChecked(uuid, "common", 5);
DonutSMPApi.setCrateKeys(uuid, "common", 10);
boolean taken = DonutSMPApi.takeCrateKeys(uuid, "common", 2);
boolean exists = DonutSMPApi.hasCrate("common");

CratesService

DonutSMPApi.crates().ifPresent(crates -> {
    int keys = crates.getKeys(uuid, crateId);
    Map<String, Integer> all = crates.getAllKeys(uuid);
    crates.giveKeys(uuid, crateId, amount);
    crates.setKeys(uuid, crateId, amount);
    boolean taken = crates.takeKeys(uuid, crateId, amount);
    boolean valid = crates.giveKeysChecked(uuid, crateId, amount);
    boolean has = crates.hasCrate(crateId);
    String resolved = crates.resolveCrateId("Common");

    boolean opened = crates.openCrate(player, crateId);
    ItemStack item = crates.createCrateItem(crateId);
    boolean given = crates.giveCrateItem(player, crateId, 1);
    boolean isKey = crates.isCrateItem(itemStack);

    crates.refreshHolograms(uuid);
    crates.cleanupPlayer(uuid);
});

Crate IDs are defined in plugins/DonutSMPCore/crates/config.yml.


Settings API

Module: settings

Static helpers

Setting keys match configName() in the settings GUI config (settings/gui/settings.ymlitems.<key>).

boolean enabled = DonutSMPApi.isSettingEnabled(player, "public_chat", true);
DonutSMPApi.setSettingEnabled(player, "tpa_requests", false);
boolean toggled = DonutSMPApi.toggleSetting(player, "pay_alerts");

UUID overloads exist for isSettingEnabled and setSettingEnabled.

Official setting keys

Key Description
public_chat Public chat visibility
private_messages Private messages
chat_server_messages Server chat messages
hotbar_server_messages Hotbar server messages
pay_alerts Pay notification alerts
bounty_alerts Bounty alerts
auction_alerts Auction alerts
quick_auction_buy Quick auction buy
fast_crystals Fast crystals
totem_particles Totem particles
explosion_particles Explosion particles
explosion_sounds Explosion sounds
chainmail_on_respawn Chainmail on respawn
player_visibility Player visibility
scoreboard Scoreboard (TAB)
tpa_confirm_menu TPA confirm menus
after_duel_songs After duel songs
duels_requests Duel requests
mob_disable Disable mob spawns
sound_notifications Sound notifications
order_notifications Order fill notifications
tpa_requests TPA requests
tpa_here_requests TPA here requests
tpa_auto TPA auto-accept
team_invites Team invites
payments Payment requests
team_chat Team chat mode
expression_messages Expression messages
worth_display Worth display on items
coords_spoof Coordinate spoof

SettingsService

DonutSMPApi.settings().ifPresent(settings -> {
    boolean on = settings.isEnabled(player, "public_chat", true);
    settings.setEnabled(player, "public_chat", false);
    settings.toggle(player, "public_chat");
    settings.openSettingsGui(player, args);
    boolean crystal = settings.isCrystalPluginAvailable();
});

TPA API

Module: tpa

DonutSMPApi.tpa().ifPresent(tpa -> {
    tpa.requestTeleport(sender, target, TpaService.RequestType.TPA);
    tpa.requestTeleport(sender, target, TpaService.RequestType.TPHERE);
    tpa.requestTeleportByName(sender, "Steve", TpaService.RequestType.TPA);

    tpa.sendRequest(sender, target, TpaService.RequestType.TPA);
    tpa.accept(target, sender);
    tpa.acceptRequest(target, sender);
    tpa.acceptRequestByName(target, "Steve");
    tpa.deny(target, sender);
    tpa.denyByName(target, "Steve");
    tpa.cancelAll(sender);

    tpa.toggleTpa(player);
    tpa.toggleTpaHere(player);
    tpa.toggleConfirmMenu(player);
    tpa.toggleAutoAccept(player);
    boolean auto = tpa.isAutoAccept(uuid);

    // Network cross-server
    tpa.deliverRemoteRequest(...);
    tpa.acceptRemoteRequest(target, senderName, type);
    tpa.cancelRemoteRequest(targetId, senderName);
    tpa.acceptCrossServerArrival(teleporting, destination);

    tpa.clearPlayer(uuid);
});

Billford API

Module: billford

DonutSMPApi.billford().ifPresent(billford -> {
    boolean traded = billford.executeTrade(player);
    String desc = billford.describeItem(itemStack);
    BillfordConfig config = billford.config();
    BillfordTradeManager trades = billford.trades();
});

Auction API

Module: auction

DonutSMPApi.auction().ifPresent(ah -> {
    List<AuctionListing> sellerListings = ah.getActiveListings(sellerUuid);
    List<AuctionListing> all = ah.getAllActiveListings();
    int count = ah.countActiveListings(sellerUuid);

    ah.removeListing(listingId);
    ah.removeListing(sellerUuid, listingId);
    ah.updateListingItem(listingId, newItemStack);
});

AuctionListing record: (long id, UUID sellerUuid, String sellerName, ItemStack item, double price, long createdAt, long expiresAt)


Order Market API

Module: order

DonutSMPApi.orderMarket().ifPresent(orders -> {
    if (!orders.isEnabled()) return;
    if (!orders.isEnabledFor(OrderMarketApi.SellSource.SELL)) return;

    // SellSource: SELL, SPAWNER_SELL, SELL_AXE
    List<ItemStack> stacks = List.of(item);
    OrderMarketApi.RouteSellResult result = orders.routeSellStacks(
            player, stacks, OrderMarketApi.SellSource.SELL);
    // result.remaining(), result.orderPayout(), result.deliveredAmount()

    OrderMarketApi.RouteSellResult estimate = orders.estimateSellStacks(
            player, stacks, OrderMarketApi.SellSource.SELL);

    orders.routeSellFromInventory(player, OrderMarketApi.SellSource.SELL);

    orders.tryRouteAuctionListing(player, item, listTotalPrice);
});

Worth / Sell API

Module: worth

DonutSMPApi.worthSell().ifPresent(worth -> {
    if (!worth.isReady()) return;
    if (!worth.canSellInWorld(player)) return;
    if (!worth.isSellable(player, item)) return;

    double total = worth.getSellPrice(player, item);
    double perUnit = worth.getSellPricePerUnit(player, item);
    double base = worth.getBaseSellPrice(item);
});

Spawner API

Module: spawner

DonutSMPApi.spawner().ifPresent(spawner -> {
    spawner.giveSpawnerItem(player, "zombie", 1);
    spawner.canFitSpawnerItem(player, "zombie", 64);
    ItemStack item = spawner.createSpawnerItem("zombie", 1);
    boolean isSpawner = spawner.isSpawnerItem(item);
    String mobId = spawner.resolveMobId(item);
    boolean managed = spawner.isManagedSpawner(location);
    spawner.reload();
});

Punishments API

Module: punishments

Static helpers

Optional<OffendDetails> offend = DonutSMPApi.findOffend("ABCD1234");
boolean validFormat = DonutSMPApi.isValidOffendIdFormat("ABCD1234");
boolean exists = DonutSMPApi.offendIdExists("ABCD1234");

OffendId utility

Package: net.donutsmp.donutcore.api.punishments.OffendId

String normalized = OffendId.normalize(rawId);   // trim + uppercase
boolean valid = OffendId.isValidFormat(rawId);   // 8-char Crockford-style ID

OffendDetails record

Looked up by offend ID. Fields: databaseId, id, punishedPlayerId, punishedPlayerName, staffId, staffName, type, reason, durationMillis, createdAtEpochMillis, expiresAtEpochMillis, active, undone.

Helper methods: isPermanent(), isExpired(now), isCurrentlyActive(), remainingMillis().

PunishmentsApi

DonutSMPApi.punishments().ifPresent(pun -> {
    String id = pun.normalizeOffendId(raw);
    Optional<OffendDetails> details = pun.findOffend(id);

    ResolvedPlayer target = pun.resolvePlayer("Steve");
    boolean banned = pun.isBanned(uuid);
    boolean muted = pun.isMuted(uuid);
    PunishmentRecord ban = pun.getActiveBan(uuid);
    PunishmentRecord mute = pun.getActiveMute(uuid);
    PunishmentRecord byId = pun.getByPunishmentId(offendId);

    List<PunishmentRecord> history = pun.getHistory(uuid, PunishmentType.BAN, page, pageSize);
    List<PunishmentRecord> allHistory = pun.getAllHistory(uuid, page, pageSize);
    int count = pun.countHistory(uuid, PunishmentType.MUTE);

    List<PunishmentRecord> activeBans = pun.getActiveBans(page, pageSize);
    int activeBanCount = pun.countActiveBans();
    pun.pruneHistory(uuid);

    // Formatting helpers
    Map<String, String> placeholders = pun.formatRecordPlaceholders(record);
    String status = pun.formatStatus(record);
    String date = pun.formatDate(epochMillis);
    String duration = pun.formatDuration(durationMillis);
    String remaining = pun.formatRemainingTime(offendDetails);

    // Apply punishments (staff must be OfflinePlayer with appropriate perms in-game)
    PunishmentRecord newBan = pun.ban(staff, target, "reason", "7d");
    PunishmentRecord newMute = pun.mute(staff, target, "reason", "1h");
    pun.unban(staff, target);
    pun.unmute(staff, target);
    pun.kick(staff, target, "reason");
    pun.warn(staff, target, "reason");
});

PunishmentType: BAN, MUTE, KICK, WARN, UNBAN, UNMUTE, UNWARN


Public API (Java)

Module: publicapi

Full HTTP route documentation: Public HTTP API

DonutSMPApi.publicApi().ifPresent(api -> {
    int limit = api.rateLimitPerMinute(); // default 250/min per key

    Optional<UUID> owner = api.validateKey(apiKey);
    boolean allowed = api.allowRequest(apiKey);

    String token = api.getOrCreatePlayerKey(playerId);
    api.resetPlayerKey(playerId);

    JsonObject lb = api.leaderboard("money", 1);
    JsonObject stats = api.stats("Steve");
    JsonObject lookup = api.lookup("Steve");
    JsonObject listings = api.auctionList(1, null, null);
    JsonObject transactions = api.auctionTransactions(1);

    boolean maintenance = api.isMaintenanceEnabled();
    api.toggleMaintenance();
    api.addMaintenanceBypass(uuid);
    api.removeMaintenanceBypass(uuid);
    int bypassCount = api.getMaintenanceBypassCount();
});

PublicApiResponses (JSON builders)

Package: net.donutsmp.donutcore.api.publicapi.PublicApiResponses

JsonObject ok = PublicApiResponses.success(resultElement);
JsonObject unauthorized = PublicApiResponses.unauthorized();  // status 401
JsonObject error = PublicApiResponses.serverError();          // status 500
JsonObject entry = PublicApiResponses.leaderboardEntry(name, uuid, value);
JsonObject seller = PublicApiResponses.seller(name, uuid);
JsonObject listing = PublicApiResponses.auctionListing(item, price, seller, timeLeftSeconds);
JsonObject purchase = PublicApiResponses.purchaseItem(item, price, seller, unixMillisDateSold);

Webhook publisher

DonutSMPApi.publicApiWebhooks().ifPresent(webhooks -> {
    JsonObject payload = new JsonObject();
    payload.addProperty("example", "data");
    webhooks.publish(WebhookEvent.AUCTION_LISTING_CREATED, payload);
});

WebhookEvent IDs:

Enum Event ID
AUCTION_LISTING_CREATED donutsmp.auction.listing_created
AUCTION_PURCHASE donutsmp.auction.purchase
ORDER_PLACED donutsmp.order.placed
ORDER_FILLED donutsmp.order.filled
ORDER_CANCELLED donutsmp.order.cancelled

Envelope sent to webhook URLs:

{
  "event": "donutsmp.auction.purchase",
  "timestamp": 1710000000000,
  "timestamp_iso": "...",
  "data": { }
}

Network API

Package: net.donutsmp.donutcore.network.api

Available when the proxy/network bridge is active (NetworkApi.isActive()).

NetworkApi

boolean active = NetworkApi.isActive();
String serverId = NetworkApi.getServerId();

String server = NetworkApi.findPlayerServer("Steve");
String serverByUuid = NetworkApi.findPlayerServer(uuid);
boolean online = NetworkApi.isPlayerOnNetwork("Steve");
int ping = NetworkApi.getPlayerPing("Steve");

String worldServer = NetworkApi.resolveServerForWorld("world");
boolean localWorld = NetworkApi.isLocalWorld("world");
boolean localLoc = NetworkApi.isLocalLocation(location);

NetworkApi.connectToServer(player, "survival");
NetworkApi.trySendCrossServerMessage(sender, "Steve", "hello");

NetworkApi.notifyPlayer(uuid, name, "&7message");
NetworkApi.broadcastToStaff("donut.staff", "&cAlert");
NetworkApi.broadcastToAll("&6Announcement");
NetworkApi.kickPlayerNetwork(uuid, "reason");
NetworkApi.requestWipeKick(uuid);

NetworkApi.broadcastSocialSpy(sender, receiver, message);

// Cache invalidation (cross-server)
NetworkApi.invalidateAuction();
NetworkApi.invalidateOrder();
NetworkApi.invalidateWorth();

// Bridges (nullable when network inactive)
TpaNetworkBridge tpa = NetworkApi.tpaBridge();
TeleportNetworkBridge tp = NetworkApi.teleportBridge();
EconomyNetworkBridge econ = NetworkApi.economyBridge();
TeamNetworkBridge team = NetworkApi.teamBridge();
PlayerNotifyNetworkBridge notify = NetworkApi.playerNotifyBridge();
MsgNetworkStateService msg = NetworkApi.msgStateService();
StaffInventoryNetworkBridge staffInv = NetworkApi.staffInventoryBridge();
GodmodeNetworkState godmode = NetworkApi.godmodeState();
StaffActionsNetworkBridge staff = NetworkApi.staffActionsBridge();
RtpDuoNetworkService rtpDuo = NetworkApi.rtpDuoNetwork();

NetworkPlayers (helper)

Package: net.donutsmp.donutcore.network.api.NetworkPlayers

boolean online = NetworkPlayers.isOnlineAnywhere("Steve");
boolean onlineUuid = NetworkPlayers.isOnlineAnywhere(uuid);
int ping = NetworkPlayers.getPing("Steve");
Player local = NetworkPlayers.findLocal("Steve");
Optional<UUID> uuid = NetworkPlayers.resolveUuid("Steve");
String[] suggestions = NetworkPlayers.suggestOnlineNames("St", excludeSelf);

Placeholders

DonutSMPCore registers PlaceholderAPI expansion %donutsmpcore_*% via DonutSMPPlaceholderExpansion. Two syntaxes are supported:

  1. PlaceholderAPI: %donutsmpcore_<module>_<key>%
  2. Colon syntax: %donutsmpcore:<module>:<key>%

See Placeholders for the full key list, leaderboard patterns, and custom module registration.


Quick reference — all DonutSMPApi static methods

Method Returns Module
getPlugin() DonutSMPCore
teams()shardsEconomy() Optional<Service> see table above
economy() Optional<Economy> economy (Vault)
getPlayerStats(UUID/Player) PlayerStats stats
areOnSameTeam(...) boolean team
isInTeam(...) boolean team
isTeamPvpEnabled(...) boolean team
getCrateKeys(...) int crates
getAllCrateKeys(...) Map<String,Integer> crates
giveCrateKeys(...) void crates
giveCrateKeysChecked(...) boolean crates
hasCrate(...) boolean crates
setCrateKeys(...) void crates
takeCrateKeys(...) boolean crates
isSettingEnabled(...) boolean settings
setSettingEnabled(...) boolean settings
toggleSetting(...) boolean settings
getShards(...) long shards
setShards(...) void shards
giveShards / addShards void shards
takeShards / removeShards boolean shards
findOffend(...) Optional<OffendDetails> punishments
isValidOffendIdFormat(...) boolean punishments
offendIdExists(...) boolean punishments

Package Purpose
net.donutsmp.donutcore.module.worth.api.* Internal worth pricing (WorthManager, Prices, SellPrices)
net.opmasterleo.serverapi.* Built-in HTTP server (port 7001) — see Public HTTP API
net.opmasterleo.statistic.* Statistic engine used by stats/leaderboard modules
net.opmasterleo.hook.PlaceholderAPIHook Internal PAPI integration