public bool DoDecompression() { LocalPools pools = Globals.WorkPool.GetPool(Chunk.ThreadID); BlockProvider provider = Chunk.World.blockProvider; if (IsDifferential) { int blockPosSize = StructSerialization.TSSize <BlockPos> .ValueSize; int blockDataSize = StructSerialization.TSSize <BlockData> .ValueSize; positionsModified = new BlockPos[positionsBytes.Length / blockPosSize]; blocksModified = new BlockData[blocksBytes.Length / blockDataSize]; int i, j; unsafe { // Extract positions fixed(byte *pSrc = positionsBytes) { for (i = 0, j = 0; j < positionsModified.Length; i += blockPosSize, j++) { positionsModified[j] = *(BlockPos *)&pSrc[i]; Chunk.Blocks.modifiedBlocks.Add(positionsModified[j]); } } // Extract block data fixed(byte *pSrc = blocksBytes) { for (i = 0, j = 0; j < blocksModified.Length; i += blockDataSize, j++) { BlockData *bd = (BlockData *)&pSrc[i]; // Convert global block types into internal optimized version ushort type = provider.GetTypeFromTypeInConfig(bd->Type); blocksModified[j] = new BlockData(type, bd->Solid); } } } } else { int blockDataSize = StructSerialization.TSSize <BlockData> .ValueSize; int requestedByteSize = Env.CHUNK_SIZE_POW_3 * blockDataSize; // Pop a large enough buffers from the pool byte[] bytes = pools.byteArrayPool.Pop(requestedByteSize); { // Decompress data int decompressedLength = CLZF2.lzf_decompress(blocksBytes, blocksBytes.Length, ref bytes); if (decompressedLength != Env.CHUNK_SIZE_POW_3 * blockDataSize) { blocksBytes = null; return(false); } // Fill chunk with decompressed data ChunkBlocks blocks = Chunk.Blocks; int i = 0; unsafe { fixed(byte *pSrc = bytes) { int index = Helpers.ZERO_CHUNK_INDEX; int yOffset = Env.CHUNK_SIZE_WITH_PADDING_POW_2 - Env.CHUNK_SIZE * Env.CHUNK_SIZE_WITH_PADDING; int zOffset = Env.CHUNK_SIZE_WITH_PADDING - Env.CHUNK_SIZE; for (int y = 0; y < Env.CHUNK_SIZE; ++y, index += yOffset) { for (int z = 0; z < Env.CHUNK_SIZE; ++z, index += zOffset) { for (int x = 0; x < Env.CHUNK_SIZE; ++x, i += blockDataSize, ++index) { BlockData *bd = (BlockData *)&pSrc[i]; // Convert global block type into internal optimized version ushort type = provider.GetTypeFromTypeInConfig(bd->Type); blocks.SetRaw(index, new BlockData(type, bd->Solid)); } } } } } } // Return our temporary buffer back to the pool pools.byteArrayPool.Push(bytes); } ResetTemporary(); return(true); }
public bool DoCompression() { if (Features.useDifferentialSerialization) { BlockProvider provider = Chunk.World.blockProvider; int blockPosSize = StructSerialization.TSSize <BlockPos> .ValueSize; int blockDataSize = StructSerialization.TSSize <BlockData> .ValueSize; int posLenBytes = blocksModified.Length * blockPosSize; int blkLenBytes = blocksModified.Length * blockDataSize; positionsBytes = new byte[posLenBytes]; blocksBytes = new byte[blkLenBytes]; unsafe { // Pack positions to a byte array fixed(byte *pDst = positionsBytes) { for (int i = 0, j = 0; i < blocksModified.Length; i++, j += blockPosSize) { *(BlockPos *)&pDst[j] = positionsModified[i]; } } // Pack block data to a byte array fixed(BlockData *pBD = blocksModified) fixed(byte *pDst = blocksBytes) { for (int i = 0, j = 0; i < blocksModified.Length; i++, j += blockDataSize) { BlockData *bd = &pBD[i]; // Convert block types from internal optimized version into global types ushort typeInConfig = provider.GetConfig(bd->Type).TypeInConfig; *(BlockData *)&pDst[j] = new BlockData(typeInConfig, bd->Solid); } } } } else { LocalPools pools = Globals.WorkPool.GetPool(Chunk.ThreadID); BlockProvider provider = Chunk.World.blockProvider; int blockDataSize = StructSerialization.TSSize <BlockData> .ValueSize; int requestedByteSize = Env.CHUNK_SIZE_POW_3 * blockDataSize; // Pop large enough buffers from the pool byte[] tmp = pools.byteArrayPool.Pop(requestedByteSize); byte[] bytesCompressed = pools.byteArrayPool.Pop(requestedByteSize); { ChunkBlocks blocks = Chunk.Blocks; int i = 0; int index = Helpers.ZERO_CHUNK_INDEX; int yOffset = Env.CHUNK_SIZE_WITH_PADDING_POW_2 - Env.CHUNK_SIZE * Env.CHUNK_SIZE_WITH_PADDING; int zOffset = Env.CHUNK_SIZE_WITH_PADDING - Env.CHUNK_SIZE; for (int y = 0; y < Env.CHUNK_SIZE; ++y, index += yOffset) { for (int z = 0; z < Env.CHUNK_SIZE; ++z, index += zOffset) { for (int x = 0; x < Env.CHUNK_SIZE; ++x, i += blockDataSize, ++index) { BlockData bd = blocks.Get(index); // Convert block types from internal optimized version into global types ushort typeInConfig = provider.GetConfig(bd.Type).TypeInConfig; // Write updated block data to destination buffer unsafe { fixed(byte *pDst = tmp) { *(BlockData *)&pDst[i] = new BlockData(typeInConfig, bd.Solid); } } } } } // Compress bytes int blkLenBytes = CLZF2.lzf_compress(tmp, requestedByteSize, ref bytesCompressed); blocksBytes = new byte[blkLenBytes]; // Copy data from a temporary buffer to block buffer Array.Copy(bytesCompressed, 0, blocksBytes, 0, blkLenBytes); } // Return our temporary buffer back to the pool pools.byteArrayPool.Push(bytesCompressed); pools.byteArrayPool.Push(tmp); } return(true); }