aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0554-Fix-potions-splash-events.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0554-Fix-potions-splash-events.patch')
-rw-r--r--patches/server/0554-Fix-potions-splash-events.patch181
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
+ */