Skip to content

Instantly share code, notes, and snippets.

@WizardlyBump17
Created August 9, 2024 21:36
Show Gist options
  • Save WizardlyBump17/4f44104016efd4486788c4997b71fd98 to your computer and use it in GitHub Desktop.
Save WizardlyBump17/4f44104016efd4486788c4997b71fd98 to your computer and use it in GitHub Desktop.
Some methods to compress coordinates
import java.util.Arrays;
public class Coord {
public static void main(String[] args) {
int x = (int) -Math.pow(2, 32);
int y = (int) Math.pow(2, 23) - 1;
int z = (int) Math.pow(2, 32);
int chunkX = x >> 4;
int chunkZ = z >> 4;
long serializedChunk = serializeChunkPos(chunkX, chunkZ);
int[] deserializedChunk = deserializeChunkPos(serializedChunk);
int serialized = serializeBlockPos(x, y, z);
int[] deserialized = deserializeBlockPos(serialized, chunkX, chunkZ);
System.out.println(x + " " + y + " " + z);
System.out.println(Arrays.toString(deserialized));
System.out.println();
System.out.println(chunkX + " " + chunkZ);
System.out.println(Arrays.toString(deserializedChunk));
}
/**
* <p>
* Serializes the given coordinate into a single integer.
* The X and Z are relative to the chunk, so they are in the range [0, 15].
* </p>
* <p>
* The serialized integer is composed of the following bits:
* <ul>
* <li>4 bits for the X coordinate</li>
* <li>1 bit for the sign of the Y coordinate</li>
* <li>23 bits for the absolute value of the Y coordinate</li>
* <li>4 bits for the Z coordinate</li>
* </ul>
* </p>
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
* @return an integer representing the given coordinate
*/
public static int serializeBlockPos(int x, int y, int z) {
return (x & 15) << 28 | (y < 0 ? 1 : 0) << 27 | (Math.abs(y) & 0x7FFFFF) << 4 | (z & 15);
}
/**
* <p>
* Deserializes the given serialized integer into an array of integers representing the X, Y, and Z coordinates.
* As the {@link #serializeBlockPos(int, int, int)} method serializes the coordinates relative to the chunk,
* you must provide the chunk X and Z coordinates to get the absolute coordinates.
* </p>
*
* @param serialized the serialized integer
* @param chunkX the X coordinate of the chunk
* @param chunkZ the Z coordinate of the chunk
* @return an array of integers representing the X, Y, and Z coordinates
* @see #serializeBlockPos(int, int, int)
*/
public static int[] deserializeBlockPos(int serialized, int chunkX, int chunkZ) {
return new int[] {
(chunkX << 4) + ((serialized >> 28) & 15),
(serialized >> 27 & 1) == 1 ? -((serialized >> 4) & 0x7FFFFF) : (serialized >> 4) & 0x7FFFFF,
(chunkZ << 4) + (serialized & 15)
};
}
/**
* <p>
* Serializes the given chunk X and Z coordinates into a single long.
* </p>
* <p>
* The serialized long is composed of the following bits:
* <ul>
* <li>32 bits for the X coordinate</li>
* <li>32 bits for the Z coordinate</li>
* </ul>
* </p>
*
* @param x the X coordinate of the chunk
* @param z the Z coordinate of the chunk
* @return a long representing the given chunk coordinates
*/
public static long serializeChunkPos(int x, int z) {
return (x & 0xFFFFFFFFL) << 32 | z & 0xFFFFFFFFL;
}
/**
* <p>
* Deserializes the given serialized long into an array of integers representing the X and Z coordinates of the chunk.
* </p>
*
* @param serialized the serialized long
* @return an array of integers representing the X and Z coordinates of the chunk
*/
public static int[] deserializeChunkPos(long serialized) {
return new int[] {
(int) (serialized >> 32),
(int) serialized
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment