// 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.");
        }
Beispiel #2
0
        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;
            }
        }
Beispiel #3
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);
        }
Beispiel #4
0
        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);
                        }
                    }
                }
            }
        }