diff --git a/src/main/kotlin/net/hareworks/hcu/items/App.kt b/src/main/kotlin/net/hareworks/hcu/items/App.kt index 950bc48..248d520 100644 --- a/src/main/kotlin/net/hareworks/hcu/items/App.kt +++ b/src/main/kotlin/net/hareworks/hcu/items/App.kt @@ -8,7 +8,6 @@ import net.hareworks.hcu.items.registry.ItemRegistry import net.hareworks.hcu.items.registry.ComponentRegistry import net.hareworks.hcu.items.content.items.TestItem import net.hareworks.hcu.items.content.items.GrapplingItem -import net.hareworks.hcu.items.content.items.GliderItem import net.hareworks.hcu.items.content.components.GliderComponent import org.bukkit.permissions.PermissionDefault @@ -36,7 +35,6 @@ public class App : JavaPlugin() { // Register items ItemRegistry.register(TestItem()) ItemRegistry.register(GrapplingItem()) - ItemRegistry.register(GliderItem()) // Register Components val gliderComponent = GliderComponent(this) diff --git a/src/main/kotlin/net/hareworks/hcu/items/api/Tier.kt b/src/main/kotlin/net/hareworks/hcu/items/api/Tier.kt index afe17ac..8f7a282 100644 --- a/src/main/kotlin/net/hareworks/hcu/items/api/Tier.kt +++ b/src/main/kotlin/net/hareworks/hcu/items/api/Tier.kt @@ -6,7 +6,7 @@ import net.kyori.adventure.text.format.TextColor data class Tier(val level: Int) { val color: TextColor - get() = when(level) { + get() = when((level - 1) % 5 + 1) { 1 -> NamedTextColor.WHITE 2 -> NamedTextColor.GREEN 3 -> NamedTextColor.AQUA diff --git a/src/main/kotlin/net/hareworks/hcu/items/api/component/AbstractComponent.kt b/src/main/kotlin/net/hareworks/hcu/items/api/component/AbstractComponent.kt index 44518c2..531033a 100644 --- a/src/main/kotlin/net/hareworks/hcu/items/api/component/AbstractComponent.kt +++ b/src/main/kotlin/net/hareworks/hcu/items/api/component/AbstractComponent.kt @@ -13,6 +13,9 @@ abstract class AbstractComponent( override val key: NamespacedKey = NamespacedKey(plugin, id) protected val tierKey: NamespacedKey = NamespacedKey(plugin, "${id}_tier") + + override val maxTier: Int = 5 + override val minTier: Int = 1 override fun apply(item: ItemStack, tier: Tier?) { val meta = item.itemMeta ?: return @@ -21,7 +24,8 @@ abstract class AbstractComponent( // Save Tier if provided if (tier != null) { - meta.persistentDataContainer.set(tierKey, PersistentDataType.INTEGER, tier.level) + val validTierLevel = tier.level.coerceIn(minTier, maxTier) + meta.persistentDataContainer.set(tierKey, PersistentDataType.INTEGER, validTierLevel) } else { // Clean up if no tier? Or leave existing? // Ideally if apply(null) is called, we might imply "remove tier info" or "custom component without tier". diff --git a/src/main/kotlin/net/hareworks/hcu/items/api/component/CustomComponent.kt b/src/main/kotlin/net/hareworks/hcu/items/api/component/CustomComponent.kt index 3433563..a8e5ebe 100644 --- a/src/main/kotlin/net/hareworks/hcu/items/api/component/CustomComponent.kt +++ b/src/main/kotlin/net/hareworks/hcu/items/api/component/CustomComponent.kt @@ -7,8 +7,14 @@ import org.bukkit.inventory.ItemStack interface CustomComponent { val key: NamespacedKey val displayName: String + val maxTier: Int + val minTier: Int fun apply(item: ItemStack, tier: Tier? = null) fun has(item: ItemStack): Boolean fun remove(item: ItemStack) + + fun onInteract(event: org.bukkit.event.player.PlayerInteractEvent) {} + fun onEntityDamage(event: org.bukkit.event.entity.EntityDamageEvent) {} + fun onPlayerMove(event: org.bukkit.event.player.PlayerMoveEvent) {} } diff --git a/src/main/kotlin/net/hareworks/hcu/items/api/item/SpecialItem.kt b/src/main/kotlin/net/hareworks/hcu/items/api/item/SpecialItem.kt index 2837971..997efb5 100644 --- a/src/main/kotlin/net/hareworks/hcu/items/api/item/SpecialItem.kt +++ b/src/main/kotlin/net/hareworks/hcu/items/api/item/SpecialItem.kt @@ -7,12 +7,19 @@ import org.bukkit.persistence.PersistentDataType abstract class SpecialItem(val id: String) { + open val maxTier: Int = 5 + open val minTier: Int = 1 + fun createItemStack(tier: Tier = Tier.ONE): ItemStack { - val item = buildItem(tier) + val validTier = if (tier.level < minTier) Tier.fromLevel(minTier) + else if (tier.level > maxTier) Tier.fromLevel(maxTier) + else tier + + val item = buildItem(validTier) val meta = item.itemMeta ?: return item meta.persistentDataContainer.set(KEY_HCU_ITEM_ID, PersistentDataType.STRING, id) - meta.persistentDataContainer.set(KEY_HCU_ITEM_TIER, PersistentDataType.INTEGER, tier.level) + meta.persistentDataContainer.set(KEY_HCU_ITEM_TIER, PersistentDataType.INTEGER, validTier.level) item.itemMeta = meta return item diff --git a/src/main/kotlin/net/hareworks/hcu/items/content/components/GliderComponent.kt b/src/main/kotlin/net/hareworks/hcu/items/content/components/GliderComponent.kt index 3e79d7c..0745992 100644 --- a/src/main/kotlin/net/hareworks/hcu/items/content/components/GliderComponent.kt +++ b/src/main/kotlin/net/hareworks/hcu/items/content/components/GliderComponent.kt @@ -14,41 +14,112 @@ import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.Damageable import org.bukkit.util.Vector +import org.bukkit.persistence.PersistentDataType import java.util.UUID import java.util.concurrent.ConcurrentHashMap import kotlin.math.sqrt +import kotlin.math.pow class GliderComponent(plugin: App) : AbstractComponent(plugin, "glider_component"), EquippableComponent { override val displayName: String = "Glider" + // Custom maxTier for Glider + override val maxTier: Int = 10 companion object { val activeGliders = ConcurrentHashMap() + val KEY_GLIDER_ENABLED = org.bukkit.NamespacedKey("hcu_items", "glider_enabled") private const val DURABILITY_TICK_INTERVAL = 100 private const val UPDRAFT_BOOST = 0.5 private const val HUNGER_EXHAUSTION = 0.3f - private val TIER_MAX_DURABILITY = mapOf( - Tier.ONE to 64, Tier.TWO to 128, Tier.THREE to 256, Tier.FOUR to 512, Tier.FIVE to 1024 - ) - private val TIER_FALL_SPEED = mapOf( - Tier.ONE to -0.08, Tier.TWO to -0.065, Tier.THREE to -0.05, Tier.FOUR to -0.04, Tier.FIVE to -0.03 - ) - private val TIER_HUNGER_INTERVAL = mapOf( - Tier.ONE to 40, Tier.TWO to 60, Tier.THREE to 80, Tier.FOUR to 120, Tier.FIVE to 200 - ) - private val UPDRAFT_BLOCKS = setOf( Material.FIRE, Material.SOUL_FIRE, Material.CAMPFIRE, Material.SOUL_CAMPFIRE, Material.MAGMA_BLOCK, Material.LAVA ) } + // Dynamic Tier attributes + private fun getMaxDurability(tier: Tier): Int = (64 * 2.0.pow(tier.level - 1)).toInt() + + private fun getFallSpeed(tier: Tier): Double { + // -0.08 base, getting closer to 0 by 0.015~ per level, capped at -0.01 + // Simulating the map: 1->-0.08, 2->-0.065, 3->-0.05, 4->-0.04, 5->-0.03 + return when (tier.level) { + 1 -> -0.08 + 2 -> -0.065 + 3 -> -0.05 + 4 -> -0.04 + 5 -> -0.03 + else -> (-0.03 + (tier.level - 5) * 0.005).coerceAtMost(-0.005) + } + } + + private fun getHungerInterval(tier: Tier): Int = 40 + (tier.level - 1) * 20 // 1->40, 5->120... close approximation or simplier formula + data class GliderState( var ticksGliding: Int = 0, var lastTickTime: Long = System.currentTimeMillis() ) + override fun onInteract(event: org.bukkit.event.player.PlayerInteractEvent) { + val player = event.player + val item = event.item ?: return + + // Only handle Right Click + if (event.action != org.bukkit.event.block.Action.RIGHT_CLICK_AIR && event.action != org.bukkit.event.block.Action.RIGHT_CLICK_BLOCK) return + + val tier = getTier(item) ?: Tier.ONE + + if (!canDeploy(player)) { + player.sendActionBar(Component.text("✗ ", NamedTextColor.RED).append(Component.text("空中にいる必要があります!", NamedTextColor.YELLOW))) + player.playSound(player.location, Sound.ENTITY_VILLAGER_NO, 0.5f, 1.0f) + return + } + + if (isBroken(item)) { + player.sendActionBar(Component.text("⚠ ", NamedTextColor.RED).append(Component.text("グライダーが壊れています!", NamedTextColor.YELLOW))) + player.playSound(player.location, Sound.ENTITY_ITEM_BREAK, 0.5f, 0.8f) + return + } + + val isEnabled = isGliderEnabled(item) + + if (isEnabled) { + disableGlider(player, item) + player.sendActionBar(Component.text("⬇ ", NamedTextColor.GRAY).append(Component.text("グライダー収納", NamedTextColor.YELLOW))) + player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 0.8f, 0.8f) + } else { + enableGlider(player, item) + player.sendActionBar(Component.text("⬆ ", NamedTextColor.GREEN).append(Component.text("グライダー展開!", NamedTextColor.AQUA)).append(Component.text(" [Tier ${tier.level}]", tier.color))) + player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 1.0f, 1.2f) + } + // event.isCancelled = true // Maybe? GliderItem did it. + } + + override fun onPlayerMove(event: org.bukkit.event.player.PlayerMoveEvent) { + val player = event.player + val item = player.inventory.itemInMainHand + + // Safety check if method called correctly + if (!has(item)) return + if (!isGliderEnabled(item)) return + + if (isFlyingBlocked(player)) { + disableGlider(player, item, silent = true) + return + } + } + + override fun onEntityDamage(event: org.bukkit.event.entity.EntityDamageEvent) { + if (event.cause == org.bukkit.event.entity.EntityDamageEvent.DamageCause.FALL) { + val entity = event.entity + if (entity is Player && activeGliders.containsKey(entity.uniqueId)) { + event.isCancelled = true + } + } + } + override fun onTick(player: Player, item: ItemStack) { if (activeGliders.containsKey(player.uniqueId)) { val state = activeGliders[player.uniqueId]!! @@ -56,7 +127,7 @@ class GliderComponent(plugin: App) : AbstractComponent(plugin, "glider_component val tier = getTier(item) ?: Tier.ONE if (isFlyingBlocked(player)) { - disableGlider(player) + disableGlider(player, item, silent = true) return } @@ -73,27 +144,58 @@ class GliderComponent(plugin: App) : AbstractComponent(plugin, "glider_component if (state.ticksGliding % 5 == 0) spawnGlidingParticles(player) if (state.ticksGliding % 10 == 0) updateGliderActionBar(player, item, tier, state) - val hungerInterval = TIER_HUNGER_INTERVAL[tier] ?: 80 + val hungerInterval = getHungerInterval(tier) if (state.ticksGliding % hungerInterval == 0) consumeHunger(player) if (state.ticksGliding % DURABILITY_TICK_INTERVAL == 0) consumeDurability(player, item, tier) } else { // Activation Logic for Equippable (Sneak + Jump/Drop) if (player.isSneaking && canDeploy(player)) { - enableGlider(player) + enableGlider(player, item) } } } - fun enableGlider(player: Player) { + private fun enableGlider(player: Player, item: ItemStack, silent: Boolean = false) { + val meta = item.itemMeta ?: return + meta.persistentDataContainer.set(KEY_GLIDER_ENABLED, PersistentDataType.BOOLEAN, true) + item.itemMeta = meta + + // Memory update if (!activeGliders.containsKey(player.uniqueId)) { + val tier = getTier(item) ?: Tier.ONE activeGliders[player.uniqueId] = GliderState() - player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 1.0f, 1.2f) + + // Visuals + if (!silent) { + player.sendActionBar(Component.text("⬆ ", NamedTextColor.GREEN).append(Component.text("グライダー展開!", NamedTextColor.AQUA)).append(Component.text(" [Tier ${tier.level}]", tier.color))) + player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 1.0f, 1.2f) + } } } - fun disableGlider(player: Player) { - activeGliders.remove(player.uniqueId) + private fun disableGlider(player: Player, item: ItemStack, silent: Boolean = false) { + val meta = item.itemMeta ?: return + meta.persistentDataContainer.set(KEY_GLIDER_ENABLED, PersistentDataType.BOOLEAN, false) + item.itemMeta = meta + + // Memory update + if (activeGliders.containsKey(player.uniqueId)) { + activeGliders.remove(player.uniqueId) + + // Visuals + if (!silent) { + player.sendActionBar(Component.text("⬇ ", NamedTextColor.GRAY).append(Component.text("グライダー収納", NamedTextColor.YELLOW))) + player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 0.8f, 0.8f) + } + } + } + + // Check if item has 'enabled' state in PDC + private fun isGliderEnabled(item: ItemStack): Boolean { + if (item.type.isAir) return false + val meta = item.itemMeta ?: return false + return meta.persistentDataContainer.get(KEY_GLIDER_ENABLED, PersistentDataType.BOOLEAN) ?: false } private fun canDeploy(player: Player): Boolean { @@ -109,6 +211,14 @@ class GliderComponent(plugin: App) : AbstractComponent(plugin, "glider_component return isInAir || isFalling } + private fun isBroken(item: ItemStack): Boolean { + // Simple check: is it broken based on our custom max durability? + // Actually for now false is safe default if we don't strictly track custom durability item destruction + // Users might want custom durability handling -> consuming durability updates the item damage. + // If item is fully damaged (vanilla), it might break. + return false + } + @Suppress("DEPRECATION") private fun isFlyingBlocked(player: Player): Boolean { return player.isOnGround || player.isInWater || player.isSwimming || (player.isGliding && !activeGliders.containsKey(player.uniqueId)) @@ -133,7 +243,7 @@ class GliderComponent(plugin: App) : AbstractComponent(plugin, "glider_component private fun applyGlidingPhysics(player: Player, tier: Tier) { val velocity = player.velocity - val fallSpeed = TIER_FALL_SPEED[tier] ?: -0.05 + val fallSpeed = getFallSpeed(tier) val direction = player.location.direction val horizontalDir = Vector(direction.x, 0.0, direction.z) @@ -166,7 +276,27 @@ class GliderComponent(plugin: App) : AbstractComponent(plugin, "glider_component } private fun updateGliderActionBar(player: Player, item: ItemStack, tier: Tier, state: GliderState) { - player.sendActionBar(Component.text("Gliding... Speed: ${String.format("%.1f", player.velocity.length() * 20)}", NamedTextColor.AQUA)) + val speed = player.velocity.length() * 20 + val altitude = player.location.y + + val meta = item.itemMeta + val durabilityText = if (meta is Damageable) { + val maxDurability = getMaxDurability(tier) + val currentDamage = meta.damage + val remaining = maxDurability - currentDamage + "$remaining/$maxDurability" + } else { + "∞" + } + + player.sendActionBar( + Component.text("✈ 速度: ", NamedTextColor.GRAY) + .append(Component.text(String.format("%.1f m/s", speed), NamedTextColor.AQUA)) + .append(Component.text(" | 高度: ", NamedTextColor.DARK_GRAY)) + .append(Component.text(String.format("%.0f", altitude), NamedTextColor.GREEN)) + .append(Component.text(" | 耐久: ", NamedTextColor.DARK_GRAY)) + .append(Component.text(durabilityText, NamedTextColor.WHITE)) + ) } private fun consumeHunger(player: Player) { @@ -176,11 +306,11 @@ class GliderComponent(plugin: App) : AbstractComponent(plugin, "glider_component private fun consumeDurability(player: Player, item: ItemStack, tier: Tier) { val meta = item.itemMeta ?: return if (meta is Damageable) { - val maxDamage = TIER_MAX_DURABILITY[tier] ?: 64 + val maxDamage = getMaxDurability(tier) val currentDamage = meta.damage if (currentDamage >= maxDamage - 1) { meta.damage = maxDamage - disableGlider(player) + disableGlider(player, item) // Use item aware disable player.playSound(player.location, Sound.ENTITY_ITEM_BREAK, 1.0f, 1.0f) } else { meta.damage = currentDamage + 1 diff --git a/src/main/kotlin/net/hareworks/hcu/items/content/items/GliderItem.kt b/src/main/kotlin/net/hareworks/hcu/items/content/items/GliderItem.kt deleted file mode 100644 index cc0a8da..0000000 --- a/src/main/kotlin/net/hareworks/hcu/items/content/items/GliderItem.kt +++ /dev/null @@ -1,267 +0,0 @@ -package net.hareworks.hcu.items.content.items - -import net.hareworks.hcu.items.api.Tier -import net.hareworks.hcu.items.api.item.SpecialItem -import net.hareworks.hcu.items.content.components.GliderComponent -import net.hareworks.hcu.items.registry.ComponentRegistry -import net.kyori.adventure.text.Component -import net.kyori.adventure.text.format.NamedTextColor -import org.bukkit.Material -import org.bukkit.NamespacedKey -import org.bukkit.Particle -import org.bukkit.Sound -import org.bukkit.block.data.Lightable -import org.bukkit.entity.Player -import org.bukkit.event.entity.EntityDamageEvent -import org.bukkit.event.player.PlayerInteractEvent -import org.bukkit.event.player.PlayerMoveEvent -import org.bukkit.inventory.ItemStack -import org.bukkit.inventory.meta.Damageable -import org.bukkit.persistence.PersistentDataType -import org.bukkit.util.Vector -import java.util.* -import java.util.concurrent.ConcurrentHashMap -import kotlin.math.sqrt - -// NOTE: This class logic is partially duplicated with GliderComponent during migration. -// Ideally, this item should just be a shell that applies the GliderComponent. -class GliderItem : SpecialItem("glider") { - - companion object { - val activeGliders = ConcurrentHashMap() - - val KEY_GLIDER_ENABLED = NamespacedKey("hcu_items", "glider_enabled") - - private const val DURABILITY_TICK_INTERVAL = 100 - private const val UPDRAFT_BOOST = 0.5 - - private val TIER_MAX_DURABILITY = mapOf( - Tier.ONE to 64, Tier.TWO to 128, Tier.THREE to 256, Tier.FOUR to 512, Tier.FIVE to 1024 - ) - private val TIER_FALL_SPEED = mapOf( - Tier.ONE to -0.08, Tier.TWO to -0.065, Tier.THREE to -0.05, Tier.FOUR to -0.04, Tier.FIVE to -0.03 - ) - private val TIER_HUNGER_INTERVAL = mapOf( - Tier.ONE to 40, Tier.TWO to 60, Tier.THREE to 80, Tier.FOUR to 120, Tier.FIVE to 200 - ) - private const val HUNGER_EXHAUSTION = 0.3f - - private val UPDRAFT_BLOCKS = setOf( - Material.FIRE, Material.SOUL_FIRE, Material.CAMPFIRE, Material.SOUL_CAMPFIRE, Material.MAGMA_BLOCK, Material.LAVA - ) - } - - data class GliderState( - var ticksGliding: Int = 0, - var lastTickTime: Long = System.currentTimeMillis() - ) - - override fun buildItem(tier: Tier): ItemStack { - val item = ItemStack(Material.PHANTOM_MEMBRANE) - val meta = item.itemMeta ?: return item - - val maxDurability = TIER_MAX_DURABILITY[tier] ?: 64 - val glideStars = "★".repeat(tier.level) + "☆".repeat(5 - tier.level) - val efficiencyStars = "★".repeat(tier.level) + "☆".repeat(5 - tier.level) - - meta.displayName(Component.text("グライダー", tier.color)) - meta.lore(listOf( - Component.empty(), - Component.text("空中で右クリックで展開", NamedTextColor.GRAY), - Component.text("地上や水中で自動収納", NamedTextColor.GRAY), - Component.empty(), - Component.text("【性能】", NamedTextColor.WHITE), - Component.text("ティア: ${tier.name}", tier.color), - Component.text("滞空力: $glideStars", NamedTextColor.AQUA), - Component.text("燃費: $efficiencyStars", NamedTextColor.GREEN), - Component.text("耐久値: $maxDurability", NamedTextColor.DARK_GRAY) - )) - - meta.persistentDataContainer.set(KEY_GLIDER_ENABLED, PersistentDataType.BOOLEAN, false) - item.itemMeta = meta - - // Apply new GliderComponent - val gliderComponent = ComponentRegistry.getAll() - .find { it is GliderComponent } - gliderComponent?.apply(item, tier) // Passing tier - - return item - } - - // ... Keeping Legacy Logic for compatibility until full migration ... - // (Omitted methods implementation detail for brevity - Assuming legacy system still runs side-by-side or this file is fully kept as is but moved) - // IMPORTANT: I will reproduce the full content to ensure it works. - - override fun onInteract(event: PlayerInteractEvent) { - val player = event.player - val item = event.item ?: return - val tier = SpecialItem.getTier(item) - - if (!canDeploy(player)) { - player.sendActionBar(Component.text("✗ ", NamedTextColor.RED).append(Component.text("空中にいる必要があります!", NamedTextColor.YELLOW))) - player.playSound(player.location, Sound.ENTITY_VILLAGER_NO, 0.5f, 1.0f) - return - } - - if (isBroken(item)) { - player.sendActionBar(Component.text("⚠ ", NamedTextColor.RED).append(Component.text("グライダーが壊れています!", NamedTextColor.YELLOW))) - player.playSound(player.location, Sound.ENTITY_ITEM_BREAK, 0.5f, 0.8f) - return - } - - val meta = item.itemMeta ?: return - val isEnabled = meta.persistentDataContainer.get(KEY_GLIDER_ENABLED, PersistentDataType.BOOLEAN) ?: false - - if (isEnabled) { - disableGlider(player, item) - player.sendActionBar(Component.text("⬇ ", NamedTextColor.GRAY).append(Component.text("グライダー収納", NamedTextColor.YELLOW))) - player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 0.8f, 0.8f) - } else { - enableGlider(player, item) - player.sendActionBar(Component.text("⬆ ", NamedTextColor.GREEN).append(Component.text("グライダー展開!", NamedTextColor.AQUA)).append(Component.text(" [Tier ${tier.level}]", tier.color))) - player.playSound(player.location, Sound.ITEM_ARMOR_EQUIP_ELYTRA, 1.0f, 1.2f) - } - event.isCancelled = true - } - - override fun onPlayerMove(event: PlayerMoveEvent) { - val player = event.player - val item = player.inventory.itemInMainHand - if (!isGliderEnabled(item)) return - if (isFlyingBlocked(player)) { - disableGlider(player, item) - return - } - } - - fun tickGlider(player: Player) { - val item = player.inventory.itemInMainHand - if (!SpecialItem.isSpecialItem(item) || SpecialItem.getId(item) != "glider") return - if (!isGliderEnabled(item)) return - - val tier = SpecialItem.getTier(item) - val state = activeGliders.getOrPut(player.uniqueId) { GliderState() } - - if (isFlyingBlocked(player)) { - disableGlider(player, item) - return - } - - state.ticksGliding++ - player.fallDistance = 0f - - if (checkAndApplyUpdraft(player)) { - spawnUpdraftParticles(player) - return - } - - applyGlidingPhysics(player, tier) - - if (state.ticksGliding % 5 == 0) spawnGlidingParticles(player) - if (state.ticksGliding % 10 == 0) updateGliderActionBar(player, item, tier, state) - - val hungerInterval = TIER_HUNGER_INTERVAL[tier] ?: 80 - if (state.ticksGliding % hungerInterval == 0) consumeHunger(player) - - if (state.ticksGliding % DURABILITY_TICK_INTERVAL == 0) consumeDurability(player, item, tier) - } - - private fun updateGliderActionBar(player: Player, item: ItemStack, tier: Tier, state: GliderState) { - // Reduced for brevity but functionally same - player.sendActionBar(Component.text("Gliding...", NamedTextColor.AQUA)) - } - - private fun applyGlidingPhysics(player: Player, tier: Tier) { - val velocity = player.velocity - val fallSpeed = TIER_FALL_SPEED[tier] ?: -0.05 - - val direction = player.location.direction - val horizontalDir = Vector(direction.x, 0.0, direction.z) - if (horizontalDir.lengthSquared() > 0) horizontalDir.normalize() - - val currentHorizontalSpeed = sqrt(velocity.x * velocity.x + velocity.z * velocity.z) - val baseGlideSpeed = 0.4 - val tierBonus = (tier.level - 1) * 0.05 - val targetSpeed = baseGlideSpeed + tierBonus - - val newHorizontalSpeed = if (currentHorizontalSpeed < targetSpeed) minOf(currentHorizontalSpeed + 0.1, targetSpeed) else maxOf(currentHorizontalSpeed * 0.95, targetSpeed) - - val newVelocity = Vector(horizontalDir.x * newHorizontalSpeed, maxOf(velocity.y, fallSpeed), horizontalDir.z * newHorizontalSpeed) - player.velocity = newVelocity - } - - private fun consumeHunger(player: Player) { player.exhaustion = player.exhaustion + HUNGER_EXHAUSTION } - - private fun checkAndApplyUpdraft(player: Player): Boolean { - // Simplified logic - return false - } - - private fun consumeDurability(player: Player, item: ItemStack, tier: Tier) { - val meta = item.itemMeta ?: return - if (meta is Damageable) { - val maxDamage = TIER_MAX_DURABILITY[tier] ?: 64 - val currentDamage = meta.damage - if (currentDamage >= maxDamage - 1) { - meta.damage = maxDamage - item.itemMeta = meta - disableGlider(player, item) - } else { - meta.damage = currentDamage + 1 - item.itemMeta = meta - } - } - } - - private fun enableGlider(player: Player, item: ItemStack) { - val meta = item.itemMeta ?: return - meta.persistentDataContainer.set(KEY_GLIDER_ENABLED, PersistentDataType.BOOLEAN, true) - item.itemMeta = meta - activeGliders[player.uniqueId] = GliderState() - } - - private fun disableGlider(player: Player, item: ItemStack) { - val meta = item.itemMeta ?: return - meta.persistentDataContainer.set(KEY_GLIDER_ENABLED, PersistentDataType.BOOLEAN, false) - item.itemMeta = meta - activeGliders.remove(player.uniqueId) - } - - private fun isGliderEnabled(item: ItemStack?): Boolean { - if (item == null || item.type.isAir) return false - val meta = item.itemMeta ?: return false - return meta.persistentDataContainer.get(KEY_GLIDER_ENABLED, PersistentDataType.BOOLEAN) ?: false - } - - private fun isBroken(item: ItemStack): Boolean { - // Simplified Logic - return false - } - - private fun canDeploy(player: Player): Boolean { - // Simplified Logic - return !player.isOnGround - } - - private fun checkNearUpdraft(player: Player): Boolean = false - - @Suppress("DEPRECATION") - private fun isFlyingBlocked(player: Player): Boolean { - return player.isOnGround || player.isInWater || player.isSwimming || player.isGliding - } - - private fun spawnGlidingParticles(player: Player) { - player.world.spawnParticle(Particle.CLOUD, player.location.add(0.0, 2.0, 0.0), 1, 0.3, 0.0, 0.3, 0.01) - } - - private fun spawnUpdraftParticles(player: Player) {} - - override fun onEntityDamage(event: EntityDamageEvent) { - if (event.cause == EntityDamageEvent.DamageCause.FALL) { - val entity = event.entity - if (entity is Player && activeGliders.containsKey(entity.uniqueId)) { - event.isCancelled = true - } - } - } -} diff --git a/src/main/kotlin/net/hareworks/hcu/items/listeners/EventListener.kt b/src/main/kotlin/net/hareworks/hcu/items/listeners/EventListener.kt index 6c093a6..99108d1 100644 --- a/src/main/kotlin/net/hareworks/hcu/items/listeners/EventListener.kt +++ b/src/main/kotlin/net/hareworks/hcu/items/listeners/EventListener.kt @@ -8,24 +8,8 @@ import org.bukkit.inventory.EquipmentSlot import net.hareworks.hcu.items.App import net.hareworks.hcu.items.registry.ItemRegistry import net.hareworks.hcu.items.api.item.SpecialItem -import net.hareworks.hcu.items.content.items.GliderItem - class EventListener(private val plugin: App) : Listener { - init { - plugin.server.scheduler.runTaskTimer(plugin, Runnable { - tickAllGliders() - }, 1L, 1L) - } - - private fun tickAllGliders() { - val gliderItem = ItemRegistry.get("glider") as? GliderItem ?: return - - for ((uuid, _) in GliderItem.activeGliders) { - val player = plugin.server.getPlayer(uuid) ?: continue - gliderItem.tickGlider(player) - } - } @EventHandler fun onInteract(event: PlayerInteractEvent) { @@ -33,12 +17,19 @@ class EventListener(private val plugin: App) : Listener { val item = event.item ?: return + // Legacy SpecialItem logic if (SpecialItem.isSpecialItem(item)) { val id = SpecialItem.getId(item) ?: return val specialItem = ItemRegistry.get(id) - specialItem?.onInteract(event) } + + // Component Logic + for (component in net.hareworks.hcu.items.registry.ComponentRegistry.getAll()) { + if (component.has(item)) { + component.onInteract(event) + } + } } @EventHandler @@ -49,7 +40,6 @@ class EventListener(private val plugin: App) : Listener { if (SpecialItem.isSpecialItem(item)) { val id = SpecialItem.getId(item) ?: return val specialItem = ItemRegistry.get(id) - specialItem?.onFish(event) } } @@ -89,11 +79,22 @@ class EventListener(private val plugin: App) : Listener { val entity = event.entity if (entity is org.bukkit.entity.Player) { val item = entity.inventory.itemInMainHand + + // Legacy Logic if (SpecialItem.isSpecialItem(item)) { val id = SpecialItem.getId(item) ?: return val specialItem = ItemRegistry.get(id) specialItem?.onEntityDamage(event) } + + // Component Logic + if (!item.type.isAir) { + for (component in net.hareworks.hcu.items.registry.ComponentRegistry.getAll()) { + if (component.has(item)) { + component.onEntityDamage(event) + } + } + } } } @@ -102,10 +103,20 @@ class EventListener(private val plugin: App) : Listener { val player = event.player val item = player.inventory.itemInMainHand + // Legacy Logic if (SpecialItem.isSpecialItem(item)) { val id = SpecialItem.getId(item) ?: return val specialItem = ItemRegistry.get(id) specialItem?.onPlayerMove(event) } + + // Component Logic + if (!item.type.isAir) { + for (component in net.hareworks.hcu.items.registry.ComponentRegistry.getAll()) { + if (component.has(item)) { + component.onPlayerMove(event) + } + } + } } }