/// <summary> /// Read block data and parse /// </summary> /// <param name="stream">File stream used for read</param> /// <param name="blockIndex">Index of block in sequence</param> /// <param name="headerLength">Number of bytes of header</param> /// <param name="blockSize">One block size</param> /// <returns>(Block MetaHeader, DataItem in array)</returns> private static (BlockMeta blockMeta, DataItem[] blockdata) ReadBlock(FileStream stream, int blockIndex, int headerLength, int blockSize) { // Init array for full block bytes byte[] blockBytes = new byte[blockSize]; // Read all bytes of specific block blockBytes = ReadBytes(stream, blockSize, headerLength + (blockSize * blockIndex)); int offset = 0; // Read block metaHeader size int blockMetaSize = BitConverter.ToInt32(blockBytes, offset); offset += sizeof(int); // Read MetaHeader BlockMeta blockMeta = BytesToObject <BlockMeta>(blockBytes, offset, blockMetaSize); offset += blockMetaSize; // Read Data Size int blockDataSize = BitConverter.ToInt32(blockBytes, offset); offset += sizeof(int); // Read Data DataItem[] items = BytesToObject <DataItem[]>(blockBytes, offset, blockDataSize); return(blockMeta, items); }
/// <summary> /// 释放缓冲区 /// </summary> /// <param name="blockMeta">区块元数据</param> private void ReleaseBlock(BlockMeta blockMeta) { if (blockMeta != null) { ReleaseBuffer(blockMeta.Storage); } }
public void SetBlockMeta(int x, int y, int z, BlockMeta meta) { x = NumericsHelper.Modulo(x, 16); z = NumericsHelper.Modulo(z, 16); var value = (short)((x << 8) | (z << 4) | y); this.BlockMetaStore[value] = meta; }
public BlockMeta Build() { var meta = new BlockMeta { Name = this.Name, Lore = this.lore, CanPlaceOn = this.canPlaceOn, BlockEntityTag = this.BlockEntityTag, BlockStateTag = this.BlockStateTag }; return(meta); }
/// <summary> /// Read block header /// </summary> /// <param name="stream">File stream used for read</param> /// <param name="blockIndex">Index of block in sequence</param> /// <param name="headerLength">Number of bytes of header</param> /// <param name="blockSize">One block size</param> /// <returns>(Block MetaHeader, DataItem in array)</returns> private static BlockMeta ReadBlockHeader(FileStream stream, int blockIndex, int headerLength, int blockSize) { // Read all bytes of specific block byte[] blockHeaderSizeBytes = ReadBytes(stream, sizeof(int), headerLength + (blockSize * blockIndex)); // Read block metaHeader size int blockMetaSize = BitConverter.ToInt32(blockHeaderSizeBytes, 0); // Read block header bytes byte[] blockHeaderBytes = ReadBytes(stream, blockMetaSize, headerLength + (blockSize * blockIndex) + sizeof(int)); // Deserialize MetaHeader BlockMeta blockMeta = BytesToObject <BlockMeta>(blockHeaderBytes); return(blockMeta); }
/// <summary> /// Find block with valid range for finding value /// </summary> /// <param name="stream">File stream used for read</param> /// <param name="metadata">File metadata</param> /// <param name="keyHash">Searching hash value</param> /// <param name="headerLength">File header size (offset for first block)</param> /// <param name="method">Searching method</param> /// <returns>Data array of appropriate block</returns> private (int blockID, DataItem[] blockData) FindBlockData(FileStream stream, FileMeta metadata, int keyHash, int headerLength, SearchMethod method) { int left = 0; int right = (metadata.BuildValuesCount - 1); int mid; int maxVal = metadata.BuildMax; int minVal = metadata.BuildMin; // While until search interval is valid while (left <= right && keyHash >= minVal && keyHash <= maxVal) { // Calculate middle index mid = CalculateMiddle(left, right, minVal, maxVal, keyHash, method); // Get blockID with item with middle index int blockId = mid / _itemsForBlock; if (mid < 0 && mid > metadata.ActualValuesCount) { throw new ApplicationException("Invalid operation! Out of range!"); } // Read block header BlockMeta block = ReadBlockHeader(stream, blockId, headerLength, metadata.BlockSize); if (block.Min <= keyHash && keyHash <= block.Max) { // Read block data for search value (value is in this range) DataItem[] data = ReadBlock(stream, blockId, headerLength, metadata.BlockSize).blockdata; return(blockId, data); } if (block.Max < keyHash) { // Is in the upper part left = mid + 1; } else { // Is in the lower part right = mid - 1; } } // Valid block not found return(-1, null); }
/// <summary> /// 保障存储块满足存储条件 /// </summary> /// <param name="value">总共需要占用的空间</param> private void EnsureStorageBlock(long value) { AssertMemoryUseable(value); if (value <= 0) { return; } var minBlockCount = (int)((value / BlockSize) + ((value % BlockSize) == 0 ? 0 : 1)); if (storage.Length >= minBlockCount) { return; } var newStorage = new BlockMeta[minBlockCount.ToPrime()]; Array.Copy(storage, 0, newStorage, 0, storage.Length); storage = newStorage; }
/// <summary> /// Build binary data block /// </summary> /// <param name="data">Data to serialize for block</param> /// <returns>Block bytes</returns> private static byte[] BuildBlock(DataItem[] data, int?minVal = null, int?maxVal = null) { int offset = 0; // Prepare block meta data BlockMeta meta = new BlockMeta(); meta.Min = (int)(minVal == null ? data[0].HashKey : minVal); meta.Max = (int)(maxVal == null ? data[data.Count() - 1].HashKey : maxVal); // Serialize objects byte[] metaBytes = ObjectToBytes(meta); byte[] metaSize = BitConverter.GetBytes(metaBytes.Length); byte[] dataBytes = ObjectToBytes(data.ToArray()); byte[] dataSize = BitConverter.GetBytes(dataBytes.Length); // Prepare output array byte[] output = new byte[metaBytes.Length + metaSize.Length + dataBytes.Length + dataSize.Length]; // Copy MetaDataSize bytes to output Array.Copy(metaSize, output, metaSize.Length); offset += metaSize.Length; // Copy MetaData bytes to output Array.Copy(metaBytes, 0, output, offset, metaBytes.Length); offset += metaBytes.Length; // Copy DataSize bytes to output Array.Copy(dataSize, 0, output, offset, dataSize.Length); offset += dataSize.Length; // Copy Data bytes to output Array.Copy(dataBytes, 0, output, offset, dataBytes.Length); offset += dataBytes.Length; return(output); }
/// <summary> /// String representation of the block /// </summary> public override string ToString() { return(BlockId.ToString() + (BlockMeta != 0 ? ":" + BlockMeta.ToString() : "")); }
public void SetBlockMeta(Vector position, BlockMeta meta) => SetBlockMeta(position.X, position.Y, position.Z, meta);
public void SetBlockMeta(Vector position, BlockMeta meta) => this.SetBlockMeta((int)position.X, (int)position.Y, (int)position.Z, meta);