Overview
AstralDungeons adds instanced, party-based procedural dungeons to the AstralRealms network. A party requests a dungeon blueprint from the lobby; the request is broadcast to the dedicated dungeon servers, one of which generates a fresh instanced world for that blueprint and pulls the party in. Inside the instance the party explores procedurally arranged rooms, fights mobs and a boss for experience and loot, and — once they return to the lobby — the loot and experience they earned are handed to them there.
Two-module architecture
The plugin ships as two separate builds of the same com.astralrealms.dungeons.AstralDungeons main class, each targeting a different tier of the network:
Module |
| Runs on | Depends on | Role |
|---|---|---|---|---|
Bridge |
| Lobby / proxy-facing servers | AstralCore, AstralParty, AstralSync | Owns |
Paper |
| Dedicated dungeon servers | AstralCore, AstralMobs | Owns dungeon generation, gameplay (room population, mob/boss spawning, decorated-pot loot, guidance trail), and per-player reward bookkeeping while a party is inside an instance. |
Both modules are load: POSTWORLD and target api-version: 26.1.2.
Creating a dungeon instance
Because the request fans out to every eligible dungeon server and each one races to reply, capacity is balanced implicitly: only servers with a free instance slot and the blueprint attempt generation at all, and the first one to finish wins. ServerService#findEmptiest(String) exists on the bridge but is not currently called from this flow.
Server discovery (dungeons:servers)
Each dungeon server heartbeats its own state into the shared dungeons:servers Redis cache every 30 seconds (starting 1 second after enable), writing a DungeonServer record: its unique ID, name, current instance count, max-instances, and the set of blueprint IDs it has loaded. The bridge keeps a Caffeine cache of this data (refreshed every minute, 1‑minute repository TTL) and uses it to drive /dungeon create's tab completion — ServerService#availableBlueprints() returns the union of blueprint IDs offered by every server that still has a free instance slot.
Inside the dungeon
Once the party is teleported in, DungeonService#registerPlayer drops each player at the blueprint's spawn room component. From there the gameplay loop is:
Explore the procedurally generated layout — rooms are pasted from schematics and stitched together from the blueprint's start/end/normal/cap room lists. See Dungeon & Room Blueprints.
Fight mobs that spawn as participants walk within a room's detection/activation range; killing one awards the experience configured for that mob ID and rolls its loot table. See Loot & Rewards.
Smash decorated pots scattered through the instance for a chance at loot from the blueprint's
potsloot table; each pot holds a few rewards before it breaks.Reach and defeat the boss, spawned once a participant comes within activation range of the blueprint's boss location — killing it ends the instance with cause
WON(an instance also ends early, with causeNO_ALIVE_PARTICIPANTS, if every participant dies or disconnects). See Dungeon Instances for the full lifecycle and state machine.
Instances are looked up and keyed three ways at once — by party ID, by world, and by player ID — so gameplay listeners (mob kills, pot interactions, player movement) can resolve "which dungeon is this?" from whichever context they fire in.
Reward carry-over
Rewards are not granted directly in the dungeon; they accumulate on a per-player DungeonPlayerData (experience total + a set of queued command strings) and are claimed back on the lobby:
On join, if the player's party has an active instance, the dungeon server adds an empty
DungeonPlayerDatato its in-memory cache for that player.Killing mobs adds to
experience; picking up a loot item that carries commands (dropped by mob kills or pots) cancels the pickup and instead adds those commands to the player's queuedcommands.On quit (including the forced kick after an instance ends), the dungeon server flushes the player's data to the
dungeons:players_data:<uuid>Redis key and drops it from its own cache.Back on the lobby, once AstralSync fires
PlayerDataLoadedEventfor the player, the bridge'sPlayerDataService#claimRewardsreads that key, runs the configuredreward-actions(aPaperActionList, with the data exposed as%data_experience%via the player's placeholder container), dispatches any queued commands from the console, and deletes the Redis entry.
Feature map
Area | Page |
|---|---|
Dungeon & room blueprints, generation | |
Mob/pot loot tables, reward carry-over | |
Instance lifecycle, state machine, timeouts | |
| |
| |
Placeholders exposed by the plugin |
Requirements
Dependency | Required by | Notes |
|---|---|---|
AstralCore | Both modules | Configuration, messaging, cache, placeholder framework, |
AstralParty | Bridge | A party is required to create an instance ( |
AstralSync | Bridge | Fires |
AstralMobs | Paper | Spawns room/boss mobs and resolves a killed entity back to its |
RabbitMQ | Both modules | Backs |
Redis | Both modules | Backs |