--- a/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
+++ b/net/minecraft/world/entity/projectile/ThrownEnderpearl.java
@@ -9,18 +9,25 @@
 import net.minecraft.world.entity.EntityType;
 import net.minecraft.world.entity.LivingEntity;
 import net.minecraft.world.entity.monster.Endermite;
+import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.item.Item;
 import net.minecraft.world.item.Items;
 import net.minecraft.world.level.GameRules;
 import net.minecraft.world.level.Level;
 import net.minecraft.world.level.block.Blocks;
 import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.dimension.LevelStem;
 import net.minecraft.world.level.portal.DimensionTransition;
 import net.minecraft.world.phys.EntityHitResult;
 import net.minecraft.world.phys.HitResult;
 import net.minecraft.world.phys.Vec3;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+import org.bukkit.event.entity.EntityRemoveEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+// CraftBukkit end
 
 public class ThrownEnderpearl extends ThrowableItemProjectile {
+
     public ThrownEnderpearl(EntityType<? extends ThrownEnderpearl> type, Level world) {
         super(type, world);
     }
@@ -44,68 +51,73 @@
     protected void onHit(HitResult hitResult) {
         super.onHit(hitResult);
 
-        for (int i = 0; i < 32; i++) {
-            this.level()
-                .addParticle(
-                    ParticleTypes.PORTAL,
-                    this.getX(),
-                    this.getY() + this.random.nextDouble() * 2.0,
-                    this.getZ(),
-                    this.random.nextGaussian(),
-                    0.0,
-                    this.random.nextGaussian()
-                );
+        for (int i = 0; i < 32; ++i) {
+            this.level().addParticle(ParticleTypes.PORTAL, this.getX(), this.getY() + this.random.nextDouble() * 2.0D, this.getZ(), this.random.nextGaussian(), 0.0D, this.random.nextGaussian());
         }
 
-        if (this.level() instanceof ServerLevel serverLevel && !this.isRemoved()) {
-            Entity entity = this.getOwner();
-            if (entity != null && isAllowedToTeleportOwner(entity, serverLevel)) {
-                if (entity.isPassenger()) {
-                    entity.unRide();
-                }
+        Level world = this.level();
 
-                if (entity instanceof ServerPlayer serverPlayer) {
-                    if (serverPlayer.connection.isAcceptingMessages()) {
-                        if (this.random.nextFloat() < 0.05F && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) {
-                            Endermite endermite = EntityType.ENDERMITE.create(serverLevel);
-                            if (endermite != null) {
-                                endermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot());
-                                serverLevel.addFreshEntity(endermite);
+        if (world instanceof ServerLevel worldserver) {
+            if (!this.isRemoved()) {
+                Entity entity = this.getOwner();
+
+                if (entity != null && ThrownEnderpearl.isAllowedToTeleportOwner(entity, worldserver)) {
+                    if (entity.isPassenger()) {
+                        entity.unRide();
+                    }
+
+                    if (entity instanceof ServerPlayer) {
+                        ServerPlayer entityplayer = (ServerPlayer) entity;
+
+                        if (entityplayer.connection.isAcceptingMessages()) {
+                            // CraftBukkit start
+                            Entity tp = entity.changeDimension(new DimensionTransition(worldserver, this.position(), entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), DimensionTransition.DO_NOTHING, PlayerTeleportEvent.TeleportCause.ENDER_PEARL));
+                            if (tp == null) {
+                                this.discard(EntityRemoveEvent.Cause.HIT);
+                                return;
                             }
-                        }
+                            // CraftBukkit end
+                            if (this.random.nextFloat() < 0.05F && worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) {
+                                Endermite entityendermite = (Endermite) EntityType.ENDERMITE.create(worldserver);
 
-                        entity.changeDimension(
-                            new DimensionTransition(
-                                serverLevel, this.position(), entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), DimensionTransition.DO_NOTHING
-                            )
-                        );
+                                if (entityendermite != null) {
+                                    entityendermite.moveTo(entity.getX(), entity.getY(), entity.getZ(), entity.getYRot(), entity.getXRot());
+                                    worldserver.addFreshEntity(entityendermite, CreatureSpawnEvent.SpawnReason.ENDER_PEARL);
+                                }
+                            }
+
+                            // entity.changeDimension(new DimensionTransition(worldserver, this.position(), entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), DimensionTransition.DO_NOTHING)); // CraftBukkit - moved up
+                            entity.resetFallDistance();
+                            entityplayer.resetCurrentImpulseContext();
+                            entity.hurt(this.damageSources().fall().customEventDamager(this), 5.0F); // CraftBukkit // Paper - fix DamageSource API
+                            this.playSound(worldserver, this.position());
+                        }
+                    } else {
+                        entity.changeDimension(new DimensionTransition(worldserver, this.position(), entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), DimensionTransition.DO_NOTHING));
                         entity.resetFallDistance();
-                        serverPlayer.resetCurrentImpulseContext();
-                        entity.hurt(this.damageSources().fall(), 5.0F);
-                        this.playSound(serverLevel, this.position());
+                        this.playSound(worldserver, this.position());
                     }
-                } else {
-                    entity.changeDimension(
-                        new DimensionTransition(
-                            serverLevel, this.position(), entity.getDeltaMovement(), entity.getYRot(), entity.getXRot(), DimensionTransition.DO_NOTHING
-                        )
-                    );
-                    entity.resetFallDistance();
-                    this.playSound(serverLevel, this.position());
+
+                    this.discard(EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause
+                    return;
                 }
 
-                this.discard();
+                this.discard(EntityRemoveEvent.Cause.HIT); // CraftBukkit - add Bukkit remove cause
                 return;
             }
-
-            this.discard();
-            return;
         }
+
     }
 
     private static boolean isAllowedToTeleportOwner(Entity entity, Level world) {
         if (entity.level().dimension() == world.dimension()) {
-            return !(entity instanceof LivingEntity livingEntity) ? entity.isAlive() : livingEntity.isAlive() && !livingEntity.isSleeping();
+            if (!(entity instanceof LivingEntity)) {
+                return entity.isAlive();
+            } else {
+                LivingEntity entityliving = (LivingEntity) entity;
+
+                return entityliving.isAlive() && !entityliving.isSleeping();
+            }
         } else {
             return entity.canUsePortal(true);
         }
@@ -114,29 +126,46 @@
     @Override
     public void tick() {
         Entity entity = this.getOwner();
+
         if (entity instanceof ServerPlayer && !entity.isAlive() && this.level().getGameRules().getBoolean(GameRules.RULE_ENDER_PEARLS_VANISH_ON_DEATH)) {
-            this.discard();
+            this.discard(EntityRemoveEvent.Cause.DESPAWN); // CraftBukkit - add Bukkit remove cause
         } else {
             super.tick();
         }
+
     }
 
     private void playSound(Level world, Vec3 pos) {
-        world.playSound(null, pos.x, pos.y, pos.z, SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS);
+        world.playSound((Player) null, pos.x, pos.y, pos.z, SoundEvents.PLAYER_TELEPORT, SoundSource.PLAYERS);
     }
 
     @Override
     public boolean canChangeDimensions(Level from, Level to) {
-        return from.dimension() == Level.END && this.getOwner() instanceof ServerPlayer serverPlayer
-            ? super.canChangeDimensions(from, to) && serverPlayer.seenCredits
-            : super.canChangeDimensions(from, to);
+        if (from.getTypeKey() == LevelStem.END) { // CraftBukkit
+            Entity entity = this.getOwner();
+
+            if (entity instanceof ServerPlayer) {
+                ServerPlayer entityplayer = (ServerPlayer) entity;
+
+                return super.canChangeDimensions(from, to) && entityplayer.seenCredits;
+            }
+        }
+
+        return super.canChangeDimensions(from, to);
     }
 
     @Override
     protected void onInsideBlock(BlockState state) {
         super.onInsideBlock(state);
-        if (state.is(Blocks.END_GATEWAY) && this.getOwner() instanceof ServerPlayer serverPlayer) {
-            serverPlayer.onInsideBlock(state);
+        if (state.is(Blocks.END_GATEWAY)) {
+            Entity entity = this.getOwner();
+
+            if (entity instanceof ServerPlayer) {
+                ServerPlayer entityplayer = (ServerPlayer) entity;
+
+                entityplayer.onInsideBlock(state);
+            }
         }
+
     }
 }
