package de.take_weiland.mods.commons.util; import de.take_weiland.mods.commons.net.MCDataOutput; import net.minecraft.block.Block; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import javax.annotation.ParametersAreNonnullByDefault; /** * @author diesieben07 */ @ParametersAreNonnullByDefault public final class BlockPos implements Comparable<BlockPos> { final int x; final int y; final int z; public BlockPos(int x, int y, int z) { this.x = x; this.y = y; this.z = z; } public BlockPos(BlockPos other) { this(other.x, other.y, other.z); } public int x() { return x; } public int y() { return y; } public int z() { return z; } public Block getBlock(World world) { return Block.blocksList[world.getBlockId(x, y, z)]; } public int getMetadata(World world) { return world.getBlockMetadata(x, y, z); } public TileEntity getTileEntity(World world) { return world.getBlockTileEntity(x, y, z); } public float distanceTo(int x, int y, int z) { float dX = this.x - x; float dY = this.y - y; float dZ = this.z - z; return (float) Math.sqrt(dX * dX + dY * dY + dZ * dZ); } public float distanceTo(BlockPos coords) { return distanceTo(coords.x, coords.y, coords.z); } public float distanceSq(int x, int y, int z) { float dX = this.x - x; float dY = this.y - y; float dZ = this.z - z; return dX * dX + dY * dY + dZ * dZ; } public float distanceSq(BlockPos coords) { return distanceSq(coords.x, coords.y, coords.z); } public boolean valid() { return x >= -30000000 && x < 30000000 && z >= -30000000 && z < 30000000 && y >= 0 && y < 256; } public void validate() { if (!valid()) { throw new IllegalStateException(String.format("Illegal Block coordinates [%d %d %d]", x, y, z)); } } public long toLong() { return toLong(x, y, z); } @Override public int compareTo(BlockPos o) { int myY; int oY; if ((myY = y) == (oY = o.y)) { int myZ; int oZ; if ((myZ = z) == (oZ = o.z)) { return x - o.x; } else { return myZ - oZ; } } else { return myY - oY; } } @Override public boolean equals(Object o) { if (o instanceof BlockPos) { BlockPos other = (BlockPos) o; return this.x == other.x && this.y == other.y && this.z == other.z; } else { return false; } } @Override public int hashCode() { return hash(x, y, z); } @Override public String toString() { return "BlockPos(" + x + ", " + y + ", " + z + ")"; } public static int hash(int x, int y, int z) { // shift z to avoid hash == y for x == z return x ^ y ^ (z << 6); } public static void toByteStream(MCDataOutput out, int x, int y, int z) { out.writeInt(x); out.writeByte(y); out.writeInt(z); } private static final int X_Z_BITS = 26; private static final long X_Z_MASK = (1L << X_Z_BITS) - 1L; private static final long Y_BITS = 8L; private static final long Y_MASK = (1L << Y_BITS) - 1L; @SuppressWarnings("SuspiciousNameCombination") private static final long Y_SHIFT = X_Z_BITS; private static final long Z_SHIFT = Y_SHIFT + Y_BITS; public static long toLong(int x, int y, int z) { return x & X_Z_MASK | (y & Y_MASK) << Y_SHIFT | (z & X_Z_MASK) << Z_SHIFT; } private static final long X_RV_MASK = (1L << X_Z_BITS) - 1; private static final long Y_RV_MASK = ((1L << Y_BITS) - 1) << Y_SHIFT; private static final long Z_RV_MASK = ((1L << X_Z_BITS) - 1) << Z_SHIFT; private static final long X_SIGN_BIT = 1 << (X_Z_BITS - 1); private static final long Z_SIGN_BIT = 1L << (X_Z_BITS + X_Z_BITS + Y_BITS - 1); private static final long NULL_LONG_VAL = 1L << 63; public static BlockPos fromLong(long l) { return new BlockPos((int) ((l & X_RV_MASK) | -(l & X_SIGN_BIT)), (int) ((l & Y_RV_MASK) >>> 26), (int) (((l & Z_RV_MASK) | -(l & Z_SIGN_BIT)) >> 34)); } }