Skip to main content

Cooldowns

Package: dev.anchorlight.stonelib.cooldown

CooldownService tracks cooldowns as player, then key, then expiry time. One service holds every cooldown a plugin has, whether that is an ability, a command, or a toggle, without a map per feature.

Example

CooldownService cooldowns = new CooldownService("myplugin.cooldown.bypass");

public void dash(Player player) {
if (!cooldowns.tryUse(player, "dash", Duration.ofSeconds(10))) {
messages.sendNamed(player, "on_cooldown",
"time", Durations.human(cooldowns.remaining(player.getUniqueId(), "dash")));
return;
}
player.setVelocity(player.getLocation().getDirection().multiply(1.5));
}

API

MethodMeaning
new CooldownService()No bypass permission.
new CooldownService(String bypassPermission)Players holding this node skip every cooldown in tryUse.
tryUse(Player, String key, Duration)The main entry point. Returns true and starts the cooldown if the action is allowed, or false if still cooling down. A bypassing player always gets true and no cooldown is recorded. A null player gets false.
isOnCooldown(UUID, String key)Whether a cooldown is still running.
remaining(UUID, String key)Time left as a Duration, zero if none.
remainingMillis(UUID, String key)Time left in milliseconds, 0 if none.
apply(UUID, String key, Duration)Starts or restarts a cooldown. A null or non-positive duration does nothing.
applyMillis(UUID, String key, long millis)As above, in milliseconds.
clear(UUID, String key)Ends one cooldown early.
clearAll(UUID)Ends every cooldown for a player.
clearEverything()Ends every cooldown for everyone. For reloads.
canBypass(Player)Whether a bypass permission is set and the player holds it.
snapshot(UUID)Every running cooldown for a player, as key to milliseconds left. For a status command.

Behaviour to know about

  • Memory only. Cooldowns do not survive a restart or a plugin reload. If a cooldown must persist, such as a daily reward, store the expiry yourself.
  • Not shared between servers. Each server has its own service. A cooldown on the hub does not apply on survival.
  • Nothing to clean up. Expired entries are dropped the next time they are read. There is no task to schedule. clearAll on quit is optional, and only worth it if players rarely return.
  • Thread-safe. Backed by concurrent maps, so it can be read from async code. tryUse checks the bypass permission, which should stay on the main thread.
  • Check-then-apply is only atomic in tryUse. Calling isOnCooldown and then apply yourself leaves a gap where two quick uses can both pass. Prefer tryUse.