Overview
AstralTower adds an instanced, party-based "dimensional tower" arena to the AstralRealms network. A party requests entry from a lobby-side portal or command; a dedicated tower server generates a fresh instanced world of procedurally sequenced rooms and pulls the party in. Inside the instance the party fights through rooms room-by-room, opening doors for artifacts, coins, a shop, or a boss, and — once they return to the lobby — any accumulated rewards are handed to them there.
Two-module architecture
The plugin ships as two separate builds of largely-parallel com.astralrealms.tower.AstralTower/com.astralrealms.tower.bridge.AstralTowerBridge main classes, each targeting a different tier of the network:
Module |
| Runs on | Depends on | Role |
|---|---|---|---|---|
Bridge |
| Lobby / proxy-facing servers | AstralCore, AstralSync, AstralParty, PlaceholderAPI, LuckPerms | Owns |
Paper |
| Dedicated tower servers | AstralCore, AstralSync, AstralClasses, AstralMobs, AstralParty, FastAsyncWorldEdit, packetevents, PacketFramework, CraftEngine, PlaceholderAPI | Owns tower generation, gameplay (room sequencing, mob spawning/scaling, artifacts, coins, shop, doors), and per-instance reward bookkeeping while a party is inside the tower. |
Both modules load config.yml and messages.yml through AstralPaperPlugin#loadConfiguration, and both register a tower placeholder namespace and messaging exchanges over the shared TowerPacketRegistry (RabbitMQ) and CacheService (Redis). See Configuration for both modules' keys and Placeholders for the two tower_* namespaces.
Creating a tower instance
See Commands for /tower create's exact failure messages and Tower Instances for room generation, phases, and doors.
Inside the tower
Once teleported in, the party spawns in the lobby room (RoomType.LOBBY, always position 0 per rooms.yml) and moves through the generated sequence:
Fight mobs — a room's
mobs.ymlset spawns over time and scales in health per room depth and per participant. Killing the last mob transitions the room toREWARDS. See Tower Instances: mob scaling.Collect the room's reward — depending on which door the party took to reach it, a room offers artifacts, coins, a shop, or (on the boss room) nothing extra: see Loot, Shop & Rewards.
Walk through a door to advance — each cleared room opens doors tagged with a reward type for the next room, so the party picks which reward they want before moving on. See Tower Instances: doors.
Reach the last room and claim the end-of-run chest, or die/disconnect/time out — any of these ends the instance. See Tower Instances: instance lifecycle.
Player state inside the instance (session coins, mobs killed) lives only in memory for the duration of the instance — PlayerDataService loads it on PlayerJoinTowerInstanceEvent and drops it on PlayerQuitTowerInstanceEvent. See Placeholders for %tower_coins%.
Cosmetic hand slot
Rather than giving players a real starter item, the paper module's InventoryPacketListener intercepts inventory/held-item packets and substitutes the inventory slots configured in config.yml — the player's actual inventory is untouched; what they see (and the item they appear to be holding at hand-slot) is purely a packet-level illusion. See Configuration.
Reward carry-over
Rewards claimed inside the tower (room-reward chests, the end-of-run chest) are not granted directly; they are cached per-player (RewardService, a 14-day-TTL Redis-backed CachedRewards record of an action list and the room index they were earned at) and claimed back on the lobby:
Reaching
RoomPhase.END_REWARDS(or interacting with a room-reward chest) queues aCachedRewardsentry and marks the player as already rewarded for that room.Back on the lobby, once AstralSync fires
PlayerDataLoadedEventfor the player, the bridge'sRewardsListenerreads every cached reward for that player, runs each entry'sPaperActionlist, fires aTowerFinishedEvent(player, room)per reward, deletes the cache entry, and deducts one daily ticket per reward whose room index is≥ 1.
See Loot, Shop & Rewards for the full sequence and the TowerFinishedEvent shape.
Daily tickets
Entering the tower costs a ticket per party member. Tickets are AstralSync player data (TowerPlayerData, snapshot key tower:player_data) refilled once per day (Europe/Paris calendar day) on PlayerDataLoadedEvent, to daily-tickets.default plus a bonus per matching daily-tickets.permissions entry the player holds. A LuckPerms NodeAddEvent listener also grants the configured bonus immediately when a group.* permission node is added to a player. See Commands: /tower tickets and Configuration.
Feature map
Area | Page |
|---|---|
Room generation, phases, doors, mob scaling, custom events | |
Artifacts, coins, shop, room/end rewards, reward carry-over | |
| |
| |
Placeholders exposed by both modules |
Requirements
Dependency | Required by | Notes |
|---|---|---|
AstralCore | Both modules | Configuration, messaging, cache, placeholder framework, |
AstralSync | Both modules |
|
AstralParty | Both modules | A party is required to create an instance ( |
AstralClasses, AstralMobs | Paper | Room mob/boss spawning ( |
PlaceholderAPI | Both modules | Declared as a hard |
PacketEvents, PacketFramework | Paper | Display entities (artifacts, coins, holograms) and the cosmetic hand-slot packet illusion. |
CraftEngine | Paper | Custom item/pack integration. |
FastAsyncWorldEdit | Paper | Pastes room schematics when generating a tower world. |
LuckPerms | Bridge |
|
RabbitMQ | Both modules | Backs |
Redis | Both modules | Backs |