diff --git a/src/main/java/net/minecraft/core/block/BaseLeavesBlock.java b/src/main/java/net/minecraft/core/block/BaseLeavesBlock.java
index 8314568e9..85924e0fc 100644
--- a/src/main/java/net/minecraft/core/block/BaseLeavesBlock.java
+++ b/src/main/java/net/minecraft/core/block/BaseLeavesBlock.java
@@ -216,7 +216,7 @@ public abstract class BaseLeavesBlock extends Block
     
     @Override
     public int getPlacedBlockMetadata(@Nullable Player player, ItemStack stack, World world, int x, int y, int z, Side side, double xPlaced, double yPlaced) {
-    	return LeavesLayerBlock.MASK_PERMANENT;
+    	return 0b1 << PERMANENT_FLAG_BIT;
     }
     
     @Override
diff --git a/src/main/java/net/minecraft/core/block/LogBlock.java b/src/main/java/net/minecraft/core/block/LogBlock.java
index b015d03b2..863d86464 100644
--- a/src/main/java/net/minecraft/core/block/LogBlock.java
+++ b/src/main/java/net/minecraft/core/block/LogBlock.java
@@ -14,25 +14,25 @@ public class LogBlock extends AxisAlignedBlock
     @Override
     public void onBlockRemoved(World world, int x, int y, int z, int data)
     {
-        byte byte0 = 4;
-        int l = byte0 + 1;
-        if(world.areBlocksLoaded(x - l, y - l, z - l, x + l, y + l, z + l))
+        byte r = 4;
+        int r2 = r + 1;
+        if(world.areBlocksLoaded(x - r2, y - r2, z - r2, x + r2, y + r2, z + r2))
         {
-            for(int i1 = -byte0; i1 <= byte0; i1++)
+            for(int _x = -r; _x <= r; _x++)
             {
-                for(int j1 = -byte0; j1 <= byte0; j1++)
+                for(int _y = -r; _y <= r; _y++)
                 {
-                    for(int k1 = -byte0; k1 <= byte0; k1++)
+                    for(int _z = -r; _z <= r; _z++)
                     {
-                        int l1 = world.getBlockId(x + i1, y + j1, z + k1);
+                        int l1 = world.getBlockId(x + _x, y + _y, z + _z);
                         if(!(Block.blocksList[l1] instanceof BaseLeavesBlock))
                         {
                             continue;
                         }
-                        int i2 = world.getBlockMetadata(x + i1, y + j1, z + k1);
-                        if((i2 & 8) == 0)
+                        int leavesMeta = world.getBlockMetadata(x + _x, y + _y, z + _z);
+                        if(!BaseLeavesBlock.isPermanent(leavesMeta))
                         {
-                            world.setBlockMetadata(x + i1, y + j1, z + k1, i2 | 8);
+                            world.setBlockMetadata(x + _x, y + _y, z + _z, BaseLeavesBlock.setDecaying(leavesMeta, true));
                         }
                     }
 
diff --git a/src/main/java/net/minecraft/core/block/MushroomBlock.java b/src/main/java/net/minecraft/core/block/MushroomBlock.java
index f14f9b8ad..19b2e8100 100644
--- a/src/main/java/net/minecraft/core/block/MushroomBlock.java
+++ b/src/main/java/net/minecraft/core/block/MushroomBlock.java
@@ -23,9 +23,9 @@ public class MushroomBlock extends FlowerBlock
     {
         if(rand.nextInt(100) == 0)
         {
-            int x1 = (z + rand.nextInt(3)) - 1;
+            int x1 = (x + rand.nextInt(3)) - 1;
             int randY = (y + rand.nextInt(2)) - rand.nextInt(2);
-            int z1 = (x + rand.nextInt(3)) - 1;
+            int z1 = (z + rand.nextInt(3)) - 1;
             if(world.isAirBlock(x1, randY, z1) && canBlockStay(world, x1, randY, z1))
             {
                 int x2 = x + rand.nextInt(3) - 1;
diff --git a/src/main/java/net/minecraft/core/world/PortalHandler.java b/src/main/java/net/minecraft/core/world/PortalHandler.java
index a3d34d141..bc4ccc125 100644
--- a/src/main/java/net/minecraft/core/world/PortalHandler.java
+++ b/src/main/java/net/minecraft/core/world/PortalHandler.java
@@ -33,7 +33,8 @@ public class PortalHandler
     public boolean attemptToTeleportToClosestPortal(World world, Entity entity, @Nullable DyeColor portalColor, Dimension oldDim, Dimension newDim)
     {
         int searchRadius = 128;
-        double lowestEntityDistanceSquared = -1D;
+        double lowestEntityDistanceSquaredXZ = -1D;
+        double lowestEntityDistanceSquaredY = -1D;
         int targetPortalId;
         int closestPortalX = 0;
         int closestPortalY = 0;
@@ -44,18 +45,15 @@ public class PortalHandler
         WorldType oldWorldType = oldDim.getDimensionData(world).getWorldType();
         WorldType newWorldType = newDim.getDimensionData(world).getWorldType();
         
-        double entityPosYScaled = entity.y;
-        int oldDimRangeY = oldWorldType.getMaxY() - oldWorldType.getMinY();
-        entityPosYScaled -= oldWorldType.getMinY();
+        double entityPosYScaled = entity.y - entity.heightOffset;
+        int oldDimRangeY = oldWorldType.getMaxPortalY() - oldWorldType.getMinPortalY();
+        entityPosYScaled -= oldWorldType.getMinPortalY();
         entityPosYScaled /= oldDimRangeY; // Now 0.0 to 1.0
-        int minY = newWorldType.getMinY();
-        if (newDim == Dimension.NETHER) {
-            minY = 128;
-        }
-        int newDimRangeY = newWorldType.getMaxY() - minY;
+        int newDimRangeY = newWorldType.getMaxPortalY() - newWorldType.getMinPortalY();
         entityPosYScaled *= newDimRangeY;
-        entityPosYScaled += minY; // Now newDim minY to newDim maxY
-        
+        entityPosYScaled += newWorldType.getMinPortalY(); // Now newDim minY to newDim maxY
+        entityPosYScaled = MathHelper.clamp(entityPosYScaled, newWorldType.getMinPortalY(), newWorldType.getMaxPortalY());
+
         if (newDim.homeDim == null)
         {
         	targetPortalId = oldDim.portalBlockId;
@@ -65,14 +63,14 @@ public class PortalHandler
         	targetPortalId = newDim.portalBlockId;
         }
         
-        // Attempt to find portal 
+        // Attempt to find closest portal along the xz plane
         for(int dx = entityBlockX - searchRadius; dx <= entityBlockX + searchRadius; dx++)
         {
             double xEntityDistance = ((double)dx + 0.5D) - entity.x;
             for(int dz = entityBlockZ - searchRadius; dz <= entityBlockZ + searchRadius; dz++)
             {
                 double zEntityDistance = ((double)dz + 0.5D) - entity.z;
-                for(int dy = newWorldType.getMaxY() - 1; dy >= minY; dy--)
+                for(int dy = newWorldType.getMaxPortalY() - 1; dy >= newWorldType.getMinPortalY(); dy--)
                 {
                     if(world.getBlockId(dx, dy, dz) != targetPortalId)
                     {
@@ -86,11 +84,11 @@ public class PortalHandler
                     // Find the bottom portal block of the portal
                     for(; world.getBlockId(dx, dy - 1, dz) == targetPortalId; dy--);
                     
-                    double yEntityDistance = ((double)dy + 0.5D) - entityPosYScaled;
-                    double entityDistanceSquared = xEntityDistance * xEntityDistance + yEntityDistance * yEntityDistance + zEntityDistance * zEntityDistance;
-                    if(lowestEntityDistanceSquared < 0.0D || entityDistanceSquared < lowestEntityDistanceSquared)
+//                    double yEntityDistance = ((double)dy + 0.5D) - entityPosYScaled;
+                    double entityDistanceSquared = xEntityDistance * xEntityDistance /*+ yEntityDistance * yEntityDistance*/ + zEntityDistance * zEntityDistance;
+                    if(lowestEntityDistanceSquaredXZ < 0.0D || entityDistanceSquared < lowestEntityDistanceSquaredXZ)
                     {
-                        lowestEntityDistanceSquared = entityDistanceSquared;
+                        lowestEntityDistanceSquaredXZ = entityDistanceSquared;
                         closestPortalX = dx;
                         closestPortalY = dy;
                         closestPortalZ = dz;
@@ -101,7 +99,40 @@ public class PortalHandler
 
         }
 
-        if(lowestEntityDistanceSquared >= 0.0D)
+        // Find closest portal to height
+        if (lowestEntityDistanceSquaredXZ >= 0.0D) {
+            int cx = closestPortalX;
+            int cz = closestPortalZ;
+            for(int dx = cx - 1; dx <= cx + 1; dx++) {
+                double xEntityDistance = ((double) dx + 0.5D) - entity.x;
+                for (int dz = cz - 1; dz <= cz + 1; dz++) {
+                    double zEntityDistance = ((double) dz + 0.5D) - entity.z;
+                    for (int dy = newWorldType.getMaxPortalY() - 1; dy >= newWorldType.getMinPortalY(); dy--) {
+                        if (world.getBlockId(dx, dy, dz) != targetPortalId) {
+                            continue;
+                        }
+
+                        if (portalColor != null && targetPortalId > 0 && ((PortalBlock) Block.getBlock(targetPortalId)).getColor(world, dx, dy, dz) != portalColor) {
+                            continue;
+                        }
+
+                        // Find the bottom portal block of the portal
+                        for (; world.getBlockId(dx, dy - 1, dz) == targetPortalId; dy--) ;
+
+                        double yEntityDistance = ((double) dy + 0.5D) - entityPosYScaled;
+                        double entityDistanceSquared = xEntityDistance * xEntityDistance + yEntityDistance * yEntityDistance + zEntityDistance * zEntityDistance;
+                        if (lowestEntityDistanceSquaredY < 0 || entityDistanceSquared < lowestEntityDistanceSquaredY) {
+                            lowestEntityDistanceSquaredY = entityDistanceSquared;
+                            closestPortalX = dx;
+                            closestPortalY = dy;
+                            closestPortalZ = dz;
+                        }
+                    }
+                }
+            }
+        }
+
+        if(lowestEntityDistanceSquaredY >= 0.0D)
         {
             int portalX = closestPortalX;
             int portalY = closestPortalY;
@@ -140,18 +171,14 @@ public class PortalHandler
         WorldType oldWorldType = oldDim.getDimensionData(world).getWorldType();
         WorldType newWorldType = newDim.getDimensionData(world).getWorldType();
 
-        double entityPosYScaled = entity.y;
-        int oldDimRangeY = oldWorldType.getMaxY() - oldWorldType.getMinY();
-        entityPosYScaled -= oldWorldType.getMinY();
+        double entityPosYScaled = entity.y - entity.heightOffset;
+        int oldDimRangeY = oldWorldType.getMaxPortalY() - oldWorldType.getMinPortalY();
+        entityPosYScaled -= oldWorldType.getMinPortalY();
         entityPosYScaled /= oldDimRangeY; // Now 0.0 to 1.0
-        int minY = newWorldType.getMinY();
-        if (newDim == Dimension.NETHER) {
-            minY = 128;
-        }
-        int newDimRangeY = newWorldType.getMaxY() - minY;
+        int newDimRangeY = newWorldType.getMaxPortalY() - newWorldType.getMinPortalY();
         entityPosYScaled *= newDimRangeY;
-        entityPosYScaled += minY; // Now newDim minY to newDim maxY
-
+        entityPosYScaled += newWorldType.getMinPortalY(); // Now newDim minY to newDim maxY
+        entityPosYScaled = MathHelper.clamp(entityPosYScaled, newWorldType.getMinPortalY(), newWorldType.getMaxPortalY());
 
 
         byte portalSearchRadius = 16;
@@ -184,7 +211,7 @@ public class PortalHandler
             for(int dz = blockZ - portalSearchRadius; dz <= blockZ + portalSearchRadius; dz++)
             {
                 double zEntityDistance = ((double)dz + 0.5D) - entity.z;
-                for(int dy = newWorldType.getMaxY() - 1; dy >= minY; dy--)
+                for(int dy = newWorldType.getMaxPortalY() - 1; dy >= newWorldType.getMinPortalY(); dy--)
                 {
                     if(!world.isAirBlock(dx, dy, dz))
                     {
@@ -246,7 +273,7 @@ label0:
                 for(int dz = blockZ - portalSearchRadius; dz <= blockZ + portalSearchRadius; dz++)
                 {
                     double entityDistanceZ = ((double)dz + 0.5D) - entity.z;
-                    for(int dy = newWorldType.getMaxY() - 1; dy >= minY; dy--)
+                    for(int dy = newWorldType.getMaxPortalY() - 1; dy >= newWorldType.getMinPortalY(); dy--)
                     {
                         if(!world.isAirBlock(dx, dy, dz))
                         {
diff --git a/src/main/java/net/minecraft/core/world/type/WorldType.java b/src/main/java/net/minecraft/core/world/type/WorldType.java
index f7abede76..332206fdb 100644
--- a/src/main/java/net/minecraft/core/world/type/WorldType.java
+++ b/src/main/java/net/minecraft/core/world/type/WorldType.java
@@ -24,7 +24,9 @@ public abstract class WorldType {
     private final boolean hasClouds;
     private final boolean hasSky;
     private final int minY;
+    private final int minPortalY;
     private final int maxY;
+    private final int maxPortalY;
     private final int oceanY;
     private final int oceanBlockId;
     private final int fillerBlockId;
@@ -44,7 +46,17 @@ public abstract class WorldType {
         this.hasClouds = properties.hasClouds;
         this.hasSky = properties.hasSky;
         this.minY = properties.minY;
+        if (properties.minPortalY != null) {
+            this.minPortalY = properties.minPortalY;
+        } else {
+            this.minPortalY = this.minY;
+        }
         this.maxY = properties.maxY;
+        if (properties.maxPortalY != null) {
+            this.maxPortalY = properties.maxPortalY;
+        } else {
+            this.maxPortalY = this.maxY;
+        }
         this.oceanY = properties.oceanY;
         this.oceanBlockId = properties.oceanBlock == null ? 0 : properties.oceanBlock.id;
         this.fillerBlockId = properties.fillerBlock == null ? 0 : properties.fillerBlock.id;
@@ -91,10 +103,18 @@ public abstract class WorldType {
         return minY;
     }
 
+    public int getMinPortalY() {
+        return minPortalY;
+    }
+
     public int getMaxY() {
         return maxY;
     }
 
+    public int getMaxPortalY() {
+        return maxPortalY;
+    }
+
     public int getOceanY() {
         return oceanY;
     }
@@ -254,7 +274,9 @@ public abstract class WorldType {
         private boolean hasClouds = true;
         private boolean hasSky = true;
         private int minY = 0;
+        private Integer minPortalY = null;
         private int maxY = 255;
+        private Integer maxPortalY = null;
         private int oceanY = 128;
         private Block oceanBlock = null;
         private Block fillerBlock = null;
@@ -328,6 +350,21 @@ public abstract class WorldType {
             return this;
         }
 
+        public Properties portalBounds(int minPortalY, int maxPortalY) {
+            if (minPortalY < 0) {
+                throw new IllegalArgumentException("minPortalY cannot be negative");
+            }
+            if (maxPortalY < 0) {
+                throw new IllegalArgumentException("maxPortalY cannot be negative");
+            }
+            if (maxPortalY <= minPortalY) {
+                throw new IllegalArgumentException("maxPortalY cannot be less than or equal to minPortalY");
+            }
+            this.minPortalY = minPortalY;
+            this.maxPortalY = maxPortalY;
+            return this;
+        }
+
         public Properties oceanBlock(Block oceanBlock) {
             this.oceanBlock = oceanBlock;
             return this;
diff --git a/src/main/java/net/minecraft/core/world/type/WorldTypes.java b/src/main/java/net/minecraft/core/world/type/WorldTypes.java
index 3a2dacbd9..9e70a39a6 100644
--- a/src/main/java/net/minecraft/core/world/type/WorldTypes.java
+++ b/src/main/java/net/minecraft/core/world/type/WorldTypes.java
@@ -28,6 +28,7 @@ public abstract class WorldTypes {
             "minecraft:nether.default",
             new WorldTypeNether(
                     WorldTypeNether.defaultProperties("worldType.nether.default")
+                        .portalBounds(127, 255)
             )
     );
     public static final WorldType NETHER_SKYBLOCK = register(
diff --git a/src/main/java/net/minecraft/core/world/type/nether/WorldTypeNetherSkyblock.java b/src/main/java/net/minecraft/core/world/type/nether/WorldTypeNetherSkyblock.java
index ea71bcce3..96fb2032a 100644
--- a/src/main/java/net/minecraft/core/world/type/nether/WorldTypeNetherSkyblock.java
+++ b/src/main/java/net/minecraft/core/world/type/nether/WorldTypeNetherSkyblock.java
@@ -14,4 +14,5 @@ public class WorldTypeNetherSkyblock
     public ChunkGenerator createChunkGenerator(World world) {
         return new ChunkGeneratorSkyblockNether(world);
     }
+
 }
