feat: Add Cooldown utility and integrate into Blink, Double Jump, and Grappling Hook.
This commit is contained in:
parent
e5d89e41b6
commit
9cc0e03c10
|
|
@ -20,6 +20,9 @@ import java.util.UUID
|
|||
import java.util.concurrent.ConcurrentHashMap
|
||||
import org.bukkit.potion.PotionEffect
|
||||
import org.bukkit.potion.PotionEffectType
|
||||
import net.hareworks.hcu.items.util.Cooldown
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
|
||||
class BlinkComponent(private val plugin: App) : AbstractComponent(plugin, "blink_component"), EquippableComponent {
|
||||
|
||||
|
|
@ -32,6 +35,7 @@ class BlinkComponent(private val plugin: App) : AbstractComponent(plugin, "blink
|
|||
companion object {
|
||||
// Track players who have used their blink (GLIDER is removed until landing)
|
||||
private val usedBlink = ConcurrentHashMap.newKeySet<UUID>()
|
||||
private val cooldown = Cooldown(1500)
|
||||
|
||||
// Color scheme - Purple/Magenta for teleport/blink theme
|
||||
private val PRIMARY_COLOR = TextColor.color(0xDA70D6) // Orchid
|
||||
|
|
@ -67,8 +71,14 @@ class BlinkComponent(private val plugin: App) : AbstractComponent(plugin, "blink
|
|||
}
|
||||
|
||||
// Landing feedback
|
||||
}
|
||||
|
||||
// Check for cooldown finish
|
||||
if (cooldown.checkFinished(player)) {
|
||||
showReadyMessage(player)
|
||||
player.playSound(player.location, Sound.BLOCK_NOTE_BLOCK_BELL, 0.5f, 1.5f)
|
||||
// Allow re-use immediately
|
||||
usedBlink.remove(player.uniqueId)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +98,13 @@ class BlinkComponent(private val plugin: App) : AbstractComponent(plugin, "blink
|
|||
event.isCancelled = true
|
||||
return
|
||||
}
|
||||
|
||||
// Check cooldown
|
||||
if (!cooldown.checkAndWarn(player)) {
|
||||
item.unsetData(DataComponentTypes.GLIDER)
|
||||
event.isCancelled = true
|
||||
return
|
||||
}
|
||||
|
||||
// Cancel the glide start
|
||||
event.isCancelled = true
|
||||
|
|
@ -95,6 +112,9 @@ class BlinkComponent(private val plugin: App) : AbstractComponent(plugin, "blink
|
|||
// Mark as used
|
||||
usedBlink.add(player.uniqueId)
|
||||
|
||||
// Start cooldown immediately
|
||||
cooldown.start(player)
|
||||
|
||||
// Execute Blink
|
||||
handleBlink(player, item)
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ import org.bukkit.inventory.ItemStack
|
|||
import org.bukkit.util.Vector
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import net.hareworks.hcu.items.util.Cooldown
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
|
||||
class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "double_jump_component"), EquippableComponent {
|
||||
|
||||
|
|
@ -31,6 +34,7 @@ class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "
|
|||
companion object {
|
||||
// Track players who have used their double jump (GLIDER is removed)
|
||||
private val usedDoubleJump = ConcurrentHashMap.newKeySet<UUID>()
|
||||
private val cooldown = Cooldown(1500)
|
||||
|
||||
// Color scheme
|
||||
private val PRIMARY_COLOR = TextColor.color(0x7DF9FF) // Electric Cyan
|
||||
|
|
@ -67,6 +71,10 @@ class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "
|
|||
}
|
||||
|
||||
// Landing feedback
|
||||
}
|
||||
|
||||
// Check for cooldown finish
|
||||
if (cooldown.checkFinished(player)) {
|
||||
showReadyMessage(player)
|
||||
player.playSound(player.location, Sound.BLOCK_NOTE_BLOCK_CHIME, 0.5f, 1.5f)
|
||||
}
|
||||
|
|
@ -89,6 +97,13 @@ class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "
|
|||
event.isCancelled = true
|
||||
return
|
||||
}
|
||||
|
||||
// Check cooldown
|
||||
if (!cooldown.checkAndWarn(player)) {
|
||||
item.unsetData(DataComponentTypes.GLIDER)
|
||||
event.isCancelled = true
|
||||
return
|
||||
}
|
||||
|
||||
// Cancel the glide start
|
||||
event.isCancelled = true
|
||||
|
|
@ -98,6 +113,7 @@ class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "
|
|||
|
||||
// Execute Double Jump
|
||||
handleDoubleJump(player, item)
|
||||
cooldown.start(player)
|
||||
|
||||
// Remove GLIDER component to prevent further glide triggers
|
||||
item.unsetData(DataComponentTypes.GLIDER)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,9 @@ import org.bukkit.Location
|
|||
import org.bukkit.Material
|
||||
import org.bukkit.event.player.PlayerFishEvent
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import net.hareworks.hcu.items.util.Cooldown
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
|
||||
class GrapplingItem : AbstractItem("grappling_hook") {
|
||||
|
||||
|
|
@ -49,6 +52,11 @@ class GrapplingItem : AbstractItem("grappling_hook") {
|
|||
val isStuck = hook.persistentDataContainer.has(KEY_HOOK_STUCK, org.bukkit.persistence.PersistentDataType.BYTE)
|
||||
|
||||
if (event.state == PlayerFishEvent.State.REEL_IN && isStuck) {
|
||||
if (!cooldown.checkAndWarn(player)) {
|
||||
return
|
||||
}
|
||||
cooldown.start(player)
|
||||
|
||||
val playerLoc = player.location
|
||||
val hookLoc = hook.location
|
||||
|
||||
|
|
@ -236,5 +244,6 @@ class GrapplingItem : AbstractItem("grappling_hook") {
|
|||
companion object {
|
||||
val KEY_HOOK_STUCK = org.bukkit.NamespacedKey("hcu_items", "hook_stuck")
|
||||
val KEY_ANCHOR_ID = org.bukkit.NamespacedKey("hcu_items", "anchor_id")
|
||||
private val cooldown = Cooldown(2000)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
62
src/main/kotlin/net/hareworks/hcu/items/util/Cooldown.kt
Normal file
62
src/main/kotlin/net/hareworks/hcu/items/util/Cooldown.kt
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
package net.hareworks.hcu.items.util
|
||||
|
||||
import net.kyori.adventure.text.Component
|
||||
import net.kyori.adventure.text.format.NamedTextColor
|
||||
import org.bukkit.Sound
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.DurationUnit
|
||||
|
||||
class Cooldown(private val defaultDurationMs: Long) {
|
||||
private val lastUsed = ConcurrentHashMap<UUID, Long>()
|
||||
private val activeCooldowns = ConcurrentHashMap.newKeySet<UUID>()
|
||||
|
||||
fun start(player: Player, durationMs: Long = defaultDurationMs) {
|
||||
val expire = System.currentTimeMillis() + durationMs
|
||||
lastUsed[player.uniqueId] = expire
|
||||
activeCooldowns.add(player.uniqueId)
|
||||
}
|
||||
|
||||
fun isReady(player: Player): Boolean {
|
||||
val expireTime = lastUsed[player.uniqueId] ?: return true
|
||||
val current = System.currentTimeMillis()
|
||||
val ready = current >= expireTime
|
||||
return ready
|
||||
}
|
||||
|
||||
fun getRemainingSeconds(player: Player): Double {
|
||||
val expireTime = lastUsed[player.uniqueId] ?: return 0.0
|
||||
val diff = expireTime - System.currentTimeMillis()
|
||||
if (diff <= 0) return 0.0
|
||||
return diff / 1000.0
|
||||
}
|
||||
|
||||
fun checkAndWarn(player: Player): Boolean {
|
||||
if (isReady(player)) return true
|
||||
|
||||
val remaining = getRemainingSeconds(player)
|
||||
player.sendActionBar(
|
||||
Component.text("⏳ ", NamedTextColor.RED)
|
||||
.append(Component.text("クールダウン中... ", NamedTextColor.GRAY))
|
||||
.append(Component.text(String.format("%.1fs", remaining), NamedTextColor.RED))
|
||||
)
|
||||
player.playSound(player.location, Sound.UI_BUTTON_CLICK, 0.5f, 0.5f) // Failure sound
|
||||
return false
|
||||
}
|
||||
|
||||
fun checkFinished(player: Player): Boolean {
|
||||
if (activeCooldowns.contains(player.uniqueId) && isReady(player)) {
|
||||
activeCooldowns.remove(player.uniqueId)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun clear(player: Player) {
|
||||
lastUsed.remove(player.uniqueId)
|
||||
activeCooldowns.remove(player.uniqueId)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user