/// <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) { #if DEBUG DateTime wStart; #endif RegionFile region = new RegionFile(); using (BinaryReader reader = new BinaryReader(stream)) { int[] sectors = new int[1024]; int[] tstamps = new int[1024]; for (int i = 0; i < 1024; i++) { sectors[i] = reader.ReadInt32(); } for (int i = 0; i < 1024; i++) { tstamps[i] = reader.ReadInt32(); } Thread offsetThread = new Thread(new ThreadStart(() => { int sector = 0; lock (sectors) for (int i = 0; i < 1024; i++) { sector = EndiannessConverter.ToInt32(sectors[i]); region.offsets[i] = new McrOffset() { SectorSize = (byte)(sector & 0xFF), SectorOffset = sector >> 8, }; } sectors = null; })); offsetThread.Name = "offset calculator thread"; offsetThread.Start(); offsetThread.Join(); Thread tstampThread = new Thread(() => { int tstamp = 0; lock (tstamps) for (int i = 0; i < 1024; i++) { tstamp = EndiannessConverter.ToInt32(tstamps[i]); region.tstamps[i] = new McrtStamp { Timestamp = tstamp, }; } tstamps = null; }) { Name = "timestamp calculator thread" }; tstampThread.Start(); tstampThread.Join(); #if DEBUG wStart = DateTime.Now; #endif byte[][] chunkBuffer = new byte[1024][]; { int length; McrOffset offset; for (int i = 0; i < 1024; i++) { offset = region.offsets[i]; if (offset.SectorOffset != 0) { stream.Seek(offset.SectorOffset * 4096, SeekOrigin.Begin); length = EndiannessConverter.ToInt32(reader.ReadInt32()); reader.ReadByte(); chunkBuffer[i] = reader.ReadBytes(length - 1); } } } int chunkSlice = 1024 / MaxTHREADS; Thread[] workerThreads = new Thread[MaxTHREADS]; { for (int i = 0; i < MaxTHREADS; i++) { byte[][] chunkWorkerBuffer = new byte[chunkSlice][]; Array.Copy(chunkBuffer, i * chunkSlice, chunkWorkerBuffer, 0, chunkSlice); int index = i; workerThreads[i] = new Thread(new ThreadStart(() => { #if DEBUG DateTime start = DateTime.Now; #endif int offset = index * (1024 / MaxTHREADS); MemoryStream mmStream = null; for (int n = 0; n < chunkWorkerBuffer.Length; n++) { byte[] chunk = chunkWorkerBuffer[n]; if (chunk == null) { continue; } mmStream = new MemoryStream(chunk); region.chunks[n + offset] = NBTFile.OpenFile(mmStream, 2); mmStream.Dispose(); } chunkWorkerBuffer = null; #if DEBUG Console.WriteLine("Thread worker " + (index + 1) + " is complete! Took " + (int)(DateTime.Now - start).TotalMilliseconds + "ms to process."); })); workerThreads[i].Name = "chunk worker thread " + (index + 1); #else }));
/// <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) { #if DEBUG DateTime wStart; #endif RegionFile region = new RegionFile(); using (BinaryReader reader = new BinaryReader(stream)) { int[] sectors = new int[1024]; int[] tstamps = new int[1024]; for (int i = 0; i < 1024; i++) sectors[i] = reader.ReadInt32(); for (int i = 0; i < 1024; i++) tstamps[i] = reader.ReadInt32(); Thread offsetThread = new Thread(new ThreadStart(() => { int sector = 0; lock (sectors) for (int i = 0; i < 1024; i++) { sector = EndiannessConverter.ToInt32(sectors[i]); region.offsets[i] = new McrOffset() { SectorSize = (byte)(sector & 0xFF), SectorOffset = sector >> 8, }; } sectors = null; })); offsetThread.Name = "offset calculator thread"; offsetThread.Start(); offsetThread.Join(); Thread tstampThread = new Thread(() => { int tstamp = 0; lock (tstamps) for (int i = 0; i < 1024; i++) { tstamp = EndiannessConverter.ToInt32(tstamps[i]); region.tstamps[i] = new McrtStamp { Timestamp = tstamp, }; } tstamps = null; }) {Name = "timestamp calculator thread"}; tstampThread.Start(); tstampThread.Join(); #if DEBUG wStart = DateTime.Now; #endif byte[][] chunkBuffer = new byte[1024][]; { int length; McrOffset offset; for (int i = 0; i < 1024; i++) { offset = region.offsets[i]; if (offset.SectorOffset != 0) { stream.Seek(offset.SectorOffset * 4096, SeekOrigin.Begin); length = EndiannessConverter.ToInt32(reader.ReadInt32()); reader.ReadByte(); chunkBuffer[i] = reader.ReadBytes(length - 1); } } } int chunkSlice = 1024 / MaxTHREADS; Thread[] workerThreads = new Thread[MaxTHREADS]; { for (int i = 0; i < MaxTHREADS; i++) { byte[][] chunkWorkerBuffer = new byte[chunkSlice][]; Array.Copy(chunkBuffer, i * chunkSlice, chunkWorkerBuffer, 0, chunkSlice); int index = i; workerThreads[i] = new Thread(new ThreadStart(() => { #if DEBUG DateTime start = DateTime.Now; #endif int offset = index * (1024 / MaxTHREADS); MemoryStream mmStream = null; for (int n = 0; n < chunkWorkerBuffer.Length; n++) { byte[] chunk = chunkWorkerBuffer[n]; if (chunk == null) continue; mmStream = new MemoryStream(chunk); region.chunks[n + offset] = NBTFile.OpenFile(mmStream, 2); mmStream.Dispose(); } chunkWorkerBuffer = null; #if DEBUG Console.WriteLine("Thread worker " + (index + 1) + " is complete! Took " + (int)(DateTime.Now - start).TotalMilliseconds + "ms to process."); })); workerThreads[i].Name = "chunk worker thread " + (index + 1); #else })); #endif workerThreads[i].Start(); } for (int i = 0; i < workerThreads.Length; i++) workerThreads[i].Join(); } }