--- a/net/minecraft/world/level/portal/PortalShape.java
+++ b/net/minecraft/world/level/portal/PortalShape.java
@@ -37,8 +_,12 @@
     private final BlockPos bottomLeft;
     private final int height;
     private final int width;
+    // CraftBukkit start - add field
+    private final org.bukkit.craftbukkit.util.BlockStateListPopulator blocks;
 
-    private PortalShape(Direction.Axis axis, int numPortalBlocks, Direction rightDir, BlockPos bottomLeft, int width, int height) {
+    private PortalShape(Direction.Axis axis, int numPortalBlocks, Direction rightDir, BlockPos bottomLeft, int width, int height, org.bukkit.craftbukkit.util.BlockStateListPopulator blocks) {
+        this.blocks = blocks;
+        // CraftBukkit end
         this.axis = axis;
         this.numPortalBlocks = numPortalBlocks;
         this.rightDir = rightDir;
@@ -62,24 +_,25 @@
     }
 
     public static PortalShape findAnyShape(BlockGetter level, BlockPos bottomLeft, Direction.Axis axis) {
+        org.bukkit.craftbukkit.util.BlockStateListPopulator blocks = new org.bukkit.craftbukkit.util.BlockStateListPopulator(((LevelAccessor) level).getMinecraftWorld()); // CraftBukkit
         Direction direction = axis == Direction.Axis.X ? Direction.WEST : Direction.SOUTH;
-        BlockPos blockPos = calculateBottomLeft(level, direction, bottomLeft);
+        BlockPos blockPos = calculateBottomLeft(level, direction, bottomLeft, blocks); // CraftBukkit
         if (blockPos == null) {
-            return new PortalShape(axis, 0, direction, bottomLeft, 0, 0);
+            return new PortalShape(axis, 0, direction, bottomLeft, 0, 0, blocks); // CraftBukkit
         } else {
-            int i = calculateWidth(level, blockPos, direction);
+            int i = calculateWidth(level, blockPos, direction, blocks); // CraftBukkit
             if (i == 0) {
-                return new PortalShape(axis, 0, direction, blockPos, 0, 0);
+                return new PortalShape(axis, 0, direction, blockPos, 0, 0, blocks); // CraftBukkit
             } else {
                 MutableInt mutableInt = new MutableInt();
-                int i1 = calculateHeight(level, blockPos, direction, i, mutableInt);
-                return new PortalShape(axis, mutableInt.getValue(), direction, blockPos, i, i1);
+                int i1 = calculateHeight(level, blockPos, direction, i, mutableInt, blocks); // CraftBukkit
+                return new PortalShape(axis, mutableInt.getValue(), direction, blockPos, i, i1, blocks); // CraftBukkit
             }
         }
     }
 
     @Nullable
-    private static BlockPos calculateBottomLeft(BlockGetter level, Direction direction, BlockPos pos) {
+    private static BlockPos calculateBottomLeft(BlockGetter level, Direction direction, BlockPos pos, org.bukkit.craftbukkit.util.BlockStateListPopulator blocks) { // CraftBukkit
         int max = Math.max(level.getMinY(), pos.getY() - 21);
 
         while (pos.getY() > max && isEmpty(level.getBlockState(pos.below()))) {
@@ -87,16 +_,16 @@
         }
 
         Direction opposite = direction.getOpposite();
-        int i = getDistanceUntilEdgeAboveFrame(level, pos, opposite) - 1;
+        int i = getDistanceUntilEdgeAboveFrame(level, pos, opposite, blocks) - 1; // CraftBukkit
         return i < 0 ? null : pos.relative(opposite, i);
     }
 
-    private static int calculateWidth(BlockGetter level, BlockPos bottomLeft, Direction direction) {
-        int distanceUntilEdgeAboveFrame = getDistanceUntilEdgeAboveFrame(level, bottomLeft, direction);
+    private static int calculateWidth(BlockGetter level, BlockPos bottomLeft, Direction direction, org.bukkit.craftbukkit.util.BlockStateListPopulator blocks) { // CraftBukkit
+        int distanceUntilEdgeAboveFrame = getDistanceUntilEdgeAboveFrame(level, bottomLeft, direction, blocks); // CraftBukkit
         return distanceUntilEdgeAboveFrame >= 2 && distanceUntilEdgeAboveFrame <= 21 ? distanceUntilEdgeAboveFrame : 0;
     }
 
-    private static int getDistanceUntilEdgeAboveFrame(BlockGetter level, BlockPos pos, Direction direction) {
+    private static int getDistanceUntilEdgeAboveFrame(BlockGetter level, BlockPos pos, Direction direction, org.bukkit.craftbukkit.util.BlockStateListPopulator blocks) { // CraftBukkit
         BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
 
         for (int i = 0; i <= 21; i++) {
@@ -104,6 +_,7 @@
             BlockState blockState = level.getBlockState(mutableBlockPos);
             if (!isEmpty(blockState)) {
                 if (FRAME.test(blockState, level, mutableBlockPos)) {
+                    blocks.setBlock(mutableBlockPos, blockState, 18); // CraftBukkit - lower left / right
                     return i;
                 }
                 break;
@@ -113,32 +_,34 @@
             if (!FRAME.test(blockState1, level, mutableBlockPos)) {
                 break;
             }
+            blocks.setBlock(mutableBlockPos, blockState1, 18); // CraftBukkit - bottom row
         }
 
         return 0;
     }
 
-    private static int calculateHeight(BlockGetter level, BlockPos pos, Direction direction, int width, MutableInt portalBlocks) {
+    private static int calculateHeight(BlockGetter level, BlockPos pos, Direction direction, int width, MutableInt portalBlocks, org.bukkit.craftbukkit.util.BlockStateListPopulator blocks) { // CraftBukkit
         BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
-        int distanceUntilTop = getDistanceUntilTop(level, pos, direction, mutableBlockPos, width, portalBlocks);
-        return distanceUntilTop >= 3 && distanceUntilTop <= 21 && hasTopFrame(level, pos, direction, mutableBlockPos, width, distanceUntilTop)
+        int distanceUntilTop = getDistanceUntilTop(level, pos, direction, mutableBlockPos, width, portalBlocks, blocks); // CraftBukkit
+        return distanceUntilTop >= 3 && distanceUntilTop <= 21 && hasTopFrame(level, pos, direction, mutableBlockPos, width, distanceUntilTop, blocks) // CraftBukkit
             ? distanceUntilTop
             : 0;
     }
 
-    private static boolean hasTopFrame(BlockGetter level, BlockPos pos, Direction direction, BlockPos.MutableBlockPos checkPos, int width, int distanceUntilTop) {
+    private static boolean hasTopFrame(BlockGetter level, BlockPos pos, Direction direction, BlockPos.MutableBlockPos checkPos, int width, int distanceUntilTop, org.bukkit.craftbukkit.util.BlockStateListPopulator blocks) { // CraftBukkit
         for (int i = 0; i < width; i++) {
             BlockPos.MutableBlockPos mutableBlockPos = checkPos.set(pos).move(Direction.UP, distanceUntilTop).move(direction, i);
             if (!FRAME.test(level.getBlockState(mutableBlockPos), level, mutableBlockPos)) {
                 return false;
             }
+            blocks.setBlock(mutableBlockPos, level.getBlockState(mutableBlockPos), 18); // CraftBukkit - upper row
         }
 
         return true;
     }
 
     private static int getDistanceUntilTop(
-        BlockGetter level, BlockPos pos, Direction direction, BlockPos.MutableBlockPos checkPos, int width, MutableInt portalBlocks
+        BlockGetter level, BlockPos pos, Direction direction, BlockPos.MutableBlockPos checkPos, int width, MutableInt portalBlocks, org.bukkit.craftbukkit.util.BlockStateListPopulator blocks // CraftBukkit
     ) {
         for (int i = 0; i < 21; i++) {
             checkPos.set(pos).move(Direction.UP, i).move(direction, -1);
@@ -162,6 +_,10 @@
                     portalBlocks.increment();
                 }
             }
+            // CraftBukkit start - left and right
+            blocks.setBlock(checkPos.set(pos).move(Direction.UP, i).move(direction, -1), level.getBlockState(checkPos), 18);
+            blocks.setBlock(checkPos.set(pos).move(Direction.UP, i).move(direction, i), level.getBlockState(checkPos), 18);
+            // CraftBukkit end
         }
 
         return 21;
@@ -175,10 +_,23 @@
         return this.width >= 2 && this.width <= 21 && this.height >= 3 && this.height <= 21;
     }
 
-    public void createPortalBlocks(LevelAccessor level) {
+    // CraftBukkit start - return boolean, add entity
+    public boolean createPortalBlocks(LevelAccessor level, Entity entity) {
+        org.bukkit.World bworld = level.getMinecraftWorld().getWorld();
+        // Copy below for loop
         BlockState blockState = Blocks.NETHER_PORTAL.defaultBlockState().setValue(NetherPortalBlock.AXIS, this.axis);
         BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1))
+            .forEach(pos -> this.blocks.setBlock(pos, blockState, 18));
+        org.bukkit.event.world.PortalCreateEvent event = new org.bukkit.event.world.PortalCreateEvent((java.util.List<org.bukkit.block.BlockState>) (java.util.List) this.blocks.getList(), bworld, (entity == null) ? null : entity.getBukkitEntity(), org.bukkit.event.world.PortalCreateEvent.CreateReason.FIRE);
+        level.getMinecraftWorld().getServer().server.getPluginManager().callEvent(event);
+
+        if (event.isCancelled()) {
+            return false;
+        }
+        // CraftBukkit end
+        BlockPos.betweenClosed(this.bottomLeft, this.bottomLeft.relative(Direction.UP, this.height - 1).relative(this.rightDir, this.width - 1))
             .forEach(pos -> level.setBlock(pos, blockState, 18));
+        return true; // CraftBukkit
     }
 
     public boolean isComplete() {
