diff --git a/src/main/java/net/minecraft/block/BlockLeaves.java b/src/main/java/net/minecraft/block/BlockLeaves.java index 86d2a39..f432cf1 100644 --- a/src/main/java/net/minecraft/block/BlockLeaves.java +++ b/src/main/java/net/minecraft/block/BlockLeaves.java @@ -8,15 +8,14 @@ import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; -import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.stats.StatList; import net.minecraft.util.IIcon; import net.minecraft.world.ColorizerFoliage; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.common.IShearable; +import org.ultramine.server.util.MinecraftUtil; public abstract class BlockLeaves extends BlockLeavesBase implements IShearable { @@ -103,6 +102,7 @@ if ((l & 8) != 0 && (l & 4) == 0) { + /* byte b0 = 4; int i1 = b0 + 1; byte b1 = 32; @@ -197,6 +197,8 @@ l1 = this.field_150128_a[k1 * j1 + k1 * b1 + k1]; if (l1 >= 0) + */ + if(MinecraftUtil.canLeavesStay(p_149674_1_, p_149674_2_, p_149674_3_, p_149674_4_, 4)) { p_149674_1_.setBlockMetadataWithNotify(p_149674_2_, p_149674_3_, p_149674_4_, l & -9, 4); } diff --git a/src/main/java/org/ultramine/server/util/MinecraftUtil.java b/src/main/java/org/ultramine/server/util/MinecraftUtil.java index 7e05bd7..fbb8a38 100644 --- a/src/main/java/org/ultramine/server/util/MinecraftUtil.java +++ b/src/main/java/org/ultramine/server/util/MinecraftUtil.java @@ -1,9 +1,13 @@ package org.ultramine.server.util; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.MathHelper; import net.minecraft.util.MovingObjectPosition; import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +import java.util.Arrays; public class MinecraftUtil { @@ -49,4 +53,88 @@ return cost; } } + + public static boolean canLeavesStay(World world, int bx, int by, int bz, int searchDistance) + { + return new LeavesPathFinder(world, bx, by, bz, searchDistance).canLeavesStay(); + } + + private static class LeavesPathFinder + { + private static final byte SIZE = 16; + private static final int SIZE_HALF = SIZE / 2; + private static final byte[] AREA = new byte[SIZE * SIZE * SIZE]; + private static final int EMPTY = 0; + private static final int WOOD = -1; + private static final int LEAVES = Byte.MAX_VALUE; + private static final int WALL = -2; + + private final World world; + private final int bx; + private final int by; + private final int bz; + private final int distance; + + public LeavesPathFinder(World world, int bx, int by, int bz, int distance) + { + this.world = world; + this.bx = bx; + this.by = by; + this.bz = bz; + this.distance = distance; + } + + public boolean canLeavesStay() + { + if(distance > 7) + throw new IllegalArgumentException("distance should be less then 8, given: " + distance); + if(!world.checkChunksExist(bx - distance - 1, by - distance - 1, bz - distance - 1, bx + distance + 1, by + distance + 1, bz + distance + 1)) + return true; + + Arrays.fill(AREA, (byte)EMPTY); + setVal(0, 0, 0, LEAVES); + return recursivePathFind(0, 0, 0, 0); + } + + private boolean recursivePathFind(int x, int y, int z, int depth) + { + int current = getVal(x, y, z); + + if(current == EMPTY) + { + Block block = world.getBlock(bx + x, by + y, bz + z); + current = block.canSustainLeaves(world, bx + x, by + y, bz + z) ? WOOD : block.isLeaves(world, bx + x, by + y, bz + z) ? LEAVES : WALL; + setVal(x, y, z, current); + } + + if(current == WOOD) + return true; + else if(current <= depth) + return false; + + setVal(x, y, z, depth); + + int newDepth = depth + 1; + if(newDepth > distance) + return false; + + if(recursivePathFind(x+1, y, z, newDepth)) return true; + if(recursivePathFind(x, y+1, z, newDepth)) return true; + if(recursivePathFind(x, y, z+1, newDepth)) return true; + if(recursivePathFind(x-1, y, z, newDepth)) return true; + if(recursivePathFind(x, y-1, z, newDepth)) return true; + if(recursivePathFind(x, y, z-1, newDepth)) return true; + return false; + } + + private static int getVal(int x, int y, int z) + { + return AREA[((x + SIZE_HALF) << 8) | ((y + SIZE_HALF) << 4) | (z + SIZE_HALF)]; + } + + private static void setVal(int x, int y, int z, int newVal) + { + AREA[((x + SIZE_HALF) << 8) | ((y + SIZE_HALF) << 4) | (z + SIZE_HALF)] = (byte)newVal; + } + } }