From 3afb2238ef9b0c2cf4ef081d8e75d9767da9d435 Mon Sep 17 00:00:00 2001 From: Justin Aquadro Date: Sat, 2 Apr 2011 08:37:20 +0000 Subject: [PATCH] More huge refactoring. Chunk split out of ChunkRef, both backed by IChunk interface. TileEntity integration added. --- .../NBToolkit/FilteredChunkEnumerator.cs | 3 + NBToolkit/NBToolkit/GenOres.cs | 3 + NBToolkit/NBToolkit/Map/Block.cs | 85 +++- NBToolkit/NBToolkit/Map/BlockInfo.cs | 201 ++------ NBToolkit/NBToolkit/Map/BlockKey.cs | 2 +- NBToolkit/NBToolkit/Map/BlockManager.cs | 14 +- NBToolkit/NBToolkit/Map/BlockRef.cs | 21 +- NBToolkit/NBToolkit/Map/Chunk.cs | 364 ++++++++++++++ NBToolkit/NBToolkit/Map/ChunkEnumerator.cs | 2 +- NBToolkit/NBToolkit/Map/ChunkKey.cs | 2 +- NBToolkit/NBToolkit/Map/ChunkManager.cs | 2 +- NBToolkit/NBToolkit/Map/ChunkRef.cs | 475 ++++++++---------- NBToolkit/NBToolkit/Map/ChunkVerifier.cs | 2 +- NBToolkit/NBToolkit/Map/NBT/NBT.cs | 3 +- NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs | 56 ++- NBToolkit/NBToolkit/Map/NBT/NBTValues.cs | 77 ++- NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs | 48 +- NBToolkit/NBToolkit/Map/Region.cs | 8 +- NBToolkit/NBToolkit/Map/RegionEnumerator.cs | 2 +- NBToolkit/NBToolkit/Map/RegionFile.cs | 2 +- NBToolkit/NBToolkit/Map/RegionKey.cs | 2 +- NBToolkit/NBToolkit/Map/RegionManager.cs | 2 +- NBToolkit/NBToolkit/Map/TileEntity.cs | 128 +++++ NBToolkit/NBToolkit/Map/Utility/Interface.cs | 11 + .../NBToolkit/Map/Utility/NibbleArray.cs | 2 +- NBToolkit/NBToolkit/Map/World.cs | 2 +- NBToolkit/NBToolkit/NBToolkit.csproj | 13 +- NBToolkit/NBToolkit/Oregen.cs | 7 +- NBToolkit/NBToolkit/Program.cs | 3 +- NBToolkit/NBToolkit/Purge.cs | 3 +- NBToolkit/NBToolkit/Replace.cs | 3 +- 31 files changed, 1070 insertions(+), 478 deletions(-) create mode 100644 NBToolkit/NBToolkit/Map/Chunk.cs create mode 100644 NBToolkit/NBToolkit/Map/TileEntity.cs create mode 100644 NBToolkit/NBToolkit/Map/Utility/Interface.cs diff --git a/NBToolkit/NBToolkit/FilteredChunkEnumerator.cs b/NBToolkit/NBToolkit/FilteredChunkEnumerator.cs index 63acc2e..209818c 100644 --- a/NBToolkit/NBToolkit/FilteredChunkEnumerator.cs +++ b/NBToolkit/NBToolkit/FilteredChunkEnumerator.cs @@ -4,6 +4,9 @@ using System.Text; namespace NBToolkit { + using Map; + using Map.NBT; + public class FilteredChunkList : ChunkList { protected IChunkFilter _filter; diff --git a/NBToolkit/NBToolkit/GenOres.cs b/NBToolkit/NBToolkit/GenOres.cs index 31ee4b7..646796e 100644 --- a/NBToolkit/NBToolkit/GenOres.cs +++ b/NBToolkit/NBToolkit/GenOres.cs @@ -4,6 +4,9 @@ using System.Text; namespace NBToolkit { + using Map; + using Map.NBT; + public interface IGenerator { bool Generate (BlockManager blockMan, Random rand, int x, int y, int z); diff --git a/NBToolkit/NBToolkit/Map/Block.cs b/NBToolkit/NBToolkit/Map/Block.cs index 97784b9..b230808 100644 --- a/NBToolkit/NBToolkit/Map/Block.cs +++ b/NBToolkit/NBToolkit/Map/Block.cs @@ -2,9 +2,10 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit +namespace NBToolkit.Map { using NBT; + using Utility; public interface IBlock { @@ -13,16 +14,20 @@ namespace NBToolkit int Data { get; set; } int BlockLight { get; set; } int SkyLight { get; set; } + + TileEntity GetTileEntity (); + bool SetTileEntity (TileEntity te); + bool ClearTileEntity (); } - public class Block : IBlock + public class Block : IBlock, ICopyable { - protected int _id; - protected int _data; - protected int _skylight; - protected int _blocklight; + private int _id; + private int _data; + private int _skylight; + private int _blocklight; - protected NBT_Compound _tileEntities; + private TileEntity _tileEntity; public BlockInfo Info { @@ -32,7 +37,13 @@ namespace NBToolkit public int ID { get { return _id; } - set { _id = value; } + set + { + if (BlockInfo.SchemaTable[_id] != BlockInfo.SchemaTable[value]) { + _tileEntity = null; + } + _id = value; + } } public int Data @@ -64,33 +75,53 @@ namespace NBToolkit _data = data; } - public Block (Block block) - { - _id = block._id; - _data = block._data; - _skylight = block._skylight; - _blocklight = block._blocklight; - } - - public Block (IBlock block) - { - _id = block.ID; - _data = block.Data; - _skylight = block.SkyLight; - _blocklight = block.BlockLight; - } - - public Block (ChunkRef chunk, int lx, int ly, int lz) + public Block (IChunk chunk, int lx, int ly, int lz) { _id = chunk.GetBlockID(lx, ly, lz); _data = chunk.GetBlockData(lx, ly, lz); _skylight = chunk.GetBlockSkyLight(lx, ly, lz); _blocklight = chunk.GetBlockLight(lx, ly, lz); + _tileEntity = chunk.GetTileEntity(lx, ly, lz).Copy(); } - public Block (BlockManager bm, int x, int y, int z) - : this(bm.GetBlockRef(x, y, z)) + public TileEntity GetTileEntity () { + return _tileEntity; } + + public bool SetTileEntity (TileEntity te) + { + NBTCompoundNode schema = BlockInfo.SchemaTable[_id]; + if (schema == null) { + return false; + } + + if (te.Verify(schema) == false) { + return false; + } + + _tileEntity = te; + return true; + } + + public bool ClearTileEntity () + { + _tileEntity = null; + return true; + } + + #region ICopyable Members + + public Block Copy () + { + Block block = new Block(_id, _data); + block._blocklight = _blocklight; + block._skylight = _skylight; + block._tileEntity = _tileEntity.Copy(); + + return block; + } + + #endregion } } diff --git a/NBToolkit/NBToolkit/Map/BlockInfo.cs b/NBToolkit/NBToolkit/Map/BlockInfo.cs index 45ef49c..499d4b1 100644 --- a/NBToolkit/NBToolkit/Map/BlockInfo.cs +++ b/NBToolkit/NBToolkit/Map/BlockInfo.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit +namespace NBToolkit.Map { using NBT; @@ -26,6 +26,8 @@ namespace NBToolkit private static int[] _opacityTable; private static int[] _luminanceTable; + protected internal static NBTCompoundNode[] _schemaTable; + public class ItemCache { private T[] _cache; @@ -52,6 +54,8 @@ namespace NBToolkit public static ItemCache LuminanceTable; + public static ItemCache SchemaTable; + public int ID { get { return _id; } @@ -107,6 +111,9 @@ namespace NBToolkit new NBTScalerNode("z", NBT_Type.TAG_INT), }; + public const int AIR = 0; + public const int FURNACE = 61; + public static BlockInfo Air; public static BlockInfo Stone; public static BlockInfo Grass; @@ -130,9 +137,9 @@ namespace NBToolkit public static BlockInfo Glass; public static BlockInfo LapisOre; public static BlockInfo LapisBlock; - public static BlockInfoTrap Dispenser; + public static TileEntityBlockInfo Dispenser; public static BlockInfo Sandstone; - public static BlockInfoMusic NoteBlock; + public static TileEntityBlockInfo NoteBlock; public static BlockInfo Bed; public static BlockInfo Wool; public static BlockInfo YellowFlower; @@ -150,23 +157,23 @@ namespace NBToolkit public static BlockInfo Obsidian; public static BlockInfo Torch; public static BlockInfo Fire; - public static BlockInfoMonster MonsterSpawner; + public static TileEntityBlockInfo MonsterSpawner; public static BlockInfo WoodStairs; - public static BlockInfoChest Chest; + public static TileEntityBlockInfo 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 BlockInfoFurnace Furnace; - public static BlockInfoFurnace BurningFurnace; - public static BlockInfoSign SignPost; + public static TileEntityBlockInfo Furnace; + public static TileEntityBlockInfo BurningFurnace; + public static TileEntityBlockInfo SignPost; public static BlockInfo WoodDoor; public static BlockInfo Ladder; public static BlockInfo Rails; public static BlockInfo CobbleStairs; - public static BlockInfoSign WallSign; + public static TileEntityBlockInfo WallSign; public static BlockInfo Lever; public static BlockInfo StonePlate; public static BlockInfo IronDoor; @@ -199,10 +206,12 @@ namespace NBToolkit _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"); @@ -227,9 +236,9 @@ namespace NBToolkit Glass = new BlockInfo(20, "Glass").SetOpacity(0); LapisOre = new BlockInfo(21, "Lapis Lazuli Ore"); LapisBlock = new BlockInfo(22, "Lapis Lazuli Block"); - Dispenser = new BlockInfoTrap(23, "Dispenser"); + Dispenser = new TileEntityBlockInfo(23, "Dispenser"); Sandstone = new BlockInfo(24, "Sandstone"); - NoteBlock = new BlockInfoMusic(25, "Note Block"); + NoteBlock = new TileEntityBlockInfo(25, "Note Block"); Bed = new BlockInfo(26, "Bed").SetOpacity(0); Wool = new BlockInfo(35, "Wool"); YellowFlower = new BlockInfo(37, "Yellow Flower").SetOpacity(0); @@ -247,23 +256,23 @@ namespace NBToolkit 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 = (BlockInfoMonster)new BlockInfoMonster(52, "Monster Spawner").SetOpacity(0); + MonsterSpawner = (TileEntityBlockInfo)new TileEntityBlockInfo(52, "Monster Spawner").SetOpacity(0); WoodStairs = new BlockInfo(53, "Wooden Stairs").SetOpacity(0); - Chest = new BlockInfoChest(54, "Chest"); + Chest = new TileEntityBlockInfo(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 BlockInfoFurnace(61, "Furnace"); - BurningFurnace = (BlockInfoFurnace)new BlockInfoFurnace(62, "Burning Furnace").SetLuminance(MAX_LUMINANCE - 1); - SignPost = (BlockInfoSign)new BlockInfoSign(63, "Sign Post").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); 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 = (BlockInfoSign)new BlockInfoSign(68, "Wall Sign").SetOpacity(0); + WallSign = (TileEntityBlockInfo)new TileEntityBlockInfo(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); @@ -296,150 +305,42 @@ namespace NBToolkit _blockTable[i] = new BlockInfo(i, "Uknown Block"); } } + + Dispenser.SetTileEntity("Trap", TileEntity.TrapSchema); + NoteBlock.SetTileEntity("Music", TileEntity.MusicSchema); + MonsterSpawner.SetTileEntity("MonsterSpawner", TileEntity.MonsterSpawnerSchema); + 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); } } - public class BlockInfoTrap : BlockInfo, IBlockTileEntity + public class TileEntityBlockInfo : BlockInfo { + private string _tileEntityName; + private NBTSchemaNode _tileEntitySchema; + public string TileEntityName { - get { return "Trap"; } + get { return _tileEntityName; } } - public NBTCompoundNode TileEntitySchema + public NBTSchemaNode TileEntitySchema { - get { return tileEntitySchema; } + get { return _tileEntitySchema; } } - public BlockInfoTrap (int id, string name) - : base(id, name) - { + public TileEntityBlockInfo (int id) : base(id) { } + + public TileEntityBlockInfo (int id, string name) : base(id, name) { } + + public BlockInfo SetTileEntity (string name, NBTCompoundNode schema) { + _tileEntityName = name; + _tileEntitySchema = schema; + _schemaTable[ID] = schema; + return this; } - - protected static new NBTCompoundNode tileEntitySchema = BlockInfo.tileEntitySchema.MergeInto(new NBTCompoundNode("") - { - new NBTListNode("Items", NBT_Type.TAG_COMPOUND), - }); - } - - public class BlockInfoMusic : BlockInfo, IBlockTileEntity - { - public string TileEntityName - { - get { return "Music"; } - } - - public NBTCompoundNode TileEntitySchema - { - get { return tileEntitySchema; } - } - - public BlockInfoMusic (int id, string name) - : base(id, name) - { - } - - protected static new NBTCompoundNode tileEntitySchema = BlockInfo.tileEntitySchema.MergeInto(new NBTCompoundNode("") - { - new NBTScalerNode("note", NBT_Type.TAG_COMPOUND), - }); - } - - public class BlockInfoMonster : BlockInfo, IBlockTileEntity - { - public string TileEntityName - { - get { return "Monster Spawner"; } - } - - public NBTCompoundNode TileEntitySchema - { - get { return tileEntitySchema; } - } - - public BlockInfoMonster (int id, string name) - : base(id, name) - { - } - - protected static new NBTCompoundNode tileEntitySchema = BlockInfo.tileEntitySchema.MergeInto(new NBTCompoundNode("") - { - new NBTScalerNode("EntityId", NBT_Type.TAG_STRING), - new NBTScalerNode("Delay", NBT_Type.TAG_SHORT), - }); - } - - public class BlockInfoChest : BlockInfo, IBlockTileEntity - { - public string TileEntityName - { - get { return "Trap"; } - } - - public NBTCompoundNode TileEntitySchema - { - get { return tileEntitySchema; } - } - - public BlockInfoChest (int id, string name) - : base(id, name) - { - } - - protected static new NBTCompoundNode tileEntitySchema = BlockInfo.tileEntitySchema.MergeInto(new NBTCompoundNode("") - { - new NBTListNode("Items", NBT_Type.TAG_COMPOUND), - }); - } - - public class BlockInfoFurnace : BlockInfo, IBlockTileEntity - { - public string TileEntityName - { - get { return "Furnace"; } - } - - public NBTCompoundNode TileEntitySchema - { - get { return tileEntitySchema; } - } - - public BlockInfoFurnace (int id, string name) - : base(id, name) - { - } - - protected static new NBTCompoundNode tileEntitySchema = BlockInfo.tileEntitySchema.MergeInto(new NBTCompoundNode("") - { - new NBTScalerNode("BurnTime", NBT_Type.TAG_SHORT), - new NBTScalerNode("CookTime", NBT_Type.TAG_SHORT), - new NBTListNode("Items", NBT_Type.TAG_COMPOUND), - }); - } - - public class BlockInfoSign : BlockInfo, IBlockTileEntity - { - public string TileEntityName - { - get { return "Sign"; } - } - - public NBTCompoundNode TileEntitySchema - { - get { return tileEntitySchema; } - } - - public BlockInfoSign (int id, string name) - : base(id, name) - { - } - - protected static new NBTCompoundNode tileEntitySchema = BlockInfo.tileEntitySchema.MergeInto(new NBTCompoundNode("") - { - new NBTScalerNode("Text1", NBT_Type.TAG_STRING), - new NBTScalerNode("Text2", NBT_Type.TAG_STRING), - new NBTScalerNode("Text3", NBT_Type.TAG_STRING), - new NBTScalerNode("Text4", NBT_Type.TAG_STRING), - }); } } diff --git a/NBToolkit/NBToolkit/Map/BlockKey.cs b/NBToolkit/NBToolkit/Map/BlockKey.cs index 5332d9e..5d58775 100644 --- a/NBToolkit/NBToolkit/Map/BlockKey.cs +++ b/NBToolkit/NBToolkit/Map/BlockKey.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit +namespace NBToolkit.Map { public struct BlockKey : IEquatable { diff --git a/NBToolkit/NBToolkit/Map/BlockManager.cs b/NBToolkit/NBToolkit/Map/BlockManager.cs index b23f712..fbcc5a2 100644 --- a/NBToolkit/NBToolkit/Map/BlockManager.cs +++ b/NBToolkit/NBToolkit/Map/BlockManager.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit +namespace NBToolkit.Map { public class BlockManager { @@ -39,6 +39,16 @@ namespace NBToolkit _chunkMan = bm._chunkMan; } + public virtual Block GetBlock (int x, int y, int z) + { + _cache = GetChunk(x, y, z); + if (_cache == null || !Check(x, y, z)) { + return null; + } + + return new Block(_cache, x & CHUNK_XMASK, y, z & CHUNK_ZMASK); + } + public virtual BlockRef GetBlockRef (int x, int y, int z) { _cache = GetChunk(x, y, z); @@ -94,8 +104,6 @@ namespace NBToolkit return true; } - public void SetBlock (int x, int y, int z, int id, int data) { } - public virtual bool SetBlockID (int x, int y, int z, int id) { _cache = GetChunk(x, y, z); diff --git a/NBToolkit/NBToolkit/Map/BlockRef.cs b/NBToolkit/NBToolkit/Map/BlockRef.cs index e7f334d..d3ca969 100644 --- a/NBToolkit/NBToolkit/Map/BlockRef.cs +++ b/NBToolkit/NBToolkit/Map/BlockRef.cs @@ -2,11 +2,11 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit +namespace NBToolkit.Map { public class BlockRef : IBlock { - protected ChunkRef _chunk; + protected IChunk _chunk; protected int _lx; protected int _ly; @@ -71,7 +71,7 @@ namespace NBToolkit set { _chunk.SetBlockSkyLight(_lx, _ly, _lz, value); } } - public BlockRef (ChunkRef c, int lx, int ly, int lz) + public BlockRef (IChunk c, int lx, int ly, int lz) { _chunk = c; _lx = lx; @@ -86,5 +86,20 @@ namespace NBToolkit BlockLight = block.BlockLight; SkyLight = block.SkyLight; } + + public TileEntity GetTileEntity () + { + return _chunk.GetTileEntity(_lx, _ly, _lz); + } + + public bool SetTileEntity (TileEntity te) + { + return _chunk.SetTileEntity(_lx, _ly, _lz, te); + } + + public bool ClearTileEntity () + { + return _chunk.ClearTileEntity(_lx, _ly, _lz); + } } } diff --git a/NBToolkit/NBToolkit/Map/Chunk.cs b/NBToolkit/NBToolkit/Map/Chunk.cs new file mode 100644 index 0000000..2bb976f --- /dev/null +++ b/NBToolkit/NBToolkit/Map/Chunk.cs @@ -0,0 +1,364 @@ +using System; +using System.IO; + +namespace NBToolkit.Map +{ + using NBT; + + public interface IChunk + { + int X { get; } + int Z { get; } + + bool IsTerrainPopulated { get; set; } + + bool Save (Stream outStream); + + Block GetBlock (int lx, int ly, int lz); + BlockRef GetBlockRef (int lx, int ly, int lz); + BlockInfo GetBlockInfo (int lx, int ly, int lz); + + int GetBlockID (int lx, int ly, int lz); + int GetBlockData (int lx, int ly, int lz); + int GetBlockLight (int lx, int ly, int lz); + int GetBlockSkyLight (int lx, int ly, int lz); + + bool SetBlockID (int lx, int ly, int lz, int id); + bool SetBlockData (int lx, int ly, int lz, int data); + bool SetBlockLight (int lx, int ly, int lz, int light); + bool SetBlockSkyLight (int lx, int ly, int lz, int light); + + int CountBlockID (int id); + int CountBlockData (int id, int data); + + int GetHeight (int lx, int lz); + + TileEntity GetTileEntity (int lx, int ly, int lz); + bool SetTileEntity (int lx, int ly, int lz, TileEntity te); + bool ClearTileEntity (int lx, int ly, int lz); + } + + public class Chunk : IChunk + { + private NBT_Tree _tree; + + private int _cx; + private int _cz; + + protected NBT_ByteArray _blocks; + protected NibbleArray _data; + protected NibbleArray _blockLight; + protected NibbleArray _skyLight; + protected NBT_ByteArray _heightMap; + + protected NBT_List _entities; + protected NBT_List _tileEntities; + + public int X + { + get { return _cx; } + } + + public int Z + { + get { return _cz; } + } + + public bool IsTerrainPopulated + { + get { return _tree.Root["Level"].ToNBTCompound()["TerrainPopulated"].ToNBTByte() == 1; } + set { _tree.Root["Level"].ToNBTCompound()["TerrainPopulated"].ToNBTByte().Data = (byte)(value ? 1 : 0); } + } + + public Chunk (int x, int z) + { + _cx = x; + _cz = z; + + BuildNBTTree(); + } + + public Chunk (NBT_Tree tree) + { + _tree = tree; + if (new ChunkVerifier(tree).Verify() == false) { + throw new MalformedNBTTreeException(); + } + + 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; + + _cx = level["xPos"].ToNBTInt(); + _cz = level["zPos"].ToNBTInt(); + } + + private void BuildNBTTree () + { + int elements2 = BlockManager.CHUNK_XLEN * BlockManager.CHUNK_ZLEN; + int elements3 = elements2 * BlockManager.CHUNK_YLEN; + + _blocks = new NBT_ByteArray(new byte[elements3]); + NBT_ByteArray data = new NBT_ByteArray(new byte[elements3 >> 1]); + NBT_ByteArray blocklight = new NBT_ByteArray(new byte[elements3 >> 1]); + NBT_ByteArray skylight = new NBT_ByteArray(new byte[elements3 >> 1]); + _heightMap = new NBT_ByteArray(new byte[elements2]); + _entities = new NBT_List(NBT_Type.TAG_COMPOUND); + _tileEntities = new NBT_List(NBT_Type.TAG_COMPOUND); + + _data = new NibbleArray(data.Data); + _blockLight = new NibbleArray(blocklight.Data); + _skyLight = new NibbleArray(skylight.Data); + + NBT_Compound level = new NBT_Compound(); + level.Add("Blocks", _blocks); + level.Add("Data", data); + level.Add("SkyLight", blocklight); + level.Add("BlockLight", skylight); + level.Add("HeightMap", _heightMap); + level.Add("Entities", _entities); + level.Add("TileEntities", _tileEntities); + level.Add("LastUpdate", new NBT_Long()); + level.Add("xPos", new NBT_Int()); + level.Add("zPos", new NBT_Int()); + level.Add("TerrainPopulated", new NBT_Byte()); + + _tree = new NBT_Tree(); + _tree.Root.Add("Level", level); + } + + public bool Save (Stream outStream) + { + if (outStream == null || !outStream.CanWrite) { + return false; + } + + _tree.WriteTo(outStream); + outStream.Close(); + + return true; + } + + public Block GetBlock (int lx, int ly, int lz) + { + return new Block(this, lx, ly, lz); + } + + public BlockRef GetBlockRef (int lx, int ly, int lz) + { + return new BlockRef(this, lx, ly, lz); + } + + public BlockInfo GetBlockInfo (int lx, int ly, int lz) + { + return BlockInfo.BlockTable[GetBlockID(lx, ly, lz)]; + } + + public int GetBlockID (int lx, int ly, int lz) + { + return _blocks.Data[lx << 11 | lz << 7 | ly]; + } + + public int GetBlockData (int lx, int ly, int lz) + { + return _data[lx << 11 | lz << 7 | ly]; + } + + public int GetBlockLight (int lx, int ly, int lz) + { + return _blockLight[lx << 11 | lz << 7 | ly]; + } + + public int GetBlockSkyLight (int lx, int ly, int lz) + { + return _skyLight[lx << 11 | lz << 7 | ly]; + } + + public bool SetBlockID (int lx, int ly, int lz, int id) + { + int index = lx << 11 | lz << 7 | ly; + if (_blocks.Data[index] == id) { + return false; + } + + // Update tile entities + + if (BlockInfo.SchemaTable[_blocks[index]] != null && + BlockInfo.SchemaTable[_blocks[index]] != BlockInfo.SchemaTable[id]) { + ClearTileEntity(lx, ly, lz); + } + + // Update height map + + int tileHeight = GetHeight(lx, lz); + int newOpacity = BlockInfo.BlockTable[id].Opacity; + + if (ly > tileHeight && newOpacity > BlockInfo.MIN_OPACITY) { + _heightMap[lz << 4 | lx] = (byte)ly; + } + else if (ly == tileHeight && newOpacity == BlockInfo.MIN_OPACITY) { + for (int i = ly - 1; i >= 0; i--) { + if (BlockInfo.BlockTable[GetBlockID(lx, i, lz)].Opacity > BlockInfo.MIN_OPACITY) { + _heightMap[lz << 4 | lx] = (byte)i; + break; + } + } + } + + // Update value + + _blocks.Data[index] = (byte)id; + return true; + } + + public bool SetBlockData (int lx, int ly, int lz, int data) + { + int index = lx << 11 | lz << 7 | ly; + if (_data[index] == data) { + return false; + } + + _data[index] = data; + return true; + } + + public bool SetBlockLight (int lx, int ly, int lz, int light) + { + int index = lx << 11 | lz << 7 | ly; + if (_blockLight[index] == light) { + return false; + } + + _blockLight[index] = light; + return true; + } + + public bool SetBlockSkyLight (int lx, int ly, int lz, int light) + { + int index = lx << 11 | lz << 7 | ly; + if (_skyLight[index] == light) { + return false; + } + + _skyLight[index] = light; + return true; + } + + public int CountBlockID (int id) + { + int c = 0; + for (int i = 0; i < _blocks.Length; i++) { + if (_blocks[i] == id) { + c++; + } + } + + return c; + } + + public int CountBlockData (int id, int data) + { + int c = 0; + for (int i = 0; i < _blocks.Length; i++) { + if (_blocks[i] == id && _data[i] == data) { + c++; + } + } + + return c; + } + + public int GetHeight (int lx, int lz) + { + return _heightMap[lz << 4 | lx]; + } + + public TileEntity GetTileEntity (int lx, int ly, int lz) + { + foreach (NBT_Compound te in _tileEntities) { + if (te["x"].ToNBTInt().Data == lx && + te["y"].ToNBTInt().Data == ly && + te["z"].ToNBTInt().Data == lz) { + return new TileEntity(te); + } + } + + return null; + } + + 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) { + return false; + } + + if (!te.Verify(schema)) { + return false; + } + + ClearTileEntity(lx, ly, lz); + + int x = BlockX(lx); + int y = BlockY(ly); + int z = BlockZ(lz); + + if (!te.LocatedAt(x, y, z)) { + te = te.Copy(); + te.Relocate(x, y, z); + } + + _tileEntities.Add(te.Root); + + return true; + } + + public bool ClearTileEntity (int x, int y, int z) + { + TileEntity te = GetTileEntity(x, y, z); + if (te == null) { + return false; + } + + return _tileEntities.Remove(te.Root); + } + + public virtual void SetLocation (int x, int z) + { + int diffx = x - _cx; + int diffz = z - _cz; + + _cx = x; + _cz = z; + + foreach (NBT_Compound te in _tileEntities) { + te["x"].ToNBTInt().Data += diffx * BlockManager.CHUNK_XLEN; + te["z"].ToNBTInt().Data += diffz * BlockManager.CHUNK_ZLEN; + } + } + + protected int BlockX (int lx) + { + return _cx * BlockManager.CHUNK_XLEN + lx; + } + + protected int BlockY (int ly) + { + return ly; + } + + protected int BlockZ (int lz) + { + return _cz * BlockManager.CHUNK_ZLEN + lz; + } + } +} diff --git a/NBToolkit/NBToolkit/Map/ChunkEnumerator.cs b/NBToolkit/NBToolkit/Map/ChunkEnumerator.cs index 90b916c..8807749 100644 --- a/NBToolkit/NBToolkit/Map/ChunkEnumerator.cs +++ b/NBToolkit/NBToolkit/Map/ChunkEnumerator.cs @@ -5,7 +5,7 @@ using System.Text; using System.Text.RegularExpressions; using System.IO; -namespace NBToolkit +namespace NBToolkit.Map { public class ChunkList : IEnumerable { diff --git a/NBToolkit/NBToolkit/Map/ChunkKey.cs b/NBToolkit/NBToolkit/Map/ChunkKey.cs index 03837db..4510705 100644 --- a/NBToolkit/NBToolkit/Map/ChunkKey.cs +++ b/NBToolkit/NBToolkit/Map/ChunkKey.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit +namespace NBToolkit.Map { public struct ChunkKey : IEquatable { diff --git a/NBToolkit/NBToolkit/Map/ChunkManager.cs b/NBToolkit/NBToolkit/Map/ChunkManager.cs index 779b434..0cf4418 100644 --- a/NBToolkit/NBToolkit/Map/ChunkManager.cs +++ b/NBToolkit/NBToolkit/Map/ChunkManager.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit +namespace NBToolkit.Map { public class ChunkManager { diff --git a/NBToolkit/NBToolkit/Map/ChunkRef.cs b/NBToolkit/NBToolkit/Map/ChunkRef.cs index 8a18c54..868767c 100644 --- a/NBToolkit/NBToolkit/Map/ChunkRef.cs +++ b/NBToolkit/NBToolkit/Map/ChunkRef.cs @@ -1,87 +1,40 @@ using System; using System.Collections.Generic; using System.Text; +using System.IO; -namespace NBToolkit +namespace NBToolkit.Map { using NBT; - public interface IChunk + public class ChunkRef : IChunk { - bool IsPopulated { get; set; } + private ChunkManager _chunkMan; + private Chunk _chunk; - BlockInfo GetBlockInfo (int lx, int ly, int lz); + private int _cx; + private int _cz; - int GetBlockID (int lx, int ly, int lz); - int GetBlockData (int lx, int ly, int lz); - int GetBlockLight (int lx, int ly, int lz); - int GetBlockSkyLight (int lx, int ly, int lz); - - void GetBlockID (int lx, int ly, int lz, int id); - void GetBlockData (int lx, int ly, int lz, int data); - void GetBlockLight (int lx, int ly, int lz, int light); - void GetBlockSkyLight (int lx, int ly, int lz, int light); - - //int CountBlocks (Predicate match); - - int CountBlockID (int id); - int CountBlockData (int id, int data); - - int GetHeight (int lx, int lz); - - NBT_Compound GetTileEntity (int lx, int ly, int lz); - - void AddTileEntity (int lx, int ly, int lz, string id, NBT_Compound data); - void RemoveTileEntity (int lx, int ly, int lz); - - //IEnumerable FilterBlocks (Predicate match); - } - - public class ChunkRef - { - protected int _cx; - protected int _cz; - - protected NBT_Tree _nbt = null; - protected NBT_ByteArray _blocks = null; - protected NibbleArray _data = null; - protected NibbleArray _blockLight = null; - protected NibbleArray _skyLight = null; - - protected bool _dirty = false; - - protected ChunkManager _chunkMan; + private bool _dirty; public int X { - get - { - return _cx; - } + get { return _cx; } } public int Z { - get - { - return _cz; - } + get { return _cz; } } public int LocalX { - get - { - return _cx & ChunkManager.REGION_XMASK; - } + get { return _cx & ChunkManager.REGION_XMASK; } } public int LocalZ { - get - { - return _cz & ChunkManager.REGION_ZMASK; - } + get { return _cz & ChunkManager.REGION_ZMASK; } } public ChunkRef (ChunkManager cm, int cx, int cz) @@ -96,217 +49,25 @@ namespace NBToolkit } } - public bool Save () + private Chunk GetChunk () { - if (_dirty) { - if (SaveTree()) { - _dirty = false; - return true; - } - return false; + if (_chunk == null) { + _chunk = new Chunk(GetTree()); } - - return true; + return _chunk; } - protected NBT_Tree GetTree () + private NBT_Tree GetTree () { - if (_nbt != null) { - return _nbt; - } - Region r = _chunkMan.GetRegion(_cx, _cz); if (r == null || !r.ChunkExists(LocalX, LocalZ)) { throw new MissingChunkException(); } - _nbt = r.GetChunkTree(LocalX, LocalZ); - ChunkVerifier cv = new ChunkVerifier(_nbt); - cv.Verify(); - - return _nbt; + return r.GetChunkTree(LocalX, LocalZ); } - protected bool SaveTree () - { - if (_nbt != null) { - _blocks = null; - _data = null; - - Region r = _chunkMan.GetRegion(_cx, _cz); - if (r == null || !r.ChunkExists(LocalX, LocalZ)) { - throw new MissingChunkException(); - } - - return r.SaveChunkTree(LocalX, LocalZ, _nbt); - } - - return false; - } - - public Block GetBlock (int lx, int ly, int lz) - { - return new Block(this, lx, ly, lz); - } - - public BlockRef GetBlockRef (int lx, int ly, int lz) - { - return new BlockRef(this, lx, ly, lz); - } - - public int GetBlockID (int x, int y, int z) - { - if (_blocks == null) { - _blocks = GetTree().Root["Level"].ToNBTCompound()["Blocks"].ToNBTByteArray(); - } - - return _blocks.Data[x << 11 | z << 7 | y]; - } - - public bool SetBlockID (int x, int y, int z, int id) - { - if (_blocks == null) { - _blocks = GetTree().Root["Level"].ToNBTCompound()["Blocks"].ToNBTByteArray(); - } - - int index = x << 11 | z << 7 | y; - if (_blocks.Data[index] == id) { - return false; - } - - _blocks.Data[index] = (byte)id; - MarkDirty(); - - return true; - } - - public int CountBlockID (int id) - { - if (_blocks == null) { - _blocks = GetTree().Root["Level"].ToNBTCompound()["Blocks"].ToNBTByteArray(); - } - - int c = 0; - for (int i = 0; i < _blocks.Length; i++) { - if (_blocks.Data[i] == id) { - c++; - } - } - - return c; - } - - public int GetBlockData (int x, int y, int z) - { - if (_data == null) { - _data = new NibbleArray(GetTree().Root["Level"].ToNBTCompound()["Data"].ToNBTByteArray().Data); - } - - return _data[x << 11 | z << 7 | y]; - } - - public bool SetBlockData (int x, int y, int z, int data) - { - if (_data == null) { - _data = new NibbleArray(GetTree().Root["Level"].ToNBTCompound()["Data"].ToNBTByteArray().Data); - } - - int index = x << 11 | z << 7 | y; - if (_data[index] == data) { - return false; - } - - _data[index] = data; - MarkDirty(); - - return true; - } - - public int GetBlockLight (int x, int y, int z) - { - if (_blockLight == null) { - _blockLight = new NibbleArray(GetTree().Root["Level"].ToNBTCompound()["BlockLight"].ToNBTByteArray().Data); - } - - return _blockLight[x << 11 | z << 7 | y]; - } - - public bool SetBlockLight (int x, int y, int z, int light) - { - if (_blockLight == null) { - _blockLight = new NibbleArray(GetTree().Root["Level"].ToNBTCompound()["BlockLight"].ToNBTByteArray().Data); - } - - int index = x << 11 | z << 7 | y; - if (_blockLight[index] == light) { - return false; - } - - _blockLight[index] = light; - MarkDirty(); - - return true; - } - - public int GetBlockSkyLight (int x, int y, int z) - { - if (_skyLight == null) { - _skyLight = new NibbleArray(GetTree().Root["Level"].ToNBTCompound()["SkyLight"].ToNBTByteArray().Data); - } - - return _skyLight[x << 11 | z << 7 | y]; - } - - public bool SetBlockSkyLight (int x, int y, int z, int light) - { - if (_skyLight == null) { - _skyLight = new NibbleArray(GetTree().Root["Level"].ToNBTCompound()["SkyLight"].ToNBTByteArray().Data); - } - - int index = x << 11 | z << 7 | y; - if (_skyLight[index] == light) { - return false; - } - - _skyLight[index] = light; - MarkDirty(); - - return true; - } - - public bool IsPopulated () - { - return GetTree().Root["Level"].ToNBTCompound()["TerrainPopulated"].ToNBTByte().Data == 1; - } - - public NBT_Compound GetTileEntity (int x, int y, int z) - { - NBT_List telist = GetTree().Root["Level"].ToNBTCompound()["TileEntities"].ToNBTList(); - - foreach (NBT_Compound te in telist) { - if (te["x"].ToNBTInt().Data == x && - te["y"].ToNBTInt().Data == y && - te["z"].ToNBTInt().Data == z) { - return te; - } - } - - return null; - } - - public bool RemoveTileEntity (int x, int y, int z) - { - NBT_Compound te = GetTileEntity(x, y, z); - if (te == null) { - return false; - } - - NBT_List telist = GetTree().Root["Level"].ToNBTCompound()["TileEntities"].ToNBTList(); - - return telist.Remove(te); - } - - protected bool MarkDirty () + private bool MarkDirty () { if (_dirty) { return false; @@ -317,6 +78,23 @@ namespace NBToolkit return true; } + public bool Save () + { + if (_dirty) { + Region r = _chunkMan.GetRegion(_cx, _cz); + if (r == null || !r.ChunkExists(LocalX, LocalZ)) { + throw new MissingChunkException(); + } + + if (GetChunk().Save(r.GetChunkOutStream(_cx, _cz))) { + _dirty = false; + return true; + } + return false; + } + return true; + } + public ChunkRef GetNorthNeighbor () { return _chunkMan.GetChunk(_cx - 1, _cz); @@ -336,5 +114,186 @@ namespace NBToolkit { return _chunkMan.GetChunk(_cx, _cz + 1); } + + #region IChunk Members + + public bool IsTerrainPopulated + { + get { return GetChunk().IsTerrainPopulated; } + set + { + if (GetChunk().IsTerrainPopulated != value) { + GetChunk().IsTerrainPopulated = value; + MarkDirty(); + } + } + } + + public bool Save (Stream outStream) + { + if (_dirty) { + if (GetChunk().Save(outStream)) { + _dirty = false; + return true; + } + return false; + } + return true; + } + + public Block GetBlock (int lx, int ly, int lz) + { + return new Block(this, lx, ly, lz); + } + + public BlockRef GetBlockRef (int lx, int ly, int lz) + { + return new BlockRef(this, lx, ly, lz); + } + + public BlockInfo GetBlockInfo (int lx, int ly, int lz) + { + return GetChunk().GetBlockInfo(lx, ly, lz); + } + + public int GetBlockID (int lx, int ly, int lz) + { + return GetChunk().GetBlockID(lx, ly, lz); + } + + public int GetBlockData (int lx, int ly, int lz) + { + return GetChunk().GetBlockData(lx, ly, lz); + } + + public int GetBlockLight (int lx, int ly, int lz) + { + return GetChunk().GetBlockSkyLight(lx, ly, lz); + } + + public int GetBlockSkyLight (int lx, int ly, int lz) + { + return GetChunk().GetBlockSkyLight(lx, ly, lz); + } + + public bool SetBlockID (int lx, int ly, int lz, int id) + { + if (GetChunk().SetBlockID(lx, ly, lz, id)) { + MarkDirty(); + return true; + } + return false; + } + + public bool SetBlockData (int lx, int ly, int lz, int data) + { + if (GetChunk().SetBlockData(lx, ly, lz, data)) { + MarkDirty(); + return true; + } + return false; + } + + public bool SetBlockLight (int lx, int ly, int lz, int light) + { + if (GetChunk().SetBlockLight(lx, ly, lz, light)) { + MarkDirty(); + return true; + } + return false; + } + + public bool SetBlockSkyLight (int lx, int ly, int lz, int light) + { + if (GetChunk().SetBlockSkyLight(lx, ly, lz, light)) { + MarkDirty(); + return true; + } + return false; + } + + public int CountBlockID (int id) + { + return GetChunk().CountBlockID(id); + } + + public int CountBlockData (int id, int data) + { + return GetChunk().CountBlockData(id, data); + } + + public int GetHeight (int lx, int lz) + { + return GetChunk().GetHeight(lx, lz); + } + + public TileEntity GetTileEntity (int lx, int ly, int lz) + { + return GetChunk().GetTileEntity(lx, ly, lz); + } + + public bool SetTileEntity (int lx, int ly, int lz, TileEntity te) + { + if (GetChunk().SetTileEntity(lx, ly, lz, te)) { + MarkDirty(); + return true; + } + return false; + } + + public bool ClearTileEntity (int lx, int ly, int lz) + { + if (GetChunk().ClearTileEntity(lx, ly, lz)) { + MarkDirty(); + return true; + } + return false; + } + + #endregion } + + /*public bool VerifyTileEntities () + { + bool pass = true; + + NBT_List telist = GetTree().Root["Level"].ToNBTCompound()["TileEntities"].ToNBTList(); + + foreach (NBT_Value val in telist) { + NBT_Compound tree = val as NBT_Compound; + if (tree == null) { + pass = false; + continue; + } + + if (new NBTVerifier(tree, TileEntity.BaseSchema).Verify() == false) { + pass = false; + continue; + } + + int x = tree["x"].ToNBTInt() & BlockManager.CHUNK_XMASK; + int y = tree["y"].ToNBTInt() & BlockManager.CHUNK_YMASK; + int z = tree["z"].ToNBTInt() & BlockManager.CHUNK_ZMASK; + int id = GetBlockID(x, y, z); + + NBTCompoundNode schema = BlockInfo.SchemaTable[id]; + if (schema == null) { + pass = false; + continue; + } + + pass = new NBTVerifier(tree, schema).Verify() && pass; + } + + return pass; + } + + private static bool LocalBounds (int lx, int ly, int lz) + { + return lx >= 0 && lx < BlockManager.CHUNK_XLEN && + ly >= 0 && ly < BlockManager.CHUNK_YLEN && + lz >= 0 && lz < BlockManager.CHUNK_ZLEN; + }*/ + + public class MalformedNBTTreeException : Exception { } } diff --git a/NBToolkit/NBToolkit/Map/ChunkVerifier.cs b/NBToolkit/NBToolkit/Map/ChunkVerifier.cs index 9a7d535..039825e 100644 --- a/NBToolkit/NBToolkit/Map/ChunkVerifier.cs +++ b/NBToolkit/NBToolkit/Map/ChunkVerifier.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit +namespace NBToolkit.Map { using NBT; diff --git a/NBToolkit/NBToolkit/Map/NBT/NBT.cs b/NBToolkit/NBToolkit/Map/NBT/NBT.cs index 68977a1..1e0e9a8 100644 --- a/NBToolkit/NBToolkit/Map/NBT/NBT.cs +++ b/NBToolkit/NBToolkit/Map/NBT/NBT.cs @@ -4,8 +4,9 @@ using System.Text; using System.IO; using System.IO.Compression; -namespace NBToolkit.NBT +namespace NBToolkit.Map.NBT { + using Map.Utility; public class NBT_Tree { diff --git a/NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs b/NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs index bce0f76..4b4ce9c 100644 --- a/NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs +++ b/NBToolkit/NBToolkit/Map/NBT/NBTSchema.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit.NBT +namespace NBToolkit.Map.NBT { public abstract class NBTSchemaNode { @@ -35,6 +35,34 @@ namespace NBToolkit.NBT } } + public class NBTStringNode : NBTSchemaNode + { + private string _value; + private int _length; + + public int Length + { + get { return _length; } + } + + public string Value + { + get { return _value; } + } + + public NBTStringNode (string name, string value) + : base(name) + { + _value = value; + } + + public NBTStringNode (string name, int length) + : base(name) + { + _length = length; + } + } + public class NBTArrayNode : NBTSchemaNode { private int _length; @@ -61,6 +89,7 @@ namespace NBToolkit.NBT { private NBT_Type _type; private int _length; + private NBTSchemaNode _subschema; public int Length { @@ -72,11 +101,15 @@ namespace NBToolkit.NBT get { return _type; } } + public NBTSchemaNode SubSchema + { + get { return _subschema; } + } + public NBTListNode (string name, NBT_Type type) : base(name) { _type = type; - _length = 0; } public NBTListNode (string name, NBT_Type type, int length) @@ -85,6 +118,21 @@ namespace NBToolkit.NBT _type = type; _length = length; } + + public NBTListNode (string name, NBT_Type type, NBTSchemaNode subschema) + : base(name) + { + _type = type; + _subschema = subschema; + } + + public NBTListNode (string name, NBT_Type type, int length, NBTSchemaNode subschema) + : base(name) + { + _type = type; + _length = length; + _subschema = subschema; + } } public class NBTCompoundNode : NBTSchemaNode, ICollection @@ -163,6 +211,10 @@ namespace NBToolkit.NBT public NBTCompoundNode MergeInto (NBTCompoundNode tree) { foreach (NBTSchemaNode node in _subnodes) { + NBTSchemaNode f = tree._subnodes.Find(n => n.Name == node.Name); + if (f != null) { + tree.Remove(f); + } tree.Add(node); } diff --git a/NBToolkit/NBToolkit/Map/NBT/NBTValues.cs b/NBToolkit/NBToolkit/Map/NBT/NBTValues.cs index 4fe4cfb..b3cc556 100644 --- a/NBToolkit/NBToolkit/Map/NBT/NBTValues.cs +++ b/NBToolkit/NBToolkit/Map/NBT/NBTValues.cs @@ -2,7 +2,9 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit.NBT { +namespace NBToolkit.Map.NBT { + + using Map.Utility; /// /// Describes the type of value held by an NBT_Tag @@ -22,7 +24,7 @@ namespace NBToolkit.NBT { TAG_COMPOUND = 10 } - public abstract class NBT_Value + public abstract class NBT_Value : ICopyable { virtual public NBT_Null ToNBTNull () { throw new InvalidCastException(); } virtual public NBT_Byte ToNBTByte () { throw new InvalidCastException(); } @@ -37,12 +39,22 @@ namespace NBToolkit.NBT { virtual public NBT_Compound ToNBTCompound () { throw new InvalidCastException(); } virtual public NBT_Type GetNBTType () { return NBT_Type.TAG_END; } + + public virtual NBT_Value Copy () + { + return null; + } } public class NBT_Null : NBT_Value { override public NBT_Null ToNBTNull () { return this; } override public NBT_Type GetNBTType () { return NBT_Type.TAG_END; } + + public override NBT_Value Copy () + { + return new NBT_Null(); + } } public class NBT_Byte : NBT_Value @@ -65,6 +77,11 @@ namespace NBToolkit.NBT { _data = d; } + public override NBT_Value Copy () + { + return new NBT_Byte(_data); + } + public static implicit operator NBT_Byte (byte b) { return new NBT_Byte(b); @@ -96,6 +113,11 @@ namespace NBToolkit.NBT { _data = d; } + public override NBT_Value Copy () + { + return new NBT_Short(_data); + } + public static implicit operator NBT_Short (short s) { return new NBT_Short(s); @@ -127,6 +149,11 @@ namespace NBToolkit.NBT { _data = d; } + public override NBT_Value Copy () + { + return new NBT_Int(_data); + } + public static implicit operator NBT_Int (int i) { return new NBT_Int(i); @@ -158,6 +185,11 @@ namespace NBToolkit.NBT { _data = d; } + public override NBT_Value Copy () + { + return new NBT_Long(_data); + } + public static implicit operator NBT_Long (long l) { return new NBT_Long(l); @@ -189,6 +221,11 @@ namespace NBToolkit.NBT { _data = d; } + public override NBT_Value Copy () + { + return new NBT_Float(_data); + } + public static implicit operator NBT_Float (float f) { return new NBT_Float(f); @@ -220,6 +257,11 @@ namespace NBToolkit.NBT { _data = d; } + public override NBT_Value Copy () + { + return new NBT_Double(_data); + } + public static implicit operator NBT_Double (double d) { return new NBT_Double(d); @@ -256,6 +298,14 @@ namespace NBToolkit.NBT { _data = d; } + public override NBT_Value Copy () + { + byte[] arr = new byte[_data.Length]; + _data.CopyTo(arr, 0); + + return new NBT_ByteArray(arr); + } + public byte this [int index] { get { return _data[index]; } set { _data[index] = value; } @@ -292,6 +342,11 @@ namespace NBToolkit.NBT { _data = d; } + public override NBT_Value Copy () + { + return new NBT_String(_data); + } + public static implicit operator NBT_String (string s) { return new NBT_String(s); @@ -334,6 +389,15 @@ namespace NBToolkit.NBT { _items = items; } + public override NBT_Value Copy () + { + NBT_List list = new NBT_List(_type); + foreach (NBT_Value item in _items) { + list.Add(item.Copy()); + } + return list; + } + #region IList Members public int IndexOf (NBT_Value item) @@ -435,6 +499,15 @@ namespace NBToolkit.NBT { _tags = new Dictionary(); } + public override NBT_Value Copy () + { + NBT_Compound list = new NBT_Compound(); + foreach (KeyValuePair item in _tags) { + list[item.Key] = item.Value.Copy(); + } + return list; + } + #region IDictionary Members public void Add (string key, NBT_Value value) diff --git a/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs b/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs index 3ba8c53..e51d16d 100644 --- a/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs +++ b/NBToolkit/NBToolkit/Map/NBT/NBTVerifier.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit.NBT +namespace NBToolkit.Map.NBT { public delegate void MissingTagHandler (Object o, TagEventArgs e); public delegate void InvalidTagTypeHandler (Object o, TagEventArgs e); @@ -28,11 +28,6 @@ namespace NBToolkit.NBT get { return _tagName; } } - /* public NBT_Tag Tag - { - get { return _tag; } - }*/ - public TagEventArgs (string tagName) : base() { @@ -56,7 +51,7 @@ namespace NBToolkit.NBT public class NBTVerifier : INBTVerifier { - private NBT_Compound _root; + private NBT_Value _root; private NBTSchemaNode _schema; public event MissingTagHandler MissingTag; @@ -65,7 +60,7 @@ namespace NBToolkit.NBT public NBTVerifier () { } - public NBTVerifier (NBT_Compound root, NBTSchemaNode schema) + public NBTVerifier (NBT_Value root, NBTSchemaNode schema) { _root = root; _schema = schema; @@ -96,6 +91,11 @@ namespace NBToolkit.NBT return VerifyScaler(tag, scaler); } + NBTStringNode str = schema as NBTStringNode; + if (str != null) { + return VerifyString(tag, str); + } + NBTArrayNode array = schema as NBTArrayNode; if (array != null) { return VerifyArray(tag, array); @@ -124,6 +124,26 @@ namespace NBToolkit.NBT return true; } + private bool VerifyString (NBT_Value tag, NBTStringNode schema) + { + NBT_String stag = tag as NBT_String; + if (stag == null) { + OnInvalidTagType(new TagEventArgs(schema, tag)); + return false; + } + if (schema.Length > 0 && stag.Length > schema.Length) { + OnInvalidTagValue(new TagEventArgs(schema, tag)); + return false; + } + if (schema.Name != null && stag.Data != schema.Value) { + OnInvalidTagValue(new TagEventArgs(schema, tag)); + return false; + } + + return true; + } + + private bool VerifyArray (NBT_Value tag, NBTArrayNode schema) { NBT_ByteArray atag = tag as NBT_ByteArray; @@ -155,7 +175,17 @@ namespace NBToolkit.NBT return false; } - return true; + bool pass = true; + + // If a subschema is set, test all items in list against it + + if (schema.SubSchema != null) { + foreach (NBT_Value v in ltag) { + pass = Verify(v, schema.SubSchema) && pass; + } + } + + return pass; } private bool VerifyCompound (NBT_Value tag, NBTCompoundNode schema) diff --git a/NBToolkit/NBToolkit/Map/Region.cs b/NBToolkit/NBToolkit/Map/Region.cs index 36a30e8..83ef8dd 100644 --- a/NBToolkit/NBToolkit/Map/Region.cs +++ b/NBToolkit/NBToolkit/Map/Region.cs @@ -4,7 +4,7 @@ using System.Text; using System.Text.RegularExpressions; using System.IO; -namespace NBToolkit +namespace NBToolkit.Map { using NBT; @@ -160,6 +160,12 @@ namespace NBToolkit return true; } + public Stream GetChunkOutStream (int lcx, int lcz) + { + RegionFile rf = GetRegionFile(); + return rf.GetChunkDataOutputStream(lcx, lcz); + } + public bool ChunkExists (int lcx, int lcz) { RegionFile rf = GetRegionFile(); diff --git a/NBToolkit/NBToolkit/Map/RegionEnumerator.cs b/NBToolkit/NBToolkit/Map/RegionEnumerator.cs index c05d74d..d87b1c1 100644 --- a/NBToolkit/NBToolkit/Map/RegionEnumerator.cs +++ b/NBToolkit/NBToolkit/Map/RegionEnumerator.cs @@ -5,7 +5,7 @@ using System.Text; using System.Text.RegularExpressions; using System.IO; -namespace NBToolkit +namespace NBToolkit.Map { public class RegionList : IEnumerable { diff --git a/NBToolkit/NBToolkit/Map/RegionFile.cs b/NBToolkit/NBToolkit/Map/RegionFile.cs index f854440..49bfb99 100644 --- a/NBToolkit/NBToolkit/Map/RegionFile.cs +++ b/NBToolkit/NBToolkit/Map/RegionFile.cs @@ -5,7 +5,7 @@ using System.IO; using Ionic.Zlib; using System.Collections; -namespace NBToolkit +namespace NBToolkit.Map { public class RegionFile : IDisposable { diff --git a/NBToolkit/NBToolkit/Map/RegionKey.cs b/NBToolkit/NBToolkit/Map/RegionKey.cs index 9a25edf..082aee8 100644 --- a/NBToolkit/NBToolkit/Map/RegionKey.cs +++ b/NBToolkit/NBToolkit/Map/RegionKey.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace NBToolkit +namespace NBToolkit.Map { public struct RegionKey : IEquatable { diff --git a/NBToolkit/NBToolkit/Map/RegionManager.cs b/NBToolkit/NBToolkit/Map/RegionManager.cs index ee1bec0..f871d90 100644 --- a/NBToolkit/NBToolkit/Map/RegionManager.cs +++ b/NBToolkit/NBToolkit/Map/RegionManager.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Text; using System.IO; -namespace NBToolkit +namespace NBToolkit.Map { public class RegionManager { diff --git a/NBToolkit/NBToolkit/Map/TileEntity.cs b/NBToolkit/NBToolkit/Map/TileEntity.cs new file mode 100644 index 0000000..06945c0 --- /dev/null +++ b/NBToolkit/NBToolkit/Map/TileEntity.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NBToolkit.Map +{ + using NBT; + using Utility; + + public class TileEntity : ICopyable + { + private NBT_Compound _tree; + + public NBT_Compound Root + { + get { return _tree; } + } + + public TileEntity (NBT_Compound tree) + { + _tree = tree; + } + + public 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 lx, int ly, int lz) + { + return _tree["x"].ToNBTInt().Data == lx && + _tree["y"].ToNBTInt().Data == ly && + _tree["z"].ToNBTInt().Data == lz; + } + + public bool Relocate (int lx, int ly, int lz) + { + if (lx >= 0 && lx < BlockManager.CHUNK_XLEN && + ly >= 0 && ly < BlockManager.CHUNK_YLEN && + lz >= 0 && lz < BlockManager.CHUNK_ZLEN) { + _tree["x"].ToNBTInt().Data = lx; + _tree["y"].ToNBTInt().Data = ly; + _tree["z"].ToNBTInt().Data = lz; + return true; + } + + return false; + } + + #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), + new NBTScalerNode("x", NBT_Type.TAG_INT), + new NBTScalerNode("y", NBT_Type.TAG_INT), + new NBTScalerNode("z", NBT_Type.TAG_INT), + }; + + 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), + }); + + public static readonly NBTCompoundNode SignSchema = BaseSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "Sign"), + new NBTScalerNode("Text1", NBT_Type.TAG_STRING), + new NBTScalerNode("Text2", NBT_Type.TAG_STRING), + new NBTScalerNode("Text3", NBT_Type.TAG_STRING), + new NBTScalerNode("Text4", NBT_Type.TAG_STRING), + }); + + public static readonly NBTCompoundNode MonsterSpawnerSchema = BaseSchema.MergeInto(new NBTCompoundNode("") + { + new NBTStringNode("id", "MonsterSpawner"), + new NBTScalerNode("EntityId", NBT_Type.TAG_STRING), + new NBTScalerNode("Delay", NBT_Type.TAG_SHORT), + }); + + 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 + + #region ICopyable Members + + public TileEntity Copy () + { + return new TileEntity(_tree.Copy() as NBT_Compound); + } + + #endregion + } +} diff --git a/NBToolkit/NBToolkit/Map/Utility/Interface.cs b/NBToolkit/NBToolkit/Map/Utility/Interface.cs new file mode 100644 index 0000000..7747757 --- /dev/null +++ b/NBToolkit/NBToolkit/Map/Utility/Interface.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NBToolkit.Map.Utility +{ + public interface ICopyable + { + T Copy (); + } +} diff --git a/NBToolkit/NBToolkit/Map/Utility/NibbleArray.cs b/NBToolkit/NBToolkit/Map/Utility/NibbleArray.cs index 34b95a0..0fca489 100644 --- a/NBToolkit/NBToolkit/Map/Utility/NibbleArray.cs +++ b/NBToolkit/NBToolkit/Map/Utility/NibbleArray.cs @@ -43,7 +43,7 @@ namespace NBToolkit { get { - return _data.Length >> 1; + return _data.Length << 1; } } } diff --git a/NBToolkit/NBToolkit/Map/World.cs b/NBToolkit/NBToolkit/Map/World.cs index 2bec498..49d7978 100644 --- a/NBToolkit/NBToolkit/Map/World.cs +++ b/NBToolkit/NBToolkit/Map/World.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Text; using System.IO; -namespace NBToolkit +namespace NBToolkit.Map { public class World { diff --git a/NBToolkit/NBToolkit/NBToolkit.csproj b/NBToolkit/NBToolkit/NBToolkit.csproj index 1ffcf81..56b1470 100644 --- a/NBToolkit/NBToolkit/NBToolkit.csproj +++ b/NBToolkit/NBToolkit/NBToolkit.csproj @@ -62,6 +62,7 @@ + @@ -70,13 +71,15 @@ + + - - - - + + + + - + diff --git a/NBToolkit/NBToolkit/Oregen.cs b/NBToolkit/NBToolkit/Oregen.cs index c61e8ed..9abeaee 100644 --- a/NBToolkit/NBToolkit/Oregen.cs +++ b/NBToolkit/NBToolkit/Oregen.cs @@ -5,7 +5,8 @@ using NDesk.Options; namespace NBToolkit { - using NBT; + using Map; + using Map.NBT; public class OregenOptions : TKOptions, IChunkFilterable { @@ -186,7 +187,7 @@ namespace NBToolkit int affectedChunks = 0; foreach (ChunkRef chunk in new FilteredChunkList(world.GetChunkManager(), opt.GetChunkFilter())) { - if (chunk == null || !chunk.IsPopulated()) { + if (chunk == null || !chunk.IsTerrainPopulated) { continue; } @@ -263,7 +264,7 @@ namespace NBToolkit return false; } - int blockID = base.GetBlockID(x, y, z); + int blockID = _cache.GetBlockID(x & CHUNK_XMASK, y, z & CHUNK_ZMASK); if ( ((opt.OPT_OA) && (blockID != opt.OPT_ID)) || diff --git a/NBToolkit/NBToolkit/Program.cs b/NBToolkit/NBToolkit/Program.cs index 6aaa8e2..be519a0 100644 --- a/NBToolkit/NBToolkit/Program.cs +++ b/NBToolkit/NBToolkit/Program.cs @@ -4,7 +4,8 @@ using System.Text; namespace NBToolkit { - using NBT; + using Map; + using Map.NBT; class Program { diff --git a/NBToolkit/NBToolkit/Purge.cs b/NBToolkit/NBToolkit/Purge.cs index c05f5ce..3e6d22f 100644 --- a/NBToolkit/NBToolkit/Purge.cs +++ b/NBToolkit/NBToolkit/Purge.cs @@ -5,7 +5,8 @@ using NDesk.Options; namespace NBToolkit { - using NBT; + using Map; + using Map.NBT; public class PurgeOptions : TKOptions, IChunkFilterable { diff --git a/NBToolkit/NBToolkit/Replace.cs b/NBToolkit/NBToolkit/Replace.cs index 8f0138e..843c1fe 100644 --- a/NBToolkit/NBToolkit/Replace.cs +++ b/NBToolkit/NBToolkit/Replace.cs @@ -5,7 +5,8 @@ using NDesk.Options; namespace NBToolkit { - using NBT; + using Map; + using Map.NBT; public class ReplaceOptions : TKOptions, IChunkFilterable {