feat: Introduce dispatchToComponentsWithDependencyCheck to conditionally dispatch events based on item data components and event handling status.
This commit is contained in:
parent
b5a51fad96
commit
e5d89e41b6
|
|
@ -94,7 +94,13 @@ class EventListener(private val plugin: Plugin) : Listener {
|
|||
|
||||
for (item in items) {
|
||||
// AbstractItem interface does not define onToggleSneak.
|
||||
dispatchToComponents(item) { it.onToggleSneak(player, item, event) }
|
||||
val handled = dispatchToComponentsWithDependencyCheck(
|
||||
item = item,
|
||||
isEventHandled = { event.isCancelled }
|
||||
) { component ->
|
||||
component.onToggleSneak(player, item, event)
|
||||
}
|
||||
if (handled) break
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +110,13 @@ class EventListener(private val plugin: Plugin) : Listener {
|
|||
if (entity is Player) {
|
||||
val items = getEquipmentItems(entity)
|
||||
for (item in items) {
|
||||
dispatchToComponents(item) { it.onToggleGlide(entity, item, event) }
|
||||
val handled = dispatchToComponentsWithDependencyCheck(
|
||||
item = item,
|
||||
isEventHandled = { event.isCancelled }
|
||||
) { component ->
|
||||
component.onToggleGlide(entity, item, event)
|
||||
}
|
||||
if (handled) break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -138,6 +150,52 @@ class EventListener(private val plugin: Plugin) : Listener {
|
|||
action(abstractItem)
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches to components on an item, but only if the item satisfies
|
||||
* the component's dataComponentDependencies.
|
||||
*
|
||||
* This prevents multiple components with the same trigger conditions
|
||||
* (e.g., GLIDER) from firing simultaneously when only one item
|
||||
* actually has the required data component active.
|
||||
*
|
||||
* @param item The item to dispatch to
|
||||
* @param isEventHandled Lambda to check if the event has been handled (e.g., cancelled)
|
||||
* @param action The action to perform on each eligible component
|
||||
* @return true if the event was handled by any component, false otherwise
|
||||
*/
|
||||
private fun dispatchToComponentsWithDependencyCheck(
|
||||
item: ItemStack,
|
||||
isEventHandled: () -> Boolean,
|
||||
action: (CustomComponent) -> Unit
|
||||
): Boolean {
|
||||
if (item.type.isAir) return false
|
||||
val meta = item.itemMeta ?: return false
|
||||
val pdc = meta.persistentDataContainer
|
||||
|
||||
for (key in pdc.keys) {
|
||||
// Stop if event is already handled by a previous component
|
||||
if (isEventHandled()) return true
|
||||
|
||||
val component = ComponentRegistry.get(key) ?: continue
|
||||
|
||||
// Check if this item has all required data component dependencies
|
||||
// This ensures the component only triggers on items that
|
||||
// actually have the necessary data components active
|
||||
val hasAllDependencies = component.dataComponentDependencies.all { dep ->
|
||||
item.hasData(dep)
|
||||
}
|
||||
if (!hasAllDependencies) continue
|
||||
|
||||
action(component)
|
||||
}
|
||||
|
||||
return isEventHandled()
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches to all components on an item without checking dependencies.
|
||||
* Use this for events that don't rely on data component triggers.
|
||||
*/
|
||||
private fun dispatchToComponents(item: ItemStack, action: (CustomComponent) -> Unit) {
|
||||
if (item.type.isAir) return
|
||||
val meta = item.itemMeta ?: return
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user