PaperMC/patches/server/Fix-potions-splash-events.patch
2023-03-14 21:25:13 +01:00

155 lines
8.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Jake Potrebic <jake.m.potrebic@gmail.com>
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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
+++ b/src/main/java/net/minecraft/world/entity/projectile/ThrownPotion.java
@@ -0,0 +0,0 @@ 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
if (flag) {
- this.applyWater();
+ showParticles = this.applyWater(); // Paper
} else if (true || !list.isEmpty()) { // CraftBukkit - Call event even if no effects to apply
if (this.isLingering()) {
- this.makeAreaOfEffectCloud(itemstack, potionregistry);
+ showParticles = this.makeAreaOfEffectCloud(itemstack, potionregistry); // Paper
} else {
- this.applySplash(list, hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null);
+ showParticles = this.applySplash(list, hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null); // Paper
}
}
+ if (showParticles) { // Paper
int i = potionregistry.hasInstantEffects() ? 2007 : 2002;
this.level.levelEvent(i, this.blockPosition(), PotionUtils.getColor(itemstack));
+ } // Paper
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
+ private boolean applyWater() { // Paper
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
+ 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
}
+ return !event.isCancelled(); // Paper
}
- private void applySplash(List<MobEffectInstance> statusEffects, @Nullable Entity entity) {
+ private boolean applySplash(List<MobEffectInstance> statusEffects, @Nullable Entity entity) { // Paper
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
@@ -0,0 +0,0 @@ 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 {
@@ -0,0 +0,0 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
}
}
}
+ return !event.isCancelled(); // Paper
}
- private void makeAreaOfEffectCloud(ItemStack stack, Potion potion) {
+ private boolean makeAreaOfEffectCloud(ItemStack stack, Potion potion) { // Paper
AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level, this.getX(), this.getY(), this.getZ());
Entity entity = this.getOwner();
@@ -0,0 +0,0 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
entityareaeffectcloud.setPotion(potion);
Iterator iterator = PotionUtils.getCustomEffects(stack).iterator();
+ boolean noEffects = potion.getEffects().isEmpty(); // Paper
while (iterator.hasNext()) {
MobEffectInstance mobeffect = (MobEffectInstance) iterator.next();
entityareaeffectcloud.addEffect(new MobEffectInstance(mobeffect));
+ noEffects = false; // Paper
}
CompoundTag nbttagcompound = stack.getTag();
@@ -0,0 +0,0 @@ public class ThrownPotion extends ThrowableItemProjectile implements ItemSupplie
// CraftBukkit start
org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, 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
}
public boolean isLingering() {