Пример #1
0
 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);
                     }
                 }
     }
 }
Пример #2
0
        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);
            }
        }