Shared Services
Deliveries
The mailbox: things an addon owes a player but could not hand over. Written once, given on their next join.
delivery().sendItem(uuid, item, "Auction sale", "XAuctionHouse");
delivery().sendMoney(uuid, "coins", 250.0, "Vote reward", "XVote");
delivery().countPending(uuid).thenAccept(count -> ...);
Money always goes through. An item is only closed once it is really in the inventory, so a full inventory postpones it rather than losing it.
Leaderboards
Declared once, refreshed on a timer, read from memory. Reading one never touches the database, which matters when a scoreboard asks for it several times a second.
leaderboards().define("kills")
.table("myaddon_stats").value("kills")
.size(10).refreshEvery(300)
.register();
leaderboards().get("kills").top(10); // the last snapshot
That also publishes %xcore_top_kills_1_name% and %xcore_top_kills_1_value%.
Network
Every server announces itself on the sync channel, so an addon can know what the network looks like instead of guessing.
network().servers(); // name, players, TPS, version
network().locate(uuid); // which server holds this player
network().totalOnline(); // across the network
network().send("lobby", "mychannel", new SyncMessage("KICK", uuid.toString()));Discord
One queue for the whole installation, with retries and rate-limit handling. Each addon keeps its own webhook address in its own config.
discord().send(url, DiscordNotifier.embed()
.title("Ban")
.description(player + " was banned by " + staff)
.color(0xC0362C)
.field("Reason", reason, false)
.timestamp()
.build());
discord().sendRaw(url, json) takes a payload an addon has already assembled.
Toolbox
| Class | Purpose |
|---|---|
Items | Items to base64 and back, giving without losing the overflow, counting, taking |
Cooldowns | Per-player cooldowns that expire on their own |
Notify | Titles, action bars and boss bars |
Formats | Durations both ways, thousands separators, compact numbers, byte sizes |
CommandHelpers | Suggestions, offline target resolution, the silent flag |
WorldConfig | Per-world overrides, resolved once at load |
BlinkCache | Both faces of a blinking item, built once |
ranks() | Primary group, weight, numbered permission levels |
Placeholders without an expansion
placeholders()
.register("kits", (player, arg) -> String.valueOf(available(player)))
.register("cooldown", (player, arg) -> Formats.duration(remaining(player, arg)));
placeholders().publish();
The identifier is the addon name in lower case, so those become %mykits_kits% and %mykits_cooldown_starter%.
Play Time
XCore counts how long each player has been connected, across sessions, in the playtime column of the shared table.
long seconds = api().getPlaytime(uuid);
The session in progress is included, so the value moves while a player is online rather than only when they disconnect. %xcore_playtime% gives it formatted.