Astral Realms Documentation Help

Classes

A class is a single YAML file in plugins/AstralClasses/classes/ (sub-folders are scanned recursively) that defines a playable class: its display name, weapon, progression curve, abilities, and subclass-specific actions (stat modifiers and effects applied on join).

Each file is deserialized directly into an AstralClass object, keyed by its id.

Minimal example

id: "knight" name: "<bold><primary_color>Knight" weapon-item: material: "turtle_scute" item-model: "tower:knight_sword" name: "<green>Steel Sword" lore: - "A reliable melee weapon." weapon-display: material: "turtle_scute" item-model: "tower:knight_sword_display" name: "<green>Steel Sword" experience-to-level-up: 150 sub-classes-abilities: default: - id: attack-1 name: "Slash" info: "A quick melee strike." display-damage: "50" skill-id: knight-attack-1 unlockable-levels: [1, 2, 3] unlockable-boost-level: 5 cooldown: 600 default-input: LEFT_CLICK force-input-binding: true sub-classes-actions: default: - "[console] stats modifiers add %player_name% class astralstats:max_health FLAT 180" - "[console] stats resource add %player_name% shield 180"

Top-level fields

Field

Type

Required

Description

id

String

Yes

Class identifier. Used as the lookup key in commands, menus, and player data.

name

MiniMessage

Yes

Display name of the class, shown in menus and selection UIs.

weapon-item

ItemStackWrapper

Yes

The equippable weapon item — matched back to a class via ClassService.findByWeaponItem().

weapon-display

ItemStackWrapper

Yes

Cosmetic item shown in the class selection menu (decoupled from the actual weapon).

experience-to-level-up

int or PlaceholderWrapper

Yes

XP required to reach each level. Supports class-level/skill-level/boosted context.

sub-classes-abilities

Map<String, List<SkillEntry>>

Yes

Map of subclass id → list of abilities for that subclass. Every class must have a default subclass.

sub-classes-actions

Map<String, PaperActionList>

No

Map of subclass id → actions run on player join for that subclass (stat modifiers, effects, etc.).

Weapon item and display

weapon-item is the actual ItemStack a player carries when they select this class. It is matched back to the class via ClassService.findByWeaponItem(ItemStack) — internally, this comparison uses ItemStackUtils.areSimilar(), which requires the same material and then falls back to a full ItemMeta equality check (persistent data, custom model data, enchantments, name, lore, and any other meta fields all have to match).

weapon-display is a separate cosmetic item shown only in the class selection menu. This decoupling allows the menu to show a distinct visual representation without forcing players to hold an identical item.

Both fields use the standard ItemStackWrapper from AstralCore: material, item-model, name, lore, enchantments, custom-model-data, durability, glow, etc. See Menu Items for the full schema.

Experience and progression

experience-to-level-up is the XP required to progress to each successive level. It is stored as a PlaceholderWrapper<Integer>, which allows the value to be a literal integer or a placeholder expression that resolves with context:

experience-to-level-up: 150 # literal experience-to-level-up: "%xp_for_level%" # placeholder

When a player gains experience, the placeholder is resolved with context including class-level, skill-level, and boosted flags.

Subclasses and abilities

Subclasses are alternate ability sets within a single class. Every class ships a default subclass, and players fall back to default unless they explicitly select another one (stored in ClassProgressData.selectedSubClassId).

sub-classes-abilities is a map of subclass id → list of SkillEntry objects. Each entry defines one ability a player can unlock and use:

Field

Type

Required

Description

id

String

Yes

Ability identifier (e.g. attack-1). Unique within the class but displayed to users.

name

MiniMessage

Yes

Display name shown in menus (e.g. "Slash").

info

MiniMessage

No

Description or flavor text shown in ability tooltips.

display-damage

MiniMessage

No

Cosmetic damage range or formula shown in menus (e.g. "50 / 75" or "50 + 10 per level"). Display-only; actual damage comes from the skill.

skill-id

String

Yes

ID of the underlying AstralSkill that executes when this ability is triggered. Must reference a loaded skill.

unlockable-levels

List\<int\>

Yes

Class levels at which this ability unlocks (e.g. [1, 2, 3] unlocks at levels 1, 2, and 3).

unlockable-boost-level

int

Yes

Class level at which a boosted version of this ability becomes available.

cooldown

long (ms) or PlaceholderWrapper

Yes

Cooldown in milliseconds between casts. Supports context: class-level, skill-level, boosted.

default-input

InputType

No

The input binding that triggers this ability by default (e.g. LEFT_CLICK). See Abilities & Input.

force-input-binding

boolean

No

If true, the player cannot rebind this ability to another input. Defaults to false.

Ability example

sub-classes-abilities: default: - id: attack-1 name: "Decisive Blow" info: "Strike with your sword; every 3 hits, gain a small damage boost." display-damage: "50 / 50 / 75" skill-id: knight-attack-1-cast unlockable-levels: [1, 2, 3] unlockable-boost-level: 5 cooldown: 600 # 600ms base cooldown default-input: LEFT_CLICK force-input-binding: true

Cooldown context: When a player triggers an ability, the cooldown is resolved with a PlaceholderContainer populated with:

  • class-level: the player's current class level

  • skill-level: the player's level in that specific ability (from ClassProgressData.skillLevels)

  • boosted: whether the ability is currently in boosted state (from ClassProgressData.boostedSkills)

This allows cooldowns to scale with progression:

cooldown: "%skill_level% * 100" # 100ms per skill level

Subclass actions

sub-classes-actions is a map of subclass id → PaperActionList executed when a player joins (or logs in with that subclass active). Actions are registered in PlayerListener#onPlayerJoin() and run immediately after the player's data loads.

Typical use: applying stat modifiers (via AstralStats) and status effects:

sub-classes-actions: default: - "[console] stats modifiers add %player_name% class astralstats:max_health FLAT 180" - "[console] effect give %player_name% minecraft:instant_health 1 200 true" - "[console] stats resource add %player_name% shield 180"

Actions use AstralCore's action DSL — see Actions for the full catalogue. Every action receives access to player placeholders (%player_name%, etc.).

Full example: Knight class

id: "knight" name: "<bold><primary_color>Classe Chevalier" weapon-item: material: "turtle_scute" item-model: "tower:knight_sword" name: "<green> Steel Sword" lore: - "" - " <color:#FFAA33>Combattant de renom, ce chevalier se dresse sans crainte" - " <color:#FFAA33>pour protéger le peuple des plus viles créatures." weapon-display: material: "turtle_scute" item-model: "tower:knight_sword_display" name: "<green> Steel Sword" lore: - "" - "<secondary_color><bold>| Caractéristiques" - " <secondary_color>Vie: <text_color>200" - " <secondary_color>Bouclier: <text_color>300" experience-to-level-up: 150 sub-classes-abilities: default: - id: attack-1 name: "Coup Désisif" info: "Frappe avec ton épée ; tout les 3 coups, profite d'un petit boost de dégâts." display-damage: "50 / 50 / 75" skill-id: knight-attack-1-cast unlockable-levels: [1, 2, 3] unlockable-boost-level: 5 cooldown: 600 default-input: LEFT_CLICK force-input-binding: true - id: attack-2 name: "Impulsion" info: "Fonce vers l'avant en infligeant des dégâts et vous rends du 40 bouclier." display-damage: "100" skill-id: knight-attack-3-impact unlockable-levels: [1, 2, 3] unlockable-boost-level: 5 cooldown: 5000 default-input: RIGHT_CLICK force-input-binding: true sub-classes-actions: default: - "[console] clear %player_name%" - "[console] stats modifiers add %player_name% class astralstats:max_health FLAT 180" - "[console] effect give %player_name% minecraft:instant_health 1 200 true" - "[console] stats modifiers add %player_name% class astralstats:max_shield FLAT 290" - "[console] stats resource add %player_name% shield 290"

Loading and resolution

Class files are loaded by ClassService.load(), which:

  1. Recursively scans plugins/AstralClasses/classes/ for .yml/.yaml files (via AstralCore's ConfigurationManager.loadFolder()).

  2. Deserializes each file as an AstralClass.

  3. Registers each class by its id in an internal map.

No skill-id validation at load time. skill-id is a plain string field — AstralClasses does not load or index AstralSkill's skill files itself, so it cannot verify at class-load time that a referenced skill actually exists. An ability whose skill-id doesn't resolve to a real AstralSkill skill will simply fail to cast (or no-op) the first time a player triggers it.

Per-file error isolation: loadFolder() catches deserialization exceptions per file and logs Failed to load configuration file: <path> without aborting the rest of the scan — so a malformed class file (missing required fields, invalid YAML, etc.) does not prevent other classes from loading.

Hot reload

/class reload (requires class.command.reload permission) re-reads every class file from disk and rebuilds the class registry, alongside the double-jump config, menus, and the weapon item supplier. Player data is preserved.

Integration: menus and placeholders

The classes selection menu (see Configuration) renders all classes and their abilities. It queries the class registry via ClassService.all() and exposes ability lore by chaining through the classes/class/skill-entry placeholder namespaces (e.g. %classes_class_raw% bound to a variable, then %variables_selected_skill-entry_attack-1_name%). See Placeholders for the complete placeholder API.

When a player equips a class, the equip-class action updates their ClassPlayerData.selectedClassId (after confirming the class is in unlockedClassIds) — it does not itself give the weapon-item to their inventory. The classes.weapon itemstack supplier (registered via WeaponClassItemSupplier) makes each class's weapon resolvable by class id for menus and [give-item]-style actions to hand out explicitly. See Actions for the full equip-class behavior.

Cross-product: skills

Each ability references an underlying AstralSkill skill (by skill-id). The skill DSL defines the actual behavior — damage, projectiles, effects, etc. — and is documented separately at Skills (AstralSkill). Classes do not define skill behavior; they only consume skills by id and wrap them with unlock levels, cooldowns, and input bindings.

The display-damage, name, and info fields are cosmetic labels for menus; they do not affect the skill's runtime behavior.

See also

  • Configuration — main class configuration file and menu setup.

  • Installation — plugin setup and dependencies.

  • Placeholders — all available player/class/ability placeholders for menus.

  • Abilities & Input — input types and how ability triggers work.

  • Commands — class-related commands (reload, toggle, reset, modifier).

  • Developer API — programmatic class access and player progression.

Last modified: 25 July 2026