From 378b78312e6d0f2be5728d023a289d68eac88685 Mon Sep 17 00:00:00 2001 From: adman Date: Sat, 25 Apr 2026 18:00:10 +0200 Subject: [PATCH] =?UTF-8?q?storage=3D=3F=3F=3F=3F=3F?= --- data/registry.go | 2 ++ level/chunk.go | 54 +++++++++++++++++++++++++++++++++++ level/packet.go | 7 ----- level/storage.go | 73 ++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 level/chunk.go diff --git a/data/registry.go b/data/registry.go index 5348690..32035d9 100644 --- a/data/registry.go +++ b/data/registry.go @@ -6,6 +6,8 @@ import ( "github.com/admin-else/strom/nbt" ) +// TODO: this is stupid loginPacket.json exists next version migrate to that + //go:embed registry/* var Registry embed.FS diff --git a/level/chunk.go b/level/chunk.go new file mode 100644 index 0000000..1e891de --- /dev/null +++ b/level/chunk.go @@ -0,0 +1,54 @@ +package level + +import ( + "encoding/binary" + "io" + "math" + + "github.com/admin-else/strom/data" + "github.com/admin-else/strom/util" +) + +type BlockState struct { + Id string + Properties map[string]string +} + +const ( + ChunkWidth = 16 + ChunkColumns = ChunkWidth * ChunkWidth + BlocksPerChunkSection = ChunkWidth * ChunkWidth * ChunkWidth + ChunkBiomesWidth = 4 + BiomesPerChunkSection = ChunkBiomesWidth * ChunkBiomesWidth * ChunkBiomesWidth +) + +type Section struct { + Blocks *Storage[*BlockState] + Biomes *Storage[string] +} + +func PossibleBpesBlocks(version string) (ret []uint8) { + maxBpe := util.BpeByNum(float64(len(data.BlocksForVersion(version)))) + ret = []uint8{0, 4, 5, 6, 7, 8, maxBpe} + return +} + +func PossibleBpesBiomes(version string) (ret []uint8) { + maxBpe := uint8(math.Ceil(math.Log2(float64(len(data.BiomesForVersion(version)))))) + ret = []uint8{0, 1, 2, 3, maxBpe} + return +} + +func SectionFromPacket(r io.Reader, version string) (s *Section, err error) { + s = &Section{} + s.Blocks = NewStorage[*BlockState](BlocksPerChunkSection, PossibleBpesBlocks(version)) + s.Biomes = NewStorage[string](BiomesPerChunkSection, PossibleBpesBiomes(version)) + + var bitsPerEntryBlocks uint8 + err = binary.Read(r, binary.BigEndian, &bitsPerEntryBlocks) + if err != nil { + return + } + + return +} diff --git a/level/packet.go b/level/packet.go index 94cdcce..4ebb85f 100644 --- a/level/packet.go +++ b/level/packet.go @@ -11,13 +11,6 @@ import ( "github.com/admin-else/strom/util" ) -const ( - ChunkWidth = 16 - ChunkColumns = ChunkWidth * ChunkWidth - BlocksPerChunkSection = ChunkWidth * ChunkWidth * ChunkWidth - BiomesPerChunkSection = 4 * 4 * 4 -) - var InvalidPalletIndexErr = errors.New("invalid palette index") func UnpackArrayPalette(r io.Reader, bitsPerEntry uint8, numberOfEntries int) (data []int32, err error) { diff --git a/level/storage.go b/level/storage.go index 2fda630..06bde04 100644 --- a/level/storage.go +++ b/level/storage.go @@ -6,8 +6,15 @@ import ( "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 @@ -41,6 +48,17 @@ func ImportStorage[T comparable](data []uint64, bpe uint8, palette []T, len int, 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 @@ -54,6 +72,7 @@ func (s *Storage[T]) CheckData() (err error) { } return } + func (s *Storage[T]) Resize(bpe uint8) { if bpe == 0 { s.Data = nil @@ -119,9 +138,6 @@ func (s *Storage[T]) Set(i int, v T) (err error) { if err != nil { return } - if s.BitsPerEntry == 0 { - return - } s.SetLow(i, uint32(pi)) return } @@ -150,3 +166,54 @@ func (s *Storage[T]) RealValues() []T { } 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-- + } +}