Overview
AstralSkill is the shared skill-scripting engine for AstralRealms — a YAML-driven DSL that defines the skill file format and provides the runtime for executing skills. The plugin ships no gameplay content of its own; instead, it is consumed by other products (AstralClasses for ability triggers, AstralMobs for mob attacks) that reference skills by id and cross-link to the skill documentation.
What is a skill?
A skill is one YAML file in the skills/ folder with a structure defined by the WrappedSkill record:
Field | Type | Description |
|---|---|---|
| String | Unique identifier for the skill (the id field, not the filename, is the skill key) |
| Root enum | Skill category: |
| Type enum | Skill implementation: one of six hardcoded types (see Cast Types) |
| Set[String] | Custom classification tags (e.g., |
| RequirementList | Optional list of conditions that must pass before the skill can be cast |
| YAML Object | Type-specific parameters (projectile velocity, impact radius, dummy payload, etc.) |
| Effect[] | Effects applied to the caster when the skill is cast |
| Effect[] | Effects applied to entities hit by the skill |
Example: fire-spark skill
The six skill types
Skills are categorized by implementation. Each type has a fixed structure and behavior pattern:
Type | Purpose |
|---|---|
| Inert skill that applies cast/target effects but does not interact with the world |
| Periodically self-triggers on an interval (no player cast required) |
| Rotates through a sequence of skills in order |
| Launches moving projectile(s) with collision detection and visual display |
| Fires continuous beam with line-of-sight targeting and hit detection |
| Instant area-of-effect damage/healing applied at a target location |
See Cast Types for the full config specification of each type.
Loading and initialization
Skills are loaded from the plugin's skills/ folder and all its subfolders recursively, regardless of nesting depth. The loading flow is:
Discovery —
SkillService.smartLoad()(called during plugin enable and on/skill reload) scansskills/and deserializes all.ymlfiles intoWrappedSkillinstancesIndexing — Each skill is indexed by its
idfield (not filename); duplicate ids overwrite silentlyInitialization — Each skill's
init()method parses itsparamsinto the concreteSkillsubclass matching itstype, and loads effectsThread startup — Shard update loops begin processing active skill instances
Errors during initialization are logged per skill and do not halt plugin startup; the failed skill simply becomes unavailable at runtime.
Async execution: sharded update engine
Skills run on a multi-threaded shard architecture, not the main Bukkit thread:
Shard count — Configurable via
skill-service.threadsinconfig.yml(default: ⌊CPU cores / 2⌋, minimum 1)Routing — Each caster (entity) is routed to a fixed shard by their UUID hash, ensuring thread safety without locks
Budget — Each shard has a 1ms per-tick budget; ticks exceeding this threshold are logged (tuned by
skill-service.warn-threshold-msandskill-service.warn-min-overrun-percent)Metrics — Access performance counters via
/skill metrics, which reports per-shard tick counts, overruns, peak latency, and active skill counts
Skill composition and chaining
Skills can trigger other skills through chaining:
Projectile/Laser — Cast another skill on entity hit (
cast-skill-on-entity) or on block hit (cast-skill-on-block)Impact — Cast another skill on hit (
cast-skill-on-hit) or on miss (cast-skill-on-miss)N_cast — Automatically rotate through a sequence of skills, stepping through them on each cast
Auto_cast — Periodically auto-trigger on an interval configured in params
Placeholder-driven values
Most numeric/string/boolean fields in params and effect params are PlaceholderWrapper values, so they accept either a literal (velocity: 1.0) or a placeholder expression (velocity: "%level% * 0.5") that is resolved at cast time against the PlaceholderContainer passed into the cast call. If the caster is a Player and no container is supplied, AstralCore builds a player-scoped container automatically (e.g. %player_name%); consumers such as AstralClasses or AstralMobs can register their own custom placeholders (e.g. %level%) into that container before casting.
Some example skill files under skills/ also carry a top-level placeholders: map (e.g. level: 1). This key has no corresponding field on the skill schema, so it is not parsed or resolved by AstralSkill — it has no effect on skill behavior.
Public API
Other plugins access the skill runtime through the SkillAPI static facade:
See Developer API for the full service interface.
Quick navigation
Topic | Link |
|---|---|
Skill file structure and loading | |
The six skill types and their params | |
Target filters and selection | |
Effect types and configuration | |
Display (particles, sounds, visuals) | |
Hitbox shapes for collision detection | |
Configuration and plugin settings | |
Commands for debugging and metrics | |
Integrating skills in custom plugins |