From 449f63be8c3200d58f2306efd285a2eba7a78321 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Thu, 8 Dec 2022 17:33:22 -0700 Subject: [PATCH] Account for splash water bottles now extinguishing entities (#8622) * Account for splash water bottles now extinguishing entities * improvements and javadocs * reorder patches * rename event to WaterBottleSplashEvent Co-authored-by: Jake Potrebic --- patches/api/Add-WaterBottleSplashEvent.patch | 150 ++++++++++++++++++ ...SplashEvent-for-water-splash-potions.patch | 42 ++--- 2 files changed, 172 insertions(+), 20 deletions(-) create mode 100644 patches/api/Add-WaterBottleSplashEvent.patch diff --git a/patches/api/Add-WaterBottleSplashEvent.patch b/patches/api/Add-WaterBottleSplashEvent.patch new file mode 100644 index 0000000000..291644f9b6 --- /dev/null +++ b/patches/api/Add-WaterBottleSplashEvent.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Thu, 8 Dec 2022 10:12:23 -0700 +Subject: [PATCH] Add WaterBottleSplashEvent + + +diff --git a/src/main/java/io/papermc/paper/event/entity/WaterBottleSplashEvent.java b/src/main/java/io/papermc/paper/event/entity/WaterBottleSplashEvent.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/event/entity/WaterBottleSplashEvent.java +@@ -0,0 +0,0 @@ ++package io.papermc.paper.event.entity; ++ ++import java.util.Collection; ++import java.util.Map; ++import java.util.Set; ++import java.util.stream.Collectors; ++import org.bukkit.entity.LivingEntity; ++import org.bukkit.entity.ThrownPotion; ++import org.bukkit.event.entity.PotionSplashEvent; ++import org.jetbrains.annotations.NotNull; ++import org.jetbrains.annotations.Unmodifiable; ++ ++/** ++ * Called when a splash water potion "splashes" and affects ++ * different entities in different ways. ++ */ ++public class WaterBottleSplashEvent extends PotionSplashEvent { ++ private final @NotNull Set rehydrate; ++ private final @NotNull Set extinguish; ++ ++ public WaterBottleSplashEvent( ++ final @NotNull ThrownPotion potion, ++ final @NotNull Map affectedEntities, ++ final @NotNull Set rehydrate, ++ final @NotNull Set extinguish ++ ) { ++ super(potion, affectedEntities); ++ this.rehydrate = rehydrate; ++ this.extinguish = extinguish; ++ } ++ ++ /** ++ * Gets an immutable collection of entities that ++ * will take damage as a result of this event. Use ++ * other methods on this class to modify which entities ++ * take damage. ++ * ++ * @return an immutable collection of entities ++ * @see #doNotDamageAsWaterSensitive(LivingEntity) ++ * @see #damageAsWaterSensitive(LivingEntity) ++ */ ++ @NotNull ++ public @Unmodifiable Collection getToDamage() { ++ return this.affectedEntities.entrySet().stream().filter(entry -> entry.getValue() > 0).map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()); ++ } ++ ++ /** ++ * Removes this entity from the group that ++ * will be damaged. ++ * ++ * @param entity entity to remove ++ */ ++ public void doNotDamageAsWaterSensitive(final @NotNull LivingEntity entity) { ++ this.affectedEntities.remove(entity); ++ } ++ ++ /** ++ * Adds this entity to the group that ++ * will be damaged ++ * ++ * @param entity entity to add ++ */ ++ public void damageAsWaterSensitive(final @NotNull LivingEntity entity) { ++ this.affectedEntities.put(entity, 1.0); ++ } ++ ++ /** ++ * Get a mutable collection of entities ++ * that will be rehydrated by this. ++ *

++ * As of 1.19.3 this only will contain Axolotls as they ++ * are the only entity type that can be rehydrated, but ++ * it may change in the future. ++ * ++ * @return the entities ++ */ ++ @NotNull ++ public Collection getToRehydrate() { ++ return this.rehydrate; ++ } ++ ++ /** ++ * Get a mutable collection of entities that will ++ * be extinguished as a result of this event. ++ * ++ * @return entities to be extinguished ++ */ ++ @NotNull ++ public Collection getToExtinguish() { ++ return this.extinguish; ++ } ++ ++ /** ++ * @return a confusing collection, don't use it ++ * @deprecated Use {@link #getToDamage()} ++ */ ++ @Deprecated ++ @Override ++ public @NotNull Collection getAffectedEntities() { ++ return super.getAffectedEntities(); ++ } ++ ++ /** ++ * Doesn't make sense for this event as intensity doesn't vary. ++ * @return a confusing value ++ * @deprecated check if {@link #getToDamage()} contains an entity ++ */ ++ @Deprecated ++ @Override ++ public double getIntensity(final @NotNull LivingEntity entity) { ++ return super.getIntensity(entity); ++ } ++ ++ /** ++ * Doesn't make sense for this event as intensity doesn't vary. ++ * @deprecated use {@link #damageAsWaterSensitive(LivingEntity)} ++ * or {@link #doNotDamageAsWaterSensitive(LivingEntity)} to change which entities are ++ * damaged ++ */ ++ @Deprecated ++ @Override ++ public void setIntensity(final @NotNull LivingEntity entity, final double intensity) { ++ super.setIntensity(entity, intensity); ++ } ++} +diff --git a/src/main/java/org/bukkit/event/entity/PotionSplashEvent.java b/src/main/java/org/bukkit/event/entity/PotionSplashEvent.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/event/entity/PotionSplashEvent.java ++++ b/src/main/java/org/bukkit/event/entity/PotionSplashEvent.java +@@ -0,0 +0,0 @@ import org.jetbrains.annotations.NotNull; + public class PotionSplashEvent extends ProjectileHitEvent implements Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; +- private final Map affectedEntities; ++ protected final Map affectedEntities; // Paper + + public PotionSplashEvent(@NotNull final ThrownPotion potion, @NotNull final Map affectedEntities) { + super(potion); diff --git a/patches/server/Fix-PotionSplashEvent-for-water-splash-potions.patch b/patches/server/Fix-PotionSplashEvent-for-water-splash-potions.patch index 64f1efe89d..6b1ac4e6fa 100644 --- a/patches/server/Fix-PotionSplashEvent-for-water-splash-potions.patch +++ b/patches/server/Fix-PotionSplashEvent-for-water-splash-potions.patch @@ -17,32 +17,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private void applyWater() { AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D); - List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE); -+ List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.APPLY_WATER_GET_ENTITIES_PREDICATE); // Paper -+ Map affected = new HashMap<>(); // Paper ++ // Paper start ++ List list = this.level.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.APPLY_WATER_GET_ENTITIES_PREDICATE); ++ Map affected = new HashMap<>(); ++ java.util.Set rehydrate = new java.util.HashSet<>(); ++ java.util.Set extinguish = new java.util.HashSet<>(); Iterator iterator = list.iterator(); while (iterator.hasNext()) { net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator.next(); -+ // Paper start - Change into single getEntities for axolotls & water sensitive + if (entityliving instanceof Axolotl axolotl) { -+ affected.put(axolotl.getBukkitLivingEntity(), 1.0); -+ continue; ++ rehydrate.add(((org.bukkit.entity.Axolotl) axolotl.getBukkitEntity())); + } -+ // Paper end double d0 = this.distanceToSqr((Entity) entityliving); if (d0 < 16.0D) { if (entityliving.isSensitiveToWater()) { - entityliving.hurt(DamageSource.indirectMagic(this, this.getOwner()), 1.0F); -+ // Paper start -+ double intensity = 1.0D - Math.sqrt(d0) / 4.0D; -+ affected.put(entityliving.getBukkitLivingEntity(), intensity); -+ // entityliving.hurt(DamageSource.indirectMagic(this, this.getOwner()), 1.0F); // Paper - moved down -+ // Paper end ++ affected.put(entityliving.getBukkitLivingEntity(), 1.0); } if (entityliving.isOnFire() && entityliving.isAlive()) { -@@ -0,0 +0,0 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie +- entityliving.extinguishFire(); ++ extinguish.add(entityliving.getBukkitLivingEntity()); + } } } @@ -53,15 +51,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - Axolotl axolotl = (Axolotl) iterator1.next(); - - axolotl.rehydrate(); -+ // Paper start -+ org.bukkit.event.entity.PotionSplashEvent event = CraftEventFactory.callPotionSplashEvent(this, affected); -+ if (!event.isCancelled()) { -+ for (LivingEntity affectedEntity : event.getAffectedEntities()) { -+ net.minecraft.world.entity.LivingEntity entityliving = ((CraftLivingEntity) affectedEntity).getHandle(); -+ if (entityliving instanceof Axolotl axolotl && event.getIntensity(affectedEntity) > 0) { ++ io.papermc.paper.event.entity.WaterBottleSplashEvent event = new io.papermc.paper.event.entity.WaterBottleSplashEvent( ++ (org.bukkit.entity.ThrownPotion) this.getBukkitEntity(), affected, rehydrate, extinguish ++ ); ++ if (event.callEvent()) { ++ for (LivingEntity affectedEntity : event.getToDamage()) { ++ ((CraftLivingEntity) affectedEntity).getHandle().hurt(DamageSource.indirectMagic(this, this.getOwner()), 1.0F); ++ } ++ for (LivingEntity toExtinguish : event.getToExtinguish()) { ++ ((CraftLivingEntity) toExtinguish).getHandle().extinguishFire(); ++ } ++ for (LivingEntity toRehydrate : event.getToRehydrate()) { ++ if (((CraftLivingEntity) toRehydrate).getHandle() instanceof Axolotl axolotl) { + axolotl.rehydrate(); -+ } else { -+ entityliving.hurt(DamageSource.indirectMagic(this, this.getOwner()), 1.0F); + } + } + // Paper end