Пример #1
0
        public ChunkColumn GetChunk(int X, int Z)
        {
            var width = 32;
            var depth = 32;

            var rx = X >> 5;
            var rz = Z >> 5;

            var filePath = Path.Combine(_basePath, string.Format(@"region\r.{0}.{1}.mca", rx, rz));

            if (!File.Exists(filePath))
            {
                return(_backEndGenerator.GenerateChunkColumn(new Vector2(X, Z)));
            }

            using (var regionFile = File.OpenRead(filePath))
            {
                var buffer = new byte[8192];

                regionFile.Read(buffer, 0, 8192);

                var xi = (X % width);
                if (xi < 0)
                {
                    xi += 32;
                }
                var zi = (Z % depth);
                if (zi < 0)
                {
                    zi += 32;
                }
                var tableOffset = (xi + zi * width) * 4;

                regionFile.Seek(tableOffset, SeekOrigin.Begin);

                var offsetBuffer = new byte[4];
                regionFile.Read(offsetBuffer, 0, 3);
                Array.Reverse(offsetBuffer);
                var offset = BitConverter.ToInt32(offsetBuffer, 0) << 4;

                var length = regionFile.ReadByte();

                //if (offset == 0 || length == 0) return _backEndGenerator.GenerateChunkColumn(new Vector2(X, Z));

                if (offset == 0 || length == 0)
                {
                    return(_backEndGenerator.GenerateChunkColumn(new Vector2(X, Z)));
                }

                regionFile.Seek(offset, SeekOrigin.Begin);
                var waste = new byte[4];
                regionFile.Read(waste, 0, 4);
                var compressionMode = regionFile.ReadByte();

                var nbt = new NbtFile();
                nbt.LoadFromStream(regionFile, NbtCompression.ZLib);

                var dataTag = nbt.RootTag["Level"];

                var sections = dataTag["Sections"] as NbtList;

                var chunk = new ChunkColumn
                {
                    X       = X,
                    Z       = Z,
                    BiomeId = dataTag["Biomes"].ByteArrayValue
                };

                for (var i = 0; i < chunk.BiomeId.Length; i++)
                {
                    if (chunk.BiomeId[i] > 22)
                    {
                        chunk.BiomeId[i] = 0;
                    }
                }
                if (chunk.BiomeId.Length > 256)
                {
                    throw new Exception();
                }

                // This will turn into a full chunk column
                foreach (var sectionTag in sections)
                {
                    var sy      = sectionTag["Y"].ByteValue * 16;
                    var blocks  = sectionTag["Blocks"].ByteArrayValue;
                    var data    = sectionTag["Data"].ByteArrayValue;
                    var addTag  = sectionTag["Add"];
                    var adddata = new byte[2048];
                    if (addTag != null)
                    {
                        adddata = addTag.ByteArrayValue;
                    }
                    var blockLight = sectionTag["BlockLight"].ByteArrayValue;
                    var skyLight   = sectionTag["SkyLight"].ByteArrayValue;

                    for (var x = 0; x < 16; x++)
                    {
                        for (var z = 0; z < 16; z++)
                        {
                            for (var y = 0; y < 16; y++)
                            {
                                var yi = sy + y - _waterOffsetY;
                                if (yi < 0 || yi >= 256)
                                {
                                    continue;
                                }

                                var anvilIndex = y * 16 * 16 + z * 16 + x;
                                var blockId    = blocks[anvilIndex] + (Nibble4(adddata, anvilIndex) << 8);


                                var b = BlockFactory.GetBlockById((ushort)blockId);
                                b.Metadata = Nibble4(data, anvilIndex);
                                chunk.SetBlock(x, yi, z, b);
                                chunk.SetBlocklight(x, yi, z, Nibble4(blockLight, anvilIndex));
                                chunk.SetSkylight(x, yi, z, Nibble4(skyLight, anvilIndex));
                            }
                        }
                    }
                }

                var entities     = dataTag["Entities"] as NbtList;
                var tileEntities = dataTag["TileEntities"] as NbtList;

                if (tileEntities != null)
                {
                    foreach (var nbtTag in tileEntities)
                    {
                        var    blockEntityTag = (NbtCompound)nbtTag;
                        string entityId       = blockEntityTag["id"].StringValue;
                        int    x = blockEntityTag["x"].IntValue;
                        int    y = blockEntityTag["y"].IntValue - _waterOffsetY;
                        int    z = blockEntityTag["z"].IntValue;
                        blockEntityTag["y"] = new NbtInt("y", y);

                        TileEntity blockEntity = TileEntityFactory.GetBlockEntityById(entityId);
                        if (blockEntity != null)
                        {
                            blockEntityTag.Name = string.Empty;
                            chunk.SetBlockEntity(new Vector3(x, y, z), blockEntityTag);
                        }
                    }
                }

                var tileTicks = dataTag["TileTicks"] as NbtList;

                chunk.IsDirty = false;
                return(chunk);
            }
        }
Пример #2
0
        public ChunkColumn GetChunk(int X, int Z)
        {
            var width = 32;
            var depth = 32;

            var rx = X >> 5;
            var rz = Z >> 5;

            var filePath = Path.Combine(_basePath, string.Format(@"region\r.{0}.{1}.mca", rx, rz));

            if (!File.Exists(filePath)) return _backEndGenerator.GenerateChunkColumn(new Vector2(X, Z));

            using (var regionFile = File.OpenRead(filePath))
            {
                var buffer = new byte[8192];

                regionFile.Read(buffer, 0, 8192);

                var xi = (X%width);
                if (xi < 0) xi += 32;
                var zi = (Z%depth);
                if (zi < 0) zi += 32;
                var tableOffset = (xi + zi*width)*4;

                regionFile.Seek(tableOffset, SeekOrigin.Begin);

                var offsetBuffer = new byte[4];
                regionFile.Read(offsetBuffer, 0, 3);
                Array.Reverse(offsetBuffer);
                var offset = BitConverter.ToInt32(offsetBuffer, 0) << 4;

                var length = regionFile.ReadByte();

                //if (offset == 0 || length == 0) return _backEndGenerator.GenerateChunkColumn(new Vector2(X, Z));

                if (offset == 0 || length == 0)
                {
                    return _backEndGenerator.GenerateChunkColumn(new Vector2(X,Z));
                }

                regionFile.Seek(offset, SeekOrigin.Begin);
                var waste = new byte[4];
                regionFile.Read(waste, 0, 4);
                var compressionMode = regionFile.ReadByte();

                var nbt = new NbtFile();
                nbt.LoadFromStream(regionFile, NbtCompression.ZLib);

                var dataTag = nbt.RootTag["Level"];

                var sections = dataTag["Sections"] as NbtList;

                var chunk = new ChunkColumn
                {
                    X = X,
                    Z = Z,
                    BiomeId = dataTag["Biomes"].ByteArrayValue
                };

                for (var i = 0; i < chunk.BiomeId.Length; i++)
                {
                    if (chunk.BiomeId[i] > 22) chunk.BiomeId[i] = 0;
                }
                if (chunk.BiomeId.Length > 256) throw new Exception();

                // This will turn into a full chunk column
                foreach (var sectionTag in sections)
                {
                    var sy = sectionTag["Y"].ByteValue*16;
                    var blocks = sectionTag["Blocks"].ByteArrayValue;
                    var data = sectionTag["Data"].ByteArrayValue;
                    var addTag = sectionTag["Add"];
                    var adddata = new byte[2048];
                    if (addTag != null) adddata = addTag.ByteArrayValue;
                    var blockLight = sectionTag["BlockLight"].ByteArrayValue;
                    var skyLight = sectionTag["SkyLight"].ByteArrayValue;

                    for (var x = 0; x < 16; x++)
                    {
                        for (var z = 0; z < 16; z++)
                        {
                            for (var y = 0; y < 16; y++)
                            {
                                var yi = sy + y - _waterOffsetY;
                                if (yi < 0 || yi >= 256) continue;

                                var anvilIndex = y*16*16 + z*16 + x;
                                var blockId = blocks[anvilIndex] + (Nibble4(adddata, anvilIndex) << 8);

                                var b = BlockFactory.GetBlockById((ushort) blockId);
                                b.Metadata = Nibble4(data, anvilIndex);
                                chunk.SetBlock(x, yi, z, b);
                                chunk.SetBlocklight(x, yi, z, Nibble4(blockLight, anvilIndex));
                                chunk.SetSkylight(x, yi, z, Nibble4(skyLight, anvilIndex));
                            }
                        }
                    }
                }

                var entities = dataTag["Entities"] as NbtList;
                var tileEntities = dataTag["TileEntities"] as NbtList;

                if (tileEntities != null)
                {
                    foreach (var nbtTag in tileEntities)
                    {
                        var blockEntityTag = (NbtCompound)nbtTag;
                        string entityId = blockEntityTag["id"].StringValue;
                        int x = blockEntityTag["x"].IntValue;
                        int y = blockEntityTag["y"].IntValue - _waterOffsetY;
                        int z = blockEntityTag["z"].IntValue;
                        blockEntityTag["y"] = new NbtInt("y", y);

                        TileEntity blockEntity = TileEntityFactory.GetBlockEntityById(entityId);
                        if (blockEntity != null)
                        {
                            blockEntityTag.Name = string.Empty;
                            chunk.SetBlockEntity(new Vector3(x, y, z), blockEntityTag);
                        }
                    }
                }

                var tileTicks = dataTag["TileTicks"] as NbtList;

                chunk.IsDirty = false;
                return chunk;
            }
        }
Пример #3
0
        public static ChunkColumn GetChunk(ChunkCoordinates coordinates, string basePath, IWorldProvider generator, int yoffset)
        {
            int width = 32;
            int depth = 32;

            int rx = coordinates.X >> 5;
            int rz = coordinates.Z >> 5;

            string filePath = Path.Combine(basePath, string.Format(@"region\r.{0}.{1}.mca", rx, rz));

            if (!File.Exists(filePath)) return generator.GenerateChunkColumn(coordinates);

            using (var regionFile = File.OpenRead(filePath))
            {
                byte[] buffer = new byte[8192];

                regionFile.Read(buffer, 0, 8192);

                int xi = (coordinates.X%width);
                if (xi < 0) xi += 32;
                int zi = (coordinates.Z%depth);
                if (zi < 0) zi += 32;
                int tableOffset = (xi + zi*width)*4;

                regionFile.Seek(tableOffset, SeekOrigin.Begin);

                byte[] offsetBuffer = new byte[4];
                regionFile.Read(offsetBuffer, 0, 3);
                Array.Reverse(offsetBuffer);
                int offset = BitConverter.ToInt32(offsetBuffer, 0) << 4;

                int length = regionFile.ReadByte();

                if (offset == 0 || length == 0)
                {
                    return generator.GenerateChunkColumn(coordinates);
                }

                regionFile.Seek(offset, SeekOrigin.Begin);
                byte[] waste = new byte[4];
                regionFile.Read(waste, 0, 4);
                int compressionMode = regionFile.ReadByte();

                var nbt = new NbtFile();
                nbt.LoadFromStream(regionFile, NbtCompression.ZLib);

                NbtTag dataTag = nbt.RootTag["Level"];

                NbtList sections = dataTag["Sections"] as NbtList;

                ChunkColumn chunk = new ChunkColumn
                {
                    x = coordinates.X,
                    z = coordinates.Z,
                    biomeId = dataTag["Biomes"].ByteArrayValue
                };

                for (int i = 0; i < chunk.biomeId.Length; i++)
                {
                    if (chunk.biomeId[i] > 22) chunk.biomeId[i] = 0;
                }
                if (chunk.biomeId.Length > 256) throw new Exception();

                // This will turn into a full chunk column
                foreach (NbtTag sectionTag in sections)
                {
                    int sy = sectionTag["Y"].ByteValue*16;
                    byte[] blocks = sectionTag["Blocks"].ByteArrayValue;
                    byte[] data = sectionTag["Data"].ByteArrayValue;
                    NbtTag addTag = sectionTag["Add"];
                    byte[] adddata = new byte[2048];
                    if (addTag != null) adddata = addTag.ByteArrayValue;
                    byte[] blockLight = sectionTag["BlockLight"].ByteArrayValue;
                    byte[] skyLight = sectionTag["SkyLight"].ByteArrayValue;

                    for (int x = 0; x < 16; x++)
                    {
                        for (int z = 0; z < 16; z++)
                        {
                            for (int y = 0; y < 16; y++)
                            {
                                int yi = sy + y - yoffset;
                                if (yi < 0 || yi >= 128) continue;

                                int anvilIndex = y*16*16 + z*16 + x;
                                int blockId = blocks[anvilIndex] + (Nibble4(adddata, anvilIndex) << 8);

                                // Anvil to PE friendly converstion
                                if (blockId == 125) blockId = 5;
                                else if (blockId == 126) blockId = 158;
                                else if (blockId == 75) blockId = 50;
                                else if (blockId == 76) blockId = 50;
                                else if (blockId == 123) blockId = 89;
                                else if (blockId == 124) blockId = 89;
                                else if (blockId == 152) blockId = 73;
                                else if (_ignore.BinarySearch(blockId) >= 0) blockId = 0;
                                else if (_gaps.BinarySearch(blockId) >= 0)
                                {
                                    Debug.WriteLine("Missing material: " + blockId);
                                    blockId = 133;
                                }

                                if (blockId > 255) blockId = 41;

                                if (yi == 127 && blockId != 0) blockId = 30;
                                if (yi == 0 && (blockId == 8 || blockId == 9 /*|| blockId == 0*/)) blockId = 7;

                                //if (blockId != 0) blockId = 41;

                                chunk.SetBlock(x, yi, z, (byte) blockId);
                                chunk.SetMetadata(x, yi, z, Nibble4(data, anvilIndex));
                                chunk.SetBlocklight(x, yi, z, Nibble4(blockLight, anvilIndex));
                                chunk.SetSkylight(x, yi, z, Nibble4(skyLight, anvilIndex));
                            }
                        }
                    }
                }

                NbtList entities = dataTag["Entities"] as NbtList;
                NbtList blockEntities = dataTag["TileEntities"] as NbtList;
                if (blockEntities != null)
                {
                    foreach (var nbtTag in blockEntities)
                    {
                        var blockEntityTag = (NbtCompound) nbtTag;
                        string entityId = blockEntityTag["id"].StringValue;
                        int x = blockEntityTag["x"].IntValue;
                        int y = blockEntityTag["y"].IntValue - yoffset;
                        int z = blockEntityTag["z"].IntValue;
                        blockEntityTag["y"] = new NbtInt("y", y);

                        BlockEntity blockEntity = BlockEntityFactory.GetBlockEntityById(entityId);
                        if (blockEntity != null)
                        {
                            blockEntityTag.Name = string.Empty;
                            chunk.SetBlockEntity(new BlockCoordinates(x, y, z), blockEntityTag);
                        }
                    }
                }

                NbtList tileTicks = dataTag["TileTicks"] as NbtList;

                chunk.isDirty = false;
                return chunk;
            }
        }
Пример #4
0
        public void SetBlockLight(Block block)
        {
            ChunkColumn chunk = GetChunk(block.Coordinates);

            chunk.SetBlocklight(block.Coordinates.X & 0x0f, block.Coordinates.Y & 0xff, block.Coordinates.Z & 0x0f, block.BlockLight);
        }