--- a/net/minecraft/world/level/block/EndPortalBlock.java
+++ b/net/minecraft/world/level/block/EndPortalBlock.java
@@ -4,6 +4,7 @@
 import net.minecraft.core.particles.ParticleTypes;
 import net.minecraft.resources.ResourceKey;
 import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
 import net.minecraft.util.RandomSource;
 import net.minecraft.world.entity.Entity;
 import net.minecraft.world.item.ItemStack;
@@ -13,13 +14,18 @@
 import net.minecraft.world.level.block.entity.TheEndPortalBlockEntity;
 import net.minecraft.world.level.block.state.BlockBehaviour;
 import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.level.dimension.LevelStem;
 import net.minecraft.world.level.material.Fluid;
 import net.minecraft.world.phys.shapes.BooleanOp;
 import net.minecraft.world.phys.shapes.CollisionContext;
 import net.minecraft.world.phys.shapes.Shapes;
 import net.minecraft.world.phys.shapes.VoxelShape;
+import org.bukkit.event.entity.EntityPortalEnterEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+// CraftBukkit end
 
 public class EndPortalBlock extends BaseEntityBlock {
+
     protected static final VoxelShape SHAPE = Block.box(0.0D, 6.0D, 0.0D, 16.0D, 12.0D, 16.0D);
 
     protected EndPortalBlock(BlockBehaviour.Properties settings) {
@@ -33,29 +39,35 @@
 
     @Override
     public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
-        return SHAPE;
+        return EndPortalBlock.SHAPE;
     }
 
     @Override
     public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
-        if (world instanceof ServerLevel && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double)(-pos.getX()), (double)(-pos.getY()), (double)(-pos.getZ()))), state.getShape(world, pos), BooleanOp.AND)) {
-            ResourceKey<Level> resourceKey = world.dimension() == Level.END ? Level.OVERWORLD : Level.END;
-            ServerLevel serverLevel = ((ServerLevel)world).getServer().getLevel(resourceKey);
-            if (serverLevel == null) {
-                return;
+        if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.v1_20_R2.block.CraftBlock.at(world, pos)).callEvent()) { return; } // Paper
+        if (world instanceof ServerLevel && entity.canChangeDimensions() && Shapes.joinIsNotEmpty(Shapes.create(entity.getBoundingBox().move((double) (-pos.getX()), (double) (-pos.getY()), (double) (-pos.getZ()))), state.getShape(world, pos), BooleanOp.AND)) {
+            ResourceKey<Level> resourcekey = world.getTypeKey() == LevelStem.END ? Level.OVERWORLD : Level.END; // CraftBukkit - SPIGOT-6152: send back to main overworld in custom ends
+            ServerLevel worldserver = ((ServerLevel) world).getServer().getLevel(resourcekey);
+
+            if (worldserver == null) {
+                // return; // CraftBukkit - always fire event in case plugins wish to change it
             }
 
-            entity.changeDimension(serverLevel);
+            // Paper start - move all of this logic into portal tick
+            entity.portalWorld = ((ServerLevel)world);
+            entity.portalBlock = pos.immutable();
+            // Paper end - move all of this logic into portal tick
         }
 
     }
 
     @Override
     public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {
-        double d = (double)pos.getX() + random.nextDouble();
-        double e = (double)pos.getY() + 0.8D;
-        double f = (double)pos.getZ() + random.nextDouble();
-        world.addParticle(ParticleTypes.SMOKE, d, e, f, 0.0D, 0.0D, 0.0D);
+        double d0 = (double) pos.getX() + random.nextDouble();
+        double d1 = (double) pos.getY() + 0.8D;
+        double d2 = (double) pos.getZ() + random.nextDouble();
+
+        world.addParticle(ParticleTypes.SMOKE, d0, d1, d2, 0.0D, 0.0D, 0.0D);
     }
 
     @Override
