diff --git a/common/src/main/java/dev/architectury/event/events/common/PlayerEvent.java b/common/src/main/java/dev/architectury/event/events/common/PlayerEvent.java index b9975081..5a30e9b6 100644 --- a/common/src/main/java/dev/architectury/event/events/common/PlayerEvent.java +++ b/common/src/main/java/dev/architectury/event/events/common/PlayerEvent.java @@ -27,11 +27,14 @@ import net.minecraft.advancements.Advancement; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; import org.jetbrains.annotations.Nullable; @@ -92,6 +95,10 @@ public interface PlayerEvent { * @see FillBucket#fill(Player, Level, ItemStack, HitResult) */ Event FILL_BUCKET = EventFactory.createCompoundEventResult(); + /** + * @see AttackEntity#attack(Player, Level, Entity, InteractionHand, EntityHitResult) + */ + Event ATTACK_ENTITY = EventFactory.createEventResult(); interface PlayerJoin { /** @@ -262,4 +269,20 @@ public interface PlayerEvent { */ CompoundEventResult fill(Player player, Level level, ItemStack stack, @Nullable HitResult target); } + + interface AttackEntity { + /** + * Invoked when a player is about to attack an entity using left-click. + * Equivalent to Forge's {@code AttackEntityEvent} and Fabric API's {@code AttackEntityCallback} events. + * + * @param player The player attacking the entity. + * @param level The level the player is in. + * @param target The entity about to be attacked. + * @param hand The hand the player is using. + * @param result The entity hit result. + * @return An {@link EventResult} determining the outcome of the event, + * the attack may be cancelled by the result. + */ + EventResult attack(Player player, Level level, Entity target, InteractionHand hand, @Nullable EntityHitResult result); + } } diff --git a/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java b/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java index e5ad152d..ebf842b5 100644 --- a/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java +++ b/fabric/src/main/java/dev/architectury/event/fabric/EventHandlerImpl.java @@ -35,6 +35,7 @@ import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; import net.fabricmc.fabric.api.event.player.AttackBlockCallback; +import net.fabricmc.fabric.api.event.player.AttackEntityCallback; import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.event.player.UseItemCallback; import net.fabricmc.fabric.api.loot.v2.LootTableEvents; @@ -74,6 +75,7 @@ public class EventHandlerImpl { UseItemCallback.EVENT.register((player, world, hand) -> InteractionEvent.RIGHT_CLICK_ITEM.invoker().click(player, hand).asMinecraft()); UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> InteractionEvent.RIGHT_CLICK_BLOCK.invoker().click(player, hand, hitResult.getBlockPos(), hitResult.getDirection()).asMinecraft()); AttackBlockCallback.EVENT.register((player, world, hand, pos, face) -> InteractionEvent.LEFT_CLICK_BLOCK.invoker().click(player, hand, pos, face).asMinecraft()); + AttackEntityCallback.EVENT.register((player, world, hand, entity, hitResult) -> PlayerEvent.ATTACK_ENTITY.invoker().attack(player, world, entity, hand, hitResult).asMinecraft()); LootTableEvents.MODIFY.register((resourceManager, lootManager, id, tableBuilder, source) -> LootEvent.MODIFY_LOOT_TABLE.invoker().modifyLootTable(lootManager, id, new LootTableModificationContextImpl(tableBuilder), source.isBuiltin())); } diff --git a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java index 52052178..a84c50a6 100644 --- a/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java +++ b/forge/src/main/java/dev/architectury/event/forge/EventHandlerImplCommon.java @@ -431,6 +431,14 @@ public class EventHandlerImplCommon { LootEvent.MODIFY_LOOT_TABLE.invoker().modifyLootTable(event.getLootTableManager(), event.getName(), new LootTableModificationContextImpl(event.getTable()), true); } + @SubscribeEvent(priority = EventPriority.HIGH) + public static void event(AttackEntityEvent event) { + EventResult result = PlayerEvent.ATTACK_ENTITY.invoker().attack(event.getPlayer(), event.getPlayer().level, event.getTarget(), event.getPlayer().getUsedItemHand(), null); + if (result.isFalse()) { + event.setCanceled(true); + } + } + public interface WorldEventAttachment { LevelAccessor architectury$getAttachedLevel();