Exemple #1
0
        /// <summary>
        ///     Saves the region file to a stream.
        /// </summary>
        /// <param name="stream">The stream the region file will write to.</param>
        /// <param name="regionFile">The region file to save.</param>
        public static void SaveRegion(Stream stream, RegionFile regionFile)
        {
            // build offset and timestamp headers

            // write data to storage
            using (var writer = new BinaryWriter(stream))
            {
                //write header information
                foreach (var offset in regionFile.offsets)
                {
                    writer.Write(EndiannessConverter.ToInt16((short)offset.SectorOffset));
                    writer.Write(EndiannessConverter.ToInt16(offset.SectorSize));
                }

                foreach (var timeStamp in regionFile.tStamps)
                {
                    writer.Write(EndiannessConverter.ToInt32((int)timeStamp.Timestamp));
                }

                var index = 0;

                // write chunk information
                foreach (var content in regionFile.Content)
                {
                    stream.Seek(regionFile.offsets[index++].SectorOffset * 4096, SeekOrigin.Begin);
                    NbtFile.SaveTag(stream, 2, content);

                    // write blank space before writing next chunk
                    var size = content.Size();
                    var csiz = (int)Math.Ceiling(size / 1024.0);

                    for (var i = 0; i < (csiz * 1024) - size; i++)
                    {
                        writer.Write((byte)0);
                    }
                }
            }
        }
Exemple #2
0
        /// <summary>
        ///     Opens the region file from a stream.
        /// </summary>
        /// <param name="stream">The stream the region file will read from.</param>
        /// <returns>The parsed region file.</returns>
        public static RegionFile OpenRegion(Stream stream)
        {
            var region = new RegionFile();

            using (var reader = new BinaryReader(stream))
            {
                // initialize values

                #region Init

                var sectors = new int[1024];
                var tstamps = new int[1024];

                #endregion

                // read header information

                #region Header IO read

                for (int i = 0; i < 1024; i++)
                    sectors[i] = reader.ReadInt32();

                for (int i = 0; i < 1024; i++)
                    tstamps[i] = reader.ReadInt32();

                #endregion

                // parse header information

                #region Offset parse

                for (int i = 0; i < 1024; i++)
                {
                    int sector = EndiannessConverter.ToInt32(sectors[i]);

                    region.offsets[i] = new Offset
                        {
                            // get the sector size of the chunk
                            SectorSize = (byte)(sector & 0xFF),
                            // get the sector offset of the chunk
                            SectorOffset = sector >> 8,
                        };
                }

                #endregion

                #region Timestamp parse

                for (int i = 0; i < 1024; i++)
                {
                    int tstamp = EndiannessConverter.ToInt32(tstamps[i]);

                    region.tStamps[i] = new TimeStamp
                        {
                            Timestamp = tstamp
                        };
                }

                #endregion

                // read content from disk

                #region Chunk IO read

                var chunkBuffer = new byte[sectors.Length][];
                {
                    for (int i = 0; i < 1024; i++)
                    {
                        Offset offset = region.offsets[i];

                        if (offset.SectorOffset <= 0)
                            continue;

                        // sector offset will always start at 2
                        stream.Seek(offset.SectorOffset * 4096, SeekOrigin.Begin);
                        reader.ReadByte();

                        chunkBuffer[i] = reader.ReadBytes(EndiannessConverter.ToInt32(reader.ReadInt32()) - 1);
                    }
                }

                #endregion

                // parse chunk information

                #region Parse content

                var workerThreads = new Thread[MaxThreads];
                var content = new List<NbtFile>();
                {
                    for (int i = 0; i < MaxThreads; i++)
                    {
                        int index = i;

                        workerThreads[i] = new Thread(() =>
                            {
                                var buffer = new List<NbtFile>();

                                int offset = index * (1024 / MaxThreads);
                                for (int n = offset; n < (chunkSlice + offset); n++)
                                {
                                    byte[] chunk = chunkBuffer[n];

                                    if (chunk == null)
                                        continue;

                                    using (var mmStream = new MemoryStream(chunk))
                                    {
                                        buffer.Add(NbtFile.OpenTag(mmStream, 2));
                                    }
                                }

                                lock (content)
                                    content.AddRange(buffer);
                            }) { Name = "Worker thread " + (i + 1) };

                        workerThreads[i].Start();
                    }

                    foreach (Thread t in workerThreads)
                        t.Join();

                    region.Content = content.ToArray();
                }

                #endregion
            }

            return region;
        }