From f82ea3e9467c8542e7ec0d25a5ff89e99a03e5a8 Mon Sep 17 00:00:00 2001 From: Justin Aquadro Date: Mon, 12 Mar 2012 00:09:49 -0400 Subject: [PATCH] Creating interrum branch that replaces Alpha and Beta support with Anvil support. --- SubstrateCS/Source/AlphaBlockCollection.cs | 29 +- SubstrateCS/Source/AnvilChunk.cs | 774 +++++++++++++++++++ SubstrateCS/Source/Core/BlockFluid.cs | 4 +- SubstrateCS/Source/Core/BlockTileEntities.cs | 4 +- SubstrateCS/Source/Core/BlockTileTicks.cs | 4 +- SubstrateCS/Source/Core/ByteArray.cs | 28 +- SubstrateCS/Source/Core/NibbleArray.cs | 36 +- 7 files changed, 854 insertions(+), 25 deletions(-) create mode 100644 SubstrateCS/Source/AnvilChunk.cs diff --git a/SubstrateCS/Source/AlphaBlockCollection.cs b/SubstrateCS/Source/AlphaBlockCollection.cs index 4be69a9..054d7c7 100644 --- a/SubstrateCS/Source/AlphaBlockCollection.cs +++ b/SubstrateCS/Source/AlphaBlockCollection.cs @@ -17,10 +17,15 @@ namespace Substrate private readonly int _ydim; private readonly int _zdim; - private XZYByteArray _blocks; - private XZYNibbleArray _data; - private XZYNibbleArray _blockLight; - private XZYNibbleArray _skyLight; + //private XZYByteArray _blocks; + //private XZYNibbleArray _data; + //private XZYNibbleArray _blockLight; + //private XZYNibbleArray _skyLight; + private IDataArray3 _blocks; + private IDataArray3 _data; + private IDataArray3 _blockLight; + private IDataArray3 _skyLight; + private ZXByteArray _heightMap; private TagNodeList _tileEntities; @@ -71,10 +76,10 @@ namespace Substrate /// An array of height map values. /// A list of tile entities corresponding to blocks in this collection. public AlphaBlockCollection ( - XZYByteArray blocks, - XZYNibbleArray data, - XZYNibbleArray blockLight, - XZYNibbleArray skyLight, + IDataArray3 blocks, + IDataArray3 data, + IDataArray3 blockLight, + IDataArray3 skyLight, ZXByteArray heightMap, TagNodeList tileEntities) : this(blocks, data, blockLight, skyLight, heightMap, tileEntities, null) @@ -92,10 +97,10 @@ namespace Substrate /// A list of tile entities corresponding to blocks in this collection. /// A list of tile ticks corresponding to blocks in this collection. public AlphaBlockCollection ( - XZYByteArray blocks, - XZYNibbleArray data, - XZYNibbleArray blockLight, - XZYNibbleArray skyLight, + IDataArray3 blocks, + IDataArray3 data, + IDataArray3 blockLight, + IDataArray3 skyLight, ZXByteArray heightMap, TagNodeList tileEntities, TagNodeList tileTicks) diff --git a/SubstrateCS/Source/AnvilChunk.cs b/SubstrateCS/Source/AnvilChunk.cs new file mode 100644 index 0000000..292334b --- /dev/null +++ b/SubstrateCS/Source/AnvilChunk.cs @@ -0,0 +1,774 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Substrate.Nbt; +using Substrate.Core; +using System.IO; + +namespace Substrate.Source +{ + public class AnvilSection : INbtObject, ICopyable + { + public static SchemaNodeCompound SectionSchema = new SchemaNodeCompound() + { + new SchemaNodeArray("Blocks", 4096), + new SchemaNodeArray("Data", 2048), + new SchemaNodeArray("SkyLight", 2048), + new SchemaNodeArray("BlockLight", 2048), + new SchemaNodeScaler("Y", TagType.TAG_INT), + new SchemaNodeArray("AddBlocks", 2048, SchemaOptions.OPTIONAL), + }; + + private const int XDIM = 16; + private const int YDIM = 16; + private const int ZDIM = 16; + + private const int MIN_Y = 0; + private const int MAX_Y = 15; + + private TagNodeCompound _tree; + + private int _y; + private YZXByteArray _blocks; + private YZXNibbleArray _data; + private YZXNibbleArray _blockLight; + private YZXNibbleArray _skyLight; + private YZXNibbleArray _addBlocks; + + private AnvilSection () + { + } + + public AnvilSection (int y) + { + if (y < MIN_Y || y > MAX_Y) + throw new ArgumentOutOfRangeException(); + + _y = y; + BuildNbtTree(); + } + + public AnvilSection (TagNodeCompound tree) + { + LoadTree(_tree); + } + + public int Y + { + get { return _y; } + set + { + if (value < MIN_Y || value > MAX_Y) + throw new ArgumentOutOfRangeException(); + + _y = value; + _tree["Y"].ToTagInt().Data = _y; + } + } + + public YZXByteArray Blocks + { + get { return _blocks; } + } + + public YZXNibbleArray Data + { + get { return _data; } + } + + public YZXNibbleArray BlockLight + { + get { return _blockLight; } + } + + public YZXNibbleArray SkyLight + { + get { return _skyLight; } + } + + public YZXNibbleArray AddBlocks + { + get { return _addBlocks; } + } + + public bool CheckEmpty () + { + return CheckBlocksEmpty() && CheckAddBlocksEmpty(); + } + + private bool CheckBlocksEmpty () + { + for (int i = 0; i < _blocks.Length; i++) + if (_blocks[i] != 0) + return false; + return true; + } + + private bool CheckAddBlocksEmpty () + { + if (_addBlocks != null) + for (int i = 0; i < _addBlocks.Length; i++) + if (_addBlocks[i] != 0) + return false; + return true; + } + + #region INbtObject Members + + public AnvilSection LoadTree (TagNode tree) + { + TagNodeCompound ctree = tree as TagNodeCompound; + if (ctree == null) { + return null; + } + + _y = ctree["Y"] as TagNodeInt; + + _blocks = new YZXByteArray(XDIM, YDIM, ZDIM, ctree["Blocks"] as TagNodeByteArray); + _data = new YZXNibbleArray(XDIM, YDIM, ZDIM, ctree["Data"] as TagNodeByteArray); + _skyLight = new YZXNibbleArray(XDIM, YDIM, ZDIM, ctree["SkyLight"] as TagNodeByteArray); + _blockLight = new YZXNibbleArray(XDIM, YDIM, ZDIM, ctree["BlockLight"] as TagNodeByteArray); + + if (!ctree.ContainsKey("AddBlocks")) + _tree["AddBlocks"] = new TagNodeByteArray(new byte[2048]); + _addBlocks = new YZXNibbleArray(XDIM, YDIM, ZDIM, ctree["AddBlocks"] as TagNodeByteArray); + + return this; + } + + public AnvilSection LoadTreeSafe (TagNode tree) + { + if (!ValidateTree(tree)) { + return null; + } + + return LoadTree(tree); + } + + public TagNode BuildTree () + { + BuildConditional(); + + return _tree; + } + + public bool ValidateTree (TagNode tree) + { + NbtVerifier v = new NbtVerifier(tree, SectionSchema); + return v.Verify(); + } + + #endregion + + private void BuildConditional () + { + if (CheckAddBlocksEmpty()) { + _tree.Remove("AddBlocks"); + } + } + + #region ICopyable Members + + public AnvilSection Copy () + { + return new AnvilSection().LoadTree(_tree.Copy()); + } + + #endregion + + private void BuildNbtTree () + { + int elements3 = XDIM * YDIM * ZDIM; + + TagNodeByteArray blocks = new TagNodeByteArray(new byte[elements3]); + TagNodeByteArray data = new TagNodeByteArray(new byte[elements3 >> 1]); + TagNodeByteArray skyLight = new TagNodeByteArray(new byte[elements3 >> 1]); + TagNodeByteArray blockLight = new TagNodeByteArray(new byte[elements3 >> 1]); + TagNodeByteArray addBlocks = new TagNodeByteArray(new byte[elements3 >> 1]); + + _blocks = new YZXByteArray(XDIM, YDIM, ZDIM, blocks); + _data = new YZXNibbleArray(XDIM, YDIM, ZDIM, data); + _skyLight = new YZXNibbleArray(XDIM, YDIM, ZDIM, skyLight); + _blockLight = new YZXNibbleArray(XDIM, YDIM, ZDIM, blockLight); + _addBlocks = new YZXNibbleArray(XDIM, YDIM, ZDIM, addBlocks); + + TagNodeCompound tree = new TagNodeCompound(); + tree.Add("Y", new TagNodeInt(_y)); + tree.Add("Blocks", blocks); + tree.Add("Data", data); + tree.Add("SkyLight", skyLight); + tree.Add("BlockLight", blockLight); + tree.Add("AddBlocks", addBlocks); + + _tree = tree; + } + } + + + + public class CompositeYZXByteArray : IDataArray3 + { + private YZXByteArray[] _sections; + + public CompositeYZXByteArray (YZXByteArray[] sections) + { + for (int i = 0; i < sections.Length; i++) + if (sections[i] == null) + throw new ArgumentException("sections argument cannot have null entries."); + + for (int i = 0; i < sections.Length; i++) { + if (sections[i].Length != sections[0].Length + || sections[i].XDim != sections[0].XDim + || sections[i].YDim != sections[0].YDim + || sections[i].ZDim != sections[0].ZDim) + throw new ArgumentException("All elements in sections argument must have same metrics."); + } + + _sections = sections; + } + + #region IByteArray3 Members + + public byte this[int x, int y, int z] + { + get + { + int ydiv = y / _sections[0].YDim; + int yrem = y - (ydiv * _sections[0].YDim); + return _sections[ydiv][x, yrem, z]; + } + + set + { + int ydiv = y / _sections[0].YDim; + int yrem = y - (ydiv * _sections[0].YDim); + _sections[ydiv][x, yrem, z] = value; + } + } + + public int XDim + { + get { return _sections[0].XDim; } + } + + public int YDim + { + get { return _sections[0].YDim; } + } + + public int ZDim + { + get { return _sections[0].ZDim; } + } + + public int GetIndex (int x, int y, int z) + { + int ydiv = y / _sections[0].YDim; + int yrem = y - (ydiv * _sections[0].YDim); + return ydiv * _sections[ydiv].GetIndex(x, yrem, z); + } + + public void GetMultiIndex (int index, out int x, out int y, out int z) + { + int idiv = index / _sections[0].Length; + int irem = index - (idiv * _sections[0].Length); + _sections[idiv].GetMultiIndex(irem, out x, out y, out z); + } + + #endregion + + #region IByteArray Members + + public byte this[int i] + { + get + { + int idiv = i / _sections[0].Length; + int irem = i - (idiv * _sections[0].Length); + return _sections[idiv][irem]; + } + set + { + int idiv = i / _sections[0].Length; + int irem = i - (idiv * _sections[0].Length); + _sections[idiv][irem] = value; + } + } + + public int Length + { + get { return _sections[0].Length * _sections.Length; } + } + + public void Clear () + { + for (int i = 0; i < _sections.Length; i++) + _sections[i].Clear(); + } + + #endregion + } + + public class CompositeYZXNibbleArray : IDataArray3 + { + private YZXNibbleArray[] _sections; + + public CompositeYZXNibbleArray (YZXNibbleArray[] sections) + { + for (int i = 0; i < sections.Length; i++) + if (sections[i] == null) + throw new ArgumentException("sections argument cannot have null entries."); + + for (int i = 0; i < sections.Length; i++) { + if (sections[i].Length != sections[0].Length + || sections[i].XDim != sections[0].XDim + || sections[i].YDim != sections[0].YDim + || sections[i].ZDim != sections[0].ZDim) + throw new ArgumentException("All elements in sections argument must have same metrics."); + } + + _sections = sections; + } + + #region IByteArray3 Members + + public byte this[int x, int y, int z] + { + get + { + int ydiv = y / _sections[0].YDim; + int yrem = y - (ydiv * _sections[0].YDim); + return _sections[ydiv][x, yrem, z]; + } + + set + { + int ydiv = y / _sections[0].YDim; + int yrem = y - (ydiv * _sections[0].YDim); + _sections[ydiv][x, yrem, z] = value; + } + } + + public int XDim + { + get { return _sections[0].XDim; } + } + + public int YDim + { + get { return _sections[0].YDim; } + } + + public int ZDim + { + get { return _sections[0].ZDim; } + } + + public int GetIndex (int x, int y, int z) + { + int ydiv = y / _sections[0].YDim; + int yrem = y - (ydiv * _sections[0].YDim); + return ydiv * _sections[ydiv].GetIndex(x, yrem, z); + } + + public void GetMultiIndex (int index, out int x, out int y, out int z) + { + int idiv = index / _sections[0].Length; + int irem = index - (idiv * _sections[0].Length); + _sections[idiv].GetMultiIndex(irem, out x, out y, out z); + } + + #endregion + + #region IByteArray Members + + public byte this[int i] + { + get + { + int idiv = i / _sections[0].Length; + int irem = i - (idiv * _sections[0].Length); + return _sections[idiv][irem]; + } + set + { + int idiv = i / _sections[0].Length; + int irem = i - (idiv * _sections[0].Length); + _sections[idiv][irem] = value; + } + } + + public int Length + { + get { return _sections[0].Length * _sections.Length; } + } + + public void Clear () + { + for (int i = 0; i < _sections.Length; i++) + _sections[i].Clear(); + } + + #endregion + } + + public class AnvilChunk : IChunk, INbtObject, ICopyable + { + public static SchemaNodeCompound LevelSchema = new SchemaNodeCompound() + { + new SchemaNodeCompound("Level") + { + new SchemaNodeList("Sections", TagType.TAG_COMPOUND, new SchemaNodeCompound() { + new SchemaNodeArray("Blocks", 4096), + new SchemaNodeArray("Data", 2048), + new SchemaNodeArray("SkyLight", 2048), + new SchemaNodeArray("BlockLight", 2048), + new SchemaNodeScaler("Y", TagType.TAG_INT), + new SchemaNodeArray("AddBlocks", 2048, SchemaOptions.OPTIONAL), + }), + new SchemaNodeArray("Biomes", 256), + new SchemaNodeArray("HeightMap", 256), + new SchemaNodeList("Entities", TagType.TAG_COMPOUND, SchemaOptions.CREATE_ON_MISSING), + new SchemaNodeList("TileEntities", TagType.TAG_COMPOUND, TileEntity.Schema, SchemaOptions.CREATE_ON_MISSING), + new SchemaNodeList("TileTicks", TagType.TAG_COMPOUND, TileTick.Schema, SchemaOptions.OPTIONAL), + new SchemaNodeScaler("LastUpdate", TagType.TAG_LONG, SchemaOptions.CREATE_ON_MISSING), + new SchemaNodeScaler("xPos", TagType.TAG_INT), + new SchemaNodeScaler("zPos", TagType.TAG_INT), + new SchemaNodeScaler("TerrainPopulated", TagType.TAG_BYTE, SchemaOptions.CREATE_ON_MISSING), + }, + }; + + private const int XDIM = 16; + private const int YDIM = 256; + private const int ZDIM = 16; + + private NbtTree _tree; + + private int _cx; + private int _cz; + + private AnvilSection[] _sections; + + private IDataArray3 _blocks; + private IDataArray3 _data; + private IDataArray3 _blockLight; + private IDataArray3 _skyLight; + + private ZXByteArray _heightMap; + + private TagNodeList _entities; + private TagNodeList _tileEntities; + private TagNodeList _tileTicks; + + private AlphaBlockCollection _blockManager; + private EntityCollection _entityManager; + + + private AnvilChunk () + { + _sections = new AnvilSection[16]; + } + + public int X + { + get { return _cx; } + } + + public int Z + { + get { return _cz; } + } + + public AlphaBlockCollection Blocks + { + get { return _blockManager; } + } + + public EntityCollection Entities + { + get { return _entityManager; } + } + + public NbtTree Tree + { + get { return _tree; } + } + + public bool IsTerrainPopulated + { + get { return _tree.Root["Level"].ToTagCompound()["TerrainPopulated"].ToTagByte() == 1; } + set { _tree.Root["Level"].ToTagCompound()["TerrainPopulated"].ToTagByte().Data = (byte)(value ? 1 : 0); } + } + + public static AnvilChunk Create (int x, int z) + { + AnvilChunk c = new AnvilChunk(); + + c._cx = x; + c._cz = z; + + c.BuildNBTTree(); + return c; + } + + public static AnvilChunk Create (NbtTree tree) + { + AnvilChunk c = new AnvilChunk(); + + return c.LoadTree(tree.Root); + } + + public static AnvilChunk CreateVerified (NbtTree tree) + { + AnvilChunk c = new AnvilChunk(); + + return c.LoadTreeSafe(tree.Root); + } + + /// + /// Updates the chunk's global world coordinates. + /// + /// Global X-coordinate. + /// Global Z-coordinate. + public virtual void SetLocation (int x, int z) + { + int diffx = (x - _cx) * XDIM; + int diffz = (z - _cz) * ZDIM; + + // Update chunk position + + _cx = x; + _cz = z; + + _tree.Root["Level"].ToTagCompound()["xPos"].ToTagInt().Data = x; + _tree.Root["Level"].ToTagCompound()["zPos"].ToTagInt().Data = z; + + // Update tile entity coordinates + + List tileEntites = new List(); + foreach (TagNodeCompound tag in _tileEntities) { + TileEntity te = TileEntityFactory.Create(tag); + if (te == null) { + te = TileEntity.FromTreeSafe(tag); + } + + if (te != null) { + te.MoveBy(diffx, 0, diffz); + tileEntites.Add(te); + } + } + + _tileEntities.Clear(); + foreach (TileEntity te in tileEntites) { + _tileEntities.Add(te.BuildTree()); + } + + // Update tile tick coordinates + + if (_tileTicks != null) { + List tileTicks = new List(); + foreach (TagNodeCompound tag in _tileTicks) { + TileTick tt = TileTick.FromTreeSafe(tag); + + if (tt != null) { + tt.MoveBy(diffx, 0, diffz); + tileTicks.Add(tt); + } + } + + _tileTicks.Clear(); + foreach (TileTick tt in tileTicks) { + _tileTicks.Add(tt.BuildTree()); + } + } + + // Update entity coordinates + + List entities = new List(); + foreach (TypedEntity entity in _entityManager) { + entity.MoveBy(diffx, 0, diffz); + entities.Add(entity); + } + + _entities.Clear(); + foreach (TypedEntity entity in entities) { + _entityManager.Add(entity); + } + } + + public bool Save (Stream outStream) + { + if (outStream == null || !outStream.CanWrite) { + return false; + } + + BuildConditional(); + + _tree.WriteTo(outStream); + outStream.Close(); + + return true; + } + + #region INbtObject Members + + public AnvilChunk LoadTree (TagNode tree) + { + TagNodeCompound ctree = tree as TagNodeCompound; + if (ctree == null) { + return null; + } + + _tree = new NbtTree(ctree); + + TagNodeCompound level = _tree.Root["Level"] as TagNodeCompound; + + TagNodeCompound sections = level["Sections"] as TagNodeCompound; + foreach (TagNodeCompound section in sections.Values) { + AnvilSection anvilSection = new AnvilSection(section); + if (anvilSection.Y < 0 || anvilSection.Y >= _sections.Length) + continue; + _sections[anvilSection.Y] = anvilSection; + } + + YZXByteArray[] blocksBA = new YZXByteArray[_sections.Length]; + YZXNibbleArray[] dataBA = new YZXNibbleArray[_sections.Length]; + YZXNibbleArray[] skyLightBA = new YZXNibbleArray[_sections.Length]; + YZXNibbleArray[] blockLightBA = new YZXNibbleArray[_sections.Length]; + + for (int i = 0; i < _sections.Length; i++) { + if (_sections[i] == null) + _sections[i] = new AnvilSection(i); + + blocksBA[i] = _sections[i].Blocks; + dataBA[i] = _sections[i].Data; + skyLightBA[i] = _sections[i].SkyLight; + blockLightBA[i] = _sections[i].BlockLight; + } + + _blocks = new CompositeYZXByteArray(blocksBA); + _data = new CompositeYZXNibbleArray(dataBA); + _skyLight = new CompositeYZXNibbleArray(skyLightBA); + _blockLight = new CompositeYZXNibbleArray(blockLightBA); + + _heightMap = new ZXByteArray(XDIM, ZDIM, level["HeightMap"] as TagNodeByteArray); + + _entities = level["Entities"] as TagNodeList; + _tileEntities = level["TileEntities"] as TagNodeList; + + if (level.ContainsKey("TileTicks")) + _tileTicks = level["TileTicks"] as TagNodeList; + else + _tileTicks = new TagNodeList(TagType.TAG_COMPOUND); + + // List-type patch up + if (_entities.Count == 0) { + level["Entities"] = new TagNodeList(TagType.TAG_COMPOUND); + _entities = level["Entities"] as TagNodeList; + } + + if (_tileEntities.Count == 0) { + level["TileEntities"] = new TagNodeList(TagType.TAG_COMPOUND); + _tileEntities = level["TileEntities"] as TagNodeList; + } + + if (_tileTicks.Count == 0) { + level["TileTicks"] = new TagNodeList(TagType.TAG_COMPOUND); + _tileTicks = level["TileTicks"] as TagNodeList; + } + + _cx = level["xPos"].ToTagInt(); + _cz = level["zPos"].ToTagInt(); + + _blockManager = new AlphaBlockCollection(_blocks, _data, _blockLight, _skyLight, _heightMap, _tileEntities, _tileTicks); + _entityManager = new EntityCollection(_entities); + + return this; + } + + public AnvilChunk LoadTreeSafe (TagNode tree) + { + if (!ValidateTree(tree)) { + return null; + } + + return LoadTree(tree); + } + + public TagNode BuildTree () + { + BuildConditional(); + + return _tree.Root; + } + + public bool ValidateTree (TagNode tree) + { + NbtVerifier v = new NbtVerifier(tree, LevelSchema); + return v.Verify(); + } + + #endregion + + #region ICopyable Members + + public AnvilChunk Copy () + { + return AnvilChunk.Create(_tree.Copy()); + } + + #endregion + + private void BuildConditional () + { + TagNodeCompound level = _tree.Root["Level"] as TagNodeCompound; + if (_tileTicks != _blockManager.TileTicks && _blockManager.TileTicks.Count > 0) { + _tileTicks = _blockManager.TileTicks; + level["TileTicks"] = _tileTicks; + } + } + + private void BuildNBTTree () + { + int elements2 = XDIM * ZDIM; + + _sections = new AnvilSection[16]; + TagNodeList sections = new TagNodeList(TagType.TAG_COMPOUND); + + for (int i = 0; i < _sections.Length; i++) { + _sections[i] = new AnvilSection(i); + sections.Add(_sections[i].BuildTree()); + } + + TagNodeByteArray heightMap = new TagNodeByteArray(new byte[elements2]); + _heightMap = new ZXByteArray(XDIM, ZDIM, heightMap); + + _entities = new TagNodeList(TagType.TAG_COMPOUND); + _tileEntities = new TagNodeList(TagType.TAG_COMPOUND); + _tileTicks = new TagNodeList(TagType.TAG_COMPOUND); + + TagNodeCompound level = new TagNodeCompound(); + level.Add("Sections", sections); + level.Add("HeightMap", heightMap); + level.Add("Entities", _entities); + level.Add("TileEntities", _tileEntities); + level.Add("TileTicks", _tileTicks); + level.Add("LastUpdate", new TagNodeLong(Timestamp())); + level.Add("xPos", new TagNodeInt(_cx)); + level.Add("zPos", new TagNodeInt(_cz)); + level.Add("TerrainPopulated", new TagNodeByte()); + + _tree = new NbtTree(); + _tree.Root.Add("Level", level); + + _blockManager = new AlphaBlockCollection(_blocks, _data, _blockLight, _skyLight, _heightMap, _tileEntities); + _entityManager = new EntityCollection(_entities); + } + + private int Timestamp () + { + DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0); + return (int)((DateTime.UtcNow - epoch).Ticks / (10000L * 1000L)); + } + } +} diff --git a/SubstrateCS/Source/Core/BlockFluid.cs b/SubstrateCS/Source/Core/BlockFluid.cs index ce14ca8..f8f721d 100644 --- a/SubstrateCS/Source/Core/BlockFluid.cs +++ b/SubstrateCS/Source/Core/BlockFluid.cs @@ -62,7 +62,7 @@ namespace Substrate.Core _chunks = new Dictionary(); } - public void ResetWater (ByteArray blocks, NibbleArray data) + public void ResetWater (IDataArray blocks, IDataArray data) { for (int i = 0; i < blocks.Length; i++) { if ((blocks[i] == BlockInfo.StationaryWater.ID || blocks[i] == BlockInfo.Water.ID) && data[i] != 0) { @@ -75,7 +75,7 @@ namespace Substrate.Core } } - public void ResetLava (ByteArray blocks, NibbleArray data) + public void ResetLava (IDataArray blocks, IDataArray data) { for (int i = 0; i < blocks.Length; i++) { if ((blocks[i] == BlockInfo.StationaryLava.ID || blocks[i] == BlockInfo.Lava.ID) && data[i] != 0) { diff --git a/SubstrateCS/Source/Core/BlockTileEntities.cs b/SubstrateCS/Source/Core/BlockTileEntities.cs index 4bdb7f2..4876da6 100644 --- a/SubstrateCS/Source/Core/BlockTileEntities.cs +++ b/SubstrateCS/Source/Core/BlockTileEntities.cs @@ -8,14 +8,14 @@ namespace Substrate.Core public class BlockTileEntities { - private XZYByteArray _blocks; + private IDataArray3 _blocks; private TagNodeList _tileEntities; private Dictionary _tileEntityTable; public event BlockCoordinateHandler TranslateCoordinates; - public BlockTileEntities (XZYByteArray blocks, TagNodeList tileEntities) + public BlockTileEntities (IDataArray3 blocks, TagNodeList tileEntities) { _blocks = blocks; _tileEntities = tileEntities; diff --git a/SubstrateCS/Source/Core/BlockTileTicks.cs b/SubstrateCS/Source/Core/BlockTileTicks.cs index b592d56..7102c62 100644 --- a/SubstrateCS/Source/Core/BlockTileTicks.cs +++ b/SubstrateCS/Source/Core/BlockTileTicks.cs @@ -6,14 +6,14 @@ namespace Substrate.Core { public class BlockTileTicks { - private XZYByteArray _blocks; + private IDataArray3 _blocks; private TagNodeList _tileTicks; private Dictionary _tileTickTable; public event BlockCoordinateHandler TranslateCoordinates; - public BlockTileTicks (XZYByteArray blocks, TagNodeList tileTicks) + public BlockTileTicks (IDataArray3 blocks, TagNodeList tileTicks) { _blocks = blocks; _tileTicks = tileTicks; diff --git a/SubstrateCS/Source/Core/ByteArray.cs b/SubstrateCS/Source/Core/ByteArray.cs index fc47e13..7bccd17 100644 --- a/SubstrateCS/Source/Core/ByteArray.cs +++ b/SubstrateCS/Source/Core/ByteArray.cs @@ -4,7 +4,27 @@ using System.Collections.Generic; namespace Substrate.Core { - public class ByteArray : ICopyable + public interface IDataArray + { + byte this[int i] { get; set; } + int Length { get; } + + void Clear (); + } + + public interface IDataArray3 : IDataArray + { + byte this[int x, int y, int z] { get; set; } + + int XDim { get; } + int YDim { get; } + int ZDim { get; } + + int GetIndex (int x, int y, int z); + void GetMultiIndex (int index, out int x, out int y, out int z); + } + + public class ByteArray : IDataArray, ICopyable { protected readonly byte[] dataArray; @@ -37,7 +57,7 @@ namespace Substrate.Core } } - #region ICopyable Members + #region ICopyable Members public virtual ByteArray Copy () { @@ -50,7 +70,7 @@ namespace Substrate.Core #endregion } - public sealed class XZYByteArray : ByteArray + public sealed class XZYByteArray : ByteArray, IDataArray3 { private readonly int _xdim; private readonly int _ydim; @@ -135,7 +155,7 @@ namespace Substrate.Core #endregion } - public sealed class YZXByteArray : ByteArray + public sealed class YZXByteArray : ByteArray, IDataArray3 { private readonly int _xdim; private readonly int _ydim; diff --git a/SubstrateCS/Source/Core/NibbleArray.cs b/SubstrateCS/Source/Core/NibbleArray.cs index 4f41f22..14a7af7 100644 --- a/SubstrateCS/Source/Core/NibbleArray.cs +++ b/SubstrateCS/Source/Core/NibbleArray.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; namespace Substrate.Core { - public class NibbleArray : ICopyable + public class NibbleArray : IDataArray, ICopyable { private readonly byte[] _data = null; @@ -82,7 +82,7 @@ namespace Substrate.Core #endregion } - public sealed class XZYNibbleArray : NibbleArray + public sealed class XZYNibbleArray : NibbleArray, IDataArray3 { private readonly int _xdim; private readonly int _ydim; @@ -139,6 +139,21 @@ namespace Substrate.Core get { return _zdim; } } + public int GetIndex (int x, int y, int z) + { + return _ydim * (x * _zdim + z) + y; + } + + public void GetMultiIndex (int index, out int x, out int y, out int z) + { + int yzdim = _ydim * _zdim; + x = index / yzdim; + + int zy = index - (x * yzdim); + z = zy / _ydim; + y = zy - (z * _ydim); + } + #region ICopyable Members public override NibbleArray Copy () @@ -152,7 +167,7 @@ namespace Substrate.Core #endregion } - public sealed class YZXNibbleArray : NibbleArray + public sealed class YZXNibbleArray : NibbleArray, IDataArray3 { private readonly int _xdim; private readonly int _ydim; @@ -208,6 +223,21 @@ namespace Substrate.Core get { return _zdim; } } + public int GetIndex (int x, int y, int z) + { + return _xdim * (y * _zdim + z) + x; + } + + public void GetMultiIndex (int index, out int x, out int y, out int z) + { + int xzdim = _xdim * _zdim; + y = index / xzdim; + + int zx = index - (y * xzdim); + z = zx / _xdim; + x = zx - (z * _xdim); + } + #region ICopyable Members public override NibbleArray Copy ()