diff --git a/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java b/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java index 569a1983..2762db8a 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java @@ -7,6 +7,8 @@ package kr.toxicity.model.api.nms; import kr.toxicity.model.api.event.ModelDamageSource; +import kr.toxicity.model.api.event.ModelInteractAtEvent; +import kr.toxicity.model.api.event.ModelInteractEvent; import kr.toxicity.model.api.platform.PlatformEntity; import org.jetbrains.annotations.NotNull; @@ -49,6 +51,8 @@ public interface HitBoxListener { return new Builder() .sync(this::sync) .damage(this::damage) + .interact(this::interact) + .interactAt(this::interactAt) .remove(this::remove) .mount(this::mount) .dismount(this::dismount); @@ -63,12 +67,16 @@ class Builder { private static final Consumer DEFAULT_SYNC = h -> {}; private static final OnDamage DEFAULT_DAMAGE = (h, s, d) -> false; + private static final Consumer DEFAULT_INTERACT = h -> {}; + private static final Consumer DEFAULT_INTERACT_AT = h -> {}; private static final Consumer DEFAULT_REMOVE = h -> {}; private static final BiConsumer DEFAULT_MOUNT = (h, e) -> {}; private static final BiConsumer DEFAULT_DISMOUNT = (h, e) -> {}; private Consumer sync = DEFAULT_SYNC; private OnDamage damage = DEFAULT_DAMAGE; + private Consumer interact = DEFAULT_INTERACT; + private Consumer interactAt = DEFAULT_INTERACT_AT; private Consumer remove = DEFAULT_REMOVE; private BiConsumer mount = DEFAULT_MOUNT; private BiConsumer dismount = DEFAULT_DISMOUNT; @@ -103,6 +111,30 @@ private Builder() { return this; } + /** + * Adds an interact handler. + * + * @param interact the interact handler + * @return this builder + * @since 2.0.2 + */ + public @NotNull Builder interact(@NotNull Consumer interact) { + this.interact = this.interact == DEFAULT_INTERACT ? interact : this.interact.andThen(interact); + return this; + } + + /** + * Adds an interact-at handler. + * + * @param interactAt the interact-at handler + * @return this builder + * @since 2.0.2 + */ + public @NotNull Builder interactAt(@NotNull Consumer interactAt) { + this.interactAt = this.interactAt == DEFAULT_INTERACT_AT ? interactAt : this.interactAt.andThen(interactAt); + return this; + } + /** * Adds a remove handler. * @@ -157,6 +189,16 @@ public boolean damage(@NotNull HitBox hitBox, @NotNull ModelDamageSource source, return Builder.this.damage.event(hitBox, source, damage); } + @Override + public void interact(@NotNull ModelInteractEvent event) { + interact.accept(event); + } + + @Override + public void interactAt(@NotNull ModelInteractAtEvent event) { + interactAt.accept(event); + } + @Override public void remove(@NotNull HitBox hitBox) { remove.accept(hitBox); @@ -224,6 +266,22 @@ interface OnDamage { */ boolean damage(@NotNull HitBox hitBox, @NotNull ModelDamageSource source, double damage); + /** + * Called when the hitbox receives an interaction. + * + * @param event the interaction event + * @since 2.0.2 + */ + void interact(@NotNull ModelInteractEvent event); + + /** + * Called when the hitbox receives an interaction at a specific position. + * + * @param event the interaction-at event + * @since 2.0.2 + */ + void interactAt(@NotNull ModelInteractAtEvent event); + /** * Called when the hitbox is removed. * diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java index 3504499d..70249636 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java @@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; +import java.util.function.BiFunction; import java.util.function.BiPredicate; import java.util.function.Predicate; import java.util.function.Supplier; @@ -678,6 +679,26 @@ public boolean replace(@NotNull Predicate filter, @NotNull String //--- Update action --- + /** + * Registers a hitbox-listener builder hook that is applied when hitboxes are created. + *

+ * This delegates to {@link kr.toxicity.model.api.bone.BoneEventDispatcher#handleCreateHitBox(BiFunction)} + * in this tracker's render pipeline event dispatcher. + *

+ * + *
{@code
+     * tracker.listenHitBox((bone, builder) -> builder.interact(event -> {
+     *     // custom interaction handling
+     * }));
+     * }
+ * + * @param function the hitbox listener builder transformer + * @since 2.0.2 + */ + public void listenHitBox(@NotNull BiFunction function) { + pipeline.eventDispatcher().handleCreateHitBox(function); + } + /** * Creates a hitbox for bones matching a predicate. * diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt index 07bfd05e..b0224cc1 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt @@ -345,6 +345,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }) + listener.interact(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS @@ -356,6 +357,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }, vec.toBukkit()) + listener.interactAt(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand, vec)) return InteractionResult.SUCCESS diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt index 5c783dbf..5cfe0535 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt @@ -358,6 +358,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }) + listener.interact(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS @@ -369,6 +370,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }, vec.toBukkit()) + listener.interactAt(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand, vec)) return InteractionResult.SUCCESS diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt index c175ece5..ee44e6cf 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt @@ -364,6 +364,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }) + listener.interact(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS @@ -375,6 +376,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }, vec.toBukkit()) + listener.interactAt(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand, vec)) return InteractionResult.SUCCESS diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt index cf44486f..2c0ec36e 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt @@ -365,6 +365,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }) + listener.interact(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS @@ -376,6 +377,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }, vec.toBukkit()) + listener.interactAt(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand, vec)) return InteractionResult.SUCCESS diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt index 5272f80d..649a235b 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt @@ -365,6 +365,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }) + listener.interact(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS @@ -376,6 +377,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }, vec.toBukkit()) + listener.interactAt(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand, vec)) return InteractionResult.SUCCESS diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt index fb1b3199..7ef2f4d1 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt @@ -365,6 +365,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }) + listener.interact(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS @@ -376,6 +377,7 @@ internal class HitBoxImpl( MAIN_HAND -> ModelInteractionHand.RIGHT OFF_HAND -> ModelInteractionHand.LEFT }, vec.toBukkit()) + listener.interactAt(interact) if (!interact.call().triggered()) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand, vec)) return InteractionResult.SUCCESS diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt index 7dcce353..e5a12cb1 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt @@ -419,20 +419,22 @@ class HitBoxEntityImpl( if (player === delegate) { return InteractionResult.FAIL } + val serverPlayer = player as ServerPlayer val interact = ModelInteractEvent( - (player as ServerPlayer).connection.wrap(), + serverPlayer.connection.wrap(), this, when (hand) { InteractionHand.MAIN_HAND -> ModelInteractionHand.RIGHT InteractionHand.OFF_HAND -> ModelInteractionHand.LEFT } ) + listener.interact(interact) if (!interact.call().triggered()) { return InteractionResult.FAIL } - player.connection.handleInteract( + serverPlayer.connection.handleInteract( ServerboundInteractPacket.createInteractionPacket( delegate, player.isShiftKeyDown, @@ -446,9 +448,10 @@ class HitBoxEntityImpl( if (player === delegate) { return InteractionResult.FAIL } + val serverPlayer = player as ServerPlayer val interact = ModelInteractAtEvent( - (player as ServerPlayer).connection.wrap(), + serverPlayer.connection.wrap(), this, when (hand) { InteractionHand.MAIN_HAND -> ModelInteractionHand.RIGHT @@ -456,12 +459,12 @@ class HitBoxEntityImpl( }, vec.toVector3f() ) - + listener.interactAt(interact) if (!interact.call().triggered()) { return InteractionResult.FAIL } - player.connection.handleInteract( + serverPlayer.connection.handleInteract( ServerboundInteractPacket.createInteractionPacket( delegate, player.isShiftKeyDown,