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;
        }