aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0585-Fix-potions-splash-events.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0585-Fix-potions-splash-events.patch')
-rw-r--r--patches/server/0585-Fix-potions-splash-events.patch155
1 files changed, 155 insertions, 0 deletions
diff --git a/patches/server/0585-Fix-potions-splash-events.patch b/patches/server/0585-Fix-potions-splash-events.patch
new file mode 100644
index 0000000000..12a8e49d26
--- /dev/null
+++ b/patches/server/0585-Fix-potions-splash-events.patch
@@ -0,0 +1,155 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Jake Potrebic <[email protected]>
+Date: Thu, 20 May 2021 20:40:53 -0700
+Subject: [PATCH] Fix potions splash events
+
+Fix PotionSplashEvent for water splash potions
+Fixes SPIGOT-6221: https://hub.spigotmc.org/jira/projects/SPIGOT/issues/SPIGOT-6221
+Fix splash events cancellation that still show particles/sound
+
+diff --git a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
+index b87077c47a0131c5f4ca085b6b32e657043a9e1a..bb116b0c75a311d0dc65c032a7727598890ef942 100644
+--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
+@@ -105,56 +105,77 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
+ Potion potionregistry = PotionUtils.getPotion(itemstack);
+ List<MobEffectInstance> list = PotionUtils.getMobEffects(itemstack);
+ boolean flag = potionregistry == Potions.WATER && list.isEmpty();
++ boolean showParticles = true; // Paper - Fix potions splash events
+
+ if (flag) {
+- this.applyWater();
++ showParticles = this.applyWater(); // Paper - Fix potions splash events
+ } else if (true || !list.isEmpty()) { // CraftBukkit - Call event even if no effects to apply
+ if (this.isLingering()) {
+- this.makeAreaOfEffectCloud(itemstack, potionregistry, hitResult); // CraftBukkit - Pass MovingObjectPosition
++ showParticles = this.makeAreaOfEffectCloud(itemstack, potionregistry, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
+ } else {
+- this.applySplash(list, hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition
++ showParticles = this.applySplash(list, hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
+ }
+ }
+
++ if (showParticles) { // Paper - Fix potions splash events
+ int i = potionregistry.hasInstantEffects() ? 2007 : 2002;
+
+ this.level().levelEvent(i, this.blockPosition(), PotionUtils.getColor(itemstack));
++ } // Paper - Fix potions splash events
+ this.discard();
+ }
+ }
+
+- private void applyWater() {
++ private static final Predicate<net.minecraft.world.entity.LivingEntity> APPLY_WATER_GET_ENTITIES_PREDICATE = ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE.or(Axolotl.class::isInstance); // Paper - Fix potions splash events
++ private boolean applyWater() { // Paper - Fix potions splash events
+ AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D);
+- List<net.minecraft.world.entity.LivingEntity> list = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE);
++ // Paper start - Fix potions splash events
++ List<net.minecraft.world.entity.LivingEntity> list = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb, ThrownPotion.APPLY_WATER_GET_ENTITIES_PREDICATE);
++ Map<LivingEntity, Double> affected = new HashMap<>();
++ java.util.Set<LivingEntity> rehydrate = new java.util.HashSet<>();
++ java.util.Set<LivingEntity> 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();
++ if (entityliving instanceof Axolotl axolotl) {
++ rehydrate.add(((org.bukkit.entity.Axolotl) axolotl.getBukkitEntity()));
++ }
+ double d0 = this.distanceToSqr((Entity) entityliving);
+
+ if (d0 < 16.0D) {
+ if (entityliving.isSensitiveToWater()) {
+- entityliving.hurt(this.damageSources().indirectMagic(this, this.getOwner()), 1.0F);
++ affected.put(entityliving.getBukkitLivingEntity(), 1.0);
+ }
+
+ if (entityliving.isOnFire() && entityliving.isAlive()) {
+- entityliving.extinguishFire();
++ extinguish.add(entityliving.getBukkitLivingEntity());
+ }
+ }
+ }
+
+- List<Axolotl> list1 = this.level().getEntitiesOfClass(Axolotl.class, axisalignedbb);
+- Iterator iterator1 = list1.iterator();
+-
+- while (iterator1.hasNext()) {
+- Axolotl axolotl = (Axolotl) iterator1.next();
+-
+- axolotl.rehydrate();
++ 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(this.damageSources().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();
++ }
++ }
++ // Paper end - Fix potions splash events
+ }
++ return !event.isCancelled(); // Paper - Fix potions splash events
+
+ }
+
+- private void applySplash(List<MobEffectInstance> list, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition
++ private boolean applySplash(List<MobEffectInstance> list, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - Fix potions splash events
+ AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D);
+ List<net.minecraft.world.entity.LivingEntity> list1 = this.level().getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb);
+ Map<LivingEntity, Double> affected = new HashMap<LivingEntity, Double>(); // CraftBukkit
+@@ -172,6 +193,7 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
+ if (d0 < 16.0D) {
+ double d1;
+
++ // Paper - diff on change, used when calling the splash event for water splash potions
+ if (entityliving == entity) {
+ d1 = 1.0D;
+ } else {
+@@ -226,10 +248,11 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
+ }
+ }
+ }
++ return !event.isCancelled(); // Paper - Fix potions splash events
+
+ }
+
+- private void makeAreaOfEffectCloud(ItemStack itemstack, Potion potionregistry, HitResult position) { // CraftBukkit - Pass MovingObjectPosition
++ private boolean makeAreaOfEffectCloud(ItemStack itemstack, Potion potionregistry, HitResult position) { // CraftBukkit - Pass MovingObjectPosition // Paper - return boolean
+ AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
+ Entity entity = this.getOwner();
+
+@@ -244,10 +267,12 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
+ entityareaeffectcloud.setPotion(potionregistry);
+ Iterator iterator = PotionUtils.getCustomEffects(itemstack).iterator();
+
++ boolean noEffects = potionregistry.getEffects().isEmpty(); // Paper - Fix potions splash events
+ while (iterator.hasNext()) {
+ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next();
+
+ entityareaeffectcloud.addEffect(new MobEffectInstance(mobeffect));
++ noEffects = false; // Paper - Fix potions splash events
+ }
+
+ CompoundTag nbttagcompound = itemstack.getTag();
+@@ -258,12 +283,13 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
+
+ // CraftBukkit start
+ org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, position, entityareaeffectcloud);
+- if (!(event.isCancelled() || entityareaeffectcloud.isRemoved())) {
++ if (!(event.isCancelled() || entityareaeffectcloud.isRemoved() || (noEffects && entityareaeffectcloud.effects.isEmpty() && entityareaeffectcloud.getPotion().getEffects().isEmpty()))) { // Paper - don't spawn area effect cloud if the effects were empty and not changed during the event handling
+ this.level().addFreshEntity(entityareaeffectcloud);
+ } else {
+ entityareaeffectcloud.discard();
+ }
+ // CraftBukkit end
++ return !event.isCancelled(); // Paper - Fix potions splash events
+ }
+
+ public boolean isLingering() {