Astral Realms Documentation Help

Developer API

AstralTown exposes its data through the TownAPI static façade and a set of services hung off the main plugin instance. Custom Bukkit events provide hookpoints.

Maven coordinates

<dependency> <groupId>com.astralrealms</groupId> <artifactId>town</artifactId> <version>1.0-SNAPSHOT</version> <scope>provided</scope> </dependency>

Repository: https://maven.astralrealms.fr/repository/maven-public/.

TownAPI

Static lookups suitable for any plugin that needs to read town state without taking a hard dependency on the service classes.

import com.astralrealms.town.TownAPI; // Player <-> town TownAPI.findPlayerSelectedTown(player); // Optional<Town> TownAPI.setPlayerSelectedTown(player, townId); TownAPI.findTownsByMember(playerUuid); // Collection<Town> // Lookups TownAPI.findTownByUniqueId(townId); // Optional<Town> TownAPI.findTownByName("MyTown"); // Optional<Town> TownAPI.findTownByLocation(location); // Optional<Town> TownAPI.findTownByChunk(chunk); // Optional<Town> // Permissions & settings (resolves subzone vs town vs wilderness) TownAPI.hasPermission(player, location, PermissionType.BLOCK_PLACE); TownAPI.hasSettingEnabled(location, TownSettings.PVP); // Claim helpers TownAPI.isWithinOwnTownClaims(player); // boolean TownAPI.findClaimsByTown(townId); // Collection<Claim> // Subzones TownAPI.findSubZonesByTown(townId); // Collection<SubZone>

hasPermission is the recommended entry point for any external plugin that wants to know "may the player do X here" — it handles subzone scoping, the owner bypass, and the town.admin override.

Plugin handle

import com.astralrealms.town.AstralTown; AstralTown plugin = AstralTown.getPlugin(AstralTown.class);

Services

Each service has a getter and a public surface. See Overview for the full list. Key examples:

// Towns plugin.towns().findById(townId); // Optional<Town> plugin.towns().findByPlayer(playerUuid); // Collection<Town> plugin.towns().updateGlobally(townId); // CompletableFuture<Void> // Claims plugin.claims().findChunkOwner(chunk); // Optional<Town> plugin.claims().countByTown(townId); // int plugin.claims().calculatePrice(currentClaims); // double // Bans plugin.bans().findByTown(townId); // CompletableFuture<Collection<TownBan>> plugin.bans().isBannedFromCached(playerId, townId); // boolean // Logs plugin.logs().findByTownId(townId); // CompletableFuture<List<TownLog>> // Chat plugin.chat().broadcast(town, component); // Warps plugin.warps().sortedWarps(); // sorted by weeklyVisits desc

Custom Bukkit events

See Events for the full catalogue. Typical use:

@EventHandler public void onJoin(TownMemberJoinEvent event) { Town town = event.getTown(); TownMember member = event.getMember(); Player player = event.getPlayer(); // Grant a "newcomer" badge, log analytics, … } @EventHandler public void onClaim(TownClaimEvent event) { Town town = event.getTown(); Claim claim = event.getClaim(); // Update your own world data here }

For lifecycle clean-up — when a town disappears entirely — use TownDisbandedEvent (post-fact, non-cancellable, async-safe).

Custom actions and placeholders

AstralTown's 22 actions go through the standard AstralPaperAPI action registry, so any plugin can trigger them programmatically or chain them in their own menus. The placeholder namespaces (towns_*, town_*, role_*, member_*, warp_*, subzone_*, ban_*, invitation_*, log_*) resolve through AstralPaperAPI.createPlaceholderContainer(player) without extra wiring.

Reading per-player state

import com.astralrealms.town.storage.TownPlayerData; import com.astralrealms.sync.SyncAPI; SyncAPI.findData(player.getUniqueId(), TownPlayerData.class) .ifPresent(data -> { Optional<Town> selected = data.selectedTown(); boolean chatOn = data.chatEnabled(); Set<UUID> pinned = data.favoriteWarps(); });

Mutating these fields directly bypasses the user-facing confirmation messages — use the actions for normal flows; only touch the snapshot directly for admin tooling.

Last modified: 25 July 2026