Abilities & Input
Overview
This page documents how player input maps to abilities and how abilities trigger AstralSkill skills. This is not a guide to the skill DSL — see AstralSkill for what skills do once they are cast. This page covers:
Input types and how they are captured from player packets and events.
How input resolves to an ability in the player's selected subclass.
The binding layer: per-player input rebinding and force-binding settings.
Cooldown calculation and scaling.
Auto-attack toggling.
Trigger throttling to prevent simultaneous casts.
Weak-hit cancellation (vanilla melee suppression).
Gating by skill enablement group.
Input Types
InputType is an enum of the valid player inputs AstralClasses can bind abilities to:
Input | Triggered by | Notes |
|---|---|---|
| Attack key (main hand) | Fired by: packet-based START_DIGGING, ANIMATION, and INTERACT_ENTITY ATTACK events. Also fired by auto-attack toggle. |
| Use key (main hand) | Fired by: packet-based USE_ITEM (main hand only) and INTERACT_ENTITY non-ATTACK interaction. |
| Drop key | Fired by: PLAYER_DIGGING DROP_ITEM or DROP_ITEM_STACK packets. Suppresses same-tick ANIMATION LEFT_CLICK. |
| Jump key | Buffered (rising-edge detection). Trigger fires only on jump press, not on hold. Also drives Double Jump. |
| Sneak key (shift) | Buffered (rising-edge detection). Trigger fires only on sneak toggle, not on hold. |
| Swap hands key | Fired by: Bukkit |
| Hotbar slots 1–8 | Enum-only. Not currently wired to packet listeners. |
Input Capture
Player inputs flow through InputPacketListener (using PacketEvents) and SkillTriggerListener (using Bukkit events):
Packet-based inputs (via InputPacketListener):
USE_ITEM packet →
RIGHT_CLICK(main hand only).PLAYER_DIGGING packet:
START_DIGGING→LEFT_CLICK.DROP_ITEMorDROP_ITEM_STACK→DROP(also records trigger to block same-tick ANIMATION).
PLAYER_INPUT packet →
SPACEandSNEAK(buffered byInputBufferto detect rising edge).INTERACT_ENTITY packet:
ATTACKaction →LEFT_CLICK.Non-ATTACK action →
RIGHT_CLICK.Packet is cancelled to prevent vanilla processing.
ANIMATION packet (main hand) →
LEFT_CLICK(unless DROP trigger was just recorded, in which case it is skipped).
Event-based input (via SkillTriggerListener):
PlayerSwapHandItemsEvent →
SWAP_HANDS.
Input buffering (SPACE and SNEAK):
InputBuffer detects state changes for SPACE (jump) and SNEAK (shift). A trigger fires only on a false→true transition (key press), not on hold or release. This prevents repeated triggers from a single long press. All other input types always trigger immediately.
Ability Resolution
When a player presses an input, SkillService.tryTriggerSkill looks up which ability to cast:
Check the player's per-input input bindings override (
ClassPlayerData.inputBindings): a map ofInputType→ ability id.If no override exists, pick the subclass ability whose
default-inputmatches the input.If no ability is found, the trigger is ignored.
The matched ability yields a list of 5 values:
skillId (String): The underlying AstralSkill skill id to cast.
cooldown (long): Base cooldown in milliseconds (after attack-speed scaling — see Cooldowns).
classLevel (int): Player's current class level.
skillLevel (int): Unlocked skill level for this ability (0 if not unlocked).
boosted (boolean): Whether the ability is boosted (per-class unlock system).
These are passed as placeholders to the skill during cast.
Input Bindings
Each player's inputBindings map (in ClassPlayerData) can override the default input for any ability. This is persisted across sessions. The force-input-binding flag on an ability controls whether its input binding is:
true (forced): Players cannot rebind this ability to a different input.
false (rebindable): Players can reassign it via the binding system (exact command/UI not documented here; see Commands).
The default out-of-box binding is default-input in the class configuration.
Example: In the Mage class (mage.yml), the ability attack-1 has default-input: LEFT_CLICK and force-input-binding: true, so players cannot rebind it.
Cooldowns
Cooldown Formula
When an ability is triggered, its base cooldown (from the ability config, in milliseconds) is scaled by the player's ATTACK_SPEED stat:
The attackSpeed is looked up per InputType via StatsAPI.stat(player, "astralstats:attack_speed", inputType). A player with attackSpeed = 1.0 sees no cooldown change. A player with attackSpeed = 1.5 triggers abilities 1.5× faster (cooldown is 1 ÷ 1.5 of the base).
Cooldown Tracking
CooldownManager records a timestamp when an ability is used and checks it on the next trigger. The player may not trigger the same ability again until the cooldown has elapsed.
Cooldown Placeholders
The remaining cooldown time for a specific ability is exposed via:
%classes_cooldown_<ability-id>%: Remaining cooldown in seconds (rounded up). Returns0if not on cooldown.%classes_cooldown_<ability-id>_max%: Maximum (base) cooldown of the ability in seconds.
For example, %classes_cooldown_attack-1% returns the remaining cooldown for the attack-1 ability.
See Placeholders for a full list.
Auto-Attack Toggle
Players can toggle auto-attack with the /class toggle command (see Commands). When enabled:
An async 50 ms loop (
SkillService.processToggle) repeatedly firesLEFT_CLICKtriggers.This causes the player's primary ability (bound to LEFT_CLICK in the selected subclass) to auto-cast at the loop's cadence (50 ms ≈ 20 ticks/sec), subject to cooldown.
The toggle state is persisted in ClassPlayerData.classSettings.toggleAutoAttack. You can check the current state via the placeholder:
%classes_toggle%: Boolean (true if auto-attack is enabled).
Trigger Throttling
SkillTriggerManager enforces a minimum of 1 server tick between ability triggers per player to prevent simultaneous skill casts when multiple packets arrive in the same tick (e.g., LEFT_CLICK and RIGHT_CLICK pressed together).
The tick counter increments every 50 ms asynchronously and is checked when canTrigger() is called. If the player triggered an ability within the minimum interval, the new trigger is rejected.
Special case: When a player presses DROP, the trigger is recorded immediately, which suppresses any ANIMATION packet (LEFT_CLICK) in the same tick.
Casting
When all checks pass (skill enabled for group, input resolved to an ability, not on cooldown, throttle allows), SkillService calls the skill:
Captures the player's eye location (with a +0.15 Y offset) and view direction.
Creates a
PlaceholderContainerand registers the ability'sclass-level,skill-level, andboostedas direct placeholders.Calls
SkillAPI.service().castAtPos(player, uuid, skillId, eyeLocation, direction, container)asynchronously.
The skill is cast at the player's eye position and direction, with class/skill level and boost status available to the skill DSL. See AstralSkill for skill execution semantics.
Weak-Hit Cancellation
SkillTriggerListener monitors EntityDamageByEntityEvent damage caused by players (melee hits). Any damage event where the damage value is less than 2.0 is cancelled. This suppresses weak vanilla melee hits so ability-driven combat is not muddied by incidental unarmed damage.
Enablement Gating
Input processing is gated by the configuration flag skill-enable-groups. If the player's group is not in this list, all input triggers are rejected before ability resolution. This allows disabling the ability system for certain groups without losing other class features (e.g., stats, level progression, etc.).
Check Configuration for the skill-enable-groups key and how to set it.
Example Configuration
From mage.yml (excerpt):
This class defines three abilities:
attack-1: LEFT_CLICK, 350 ms cooldown (forced binding).
attack-2: RIGHT_CLICK, 1000 ms cooldown (forced binding).
attack-3: SWAP_HANDS, 5000 ms cooldown (rebindable).
Each maps to an underlying skill (e.g., mage-attack-1-laser) that handles the actual effect. See AstralSkill to learn what these skills do.
Related Pages
Classes — Class configuration and structure.
AstralSkill — Skill DSL and execution (separate product).
Commands —
/class toggleand other commands.Placeholders — Full placeholder reference including
%classes_toggle%and%classes_cooldown_*%.Double Jump — SPACE input handling for double-jump.