예제 #1
0
        public void SkippingTagsOnFileLoad()
        {
            var loadedFile = new NbtFile();

            loadedFile.LoadFromFile("TestFiles/bigtest.nbt",
                                    NbtCompression.None,
                                    tag => tag.Name != "nested compound test");
            NbtCompound rootTag = (NbtCompound)loadedFile.RootTag;

            Assert.IsFalse(rootTag.Contains("nested compound test"));
            Assert.IsTrue(rootTag.Contains("listTest (long)"));

            loadedFile.LoadFromFile("TestFiles/bigtest.nbt",
                                    NbtCompression.None,
                                    tag => tag.TagType != NbtTagType.Float || tag.Parent.Name != "Level");
            rootTag = (NbtCompound)loadedFile.RootTag;
            Assert.IsFalse(rootTag.Contains("floatTest"));
            Assert.AreEqual(0.75f, rootTag["nested compound test"]["ham"]["value"].FloatValue);

            loadedFile.LoadFromFile("TestFiles/bigtest.nbt",
                                    NbtCompression.None,
                                    tag => tag.Name != "listTest (long)");
            rootTag = (NbtCompound)loadedFile.RootTag;
            Assert.IsFalse(rootTag.Contains("listTest (long)"));
            Assert.IsTrue(rootTag.Contains("byteTest"));

            loadedFile.LoadFromFile("TestFiles/bigtest.nbt",
                                    NbtCompression.None,
                                    tag => false);
            rootTag = (NbtCompound)loadedFile.RootTag;
            Assert.AreEqual(0, rootTag.Count);
        }
예제 #2
0
        static void ReadMetadata(NbtCompound root, Level lvl)
        {
            if (!root.Contains("CPE"))
            {
                return;
            }
            NbtCompound cpe = (NbtCompound)root["CPE"];

            if (cpe.Contains("EnvWeatherType"))
            {
                lvl.Config.Weather = cpe["EnvWeatherType"]["WeatherType"].ByteValue;
            }
            if (cpe.Contains("EnvMapAppearance"))
            {
                ParseEnvMapAppearance(cpe, lvl);
            }
            if (cpe.Contains("EnvColors"))
            {
                ParseEnvColors(cpe, lvl);
            }
            if (cpe.Contains("BlockDefinitions"))
            {
                ParseBlockDefinitions(cpe, lvl);
            }
        }
예제 #3
0
        public void AddingAndRemoving()
        {
            var test = new NbtCompound();

            var foo = new NbtInt("Foo");

            test.Add(foo);

            // adding duplicate object
            Assert.Throws <ArgumentException>(() => test.Add(foo));

            // adding duplicate name
            Assert.Throws <ArgumentException>(() => test.Add(new NbtByte("Foo")));

            // adding unnamed tag
            Assert.Throws <ArgumentException>(() => test.Add(new NbtInt()));

            // adding null
            Assert.Throws <ArgumentNullException>(() => test.Add(null));

            // contains existing name
            Assert.IsTrue(test.Contains("Foo"));

            // contains existing object
            Assert.IsTrue(test.Contains(foo));

            // contains non-existent name
            Assert.IsFalse(test.Contains("Bar"));

            // contains existing name / different object
            Assert.IsFalse(test.Contains(new NbtInt("Foo")));

            // removing non-existent name
            Assert.IsFalse(test.Remove("Bar"));

            // removing existing name
            Assert.IsTrue(test.Remove("Foo"));

            // removing non-existent name
            Assert.IsFalse(test.Remove("Foo"));

            // re-adding object
            test.Add(foo);

            // removing existing object
            Assert.IsTrue(test.Remove(foo));

            // clearing an empty NbtCompound
            Assert.AreEqual(test.Count, 0);
            test.Clear();

            // re-adding after clearing
            test.Add(foo);
            Assert.AreEqual(test.Count, 1);

            // clearing a non-empty NbtCompound
            test.Clear();
            Assert.AreEqual(test.Count, 0);
        }
예제 #4
0
        public void AddingAndRemoving()
        {
            NbtCompound test = new NbtCompound();

            NbtInt foo =  new NbtInt( "Foo" );

            test.Add( foo );

            // adding duplicate object
            Assert.Throws<ArgumentException>( () => test.Add( foo ) );

            // adding duplicate name
            Assert.Throws<ArgumentException>( () => test.Add( new NbtByte( "Foo" ) ) );

            // adding unnamed tag
            Assert.Throws<ArgumentException>( () => test.Add( new NbtInt() ) );

            // adding null
            Assert.Throws<ArgumentNullException>( () => test.Add( null ) );

            // contains existing name
            Assert.IsTrue( test.Contains( "Foo" ) );

            // contains existing object
            Assert.IsTrue( test.Contains( foo ) );

            // contains non-existent name
            Assert.IsFalse( test.Contains( "Bar" ) );

            // contains existing name / different object
            Assert.IsFalse( test.Contains( new NbtInt( "Foo" ) ) );

            // removing non-existent name
            Assert.IsFalse( test.Remove( "Bar" ) );

            // removing existing name
            Assert.IsTrue( test.Remove( "Foo" ) );

            // removing non-existent name
            Assert.IsFalse( test.Remove( "Foo" ) );

            // re-adding object
            test.Add( foo );

            // removing existing object
            Assert.IsTrue( test.Remove( foo ) );

            // clearing an empty NbtCompound
            Assert.AreEqual( test.Count, 0 );
            test.Clear();

            // re-adding after clearing
            test.Add( foo );
            Assert.AreEqual( test.Count, 1 );

            // clearing a non-empty NbtCompound
            test.Clear();
            Assert.AreEqual( test.Count, 0 );
        }
예제 #5
0
        static void ReadData(NbtCompound root, string name, out Level lvl)
        {
            if (root["FormatVersion"].ByteValue > 1)
            {
                throw new NotSupportedException("Only version 1 of ClassicWorld format is supported.");
            }

            short x = root["X"].ShortValue, y = root["Y"].ShortValue, z = root["Z"].ShortValue;

            if (x <= 0 || y <= 0 || z <= 0)
            {
                throw new InvalidDataException("Level dimensions must be > 0.");
            }

            lvl        = new Level(name, (ushort)x, (ushort)y, (ushort)z);
            lvl.blocks = root["BlockArray"].ByteArrayValue;
            ReadSpawn(root, lvl);

            #if TEN_BIT_BLOCKS
            // Can't use ConvertCustom, as that changes lvl.blocks
            // (aka the array containing the lower 8 bits of block ids)
            if (root.Contains("BlockArray2"))
            {
                ReadExtBlocks(root, lvl); return;
            }
            #endif
            ConvertCustom(lvl);
        }
예제 #6
0
        static void ReadData(NbtCompound root, string name, out Level lvl)
        {
            if (root["FormatVersion"].ByteValue > 1)
            {
                throw new NotSupportedException("Only version 1 of ClassicWorld format is supported.");
            }

            ushort width  = (ushort)root["X"].ShortValue;
            ushort height = (ushort)root["Y"].ShortValue;
            ushort length = (ushort)root["Z"].ShortValue;

            byte[] blocks = root["BlockArray"].ByteArrayValue;
            lvl = new Level(name, width, height, length, blocks);

            ReadSpawn(root, lvl);
            #if TEN_BIT_BLOCKS
            // Can't use ConvertCustom, as that changes lvl.blocks
            // (aka the array containing the lower 8 bits of block ids)
            if (root.Contains("BlockArray2"))
            {
                ReadExtBlocks(root, lvl); return;
            }
            #endif
            ConvertCustom(lvl);
        }
예제 #7
0
        void ReadData(NbtCompound root, string name, out Level lvl)
        {
            if (root["FormatVersion"].ByteValue > 1)
            {
                throw new NotSupportedException("Only version 1 of ClassicWorld format is supported.");
            }

            short x = root["X"].ShortValue, y = root["Y"].ShortValue, z = root["Z"].ShortValue;

            if (x <= 0 || y <= 0 || z <= 0)
            {
                throw new InvalidDataException("Level dimensions must be > 0.");
            }

            lvl        = new Level(name, (ushort)x, (ushort)y, (ushort)z);
            lvl.blocks = root["BlockArray"].ByteArrayValue;
            ConvertCustom(lvl);

            if (!root.Contains("Spawn"))
            {
                return;
            }
            NbtTag spawn = root["Spawn"];

            lvl.spawnx = (ushort)spawn["X"].ShortValue;
            lvl.spawny = (ushort)spawn["Y"].ShortValue;
            lvl.spawnz = (ushort)spawn["Z"].ShortValue;
            lvl.rotx   = spawn["H"].ByteValue;
            lvl.roty   = spawn["P"].ByteValue;
        }
예제 #8
0
        static void ParseEnvMapAppearance(NbtCompound cpe, Level lvl)
        {
            NbtCompound comp = (NbtCompound)cpe["EnvMapAppearance"];

            lvl.Config.HorizonBlock = Block.FromRaw(comp["EdgeBlock"].ByteValue);
            lvl.Config.EdgeBlock    = Block.FromRaw(comp["SideBlock"].ByteValue);
            lvl.Config.EdgeLevel    = comp["SideLevel"].ShortValue;

            if (lvl.Config.EdgeLevel == -1)
            {
                lvl.Config.EdgeLevel = (short)(lvl.Height / 2);
            }
            if (!comp.Contains("TextureURL"))
            {
                return;
            }

            string url = comp["TextureURL"].StringValue;

            if (url.CaselessEnds(".png"))
            {
                lvl.Config.Terrain = url == ServerConfig.DefaultTerrain ? "" : url;
            }
            else
            {
                lvl.Config.TexturePack = url == ServerConfig.DefaultTexture ? "" : url;
            }
        }
예제 #9
0
        /// <summary>
        /// Construct a piece from an NbtCompound containing the piece's data
        /// </summary>
        /// <param name="nbt">The NbtCompound conatining the piece's data</param>
        public Piece(NbtCompound nbt)
        {
            NbtCompound data;

            if (nbt.Contains("data")) //New NBT format
            {
                X    = nbt["x"].IntValue;
                Y    = nbt["y"].IntValue;
                data = (NbtCompound)nbt["data"];
                Key  = data["key"].StringValue;
            }
            else //Old NBT format
            {
                X    = nbt["spellPosX"].IntValue;
                Y    = nbt["spellPosY"].IntValue;
                data = (NbtCompound)nbt["spellData"];
                Key  = data["spellKey"].StringValue;
            }

            if (data.Contains("constantValue"))
            {
                ConstantValue = data["constantValue"].StringValue;
            }

            if (data.Contains("params"))
            {
                NbtCompound paramsTag = (NbtCompound)data["params"];
                Parameters = new Side[paramsTag.Count];
                int i = 0;
                foreach (NbtInt p in paramsTag)
                {
                    Parameters[i++] = (Side)p.IntValue;
                }
            }
        }
예제 #10
0
        static void ReadSpawn(NbtCompound root, Level lvl)
        {
            if (!root.Contains("Spawn"))
            {
                return;
            }
            NbtTag spawn = root["Spawn"];

            lvl.spawnx = (ushort)spawn["X"].ShortValue;
            lvl.spawny = (ushort)spawn["Y"].ShortValue;
            lvl.spawnz = (ushort)spawn["Z"].ShortValue;
            lvl.rotx   = spawn["H"].ByteValue;
            lvl.roty   = spawn["P"].ByteValue;
        }
예제 #11
0
        static string GetColor(NbtCompound comp, string type)
        {
            if (!comp.Contains(type))
            {
                return("");
            }
            NbtCompound rgb = (NbtCompound)comp[type];
            short       r = rgb["R"].ShortValue, g = rgb["G"].ShortValue, b = rgb["B"].ShortValue;

            if (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255)
            {
                return("");
            }
            return(r.ToString("X2") + g.ToString("X2") + b.ToString("X2"));
        }
예제 #12
0
        public static void SetNbt(NbtCompound compound, NbtTag value, params string[] path)
        {
            NbtCompound tag = compound;

            foreach (var item in path)
            {
                if (!tag.Contains(item))
                {
                    tag.Add(new NbtCompound(item));
                }
                tag = (NbtCompound)tag[item]; // exception if existing non-compound tag is present
            }
            if (tag.TryGet(value.Name, out NbtTag existing) && existing.TagType == value.TagType)
            {
                tag.Remove(value.Name);
            }
            tag.Add(value);
        }
예제 #13
0
        public ChunkColumn GetChunk(ChunkCoordinates coordinates, string basePath, IWorldGenerator generator)
        {
            try
            {
                int width = 32;
                int depth = 32;

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

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

                if (!File.Exists(filePath))
                {
                    var chunkColumn = generator?.GenerateChunkColumn(coordinates);
                    if (chunkColumn != null)
                    {
                        //chunkColumn.NeedSave = true;
                    }

                    return(chunkColumn);
                }

                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;

                    byte[] bytes = BitConverter.GetBytes(offset >> 4);
                    Array.Reverse(bytes);
                    if (offset != 0 && offsetBuffer[0] != bytes[0] && offsetBuffer[1] != bytes[1] && offsetBuffer[2] != bytes[2])
                    {
                        throw new Exception($"Not the same buffer\n{Package.HexDump(offsetBuffer)}\n{Package.HexDump(bytes)}");
                    }

                    int length = regionFile.ReadByte();

                    if (offset == 0 || length == 0)
                    {
                        var chunkColumn = generator?.GenerateChunkColumn(coordinates);
                        if (chunkColumn != null)
                        {
                            //chunkColumn.NeedSave = true;
                        }

                        return(chunkColumn);
                    }

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

                    if (compressionMode != 0x02)
                    {
                        throw new Exception($"CX={coordinates.X}, CZ={coordinates.Z}, NBT wrong compression. Expected 0x02, got 0x{compressionMode:X2}. " +
                                            $"Offset={offset}, length={length}\n{Package.HexDump(waste)}");
                    }

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

                    NbtCompound dataTag = (NbtCompound)nbt.RootTag["Level"];

                    bool isPocketEdition = false;
                    if (dataTag.Contains("MCPE BID"))
                    {
                        isPocketEdition = dataTag["MCPE BID"].ByteValue == 1;
                    }

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

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

                    if (chunk.biomeId.Length > 256)
                    {
                        throw new Exception();
                    }

                    NbtTag heights = dataTag["HeightMap"] as NbtIntArray;
                    if (heights != null)
                    {
                        int[] intHeights = heights.IntArrayValue;
                        for (int i = 0; i < 256; i++)
                        {
                            chunk.height[i] = (short)intHeights[i];
                        }
                    }

                    // This will turn into a full chunk column
                    foreach (NbtTag sectionTag in sections)
                    {
                        ReadSection(sectionTag, chunk, !isPocketEdition);
                    }

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

                            if (entityId.StartsWith("minecraft:"))
                            {
                                var id = entityId.Split(':')[1];

                                entityId = id.First().ToString().ToUpper() + id.Substring(1);

                                blockEntityTag["id"] = new NbtString("id", entityId);
                            }

                            BlockEntity blockEntity = BlockEntityFactory.GetBlockEntityById(entityId);

                            if (blockEntity != null)
                            {
                                blockEntityTag.Name = string.Empty;

                                if (blockEntity is Sign)
                                {
                                    // Remove the JSON stuff and get the text out of extra data.
                                    // TAG_String("Text2"): "{"extra":["10c a loaf!"],"text":""}"
                                    CleanSignText(blockEntityTag, "Text1");
                                    CleanSignText(blockEntityTag, "Text2");
                                    CleanSignText(blockEntityTag, "Text3");
                                    CleanSignText(blockEntityTag, "Text4");
                                }
                                else if (blockEntity is ChestBlockEntity)
                                {
                                    NbtList items = (NbtList)blockEntityTag["Items"];

                                    if (items != null)
                                    {
                                        //for (byte i = 0; i < items.Count; i++)
                                        //{
                                        //	NbtCompound item = (NbtCompound) items[i];

                                        //	item.Add(new NbtShort("OriginalDamage", item["Damage"].ShortValue));

                                        //	byte metadata = (byte) (item["Damage"].ShortValue & 0xff);
                                        //	item.Remove("Damage");
                                        //	item.Add(new NbtByte("Damage", metadata));
                                        //}
                                    }
                                }

                                chunk.SetBlockEntity(new BlockCoordinates(x, y, z), blockEntityTag);
                            }
                            else
                            {
                                if (Log.IsDebugEnabled)
                                {
                                    Log.Debug($"Loaded unknown block entity: {blockEntityTag}");
                                }
                            }
                        }
                    }

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

                    chunk.isDirty  = false;
                    chunk.NeedSave = false;
                    return(chunk);
                }
            }
            catch (Exception e)
            {
                Log.Error($"Loading chunk {coordinates}", e);
                var chunkColumn = generator?.GenerateChunkColumn(coordinates);
                if (chunkColumn != null)
                {
                    //chunkColumn.NeedSave = true;
                }

                return(chunkColumn);
            }
        }
예제 #14
0
        public ChunkColumn GetChunk(ChunkCoordinates coordinates, string basePath, IWorldGenerator generator)
        {
            try
            {
                const int width = 32;
                const int depth = 32;

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

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

                if (!File.Exists(filePath))
                {
                    var chunkColumn = generator?.GenerateChunkColumn(coordinates);
                    if (chunkColumn != null)
                    {
                        //SkyLightBlockAccess blockAccess = new SkyLightBlockAccess(this, chunkColumn);
                        //new SkyLightCalculations().RecalcSkyLight(chunkColumn, blockAccess);
                    }

                    return(chunkColumn);
                }

                using (var regionFile = File.OpenRead(filePath))
                {
                    int locationIndex = ((coordinates.X & (width - 1)) + (coordinates.Z & (depth - 1)) * width) << 2;
                    regionFile.Seek(locationIndex, SeekOrigin.Begin);

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

                    int sectorCount = regionFile.ReadByte();

                    if (offset == 0 || sectorCount == 0)
                    {
                        var chunkColumn = generator?.GenerateChunkColumn(coordinates);
                        if (chunkColumn != null)
                        {
                            chunkColumn.NeedSave = true;
                        }

                        return(chunkColumn);
                    }

                    /*regionFile.Seek(4096 + locationIndex, SeekOrigin.Begin);
                     * regionFile.Read(offsetBuffer, 0, 4);
                     * Array.Reverse(offsetBuffer);
                     * int lastModified = BitConverter.ToInt32(offsetBuffer, 0);
                     * Log.Warn("Last modified: " + lastModified);*/

                    regionFile.Seek(offset + 4, SeekOrigin.Begin);                     //Offset + the length header

                    int compressionMode = regionFile.ReadByte();

                    if (compressionMode != 0x02)
                    {
                        throw new Exception($"CX={coordinates.X}, CZ={coordinates.Z}, NBT wrong compression. Expected 0x02, got 0x{compressionMode:X2}. " +
                                            $"Offset={offset}, Sectors={sectorCount}");
                    }

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

                    NbtCompound dataTag = (NbtCompound)nbt.RootTag["Level"];

                    bool isPocketEdition = false;
                    if (dataTag.Contains("MCPE BID"))
                    {
                        isPocketEdition = dataTag["MCPE BID"].ByteValue == 1;
                    }

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

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

                    if (chunk.biomeId.Length > 256)
                    {
                        throw new Exception();
                    }

                    NbtTag heights = dataTag["HeightMap"] as NbtIntArray;
                    if (heights != null)
                    {
                        int[] intHeights = heights.IntArrayValue;
                        for (int i = 0; i < 256; i++)
                        {
                            chunk.height[i] = (short)intHeights[i];
                        }
                    }

                    // This will turn into a full chunk column
                    foreach (NbtTag sectionTag in sections)
                    {
                        ReadSection(sectionTag, chunk, !isPocketEdition);
                    }

                    NbtList entities = dataTag["Entities"] as NbtList;
                    if (entities != null)
                    {
                        chunk.Entities = entities.ToArray <NbtCompound>();
                    }

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

                            if (entityId.StartsWith("minecraft:"))
                            {
                                var id = entityId.Split(':')[1];

                                entityId = id.First().ToString().ToUpper() + id.Substring(1);

                                blockEntityTag["id"] = new NbtString("id", entityId);
                            }

                            BlockEntity blockEntity = BlockEntityFactory.GetBlockEntityById(entityId);

                            if (blockEntity != null)
                            {
                                blockEntityTag.Name = string.Empty;

                                if (blockEntity is Sign)
                                {
                                    // Remove the JSON stuff and get the text out of extra data.
                                    // TAG_String("Text2"): "{"extra":["10c a loaf!"],"text":""}"
                                    CleanSignText(blockEntityTag, "Text1");
                                    CleanSignText(blockEntityTag, "Text2");
                                    CleanSignText(blockEntityTag, "Text3");
                                    CleanSignText(blockEntityTag, "Text4");
                                }
                                else if (blockEntity is ChestBlockEntity)
                                {
                                    NbtList items = (NbtList)blockEntityTag["Items"];

                                    if (items != null)
                                    {
                                        //for (byte i = 0; i < items.Count; i++)
                                        //{
                                        //	NbtCompound item = (NbtCompound) items[i];

                                        //	item.Add(new NbtShort("OriginalDamage", item["Damage"].ShortValue));

                                        //	byte metadata = (byte) (item["Damage"].ShortValue & 0xff);
                                        //	item.Remove("Damage");
                                        //	item.Add(new NbtByte("Damage", metadata));
                                        //}
                                    }
                                }

                                chunk.SetBlockEntity(new BlockCoordinates(x, y, z), blockEntityTag);
                            }
                            else
                            {
                                if (Log.IsDebugEnabled)
                                {
                                    Log.Debug($"Loaded unknown block entity: {blockEntityTag}");
                                }
                            }
                        }
                    }

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

                    chunk.RecalcHeight();

                    chunk.isDirty  = false;
                    chunk.NeedSave = false;

                    if (Config.GetProperty("CalculateLights", false))
                    {
                        SkyLightBlockAccess blockAccess = new SkyLightBlockAccess(this, chunk);
                        new SkyLightCalculations().RecalcSkyLight(chunk, blockAccess);
                        //TODO: Block lights.
                    }

                    return(chunk);
                }
            }
            catch (Exception e)
            {
                Log.Error($"Loading chunk {coordinates}", e);
                var chunkColumn = generator?.GenerateChunkColumn(coordinates);
                if (chunkColumn != null)
                {
                    //chunkColumn.NeedSave = true;
                }

                return(chunkColumn);
            }
        }
예제 #15
0
    public void AddingAndRemoving()
    {
        var foo  = new NbtInt("Foo");
        var test = new NbtCompound {
            foo
        };

        // adding duplicate object
        Assert.Throws <ArgumentException>(() => test.Add(foo));

        // adding duplicate name
        Assert.Throws <ArgumentException>(() => test.Add(new NbtByte("Foo")));

        // adding unnamed tag
        Assert.Throws <ArgumentException>(() => test.Add(new NbtInt()));

        // adding null
        Assert.Throws <ArgumentNullException>(() => test.Add(null));

        // adding tag to self
        Assert.Throws <ArgumentException>(() => test.Add(test));

        // contains existing name/object
        Assert.True(test.Contains("Foo"));
        Assert.Contains(foo, test);
        Assert.Throws <ArgumentNullException>(() => test.Contains((string)null));
        Assert.Throws <ArgumentNullException>(() => test.Contains((NbtTag)null));

        // contains non-existent name
        Assert.False(test.Contains("Bar"));

        // contains existing name / different object
        Assert.DoesNotContain(new NbtInt("Foo"), test);

        // removing non-existent name
        Assert.Throws <ArgumentNullException>(() => test.Remove((string)null));
        Assert.False(test.Remove("Bar"));

        // removing existing name
        Assert.True(test.Remove("Foo"));

        // removing non-existent name
        Assert.False(test.Remove("Foo"));

        // re-adding object
        test.Add(foo);

        // removing existing object
        Assert.Throws <ArgumentNullException>(() => test.Remove((NbtTag)null));
        Assert.True(test.Remove(foo));
        Assert.False(test.Remove(foo));

        // clearing an empty NbtCompound
        Assert.Empty(test);
        test.Clear();

        // re-adding after clearing
        test.Add(foo);
        Assert.Single(test);

        // clearing a non-empty NbtCompound
        test.Clear();
        Assert.Empty(test);
    }
        public void AddingAndRemoving()
        {
            var foo = new NbtInt("Foo");
            var test = new NbtCompound
            {
                foo
            };

            // adding duplicate object
            Assert.Throws<ArgumentException>(() => test.Add(foo));

            // adding duplicate name
            Assert.Throws<ArgumentException>(() => test.Add(new NbtByte("Foo")));

            // adding unnamed tag
            Assert.Throws<ArgumentException>(() => test.Add(new NbtInt()));

            // adding null
            Assert.Throws<ArgumentNullException>(() => test.Add(null));

            // adding tag to self
            Assert.Throws<ArgumentException>(() => test.Add(test));

            // contains existing name/object
            Assert.True(test.Contains("Foo"));
            Assert.True(test.Contains(foo));
            Assert.Throws<ArgumentNullException>(() => test.Contains((string) null));
            Assert.Throws<ArgumentNullException>(() => test.Contains((NbtTag) null));

            // contains non-existent name
            Assert.False(test.Contains("Bar"));

            // contains existing name / different object
            Assert.False(test.Contains(new NbtInt("Foo")));

            // removing non-existent name
            Assert.Throws<ArgumentNullException>(() => test.Remove((string) null));
            Assert.False(test.Remove("Bar"));

            // removing existing name
            Assert.True(test.Remove("Foo"));

            // removing non-existent name
            Assert.False(test.Remove("Foo"));

            // re-adding object
            test.Add(foo);

            // removing existing object
            Assert.Throws<ArgumentNullException>(() => test.Remove((NbtTag) null));
            Assert.True(test.Remove(foo));
            Assert.False(test.Remove(foo));

            // clearing an empty NbtCompound
            Assert.Equal(0, test.Count);
            test.Clear();

            // re-adding after clearing
            test.Add(foo);
            Assert.Equal(1, test.Count);

            // clearing a non-empty NbtCompound
            test.Clear();
            Assert.Equal(0, test.Count);
        }
예제 #17
0
        static void ParseBlockDefinitions(NbtCompound cpe, Level lvl)
        {
            NbtCompound blocks       = (NbtCompound)cpe["BlockDefinitions"];
            bool        hasBlockDefs = false;

            foreach (NbtTag tag in blocks)
            {
                if (tag.TagType != NbtTagType.Compound)
                {
                    continue;
                }

                NbtCompound     props = (NbtCompound)tag;
                BlockDefinition def   = new BlockDefinition();
                def.RawID = props["ID"].ByteValue;
                // can't change "ID" to short since backwards compatibility
                if (props.Contains("ID2"))
                {
                    def.RawID = (ushort)props["ID2"].ShortValue;
                }

                def.Name        = props["Name"].StringValue;
                def.CollideType = props["CollideType"].ByteValue;
                def.Speed       = props["Speed"].FloatValue;

                def.BlocksLight = props["TransmitsLight"].ByteValue == 0;
                def.WalkSound   = props["WalkSound"].ByteValue;
                def.FullBright  = props["FullBright"].ByteValue != 0;
                def.Shape       = props["Shape"].ByteValue;
                def.BlockDraw   = props["BlockDraw"].ByteValue;

                byte[] fog = props["Fog"].ByteArrayValue;
                def.FogDensity = fog[0];
                // Fix for older ClassicalSharp versions which saved wrong value for density = 0
                if (def.FogDensity == 0xFF)
                {
                    def.FogDensity = 0;
                }
                def.FogR = fog[1]; def.FogG = fog[2]; def.FogB = fog[3];

                byte[] tex = props["Textures"].ByteArrayValue;
                ImportTexs(def, tex, 0);
                if (tex.Length > 6)
                {
                    ImportTexs(def, tex, 6);
                }

                byte[] coords = props["Coords"].ByteArrayValue;
                def.MinX = coords[0]; def.MinZ = coords[1]; def.MinY = coords[2];
                def.MaxX = coords[3]; def.MaxZ = coords[4]; def.MaxY = coords[5];

                BlockID block = def.GetBlock();
                if (block >= Block.ExtendedCount)
                {
                    Logger.Log(LogType.Warning, "Cannot import custom block {0} (ID {1})",
                               def.Name, def.RawID);
                    continue;
                }

                // Don't define level custom block if same as global custom block
                BlockDefinition globalDef = BlockDefinition.GlobalDefs[block];
                if (PropsEquals(def, globalDef))
                {
                    continue;
                }

                lvl.UpdateCustomBlock(block, def);
                hasBlockDefs = true;
            }

            if (hasBlockDefs)
            {
                BlockDefinition.Save(false, lvl);
            }
        }