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 java.util.concurrent.ConcurrentHashMap
|
||||||
import org.bukkit.potion.PotionEffect
|
import org.bukkit.potion.PotionEffect
|
||||||
import org.bukkit.potion.PotionEffectType
|
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 {
|
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 {
|
companion object {
|
||||||
// Track players who have used their blink (GLIDER is removed until landing)
|
// Track players who have used their blink (GLIDER is removed until landing)
|
||||||
private val usedBlink = ConcurrentHashMap.newKeySet<UUID>()
|
private val usedBlink = ConcurrentHashMap.newKeySet<UUID>()
|
||||||
|
private val cooldown = Cooldown(1500)
|
||||||
|
|
||||||
// Color scheme - Purple/Magenta for teleport/blink theme
|
// Color scheme - Purple/Magenta for teleport/blink theme
|
||||||
private val PRIMARY_COLOR = TextColor.color(0xDA70D6) // Orchid
|
private val PRIMARY_COLOR = TextColor.color(0xDA70D6) // Orchid
|
||||||
|
|
@ -67,8 +71,14 @@ class BlinkComponent(private val plugin: App) : AbstractComponent(plugin, "blink
|
||||||
}
|
}
|
||||||
|
|
||||||
// Landing feedback
|
// Landing feedback
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for cooldown finish
|
||||||
|
if (cooldown.checkFinished(player)) {
|
||||||
showReadyMessage(player)
|
showReadyMessage(player)
|
||||||
player.playSound(player.location, Sound.BLOCK_NOTE_BLOCK_BELL, 0.5f, 1.5f)
|
player.playSound(player.location, Sound.BLOCK_NOTE_BLOCK_BELL, 0.5f, 1.5f)
|
||||||
|
// Allow re-use immediately
|
||||||
|
usedBlink.remove(player.uniqueId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,12 +99,22 @@ class BlinkComponent(private val plugin: App) : AbstractComponent(plugin, "blink
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check cooldown
|
||||||
|
if (!cooldown.checkAndWarn(player)) {
|
||||||
|
item.unsetData(DataComponentTypes.GLIDER)
|
||||||
|
event.isCancelled = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Cancel the glide start
|
// Cancel the glide start
|
||||||
event.isCancelled = true
|
event.isCancelled = true
|
||||||
|
|
||||||
// Mark as used
|
// Mark as used
|
||||||
usedBlink.add(player.uniqueId)
|
usedBlink.add(player.uniqueId)
|
||||||
|
|
||||||
|
// Start cooldown immediately
|
||||||
|
cooldown.start(player)
|
||||||
|
|
||||||
// Execute Blink
|
// Execute Blink
|
||||||
handleBlink(player, item)
|
handleBlink(player, item)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ import org.bukkit.inventory.ItemStack
|
||||||
import org.bukkit.util.Vector
|
import org.bukkit.util.Vector
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
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 {
|
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 {
|
companion object {
|
||||||
// Track players who have used their double jump (GLIDER is removed)
|
// Track players who have used their double jump (GLIDER is removed)
|
||||||
private val usedDoubleJump = ConcurrentHashMap.newKeySet<UUID>()
|
private val usedDoubleJump = ConcurrentHashMap.newKeySet<UUID>()
|
||||||
|
private val cooldown = Cooldown(1500)
|
||||||
|
|
||||||
// Color scheme
|
// Color scheme
|
||||||
private val PRIMARY_COLOR = TextColor.color(0x7DF9FF) // Electric Cyan
|
private val PRIMARY_COLOR = TextColor.color(0x7DF9FF) // Electric Cyan
|
||||||
|
|
@ -67,6 +71,10 @@ class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "
|
||||||
}
|
}
|
||||||
|
|
||||||
// Landing feedback
|
// Landing feedback
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for cooldown finish
|
||||||
|
if (cooldown.checkFinished(player)) {
|
||||||
showReadyMessage(player)
|
showReadyMessage(player)
|
||||||
player.playSound(player.location, Sound.BLOCK_NOTE_BLOCK_CHIME, 0.5f, 1.5f)
|
player.playSound(player.location, Sound.BLOCK_NOTE_BLOCK_CHIME, 0.5f, 1.5f)
|
||||||
}
|
}
|
||||||
|
|
@ -90,6 +98,13 @@ class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check cooldown
|
||||||
|
if (!cooldown.checkAndWarn(player)) {
|
||||||
|
item.unsetData(DataComponentTypes.GLIDER)
|
||||||
|
event.isCancelled = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Cancel the glide start
|
// Cancel the glide start
|
||||||
event.isCancelled = true
|
event.isCancelled = true
|
||||||
|
|
||||||
|
|
@ -98,6 +113,7 @@ class DoubleJumpComponent(private val plugin: App) : AbstractComponent(plugin, "
|
||||||
|
|
||||||
// Execute Double Jump
|
// Execute Double Jump
|
||||||
handleDoubleJump(player, item)
|
handleDoubleJump(player, item)
|
||||||
|
cooldown.start(player)
|
||||||
|
|
||||||
// Remove GLIDER component to prevent further glide triggers
|
// Remove GLIDER component to prevent further glide triggers
|
||||||
item.unsetData(DataComponentTypes.GLIDER)
|
item.unsetData(DataComponentTypes.GLIDER)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ import org.bukkit.Location
|
||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
import org.bukkit.event.player.PlayerFishEvent
|
import org.bukkit.event.player.PlayerFishEvent
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import net.hareworks.hcu.items.util.Cooldown
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
|
|
||||||
class GrapplingItem : AbstractItem("grappling_hook") {
|
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)
|
val isStuck = hook.persistentDataContainer.has(KEY_HOOK_STUCK, org.bukkit.persistence.PersistentDataType.BYTE)
|
||||||
|
|
||||||
if (event.state == PlayerFishEvent.State.REEL_IN && isStuck) {
|
if (event.state == PlayerFishEvent.State.REEL_IN && isStuck) {
|
||||||
|
if (!cooldown.checkAndWarn(player)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cooldown.start(player)
|
||||||
|
|
||||||
val playerLoc = player.location
|
val playerLoc = player.location
|
||||||
val hookLoc = hook.location
|
val hookLoc = hook.location
|
||||||
|
|
||||||
|
|
@ -236,5 +244,6 @@ class GrapplingItem : AbstractItem("grappling_hook") {
|
||||||
companion object {
|
companion object {
|
||||||
val KEY_HOOK_STUCK = org.bukkit.NamespacedKey("hcu_items", "hook_stuck")
|
val KEY_HOOK_STUCK = org.bukkit.NamespacedKey("hcu_items", "hook_stuck")
|
||||||
val KEY_ANCHOR_ID = org.bukkit.NamespacedKey("hcu_items", "anchor_id")
|
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