Astral Realms Documentation Help

Service System

AstralCore uses a ServiceRepository to allow loose coupling between plugins. Any AstralService implementation can be registered and retrieved without creating a hard compile-time dependency.

AstralService Interface

AstralService is a marker interface in commons. Implement it to mark your service class:

import com.astralrealms.core.service.AstralService; public interface MyEconomyService extends AstralService { double getBalance(Player player); void pay(Player player, double amount); }

Registering a Service

Register your implementation during onEnable:

@Override public void onEnable() { AstralPaperAPI.registerService(MyEconomyService.class, new MyEconomyServiceImpl()); }

Retrieving a Service

Optional<MyEconomyService> economy = AstralPaperAPI.getService(MyEconomyService.class); economy.ifPresent(e -> { double balance = e.getBalance(player); player.sendMessage("Balance: " + balance); });

Or directly via the repository:

ServiceRepository repo = AstralPaperAPI.services(); repo.get(MyEconomyService.class).ifPresent(...);

Built-in Services

AstralCore ships several built-in services accessible through the main plugin instance:

Service

Access

Description

PlayerService

AstralPaperAPI.players()

Network-wide player tracking and lookup

ServerService

AstralPaperAPI.servers()

Server discovery and heartbeat management

MenuService

AstralCore.get().menus()

Menu blueprint management and opening

DialogService

AstralCore.get().dialogs()

Dialog blueprint management and opening

BlockService

AstralCore.get().blocks()

Player-placed block tracking

PaperTeleporationService

AstralCore.get().teleportation()

Cross-server teleportation

EconomyService

AstralPaperAPI.getService(EconomyService.class)

Multi-currency economy: balances, deposit / withdraw / transfer, bulk transactions

PlayerService

PlayerService players = AstralPaperAPI.players(); // Online check boolean online = players.isOnline(uuid); // Lookup by name (async, hybrid cache/DB) players.findByName("Steve").thenAccept(opt -> { opt.ifPresent(p -> System.out.println(p.server())); }); // All online player names Collection<String> names = players.onlinePlayerNames();

ServerService

ServerService servers = AstralPaperAPI.servers(); // Find the least-populated server in a group servers.findEmptiestByGroup("survival").thenAccept(opt -> { opt.ifPresent(server -> { // Transfer player to that server }); });

EconomyService

A built-in multi-currency economy abstraction (com.astralrealms.core.service.impl.EconomyService). Mutating operations are asynchronous (CompletableFuture<Boolean>); balances are also available synchronously from a local cache. Most methods come in default-currency and explicit-currency overloads, and deposit/withdraw take an optional notify flag.

EconomyService economy = AstralPaperAPI.getService(EconomyService.class).orElseThrow(); // Cached (sync) balance in the default currency BigDecimal balance = economy.getCachedBalance(playerId); // Async operations economy.deposit(playerId, 100.0); economy.withdraw(playerId, "gems", 5.0); economy.transfer(fromId, toId, 50.0); economy.hasBalance(playerId, 25.0).thenAccept(ok -> { /* ... */ });

Bulk transactions

bulkTransactions settles many deposits / withdrawals / transfers as a single batched future — use it instead of chaining individual operations when applying a whole set of balance changes at once.

economy.bulkTransactions(List.of( new EconomyService.TransactionRequest(null, winnerId, 1000, "coins", TransactionType.DEPOSIT), new EconomyService.TransactionRequest(loserId, null, 250, "coins", TransactionType.WITHDRAW), new EconomyService.TransactionRequest(payerId, payeeId, 500, "coins", TransactionType.TRANSFER) ));

TransactionRequest field

Type

Notes

source

@Nullable UUID

Payer. null for a DEPOSIT.

target

UUID

Recipient.

amount

double

Transaction amount.

currency

String

Currency id.

type

TransactionType

DEPOSIT, WITHDRAW, or TRANSFER.

Service Lifecycle

Services are registered once and persist until the plugin is disabled. There is no built-in unregister — if your plugin is reloaded it should re-register its services on the next onEnable.

Last modified: 25 July 2026