diff --git a/world/chunk_data.go b/world/chunk_data.go index a9d4915..9c66512 100644 --- a/world/chunk_data.go +++ b/world/chunk_data.go @@ -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, } } diff --git a/world/data_format.go b/world/data_format.go index 9b4c5e7..a25f449 100644 --- a/world/data_format.go +++ b/world/data_format.go @@ -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 diff --git a/world/indexing_test.go b/world/indexing_test.go new file mode 100644 index 0000000..b340dac --- /dev/null +++ b/world/indexing_test.go @@ -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) + } + } +}