Skip to content

Commit

Permalink
Add CoordinatePacker
Browse files Browse the repository at this point in the history
* Currently used in Angelica & GT5u
  • Loading branch information
mitchej123 committed Jul 7, 2024
1 parent f359d38 commit 0b4a4f9
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 4 deletions.
7 changes: 7 additions & 0 deletions addon.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

test {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
}
}
4 changes: 0 additions & 4 deletions dependencies.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,3 @@ dependencies {
compileOnly("org.projectlombok:lombok:1.18.22") {transitive = false }
annotationProcessor("org.projectlombok:lombok:1.18.22")
}

test {
useJUnitPlatform()
}
62 changes: 62 additions & 0 deletions src/main/java/com/gtnewhorizon/gtnhlib/util/CoordinatePacker.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.gtnewhorizon.gtnhlib.util;

import net.minecraft.util.ChunkCoordinates;

import org.joml.Vector3i;

public final class CoordinatePacker {

private static final int SIZE_BITS_X = 26; // range in MC: -30,000,000 to 30,000,000; Range here - [-33554432,
// 33554431]
private static final int SIZE_BITS_Z = SIZE_BITS_X; // Same as X
private static final int SIZE_BITS_Y = 64 - SIZE_BITS_X - SIZE_BITS_Z; // range in MC: [0, 255]; Range here -
// [-2048, 2047]

private static final long BITS_X = (1L << SIZE_BITS_X) - 1L;
private static final long BITS_Y = (1L << SIZE_BITS_Y) - 1L;
private static final long BITS_Z = (1L << SIZE_BITS_Z) - 1L;

private static final int BIT_SHIFT_X = SIZE_BITS_Y + SIZE_BITS_Z;
private static final int BIT_SHIFT_Z = SIZE_BITS_Y;
private static final int BIT_SHIFT_Y = 0;

public static long pack(int x, int y, int z) {
long l = 0L;
l |= ((long) x & BITS_X) << BIT_SHIFT_X;
l |= ((long) y & BITS_Y) << BIT_SHIFT_Y;
l |= ((long) z & BITS_Z) << BIT_SHIFT_Z;
return l;
}

public static long pack(ChunkCoordinates coords) {
return pack(coords.posX, coords.posY, coords.posZ);
}

public static long pack(Vector3i coords) {
return pack(coords.x, coords.y, coords.z);
}

public static int unpackX(long packed) {
return (int) (packed << 64 - BIT_SHIFT_X - SIZE_BITS_X >> 64 - SIZE_BITS_X);
}

public static int unpackY(long packed) {
return (int) (packed << 64 - SIZE_BITS_Y >> 64 - SIZE_BITS_Y);
}

public static int unpackZ(long packed) {
return (int) (packed << 64 - BIT_SHIFT_Z - SIZE_BITS_Z >> 64 - SIZE_BITS_Z);
}

public static void unpack(long packed, ChunkCoordinates coords) {
coords.posX = unpackX(packed);
coords.posY = unpackY(packed);
coords.posZ = unpackZ(packed);
}

public static void unpack(long packed, Vector3i coords) {
coords.x = unpackX(packed);
coords.y = unpackY(packed);
coords.z = unpackZ(packed);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.gtnewhorizon.gtnhlib.test.util;

import static org.junit.jupiter.api.Assertions.assertTrue;

import net.minecraft.util.ChunkCoordinates;

import org.junit.jupiter.api.Test;

import com.gtnewhorizon.gtnhlib.util.CoordinatePacker;

public class CoordinatePackerTest {

@Test
void testPackUnpack() {
int[][] coordinates = {
// 0
{ 0, 0, 0 },
// MC min, [0, 255], MC min
{ -30_000_000, 0, -30_000_000 }, { -30_000_000, 255, -30_000_000 },
// MC max, [0, 255], MC max
{ 30_000_000, 0, 30_000_000 }, { 30_000_000, 255, 30_000_000 },
// MC min, [0, 255], MC max
{ -30_000_000, 0, 30_000_000 }, { -30_000_000, 255, 30_000_000 },
// MC max, [0, 255], MC min
{ 30_000_000, 0, -30_000_000 }, { 30_000_000, 255, -30_000_000 },
// Java Min/Max based on bits
{ -33_554_432, -2048, -33_554_432 }, { 33_554_431, 2047, 33_554_431 },
// bunch of 255's
{ 255, 255, 255 }, { 255, 255, 0 }, { 255, 0, 255 }, { 0, 255, 255 }, { 0, 0, 255 }, { 0, 255, 0 },
{ 255, 0, 0 }, { 0, 255, 0 }, { 0, 0, 255 },
// 0, min/max, 0
{ 0, -2048, 0 }, { 0, 2047, 0 }, };
final ChunkCoordinates chunkCoordinates = new ChunkCoordinates();
final ChunkCoordinates unpackedCoordinates = new ChunkCoordinates();
for (int[] coordinate : coordinates) {
chunkCoordinates.set(coordinate[0], coordinate[1], coordinate[2]);
long packed = CoordinatePacker.pack(chunkCoordinates);
CoordinatePacker.unpack(packed, unpackedCoordinates);
assertTrue(
coordinate[0] == unpackedCoordinates.posX && coordinate[1] == unpackedCoordinates.posY
&& coordinate[2] == unpackedCoordinates.posZ,
"Failed for " + coordinate[0]
+ ", "
+ coordinate[1]
+ ", "
+ coordinate[2]
+ " -> "
+ packed
+ " -> "
+ unpackedCoordinates.posX
+ ", "
+ unpackedCoordinates.posY
+ ", "
+ unpackedCoordinates.posZ);
}
}

}

0 comments on commit 0b4a4f9

Please sign in to comment.