From aa6f268c74941b71ae2aa5f3a0b9ab634121c689 Mon Sep 17 00:00:00 2001 From: LexManos Date: Mon, 29 Jan 2024 13:13:28 -0800 Subject: [PATCH] Fix cases where LivingConversionEvents were not fired for vanilla conversions. Closes #9850 --- .../entity/animal/MushroomCow.java.patch | 9 +++- .../entity/animal/frog/Tadpole.java.patch | 18 ++++++++ .../world/entity/monster/Husk.java.patch | 10 +++++ .../world/entity/monster/Skeleton.java.patch | 16 ++++++++ .../world/entity/monster/Zombie.java.patch | 34 +++++++-------- .../world/entity/npc/Villager.java.patch | 2 +- .../entity/living/LivingConversionEvent.java | 41 +++++++++++-------- .../resources/META-INF/accesstransformer.cfg | 1 + 8 files changed, 93 insertions(+), 38 deletions(-) create mode 100644 patches/minecraft/net/minecraft/world/entity/animal/frog/Tadpole.java.patch create mode 100644 patches/minecraft/net/minecraft/world/entity/monster/Husk.java.patch create mode 100644 patches/minecraft/net/minecraft/world/entity/monster/Skeleton.java.patch diff --git a/patches/minecraft/net/minecraft/world/entity/animal/MushroomCow.java.patch b/patches/minecraft/net/minecraft/world/entity/animal/MushroomCow.java.patch index 5b54a61b24..127d1e86bf 100644 --- a/patches/minecraft/net/minecraft/world/entity/animal/MushroomCow.java.patch +++ b/patches/minecraft/net/minecraft/world/entity/animal/MushroomCow.java.patch @@ -18,7 +18,7 @@ this.shear(SoundSource.PLAYERS); this.gameEvent(GameEvent.SHEAR, p_28941_); if (!this.level().isClientSide) { -@@ -141,7 +_,17 @@ +@@ -141,9 +_,20 @@ } } @@ -35,10 +35,15 @@ + private java.util.List shearInternal(SoundSource p_28924_) { this.level().playSound((Player)null, this, SoundEvents.MOOSHROOM_SHEAR, p_28924_, 1.0F, 1.0F); if (!this.level().isClientSide()) { ++ if (!net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.COW, time -> {})) return java.util.Collections.emptyList(); Cow cow = EntityType.COW.create(this.level()); -@@ -163,11 +_,14 @@ + if (cow != null) { + ((ServerLevel)this.level()).sendParticles(ParticleTypes.EXPLOSION, this.getX(), this.getY(0.5D), this.getZ(), 1, 0.0D, 0.0D, 0.0D, 0.0D); +@@ -162,12 +_,16 @@ + cow.setInvulnerable(this.isInvulnerable()); this.level().addFreshEntity(cow); ++ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, cow); + java.util.List items = new java.util.ArrayList<>(); for(int i = 0; i < 5; ++i) { diff --git a/patches/minecraft/net/minecraft/world/entity/animal/frog/Tadpole.java.patch b/patches/minecraft/net/minecraft/world/entity/animal/frog/Tadpole.java.patch new file mode 100644 index 0000000000..58758f8449 --- /dev/null +++ b/patches/minecraft/net/minecraft/world/entity/animal/frog/Tadpole.java.patch @@ -0,0 +1,18 @@ +--- a/net/minecraft/world/entity/animal/frog/Tadpole.java ++++ b/net/minecraft/world/entity/animal/frog/Tadpole.java +@@ -197,6 +_,7 @@ + private void ageUp() { + Level $$1 = this.level(); + if ($$1 instanceof ServerLevel serverlevel) { ++ if (!net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.FROG, timer -> this.ticksToBeFrog = this.age + timer)) return; + Frog frog = EntityType.FROG.create(this.level()); + if (frog != null) { + frog.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); +@@ -210,6 +_,7 @@ + frog.setPersistenceRequired(); + this.playSound(SoundEvents.TADPOLE_GROW_UP, 0.15F, 1.0F); + serverlevel.addFreshEntityWithPassengers(frog); ++ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, frog); + this.discard(); + } + } diff --git a/patches/minecraft/net/minecraft/world/entity/monster/Husk.java.patch b/patches/minecraft/net/minecraft/world/entity/monster/Husk.java.patch new file mode 100644 index 0000000000..1e23a3bc6c --- /dev/null +++ b/patches/minecraft/net/minecraft/world/entity/monster/Husk.java.patch @@ -0,0 +1,10 @@ +--- a/net/minecraft/world/entity/monster/Husk.java ++++ b/net/minecraft/world/entity/monster/Husk.java +@@ -62,6 +_,7 @@ + } + + protected void doUnderWaterConversion() { ++ if (!net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.ZOMBIE, (timer) -> this.conversionTime = timer)) return; + this.convertToZombieType(EntityType.ZOMBIE); + if (!this.isSilent()) { + this.level().levelEvent((Player)null, 1041, this.blockPosition(), 0); diff --git a/patches/minecraft/net/minecraft/world/entity/monster/Skeleton.java.patch b/patches/minecraft/net/minecraft/world/entity/monster/Skeleton.java.patch new file mode 100644 index 0000000000..2ab2956ac0 --- /dev/null +++ b/patches/minecraft/net/minecraft/world/entity/monster/Skeleton.java.patch @@ -0,0 +1,16 @@ +--- a/net/minecraft/world/entity/monster/Skeleton.java ++++ b/net/minecraft/world/entity/monster/Skeleton.java +@@ -83,10 +_,12 @@ + } + + protected void doFreezeConversion() { +- this.convertTo(EntityType.STRAY, true); ++ if (!net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.STRAY, (timer) -> this.conversionTime = timer)) return; ++ var result = this.convertTo(EntityType.STRAY, true); + if (!this.isSilent()) { + this.level().levelEvent((Player)null, 1048, this.blockPosition(), 0); + } ++ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, result); + + } + diff --git a/patches/minecraft/net/minecraft/world/entity/monster/Zombie.java.patch b/patches/minecraft/net/minecraft/world/entity/monster/Zombie.java.patch index bd01b153e8..f7920c59c6 100644 --- a/patches/minecraft/net/minecraft/world/entity/monster/Zombie.java.patch +++ b/patches/minecraft/net/minecraft/world/entity/monster/Zombie.java.patch @@ -1,14 +1,13 @@ --- a/net/minecraft/world/entity/monster/Zombie.java +++ b/net/minecraft/world/entity/monster/Zombie.java -@@ -193,7 +_,7 @@ - if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { - if (this.isUnderWaterConverting()) { - --this.conversionTime; -- if (this.conversionTime < 0) { -+ if (this.conversionTime < 0 && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.DROWNED, (timer) -> this.conversionTime = timer)) { - this.doUnderWaterConversion(); - } - } else if (this.convertsInWater()) { +@@ -243,6 +_,7 @@ + } + + protected void doUnderWaterConversion() { ++ if (!net.minecraftforge.event.ForgeEventFactory.canLivingConvert(this, EntityType.DROWNED, (timer) -> this.conversionTime = timer)) return; + this.convertToZombieType(EntityType.DROWNED); + if (!this.isSilent()) { + this.level().levelEvent((Player)null, 1040, this.blockPosition(), 0); @@ -255,6 +_,7 @@ if (zombie != null) { zombie.handleAttributes(zombie.level().getCurrentDifficultyAt(zombie.blockPosition()).getSpecialMultiplier()); @@ -43,20 +42,21 @@ zombie.setTarget(livingentity); zombie.finalizeSpawn(serverlevel, this.level().getCurrentDifficultyAt(zombie.blockPosition()), MobSpawnType.REINFORCEMENT, (SpawnGroupData)null, (CompoundTag)null); serverlevel.addFreshEntityWithPassengers(zombie); -@@ -376,7 +_,7 @@ - - public boolean killedEntity(ServerLevel p_219160_, LivingEntity p_219161_) { - boolean flag = super.killedEntity(p_219160_, p_219161_); -- if ((p_219160_.getDifficulty() == Difficulty.NORMAL || p_219160_.getDifficulty() == Difficulty.HARD) && p_219161_ instanceof Villager villager) { -+ if ((p_219160_.getDifficulty() == Difficulty.NORMAL || p_219160_.getDifficulty() == Difficulty.HARD) && p_219161_ instanceof Villager villager && net.minecraftforge.event.ForgeEventFactory.canLivingConvert(p_219161_, EntityType.ZOMBIE_VILLAGER, (timer) -> {})) { - if (p_219160_.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { +@@ -381,6 +_,9 @@ return flag; } + ++ if (!net.minecraftforge.event.ForgeEventFactory.canLivingConvert(p_219161_, EntityType.ZOMBIE_VILLAGER, (timer) -> {})) ++ return flag; ++ + ZombieVillager zombievillager = villager.convertTo(EntityType.ZOMBIE_VILLAGER, false); + if (zombievillager != null) { + zombievillager.finalizeSpawn(p_219160_, p_219160_.getCurrentDifficultyAt(zombievillager.blockPosition()), MobSpawnType.CONVERSION, new Zombie.ZombieGroupData(false, true), (CompoundTag)null); @@ -388,6 +_,7 @@ zombievillager.setGossips(villager.getGossips().store(NbtOps.INSTANCE)); zombievillager.setTradeOffers(villager.getOffers().createTag()); zombievillager.setVillagerXp(villager.getVillagerXp()); -+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(p_219161_, zombievillager); ++ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(p_219161_, zombievillager); if (!this.isSilent()) { p_219160_.levelEvent((Player)null, 1026, this.blockPosition(), 0); } diff --git a/patches/minecraft/net/minecraft/world/entity/npc/Villager.java.patch b/patches/minecraft/net/minecraft/world/entity/npc/Villager.java.patch index 5b0f60783e..669c59a8ff 100644 --- a/patches/minecraft/net/minecraft/world/entity/npc/Villager.java.patch +++ b/patches/minecraft/net/minecraft/world/entity/npc/Villager.java.patch @@ -32,7 +32,7 @@ } witch.setPersistenceRequired(); -+ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, witch); ++ net.minecraftforge.event.ForgeEventFactory.onLivingConvert(this, witch); p_35409_.addFreshEntityWithPassengers(witch); this.releaseAllPois(); this.discard(); diff --git a/src/main/java/net/minecraftforge/event/entity/living/LivingConversionEvent.java b/src/main/java/net/minecraftforge/event/entity/living/LivingConversionEvent.java index 71c91ea0aa..a3242ac876 100644 --- a/src/main/java/net/minecraftforge/event/entity/living/LivingConversionEvent.java +++ b/src/main/java/net/minecraftforge/event/entity/living/LivingConversionEvent.java @@ -11,10 +11,22 @@ import net.minecraftforge.eventbus.api.Cancelable; import java.util.function.Consumer; -public class LivingConversionEvent extends LivingEvent -{ - public LivingConversionEvent(LivingEntity entity) - { +/** + * Currently known conversions: + * Pig -> Zombie Piglin when struck by lightning + * Villager -> Zombie Villager when killed by a zombie + * Zombie -> Drowned when under water + * Husk -> Zombie when under water + * Zombie Villager -> Villager + * Hoglin -> Zogline when in overworld + * Piglin/Piglin Brute -> Zombie Pigman when in overworld + * Villager -> Witch when struck by lightning + * Skeleton -> Stray when sitting in snow + * Tadpole -> Frog when it grows up + * Mushroom Cow -> Cow when sheared + */ +public class LivingConversionEvent extends LivingEvent { + public LivingConversionEvent(LivingEntity entity) { super(entity); } @@ -30,13 +42,11 @@ public class LivingConversionEvent extends LivingEvent * If cancelled, the replacement will not occur */ @Cancelable - public static class Pre extends LivingConversionEvent - { + public static class Pre extends LivingConversionEvent { private final EntityType outcome; private final Consumer timer; - public Pre(LivingEntity entity, EntityType outcome, Consumer timer) - { + public Pre(LivingEntity entity, EntityType outcome, Consumer timer) { super(entity); this.outcome = outcome; this.timer = timer; @@ -47,8 +57,7 @@ public class LivingConversionEvent extends LivingEvent * converting to * @return the entity type of the new entity */ - public EntityType getOutcome() - { + public EntityType getOutcome() { return outcome; } @@ -60,8 +69,7 @@ public class LivingConversionEvent extends LivingEvent * Not every conversion is applicable for this * @param ticks timer ticks */ - public void setConversionTimer(int ticks) - { + public void setConversionTimer(int ticks) { timer.accept(ticks); } } @@ -71,12 +79,10 @@ public class LivingConversionEvent extends LivingEvent * itself with another entity. * The old living entity is likely to be removed right after this event. */ - public static class Post extends LivingConversionEvent - { + public static class Post extends LivingConversionEvent { private final LivingEntity outcome; - public Post(LivingEntity entity, LivingEntity outcome) - { + public Post(LivingEntity entity, LivingEntity outcome) { super(entity); this.outcome = outcome; } @@ -86,8 +92,7 @@ public class LivingConversionEvent extends LivingEvent * effect and equipments set) * @return the finalized new entity */ - public LivingEntity getOutcome() - { + public LivingEntity getOutcome() { return outcome; } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 74a06bf18f..9da0a063df 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -260,6 +260,7 @@ protected net.minecraft.world.entity.monster.AbstractSkeleton m_7878_()Lnet/mine protected net.minecraft.world.entity.monster.Skeleton m_7878_()Lnet/minecraft/sounds/SoundEvent; # getStepSound - make AbstractSkeletonEntity implementable protected net.minecraft.world.entity.monster.Stray m_7878_()Lnet/minecraft/sounds/SoundEvent; # getStepSound - make AbstractSkeletonEntity implementable protected net.minecraft.world.entity.monster.WitherSkeleton m_7878_()Lnet/minecraft/sounds/SoundEvent; # getStepSound - make AbstractSkeletonEntity implementable +protected net.minecraft.world.entity.monster.Zombie f_34266_ # conversionTime public net.minecraft.world.entity.npc.VillagerType (Ljava/lang/String;)V # constructor public net.minecraft.world.entity.player.Player m_6915_()V # closeContainer protected net.minecraft.world.entity.projectile.Projectile (Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/level/Level;)V # constructor