mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-30 16:19:03 +01:00
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
This commit is contained in:
parent
9b7c0ce420
commit
0bf80e49be
2 changed files with 100 additions and 13 deletions
|
@ -55,47 +55,98 @@
|
||||||
super(EntityType.POTION, owner, world, stack);
|
super(EntityType.POTION, owner, world, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,28 +111,28 @@
|
@@ -99,64 +109,86 @@
|
||||||
|
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)) {
|
if (potioncontents.is(Potions.WATER)) {
|
||||||
this.applyWater(worldserver);
|
- this.applyWater(worldserver);
|
||||||
- } else if (potioncontents.hasEffects()) {
|
- } else if (potioncontents.hasEffects()) {
|
||||||
|
+ showParticles = this.applyWater(worldserver, hitResult); // Paper - Fix potions splash events
|
||||||
+ } else if (true || potioncontents.hasEffects()) { // CraftBukkit - Call event even if no effects to apply
|
+ } else if (true || potioncontents.hasEffects()) { // CraftBukkit - Call event even if no effects to apply
|
||||||
if (this.isLingering()) {
|
if (this.isLingering()) {
|
||||||
- this.makeAreaOfEffectCloud(potioncontents);
|
- this.makeAreaOfEffectCloud(potioncontents);
|
||||||
+ this.makeAreaOfEffectCloud(potioncontents, hitResult); // CraftBukkit - Pass MovingObjectPosition
|
+ showParticles = this.makeAreaOfEffectCloud(potioncontents, hitResult); // CraftBukkit - Pass MovingObjectPosition // Paper
|
||||||
} else {
|
} else {
|
||||||
- this.applySplash(worldserver, potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null);
|
- this.applySplash(worldserver, potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null);
|
||||||
+ this.applySplash(worldserver, potioncontents.getAllEffects(), hitResult.getType() == HitResult.Type.ENTITY ? ((EntityHitResult) hitResult).getEntity() : null, hitResult); // CraftBukkit - Pass MovingObjectPosition
|
+ showParticles = this.applySplash(worldserver, 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;
|
int i = potioncontents.potion().isPresent() && ((Potion) ((Holder) potioncontents.potion().get()).value()).hasInstantEffects() ? 2007 : 2002;
|
||||||
|
|
||||||
worldserver.levelEvent(i, this.blockPosition(), potioncontents.getColor());
|
worldserver.levelEvent(i, this.blockPosition(), potioncontents.getColor());
|
||||||
- this.discard();
|
- this.discard();
|
||||||
|
+ } // Paper - Fix potions splash events
|
||||||
+ this.discard(EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause
|
+ this.discard(EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyWater(ServerLevel world) {
|
- private void applyWater(ServerLevel world) {
|
||||||
|
+ 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(ServerLevel world, @Nullable HitResult hitResult) { // Paper - Fix potions splash events
|
||||||
AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D);
|
AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D);
|
||||||
- List<LivingEntity> list = this.level().getEntitiesOfClass(LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE);
|
- List<LivingEntity> list = this.level().getEntitiesOfClass(LivingEntity.class, axisalignedbb, ThrownPotion.WATER_SENSITIVE_OR_ON_FIRE);
|
||||||
+ 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();
|
Iterator iterator = list.iterator();
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
- LivingEntity entityliving = (LivingEntity) iterator.next();
|
- LivingEntity entityliving = (LivingEntity) iterator.next();
|
||||||
+ net.minecraft.world.entity.LivingEntity entityliving = (net.minecraft.world.entity.LivingEntity) iterator.next();
|
+ 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);
|
double d0 = this.distanceToSqr((Entity) entityliving);
|
||||||
|
|
||||||
if (d0 < 16.0D) {
|
if (d0 < 16.0D) {
|
||||||
@@ -147,16 +157,17 @@
|
if (entityliving.isSensitiveToWater()) {
|
||||||
|
- entityliving.hurtServer(world, 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().hurtServer(world, 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(ServerLevel world, Iterable<MobEffectInstance> effects, @Nullable Entity entity) {
|
- private void applySplash(ServerLevel world, Iterable<MobEffectInstance> effects, @Nullable Entity entity) {
|
||||||
+ private void applySplash(ServerLevel worldserver, Iterable<MobEffectInstance> iterable, @Nullable Entity entity, HitResult position) { // CraftBukkit - Pass MovingObjectPosition
|
+ private boolean applySplash(ServerLevel worldserver, 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);
|
AABB axisalignedbb = this.getBoundingBox().inflate(4.0D, 2.0D, 4.0D);
|
||||||
- List<LivingEntity> list = world.getEntitiesOfClass(LivingEntity.class, axisalignedbb);
|
- List<LivingEntity> list = world.getEntitiesOfClass(LivingEntity.class, axisalignedbb);
|
||||||
+ List<net.minecraft.world.entity.LivingEntity> list = worldserver.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb);
|
+ List<net.minecraft.world.entity.LivingEntity> list = worldserver.getEntitiesOfClass(net.minecraft.world.entity.LivingEntity.class, axisalignedbb);
|
||||||
|
@ -111,7 +162,14 @@
|
||||||
|
|
||||||
if (entityliving.isAffectedByPotions()) {
|
if (entityliving.isAffectedByPotions()) {
|
||||||
double d0 = this.distanceToSqr((Entity) entityliving);
|
double d0 = this.distanceToSqr((Entity) entityliving);
|
||||||
@@ -170,37 +181,63 @@
|
@@ -164,43 +196,71 @@
|
||||||
|
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 {
|
||||||
d1 = 1.0D - Math.sqrt(d0) / 4.0D;
|
d1 = 1.0D - Math.sqrt(d0) / 4.0D;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,11 +237,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
+ return !event.isCancelled(); // Paper - Fix potions splash events
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- private void makeAreaOfEffectCloud(PotionContents potion) {
|
- private void makeAreaOfEffectCloud(PotionContents potion) {
|
||||||
+ 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());
|
AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ());
|
||||||
Entity entity = this.getOwner();
|
Entity entity = this.getOwner();
|
||||||
|
|
||||||
|
@ -192,25 +251,27 @@
|
||||||
entityareaeffectcloud.setOwner(entityliving);
|
entityareaeffectcloud.setOwner(entityliving);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,8 +245,15 @@
|
@@ -208,8 +268,17 @@
|
||||||
entityareaeffectcloud.setRadiusOnUse(-0.5F);
|
entityareaeffectcloud.setRadiusOnUse(-0.5F);
|
||||||
entityareaeffectcloud.setWaitTime(10);
|
entityareaeffectcloud.setWaitTime(10);
|
||||||
entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration());
|
entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration());
|
||||||
- entityareaeffectcloud.setPotionContents(potion);
|
- entityareaeffectcloud.setPotionContents(potion);
|
||||||
- this.level().addFreshEntity(entityareaeffectcloud);
|
- this.level().addFreshEntity(entityareaeffectcloud);
|
||||||
+ entityareaeffectcloud.setPotionContents(potioncontents);
|
+ entityareaeffectcloud.setPotionContents(potioncontents);
|
||||||
|
+ boolean noEffects = potioncontents.hasEffects(); // Paper - Fix potions splash events
|
||||||
+ // CraftBukkit start
|
+ // CraftBukkit start
|
||||||
+ org.bukkit.event.entity.LingeringPotionSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callLingeringPotionSplashEvent(this, position, entityareaeffectcloud);
|
+ 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);
|
+ this.level().addFreshEntity(entityareaeffectcloud);
|
||||||
+ } else {
|
+ } else {
|
||||||
+ entityareaeffectcloud.discard(null); // CraftBukkit - add Bukkit remove cause
|
+ entityareaeffectcloud.discard(null); // CraftBukkit - add Bukkit remove cause
|
||||||
+ }
|
+ }
|
||||||
+ // CraftBukkit end
|
+ // CraftBukkit end
|
||||||
|
+ return !event.isCancelled(); // Paper - Fix potions splash events
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLingering() {
|
public boolean isLingering() {
|
||||||
@@ -220,19 +264,31 @@
|
@@ -220,19 +289,31 @@
|
||||||
BlockState iblockdata = this.level().getBlockState(pos);
|
BlockState iblockdata = this.level().getBlockState(pos);
|
||||||
|
|
||||||
if (iblockdata.is(BlockTags.FIRE)) {
|
if (iblockdata.is(BlockTags.FIRE)) {
|
||||||
|
|
|
@ -884,6 +884,32 @@ public class CraftEventFactory {
|
||||||
return event;
|
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
|
* BlockFadeEvent
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue