From f0afbb7fa042c58242bbeae351a5928775b5132c Mon Sep 17 00:00:00 2001 From: Tnze Date: Fri, 12 Mar 2021 21:56:04 +0800 Subject: [PATCH] BitStorage implement like mojang --- save/bitstorage.go | 148 ++++++++++++++++++++++++++++++++++++++++ save/bitstorage_test.go | 28 ++++++++ 2 files changed, 176 insertions(+) create mode 100644 save/bitstorage.go create mode 100644 save/bitstorage_test.go diff --git a/save/bitstorage.go b/save/bitstorage.go new file mode 100644 index 0000000..83f62ef --- /dev/null +++ b/save/bitstorage.go @@ -0,0 +1,148 @@ +package save + +import ( + "fmt" + "math" +) + +// This implement the format since Minecraft 1.16 +type BitStorage struct { + data []uint64 + mask uint64 + + bits, size int + valuesPerLong int + + divideMul int + divideAdd int + divideShift int +} + +// NewBitStorage create a new BitStorage, // TODO: document +func NewBitStorage(bits, size int, arrl []uint64) (b *BitStorage) { + var _MAGIC = [...]int{ + -1, -1, 0, + math.MinInt32, 0, 0, + 1431655765, 1431655765, 0, + math.MinInt32, 0, 1, + 858993459, 858993459, 0, + 715827882, 715827882, 0, + 613566756, 613566756, 0, + math.MinInt32, 0, 2, + 477218588, 477218588, 0, + 429496729, 429496729, 0, + 390451572, 390451572, 0, + 357913941, 357913941, 0, + 330382099, 330382099, 0, + 306783378, 306783378, 0, + 286331153, 286331153, 0, + math.MinInt32, 0, 3, + 252645135, 252645135, 0, + 238609294, 238609294, 0, + 226050910, 226050910, 0, + 214748364, 214748364, 0, + 204522252, 204522252, 0, + 195225786, 195225786, 0, + 186737708, 186737708, 0, + 178956970, 178956970, 0, + 171798691, 171798691, 0, + 165191049, 165191049, 0, + 159072862, 159072862, 0, + 153391689, 153391689, 0, + 148102320, 148102320, 0, + 143165576, 143165576, 0, + 138547332, 138547332, 0, + math.MinInt32, 0, 4, + 130150524, 130150524, 0, + 126322567, 126322567, 0, + 122713351, 122713351, 0, + 119304647, 119304647, 0, + 116080197, 116080197, 0, + 113025455, 113025455, 0, + 110127366, 110127366, 0, + 107374182, 107374182, 0, + 104755299, 104755299, 0, + 102261126, 102261126, 0, + 99882960, 99882960, 0, + 97612893, 97612893, 0, + 95443717, 95443717, 0, + 93368854, 93368854, 0, + 91382282, 91382282, 0, + 89478485, 89478485, 0, + 87652393, 87652393, 0, + 85899345, 85899345, 0, + 84215045, 84215045, 0, + 82595524, 82595524, 0, + 81037118, 81037118, 0, + 79536431, 79536431, 0, + 78090314, 78090314, 0, + 76695844, 76695844, 0, + 75350303, 75350303, 0, + 74051160, 74051160, 0, + 72796055, 72796055, 0, + 71582788, 71582788, 0, + 70409299, 70409299, 0, + 69273666, 69273666, 0, + 68174084, 68174084, 0, + math.MinInt32, 0, 5, + } + + n3 := 3 * (64/bits - 1) + b = &BitStorage{ + mask: 1<> 32 >> b.divideShift) +} + +func (b *BitStorage) Swap(i, v int) (old int) { + if i < 0 || i > b.size-1 || + v < 0 || uint64(v) > b.mask { + panic("out of bounds") + } + c := b.cellIndex(i) + l := b.data[c] + offset := uint64((i - c*b.valuesPerLong) * b.bits) + old = int(l >> offset & b.mask) + b.data[c] = l&(b.mask< b.size-1 || + v < 0 || uint64(v) > b.mask { + panic("out of bounds") + } + c := b.cellIndex(i) + l := b.data[c] + offset := (i - c*b.valuesPerLong) * b.bits + b.data[c] = l&(b.mask< b.size-1 { + panic("out of bounds") + } + c := b.cellIndex(i) + l := b.data[c] + offset := (i - c*b.valuesPerLong) * b.bits + return int(l >> offset & b.mask) +} diff --git a/save/bitstorage_test.go b/save/bitstorage_test.go new file mode 100644 index 0000000..382fb93 --- /dev/null +++ b/save/bitstorage_test.go @@ -0,0 +1,28 @@ +package save + +import ( + "reflect" + "testing" +) + +var data = []uint64{0x0020863148418841, 0x01018A7260F68C87} +var want = []int{1, 2, 2, 3, 4, 4, 5, 6, 6, 4, 8, 0, 7, 4, 3, 13, 15, 16, 9, 14, 10, 12, 0, 2} + +func TestBitStorage_Get(t *testing.T) { + bs := NewBitStorage(5, 24, data) + for i := 0; i < 24; i++ { + if got := bs.Get(i); got != want[i] { + t.Errorf("Decode error, got: %d but expected: %d", got, want[i]) + } + } +} + +func TestBitStorage_Set(t *testing.T) { + bs := NewBitStorage(5, 24, nil) + for i := 0; i < 24; i++ { + bs.Set(i, want[i]) + } + if !reflect.DeepEqual(bs.data, data) { + t.Errorf("Encode error, got %v but expected: %v", bs.data, data) + } +}