/*
* This file is part of Cubic Chunks Mod, licensed under the MIT License (MIT).
*
* Copyright (c) 2015 contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package cubicchunks.util;
// TODO: remove this... packing x, y, z into a long is just stupid.
// Mojang did it with x, z and it was stupid than also!
public class AddressTools {
// Anvil format details:
// within a region file, each chunk coord gets 5 bits
// the coord for each region is capped at 27 bits
// here's the encoding scheme for 64 bits of space:
// y: 20 bits, signed, 1,048,576 chunks, 16,777,216 blocks
// x: 22 bits, signed, 4,194,304 chunks, 67,108,864 blocks
// z: 22 bits, signed, 4,194,304 chunks, 67,108,864 blocks
// World.setBlock() caps block x,z at -30m to 30m, so our 22-bit cap on chunk x,z is just right!
// the Anvil format gives 32 bits to each chunk coordinate, but we're only giving 22 bits
// moving at 8 blocks/s (which is like minecart speed), it would take ~48 days to reach the x or z edge from the center
// at the same speed, it would take ~24 days to reach the top from the bottom
// that seems like enough room for a minecraft world
// 0 1 |2 3 4| 5 6 |
// 0123456789012345678901234567890123456789012345678901234567890123
// yyyyyyyyyyyyyyyyyyyyxxxxxxxxxxxxxxxxxxxxxxzzzzzzzzzzzzzzzzzzzzzz
private static final int Y_BITS = 20;
private static final int X_BITS = 22;
private static final int Z_BITS = 22;
private static final int Z_BIT_OFFSET = 0;
private static final int X_BIT_OFFSET = Z_BIT_OFFSET + Z_BITS;
private static final int Y_BIT_OFFSET = X_BIT_OFFSET + X_BITS;
public static final int MIN_CUBE_Y = Bits.getMinSigned(Y_BITS);
public static final int MAX_CUBE_Y = Bits.getMaxSigned(Y_BITS);
public static final int MIN_CUBE_X = Bits.getMinSigned(X_BITS);
public static final int MAX_CUBE_X = Bits.getMaxSigned(X_BITS);
public static final int MIN_CUBE_Z = Bits.getMinSigned(Z_BITS);
public static final int MAX_CUBE_Z = Bits.getMaxSigned(Z_BITS);
public static final int MIN_BLOCK_Y = Coords.cubeToMinBlock(MIN_CUBE_Y);
public static final int MAX_BLOCK_Y = Coords.cubeToMaxBlock(MAX_CUBE_Y);
public static long getAddress(int x, int y, int z) {
return Bits.packSignedToLong(y, Y_BITS, Y_BIT_OFFSET)
| Bits.packSignedToLong(x, X_BITS, X_BIT_OFFSET)
| Bits.packSignedToLong(z, Z_BITS, Z_BIT_OFFSET);
}
public static long getAddress(int x, int z) {
return Bits.packSignedToLong(x, X_BITS, X_BIT_OFFSET)
| Bits.packSignedToLong(z, Z_BITS, Z_BIT_OFFSET);
}
public static int getY(long address) {
return Bits.unpackSigned(address, Y_BITS, Y_BIT_OFFSET);
}
public static int getX(long address) {
return Bits.unpackSigned(address, X_BITS, X_BIT_OFFSET);
}
public static int getZ(long address) {
return Bits.unpackSigned(address, Z_BITS, Z_BIT_OFFSET);
}
public static short getLocalAddress(int localX, int localY, int localZ) {
return (short) (Bits.packUnsignedToInt(localX, 4, 0)
| Bits.packUnsignedToInt(localY, 4, 4)
| Bits.packUnsignedToInt(localZ, 4, 8));
}
public static int getLocalX(int localAddress) {
return Bits.unpackUnsigned(localAddress, 4, 0);
}
public static int getLocalY(int localAddress) {
return Bits.unpackUnsigned(localAddress, 4, 4);
}
public static int getLocalZ(int localAddress) {
return Bits.unpackUnsigned(localAddress, 4, 8);
}
}