// todo: this needs reimplemented. There is no such thing as a binary chunk index, and the chunk may not be in 0, 1, 2 order // Moves stream position to binary chunk location public static ChunkInfo SeekToBinaryChunk(Stream stream, int binaryChunkIndex, long startPosition = 0) { stream.Position = startPosition + 4; // start after magic number chunk GLBHeader header = ParseGLBHeader(stream); uint chunkOffset = 12; // sizeof(GLBHeader) + magic number uint chunkLength = 0; for (int i = 0; i < binaryChunkIndex + 2; ++i) { chunkOffset += chunkLength; stream.Position = chunkOffset; chunkLength = GetUInt32(stream); chunkOffset += 8; // to account for chunk length (4 bytes) and type (4 bytes) } // Load Binary Chunk if (chunkOffset + chunkLength <= header.FileLength) { ChunkFormat chunkType = (ChunkFormat)GetUInt32(stream); if (chunkType != ChunkFormat.BIN) { throw new GLTFHeaderInvalidException("Second chunk must be of type BIN if present"); } return(new ChunkInfo { StartPosition = stream.Position - CHUNK_HEADER_SIZE, Length = chunkLength, Type = chunkType }); } throw new GLTFHeaderInvalidException("File length does not match chunk header."); }
public Column(ChunkFormat format, MemoryStream chunkDataStream, DateTime timestamp) { Modified = timestamp; var stream = GetDecompressedStream(format, chunkDataStream); //TODO: Need to dispose of this manually? _nbtDoc = NbtDocument.LoadDocument(stream); var level = _nbtDoc.Query <TagCompound>("Level"); XWorld = level.GetIntValue("xPos") * 16; ZWorld = level.GetIntValue("zPos") * 16; var terrainPopulated = level.GetByte("TerrainPopulated"); if (terrainPopulated != null) { TerrainPopulated = terrainPopulated.Value == 1; } else { TerrainPopulated = level.GetLongValue("LastUpdate") > 0; } }
private Stream GetDecompressedStream(ChunkFormat format, MemoryStream chunkDataStream) { var outputStream = new MemoryStream(); switch (format) { case ChunkFormat.ZLIB_DEFLATE: if (chunkDataStream.ReadByte() != 0x78 || chunkDataStream.ReadByte() != 0x9C) //zlib header { throw new Exception("Incorrect zlib header"); } using (var deflateStream = new DeflateStream(chunkDataStream, CompressionMode.Decompress, false)) { deflateStream.CopyTo(outputStream); } break; case ChunkFormat.GZIP: using (var gzipStream = new GZipStream(chunkDataStream, CompressionMode.Decompress, false)) { gzipStream.CopyTo(outputStream); } break; default: chunkDataStream.CopyTo(outputStream); break; } outputStream.Seek(0, SeekOrigin.Begin); return(outputStream); }
private IEnumerable <Column> GetColumns() { using (var stream = File.OpenRead(_reqionFilePath)) { var offsets = new List <int>(); var timestamps = new List <int>(); using (var reader = new BinaryReader(stream)) { for (int i = 0; i < SECTOR_INTS; i++) { int offset = reader.ReadInt32BE(); offsets.Add(offset); } for (int i = 0; i < SECTOR_INTS; i++) { int timestamp = reader.ReadInt32BE(); timestamps.Add(timestamp); } for (int i = 0; i < offsets.Count; i++) { if (offsets[i] == 0) { continue; } int sectorNumber = offsets[i] >> 8; int numSectors = offsets[i] & 0xFF; if (numSectors == 0) { continue; } stream.Seek(sectorNumber * SECTOR_BYTES, SeekOrigin.Begin); int length = reader.ReadInt32BE(); ChunkFormat format = (ChunkFormat)reader.ReadByte(); var data = reader.ReadBytes(length - 1); Column column = null; try { column = new Column(format, new MemoryStream(data), UnixDateTimeHelpers.ToDateTime(timestamps[i])); } catch (InvalidDataException) { //Ignore } if (column != null) { yield return(column); } } } } }