fix: Fixed reverse chunk indexing algorithm

This commit is contained in:
Nicholas Novak 2023-11-28 14:47:22 -08:00
parent 134e9b62b0
commit 9aa5e65c6c
3 changed files with 69 additions and 6 deletions

View File

@ -16,10 +16,13 @@ func (cd *ChunkData) SectionFor(pos BlockPos) *ChunkSection {
}
func (cd *ChunkData) IndexToBlockPos(index int) BlockPos {
posX := index % 16
posZ := ((index - posX) % 256) / 16
posY := ((index - posZ) % 4096) / 256
return BlockPos{
X: index%16 + cd.Pos.X,
Y: uint(index % sliceSize),
Z: index%32 + cd.Pos.Z,
X: posX + cd.Pos.X,
Y: uint(posY),
Z: posZ + cd.Pos.Z,
}
}

View File

@ -16,6 +16,10 @@ type BlockPos struct {
Z int `json:"z"`
}
func (b BlockPos) String() string {
return fmt.Sprintf("BlockPos { X: %v, Y: %v, Z: %v }", b.X, b.Y, b.Z)
}
func RandomBlockPosWithRange(maxRange float64) BlockPos {
return BlockPos{
X: int(rand.NormFloat64() * maxRange),
@ -54,7 +58,7 @@ func rem_euclid(a, b int) int {
return (a%b + b) % b
}
func (cs *ChunkSection) IndexOfBlock(pos BlockPos) int {
func IndexOfBlock(pos BlockPos) int {
baseX := rem_euclid(pos.X, 16)
baseY := rem_euclid(int(pos.Y), 16)
baseZ := rem_euclid(pos.Z, 16)
@ -69,11 +73,11 @@ func (cs *ChunkSection) UpdateBlockAtIndex(index int, targetState BlockID) {
}
func (cs *ChunkSection) UpdateBlock(pos BlockPos, targetState BlockID) {
cs.BlockStates[cs.IndexOfBlock(pos)] = targetState
cs.BlockStates[IndexOfBlock(pos)] = targetState
}
func (cs *ChunkSection) FetchBlock(pos BlockPos) BlockID {
return cs.BlockStates[cs.IndexOfBlock(pos)]
return cs.BlockStates[IndexOfBlock(pos)]
}
type BlockID uint8

56
world/indexing_test.go Normal file
View File

@ -0,0 +1,56 @@
package world
import (
"testing"
)
func TestUniqueDataPoints(t *testing.T) {
points := make(map[int]bool)
for x := 0; x < 16; x++ {
for y := 0; y < 16; y++ {
for z := 0; z < 16; z++ {
pos := BlockPos{
X: x,
Y: uint(y),
Z: z,
}
points[IndexOfBlock(pos)] = true
}
}
}
if len(points) != 4096 {
t.Fatalf("Expected %d unique points, got %d", 4096, len(points))
}
}
func TestCorrectIndexReversal(t *testing.T) {
points := make(map[int]BlockPos)
for x := 0; x < 16; x++ {
for y := 0; y < 16; y++ {
for z := 0; z < 16; z++ {
pos := BlockPos{
X: x,
Y: uint(y),
Z: z,
}
points[IndexOfBlock(pos)] = pos
}
}
}
var chunk ChunkData
for index, blockPos := range points {
testBlock := chunk.IndexToBlockPos(index)
if testBlock != blockPos {
t.Fatalf("Expected block %v, got %v", blockPos, testBlock)
}
}
}