private void GrowPalette() { // Decode the indices int[] indices = new int[_size]; for (int i = 0; i < _size; i++) { indices[i] = (int)_data.GetBits(i * indicesLength, indicesLength).Data; } // Create a new palette, double the size indicesLength = indicesLength << 1; PaletteEntry[] newPalette = new PaletteEntry[(int)MathF.Pow(2, indicesLength)]; int k = 0; for (int i = 0; i < palette.Length; i++) { if (palette[i] != null && palette[i].refcount > 0) { newPalette[k++] = palette[i]; } } palette = newPalette; _data = new BitBuffer(_size * indicesLength); for (int i = 0; i < indices.Length; i++) { _data.SetBits(i * indicesLength, indicesLength, new BitArray32((uint)indices[i])); } }
public BlockStorage(int size) { this._size = size; this.indicesLength = 1; this.paletteCount = 0; this.palette = new PaletteEntry[1 << indicesLength]; this._data = new BitBuffer(size * indicesLength); palette[0] = new PaletteEntry(size, 0); }
// Shrink the palette because it may be too big (old entries removed) private void FitPalette() { for (int i = 0; i < palette.Length; i++) { // Remove old entries if (palette[i] != null && palette[i].refcount == 0) { palette[i] = null; paletteCount -= 1; } } if (paletteCount > PowerOfTwo(paletteCount) / 2) { // Cannot shrink palette return; } int[] indices = new int[_size]; for (int i = 0; i < _size; i++) { indices[i] = (int)_data.GetBits(i * indicesLength, indicesLength).Data; } indicesLength = indicesLength >> 1; PaletteEntry[] newPalette = new PaletteEntry[(int)MathF.Pow(2, indicesLength)]; int paletteCounter = 0; for (int pi = 0; pi < palette.Length; pi++, paletteCounter++) { PaletteEntry entry = newPalette[paletteCounter] = palette[pi]; for (int di = 0, fc = 0; di < indicesLength && fc < entry.refcount; di++) { if (pi == indices[di]) { indices[di] = paletteCounter; fc += 1; } } } // allocate a new bitbuffer _data = new BitBuffer(_size * indicesLength); // Reencode indices for (int i = 0; i < indices.Length; i++) { _data.SetBits(i * indicesLength, indicesLength, new BitArray32((uint)indices[i])); } }
// Setting the wrong bit :eyesBlur: public void SetBlock(int index, int blockType) { // Get the type of block at that position int paletteIndex = (int)_data.GetBits(index * indicesLength, indicesLength).Data; PaletteEntry current = palette[paletteIndex]; // That block at the position no longer exists, so one less reference of the block in the palette current.refcount -= 1; // Is the block type already in the palette int replace = -1; for (int i = 0; i < palette.Length; i++) { if (palette[i] != null && palette[i].type == blockType) { replace = i; break; } } if (replace != -1) { _data.SetBits(index * indicesLength, indicesLength, new BitArray32((uint)replace)); palette[replace].refcount += 1; return; } // Otherwise if we can overwrite the current palette entry if (current.refcount == 0) { current.type = blockType; current.refcount = 1; return; } // A new palette entry is needed! int newEntry = NewPaletteEntry(); palette[newEntry] = new PaletteEntry(1, blockType); _data.SetBits(index * indicesLength, indicesLength, new BitArray32((uint)newEntry)); paletteCount += 1; }