diff options
Diffstat (limited to 'patches/server/0554-Fix-potions-splash-events.patch')
-rw-r--r-- | patches/server/0554-Fix-potions-splash-events.patch | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/patches/server/0554-Fix-potions-splash-events.patch b/patches/server/0554-Fix-potions-splash-events.patch new file mode 100644 index 0000000000..38cfaf9769 --- /dev/null +++ b/patches/server/0554-Fix-potions-splash-events.patch @@ -0,0 +1,181 @@ +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 be787a5b52e90796d4f06e17e564f4324807c3e6..cb34cc9443da56c0497c7a0192c8b8363c3426fe 100644 +--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java ++++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java +@@ -106,55 +106,76 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie + ItemStack itemstack = this.getItem(); + PotionContents potioncontents = (PotionContents) itemstack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY); + ++ boolean showParticles = true; // Paper - Fix potions splash events + if (potioncontents.is(Potions.WATER)) { +- this.applyWater(); ++ showParticles = this.applyWater(hitResult); // Paper - Fix potions splash events + } else if (true || potioncontents.hasEffects()) { // CraftBukkit - Call event even if no effects to apply + if (this.isLingering()) { +- this.makeAreaOfEffectCloud(potioncontents, hitResult); // CraftBukkit - Pass MovingObjectPosition ++ showParticles = this.makeAreaOfEffectCloud(potioncontents, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper + } else { +- this.applySplash(potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition ++ showParticles = this.applySplash(potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper + } + } + ++ if (showParticles) { // Paper - Fix potions splash events + int i = potioncontents.potion().isPresent() && ((Potion) ((Holder) potioncontents.potion().get()).value()).hasInstantEffects() ? 2007 : 2002; + + this.level().levelEvent(i, this.blockPosition(), potioncontents.getColor()); ++ } // Paper - Fix potions splash events + this.discard(EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause + } + } + +- 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(@Nullable HitResult hitResult) { // 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 = org.bukkit.craftbukkit.event.CraftEventFactory.callWaterBottleSplashEvent( ++ this, hitResult, affected, rehydrate, extinguish ++ ); ++ if (!event.isCancelled()) { ++ 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(Iterable<MobEffectInstance> iterable, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ private boolean applySplash(Iterable<MobEffectInstance> iterable, @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> list = 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 { +@@ -227,10 +249,11 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie + } + } + } ++ return !event.isCancelled(); // Paper - Fix potions splash events + + } + +- private void makeAreaOfEffectCloud(PotionContents potioncontents, HitResult position) { // CraftBukkit - Pass MovingObjectPosition ++ private boolean makeAreaOfEffectCloud(PotionContents potioncontents, HitResult position) { // CraftBukkit - Pass MovingObjectPosition + AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); + Entity entity = this.getOwner(); + +@@ -243,14 +266,16 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie + entityareaeffectcloud.setWaitTime(10); + entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration()); + entityareaeffectcloud.setPotionContents(potioncontents); ++ boolean noEffects = potioncontents.hasEffects(); // Paper - Fix potions splash events + // 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.potionContents.hasEffects()))) { // 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(null); // CraftBukkit - add Bukkit remove cause + } + // CraftBukkit end ++ return !event.isCancelled(); // Paper - Fix potions splash events + } + + public boolean isLingering() { +diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +index 36adcab02e97cae2d087bae74cc4ceaf3052a9f8..b93fa1ea73f0b218e6c6bed8bd36694e26544ab0 100644 +--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java ++++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +@@ -886,6 +886,32 @@ public class CraftEventFactory { + return event; + } + ++ // Paper start - Fix potions splash events ++ public static io.papermc.paper.event.entity.WaterBottleSplashEvent callWaterBottleSplashEvent(net.minecraft.world.entity.projectile.ThrownPotion potion, @Nullable HitResult hitResult, Map<LivingEntity, Double> affectedEntities, java.util.Set<LivingEntity> rehydrate, java.util.Set<LivingEntity> extinguish) { ++ ThrownPotion thrownPotion = (ThrownPotion) potion.getBukkitEntity(); ++ ++ Block hitBlock = null; ++ BlockFace hitFace = null; ++ org.bukkit.entity.Entity hitEntity = null; ++ ++ if (hitResult != null) { ++ if (hitResult.getType() == HitResult.Type.BLOCK) { ++ BlockHitResult blockHitResult = (BlockHitResult) hitResult; ++ hitBlock = CraftBlock.at(potion.level(), blockHitResult.getBlockPos()); ++ hitFace = CraftBlock.notchToBlockFace(blockHitResult.getDirection()); ++ } else if (hitResult.getType() == HitResult.Type.ENTITY) { ++ hitEntity = ((EntityHitResult) hitResult).getEntity().getBukkitEntity(); ++ } ++ } ++ ++ io.papermc.paper.event.entity.WaterBottleSplashEvent event = new io.papermc.paper.event.entity.WaterBottleSplashEvent( ++ thrownPotion, hitEntity, hitBlock, hitFace, affectedEntities, rehydrate, extinguish ++ ); ++ event.callEvent(); ++ return event; ++ } ++ // Paper end - Fix potions splash events ++ + /** + * BlockFadeEvent + */ |