Developer API
AstralSkill exposes its casting and lifecycle API through the SkillAPI static façade and the SkillService. Consumers (AstralClasses, AstralMobs, and other plugins) call cast methods with a skill id, a caster entity, and optionally a PlaceholderContainer for custom level/attribute bindings. The skill DSL and configuration are covered in Skill Files and Configuration; this page documents the entry points for programmatic skill casting.
Maven coordinates
Repository: https://maven.astralrealms.fr/repository/maven-public/.
Entry point
SkillAPI.service() returns the SkillService singleton, which gates access to all casting and lookup methods. SkillAPI.targeting() returns the SkillTargetService, the registry for hit-detection rules. Both throw IllegalStateException if the plugin has not enabled yet.
The SkillService singleton If called before the AstralSkill plugin has enabled, it throws IllegalStateException. Callers should guard with a soft dependency (check if AstralSkill is loaded via Bukkit.getPluginManager().getPlugin("AstralSkill")) or defer initialization to a later event.
Casting methods
The three primary cast methods differ in how the target is specified:
castAtPos(…) — direct position cast
Casts a skill at an explicit location and direction. The direction vector is typically normalized (e.g. from a player's eye direction, or a computed path). If container is null and the caster is a Player, a player-aware placeholder container is auto-created via AstralPaperAPI.createPlaceholderContainer(player); otherwise a blank PlaceholderContainer() is used. If the skill id is unknown, a warning is logged and the cast is abandoned.
Before the cast initializes, the skill's PaperRequirementList (if present and the caster is a Player) is evaluated; if requirements fail, the cast is aborted.
Parameters:
caster: The entity triggering the skill (may be a Player, Mob, ArmorStand, etc.).casterUUID: The UUID of the caster; carried through to caster effects and targeting.skillId: The id of the skill file (must match a file underskills/).location: The center/spawn point of the skill (interpreted in the location's world).direction: A velocity/heading vector (typically normalized). For impact skills, points along the terrain normal; for projectiles, defines the launch direction.container: Custom placeholder bindings (e.g.level, custom stats). Ifnulland caster is a Player, a container is auto-built.
castThroughPos(…) — projectile auto-aim
Solves the launch pitch so a projectile skill's simulated arc passes through passLocation. Unlike castAtPos, the caller does not supply a direction; instead the projectile's full trajectory is simulated using its configured velocity, drag, gravity, and range, and the launch pitch is computed. The horizontal heading always points from startLocation toward passLocation.
This only works for projectile skills (see Cast Types). If the skill is not a projectile, or the target cannot be reached (out of range, too much drag, etc.), the cast is aborted with a warning.
When both a direct arc and a lobbed arc can reach the point, the flatter path is preferred.
Skills that enforce a fixed pitch cannot be aimed vertically, so arbitrary heights may not be reachable; in such cases the cast is aborted.
Variant without forceCast: If the target is unreachable, the cast is abandoned.
Variant with forceCast = true: If the target is unreachable, the projectile is still fired along the straight line from startLocation toward passLocation (it simply will not reach the point). This is useful for "best-effort" aiming (e.g. chase/homing skills that should always activate even if the geometry is challenging).
Parameters:
startLocation: Where the projectile spawns; defines the world the cast happens in. IfpassLocationis in a different world, it is re-interpreted in the start location's world and a warning is logged.passLocation: The location the projectile should pass through.container: Custom placeholder bindings. Null-handling is the same ascastAtPos.forceCast: Whentrue, fire along a direct heading if the target is unreachable; whenfalse, abort.
castAtTarget(…) — entity targeting
Resolves an entity on the main thread (via world.getEntity(entityUUID)) and casts at its location. If the entity no longer exists, a warning is logged and the cast is abandoned. Otherwise, delegates to castAtPos(caster, casterUUID, skillId, target.getLocation().clone(), new Vector3d(0.0), container).
Lookup methods
Method | Returns | Use |
|---|---|---|
|
| Resolve a skill by id. Returns a defensive copy. |
|
| Every loaded skill (unmodifiable snapshot). |
findById() returns a defensive copy of the skill, so modifications do not affect the shared state.
Lifecycle control
Active skills are tracked per caster and automatically updated each tick. Consumers rarely call these directly; most lifecycle management happens automatically:
Method | Returns | Use |
|---|---|---|
|
| Register a skill as active (queues it for update). Called internally by cast methods. |
|
| Unregister one active skill instance. |
|
| Unregister a set of skills. |
|
| Deactivate all active skills for a single entity. |
|
| Deactivate all active skills across all casters. Returns a future that completes when all shards have cleared. |
The deactivateAllSkills() variant (no argument) is called during plugin shutdown and reload.
Performance monitoring
metricsSummary() returns a human-readable snapshot of every shard's update-loop performance, including tick counts, overruns, peak timing, and active skill counts. Safe to call from any thread. The output looks like:
Requirement gating
Before a skill cast initializes, if the caster is a Player and the skill has a PaperRequirementList defined in its configuration, the requirements are evaluated. If any requirement fails (e.g. not enough money, cooldown active, level too low), the cast is aborted silently and no effects fire.
See Skill Files for how to define requirements on a skill.
Threading model
AstralSkill uses a fixed pool of shards (update threads) to isolate skill state and avoid lock contention. Each caster is routed to the same shard via hash, so all of its active skills are updated on a single thread.
Utility scheduling
getExecutor() exposes shard 0's scheduled executor for callers that need to schedule utility work (e.g. delayed casts, cooldown timers). Callers must not touch shard state or access active skills from this thread. Only use it for work that does not depend on the skill update loop or shared caster state.
Cast dispatch
Casts are dispatched to the caster's assigned shard. The cast initializes and the skill is queued for updates. Each update tick (1ms budget per shard, across all active skills), the skill's update() method is called; when it returns true, the skill is marked finished and removed from the active set.
Automatic cleanup
The EntityListener deactivates all of a caster's active skills when the entity dies (EntityDeathEvent). The PlayerListener manages chunk snapshots and player-specific caches when players join, change worlds, or quit. As a consumer, you do not need to call cleanup methods when an entity disappears; it happens automatically.
Target rules
SkillAPI.targeting() returns the SkillTargetService: the registry a plugin uses to say which entities skills may hit, and — optionally — which entities are worth tracking at all. A plugin holds at most one of each; registering again replaces what it registered before.
Method | Purpose |
|---|---|
| A rule deciding whether a particular entity may be hit. |
| The entities this plugin wants reachable by skills. |
| Drops both — its entities become ordinary skill targets again. |
| Whether every registered filter allows the hit. |
| Whether any plugin has handed over a list of entities. |
SkillTargetFilter
Where a skill's targets: answers "which kinds of entity does this skill hit", a filter answers "may this particular entity be hit by a skill at all" — something the configuration cannot express, since it only compares entity types. AstralMobs uses it to keep pets out of hit detection entirely: an owned pet shares its server-side type with every other mob of that species.
Returning false hides the entity from other casters' hit detection — no damage, no knockback, no effects, and projectiles pass straight through it instead of stopping. Its owner's own self-targeted skills still reach it.
SkillTargetSource
Where a filter narrows what the sweep already found, a source replaces the search. With caches.entities.registered-targets-only on, the entity cache stops walking every living entity in every world each tick and tracks only the players plus whatever the registered sources hand it.
Called once per tick on the main thread while the snapshot is rebuilt, so it should hand back a live view of a registry the plugin already keeps — not a fresh world search. Entities returned still go through every registered filter, so a source may safely include entities its own filter then hides (pets being the obvious case). A source that throws contributes nothing and is reported once, the same as a broken filter.
Events
SkillDamageEvent
Fully qualified name: com.astralrealms.skill.event.SkillDamageEvent (extends Event, implements Cancellable).
Fired on the main thread right before a skill damages an entity, and only for a skill that declares a damage-type. A skill without one damages as it always has, without firing anything.
The damage type is whatever string the skill's damage-type resolved to — not a Bukkit DamageType, and the engine gives it no meaning of its own. It exists so other plugins can key their own rules (resistances, immunities, shields) off it.
Field | Type | Description |
|---|---|---|
|
| The skill dealing the damage. |
|
| The entity credited with the cast, or |
|
| The entity about to be damaged. |
|
| The resolved |
|
| The damage about to be dealt. Settable; |
Cancelling skips the damage entirely: no EntityDamageEvent is fired for it and the target is left untouched. The rest of the impact — knockback, effects — is unaffected, as those are applied independently.
Integration pattern
AstralClasses and AstralMobs call the cast methods directly with a skill id and optional custom PlaceholderContainer. They do not re-implement the skill DSL — they rely on this API to execute skills.
Example from a class ability:
For skill DSL details (cast types, targeting, effects, displays, hitbox shapes), see:
Skill Files — the overall structure and config schema.
Cast Types —
projectile,impact,laser,auto-cast,n-cast.Targeting — collision detection and entity selection.
Effects — caster/target effect pipeline.
Displays — visual rendering (particles, sounds).