public Anvil(string path) { NbtTag levelDat = new NbtFile(Path.Combine(path, "level.dat")).RootTag["Data"]; string levelName = levelDat["LevelName"].StringValue; string[] regionFiles = Directory.GetFiles(Path.Combine(path, "region"), "*.mca"); for (int idx = 0; idx < regionFiles.Length; idx++) ParseRegion(regionFiles[idx]); Bounds bounds = ScanForBounds(); boundaryWidth = bounds.Width; boundaryHeight = bounds.Height; boundaryLength = bounds.Length; offsetX = -bounds.minX; offsetY = -bounds.minY; offsetZ = -bounds.minZ; Console.WriteLine("Extracting blocks within boundary."); foreach (KeyValuePair<CoordinateInt, Block[]> pair in chunks) { CoordinateInt chunkCoord = pair.Key; if (bounds.ContainsChunk(chunkCoord)) for (int idx = 0; idx < pair.Value.Length; idx++) if (BlockTypeIsSupported(pair.Value[idx].id)) { int absoluteX = chunkCoord.X * 16 + idx % 16; int absoluteZ = chunkCoord.Z * 16 + (idx / 16) % 16; int absoluteY = chunkCoord.Y * 16 + idx / (16 * 16); if (bounds.Contains(absoluteX, absoluteY, absoluteZ)) { CoordinateInt blockCoord = new CoordinateInt(absoluteX + offsetX, absoluteZ + offsetZ, absoluteY + offsetY); blocks[blockCoord] = new Block(pair.Value[idx].id, 0);// pair.Value[idx].data); } } } }
private void ParseRegion(string regionPath) { string fileName = Path.GetFileName(regionPath); int chunkCount = 0; using (BinaryReader binaryReader = new BinaryReader(File.Open(regionPath, FileMode.Open))) { List<LocationData> locationList = new List<LocationData>(); for (int idx = 0; idx < 1024; idx++) { int row = Endian.ToBig(binaryReader.ReadInt32()); int offset = (row >> 8); byte sectorCount = (byte)(row & 0x000000FF); if (offset != 0 || sectorCount != 0) locationList.Add(new LocationData(idx % 32, idx / 32, offset, sectorCount)); } for (int locationIdx = 0; locationIdx < locationList.Count; locationIdx++) { binaryReader.BaseStream.Seek(sectorSize * locationList[locationIdx].offset, SeekOrigin.Begin); int length = Endian.ToBig(binaryReader.ReadInt32()); byte compressionType = binaryReader.ReadByte(); byte[] dataBuffer = binaryReader.ReadBytes(length - 1); NbtFile region = new NbtFile(); region.LoadFromBuffer(dataBuffer, 0, dataBuffer.Length, NbtCompression.ZLib); NbtTag levelTag = region.RootTag["Level"]; int chunkX = levelTag["xPos"].IntValue; int chunkZ = levelTag["zPos"].IntValue; NbtList sections = levelTag["Sections"] as NbtList; for (int sectionIdx = 0; sectionIdx < sections.Count; sectionIdx++) { Block[] blocks = new Block[16 * 16 * 16]; NbtTag sectionTag = sections[sectionIdx]; int offsetY = sectionTag["Y"].ByteValue; byte[] blockIDs = sectionTag["Blocks"].ByteArrayValue; byte[] blockData = sectionTag["Data"].ByteArrayValue; for (int blockIdx = 0; blockIdx < blockIDs.Length; blockIdx++) blocks[blockIdx] = new Block((BlockIdentifier)blockIDs[blockIdx], MaskTo4Bit(blockData, blockIdx)); CoordinateInt coord = new CoordinateInt(chunkX, offsetY, chunkZ); chunks.Add(coord, blocks); chunkCount++; } } Console.WriteLine("Parsed {0} ({1} chunks)", fileName, chunkCount); } }