fix position encoding

This commit is contained in:
Moritz Zwerger 2025-03-05 14:03:29 +01:00
parent 3feebb8935
commit 2bb4cfc4dc
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
7 changed files with 80 additions and 23 deletions

View File

@ -209,7 +209,7 @@ class World(
} }
companion object { companion object {
const val MAX_SIZE = 30_000_000 const val MAX_SIZE = BlockPosition.MAX_X
const val MAX_SIZEf = MAX_SIZE.toFloat() const val MAX_SIZEf = MAX_SIZE.toFloat()
const val MAX_SIZEd = MAX_SIZE.toDouble() const val MAX_SIZEd = MAX_SIZE.toDouble()
const val MAX_RENDER_DISTANCE = 64 const val MAX_RENDER_DISTANCE = 64

View File

@ -33,11 +33,12 @@ value class BlockPosition(
assertPosition(y, MIN_Y, MAX_Y) assertPosition(y, MIN_Y, MAX_Y)
assertPosition(z, -MAX_Z, MAX_Z) assertPosition(z, -MAX_Z, MAX_Z)
} }
constructor(position: InChunkPosition) : this(position.x, position.y, position.z) constructor(position: InChunkPosition) : this(position.x, position.y, position.z)
inline val x: Int get() = (raw shr SHIFT_X).toInt() and MASK_X inline val x: Int get() = (((raw ushr SHIFT_X).toInt() and MASK_X) shl (Int.SIZE_BITS - BITS_X)) shr (Int.SIZE_BITS - BITS_X)
inline val y: Int get() = (raw shr SHIFT_Y).toInt() and MASK_Y inline val y: Int get() = (((raw ushr SHIFT_Y).toInt() and MASK_Y) shl (Int.SIZE_BITS - BITS_Y)) shr (Int.SIZE_BITS - BITS_Y)
inline val z: Int get() = (raw shr SHIFT_Z).toInt() and MASK_Z inline val z: Int get() = (((raw ushr SHIFT_Z).toInt() and MASK_Z) shl (Int.SIZE_BITS - BITS_Z)) shr (Int.SIZE_BITS - BITS_Z)
inline fun plusX(): BlockPosition { inline fun plusX(): BlockPosition {
@ -61,7 +62,7 @@ value class BlockPosition(
} }
inline fun plusY(y: Int): BlockPosition { inline fun plusY(y: Int): BlockPosition {
assertPosition(this.y + y, -MAX_Y, MAX_Y) assertPosition(this.y + y, MIN_Y, MAX_Y)
return BlockPosition(raw + Y * y) return BlockPosition(raw + Y * y)
} }
@ -129,13 +130,13 @@ value class BlockPosition(
const val MASK_Y = (1 shl BITS_Y) - 1 const val MASK_Y = (1 shl BITS_Y) - 1
const val SHIFT_Y = BITS_X + BITS_Z const val SHIFT_Y = BITS_X + BITS_Z
const val X = 1 shl SHIFT_X const val X = 1L shl SHIFT_X
const val Z = 1 shl SHIFT_Z const val Z = 1L shl SHIFT_Z
const val Y = 1 shl SHIFT_Y const val Y = 1L shl SHIFT_Y
const val MAX_X = 30_000_000 const val MAX_X = 30_000_000
const val MIN_Y = -2047 const val MIN_Y = -2048
const val MAX_Y = 2048 const val MAX_Y = 2047
const val MAX_Z = 30_000_000 const val MAX_Z = 30_000_000

View File

@ -26,7 +26,7 @@ value class ChunkPosition(
constructor() : this(0, 0) constructor() : this(0, 0)
constructor(x: Int, z: Int) : this((z.toLong() shl SHIFT_Z) or (x.toLong() shl SHIFT_X)) { constructor(x: Int, z: Int) : this(((z.toLong() and Integer.toUnsignedLong(MASK_Z)) shl SHIFT_Z) or ((x.toLong() and Integer.toUnsignedLong(MASK_X)) shl SHIFT_X)) {
assertPosition(x, -MAX_X, MAX_X) assertPosition(x, -MAX_X, MAX_X)
assertPosition(z, -MAX_Z, MAX_Z) assertPosition(z, -MAX_Z, MAX_Z)
} }
@ -92,19 +92,19 @@ value class ChunkPosition(
companion object { companion object {
const val BITS_X = 32 const val BITS_X = 32
const val MASK_X = (1 shl BITS_X) - 1 const val MASK_X = ((1L shl BITS_X) - 1).toInt()
const val SHIFT_X = 0 const val SHIFT_X = 0
const val BITS_Z = 32 const val BITS_Z = 32
const val MASK_Z = (1 shl BITS_Z) - 1 const val MASK_Z = ((1L shl BITS_Z) - 1).toInt()
const val SHIFT_Z = BITS_X const val SHIFT_Z = BITS_X
const val X = 1L shl SHIFT_X const val X = 1L shl SHIFT_X
const val Z = 1L shl SHIFT_Z const val Z = 1L shl SHIFT_Z
const val MAX_X = Int.MAX_VALUE // TODO const val MAX_X = (BlockPosition.MAX_X shr 4) + 1
const val MAX_Z = Int.MAX_VALUE // TODO const val MAX_Z = (BlockPosition.MAX_Z shr 4) + 1
val EMPTY = ChunkPosition(0, 0) val EMPTY = ChunkPosition(0, 0)

View File

@ -34,9 +34,9 @@ value class InChunkPosition(
assertPosition(z, 0, ProtocolDefinition.SECTION_MAX_Z) assertPosition(z, 0, ProtocolDefinition.SECTION_MAX_Z)
} }
inline val x: Int get() = (raw shr SHIFT_X) and MASK_X inline val x: Int get() = (raw ushr SHIFT_X) and MASK_X
inline val y: Int get() = (raw and (MASK_Y shl SHIFT_Y)) shl 20 shr 20 inline val y: Int get() = (((raw ushr SHIFT_Y) and MASK_Y) shl (Int.SIZE_BITS - BITS_Y)) shr (Int.SIZE_BITS - BITS_Y)
inline val z: Int get() = (raw shr SHIFT_Z) and MASK_Z inline val z: Int get() = (raw ushr SHIFT_Z) and MASK_Z
inline val xz: Int get() = raw and ((MASK_X shl SHIFT_X) or (MASK_Z shl SHIFT_Z)) inline val xz: Int get() = raw and ((MASK_X shl SHIFT_X) or (MASK_Z shl SHIFT_Z))

View File

@ -40,12 +40,24 @@ class BlockPositionTest {
assertEquals(position.x, 2) assertEquals(position.x, 2)
} }
@Test
fun `correct positive x large`() {
val position = BlockPosition(29_999_999, 0xF, 0xF)
assertEquals(position.x, 29_999_999)
}
@Test @Test
fun `correct negative x`() { fun `correct negative x`() {
val position = BlockPosition(-2, 0xF, 0xF) val position = BlockPosition(-2, 0xF, 0xF)
assertEquals(position.x, -2) assertEquals(position.x, -2)
} }
@Test
fun `correct negative x large`() {
val position = BlockPosition(-29_999_999, 0xF, 0xF)
assertEquals(position.x, -29_999_999)
}
@Test @Test
fun `correct plus x`() { fun `correct plus x`() {
val position = BlockPosition(2, 0xF, 0xF) val position = BlockPosition(2, 0xF, 0xF)
@ -70,12 +82,24 @@ class BlockPositionTest {
assertEquals(position.y, -1000) assertEquals(position.y, -1000)
} }
@Test
fun `correct negative y large`() {
val position = BlockPosition(-2048, 0xF, 0xF)
assertEquals(position.x, -2048)
}
@Test @Test
fun `correct positive y`() { fun `correct positive y`() {
val position = BlockPosition(0xF, 1000, 0xF) val position = BlockPosition(0xF, 1000, 0xF)
assertEquals(position.y, 1000) assertEquals(position.y, 1000)
} }
@Test
fun `correct positive y large`() {
val position = BlockPosition(0xF, 2047, 0xF)
assertEquals(position.y, 2047)
}
@Test @Test
fun `correct plus y`() { fun `correct plus y`() {
val position = BlockPosition(0xF, 2, 0xF) val position = BlockPosition(0xF, 2, 0xF)
@ -100,12 +124,25 @@ class BlockPositionTest {
assertEquals(position.z, 4) assertEquals(position.z, 4)
} }
@Test
fun `correct positive z large`() {
val position = BlockPosition(0, 0, 29_999_999)
assertEquals(position.z, 29_999_999)
}
@Test @Test
fun `correct negative z`() { fun `correct negative z`() {
val position = BlockPosition(0xF, 0xF, -4) val position = BlockPosition(0xF, 0xF, -4)
assertEquals(position.z, -4) assertEquals(position.z, -4)
} }
@Test
fun `correct negative z large`() {
val position = BlockPosition(0, 0, -29_999_999)
assertEquals(position.z, -29_999_999)
}
@Test @Test
fun `correct plus z`() { fun `correct plus z`() {
val position = BlockPosition(0xF, 0xF, 2) val position = BlockPosition(0xF, 0xF, 2)

View File

@ -37,9 +37,4 @@ class BlockPositionUtilTest {
fun hash4() { fun hash4() {
assertEquals(10888876138951, BlockPosition(123, -456, 789).hash) assertEquals(10888876138951, BlockPosition(123, -456, 789).hash)
} }
@Test
fun hash5() {
assertEquals(65198192324831, BlockPosition(5473628, 123123, 1234737534).hash)
}
} }

View File

@ -40,12 +40,24 @@ class ChunkPositionTest {
assertEquals(position.x, 2) assertEquals(position.x, 2)
} }
@Test
fun `correct positive x large`() {
val position = ChunkPosition(1875000, 1875000)
assertEquals(position.x, 1875000)
}
@Test @Test
fun `correct negative x`() { fun `correct negative x`() {
val position = ChunkPosition(-2, 0xF) val position = ChunkPosition(-2, 0xF)
assertEquals(position.x, -2) assertEquals(position.x, -2)
} }
@Test
fun `correct negative x large`() {
val position = ChunkPosition(-1875000, -1875000)
assertEquals(position.x, -1875000)
}
@Test @Test
fun `correct plus x`() { fun `correct plus x`() {
val position = ChunkPosition(2, 0xF) val position = ChunkPosition(2, 0xF)
@ -70,12 +82,24 @@ class ChunkPositionTest {
assertEquals(position.z, 4) assertEquals(position.z, 4)
} }
@Test
fun `correct positive z large`() {
val position = ChunkPosition(1875000, 1875000)
assertEquals(position.z, 1875000)
}
@Test @Test
fun `correct negative z`() { fun `correct negative z`() {
val position = ChunkPosition(0xF, -4) val position = ChunkPosition(0xF, -4)
assertEquals(position.z, -4) assertEquals(position.z, -4)
} }
@Test
fun `correct negative z large`() {
val position = ChunkPosition(-1875000, -1875000)
assertEquals(position.z, -1875000)
}
@Test @Test
fun `correct plus z`() { fun `correct plus z`() {
val position = ChunkPosition(0xF, 2) val position = ChunkPosition(0xF, 2)