public static void WriteChunk(NetBinaryWriter writer, LocalChunkColumn chunkColumn, int includeMask)
        {
            if (chunkColumn == null)
            {
                throw new ArgumentNullException(nameof(chunkColumn));
            }

            for (int sectionY = 0; sectionY < ColumnHeight; sectionY++)
            {
                if ((includeMask & (1 << sectionY)) == 0)
                {
                    continue;
                }

                if (chunkColumn.TryGetChunk(sectionY, out LocalChunk? chunk))
                {
                    LocalChunk.BlockEnumerator blocks = chunk.EnumerateBlocks();

                    JavaCompatibleBlockPalette <IBlockPalette> javaPalette = new(blocks.BlockPalette);

                    WritePalette(writer, javaPalette);
                    WriteBlocks(writer, ref blocks, javaPalette.BitsPerBlock);
                }
            }
        }
        public static int GetChunkColumnDataLength(LocalChunkColumn chunkColumn, int includeMask)
        {
            if (chunkColumn == null)
            {
                throw new ArgumentNullException(nameof(chunkColumn));
            }

            int length = 0;

            for (int sectionY = 0; sectionY < ColumnHeight; sectionY++)
            {
                if ((includeMask & (1 << sectionY)) == 0)
                {
                    continue;
                }

                if (chunkColumn.TryGetChunk(sectionY, out LocalChunk? chunk))
                {
                    JavaCompatibleBlockPalette <IBlockPalette> javaPalette = new(chunk.BlockPalette);
                    length += GetChunkDataLength(javaPalette);
                }
            }

            return(length);
        }
        public static int GetSectionMask(LocalChunkColumn chunkColumn)
        {
            if (chunkColumn == null)
            {
                throw new ArgumentNullException(nameof(chunkColumn));
            }

            int sectionMask = 0;

            for (int sectionY = 0; sectionY < ColumnHeight; sectionY++)
            {
                if (chunkColumn.TryGetChunk(sectionY, out var chunk))
                {
                    if (!chunk.IsEmpty)
                    {
                        sectionMask |= 1 << sectionY;
                    }
                }
            }
            return(sectionMask);
        }
        // TODO?: create flash-copying (fast deep-clone) of chunks for serialization purposes,
        // possibly with some kind of locking on end of dimension tick

        public ServerChunkData(LocalChunkColumn chunkColumn, int includedSectionsMask, bool fullChunk)
        {
            ChunkColumn          = chunkColumn;
            IncludedSectionsMask = includedSectionsMask;
            FullChunk            = fullChunk;
        }