refactor shit
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
package level
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
|
||||
"github.com/admin-else/strom/data"
|
||||
"github.com/admin-else/strom/util"
|
||||
)
|
||||
|
||||
type ChunkBuilder struct {
|
||||
Biomes, Blocks [][]int32
|
||||
Bottom, Top int32
|
||||
Version string
|
||||
}
|
||||
|
||||
func NewChunkBuilder(bottom, top int32, version string) *ChunkBuilder {
|
||||
return &ChunkBuilder{Bottom: bottom, Top: top, Version: version}
|
||||
}
|
||||
|
||||
func NewOverworldChunkBuilder(version string) *ChunkBuilder {
|
||||
return NewChunkBuilder(-64, 320, version)
|
||||
}
|
||||
|
||||
func (cb *ChunkBuilder) ColumnHeight() int32 {
|
||||
absBottom := cb.Bottom
|
||||
if absBottom < 0 {
|
||||
absBottom *= -1
|
||||
}
|
||||
return absBottom + cb.Top
|
||||
}
|
||||
|
||||
func (cb *ChunkBuilder) FillAllById(block, biome int32) {
|
||||
numSections := cb.ColumnHeight() / ChunkWidth
|
||||
blockSection := util.MakeSingleValuedSlice(block, BlocksPerChunkSection)
|
||||
biomeSection := util.MakeSingleValuedSlice(biome, BiomesPerChunkSection)
|
||||
cb.Blocks = make([][]int32, numSections)
|
||||
cb.Biomes = make([][]int32, numSections)
|
||||
for i := range cb.Blocks {
|
||||
|
||||
// Otherwise setting one block will set it also in all other sections because the slice is the same
|
||||
var blocks = make([]int32, BlocksPerChunkSection)
|
||||
copy(blocks, blockSection)
|
||||
|
||||
var biomes = make([]int32, BiomesPerChunkSection)
|
||||
copy(biomes, biomeSection)
|
||||
|
||||
cb.Blocks[i] = blocks
|
||||
cb.Biomes[i] = biomes
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (cb *ChunkBuilder) FillAll(biome, block string) (err error) {
|
||||
blockData, ok := data.LookupBlockByName(cb.Version, block)
|
||||
if !ok {
|
||||
err = data.UnknownBlockNameErr
|
||||
return
|
||||
}
|
||||
biomeData, ok := data.LookupBiomeByName(cb.Version, biome)
|
||||
if !ok {
|
||||
err = data.UnknownBiomeNameErr
|
||||
return
|
||||
}
|
||||
cb.FillAllById(blockData.DefaultState, biomeData.Id)
|
||||
return
|
||||
}
|
||||
|
||||
var InvalidChunkPositionErr = errors.New("invalid chunk position")
|
||||
|
||||
func (cb *ChunkBuilder) SetBlockId(x, y, z, id int32) (err error) {
|
||||
if x < 0 || x >= ChunkWidth || z < 0 || z >= ChunkWidth || y < cb.Bottom || y >= cb.Top {
|
||||
err = InvalidChunkPositionErr
|
||||
return
|
||||
}
|
||||
|
||||
y += cb.Bottom * -1
|
||||
section := util.FloorDiv(y, ChunkWidth)
|
||||
i := (y%ChunkWidth)*ChunkWidth*ChunkWidth + z*ChunkWidth + x
|
||||
cb.Blocks[section][i] = id
|
||||
return
|
||||
}
|
||||
|
||||
func (cb *ChunkBuilder) SetBlock(x, y, z int32, block string) (err error) {
|
||||
blockData, ok := data.LookupBlockByName(cb.Version, block)
|
||||
if !ok {
|
||||
err = data.UnknownBlockNameErr
|
||||
return
|
||||
}
|
||||
return cb.SetBlockId(x, y, z, blockData.DefaultState)
|
||||
}
|
||||
|
||||
func (cb *ChunkBuilder) Build() (data []byte, err error) {
|
||||
b := bytes.NewBuffer(nil)
|
||||
err = PackSections(cb.Blocks, cb.Biomes, cb.Version, b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
data = b.Bytes()
|
||||
return
|
||||
}
|
||||
+12
-12
@@ -6,7 +6,7 @@ import (
|
||||
"slices"
|
||||
)
|
||||
|
||||
type RealStorageFormat struct {
|
||||
type StorageFormat struct {
|
||||
AvailableBpes []uint8
|
||||
BiggestDirect bool
|
||||
Len int32
|
||||
@@ -21,7 +21,7 @@ var RealInvalidPaletteIndexErr = errors.New("invalid palette index")
|
||||
var AvailableBpeMustBeSortedErr = errors.New("available bpe must be sorted")
|
||||
var DirectModeCantResizeErr = errors.New("direct mode cannot resize")
|
||||
|
||||
func (r RealStorageFormat) Import(data []uint64, bpe uint8, palette []int32) (s *RealStorage, err error) {
|
||||
func (r StorageFormat) Import(data []uint64, bpe uint8, palette []int32) (s *Storage, err error) {
|
||||
if !slices.IsSorted(r.AvailableBpes) {
|
||||
err = AvailableBpeMustBeSortedErr
|
||||
return
|
||||
@@ -31,7 +31,7 @@ func (r RealStorageFormat) Import(data []uint64, bpe uint8, palette []int32) (s
|
||||
err = BpeNotAvailableErr
|
||||
return
|
||||
}
|
||||
s = new(RealStorage)
|
||||
s = new(Storage)
|
||||
s.format = r
|
||||
s.resize(bpe)
|
||||
if bpe == 0 && len(palette) != 1 {
|
||||
@@ -45,7 +45,7 @@ func (r RealStorageFormat) Import(data []uint64, bpe uint8, palette []int32) (s
|
||||
return
|
||||
}
|
||||
|
||||
func (r RealStorageFormat) ImportDataDirect(data []uint64) (s *RealStorage, err error) {
|
||||
func (r StorageFormat) ImportDataDirect(data []uint64) (s *Storage, err error) {
|
||||
if len(r.AvailableBpes) != 1 {
|
||||
err = AvailableBpeMustBeLenOneErr
|
||||
return
|
||||
@@ -53,8 +53,8 @@ func (r RealStorageFormat) ImportDataDirect(data []uint64) (s *RealStorage, err
|
||||
return r.Import(data, r.AvailableBpes[0], nil)
|
||||
}
|
||||
|
||||
type RealStorage struct {
|
||||
format RealStorageFormat
|
||||
type Storage struct {
|
||||
format StorageFormat
|
||||
data []uint64
|
||||
bpe uint8
|
||||
palette []int32
|
||||
@@ -64,7 +64,7 @@ type RealStorage struct {
|
||||
mask uint64
|
||||
}
|
||||
|
||||
func (r *RealStorage) doWeResizeDirect(bpe uint8) bool {
|
||||
func (r *Storage) doWeResizeDirect(bpe uint8) bool {
|
||||
if !r.format.BiggestDirect || r.format.AvailableBpes == nil {
|
||||
return false
|
||||
}
|
||||
@@ -72,7 +72,7 @@ func (r *RealStorage) doWeResizeDirect(bpe uint8) bool {
|
||||
}
|
||||
|
||||
// only resizes upwards
|
||||
func (r *RealStorage) resize(bpe uint8) {
|
||||
func (r *Storage) resize(bpe uint8) {
|
||||
if bpe == 0 {
|
||||
r.data = nil
|
||||
r.bpe = 0
|
||||
@@ -116,7 +116,7 @@ func (r *RealStorage) resize(bpe uint8) {
|
||||
return
|
||||
}
|
||||
|
||||
func (r *RealStorage) Get(i int32) (s int32, err error) {
|
||||
func (r *Storage) Get(i int32) (s int32, err error) {
|
||||
if i < 0 || i >= r.format.Len {
|
||||
err = OutOfBoundsErr
|
||||
return
|
||||
@@ -144,12 +144,12 @@ func (r *RealStorage) Get(i int32) (s int32, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (r *RealStorage) set(i int32, v int32) {
|
||||
func (r *Storage) set(i int32, v int32) {
|
||||
shift := (i % r.elementsPerLong) * int32(r.bpe)
|
||||
r.data[i/r.elementsPerLong] = (r.data[i/r.elementsPerLong] & ^(r.mask << shift)) | (uint64(v) << shift)
|
||||
}
|
||||
|
||||
func (r *RealStorage) Set(i int32, v int32) (err error) {
|
||||
func (r *Storage) Set(i int32, v int32) (err error) {
|
||||
if i < 0 || i >= r.format.Len {
|
||||
err = OutOfBoundsErr
|
||||
return
|
||||
@@ -165,7 +165,7 @@ func (r *RealStorage) Set(i int32, v int32) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (r *RealStorage) appendPalette(v int32) (i int, err error) {
|
||||
func (r *Storage) appendPalette(v int32) (i int, err error) {
|
||||
i = len(r.palette)
|
||||
if r.palette == nil {
|
||||
err = DirectModeCantResizeErr
|
||||
|
||||
+36
-36
@@ -6,23 +6,23 @@ import (
|
||||
"github.com/admin-else/strom/level"
|
||||
)
|
||||
|
||||
func heightmapFormat() level.RealStorageFormat {
|
||||
return level.RealStorageFormat{
|
||||
func heightmapFormat() level.StorageFormat {
|
||||
return level.StorageFormat{
|
||||
AvailableBpes: []uint8{9},
|
||||
BiggestDirect: true,
|
||||
Len: 256,
|
||||
}
|
||||
}
|
||||
|
||||
func blockStorageFormat() level.RealStorageFormat {
|
||||
return level.RealStorageFormat{
|
||||
func blockStorageFormat() level.StorageFormat {
|
||||
return level.StorageFormat{
|
||||
AvailableBpes: []uint8{0, 4, 5, 6, 7, 8, 15},
|
||||
BiggestDirect: true,
|
||||
Len: 4096,
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageImportDataDirect(t *testing.T) {
|
||||
func TestStorageImportDataDirect(t *testing.T) {
|
||||
format := heightmapFormat()
|
||||
data := make([]uint64, 256)
|
||||
data[0] = 42
|
||||
@@ -41,8 +41,8 @@ func TestRealStorageImportDataDirect(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageImportDataDirectMultipleBpe(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageImportDataDirectMultipleBpe(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{4, 8},
|
||||
BiggestDirect: true,
|
||||
Len: 256,
|
||||
@@ -54,8 +54,8 @@ func TestRealStorageImportDataDirectMultipleBpe(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageImportUnsortedBpe(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageImportUnsortedBpe(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{9, 4},
|
||||
BiggestDirect: true,
|
||||
Len: 256,
|
||||
@@ -67,7 +67,7 @@ func TestRealStorageImportUnsortedBpe(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageImportBpeNotAvailable(t *testing.T) {
|
||||
func TestStorageImportBpeNotAvailable(t *testing.T) {
|
||||
format := heightmapFormat()
|
||||
|
||||
_, err := format.Import([]uint64{1}, 4, nil)
|
||||
@@ -76,7 +76,7 @@ func TestRealStorageImportBpeNotAvailable(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageGetSet(t *testing.T) {
|
||||
func TestStorageGetSet(t *testing.T) {
|
||||
format := blockStorageFormat()
|
||||
s, err := format.Import(nil, 4, []int32{0, 1, 2, 3})
|
||||
if err != nil {
|
||||
@@ -98,7 +98,7 @@ func TestRealStorageGetSet(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageOutOfBounds(t *testing.T) {
|
||||
func TestStorageOutOfBounds(t *testing.T) {
|
||||
format := blockStorageFormat()
|
||||
s, err := format.Import(nil, 4, []int32{0, 1})
|
||||
if err != nil {
|
||||
@@ -116,8 +116,8 @@ func TestRealStorageOutOfBounds(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageBpeZero(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageBpeZero(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{0, 4, 8},
|
||||
BiggestDirect: true,
|
||||
Len: 64,
|
||||
@@ -139,8 +139,8 @@ func TestRealStorageBpeZero(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageBpeZeroPaletteLen(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageBpeZeroPaletteLen(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{0, 4, 8},
|
||||
BiggestDirect: true,
|
||||
Len: 64,
|
||||
@@ -152,8 +152,8 @@ func TestRealStorageBpeZeroPaletteLen(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageResize(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageResize(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{4, 8},
|
||||
BiggestDirect: false,
|
||||
Len: 16,
|
||||
@@ -179,8 +179,8 @@ func TestRealStorageResize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageResizePreservesData(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageResizePreservesData(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{4, 5, 6, 8},
|
||||
BiggestDirect: false,
|
||||
Len: 8,
|
||||
@@ -207,8 +207,8 @@ func TestRealStorageResizePreservesData(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStoragePaletteGrowth(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStoragePaletteGrowth(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{4, 5, 6, 8},
|
||||
BiggestDirect: false,
|
||||
Len: 16,
|
||||
@@ -239,8 +239,8 @@ func TestRealStoragePaletteGrowth(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageNoAvailableBpe(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageNoAvailableBpe(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{4},
|
||||
BiggestDirect: false,
|
||||
Len: 16,
|
||||
@@ -257,8 +257,8 @@ func TestRealStorageNoAvailableBpe(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageBiggestDirect(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageBiggestDirect(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{4, 8},
|
||||
BiggestDirect: true,
|
||||
Len: 64,
|
||||
@@ -284,8 +284,8 @@ func TestRealStorageBiggestDirect(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageDirectModeNoPalette(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageDirectModeNoPalette(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{9},
|
||||
BiggestDirect: true,
|
||||
Len: 256,
|
||||
@@ -308,8 +308,8 @@ func TestRealStorageDirectModeNoPalette(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageInvalidPaletteIndex(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageInvalidPaletteIndex(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{4, 8},
|
||||
BiggestDirect: false,
|
||||
Len: 16,
|
||||
@@ -327,7 +327,7 @@ func TestRealStorageInvalidPaletteIndex(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageOverwrite(t *testing.T) {
|
||||
func TestStorageOverwrite(t *testing.T) {
|
||||
format := blockStorageFormat()
|
||||
s, err := format.Import(nil, 4, []int32{0, 1, 2})
|
||||
if err != nil {
|
||||
@@ -347,7 +347,7 @@ func TestRealStorageOverwrite(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageSetOutOfBounds(t *testing.T) {
|
||||
func TestStorageSetOutOfBounds(t *testing.T) {
|
||||
format := blockStorageFormat()
|
||||
s, err := format.Import(nil, 4, []int32{0, 1})
|
||||
if err != nil {
|
||||
@@ -365,8 +365,8 @@ func TestRealStorageSetOutOfBounds(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageGetAfterResize(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageGetAfterResize(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{4, 5, 6, 8},
|
||||
BiggestDirect: false,
|
||||
Len: 32,
|
||||
@@ -392,8 +392,8 @@ func TestRealStorageGetAfterResize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRealStorageResizeDirect(t *testing.T) {
|
||||
format := level.RealStorageFormat{
|
||||
func TestStorageResizeDirect(t *testing.T) {
|
||||
format := level.StorageFormat{
|
||||
AvailableBpes: []uint8{4, 8},
|
||||
BiggestDirect: true,
|
||||
Len: 64,
|
||||
|
||||
@@ -1,219 +0,0 @@
|
||||
package level
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type DynamicPalletLookup[T comparable] interface {
|
||||
GetIndex(T) uint32
|
||||
GetT(uint33 uint32) T
|
||||
Resize(storage *Storage[T]) error
|
||||
}
|
||||
|
||||
type Storage[T comparable] struct {
|
||||
Palette []T
|
||||
CustomPallet DynamicPalletLookup[T]
|
||||
Data []uint64
|
||||
PossibleBitsPerEntryValues []uint8 // These should be sorted
|
||||
BitsPerEntry uint8
|
||||
Len int
|
||||
MaxAtCurrentBpe int
|
||||
ElementsPerLong int
|
||||
Mask uint64
|
||||
}
|
||||
|
||||
var CannotGrowPalletErr = errors.New("cannot grow pallet")
|
||||
var CannotGrowPalletNoPossibleBpeErr = errors.New("cannot grow pallet, no possible bpe provided")
|
||||
var Bpe0ButNot1LenPaletteErr = errors.New("bpe 0 but not 1, len palette")
|
||||
var InvalidPaletteIndexErr = errors.New("invalid palette index")
|
||||
|
||||
func NewStorage[T comparable](len int, possibleBpe []uint8) (s *Storage[T]) {
|
||||
s = new(Storage[T])
|
||||
s.Len = len
|
||||
s.PossibleBitsPerEntryValues = possibleBpe
|
||||
s.Resize(possibleBpe[0])
|
||||
return
|
||||
}
|
||||
|
||||
func ImportStorage[T comparable](data []uint64, bpe uint8, palette []T, len int, possibleBpe []uint8) (s *Storage[T], err error) {
|
||||
s = new(Storage[T])
|
||||
s.Resize(bpe)
|
||||
s.Data = data
|
||||
s.Palette = palette
|
||||
s.Len = len
|
||||
s.PossibleBitsPerEntryValues = possibleBpe
|
||||
err = s.CheckData()
|
||||
return
|
||||
}
|
||||
|
||||
func ImportStoragePaletteFunc[T comparable](data []uint64, bpe uint8, paletteF DynamicPalletLookup[T], len int, possibleBpe []uint8) (s *Storage[T], err error) {
|
||||
s = new(Storage[T])
|
||||
s.Resize(bpe)
|
||||
s.Data = data
|
||||
s.CustomPallet = paletteF
|
||||
s.Len = len
|
||||
s.PossibleBitsPerEntryValues = possibleBpe
|
||||
err = s.CheckData()
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Storage[T]) CheckData() (err error) {
|
||||
if s.BitsPerEntry == 0 && len(s.Palette) != 1 {
|
||||
err = Bpe0ButNot1LenPaletteErr
|
||||
return
|
||||
}
|
||||
for i := range s.Len {
|
||||
if s.GetLow(i) >= uint32(len(s.Palette)) {
|
||||
err = InvalidPaletteIndexErr
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Storage[T]) Resize(bpe uint8) {
|
||||
if bpe == 0 {
|
||||
s.Data = nil
|
||||
s.BitsPerEntry = 0
|
||||
s.ElementsPerLong = 0
|
||||
s.Mask = 0
|
||||
s.MaxAtCurrentBpe = 1
|
||||
return
|
||||
}
|
||||
elementsPerLong := int(64 / int(bpe))
|
||||
numberOfLongs := int(math.Ceil(float64(s.Len) / float64(elementsPerLong)))
|
||||
newData := make([]uint64, numberOfLongs)
|
||||
if s.BitsPerEntry == 0 {
|
||||
s.Data = newData
|
||||
s.BitsPerEntry = bpe
|
||||
s.ElementsPerLong = elementsPerLong
|
||||
s.Mask = (uint64(1) << uint32(bpe)) - 1
|
||||
s.MaxAtCurrentBpe = 1 << s.BitsPerEntry
|
||||
return
|
||||
}
|
||||
for i := range s.Len {
|
||||
v := s.GetLow(i)
|
||||
newData[i/elementsPerLong] |= uint64(v) << ((i % elementsPerLong) * int(bpe))
|
||||
}
|
||||
s.Data = newData
|
||||
s.BitsPerEntry = bpe
|
||||
s.ElementsPerLong = elementsPerLong
|
||||
s.Mask = (uint64(1) << uint32(bpe)) - 1
|
||||
s.MaxAtCurrentBpe = 1 << s.BitsPerEntry
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Storage[T]) GrowPallet(v T) (index int, err error) {
|
||||
index = len(s.Palette)
|
||||
if index+1 > s.MaxAtCurrentBpe {
|
||||
if s.PossibleBitsPerEntryValues == nil {
|
||||
err = CannotGrowPalletNoPossibleBpeErr
|
||||
return
|
||||
}
|
||||
|
||||
bpei := slices.Index(s.PossibleBitsPerEntryValues, s.BitsPerEntry)
|
||||
if bpei == len(s.PossibleBitsPerEntryValues)-1 {
|
||||
err = CannotGrowPalletErr
|
||||
return
|
||||
}
|
||||
newBpe := s.PossibleBitsPerEntryValues[bpei+1]
|
||||
s.Resize(newBpe)
|
||||
}
|
||||
s.Palette = append(s.Palette, v)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Storage[T]) Set(i int, v T) (err error) {
|
||||
pi := slices.Index(s.Palette, v)
|
||||
if pi != -1 {
|
||||
if s.BitsPerEntry == 0 {
|
||||
return
|
||||
}
|
||||
s.SetLow(i, uint32(pi))
|
||||
return
|
||||
}
|
||||
pi, err = s.GrowPallet(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.SetLow(i, uint32(pi))
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Storage[T]) Get(i int) (v T) {
|
||||
if s.BitsPerEntry == 0 {
|
||||
return s.Palette[0]
|
||||
}
|
||||
return s.Palette[s.GetLow(i)]
|
||||
}
|
||||
|
||||
func (s *Storage[T]) GetLow(i int) (j uint32) {
|
||||
j = uint32((s.Data[i/s.ElementsPerLong] >> ((i % s.ElementsPerLong) * int(s.BitsPerEntry))) & s.Mask)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Storage[T]) SetLow(i int, v uint32) {
|
||||
s.Data[i/s.ElementsPerLong] &= ^(s.Mask << ((i % s.ElementsPerLong) * int(s.BitsPerEntry)))
|
||||
s.Data[i/s.ElementsPerLong] |= uint64(v) << ((i % s.ElementsPerLong) * int(s.BitsPerEntry))
|
||||
}
|
||||
|
||||
func (s *Storage[T]) RealValues() []T {
|
||||
ret := make([]T, s.Len)
|
||||
for i := range s.Len {
|
||||
ret[i] = s.Get(i)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (s *Storage[T]) SetMany(i, j int, v T) (err error) {
|
||||
if i == 0 && j == s.Len-1 && slices.Contains(s.PossibleBitsPerEntryValues, 0) {
|
||||
s.Resize(0)
|
||||
s.Palette = []T{v}
|
||||
return
|
||||
}
|
||||
pi := slices.Index(s.Palette, v)
|
||||
if pi != -1 {
|
||||
if s.BitsPerEntry == 0 {
|
||||
return
|
||||
}
|
||||
s.SetLow(i, uint32(pi))
|
||||
return
|
||||
}
|
||||
pi, err = s.GrowPallet(v)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.SetManyLow(i, j, uint32(pi))
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Storage[T]) SetManyLow(i, j int, v uint32) {
|
||||
n := j - i
|
||||
if n > s.ElementsPerLong*2 {
|
||||
for k := i; k < j; k++ {
|
||||
s.SetLow(k, v)
|
||||
}
|
||||
return
|
||||
}
|
||||
for i%s.ElementsPerLong == 0 {
|
||||
s.SetLow(i, v)
|
||||
i++
|
||||
}
|
||||
|
||||
var vFilled uint64
|
||||
for k := range s.ElementsPerLong {
|
||||
vFilled |= uint64(v) << (k * int(s.BitsPerEntry))
|
||||
}
|
||||
|
||||
t := i / s.ElementsPerLong
|
||||
for k := range (j - i) / s.ElementsPerLong {
|
||||
s.Data[t+k] = vFilled
|
||||
}
|
||||
|
||||
for j%s.ElementsPerLong != 0 {
|
||||
s.SetLow(j, v)
|
||||
j--
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package level
|
||||
|
||||
// This is the func to generate a block storage or whatever like block storagw would be
|
||||
// Len=4096
|
||||
// DynamicResolver=dynamicblockresolver1.21.11
|
||||
// PossibleBpes=0, 4, 5, 6,7, 8, 9, 15
|
||||
// T=*BlockState
|
||||
func NewStorageFormat() {
|
||||
|
||||
}
|
||||
|
||||
// StorageFormat.ImportLongArrays(bpe, r) -> *Storage
|
||||
// StorageFormat.ImportReaderReader(bpe, r) -> *Storage
|
||||
@@ -1,186 +0,0 @@
|
||||
package level_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/admin-else/strom/level"
|
||||
"github.com/admin-else/strom/util"
|
||||
)
|
||||
|
||||
var possibleBpe = []uint8{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
|
||||
|
||||
func FuzzStorage(f *testing.F) {
|
||||
f.Add([]byte{4, 0, 1})
|
||||
f.Add([]byte{4, 0, 1, 0, 2, 0, 1})
|
||||
f.Add([]byte{8, 0, 10, 1, 20, 2, 30, 3, 40, 4, 50})
|
||||
f.Add([]byte{4, 0, 5, 1, 10, 2, 15, 3, 20, 0, 25})
|
||||
f.Add([]byte{2, 0, 1, 1, 2, 0, 3, 1, 4})
|
||||
f.Add([]byte{8, 0, 42, 1, 42, 2, 42, 3, 42})
|
||||
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
if len(data) < 1 {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
length := int(data[0])%64 + 1
|
||||
s := level.NewStorage[int32](length, possibleBpe)
|
||||
|
||||
ref := make([]int32, length)
|
||||
refSet := make([]bool, length)
|
||||
|
||||
for i := 1; i+1 < len(data); i += 2 {
|
||||
idx := int(data[i]) % length
|
||||
val := int32(data[i+1])
|
||||
|
||||
err := s.Set(idx, val)
|
||||
if err == level.CannotGrowPalletErr {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
ref[idx] = val
|
||||
refSet[idx] = true
|
||||
}
|
||||
|
||||
for i := range length {
|
||||
if !refSet[i] {
|
||||
continue
|
||||
}
|
||||
got := s.Get(i)
|
||||
if got != ref[i] {
|
||||
t.Errorf("Get(%d) = %d, want %d", i, got, ref[i])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetOverwrite(t *testing.T) {
|
||||
s := level.NewStorage[int32](8, []uint8{2, 4})
|
||||
|
||||
s.Set(0, 1)
|
||||
s.Set(0, 2)
|
||||
s.Set(0, 1)
|
||||
|
||||
got := s.Get(0)
|
||||
if got != 1 {
|
||||
t.Errorf("Get(0) = %d, want 1 (|= does not clear old bits)", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResizePreservesData(t *testing.T) {
|
||||
s := level.NewStorage[int32](8, []uint8{2, 4})
|
||||
|
||||
s.Set(0, 10)
|
||||
s.Set(1, 20)
|
||||
s.Set(2, 30)
|
||||
s.Set(3, 40)
|
||||
s.Set(4, 50)
|
||||
|
||||
for i, want := range []int32{10, 20, 30, 40} {
|
||||
got := s.Get(i)
|
||||
if got != want {
|
||||
t.Errorf("Get(%d) = %d, want %d (resize repacks with old BPE)", i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBpeZeroSingleValue(t *testing.T) {
|
||||
s := level.NewStorage[int32](64, possibleBpe)
|
||||
s.Palette = append(s.Palette, 42)
|
||||
|
||||
for i := range 64 {
|
||||
if s.Get(i) != 42 {
|
||||
t.Errorf("Get(%d) = %d, want 42 (BPE 0 should always return first palette entry)", i, s.Get(i))
|
||||
}
|
||||
}
|
||||
|
||||
s.Set(30, 42)
|
||||
s.Set(0, 42)
|
||||
|
||||
for i := range 64 {
|
||||
if s.Get(i) != 42 {
|
||||
t.Errorf("Get(%d) = %d, want 42 after Set same value", i, s.Get(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBpeZeroGrowPallet(t *testing.T) {
|
||||
s := level.NewStorage[int32](64, possibleBpe)
|
||||
s.Palette = append(s.Palette, 10)
|
||||
|
||||
s.Set(0, 10)
|
||||
s.Set(1, 20)
|
||||
|
||||
if s.Get(0) != 10 {
|
||||
t.Errorf("Get(0) = %d, want 10 after grow from BPE 0", s.Get(0))
|
||||
}
|
||||
if s.Get(1) != 20 {
|
||||
t.Errorf("Get(1) = %d, want 20 after grow from BPE 0", s.Get(1))
|
||||
}
|
||||
}
|
||||
|
||||
func TestResizeElementsPerLong(t *testing.T) {
|
||||
s := level.NewStorage[int32](8, []uint8{2, 4})
|
||||
|
||||
s.Set(0, 10)
|
||||
s.Set(1, 20)
|
||||
s.Set(2, 30)
|
||||
s.Set(3, 40)
|
||||
s.Set(4, 50)
|
||||
|
||||
if s.ElementsPerLong != 16 {
|
||||
t.Errorf("ElementsPerLong = %d, want 16 (resize stores old ElementsPerLong)", s.ElementsPerLong)
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportData(t *testing.T) {
|
||||
data := []uint64{
|
||||
2924043581155788451,
|
||||
3014291839833165474,
|
||||
2924008396783439527,
|
||||
3014291770978157730,
|
||||
2905993930227668138,
|
||||
2978157076574191776,
|
||||
2888296810347582631,
|
||||
2941952219986869920,
|
||||
3122589749976320164,
|
||||
2833795322612367018,
|
||||
3086525630071259805,
|
||||
2833830575707083949,
|
||||
3014115504847927964,
|
||||
2851845594302469291,
|
||||
2905958400778123933,
|
||||
3014291839833162913,
|
||||
2815745670742620830,
|
||||
2942057979530264736,
|
||||
2815745670876841123,
|
||||
2887944277684467868,
|
||||
2815745740402934945,
|
||||
2887944277549201564,
|
||||
3032094718851891360,
|
||||
2887908817896552616,
|
||||
2887944277684469920,
|
||||
2869788867884569248,
|
||||
2869894626083422368,
|
||||
2834183176950988960,
|
||||
2869894625949204127,
|
||||
3032376331669946015,
|
||||
2869894694802636456,
|
||||
2996136153003671199,
|
||||
2869929879174992040,
|
||||
2869894625948941983,
|
||||
2887944277684735139,
|
||||
2869894625948941983,
|
||||
22322953887,
|
||||
}
|
||||
n := int32(384 + 1)
|
||||
bpe := util.BpeByNum(float64(n)) // overworld world height
|
||||
s, err := level.ImportStorage[int32](data, bpe, util.SliceRange(0, n), level.ChunkColumns, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fmt.Println(s.RealValues())
|
||||
}
|
||||
Reference in New Issue
Block a user