From ed198f062c2cba96d6df3eebf0f3b457f3a29bdf Mon Sep 17 00:00:00 2001 From: Budschie <65289971+Budschie@users.noreply.github.com> Date: Sat, 3 Sep 2022 21:11:10 +0200 Subject: [PATCH] [1.19.x] Make LivingSetAttackTargetEvent compatible with the Brain/Behavior system. (Port of PR #8918) (#8954) --- .../net/minecraft/world/entity/Mob.java.patch | 11 +- .../ai/behavior/StartAttacking.java.patch | 16 +++ .../net/minecraftforge/common/ForgeHooks.java | 19 ++++ .../living/LivingChangeTargetEvent.java | 104 ++++++++++++++++++ .../living/LivingSetAttackTargetEvent.java | 41 ++++++- .../LivingSetAttackTargetEventTest.java | 44 ++++++++ src/test/resources/META-INF/mods.toml | 3 +- 7 files changed, 228 insertions(+), 10 deletions(-) create mode 100644 patches/minecraft/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch create mode 100644 src/main/java/net/minecraftforge/event/entity/living/LivingChangeTargetEvent.java create mode 100644 src/test/java/net/minecraftforge/debug/entity/living/LivingSetAttackTargetEventTest.java diff --git a/patches/minecraft/net/minecraft/world/entity/Mob.java.patch b/patches/minecraft/net/minecraft/world/entity/Mob.java.patch index 71fce5b7df..28da8713ac 100644 --- a/patches/minecraft/net/minecraft/world/entity/Mob.java.patch +++ b/patches/minecraft/net/minecraft/world/entity/Mob.java.patch @@ -1,10 +1,15 @@ --- a/net/minecraft/world/entity/Mob.java +++ b/net/minecraft/world/entity/Mob.java -@@ -211,6 +_,7 @@ +@@ -210,7 +_,11 @@ + } public void m_6710_(@Nullable LivingEntity p_21544_) { - this.f_21362_ = p_21544_; -+ net.minecraftforge.common.ForgeHooks.onLivingSetAttackTarget(this, p_21544_); +- this.f_21362_ = p_21544_; ++ net.minecraftforge.event.entity.living.LivingChangeTargetEvent changeTargetEvent = net.minecraftforge.common.ForgeHooks.onLivingChangeTarget(this, p_21544_, net.minecraftforge.event.entity.living.LivingChangeTargetEvent.LivingTargetType.MOB_TARGET); ++ if(!changeTargetEvent.isCanceled()) { ++ this.f_21362_ = changeTargetEvent.getNewTarget(); ++ net.minecraftforge.common.ForgeHooks.onLivingSetAttackTarget(this, this.f_21362_); // TODO: Remove in 1.20 ++ } } public boolean m_6549_(EntityType p_21399_) { diff --git a/patches/minecraft/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch b/patches/minecraft/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch new file mode 100644 index 0000000000..d38a1e6c6c --- /dev/null +++ b/patches/minecraft/net/minecraft/world/entity/ai/behavior/StartAttacking.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/entity/ai/behavior/StartAttacking.java ++++ b/net/minecraft/world/entity/ai/behavior/StartAttacking.java +@@ -46,7 +_,11 @@ + } + + public static void m_24213_(E p_24214_, LivingEntity p_24215_) { +- p_24214_.m_6274_().m_21879_(MemoryModuleType.f_26372_, p_24215_); +- p_24214_.m_6274_().m_21936_(MemoryModuleType.f_26326_); ++ net.minecraftforge.event.entity.living.LivingChangeTargetEvent changeTargetEvent = net.minecraftforge.common.ForgeHooks.onLivingChangeTarget(p_24214_, p_24215_, net.minecraftforge.event.entity.living.LivingChangeTargetEvent.LivingTargetType.BEHAVIOR_TARGET); ++ if(!changeTargetEvent.isCanceled()) { ++ p_24214_.m_6274_().m_21879_(MemoryModuleType.f_26372_, changeTargetEvent.getNewTarget()); ++ p_24214_.m_6274_().m_21936_(MemoryModuleType.f_26326_); ++ net.minecraftforge.common.ForgeHooks.onLivingSetAttackTarget(p_24214_, changeTargetEvent.getNewTarget(), net.minecraftforge.event.entity.living.LivingChangeTargetEvent.LivingTargetType.BEHAVIOR_TARGET); // TODO: Remove in 1.20 ++ } + } + } diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index f88dae7fba..f560bc00bf 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -118,12 +118,14 @@ import net.minecraftforge.event.entity.EntityTravelToDimensionEvent; import net.minecraftforge.event.entity.item.ItemTossEvent; import net.minecraftforge.event.entity.living.EnderManAngerEvent; import net.minecraftforge.event.entity.living.LivingAttackEvent; +import net.minecraftforge.event.entity.living.LivingChangeTargetEvent; import net.minecraftforge.event.entity.living.LivingDamageEvent; import net.minecraftforge.event.entity.living.LivingDeathEvent; import net.minecraftforge.event.entity.living.LivingDropsEvent; import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.event.entity.living.LivingEvent.LivingJumpEvent; import net.minecraftforge.event.entity.living.LivingEvent.LivingTickEvent; +import net.minecraftforge.event.entity.living.LivingChangeTargetEvent.ILivingTargetType; import net.minecraftforge.event.entity.living.LivingFallEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent; import net.minecraftforge.event.entity.living.LivingKnockBackEvent; @@ -263,11 +265,28 @@ public class ForgeHooks //Optifine Helper Functions u.u, these are here specifically for Optifine //Note: When using Optifine, these methods are invoked using reflection, which //incurs a major performance penalty. + // TODO: Remove in 1.20 + @Deprecated(since = "1.19.2", forRemoval = true) public static void onLivingSetAttackTarget(LivingEntity entity, LivingEntity target) { MinecraftForge.EVENT_BUS.post(new LivingSetAttackTargetEvent(entity, target)); } + // TODO: Remove in 1.20 + @Deprecated(since = "1.19.2", forRemoval = true) + public static void onLivingSetAttackTarget(LivingEntity entity, LivingEntity target, ILivingTargetType targetType) + { + MinecraftForge.EVENT_BUS.post(new LivingSetAttackTargetEvent(entity, target, targetType)); + } + + public static LivingChangeTargetEvent onLivingChangeTarget(LivingEntity entity, LivingEntity originalTarget, ILivingTargetType targetType) + { + LivingChangeTargetEvent event = new LivingChangeTargetEvent(entity, originalTarget, targetType); + MinecraftForge.EVENT_BUS.post(event); + + return event; + } + public static boolean onLivingTick(LivingEntity entity) { return MinecraftForge.EVENT_BUS.post(new LivingTickEvent(entity)); diff --git a/src/main/java/net/minecraftforge/event/entity/living/LivingChangeTargetEvent.java b/src/main/java/net/minecraftforge/event/entity/living/LivingChangeTargetEvent.java new file mode 100644 index 0000000000..e01d442be8 --- /dev/null +++ b/src/main/java/net/minecraftforge/event/entity/living/LivingChangeTargetEvent.java @@ -0,0 +1,104 @@ +package net.minecraftforge.event.entity.living; + +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.behavior.StartAttacking; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.Cancelable; + +/** + * This event allows you to change the target an entity has.
+ * This event is fired before {@link LivingSetAttackTargetEvent}.
+ *
+ * This event is fired via the {@link ForgeHooks#onLivingChangeTarget(LivingEntity, LivingEntity, ILivingTargetType)}
+ *
+ * {@link #getOriginalTarget()} returns the target that should originally be set. + * The return value cannot be affected by calling {@link #setNewTarget(LivingEntity)}.
+ * {@link #getNewTarget()} returns the new target that this entity will have. + * The return value can be affected by calling {@link #setNewTarget(LivingEntity)}.
+ * {@link #getTargetType()} returns the target type that caused the change of targets.
+ *
+ * This event is {@link net.minecraftforge.eventbus.api.Cancelable}.
+ *
+ * If you cancel this event, the target will not be changed and it will stay the same. + * Cancelling this event will prevent {@link LivingSetAttackTargetEvent} from being posted.
+ *
+ * This event does not have a result. {@link HasResult}
+ *
+ * This event is fired on the {@link MinecraftForge#EVENT_BUS}. + */ +@Cancelable +public class LivingChangeTargetEvent extends LivingEvent +{ + private final ILivingTargetType targetType; + private final LivingEntity originalTarget; + private LivingEntity newTarget; + + public LivingChangeTargetEvent(LivingEntity entity, LivingEntity originalTarget, ILivingTargetType targetType) + { + super(entity); + this.originalTarget = originalTarget; + this.newTarget = originalTarget; + this.targetType = targetType; + } + + /** + * {@return the new target of this entity.} + */ + public LivingEntity getNewTarget() + { + return newTarget; + } + + /** + * Sets the new target this entity shall have. + * @param newTarget The new target of this entity. + */ + public void setNewTarget(LivingEntity newTarget) + { + this.newTarget = newTarget; + } + + /** + * {@return the living target type.} + */ + public ILivingTargetType getTargetType() + { + return targetType; + } + + /** + * {@return the original entity MC intended to use as a target before firing this event.} + */ + public LivingEntity getOriginalTarget() + { + return originalTarget; + } + + + /** + * A living target type indicates what kind of system caused a change of + * targets. For a list of default target types, take a look at + * {@link LivingTargetType}. + */ + public static interface ILivingTargetType + { + + } + + /** + * This enum contains two default living target types. + */ + public static enum LivingTargetType implements ILivingTargetType + { + /** + * This target type indicates that the target has been set by calling {@link Mob#setTarget(LivingEntity)}. + */ + MOB_TARGET, + /** + * This target type indicates that the target has been set by the {@link StartAttacking} behavior. + */ + BEHAVIOR_TARGET; + } +} diff --git a/src/main/java/net/minecraftforge/event/entity/living/LivingSetAttackTargetEvent.java b/src/main/java/net/minecraftforge/event/entity/living/LivingSetAttackTargetEvent.java index c0d565400c..8b9a41bee8 100644 --- a/src/main/java/net/minecraftforge/event/entity/living/LivingSetAttackTargetEvent.java +++ b/src/main/java/net/minecraftforge/event/entity/living/LivingSetAttackTargetEvent.java @@ -7,17 +7,23 @@ package net.minecraftforge.event.entity.living; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.ai.behavior.StartAttacking; import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingChangeTargetEvent.ILivingTargetType; +import net.minecraftforge.event.entity.living.LivingChangeTargetEvent.LivingTargetType; /** + * This event is deprecated. Use {@link LivingChangeTargetEvent} instead.
+ *
* LivingSetAttackTargetEvent is fired when an Entity sets a target to attack.
* This event is fired whenever an Entity sets a target to attack in - * {@link Mob#setTarget(LivingEntity)}.
+ * {@link Mob#setTarget(LivingEntity)} or {@link StartAttacking#setAttackTarget(Mob, LivingEntity)}
*
* This event is fired via the {@link ForgeHooks#onLivingSetAttackTarget(LivingEntity, LivingEntity)}.
*
- * {@link #target} contains the newly targeted Entity.
+ * {@link #getTarget} returns the newly targeted Entity.
+ * {@link #getTargetType()} returns the target type that caused the change of targets.
*
* This event is not {@link net.minecraftforge.eventbus.api.Cancelable}.
*
@@ -25,18 +31,41 @@ import net.minecraftforge.common.MinecraftForge; *
* This event is fired on the {@link MinecraftForge#EVENT_BUS}. **/ +// TODO: Remove in 1.20 +@Deprecated(since = "1.19.2", forRemoval = true) public class LivingSetAttackTargetEvent extends LivingEvent { - - private final LivingEntity target; + private final ILivingTargetType targetType; + private final LivingEntity originalTarget; + public LivingSetAttackTargetEvent(LivingEntity entity, LivingEntity target) { super(entity); - this.target = target; + this.targetType = LivingTargetType.MOB_TARGET; + this.originalTarget = target; + } + + public LivingSetAttackTargetEvent(LivingEntity entity, LivingEntity target, ILivingTargetType targetType) + { + super(entity); + this.targetType = targetType; + this.originalTarget = target; } + /** + * {@return the target this living entity had after changing its target to a new + * target, but before posting this event.} + */ public LivingEntity getTarget() { - return target; + return originalTarget; + } + + /** + * {@return the target type of this event.} + */ + public ILivingTargetType getTargetType() + { + return targetType; } } diff --git a/src/test/java/net/minecraftforge/debug/entity/living/LivingSetAttackTargetEventTest.java b/src/test/java/net/minecraftforge/debug/entity/living/LivingSetAttackTargetEventTest.java new file mode 100644 index 0000000000..adb7ac065a --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/entity/living/LivingSetAttackTargetEventTest.java @@ -0,0 +1,44 @@ +package net.minecraftforge.debug.entity.living; + +import net.minecraft.world.entity.monster.piglin.AbstractPiglin; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.Items; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.living.LivingChangeTargetEvent; +import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod("living_set_attack_target_event_test") +public class LivingSetAttackTargetEventTest +{ + public static final boolean ENABLE = true; + + public LivingSetAttackTargetEventTest() + { + if(ENABLE) + { + MinecraftForge.EVENT_BUS.register(this); + } + } + + @SubscribeEvent + public void onLivingSetAttackTarget(LivingSetAttackTargetEvent event) + { + // Make piglins die when they start attacking a player who is not holding a stick in their main hand. + if (event.getTarget() instanceof Player player && event.getEntity() instanceof AbstractPiglin piglin && player.getMainHandItem().getItem() != Items.STICK) + { + event.getEntity().kill(); + } + } + + @SubscribeEvent + public void onLivingChangeTargetEvent(LivingChangeTargetEvent event) + { + // Prevents the piglin from attacking the player if they hold a stick in their hands. + if(event.getNewTarget() instanceof Player player && event.getEntity() instanceof AbstractPiglin piglin && player.getMainHandItem().getItem() == Items.STICK) + { + event.setCanceled(true); + } + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 00f559698f..d8a6fa92b3 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -247,6 +247,8 @@ modId="emissive_elements_test" [[mods]] modId="anvil_update_event_fix" [[mods]] +modId="living_set_attack_target_event_test" +[[mods]] modId="item_use_animation_test" [[mods]] modId="custom_color_resolver_test" @@ -254,5 +256,4 @@ modId="custom_color_resolver_test" modId="custom_item_decorations_test" - # ADD ABOVE THIS LINE