diff --git a/NBToolkit/NBToolkit/Map/Block.cs b/NBToolkit/NBToolkit/Map/Block.cs index 40baf9a..bc646a4 100644 --- a/NBToolkit/NBToolkit/Map/Block.cs +++ b/NBToolkit/NBToolkit/Map/Block.cs @@ -26,9 +26,19 @@ namespace NBToolkit.Map get { return _id; } set { - if (BlockInfo.SchemaTable[_id] != BlockInfo.SchemaTable[value]) { - _tileEntity = null; + BlockInfoEx info1 = BlockInfo.BlockTable[_id] as BlockInfoEx; + BlockInfoEx info2 = BlockInfo.BlockTable[value] as BlockInfoEx; + + if (info1 != info2) { + if (info1 != null) { + _tileEntity = null; + } + + if (info2 != null) { + _tileEntity = TileEntityFactory.Create(info2.TileEntityName); + } } + _id = value; } } @@ -86,12 +96,12 @@ namespace NBToolkit.Map public bool SetTileEntity (TileEntity te) { - NBTCompoundNode schema = BlockInfo.SchemaTable[_id]; - if (schema == null) { + BlockInfoEx info = BlockInfo.BlockTable[_id] as BlockInfoEx; + if (info == null) { return false; } - if (te.Verify(schema) == false) { + if (te.GetType() != TileEntityFactory.Lookup(info.TileEntityName)) { return false; } diff --git a/NBToolkit/NBToolkit/Map/BlockInfo.cs b/NBToolkit/NBToolkit/Map/BlockInfo.cs index 18abbb7..266537e 100644 --- a/NBToolkit/NBToolkit/Map/BlockInfo.cs +++ b/NBToolkit/NBToolkit/Map/BlockInfo.cs @@ -110,8 +110,6 @@ namespace NBToolkit.Map private static int[] _opacityTable; private static int[] _luminanceTable; - protected internal static NBTCompoundNode[] _schemaTable; - public class ItemCache { private T[] _cache; @@ -261,9 +259,9 @@ namespace NBToolkit.Map public static BlockInfo Glass; public static BlockInfo LapisOre; public static BlockInfo LapisBlock; - public static TileEntityBlockInfo Dispenser; + public static BlockInfoEx Dispenser; public static BlockInfo Sandstone; - public static TileEntityBlockInfo NoteBlock; + public static BlockInfoEx NoteBlock; public static BlockInfo Bed; public static BlockInfo Wool; public static BlockInfo YellowFlower; @@ -281,23 +279,23 @@ namespace NBToolkit.Map public static BlockInfo Obsidian; public static BlockInfo Torch; public static BlockInfo Fire; - public static TileEntityBlockInfo MonsterSpawner; + public static BlockInfoEx MonsterSpawner; public static BlockInfo WoodStairs; - public static TileEntityBlockInfo Chest; + public static BlockInfoEx Chest; public static BlockInfo RedstoneWire; public static BlockInfo DiamondOre; public static BlockInfo DiamondBlock; public static BlockInfo CraftTable; public static BlockInfo Crops; public static BlockInfo Farmland; - public static TileEntityBlockInfo Furnace; - public static TileEntityBlockInfo BurningFurnace; - public static TileEntityBlockInfo SignPost; + public static BlockInfoEx Furnace; + public static BlockInfoEx BurningFurnace; + public static BlockInfoEx SignPost; public static BlockInfo WoodDoor; public static BlockInfo Ladder; public static BlockInfo Rails; public static BlockInfo CobbleStairs; - public static TileEntityBlockInfo WallSign; + public static BlockInfoEx WallSign; public static BlockInfo Lever; public static BlockInfo StonePlate; public static BlockInfo IronDoor; @@ -330,12 +328,10 @@ namespace NBToolkit.Map _blockTable = new BlockInfo[MAX_BLOCKS]; _opacityTable = new int[MAX_BLOCKS]; _luminanceTable = new int[MAX_BLOCKS]; - _schemaTable = new NBTCompoundNode[MAX_BLOCKS]; BlockTable = new ItemCache(_blockTable); OpacityTable = new ItemCache(_opacityTable); LuminanceTable = new ItemCache(_luminanceTable); - SchemaTable = new ItemCache(_schemaTable); Air = new BlockInfo(0, "Air").SetOpacity(0); Stone = new BlockInfo(1, "Stone"); @@ -360,9 +356,9 @@ namespace NBToolkit.Map Glass = new BlockInfo(20, "Glass").SetOpacity(0); LapisOre = new BlockInfo(21, "Lapis Lazuli Ore"); LapisBlock = new BlockInfo(22, "Lapis Lazuli Block"); - Dispenser = new TileEntityBlockInfo(23, "Dispenser"); + Dispenser = new BlockInfoEx(23, "Dispenser"); Sandstone = new BlockInfo(24, "Sandstone"); - NoteBlock = new TileEntityBlockInfo(25, "Note Block"); + NoteBlock = new BlockInfoEx(25, "Note Block"); Bed = new BlockInfo(26, "Bed").SetOpacity(0); Wool = new BlockInfo(35, "Wool"); YellowFlower = new BlockInfo(37, "Yellow Flower").SetOpacity(0); @@ -380,23 +376,23 @@ namespace NBToolkit.Map Obsidian = new BlockInfo(49, "Obsidian"); Torch = new BlockInfo(50, "Torch").SetOpacity(0).SetLuminance(MAX_LUMINANCE - 1); Fire = new BlockInfo(51, "Fire").SetOpacity(0).SetLuminance(MAX_LUMINANCE); - MonsterSpawner = (TileEntityBlockInfo)new TileEntityBlockInfo(52, "Monster Spawner").SetOpacity(0); + MonsterSpawner = (BlockInfoEx)new BlockInfoEx(52, "Monster Spawner").SetOpacity(0); WoodStairs = new BlockInfo(53, "Wooden Stairs").SetOpacity(0); - Chest = new TileEntityBlockInfo(54, "Chest"); + Chest = new BlockInfoEx(54, "Chest"); RedstoneWire = new BlockInfo(55, "Redstone Wire").SetOpacity(0); DiamondOre = new BlockInfo(56, "Diamond Ore"); DiamondBlock = new BlockInfo(57, "Diamond Block"); CraftTable = new BlockInfo(58, "Crafting Table"); Crops = new BlockInfo(59, "Crops").SetOpacity(0); Farmland = new BlockInfo(60, "Farmland").SetOpacity(0); - Furnace = new TileEntityBlockInfo(61, "Furnace"); - BurningFurnace = (TileEntityBlockInfo)new TileEntityBlockInfo(62, "Burning Furnace").SetLuminance(MAX_LUMINANCE - 1); - SignPost = (TileEntityBlockInfo)new TileEntityBlockInfo(63, "Sign Post").SetOpacity(0); + Furnace = new BlockInfoEx(61, "Furnace"); + BurningFurnace = (BlockInfoEx)new BlockInfoEx(62, "Burning Furnace").SetLuminance(MAX_LUMINANCE - 1); + SignPost = (BlockInfoEx)new BlockInfoEx(63, "Sign Post").SetOpacity(0); WoodDoor = new BlockInfo(64, "Wooden Door").SetOpacity(0); Ladder = new BlockInfo(65, "Ladder").SetOpacity(0); Rails = new BlockInfo(66, "Rails").SetOpacity(0); CobbleStairs = new BlockInfo(67, "Cobblestone Stairs").SetOpacity(0); - WallSign = (TileEntityBlockInfo)new TileEntityBlockInfo(68, "Wall Sign").SetOpacity(0); + WallSign = (BlockInfoEx)new BlockInfoEx(68, "Wall Sign").SetOpacity(0); Lever = new BlockInfo(69, "Lever").SetOpacity(0); StonePlate = new BlockInfo(70, "Stone Pressure Plate").SetOpacity(0); IronDoor = new BlockInfo(71, "Iron Door").SetOpacity(0); @@ -432,14 +428,14 @@ namespace NBToolkit.Map // Set Tile Entity Data - Dispenser.SetTileEntity("Trap", TileEntity.TrapSchema); - NoteBlock.SetTileEntity("Music", TileEntity.MusicSchema); - MonsterSpawner.SetTileEntity("MonsterSpawner", TileEntity.MobSpawnerSchema); - Chest.SetTileEntity("Chest", TileEntity.ChestSchema); - Furnace.SetTileEntity("Furnace", TileEntity.FurnaceSchema); - BurningFurnace.SetTileEntity("Furnace", TileEntity.FurnaceSchema); - SignPost.SetTileEntity("Sign", TileEntity.SignSchema); - WallSign.SetTileEntity("Sign", TileEntity.SignSchema); + Dispenser.SetTileEntity("Trap"); + NoteBlock.SetTileEntity("Music"); + MonsterSpawner.SetTileEntity("MobSpawner"); + Chest.SetTileEntity("Chest"); + Furnace.SetTileEntity("Furnace"); + BurningFurnace.SetTileEntity("Furnace"); + SignPost.SetTileEntity("Sign"); + WallSign.SetTileEntity("Sign"); // Set Data Limits @@ -482,29 +478,21 @@ namespace NBToolkit.Map } } - public class TileEntityBlockInfo : BlockInfo + public class BlockInfoEx : BlockInfo { private string _tileEntityName; - private NBTSchemaNode _tileEntitySchema; public string TileEntityName { get { return _tileEntityName; } } - public NBTSchemaNode TileEntitySchema - { - get { return _tileEntitySchema; } - } + public BlockInfoEx (int id) : base(id) { } - public TileEntityBlockInfo (int id) : base(id) { } + public BlockInfoEx (int id, string name) : base(id, name) { } - public TileEntityBlockInfo (int id, string name) : base(id, name) { } - - public BlockInfo SetTileEntity (string name, NBTCompoundNode schema) { + public BlockInfo SetTileEntity (string name) { _tileEntityName = name; - _tileEntitySchema = schema; - _schemaTable[ID] = schema; return this; } } diff --git a/NBToolkit/NBToolkit/Map/BlockInterface.cs b/NBToolkit/NBToolkit/Map/BlockInterface.cs index 1facac9..72cbb86 100644 --- a/NBToolkit/NBToolkit/Map/BlockInterface.cs +++ b/NBToolkit/NBToolkit/Map/BlockInterface.cs @@ -49,4 +49,14 @@ namespace NBToolkit.Map bool SetTileEntity (int lx, int ly, int lz, TileEntity te); bool ClearTileEntity (int lx, int ly, int lz); } + + public interface IEntity + { + + } + + public interface IEntityCollection + { + List FindAll (Predicate match); + } } diff --git a/NBToolkit/NBToolkit/Map/Chunk.cs b/NBToolkit/NBToolkit/Map/Chunk.cs index 60882d9..5b1e8fd 100644 --- a/NBToolkit/NBToolkit/Map/Chunk.cs +++ b/NBToolkit/NBToolkit/Map/Chunk.cs @@ -5,9 +5,28 @@ namespace NBToolkit.Map { using NBT; using Utility; + using System.Collections.Generic; - public class Chunk : IChunk, ICopyable + public class Chunk : IChunk, INBTObject, ICopyable { + public static NBTCompoundNode LevelSchema = new NBTCompoundNode() + { + new NBTCompoundNode("Level") + { + new NBTArrayNode("Blocks", 32768), + new NBTArrayNode("Data", 16384), + new NBTArrayNode("SkyLight", 16384), + new NBTArrayNode("BlockLight", 16384), + new NBTArrayNode("HeightMap", 256), + new NBTListNode("Entities", NBT_Type.TAG_COMPOUND), + new NBTListNode("TileEntities", NBT_Type.TAG_COMPOUND, TileEntity.BaseSchema), + new NBTScalerNode("LastUpdate", NBT_Type.TAG_LONG), + new NBTScalerNode("xPos", NBT_Type.TAG_INT), + new NBTScalerNode("zPos", NBT_Type.TAG_INT), + new NBTScalerNode("TerrainPopulated", NBT_Type.TAG_BYTE), + }, + }; + private NBT_Tree _tree; private int _cx; @@ -22,6 +41,8 @@ namespace NBToolkit.Map protected NBT_List _entities; protected NBT_List _tileEntities; + protected Dictionary _tileEntityTable; + public int X { get { return _cx; } @@ -49,39 +70,15 @@ namespace NBToolkit.Map _cz = z; BuildNBTTree(); + + BuildTileEntityCache(); } public Chunk (NBT_Tree tree) { - _tree = tree; - if (new ChunkVerifier(tree).Verify() == false) { - throw new MalformedNBTTreeException(); + if (LoadTreeSafe(tree.Root) == null) { + throw new InvalidNBTObjectException(); } - - NBT_Compound level = tree.Root["Level"] as NBT_Compound; - - _blocks = level["Blocks"] as NBT_ByteArray; - _data = new NibbleArray(level["Data"].ToNBTByteArray().Data); - _blockLight = new NibbleArray(level["BlockLight"].ToNBTByteArray().Data); - _skyLight = new NibbleArray(level["SkyLight"].ToNBTByteArray().Data); - _heightMap = level["HeightMap"] as NBT_ByteArray; - - _entities = level["Entities"] as NBT_List; - _tileEntities = level["TileEntities"] as NBT_List; - - // List-type patch up - if (_entities.Count == 0) { - level["Entities"] = new NBT_List(NBT_Type.TAG_COMPOUND); - _entities = level["Entities"] as NBT_List; - } - - if (_tileEntities.Count == 0) { - level["TileEntities"] = new NBT_List(NBT_Type.TAG_COMPOUND); - _tileEntities = level["TileEntities"] as NBT_List; - } - - _cx = level["xPos"].ToNBTInt(); - _cz = level["zPos"].ToNBTInt(); } private void BuildNBTTree () @@ -211,13 +208,32 @@ namespace NBToolkit.Map public bool SetBlockID (int lx, int ly, int lz, int id) { int index = lx << 11 | lz << 7 | ly; - if (_blocks.Data[index] == id) { + int oldid = _blocks.Data[index]; + + if (oldid == id) { return false; } + // Update value + + _blocks.Data[index] = (byte)id; + // Update tile entities - if (BlockInfo.SchemaTable[_blocks[index]] != BlockInfo.SchemaTable[id]) { + BlockInfoEx info1 = BlockInfo.BlockTable[oldid] as BlockInfoEx; + BlockInfoEx info2 = BlockInfo.BlockTable[id] as BlockInfoEx; + + if (info1 != info2) { + if (info1 != null) { + ClearTileEntity(lx, ly, lz); + } + + if (info2 != null) { + CreateTileEntity(lx, ly, lz); + } + } + + /*if (BlockInfo.SchemaTable[_blocks[index]] != BlockInfo.SchemaTable[id]) { if (BlockInfo.SchemaTable[_blocks[index]] != null) { ClearTileEntity(lx, ly, lz); } @@ -229,7 +245,7 @@ namespace NBToolkit.Map te.Z = BlockGlobalZ(lz); _tileEntities.Add(te.Root); } - } + }*/ // Update height map @@ -250,9 +266,6 @@ namespace NBToolkit.Map } } - // Update value - - _blocks.Data[index] = (byte)id; return true; } @@ -324,55 +337,92 @@ namespace NBToolkit.Map return _heightMap[lz << 4 | lx]; } + private void CreateTileEntity (int lx, int ly, int lz) + { + BlockInfoEx info = GetBlockInfo(lx, ly, lz) as BlockInfoEx; + if (info == null) { + return; + } + + TileEntity te = TileEntityFactory.Create(info.TileEntityName); + if (te == null) { + return; + } + + te.X = BlockGlobalX(lx); + te.Y = BlockGlobalY(ly); + te.Z = BlockGlobalZ(lz); + + _tileEntities.Add(te.BuildTree()); + } + public TileEntity GetTileEntity (int lx, int ly, int lz) { int x = BlockGlobalX(lx); int y = BlockGlobalY(ly); int z = BlockGlobalZ(lz); - foreach (NBT_Compound te in _tileEntities) { - if (te["x"].ToNBTInt().Data == x && - te["y"].ToNBTInt().Data == y && - te["z"].ToNBTInt().Data == z) { - return new TileEntity(te); - } + BlockKey key = new BlockKey(x, y, z); + NBT_Compound te; + + if (!_tileEntityTable.TryGetValue(key, out te)) { + return null; } - return null; + return TileEntityFactory.Create(te); } public bool SetTileEntity (int lx, int ly, int lz, TileEntity te) { - int id = GetBlockID(lx, ly, lz); - - NBTCompoundNode schema = BlockInfo.SchemaTable[id]; - if (schema == null) { + BlockInfoEx info = GetBlockInfo(lx, ly, lz) as BlockInfoEx; + if (info == null) { return false; } - if (!te.Verify(schema)) { + if (te.GetType() != TileEntityFactory.Lookup(info.TileEntityName)) { return false; } - ClearTileEntity(lx, ly, lz); + int x = BlockGlobalX(lx); + int y = BlockGlobalY(ly); + int z = BlockGlobalZ(lz); - te.X = BlockGlobalX(lx); - te.Y = BlockGlobalY(ly); - te.Z = BlockGlobalZ(lz); + BlockKey key = new BlockKey(x, y, z); + NBT_Compound oldte; - _tileEntities.Add(te.Root); + if (_tileEntityTable.TryGetValue(key, out oldte)) { + _tileEntities.Remove(oldte); + } + + te.X = x; + te.Y = y; + te.Z = z; + + NBT_Compound tree = te.BuildTree() as NBT_Compound; + + _tileEntities.Add(tree); + _tileEntityTable[key] = tree; return true; } public bool ClearTileEntity (int lx, int ly, int lz) { - TileEntity te = GetTileEntity(lx, ly, lz); - if (te == null) { + int x = BlockGlobalX(lx); + int y = BlockGlobalY(ly); + int z = BlockGlobalZ(lz); + + BlockKey key = new BlockKey(x, y, z); + NBT_Compound te; + + if (!_tileEntityTable.TryGetValue(key, out te)) { return false; } - return _tileEntities.Remove(te.Root); + _tileEntities.Remove(te); + _tileEntityTable.Remove(key); + + return true; } public virtual void SetLocation (int x, int z) @@ -383,9 +433,20 @@ namespace NBToolkit.Map _cx = x; _cz = z; + BuildTileEntityCache(); + } + + private void BuildTileEntityCache () + { + _tileEntityTable = new Dictionary(); + foreach (NBT_Compound te in _tileEntities) { - te["x"].ToNBTInt().Data += diffx * BlockManager.CHUNK_XLEN; - te["z"].ToNBTInt().Data += diffz * BlockManager.CHUNK_ZLEN; + int tex = te["x"].ToNBTInt(); + int tey = te["y"].ToNBTInt(); + int tez = te["z"].ToNBTInt(); + + BlockKey key = new BlockKey(tex, tey, tez); + _tileEntityTable[key] = te; } } @@ -397,5 +458,67 @@ namespace NBToolkit.Map } #endregion + + #region INBTObject Members + + public Chunk LoadTree (NBT_Value tree) + { + NBT_Compound ctree = tree as NBT_Compound; + if (ctree == null) { + return null; + } + + _tree = new NBT_Tree(ctree); + + NBT_Compound level = _tree.Root["Level"] as NBT_Compound; + + _blocks = level["Blocks"] as NBT_ByteArray; + _data = new NibbleArray(level["Data"].ToNBTByteArray().Data); + _blockLight = new NibbleArray(level["BlockLight"].ToNBTByteArray().Data); + _skyLight = new NibbleArray(level["SkyLight"].ToNBTByteArray().Data); + _heightMap = level["HeightMap"] as NBT_ByteArray; + + _entities = level["Entities"] as NBT_List; + _tileEntities = level["TileEntities"] as NBT_List; + + // List-type patch up + if (_entities.Count == 0) { + level["Entities"] = new NBT_List(NBT_Type.TAG_COMPOUND); + _entities = level["Entities"] as NBT_List; + } + + if (_tileEntities.Count == 0) { + level["TileEntities"] = new NBT_List(NBT_Type.TAG_COMPOUND); + _tileEntities = level["TileEntities"] as NBT_List; + } + + _cx = level["xPos"].ToNBTInt(); + _cz = level["zPos"].ToNBTInt(); + + BuildTileEntityCache(); + + return this; + } + + public Chunk LoadTreeSafe (NBT_Value tree) + { + if (!ValidateTree(tree)) { + return null; + } + + return LoadTree(tree); + } + + public NBT_Value BuildTree () + { + return _tree.Root; + } + + public bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, LevelSchema).Verify(); + } + + #endregion } } diff --git a/NBToolkit/NBToolkit/Map/ChunkManager.cs b/NBToolkit/NBToolkit/Map/ChunkManager.cs index 1190c19..a36affe 100644 --- a/NBToolkit/NBToolkit/Map/ChunkManager.cs +++ b/NBToolkit/NBToolkit/Map/ChunkManager.cs @@ -5,7 +5,7 @@ using System.Text; namespace NBToolkit.Map { - public class ChunkManager : IChunkContainer, IChunkCache + public class ChunkManager : IChunkContainer, IChunkCache, IEnumerable { public const int REGION_XLEN = 32; public const int REGION_ZLEN = 32; @@ -169,6 +169,24 @@ namespace NBToolkit.Map cz >>= REGION_ZLOG; return _regionMan.GetRegion(cx, cz); } + + #region IEnumerable Members + + public IEnumerator GetEnumerator () + { + return new ChunkEnumerator(this); + } + + #endregion + + #region IEnumerable Members + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () + { + return new ChunkEnumerator(this); + } + + #endregion } public class MissingChunkException : Exception diff --git a/NBToolkit/NBToolkit/Map/ChunkVerifier.cs b/NBToolkit/NBToolkit/Map/ChunkVerifier.cs deleted file mode 100644 index 039825e..0000000 --- a/NBToolkit/NBToolkit/Map/ChunkVerifier.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace NBToolkit.Map -{ - using NBT; - - public class ChunkVerifier : NBTVerifier - { - protected static NBTCompoundNode levelSchema = new NBTCompoundNode() - { - new NBTCompoundNode("Level") - { - new NBTArrayNode("Blocks", 32768), - new NBTArrayNode("Data", 16384), - new NBTArrayNode("SkyLight", 16384), - new NBTArrayNode("BlockLight", 16384), - new NBTArrayNode("HeightMap", 256), - new NBTListNode("Entities", NBT_Type.TAG_COMPOUND), - new NBTListNode("TileEntities", NBT_Type.TAG_COMPOUND), - new NBTScalerNode("LastUpdate", NBT_Type.TAG_LONG), - new NBTScalerNode("xPos", NBT_Type.TAG_INT), - new NBTScalerNode("zPos", NBT_Type.TAG_INT), - new NBTScalerNode("TerrainPopulated", NBT_Type.TAG_BYTE), - }, - }; - - public ChunkVerifier (NBT_Tree tree) - : base(tree.Root, levelSchema) - { - } - } -} diff --git a/NBToolkit/NBToolkit/Map/Entity.cs b/NBToolkit/NBToolkit/Map/Entity.cs index 6e2cd02..f449719 100644 --- a/NBToolkit/NBToolkit/Map/Entity.cs +++ b/NBToolkit/NBToolkit/Map/Entity.cs @@ -9,12 +9,22 @@ namespace NBToolkit.Map public class Entity { - private NBT_Compound _tree; + private string _entityID; + private double _posX; + private double _posY; + private double _posZ; + private double _motionX; + private double _motionY; + private double _motionZ; + private float _rotationYaw; + private float _rotationPitch; + private float _fallDistance; + private short _fire; + private short _air; + private byte _onGround; - public NBT_Compound Root - { - get { return _tree; } - } + + #region Predefined Schemas public static readonly NBTCompoundNode BaseSchema = new NBTCompoundNode("") { @@ -42,28 +52,79 @@ namespace NBToolkit.Map new NBTStringNode("id", "Monster"), }); + public static readonly NBTCompoundNode CreeperSchema = MobSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Creeper"), + }); + + public static readonly NBTCompoundNode SkeletonSchema = MobSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Skeleton"), + }); + + public static readonly NBTCompoundNode SpiderSchema = MobSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Spider"), + }); + + public static readonly NBTCompoundNode GiantSchema = MobSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Giant"), + }); + + public static readonly NBTCompoundNode ZombieSchema = MobSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Zombie"), + }); + + public static readonly NBTCompoundNode PigZombieSchema = MobSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "PigZombie"), + }); + + public static readonly NBTCompoundNode GhastSchema = MobSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Ghast"), + }); + public static readonly NBTCompoundNode PigSchema = MobSchema.MergeInto(new NBTCompoundNode("") { + new NBTStringNode("id", "Pig"), new NBTScalerNode("Saddle", NBT_Type.TAG_BYTE), }); public static readonly NBTCompoundNode SheepSchema = MobSchema.MergeInto(new NBTCompoundNode("") { + new NBTStringNode("id", "Sheep"), new NBTScalerNode("Sheared", NBT_Type.TAG_BYTE), new NBTScalerNode("Color", NBT_Type.TAG_BYTE), }); + public static readonly NBTCompoundNode CowSchema = MobSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Cow"), + }); + + public static readonly NBTCompoundNode ChickenSchema = MobSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Chicken"), + }); + public static readonly NBTCompoundNode Slimechema = MobSchema.MergeInto(new NBTCompoundNode("") { + new NBTStringNode("id", "Slime"), new NBTScalerNode("Size", NBT_Type.TAG_INT), }); public static readonly NBTCompoundNode WolfSchema = MobSchema.MergeInto(new NBTCompoundNode("") { + new NBTStringNode("id", "Wolf"), new NBTScalerNode("Owner", NBT_Type.TAG_STRING), new NBTScalerNode("Sitting", NBT_Type.TAG_BYTE), new NBTScalerNode("Angry", NBT_Type.TAG_BYTE), }); + + #endregion } public class MobEntity : Entity diff --git a/NBToolkit/NBToolkit/Map/Item.cs b/NBToolkit/NBToolkit/Map/Item.cs index 57ec84d..4150b45 100644 --- a/NBToolkit/NBToolkit/Map/Item.cs +++ b/NBToolkit/NBToolkit/Map/Item.cs @@ -5,54 +5,121 @@ using System.Text; namespace NBToolkit.Map { using NBT; + using Utility; public interface IItemContainer { ItemCollection Items { get; } } - public class Item + public class Item : INBTObject, ICopyable { - protected NBT_Compound _tree; - - public NBT_Compound Root + public static readonly NBTCompoundNode ItemSchema = new NBTCompoundNode("") { - get { return _tree; } - } + new NBTScalerNode("id", NBT_Type.TAG_SHORT), + new NBTScalerNode("Damage", NBT_Type.TAG_SHORT), + new NBTScalerNode("Count", NBT_Type.TAG_BYTE), + }; + + private short _id; + private byte _count; + private short _damage; public int ID { - get { return _tree["id"].ToNBTShort(); } - set { _tree["id"].ToNBTShort().Data = (short)value; } + get { return _id; } + set { _id = (short)value; } } public int Damage { - get { return _tree["Damage"].ToNBTShort(); } - set { _tree["Count"].ToNBTShort().Data = (short)value; } + get { return _damage; } + set { _damage = (short)value; } } public int Count { - get { return _tree["Count"].ToNBTByte(); } - set { _tree["Count"].ToNBTByte().Data = (byte) value; } + get { return _count; } + set { _count = (byte)value; } } - public Item (NBT_Compound tree) + public Item () { - _tree = tree; } + + #region ICopyable Members + + public Item Copy () + { + Item item = new Item(); + item._id = _id; + item._count = _count; + item._damage = _damage; + + return item; + } + + #endregion + + #region INBTObject Members + + public Item LoadTree (NBT_Value tree) + { + NBT_Compound ctree = tree as NBT_Compound; + if (ctree == null) { + return null; + } + + _id = ctree["id"].ToNBTShort(); + _count = ctree["Count"].ToNBTByte(); + _damage = ctree["Damage"].ToNBTShort(); + + return this; + } + + public Item LoadTreeSafe (NBT_Value tree) + { + if (!ValidateTree(tree)) { + return null; + } + + return LoadTree(tree); + } + + public NBT_Value BuildTree () + { + NBT_Compound tree = new NBT_Compound(); + tree["id"] = new NBT_Short(_id); + tree["Count"] = new NBT_Byte(_count); + tree["Damage"] = new NBT_Short(_damage); + + return tree; + } + + public bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, ItemSchema).Verify(); + } + + #endregion } - public class ItemCollection + public class ItemCollection : INBTObject, ICopyable { - protected NBT_List _list; + public static readonly NBTCompoundNode InventorySchema = Item.ItemSchema.MergeInto(new NBTCompoundNode("") + { + new NBTScalerNode("Slot", NBT_Type.TAG_BYTE), + }); + + public static readonly NBTListNode ListSchema = new NBTListNode("", NBT_Type.TAG_COMPOUND, InventorySchema); + + protected Dictionary _items; protected int _capacity; - public ItemCollection (NBT_List list, int capacity) + public ItemCollection (int capacity) { - _list = list; _capacity = capacity; + _items = new Dictionary(); } public int Capacity @@ -62,19 +129,16 @@ namespace NBToolkit.Map public int Count { - get { return _list.Count; } + get { return _items.Count; } } public Item this [int slot] { get { - foreach (NBT_Compound tag in _list) { - if (tag["Slot"].ToNBTByte() == slot) { - return new Item(tag); - } - } - return null; + Item item; + _items.TryGetValue(slot, out item); + return item; } set @@ -82,109 +146,82 @@ namespace NBToolkit.Map if (slot < 0 || slot >= _capacity) { return; } - foreach (NBT_Compound tag in _list) { - if (tag["Slot"].ToNBTByte() == slot) { - _list.Remove(tag); - break; - } - } - _list.Add(value.Root); + _items[slot] = value; } } - public int GetItemID (int slot) - { - NBT_Compound tag = FindTag(slot); - if (tag == null) { - return 0; - } - - return tag["id"].ToNBTShort(); - } - - public int GetItemCount (int slot) - { - NBT_Compound tag = FindTag(slot); - if (tag == null) { - return 0; - } - - return tag["Count"].ToNBTByte(); - } - - public int GetItemDamage (int slot) - { - NBT_Compound tag = FindTag(slot); - if (tag == null) { - return 0; - } - - return tag["Damage"].ToNBTShort(); - } - - public bool SetItemID (int slot, int id) - { - NBT_Compound tag = FindTag(slot); - if (tag == null) { - return false; - } - - tag["id"].ToNBTShort().Data = (short) id; - return true; - } - - public bool SetItemCount (int slot, int count) - { - NBT_Compound tag = FindTag(slot); - if (tag == null) { - return false; - } - - tag["Count"].ToNBTByte().Data = (byte) count; - return true; - } - - public bool SetItemDamage (int slot, int damage) - { - NBT_Compound tag = FindTag(slot); - if (tag == null) { - return false; - } - - tag["Damage"].ToNBTShort().Data = (short)damage; - return true; - } - - public bool ClearItem (int slot) - { - foreach (NBT_Compound tag in _list) { - if (tag["Slot"].ToNBTByte() == slot) { - _list.Remove(tag); - return true; - } - } - - return false; - } - public bool ItemExists (int slot) { - return FindTag(slot) != null; + return _items.ContainsKey(slot); + } + + public bool Clear (int slot) + { + return _items.Remove(slot); } public void ClearAllItems () { - _list.Clear(); + _items.Clear(); } - private NBT_Compound FindTag (int slot) + #region ICopyable Members + + public ItemCollection Copy () { - foreach (NBT_Compound tag in _list) { - if (tag["Slot"].ToNBTByte() == slot) { - return tag; - } + ItemCollection ic = new ItemCollection(_capacity); + foreach (KeyValuePair item in _items) { + ic[item.Key] = item.Value.Copy(); } - return null; + return ic; } + + #endregion + + #region INBTObject Members + + public ItemCollection LoadTree (NBT_Value tree) + { + NBT_List ltree = tree as NBT_List; + if (ltree == null) { + return null; + } + + foreach (NBT_Compound item in ltree) { + int slot = item["Slot"].ToNBTByte(); + _items[slot] = new Item().LoadTree(item); + } + + return this; + } + + public ItemCollection LoadTreeSafe (NBT_Value tree) + { + if (!ValidateTree(tree)) { + return null; + } + + return LoadTree(tree); + } + + public NBT_Value BuildTree () + { + NBT_List list = new NBT_List(NBT_Type.TAG_COMPOUND); + + foreach (KeyValuePair item in _items) { + NBT_Compound itemtree = item.Value.BuildTree() as NBT_Compound; + itemtree["Slot"] = new NBT_Byte((byte)item.Key); + list.Add(itemtree); + } + + return list; + } + + public bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, ListSchema).Verify(); + } + + #endregion } } diff --git a/NBToolkit/NBToolkit/Map/NBT/NBT.cs b/NBToolkit/NBToolkit/Map/NBT/NBT.cs index 339e5f0..04e4810 100644 --- a/NBToolkit/NBToolkit/Map/NBT/NBT.cs +++ b/NBToolkit/NBToolkit/Map/NBT/NBT.cs @@ -8,6 +8,16 @@ namespace NBToolkit.Map.NBT { using Map.Utility; + public interface INBTObject + { + T LoadTree (NBT_Value tree); + T LoadTreeSafe (NBT_Value tree); + + NBT_Value BuildTree (); + + bool ValidateTree (NBT_Value tree); + } + public class NBT_Tree : ICopyable { private Stream _stream = null; @@ -25,6 +35,11 @@ namespace NBToolkit.Map.NBT _root = new NBT_Compound(); } + public NBT_Tree (NBT_Compound tree) + { + _root = tree; + } + public NBT_Tree (Stream s) { ReadFrom(s); @@ -487,6 +502,8 @@ namespace NBToolkit.Map.NBT public NBTException (String msg, Exception innerException) : base(msg, innerException) { } } + public class InvalidNBTObjectException : Exception { } + public class InvalidTagException : Exception { } public class InvalidValueException : Exception { } diff --git a/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs b/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs index 5c721fc..1cf7046 100644 --- a/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs +++ b/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs @@ -135,7 +135,7 @@ namespace NBToolkit.Map.NBT OnInvalidTagValue(new TagEventArgs(schema, tag)); return false; } - if (schema.Name != null && stag.Data != schema.Value) { + if (schema.Value != null && stag.Data != schema.Value) { OnInvalidTagValue(new TagEventArgs(schema, tag)); return false; } diff --git a/NBToolkit/NBToolkit/Map/TileEntity.cs b/NBToolkit/NBToolkit/Map/TileEntity.cs index a8b9230..6a7301f 100644 --- a/NBToolkit/NBToolkit/Map/TileEntity.cs +++ b/NBToolkit/NBToolkit/Map/TileEntity.cs @@ -7,95 +7,8 @@ namespace NBToolkit.Map using NBT; using Utility; - public class TileEntity : ICopyable + public class TileEntity : INBTObject, ICopyable { - protected NBT_Compound _tree; - - public NBT_Compound Root - { - get { return _tree; } - } - - public string ID - { - get { return _tree["id"].ToNBTString(); } - } - - public int X - { - get { return _tree["x"].ToNBTInt(); } - set { _tree["x"] = new NBT_Int(value); } - } - - public int Y - { - get { return _tree["y"].ToNBTInt(); } - set { _tree["y"] = new NBT_Int(value); } - } - - public int Z - { - get { return _tree["z"].ToNBTInt(); } - set { _tree["z"] = new NBT_Int(value); } - } - - public TileEntity (string id) - { - _tree = new NBT_Compound(); - _tree["id"] = new NBT_String(id); - _tree["x"] = new NBT_Int(); - _tree["y"] = new NBT_Int(); - _tree["z"] = new NBT_Int(); - } - - public TileEntity (NBT_Compound tree) - { - _tree = tree; - } - - public TileEntity (NBTSchemaNode schema) - { - _tree = schema.BuildDefaultTree() as NBT_Compound; - } - - public virtual bool Verify () - { - NBTVerifier v = new NBTVerifier(Root, BaseSchema); - return v.Verify(); - } - - public bool Verify (NBTSchemaNode schema) - { - NBTVerifier v = new NBTVerifier(Root, schema); - return v.Verify(); - } - - public bool LocatedAt (int x, int y, int z) - { - return _tree["x"].ToNBTInt().Data == x && - _tree["y"].ToNBTInt().Data == y && - _tree["z"].ToNBTInt().Data == z; - } - - #region ICopyable Members - - public virtual TileEntity Copy () - { - return new TileEntity(_tree.Copy() as NBT_Compound); - } - - #endregion - - #region Predefined Schemas - - public static readonly NBTCompoundNode InventorySchema = new NBTCompoundNode("") - { - new NBTScalerNode("id", NBT_Type.TAG_SHORT), - new NBTScalerNode("Damage", NBT_Type.TAG_SHORT), - new NBTScalerNode("Count", NBT_Type.TAG_BYTE), - new NBTScalerNode("Slot", NBT_Type.TAG_BYTE), - }; - public static readonly NBTCompoundNode BaseSchema = new NBTCompoundNode("") { new NBTScalerNode("id", NBT_Type.TAG_STRING), @@ -104,14 +17,211 @@ namespace NBToolkit.Map new NBTScalerNode("z", NBT_Type.TAG_INT), }; + private string _id; + private int _x; + private int _y; + private int _z; + + public string ID + { + get { return _id; } + } + + public int X + { + get { return _x; } + set { _x = value; } + } + + public int Y + { + get { return _y; } + set { _y = value; } + } + + public int Z + { + get { return _z; } + set { _z = value; } + } + + public TileEntity (string id) + { + _id = id; + } + + public TileEntity (TileEntity te) + { + _id = te._id; + _x = te._x; + _y = te._y; + _z = te._z; + } + + public bool LocatedAt (int x, int y, int z) + { + return _x == x && _y == y && _z == z; + } + + #region ICopyable Members + + public virtual TileEntity Copy () + { + return new TileEntity(this); + } + + #endregion + + #region INBTObject Members + + public virtual TileEntity LoadTree (NBT_Value tree) + { + NBT_Compound ctree = tree as NBT_Compound; + if (ctree == null) { + return null; + } + + _id = ctree["id"].ToNBTString(); + _x = ctree["x"].ToNBTInt(); + _y = ctree["y"].ToNBTInt(); + _z = ctree["z"].ToNBTInt(); + + return this; + } + + public virtual TileEntity LoadTreeSafe (NBT_Value tree) + { + if (!ValidateTree(tree)) { + return null; + } + + return LoadTree(tree); + } + + public virtual NBT_Value BuildTree () + { + NBT_Compound tree = new NBT_Compound(); + tree["id"] = new NBT_String(_id); + tree["x"] = new NBT_Int(_x); + tree["y"] = new NBT_Int(_y); + tree["z"] = new NBT_Int(_z); + + return tree; + } + + public virtual bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, BaseSchema).Verify(); + } + + #endregion + } + + public class TileEntityFurnace : TileEntity, IItemContainer + { public static readonly NBTCompoundNode FurnaceSchema = BaseSchema.MergeInto(new NBTCompoundNode("") { new NBTStringNode("id", "Furnace"), new NBTScalerNode("BurnTime", NBT_Type.TAG_SHORT), new NBTScalerNode("CookTime", NBT_Type.TAG_SHORT), - new NBTListNode("Items", NBT_Type.TAG_COMPOUND, InventorySchema), + new NBTListNode("Items", NBT_Type.TAG_COMPOUND, ItemCollection.ListSchema), }); + private const int _CAPACITY = 3; + + private short _burnTime; + private short _cookTime; + + private ItemCollection _items; + + public int BurnTime + { + get { return _burnTime; } + set { _burnTime = (short)value; } + } + + public int CookTime + { + get { return _cookTime; } + set { _cookTime = (short)value; } + } + + public TileEntityFurnace () + : base("Furnace") + { + _items = new ItemCollection(_CAPACITY); + } + + public TileEntityFurnace (TileEntity te) + : base (te) + { + TileEntityFurnace tec = te as TileEntityFurnace; + if (tec != null) { + _cookTime = tec._cookTime; + _burnTime = tec._burnTime; + _items = tec._items.Copy(); + } + else { + _items = new ItemCollection(_CAPACITY); + } + } + + #region ICopyable Members + + public override TileEntity Copy () + { + return new TileEntityFurnace(this); + } + + #endregion + + #region IItemContainer Members + + public ItemCollection Items + { + get { return _items; } + } + + #endregion + + #region INBTObject Members + + public override TileEntity LoadTree (NBT_Value tree) + { + NBT_Compound ctree = tree as NBT_Compound; + if (ctree == null || base.LoadTree(tree) == null) { + return null; + } + + _burnTime = ctree["BurnTime"].ToNBTShort(); + _cookTime = ctree["CookTime"].ToNBTShort(); + + NBT_List items = ctree["Items"].ToNBTList(); + _items = new ItemCollection(_CAPACITY).LoadTree(items); + + return this; + } + + public override NBT_Value BuildTree () + { + NBT_Compound tree = base.BuildTree() as NBT_Compound; + tree["BurnTime"] = new NBT_Short(_burnTime); + tree["CookTime"] = new NBT_Short(_cookTime); + tree["Items"] = _items.BuildTree(); + + return tree; + } + + public override bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, FurnaceSchema).Verify(); + } + + #endregion + } + + public class TileEntitySign : TileEntity + { public static readonly NBTCompoundNode SignSchema = BaseSchema.MergeInto(new NBTCompoundNode("") { new NBTStringNode("id", "Sign"), @@ -121,132 +231,92 @@ namespace NBToolkit.Map new NBTScalerNode("Text4", NBT_Type.TAG_STRING), }); - public static readonly NBTCompoundNode MobSpawnerSchema = BaseSchema.MergeInto(new NBTCompoundNode("") - { - new NBTStringNode("id", "MobSpawner"), - new NBTScalerNode("EntityId", NBT_Type.TAG_STRING), - new NBTScalerNode("Delay", NBT_Type.TAG_SHORT), - }); + private string _text1 = ""; + private string _text2 = ""; + private string _text3 = ""; + private string _text4 = ""; - public static readonly NBTCompoundNode ChestSchema = BaseSchema.MergeInto(new NBTCompoundNode("") - { - new NBTStringNode("id", "Chest"), - new NBTListNode("Items", NBT_Type.TAG_COMPOUND, InventorySchema), - }); - - public static readonly NBTCompoundNode MusicSchema = BaseSchema.MergeInto(new NBTCompoundNode("") - { - new NBTStringNode("id", "Music"), - new NBTScalerNode("note", NBT_Type.TAG_BYTE), - }); - - public static readonly NBTCompoundNode TrapSchema = BaseSchema.MergeInto(new NBTCompoundNode("") - { - new NBTStringNode("id", "Trap"), - new NBTListNode("Items", NBT_Type.TAG_COMPOUND, InventorySchema), - }); - - #endregion - } - - public class TileEntityFurnace : TileEntity, IItemContainer - { - protected const int _capacity = 3; - - protected ItemCollection _items; - - public int BurnTime - { - get { return _tree["BurnTime"].ToNBTShort(); } - set { _tree["BurnTime"] = new NBT_Short((short)value); } - } - - public int CookTime - { - get { return _tree["CookTime"].ToNBTShort(); } - set { _tree["CookTime"] = new NBT_Short((short)value); } - } - - public TileEntityFurnace (NBT_Compound tree) - : base(tree) - { - NBT_List items = tree["Items"].ToNBTList(); - - if (items.Count == 0) { - tree["Items"] = new NBT_List(NBT_Type.TAG_COMPOUND); - items = _tree["Items"].ToNBTList(); - } - - _items = new ItemCollection(items, _capacity); - } - - public override bool Verify () - { - NBTVerifier v = new NBTVerifier(Root, TileEntity.FurnaceSchema); - return v.Verify(); - } - - #region ICopyable Members - - public override TileEntity Copy () - { - return new TileEntityFurnace(_tree.Copy() as NBT_Compound); - } - - #endregion - - #region IItemContainer Members - - public ItemCollection Items - { - get { return _items; } - } - - #endregion - } - - public class TileEntitySign : TileEntity - { public string Text1 { - get { return _tree["Text1"].ToNBTString(); } - set { _tree["Text1"] = new NBT_String(value.Substring(0, 12)); } + get { return _text1; } + set { _text1 = value.Substring(0, 12); } } public string Text2 { - get { return _tree["Text2"].ToNBTString(); } - set { _tree["Text2"] = new NBT_String(value.Substring(0, 12)); } + get { return _text2; } + set { _text2 = value.Substring(0, 12); } } public string Text3 { - get { return _tree["Text3"].ToNBTString(); } - set { _tree["Text3"] = new NBT_String(value.Substring(0, 12)); } + get { return _text3; } + set { _text3 = value.Substring(0, 12); } } public string Text4 { - get { return _tree["Text4"].ToNBTString(); } - set { _tree["Text4"] = new NBT_String(value.Substring(0, 12)); } + get { return _text4; } + set { _text4 = value.Substring(0, 12); } } - public TileEntitySign (NBT_Compound tree) - : base(tree) + public TileEntitySign () + : base("Sign") { } - public override bool Verify () + public TileEntitySign (TileEntity te) + : base(te) { - NBTVerifier v = new NBTVerifier(Root, TileEntity.SignSchema); - return v.Verify(); + TileEntitySign tes = te as TileEntitySign; + if (tes != null) { + _text1 = tes._text1; + _text2 = tes._text2; + _text3 = tes._text3; + _text4 = tes._text4; + } } #region ICopyable Members public override TileEntity Copy () { - return new TileEntitySign(_tree.Copy() as NBT_Compound); + return new TileEntitySign(this); + } + + #endregion + + #region INBTObject Members + + public override TileEntity LoadTree (NBT_Value tree) + { + NBT_Compound ctree = tree as NBT_Compound; + if (ctree == null || base.LoadTree(tree) == null) { + return null; + } + + _text1 = ctree["Text1"].ToNBTString(); + _text2 = ctree["Text2"].ToNBTString(); + _text3 = ctree["Text3"].ToNBTString(); + _text4 = ctree["Text4"].ToNBTString(); + + return this; + } + + public override NBT_Value BuildTree () + { + NBT_Compound tree = base.BuildTree() as NBT_Compound; + tree["Text1"] = new NBT_String(_text1); + tree["Text2"] = new NBT_String(_text2); + tree["Text3"] = new NBT_String(_text3); + tree["Text4"] = new NBT_String(_text4); + + return tree; + } + + public override bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, SignSchema).Verify(); } #endregion @@ -254,34 +324,79 @@ namespace NBToolkit.Map public class TileEntityMobSpawner : TileEntity { + public static readonly NBTCompoundNode MobSpawnerSchema = BaseSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "MobSpawner"), + new NBTScalerNode("EntityId", NBT_Type.TAG_STRING), + new NBTScalerNode("Delay", NBT_Type.TAG_SHORT), + }); + + private short _delay; + private string _entityID; + public int Delay { - get { return _tree["Delay"].ToNBTShort(); } - set { _tree["Delay"] = new NBT_Short((short)value); } + get { return _delay; } + set { _delay = (short)value; } } public string EntityID { - get { return _tree["EntityID"].ToNBTString(); } - set { _tree["EntityID"] = new NBT_String(value); } + get { return _entityID; } + set { _entityID = value; } } - public TileEntityMobSpawner (NBT_Compound tree) - : base(tree) + public TileEntityMobSpawner () + : base("MobSpawner") { } - public override bool Verify () + public TileEntityMobSpawner (TileEntity te) + : base(te) { - NBTVerifier v = new NBTVerifier(Root, TileEntity.MobSpawnerSchema); - return v.Verify(); + TileEntityMobSpawner tes = te as TileEntityMobSpawner; + if (tes != null) { + _delay = tes._delay; + _entityID = tes._entityID; + } } #region ICopyable Members public override TileEntity Copy () { - return new TileEntityMobSpawner(_tree.Copy() as NBT_Compound); + return new TileEntityMobSpawner(this); + } + + #endregion + + #region INBTObject Members + + public override TileEntity LoadTree (NBT_Value tree) + { + NBT_Compound ctree = tree as NBT_Compound; + if (ctree == null || base.LoadTree(tree) == null) { + return null; + } + + _delay = ctree["Delay"].ToNBTShort(); + _entityID = ctree["EntityID"].ToNBTString(); + + return this; + } + + public override NBT_Value BuildTree () + { + NBT_Compound tree = base.BuildTree() as NBT_Compound; + tree["EntityID"] = new NBT_String(_entityID); + tree["Delay"] = new NBT_Short(_delay); + + return tree; + } + + public override bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, MobSpawnerSchema).Verify(); } #endregion @@ -289,34 +404,39 @@ namespace NBToolkit.Map public class TileEntityChest : TileEntity, IItemContainer { - protected const int _capacity = 27; - - protected ItemCollection _items; - - public TileEntityChest (NBT_Compound tree) - : base(tree) + public static readonly NBTCompoundNode ChestSchema = BaseSchema.MergeInto(new NBTCompoundNode("") { - NBT_List items = tree["Items"].ToNBTList(); + new NBTStringNode("id", "Chest"), + new NBTListNode("Items", NBT_Type.TAG_COMPOUND, ItemCollection.ListSchema), + }); - if (items.Count == 0) { - tree["Items"] = new NBT_List(NBT_Type.TAG_COMPOUND); - items = _tree["Items"].ToNBTList(); - } + private const int _CAPACITY = 27; - _items = new ItemCollection(items, _capacity); + private ItemCollection _items; + + public TileEntityChest () + : base("Chest") + { + _items = new ItemCollection(_CAPACITY); } - public override bool Verify () + public TileEntityChest (TileEntity te) + : base(te) { - NBTVerifier v = new NBTVerifier(Root, TileEntity.ChestSchema); - return v.Verify(); + TileEntityChest tec = te as TileEntityChest; + if (tec != null) { + _items = tec._items.Copy(); + } + else { + _items = new ItemCollection(_CAPACITY); + } } #region ICopyable Members public override TileEntity Copy () { - return new TileEntityChest(_tree.Copy() as NBT_Compound); + return new TileEntityChest(this); } #endregion @@ -329,32 +449,102 @@ namespace NBToolkit.Map } #endregion + + #region INBTObject Members + + public override TileEntity LoadTree (NBT_Value tree) + { + NBT_Compound ctree = tree as NBT_Compound; + if (ctree == null || base.LoadTree(tree) == null) { + return null; + } + + NBT_List items = ctree["Items"].ToNBTList(); + _items = new ItemCollection(_CAPACITY).LoadTree(items); + + return this; + } + + public override NBT_Value BuildTree () + { + NBT_Compound tree = base.BuildTree() as NBT_Compound; + tree["Items"] = _items.BuildTree(); + + return tree; + } + + public override bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, ChestSchema).Verify(); + } + + #endregion } public class TileEntityMusic : TileEntity { + public static readonly NBTCompoundNode MusicSchema = BaseSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Music"), + new NBTScalerNode("note", NBT_Type.TAG_BYTE), + }); + + private byte _note; + public int Note { - get { return _tree["Note"].ToNBTByte(); } - set { _tree["Note"] = new NBT_Byte((byte)value); } + get { return _note; } + set { _note = (byte)value; } } - public TileEntityMusic (NBT_Compound tree) - : base(tree) + public TileEntityMusic () + : base("Music") { } - public override bool Verify () + public TileEntityMusic (TileEntity te) + : base(te) { - NBTVerifier v = new NBTVerifier(Root, TileEntity.MusicSchema); - return v.Verify(); + TileEntityMusic tes = te as TileEntityMusic; + if (tes != null) { + _note = tes._note; + } } #region ICopyable Members public override TileEntity Copy () { - return new TileEntityMusic(_tree.Copy() as NBT_Compound); + return new TileEntityMusic(this); + } + + #endregion + + #region INBTObject Members + + public override TileEntity LoadTree (NBT_Value tree) + { + NBT_Compound ctree = tree as NBT_Compound; + if (ctree == null || base.LoadTree(tree) == null) { + return null; + } + + _note = ctree["Note"].ToNBTByte(); + + return this; + } + + public override NBT_Value BuildTree () + { + NBT_Compound tree = base.BuildTree() as NBT_Compound; + tree["Note"] = new NBT_Byte(_note); + + return tree; + } + + public override bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, MusicSchema).Verify(); } #endregion @@ -362,34 +552,39 @@ namespace NBToolkit.Map public class TileEntityTrap : TileEntity, IItemContainer { - protected const int _capacity = 8; - - protected ItemCollection _items; - - public TileEntityTrap (NBT_Compound tree) - : base(tree) + public static readonly NBTCompoundNode TrapSchema = BaseSchema.MergeInto(new NBTCompoundNode("") { - NBT_List items = tree["Items"].ToNBTList(); + new NBTStringNode("id", "Trap"), + new NBTListNode("Items", NBT_Type.TAG_COMPOUND, ItemCollection.ListSchema), + }); - if (items.Count == 0) { - tree["Items"] = new NBT_List(NBT_Type.TAG_COMPOUND); - items = _tree["Items"].ToNBTList(); - } + private const int _CAPACITY = 8; - _items = new ItemCollection(items, _capacity); + private ItemCollection _items; + + public TileEntityTrap () + : base("Trap") + { + _items = new ItemCollection(_CAPACITY); } - public override bool Verify () + public TileEntityTrap (TileEntity te) + : base(te) { - NBTVerifier v = new NBTVerifier(Root, TileEntity.TrapSchema); - return v.Verify(); + TileEntityTrap tec = te as TileEntityTrap; + if (tec != null) { + _items = tec._items.Copy(); + } + else { + _items = new ItemCollection(_CAPACITY); + } } #region ICopyable Members public override TileEntity Copy () { - return new TileEntityTrap(_tree.Copy() as NBT_Compound); + return new TileEntityTrap(this); } #endregion @@ -402,5 +597,35 @@ namespace NBToolkit.Map } #endregion + + #region INBTObject Members + + public override TileEntity LoadTree (NBT_Value tree) + { + NBT_Compound ctree = tree as NBT_Compound; + if (ctree == null || base.LoadTree(tree) == null) { + return null; + } + + NBT_List items = ctree["Items"].ToNBTList(); + _items = new ItemCollection(_CAPACITY).LoadTree(items); + + return this; + } + + public override NBT_Value BuildTree () + { + NBT_Compound tree = base.BuildTree() as NBT_Compound; + tree["Items"] = _items.BuildTree(); + + return tree; + } + + public override bool ValidateTree (NBT_Value tree) + { + return new NBTVerifier(tree, TrapSchema).Verify(); + } + + #endregion } } diff --git a/NBToolkit/NBToolkit/Map/TileEntityFactory.cs b/NBToolkit/NBToolkit/Map/TileEntityFactory.cs new file mode 100644 index 0000000..00be6e6 --- /dev/null +++ b/NBToolkit/NBToolkit/Map/TileEntityFactory.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NBToolkit.Map +{ + using NBT; + + public class TileEntityFactory + { + private static Dictionary _registry; + + public static TileEntity Create (string type) + { + Type t; + if (!_registry.TryGetValue(type, out t)) { + return null; + } + + return Activator.CreateInstance(t) as TileEntity; + } + + public static TileEntity Create (NBT_Compound tree) + { + string type = tree["id"].ToNBTString(); + + Type t; + if (!_registry.TryGetValue(type, out t)) { + return null; + } + + TileEntity te = Activator.CreateInstance(t, new object[] { tree }) as TileEntity; + + return te.LoadTreeSafe(tree); + } + + public static Type Lookup (string type) + { + Type t; + if (!_registry.TryGetValue(type, out t)) { + return null; + } + + return t; + } + + public static void Register (string id, Type subtype) + { + _registry[id] = subtype; + } + + static TileEntityFactory () + { + _registry = new Dictionary(); + + _registry["Chest"] = typeof(TileEntityChest); + _registry["Furnace"] = typeof(TileEntityFurnace); + _registry["MobSpawner"] = typeof(TileEntityMobSpawner); + _registry["Music"] = typeof(TileEntityMusic); + _registry["Sign"] = typeof(TileEntitySign); + _registry["Trap"] = typeof(TileEntityTrap); + } + } +} diff --git a/NBToolkit/NBToolkit/NBToolkit.csproj b/NBToolkit/NBToolkit/NBToolkit.csproj index ad4f0c8..93d0e28 100644 --- a/NBToolkit/NBToolkit/NBToolkit.csproj +++ b/NBToolkit/NBToolkit/NBToolkit.csproj @@ -73,11 +73,13 @@ - + + + diff --git a/NBToolkit/NBToolkit/Replace.cs b/NBToolkit/NBToolkit/Replace.cs index 3ddab8e..874ff55 100644 --- a/NBToolkit/NBToolkit/Replace.cs +++ b/NBToolkit/NBToolkit/Replace.cs @@ -7,6 +7,7 @@ namespace NBToolkit { using Map; using Map.NBT; + using System.Globalization; public class ReplaceOptions : TKOptions, IChunkFilterable { @@ -49,7 +50,7 @@ namespace NBToolkit { "d|data=", "Set the new block's data value to {VAL} (0-15)", v => OPT_DATA = Convert.ToInt32(v) % 16 }, { "p|prob=", "Replace any matching block with probability {VAL} (0.0-1.0)", - v => { OPT_PROB = Convert.ToDouble(v); + v => { OPT_PROB = Convert.ToDouble(v, new CultureInfo("en-US")); OPT_PROB = Math.Max((double)OPT_PROB, 0.0); OPT_PROB = Math.Min((double)OPT_PROB, 1.0); } }, { "bxr|BlockXRange=", "Update blocks with X-coord between {0:V1} and {1:V2}, inclusive. V1 or V2 may be left blank.",