Ejemplo n.º 1
0
        public unsafe static void CompressMap(Player p, LevelChunkStream dst)
        {
            const int bufferSize = 64 * 1024;

            byte[] buffer = new byte[bufferSize];
            int    bIndex = 0;

            // Store on stack instead of performing function call for every block in map
            byte *conv    = stackalloc byte[256];
            byte *convCPE = stackalloc byte[256];

            for (int i = 0; i < 256; i++)
            {
                conv[i] = Block.Convert((byte)i);
            }

            if (!p.hasCustomBlocks)
            {
                for (int i = 0; i < 256; i++)
                {
                    convCPE[i] = Block.ConvertCPE((byte)i);
                    conv[i]    = Block.ConvertCPE(conv[i]);
                }
            }

            Level lvl          = p.level;
            bool  hasBlockDefs = p.hasBlockDefs;

            using (GZipStream gs = new GZipStream(dst, CompressionMode.Compress, true)) {
                byte[] blocks = lvl.blocks;
                NetUtils.WriteI32(blocks.Length, buffer, 0);
                gs.Write(buffer, 0, sizeof(int));
                dst.length = blocks.Length;

                // compress the map data in 64 kb chunks
                if (p.hasCustomBlocks)
                {
                    for (int i = 0; i < blocks.Length; ++i)
                    {
                        byte block = blocks[i];
                        if (block == Block.custom_block)
                        {
                            buffer[bIndex] = hasBlockDefs ? lvl.GetExtTile(i) : lvl.GetFallbackExtTile(i);
                        }
                        else
                        {
                            buffer[bIndex] = conv[block];
                        }

                        bIndex++;
                        if (bIndex == bufferSize)
                        {
                            dst.position = i;
                            gs.Write(buffer, 0, bufferSize); bIndex = 0;
                        }
                    }
                }
                else
                {
                    for (int i = 0; i < blocks.Length; ++i)
                    {
                        byte block = blocks[i];
                        if (block == Block.custom_block)
                        {
                            block          = hasBlockDefs ? lvl.GetExtTile(i) : lvl.GetFallbackExtTile(i);
                            buffer[bIndex] = convCPE[block];
                        }
                        else
                        {
                            buffer[bIndex] = conv[block];
                        }

                        bIndex++;
                        if (bIndex == bufferSize)
                        {
                            dst.position = i;
                            gs.Write(buffer, 0, bufferSize); bIndex = 0;
                        }
                    }
                }
                if (bIndex > 0)
                {
                    gs.Write(buffer, 0, bIndex);
                }
            }
        }