--- a/net/minecraft/world/entity/projectile/AbstractThrownPotion.java
+++ b/net/minecraft/world/entity/projectile/AbstractThrownPotion.java
@@ -67,54 +_,95 @@
     @Override
     protected void onHit(HitResult result) {
         super.onHit(result);
+        // Paper start - More projectile API
+        this.splash(result);
+    }
+
+    public void splash(HitResult result) {
+        // Paper end - More projectile API
         if (this.level() instanceof ServerLevel serverLevel) {
             ItemStack item = this.getItem();
             PotionContents potionContents = item.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
+            boolean showParticles = true; // Paper - Fix potions splash events
             if (potionContents.is(Potions.WATER)) {
-                this.onHitAsWater(serverLevel);
-            } else if (potionContents.hasEffects()) {
-                this.onHitAsPotion(serverLevel, item, result);
+                showParticles = this.onHitAsWater(serverLevel, result); // Paper - Fix potions splash events
+            } else if (true || potionContents.hasEffects()) { // CraftBukkit - Call event even if no effects to apply
+                showParticles = this.onHitAsPotion(serverLevel, item, result); // Paper - pass HitResult
             }
 
+            if (showParticles) { // Paper - Fix potions splash events
             int i = potionContents.potion().isPresent() && potionContents.potion().get().value().hasInstantEffects() ? 2007 : 2002;
             serverLevel.levelEvent(i, this.blockPosition(), potionContents.getColor());
-            this.discard();
+            } // Paper - Fix potions splash events
+            this.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause
         }
     }
 
-    private void onHitAsWater(ServerLevel level) {
+    private static final Predicate<LivingEntity> APPLY_WATER_GET_ENTITIES_PREDICATE = AbstractThrownPotion.WATER_SENSITIVE_OR_ON_FIRE.or(Axolotl.class::isInstance); // Paper - Fix potions splash events
+
+    private boolean onHitAsWater(ServerLevel level, HitResult result) { // Paper - Fix potions splash events
         AABB aabb = this.getBoundingBox().inflate(4.0, 2.0, 4.0);
 
-        for (LivingEntity livingEntity : this.level().getEntitiesOfClass(LivingEntity.class, aabb, WATER_SENSITIVE_OR_ON_FIRE)) {
+        // Paper start - Fix potions splash events
+        java.util.Map<org.bukkit.entity.LivingEntity, Double> affected = new java.util.HashMap<>();
+        java.util.Set<org.bukkit.entity.LivingEntity> rehydrate = new java.util.HashSet<>();
+        java.util.Set<org.bukkit.entity.LivingEntity> extinguish = new java.util.HashSet<>();
+        for (LivingEntity livingEntity : this.level().getEntitiesOfClass(LivingEntity.class, aabb, APPLY_WATER_GET_ENTITIES_PREDICATE)) {
+            if (livingEntity instanceof Axolotl axolotl) {
+                rehydrate.add(((org.bukkit.entity.Axolotl) axolotl.getBukkitEntity()));
+            }
+            // Paper end - Fix potions splash events
             double d = this.distanceToSqr(livingEntity);
             if (d < 16.0) {
                 if (livingEntity.isSensitiveToWater()) {
-                    livingEntity.hurtServer(level, this.damageSources().indirectMagic(this, this.getOwner()), 1.0F);
+                    affected.put(livingEntity.getBukkitLivingEntity(), 1.0); // Paper - Fix potions splash events
                 }
 
                 if (livingEntity.isOnFire() && livingEntity.isAlive()) {
-                    livingEntity.extinguishFire();
+                    extinguish.add(livingEntity.getBukkitLivingEntity()); // Paper - Fix potions splash events
                 }
             }
         }
 
-        for (Axolotl axolotl : this.level().getEntitiesOfClass(Axolotl.class, aabb)) {
-            axolotl.rehydrate();
+        // Paper start - Fix potions splash events
+        io.papermc.paper.event.entity.WaterBottleSplashEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callWaterBottleSplashEvent(
+            this, result, affected, rehydrate, extinguish
+        );
+        if (!event.isCancelled()) {
+            for (org.bukkit.entity.LivingEntity affectedEntity : event.getToDamage()) {
+                ((org.bukkit.craftbukkit.entity.CraftLivingEntity) affectedEntity).getHandle().hurtServer(level, this.damageSources().indirectMagic(this, this.getOwner()), 1.0F);
+            }
+            for (org.bukkit.entity.LivingEntity toExtinguish : event.getToExtinguish()) {
+                ((org.bukkit.craftbukkit.entity.CraftLivingEntity) toExtinguish).getHandle().extinguishFire();
+            }
+            for (org.bukkit.entity.LivingEntity toRehydrate : event.getToRehydrate()) {
+                if (((org.bukkit.craftbukkit.entity.CraftLivingEntity) toRehydrate).getHandle() instanceof Axolotl axolotl) {
+                    axolotl.rehydrate();
+                }
+            }
+            // Paper end - Fix potions splash events
         }
+        return !event.isCancelled(); // Paper - Fix potions splash events
     }
 
-    protected abstract void onHitAsPotion(ServerLevel level, ItemStack stack, HitResult hitResult);
+    protected abstract boolean onHitAsPotion(ServerLevel level, ItemStack stack, HitResult hitResult); // Paper - Fix potions splash events & More Projectile API
 
     private void dowseFire(BlockPos pos) {
         BlockState blockState = this.level().getBlockState(pos);
         if (blockState.is(BlockTags.FIRE)) {
+            if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.getFluidState().createLegacyBlock())) { // Paper - fix wrong block state
             this.level().destroyBlock(pos, false, this);
+            } // CraftBukkit
         } else if (AbstractCandleBlock.isLit(blockState)) {
+            if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.setValue(AbstractCandleBlock.LIT, false))) { // CraftBukkit
             AbstractCandleBlock.extinguish(null, blockState, this.level(), pos);
+            } // CraftBukkit
         } else if (CampfireBlock.isLitCampfire(blockState)) {
+            if (org.bukkit.craftbukkit.event.CraftEventFactory.callEntityChangeBlockEvent(this, pos, blockState.setValue(CampfireBlock.LIT, false))) { // CraftBukkit
             this.level().levelEvent(null, 1009, pos, 0);
             CampfireBlock.dowse(this.getOwner(), this.level(), pos, blockState);
             this.level().setBlockAndUpdate(pos, blockState.setValue(CampfireBlock.LIT, false));
+            } // CraftBukkit
         }
     }
 
