From 7634694b2e81f7663c5ffdade0df9561ce852eb7 Mon Sep 17 00:00:00 2001 From: Laurin Date: Mon, 1 Dec 2025 19:35:33 +0100 Subject: [PATCH] Added AbilityHitListener.kt --- .../speedhg/ability/AbilityContext.kt | 58 +++++++++++++++++++ .../speedhg/ability/AbilityHitListener.kt | 36 ++++++++++++ .../mcscrims/speedhg/ability/AbilityResult.kt | 18 ++++++ .../speedhg/ability/CooldownManager.kt | 50 ++++++++++++++++ .../speedhg/ability/HitCounterManager.kt | 41 +++++++++++++ 5 files changed, 203 insertions(+) create mode 100644 src/main/kotlin/club/mcscrims/speedhg/ability/AbilityContext.kt create mode 100644 src/main/kotlin/club/mcscrims/speedhg/ability/AbilityHitListener.kt create mode 100644 src/main/kotlin/club/mcscrims/speedhg/ability/AbilityResult.kt create mode 100644 src/main/kotlin/club/mcscrims/speedhg/ability/CooldownManager.kt create mode 100644 src/main/kotlin/club/mcscrims/speedhg/ability/HitCounterManager.kt diff --git a/src/main/kotlin/club/mcscrims/speedhg/ability/AbilityContext.kt b/src/main/kotlin/club/mcscrims/speedhg/ability/AbilityContext.kt new file mode 100644 index 0000000..8cf29cc --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/ability/AbilityContext.kt @@ -0,0 +1,58 @@ +package club.mcscrims.speedhg.ability + +import org.bukkit.entity.Player + +class AbilityContext( + private val cooldownManager: CooldownManager, + private val hitCounterManager: HitCounterManager +) { + + fun canUseAbility( + player: Player, + key: String, + requiredHits: Int? = null, + cooldownSeconds: Int? = null + ): AbilityResult { + if (cooldownSeconds != null && cooldownManager.isOnCooldown(player, key)) { + val remaining = cooldownManager.getRemainingSeconds(player, key) + return AbilityResult.onCooldown(remaining) + } + + if (requiredHits != null && !hitCounterManager.hasReachedThreshold(player, key, requiredHits)) { + val missing = hitCounterManager.getRemainingHits(player, key, requiredHits) + return AbilityResult.insufficientHits(missing) + } + + if (requiredHits != null) { + hitCounterManager.resetHits(player, key) + } + + if (cooldownSeconds != null) { + cooldownManager.startCooldown(player, key, cooldownSeconds) + } + + return AbilityResult.success() + } + + fun incrementHit(player: Player, key: String): Int { + return hitCounterManager.incrementHit(player, key) + } + + fun getHits(player: Player, key: String): Int { + return hitCounterManager.getHits(player, key) + } + + fun getRemainingCooldown(player: Player, key: String): Double { + return cooldownManager.getRemainingSeconds(player, key) + } + + fun clearPlayerData(player: Player) { + cooldownManager.clearAllCooldowns(player) + hitCounterManager.clearAllHits(player) + } + + fun clearAll() { + cooldownManager.clearAll() + hitCounterManager.clearAll() + } +} diff --git a/src/main/kotlin/club/mcscrims/speedhg/ability/AbilityHitListener.kt b/src/main/kotlin/club/mcscrims/speedhg/ability/AbilityHitListener.kt new file mode 100644 index 0000000..667ed05 --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/ability/AbilityHitListener.kt @@ -0,0 +1,36 @@ +package club.mcscrims.speedhg.ability + +import org.bukkit.entity.Player +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.entity.EntityDamageByEntityEvent + +class AbilityHitListener(private val abilityContext: AbilityContext) : Listener { + + @EventHandler + fun onEntityDamage(event: EntityDamageByEntityEvent) { + val damager = event.damager + val victim = event.entity + + if (damager !is Player || victim !is Player) { + return + } + + val hitCount = abilityContext.incrementHit(damager, "melee_hit") + + val result = abilityContext.canUseAbility( + player = damager, + key = "example_ability", + requiredHits = 3, + cooldownSeconds = 10 + ) + + if (result.success) { + damager.sendMessage("§aAbility activated! You hit ${victim.name}") + } else if (result.missingHits > 0) { + damager.sendMessage("§e${result.missingHits} more hit(s) needed (Current: ${hitCount})") + } else if (result.remainingCooldown > 0) { + damager.sendMessage("§cAbility on cooldown: ${String.format("%.1f", result.remainingCooldown)}s remaining") + } + } +} diff --git a/src/main/kotlin/club/mcscrims/speedhg/ability/AbilityResult.kt b/src/main/kotlin/club/mcscrims/speedhg/ability/AbilityResult.kt new file mode 100644 index 0000000..734d1b7 --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/ability/AbilityResult.kt @@ -0,0 +1,18 @@ +package club.mcscrims.speedhg.ability + +data class AbilityResult( + val success: Boolean, + val reason: String?, + val remainingCooldown: Double = 0.0, + val missingHits: Int = 0 +) { + companion object { + fun success(): AbilityResult = AbilityResult(true, null) + + fun onCooldown(remaining: Double): AbilityResult = + AbilityResult(false, "Ability is on cooldown", remainingCooldown = remaining) + + fun insufficientHits(missing: Int): AbilityResult = + AbilityResult(false, "Not enough hits", missingHits = missing) + } +} diff --git a/src/main/kotlin/club/mcscrims/speedhg/ability/CooldownManager.kt b/src/main/kotlin/club/mcscrims/speedhg/ability/CooldownManager.kt new file mode 100644 index 0000000..f3cf41d --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/ability/CooldownManager.kt @@ -0,0 +1,50 @@ +package club.mcscrims.speedhg.ability + +import org.bukkit.entity.Player +import java.util.UUID +import java.util.concurrent.ConcurrentHashMap + +class CooldownManager { + + private val cooldowns = ConcurrentHashMap>() + + fun startCooldown(player: Player, key: String, seconds: Int) { + val expiryTime = System.currentTimeMillis() + (seconds * 1000L) + cooldowns.computeIfAbsent(player.uniqueId) { ConcurrentHashMap() }[key] = expiryTime + } + + fun isOnCooldown(player: Player, key: String): Boolean { + val playerCooldowns = cooldowns[player.uniqueId] ?: return false + val expiryTime = playerCooldowns[key] ?: return false + + if (System.currentTimeMillis() >= expiryTime) { + playerCooldowns.remove(key) + if (playerCooldowns.isEmpty()) { + cooldowns.remove(player.uniqueId) + } + return false + } + + return true + } + + fun getRemainingSeconds(player: Player, key: String): Double { + val playerCooldowns = cooldowns[player.uniqueId] ?: return 0.0 + val expiryTime = playerCooldowns[key] ?: return 0.0 + + val remaining = (expiryTime - System.currentTimeMillis()) / 1000.0 + return if (remaining > 0) remaining else 0.0 + } + + fun clearCooldown(player: Player, key: String) { + cooldowns[player.uniqueId]?.remove(key) + } + + fun clearAllCooldowns(player: Player) { + cooldowns.remove(player.uniqueId) + } + + fun clearAll() { + cooldowns.clear() + } +} diff --git a/src/main/kotlin/club/mcscrims/speedhg/ability/HitCounterManager.kt b/src/main/kotlin/club/mcscrims/speedhg/ability/HitCounterManager.kt new file mode 100644 index 0000000..fc21156 --- /dev/null +++ b/src/main/kotlin/club/mcscrims/speedhg/ability/HitCounterManager.kt @@ -0,0 +1,41 @@ +package club.mcscrims.speedhg.ability + +import org.bukkit.entity.Player +import java.util.UUID +import java.util.concurrent.ConcurrentHashMap + +class HitCounterManager { + + private val hitCounts = ConcurrentHashMap>() + + fun incrementHit(player: Player, key: String): Int { + val playerHits = hitCounts.computeIfAbsent(player.uniqueId) { ConcurrentHashMap() } + val newCount = playerHits.compute(key) { _, current -> (current ?: 0) + 1 } ?: 1 + return newCount + } + + fun getHits(player: Player, key: String): Int { + return hitCounts[player.uniqueId]?.get(key) ?: 0 + } + + fun resetHits(player: Player, key: String) { + hitCounts[player.uniqueId]?.remove(key) + } + + fun hasReachedThreshold(player: Player, key: String, requiredHits: Int): Boolean { + return getHits(player, key) >= requiredHits + } + + fun getRemainingHits(player: Player, key: String, requiredHits: Int): Int { + val current = getHits(player, key) + return maxOf(0, requiredHits - current) + } + + fun clearAllHits(player: Player) { + hitCounts.remove(player.uniqueId) + } + + fun clearAll() { + hitCounts.clear() + } +}