public void Load() { lock (_chunkCache) { string filePath = FilePath; if (!File.Exists(filePath)) { // Welp, nothing to load. IsLoaded = true; return; } using (FileStream regionFile = File.OpenRead(filePath)) { AnvilRegionHeader header = LoadRegionHeader(regionFile); RegionHeader = header; //File.WriteAllLines(FilePath + ".header", header.GetAllChunkData().Select(h => string.Format("{0,-10}\t=>\t{1,-10}\t{2,-10}\t{3,-10}", h.ChunkCoordinates, h.LocationOffset, h.SectorCount, h.UpdatedTimestamp)).ToArray()); foreach (AnvilRegionHeaderChunkData data in header.GetAllChunkData()) { // Attempt to load NbtFile for each chunk. if (!data.ChunkExists) { continue; } regionFile.Seek(data.LocationOffset, SeekOrigin.Begin); var lengthBuffer = new byte[4]; regionFile.Read(lengthBuffer, 0, 4); Array.Reverse(lengthBuffer); int nbtDataLength = BitConverter.ToInt32(lengthBuffer, 0) - 1; int compressionMode = regionFile.ReadByte(); NbtCompression compression = compressionMode == 2 ? NbtCompression.ZLib : (compressionMode == 1 ? NbtCompression.GZip : NbtCompression.None); var nbtDataBuffer = new byte[nbtDataLength]; regionFile.Read(nbtDataBuffer, 0, nbtDataLength); //Debug.WriteLine($"({data.ChunkCoordinates.X}, {data.ChunkCoordinates.Z}) Offset: {data.LocationOffset}, Header Length: {data.SectorCount}, NbtDataLength: {nbtDataLength}"); var nbtFile = new NbtFile(); nbtFile.LoadFromBuffer(nbtDataBuffer, 0, nbtDataLength, compression); //File.WriteAllText(Path.Combine(Provider.BasePath, "region", FileName + $"_{data.ChunkCoordinates.X}-{data.ChunkCoordinates.Z}.txt"), nbtFile.ToString()); //Debug.WriteLine( // $"Region: ({X},{Z}), Chunk({data.ChunkCoordinates.X}, {data.ChunkCoordinates.Z}): NbtDataLength: {nbtDataLength}"); _containingChunks.TryAdd(data.ChunkCoordinates, nbtFile); } } IsLoaded = true; } }
private AnvilRegionHeader LoadRegionHeader(FileStream regionFile) { var header = new AnvilRegionHeader(); var completeUpdatedTimeBuffer = new byte[4096]; regionFile.Seek(4096, SeekOrigin.Begin); regionFile.Read(completeUpdatedTimeBuffer, 0, 4096); regionFile.Seek(0, SeekOrigin.Begin); //int read = 0; int baseX = X * Width; int baseZ = Z * Width; // Load Chunk Locations for (var zi = 0; zi < Width; zi++) { for (var xi = 0; xi < Width; xi++) { int x = baseX + xi; int z = baseZ + zi; int index = (xi + zi * Width) * 4; var coords = new ChunkCoordinates(x, z); var chunkLocationBuffer = new byte[4]; regionFile.Read(chunkLocationBuffer, 0, 3); Array.Reverse(chunkLocationBuffer); int offset = BitConverter.ToInt32(chunkLocationBuffer, 0) << 4; int length = regionFile.ReadByte() << 12; var updatedTimeBuffer = new byte[4]; Array.Copy(completeUpdatedTimeBuffer, index, updatedTimeBuffer, 0, 4); Array.Reverse(updatedTimeBuffer); int updatedTime = BitConverter.ToInt32(updatedTimeBuffer, 0); //Debug.WriteLine($"Header ({x},{z}) Offset: {offset} Length: {length} UpdatedTime: {updatedTime}"); var chunkHeader = new AnvilRegionHeaderChunkData(coords, offset, length, updatedTime); header.SetChunkData(coords, chunkHeader); } } return(header); }