feat: Introduce ToolComponent interface for held item events and update EventListener to dispatch them.

This commit is contained in:
Kariya 2025-12-16 13:02:20 +00:00
parent f45947b9e9
commit 6752d075f4
4 changed files with 83 additions and 7 deletions

View File

@ -0,0 +1,9 @@
package net.hareworks.hcu.items.api.component
import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack
interface ToolComponent : CustomComponent {
fun onHoldTick(player: Player, item: ItemStack)
fun onStopHolding(player: Player, item: ItemStack) {}
}

View File

@ -1,6 +1,6 @@
package net.hareworks.hcu.items.content.components package net.hareworks.hcu.items.content.components
import net.hareworks.hcu.items.api.component.EquippableComponent import net.hareworks.hcu.items.api.component.ToolComponent
import net.hareworks.hcu.items.api.Tier import net.hareworks.hcu.items.api.Tier
import net.hareworks.hcu.items.config.Config import net.hareworks.hcu.items.config.Config
import org.bukkit.Material import org.bukkit.Material
@ -25,7 +25,7 @@ import java.util.Queue
import java.util.Random import java.util.Random
import java.util.UUID import java.util.UUID
class VeinMinerComponent(private val plugin: JavaPlugin) : EquippableComponent { class VeinMinerComponent(private val plugin: JavaPlugin) : ToolComponent {
override val key: NamespacedKey = NamespacedKey(plugin, "vein_miner") override val key: NamespacedKey = NamespacedKey(plugin, "vein_miner")
override val displayName: String = "Vein Miner" override val displayName: String = "Vein Miner"
@ -57,7 +57,7 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : EquippableComponent {
item.itemMeta = meta item.itemMeta = meta
} }
override fun onTick(player: Player, item: ItemStack) { override fun onHoldTick(player: Player, item: ItemStack) {
// ハイライト条件チェック (Sneakしながら) // ハイライト条件チェック (Sneakしながら)
if (!player.isSneaking) { if (!player.isSneaking) {
clearHighlight(player) clearHighlight(player)
@ -117,8 +117,7 @@ class VeinMinerComponent(private val plugin: JavaPlugin) : EquippableComponent {
activeHighlights[player.uniqueId] = HighlightSession(targetBlock, entities, System.currentTimeMillis()) activeHighlights[player.uniqueId] = HighlightSession(targetBlock, entities, System.currentTimeMillis())
} }
// アイテム持ち替えやスニーク解除時にも消えるように override fun onStopHolding(player: Player, item: ItemStack) {
override fun onUnequip(player: Player, item: ItemStack) {
clearHighlight(player) clearHighlight(player)
} }

View File

@ -11,10 +11,15 @@ import org.bukkit.inventory.EquipmentSlot
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import net.hareworks.hcu.items.api.component.EquippableComponent import net.hareworks.hcu.items.api.component.EquippableComponent
import net.hareworks.hcu.items.api.component.ToolComponent
import org.bukkit.plugin.Plugin import org.bukkit.plugin.Plugin
class EventListener(private val plugin: Plugin) : Listener { class EventListener(private val plugin: Plugin) : Listener {
// Track previously held items for ToolComponents to detect when they stop being held
// Key: Player UUID, Value: Pair(MainHandItem, OffHandItem)
private val lastHeldItems = java.util.concurrent.ConcurrentHashMap<java.util.UUID, Pair<ItemStack?, ItemStack?>>()
init { init {
plugin.server.scheduler.runTaskTimer(plugin, Runnable { plugin.server.scheduler.runTaskTimer(plugin, Runnable {
tickComponents() tickComponents()
@ -132,14 +137,72 @@ class EventListener(private val plugin: Plugin) : Listener {
private fun tickComponents() { private fun tickComponents() {
for (player in plugin.server.onlinePlayers) { for (player in plugin.server.onlinePlayers) {
val items = getEquipmentItems(player) val uuid = player.uniqueId
for (item in items) { val currentMainHand = player.inventory.itemInMainHand
val currentOffHand = player.inventory.itemInOffHand
// Get previous items
val lastItems = lastHeldItems[uuid]
val lastMainHand = lastItems?.first
val lastOffHand = lastItems?.second
// Check Main Hand Change
if (lastMainHand != null && lastMainHand != currentMainHand) {
dispatchToComponents(lastMainHand) { component ->
if (component is ToolComponent) {
component.onStopHolding(player, lastMainHand)
}
}
}
// Check Off Hand Change
if (lastOffHand != null && lastOffHand != currentOffHand) {
dispatchToComponents(lastOffHand) { component ->
if (component is ToolComponent) {
component.onStopHolding(player, lastOffHand)
}
}
}
// Update Cache
lastHeldItems[uuid] = Pair(currentMainHand, currentOffHand)
// --- Regular Tick Processing ---
// Armor Tick
val armorItems = player.inventory.armorContents.filterNotNull()
for (item in armorItems) {
if (item.type.isAir) continue
dispatchToComponents(item) { component -> dispatchToComponents(item) { component ->
if (component is EquippableComponent) { if (component is EquippableComponent) {
component.onTick(player, item) component.onTick(player, item)
} }
} }
} }
// ToolComponents in Main Hand
if (!currentMainHand.type.isAir) {
dispatchToComponents(currentMainHand) { component ->
if (component is ToolComponent) {
component.onHoldTick(player, currentMainHand)
}
if (component is EquippableComponent) {
component.onTick(player, currentMainHand)
}
}
}
// ToolComponents in Off Hand
if (!currentOffHand.type.isAir) {
dispatchToComponents(currentOffHand) { component ->
if (component is ToolComponent) {
component.onHoldTick(player, currentOffHand)
}
if (component is EquippableComponent) {
component.onTick(player, currentOffHand)
}
}
}
} }
} }

View File

@ -3,6 +3,7 @@ package net.hareworks.hcu.items.registry
import net.hareworks.hcu.items.api.Tier import net.hareworks.hcu.items.api.Tier
import net.hareworks.hcu.items.api.component.CustomComponent import net.hareworks.hcu.items.api.component.CustomComponent
import net.hareworks.hcu.items.api.component.EquippableComponent import net.hareworks.hcu.items.api.component.EquippableComponent
import net.hareworks.hcu.items.api.component.ToolComponent
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
object ComponentRegistry { object ComponentRegistry {
@ -20,6 +21,10 @@ object ComponentRegistry {
return components.values.filterIsInstance<EquippableComponent>() return components.values.filterIsInstance<EquippableComponent>()
} }
fun getToolComponents(): List<ToolComponent> {
return components.values.filterIsInstance<ToolComponent>()
}
/** /**
* コンポーネントを依存関係を解決しながら適用する * コンポーネントを依存関係を解決しながら適用する
*/ */