diff --git a/Substrate/SubstrateCS/Source/AlphaBlock.cs b/Substrate/SubstrateCS/Source/AlphaBlock.cs index d531eef..42777c2 100644 --- a/Substrate/SubstrateCS/Source/AlphaBlock.cs +++ b/Substrate/SubstrateCS/Source/AlphaBlock.cs @@ -53,11 +53,15 @@ namespace Substrate /// The local X-coordinate of a block within the collection. /// The local Y-coordinate of a block within the collection. /// The local Z-coordinate of a block within the collection. - public AlphaBlock (IAlphaBlockCollection chunk, int lx, int ly, int lz) + public AlphaBlock (AlphaBlockCollection chunk, int lx, int ly, int lz) { _id = chunk.GetID(lx, ly, lz); _data = chunk.GetData(lx, ly, lz); - _tileEntity = chunk.GetTileEntity(lx, ly, lz).Copy(); + + TileEntity te = chunk.GetTileEntity(lx, ly, lz); + if (te != null) { + _tileEntity = te.Copy(); + } } diff --git a/Substrate/SubstrateCS/Source/AlphaBlockCollection.cs b/Substrate/SubstrateCS/Source/AlphaBlockCollection.cs index 83ecf47..31b44d3 100644 --- a/Substrate/SubstrateCS/Source/AlphaBlockCollection.cs +++ b/Substrate/SubstrateCS/Source/AlphaBlockCollection.cs @@ -35,6 +35,71 @@ namespace Substrate public delegate AlphaBlockCollection NeighborLookupHandler (int relx, int rely, int relz); + /// + /// Creates a new of a given dimension. + /// + /// The length of the X-dimension of the collection. + /// The length of the Y-dimension of the collection. + /// The length of the Z-dimension of the collection. + public AlphaBlockCollection (int xdim, int ydim, int zdim) + { + _blocks = new XZYByteArray(xdim, ydim, zdim); + _data = new XZYNibbleArray(xdim, ydim, zdim); + _blockLight = new XZYNibbleArray(xdim, ydim, zdim); + _skyLight = new XZYNibbleArray(xdim, ydim, zdim); + _heightMap = new ZXByteArray(xdim, zdim); + _tileEntities = new TagNodeList(TagType.TAG_COMPOUND); + + _xdim = xdim; + _ydim = ydim; + _zdim = zdim; + + Refresh(); + } + + /// + /// Creates a new overlay on top of Alpha-specific units of data. + /// + /// An array of Block IDs. + /// An array of data nibbles. + /// An array of block light nibbles. + /// An array of sky light nibbles. + /// 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, + ZXByteArray heightMap, + TagNodeList tileEntities) + { + _blocks = blocks; + _data = data; + _blockLight = blockLight; + _skyLight = skyLight; + _heightMap = heightMap; + _tileEntities = tileEntities; + + _xdim = _blocks.XDim; + _ydim = _blocks.YDim; + _zdim = _blocks.ZDim; + + Refresh(); + } + + /// + /// Updates internal managers if underlying data, such as TileEntities, have been modified outside of the container. + /// + public void Refresh () + { + _lightManager = new BlockLight(this); + _fluidManager = new BlockFluid(this); + _tileEntityManager = new BlockTileEntities(_blocks, _tileEntities); + } + + #region Events + public event NeighborLookupHandler ResolveNeighbor { add @@ -61,6 +126,8 @@ namespace Substrate remove { _tileEntityManager.TranslateCoordinates -= value; } } + #endregion + /// /// Gets or sets a value indicating whether changes to blocks will trigger automatic lighting updates. /// @@ -94,38 +161,7 @@ namespace Substrate set { _dirty = value; } } - /// - /// Creates a new overlay on top of Alpha-specific units of data. - /// - /// An array of Block IDs. - /// An array of data nibbles. - /// An array of block light nibbles. - /// An array of sky light nibbles. - /// 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, - ZXByteArray heightMap, - TagNodeList tileEntities) - { - _blocks = blocks; - _data = data; - _blockLight = blockLight; - _skyLight = skyLight; - _heightMap = heightMap; - _tileEntities = tileEntities; - - _xdim = _blocks.XDim; - _ydim = _blocks.YDim; - _zdim = _blocks.ZDim; - - _lightManager = new BlockLight(this); - _fluidManager = new BlockFluid(this); - _tileEntityManager = new BlockTileEntities(_blocks, _tileEntities); - } + /// /// Returns a new object from local coordinates relative to this collection. @@ -473,12 +509,6 @@ namespace Substrate } /// - /// The lighting of the block will be updated to be consistent with the lighting in neighboring blocks. - /// If the block is itself a light source, many nearby blocks may be updated to maintain consistent lighting. These - /// updates may also touch neighboring objects, if they can be resolved. - /// This function assumes that the entire and neighboring s - /// already have consistent lighting, with the exception of the block being updated. If this assumption is violated, - /// lighting may fail to converge correctly. public void UpdateBlockLight (int x, int y, int z) { _lightManager.UpdateBlockLight(x, y, z); @@ -486,127 +516,69 @@ namespace Substrate } /// - /// The lighting of the block will be updated to be consistent with the lighting in neighboring blocks. - /// If the block is itself a light source, many nearby blocks may be updated to maintain consistent lighting. These - /// updates may also touch neighboring objects, if they can be resolved. - /// This function assumes that the entire and neighboring s - /// already have consistent lighting, with the exception of the block being updated. If this assumption is violated, - /// lighting may fail to converge correctly. public void UpdateSkyLight (int x, int y, int z) { _lightManager.UpdateBlockSkyLight(x, y, z); _dirty = true; } - /// - /// Resets the block-source light value to 0 for all blocks in this . - /// + /// public void ResetBlockLight () { _blockLight.Clear(); _dirty = true; } - /// - /// Resets the sky-source light value to 0 for all blocks in this . - /// + /// public void ResetSkyLight () { _skyLight.Clear(); _dirty = true; } - /// - /// Reconstructs the block-source lighting for all blocks in this . - /// - /// This function should only be called after the lighting has been reset in this - /// and all neighboring s, or lighting may fail to converge correctly. - /// This function cannot reset the lighting on its own, due to interactions between s. - /// If many light source or block opacity values will be modified in this , it may - /// be preferable to avoid explicit or implicit calls to and call this function once when - /// modifications are complete. - /// / + /// public void RebuildBlockLight () { _lightManager.RebuildBlockLight(); _dirty = true; } - /// - /// Reconstructs the sky-source lighting for all blocks in this . - /// - /// This function should only be called after the lighting has been reset in this - /// and all neighboring s, or lighting may fail to converge correctly. - /// This function cannot reset the lighting on its own, due to interactions between s. - /// If many light source or block opacity values will be modified in this , it may - /// be preferable to avoid explicit or implicit calls to and call this function once when - /// modifications are complete. - /// + /// public void RebuildSkyLight () { _lightManager.RebuildBlockSkyLight(); _dirty = true; } - /// - /// Reconstructs the height-map for this . - /// + /// public void RebuildHeightMap () { _lightManager.RebuildHeightMap(); _dirty = true; } - /// - /// Reconciles any block-source lighting inconsistencies between this and any of its neighbors. - /// - /// It will be necessary to call this function if an is reset and rebuilt, but - /// some of its neighbors are not. A rebuilt will spill lighting updates into its neighbors, - /// but will not see lighting that should be propagated back from its neighbors. - /// + /// public void StitchBlockLight () { _lightManager.StitchBlockLight(); _dirty = true; } - /// - /// Reconciles any sky-source lighting inconsistencies between this and any of its neighbors. - /// - /// It will be necessary to call this function if an is reset and rebuilt, but - /// some of its neighbors are not. A rebuilt will spill lighting updates into its neighbors, - /// but will not see lighting that should be propagated back from its neighbors. - /// + /// public void StitchSkyLight () { _lightManager.StitchBlockSkyLight(); _dirty = true; } - /// - /// Reconciles any block-source lighting inconsistencies between this and another on a given edge. - /// - /// An -compatible object with the same dimensions as this . - /// The edge that is a neighbor on. - /// It will be necessary to call this function if an is reset and rebuilt, but - /// some of its neighbors are not. A rebuilt will spill lighting updates into its neighbors, - /// but will not see lighting that should be propagated back from its neighbors. - /// + /// public void StitchBlockLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge) { _lightManager.StitchBlockLight(blockset, edge); _dirty = true; } - /// - /// Reconciles any sky-source lighting inconsistencies between this and another on a given edge. - /// - /// An -compatible object with the same dimensions as this . - /// The edge that is a neighbor on. - /// It will be necessary to call this function if an is reset and rebuilt, but - /// some of its neighbors are not. A rebuilt will spill lighting updates into its neighbors, - /// but will not see lighting that should be propagated back from its neighbors. - /// + /// public void StitchSkyLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge) { _lightManager.StitchBlockSkyLight(blockset, edge); @@ -735,7 +707,7 @@ namespace Substrate #region Unbounded Container Implementations - IBlock IBlockCollection.GetBlock (int x, int y, int z) + /*IBlock IBlockCollection.GetBlock (int x, int y, int z) { if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) { return GetBlock(x, y, z); @@ -986,7 +958,7 @@ namespace Substrate SetBlock(x, y, z, block); } throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z"); - } + }*/ #endregion diff --git a/Substrate/SubstrateCS/Source/Core/BlockInterface.cs b/Substrate/SubstrateCS/Source/Core/BlockInterface.cs index 5bf603a..76d1cfd 100644 --- a/Substrate/SubstrateCS/Source/Core/BlockInterface.cs +++ b/Substrate/SubstrateCS/Source/Core/BlockInterface.cs @@ -104,305 +104,6 @@ namespace Substrate.Core bool IsValid { get; } } - /// - /// A basic unconstrained container of blocks. - /// - /// The scope of coordinates is undefined for unconstrained block containers. - public interface IBlockCollection - { - /// - /// Gets a basic block from a block container.. - /// - /// The global X-coordinate of a block. - /// The global Y-coordinate of a block. - /// The global Z-coordinate of a block. - /// A basic from the collection at the given coordinates. - IBlock GetBlock (int x, int y, int z); - - /// - /// Gets a reference object to a basic within a block container. - /// - /// The global X-coordinate of a block. - /// The global Y-coordinate of a block. - /// The global Z-coordinate of a block. - /// A basic acting as a reference directly into the container at the given coordinates. - IBlock GetBlockRef (int x, int y, int z); - - /// - /// Updates a block in a block container with data from an existing object. - /// - /// The global X-coordinate of a block. - /// The global Y-coordinate of a block. - /// The global Z-coordinate of a block. - /// The to copy basic data from. - void SetBlock (int x, int y, int z, IBlock block); - - /// - /// Gets a block's id (type) from a block container. - /// - /// The global X-coordinate of a block. - /// The global Y-coordinate of a block. - /// The global Z-coordinate of a block. - /// The block id (type) from the block container at the given coordinates. - int GetID (int x, int y, int z); - - /// - /// Sets a block's id (type) within a block container. - /// - /// The global X-coordinate of a block. - /// The global Y-coordinate of a block. - /// The global Z-coordinate of a block. - /// The id (type) to assign to a block at the given coordinates. - void SetID (int x, int y, int z, int id); - - /// - /// Gets info and attributes on a block's type within a block container. - /// - /// The global X-coordinate of a block. - /// The global Y-coordinate of a block. - /// The global Z-coordinate of a block. - /// A instance for the block's type. - BlockInfo GetInfo (int x, int y, int z); - } - - /// - /// A container of blocks with set dimensions. - /// - public interface IBoundedBlockCollection : IBlockCollection - { - /// - /// Gets the length of the X-dimension of the container. - /// - int XDim { get; } - - /// - /// Gets the length of the Y-dimension of the container. - /// - int YDim { get; } - - /// - /// Gets the length of the Z-dimension of the container. - /// - int ZDim { get; } - - /// - /// Counts all instances of a block with the given type in the container. - /// - /// The id (type) of the block to count. - /// The count of blocks in the container matching the given id (type). - int CountByID (int id); - - #region Local Overrides - - /// - /// Gets a basic block from a block container.. - /// - /// The container-local X-coordinate of a block. - /// The container-local Y-coordinate of a block. - /// The container-local Z-coordinate of a block. - /// A basic from the collection at the given coordinates. - new IBlock GetBlock (int x, int y, int z); - - /// - /// Gets a reference object to a basic within a block container. - /// - /// The container-local X-coordinate of a block. - /// The container-local Y-coordinate of a block. - /// The container-local Z-coordinate of a block. - /// A basic acting as a reference directly into the container at the given coordinates. - new IBlock GetBlockRef (int x, int y, int z); - - /// - /// Updates a block in a block container with data from an existing object. - /// - /// The container-local X-coordinate of a block. - /// The container-local Y-coordinate of a block. - /// The container-local Z-coordinate of a block. - /// The to copy basic data from. - new void SetBlock (int x, int y, int z, IBlock block); - - /// - /// Gets a block's id (type) from a block container. - /// - /// The container-local X-coordinate of a block. - /// The container-local Y-coordinate of a block. - /// The container-local Z-coordinate of a block. - /// The block id (type) from the block container at the given coordinates. - new int GetID (int x, int y, int z); - - /// - /// Sets a block's id (type) within a block container. - /// - /// The container-local X-coordinate of a block. - /// The container-local Y-coordinate of a block. - /// The container-local Z-coordinate of a block. - /// The id (type) to assign to a block at the given coordinates. - new void SetID (int x, int y, int z, int id); - - /// - /// Gets info and attributes on a block's type within a block container. - /// - /// The container-local X-coordinate of a block. - /// The container-local Y-coordinate of a block. - /// The container-local Z-coordinate of a block. - /// A instance for the block's type. - new BlockInfo GetInfo (int x, int y, int z); - - #endregion - } - - /// - /// An unbounded container of blocks supporting data fields. - /// - public interface IDataBlockCollection : IBlockCollection - { - new IDataBlock GetBlock (int x, int y, int z); - new IDataBlock GetBlockRef (int x, int y, int z); - - void SetBlock (int x, int y, int z, IDataBlock block); - - int GetData (int x, int y, int z); - void SetData (int x, int y, int z, int data); - } - - /// - /// A bounded version of the interface. - /// - public interface IBoundedDataBlockCollection : IDataBlockCollection, IBoundedBlockCollection - { - new IDataBlock GetBlock (int x, int y, int z); - new IDataBlock GetBlockRef (int x, int y, int z); - - new void SetBlock (int x, int y, int z, IDataBlock block); - - new int GetData (int x, int y, int z); - new void SetData (int x, int y, int z, int data); - - int CountByData (int id, int data); - } - - /// - /// An unbounded container of blocks supporting dual-source lighting. - /// - public interface ILitBlockCollection : IBlockCollection - { - new ILitBlock GetBlock (int x, int y, int z); - new ILitBlock GetBlockRef (int x, int y, int z); - - void SetBlock (int x, int y, int z, ILitBlock block); - - // Local Light - int GetBlockLight (int x, int y, int z); - int GetSkyLight (int x, int y, int z); - - void SetBlockLight (int x, int y, int z, int light); - void SetSkyLight (int x, int y, int z, int light); - - int GetHeight (int x, int z); - void SetHeight (int x, int z, int height); - - // Update and propagate light at a single block - void UpdateBlockLight (int x, int y, int z); - void UpdateSkyLight (int x, int y, int z); - } - - /// - /// A bounded version of the interface. - /// - public interface IBoundedLitBlockCollection : ILitBlockCollection, IBoundedBlockCollection - { - new ILitBlock GetBlock (int x, int y, int z); - new ILitBlock GetBlockRef (int x, int y, int z); - - new void SetBlock (int x, int y, int z, ILitBlock block); - - // Local Light - new int GetBlockLight (int x, int y, int z); - new int GetSkyLight (int x, int y, int z); - - new void SetBlockLight (int x, int y, int z, int light); - new void SetSkyLight (int x, int y, int z, int light); - - new int GetHeight (int x, int z); - new void SetHeight (int x, int z, int height); - - // Update and propagate light at a single block - new void UpdateBlockLight (int x, int y, int z); - new void UpdateSkyLight (int x, int y, int z); - - // Zero out light in entire collection - void ResetBlockLight (); - void ResetSkyLight (); - - // Recalculate light in entire collection - void RebuildBlockLight (); - void RebuildSkyLight (); - void RebuildHeightMap (); - - // Reconcile inconsistent lighting between the edges of two containers of same size - void StitchBlockLight (); - void StitchSkyLight (); - - void StitchBlockLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge); - void StitchSkyLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge); - } - - /// - /// An unbounded container for blocks supporting additional properties. - /// - public interface IPropertyBlockCollection : IBlockCollection - { - new IPropertyBlock GetBlock (int x, int y, int z); - new IPropertyBlock GetBlockRef (int x, int y, int z); - - void SetBlock (int x, int y, int z, IPropertyBlock block); - - TileEntity GetTileEntity (int x, int y, int z); - void SetTileEntity (int x, int y, int z, TileEntity te); - - void CreateTileEntity (int x, int y, int z); - void ClearTileEntity (int x, int y, int z); - } - - /// - /// A bounded version of the interface. - /// - public interface IBoundedPropertyBlockCollection : IPropertyBlockCollection, IBoundedBlockCollection - { - new IPropertyBlock GetBlock (int x, int y, int z); - new IPropertyBlock GetBlockRef (int x, int y, int z); - - new void SetBlock (int x, int y, int z, IPropertyBlock block); - - new TileEntity GetTileEntity (int x, int y, int z); - new void SetTileEntity (int x, int y, int z, TileEntity te); - - new void CreateTileEntity (int x, int y, int z); - new void ClearTileEntity (int x, int y, int z); - } - - /// - /// An unbounded container of blocks supporting data, lighting, and properties. - /// - public interface IAlphaBlockCollection : IDataBlockCollection, ILitBlockCollection, IPropertyBlockCollection - { - new AlphaBlock GetBlock (int x, int y, int z); - new AlphaBlockRef GetBlockRef (int x, int y, int z); - - void SetBlock (int x, int y, int z, AlphaBlock block); - } - - /// - /// A bounded version of the interface. - /// - public interface IBoundedAlphaBlockCollection : IAlphaBlockCollection, IBoundedDataBlockCollection, IBoundedLitBlockCollection, IBoundedPropertyBlockCollection - { - new AlphaBlock GetBlock (int x, int y, int z); - new AlphaBlockRef GetBlockRef (int x, int y, int z); - - new void SetBlock (int x, int y, int z, AlphaBlock block); - } - /// /// Provides a common interface for block containers that provide global management. /// diff --git a/Substrate/SubstrateCS/Source/Core/BoundedBlockInterface.cs b/Substrate/SubstrateCS/Source/Core/BoundedBlockInterface.cs new file mode 100644 index 0000000..b52b594 --- /dev/null +++ b/Substrate/SubstrateCS/Source/Core/BoundedBlockInterface.cs @@ -0,0 +1,451 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Substrate.Core +{ + /// + /// A container of blocks with set dimensions. + /// + public interface IBoundedBlockCollection + { + /// + /// Gets the length of the X-dimension of the container. + /// + int XDim { get; } + + /// + /// Gets the length of the Y-dimension of the container. + /// + int YDim { get; } + + /// + /// Gets the length of the Z-dimension of the container. + /// + int ZDim { get; } + + /// + /// Counts all instances of a block with the given type in the bounded block container. + /// + /// The id (type) of the block to count. + /// The count of blocks in the container matching the given id (type). + int CountByID (int id); + + /// + /// Gets a basic block from a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// A basic from the collection at the given coordinates. + IBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a basic within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// A basic acting as a reference directly into the container at the given coordinates. + IBlock GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in a bounded block container with data from an existing object. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The to copy basic data from. + void SetBlock (int x, int y, int z, IBlock block); + + /// + /// Gets a block's id (type) from a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The block id (type) from the block container at the given coordinates. + int GetID (int x, int y, int z); + + /// + /// Sets a block's id (type) within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The id (type) to assign to a block at the given coordinates. + void SetID (int x, int y, int z, int id); + + /// + /// Gets info and attributes on a block's type within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// A instance for the block's type. + BlockInfo GetInfo (int x, int y, int z); + } + + /// + /// A bounded container of blocks supporting data fields. + /// + /// + public interface IBoundedDataBlockCollection : IBoundedBlockCollection + { + /// + /// Gets a block with data field from a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// An from the collection at the given coordinates. + new IDataBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a block with data field within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// An acting as a reference directly into the container at the given coordinates. + new IDataBlock GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in a bounded block container with data from an existing object. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The to copy data from. + void SetBlock (int x, int y, int z, IDataBlock block); + + /// + /// Gets a block's data field from a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The data field of a block at the given coordinates. + int GetData (int x, int y, int z); + + /// + /// Sets a block's data field within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The data field to assign to a block at the given coordinates. + void SetData (int x, int y, int z, int data); + + /// + /// Counts all blocks within a bounded container set to a given id (type) and data value. + /// + /// The id (type) of blocks to match. + /// The data value of blocks to match. + /// A count of all blocks in the container matching both conditions. + int CountByData (int id, int data); + } + + /// + /// A bounded container of blocks supporting dual-source lighting. + /// + /// + public interface IBoundedLitBlockCollection : IBoundedBlockCollection + { + /// + /// Gets a block with lighting information from a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// An from the collection at the given coordinates. + new ILitBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a block with lighting information within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// An acting as a reference directly into the container at the given coordinates. + new ILitBlock GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in a bounded block container with data from an existing object. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The to copy data from. + void SetBlock (int x, int y, int z, ILitBlock block); + + /// + /// Gets a block's block-source light value from a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The block-source light value of a block at the given coordinates. + int GetBlockLight (int x, int y, int z); + + /// + /// Gets a block's sky-source light value from a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The sky-source light value of a block at the given coordinates. + int GetSkyLight (int x, int y, int z); + + /// + /// Sets a block's block-source light value within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The block-source light value to assign to a block at the given coordinates. + void SetBlockLight (int x, int y, int z, int light); + + /// + /// Sets a block's sky-source light value within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The sky-source light value to assign to a block at the given coordinates. + void SetSkyLight (int x, int y, int z, int light); + + /// + /// Gets the Y-coordinate of the lowest block with unobstructed view of the sky at the given coordinates within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The height value of an X-Z coordinate pair in the block container. + /// The height value represents the lowest block with an unobstructed view of the sky. This is the lowest block with + /// a maximum-value sky-light value. Fully transparent blocks, like glass, do not count as an obstruction. + int GetHeight (int x, int z); + + /// + /// Sets the Y-coordinate of the lowest block with unobstructed view of the sky at the given coordinates within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The height value of an X-Z coordinate pair in the block container. + /// Minecraft lighting algorithms rely heavily on this value being correct. Setting this value too low may result in + /// rooms that can never get dark, for example. + void SetHeight (int x, int z, int height); + + /// + /// Recalculates the block-source light value of a single block within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The lighting of the block will be updated to be consistent with the lighting in neighboring blocks. + /// If the block is itself a light source, many nearby blocks may be updated to maintain consistent lighting. These + /// updates may also touch neighboring objects, if they can be resolved. + /// This function assumes that the entire and neighboring s + /// already have consistent lighting, with the exception of the block being updated. If this assumption is violated, + /// lighting may fail to converge correctly. + void UpdateBlockLight (int x, int y, int z); + + /// + /// Recalculates the sky-source light value of a single block within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The lighting of the block will be updated to be consistent with the lighting in neighboring blocks. + /// If the block is itself a light source, many nearby blocks may be updated to maintain consistent lighting. These + /// updates may also touch neighboring objects, if they can be resolved. + /// This function assumes that the entire and neighboring s + /// already have consistent lighting, with the exception of the block being updated. If this assumption is violated, + /// lighting may fail to converge correctly. + void UpdateSkyLight (int x, int y, int z); + + /// + /// Resets the block-source light value to 0 for all blocks within a bounded block container. + /// + void ResetBlockLight (); + + /// + /// Resets the sky-source light value to 0 for all blocks within a bounded block container. + /// + void ResetSkyLight (); + + /// + /// Reconstructs the block-source lighting for all blocks within a bounded block container. + /// + /// This function should only be called after the lighting has been reset in this + /// and all neighboring s, or lighting may fail to converge correctly. + /// This function cannot reset the lighting on its own, due to interactions between s. + /// If many light source or block opacity values will be modified in this , it may + /// be preferable to avoid explicit or implicit calls to and call this function once when + /// modifications are complete. + /// + void RebuildBlockLight (); + + /// + /// Reconstructs the sky-source lighting for all blocks within a bounded block container. + /// + /// This function should only be called after the lighting has been reset in this + /// and all neighboring s, or lighting may fail to converge correctly. + /// This function cannot reset the lighting on its own, due to interactions between s. + /// If many light source or block opacity values will be modified in this , it may + /// be preferable to avoid explicit or implicit calls to and call this function once when + /// modifications are complete. + /// + void RebuildSkyLight (); + + /// + /// Reconstructs the height-map for a bounded block container. + /// + void RebuildHeightMap (); + + /// + /// Reconciles any block-source lighting inconsistencies between this and any of its neighbors. + /// + /// It will be necessary to call this function if an is reset and rebuilt, but + /// some of its neighbors are not. A rebuilt will spill lighting updates into its neighbors, + /// but will not see lighting that should be propagated back from its neighbors. + /// + void StitchBlockLight (); + + /// + /// Reconciles any sky-source lighting inconsistencies between this and any of its neighbors. + /// + /// It will be necessary to call this function if an is reset and rebuilt, but + /// some of its neighbors are not. A rebuilt will spill lighting updates into its neighbors, + /// but will not see lighting that should be propagated back from its neighbors. + /// + void StitchSkyLight (); + + /// + /// Reconciles any block-source lighting inconsistencies between this and another on a given edge. + /// + /// An -compatible object with the same dimensions as this . + /// The edge that is a neighbor on. + /// It will be necessary to call this function if an is reset and rebuilt, but + /// some of its neighbors are not. A rebuilt will spill lighting updates into its neighbors, + /// but will not see lighting that should be propagated back from its neighbors. + /// + void StitchBlockLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge); + + /// + /// Reconciles any sky-source lighting inconsistencies between this and another on a given edge. + /// + /// An -compatible object with the same dimensions as this . + /// The edge that is a neighbor on. + /// It will be necessary to call this function if an is reset and rebuilt, but + /// some of its neighbors are not. A rebuilt will spill lighting updates into its neighbors, + /// but will not see lighting that should be propagated back from its neighbors. + /// + void StitchSkyLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge); + } + + /// + /// A bounded container for blocks supporting additional properties. + /// + /// + public interface IBoundedPropertyBlockCollection : IBoundedBlockCollection + { + /// + /// Gets a block supporting extra properties from a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// An from the collection at the given coordinates. + new IPropertyBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a block supporting extra properties within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// An acting as a reference directly into the container at the given coordinates. + new IPropertyBlock GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in a bounded block container with data from an existing object. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The to copy data from. + void SetBlock (int x, int y, int z, IPropertyBlock block); + + /// + /// Gets the record of a block within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// A record attached to a block at the given coordinates, or null if no tile entity is set. + TileEntity GetTileEntity (int x, int y, int z); + + /// + /// Sets a record to a block within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The record to assign to the given block. + /// Thrown when an incompatible is added to a block. + /// Thrown when a is added to a block that does not use tile entities. + void SetTileEntity (int x, int y, int z, TileEntity te); + + /// + /// Creates a new default record for a block within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// Thrown when a is created for a block that does not use tile entities. + /// Thrown when the tile entity type associated with the given block has not been registered with . + void CreateTileEntity (int x, int y, int z); + + /// + /// Deletes a record associated with a block within a bounded block container, if it exists. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + void ClearTileEntity (int x, int y, int z); + } + + /// + /// A bounded container of blocks supporting data, lighting, and properties. + /// + /// + public interface IBoundedAlphaBlockCollection : IBoundedDataBlockCollection, IBoundedLitBlockCollection, IBoundedPropertyBlockCollection + { + /// + /// Gets a context-sensitive Alpha-compatible block from a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// An from the collection at the given coordinates. + new AlphaBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a context-sensitive Alpha-compatible block within a bounded block container. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// An acting as a reference directly into the container at the given coordinates. + new AlphaBlockRef GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in a bounded block container with data from an existing object. + /// + /// The container-local X-coordinate of a block. + /// The container-local Y-coordinate of a block. + /// The container-local Z-coordinate of a block. + /// The to copy data from. + void SetBlock (int x, int y, int z, AlphaBlock block); + } +} diff --git a/Substrate/SubstrateCS/Source/Core/ItemInterface.cs b/Substrate/SubstrateCS/Source/Core/ItemInterface.cs new file mode 100644 index 0000000..2207bb5 --- /dev/null +++ b/Substrate/SubstrateCS/Source/Core/ItemInterface.cs @@ -0,0 +1,15 @@ +using System; + +namespace Substrate.Core +{ + /// + /// An interface that exposes an for the object. + /// + public interface IItemContainer + { + /// + /// Gets an associated with the object. + /// + ItemCollection Items { get; } + } +} diff --git a/Substrate/SubstrateCS/Source/Core/NibbleArray.cs b/Substrate/SubstrateCS/Source/Core/NibbleArray.cs index 30df44f..bc6fc92 100644 --- a/Substrate/SubstrateCS/Source/Core/NibbleArray.cs +++ b/Substrate/SubstrateCS/Source/Core/NibbleArray.cs @@ -11,7 +11,7 @@ namespace Substrate.Core public NibbleArray (int length) { - _data = new byte[length / 2]; + _data = new byte[(int)Math.Ceiling(length / 2.0)]; } public NibbleArray (byte[] data) diff --git a/Substrate/SubstrateCS/Source/Core/UnboundedBlockInterface.cs b/Substrate/SubstrateCS/Source/Core/UnboundedBlockInterface.cs new file mode 100644 index 0000000..e37ba22 --- /dev/null +++ b/Substrate/SubstrateCS/Source/Core/UnboundedBlockInterface.cs @@ -0,0 +1,343 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Substrate.Core +{ + /// + /// A basic unconstrained container of blocks. + /// + /// The scope of coordinates is undefined for unconstrained block containers. + public interface IBlockCollection + { + /// + /// Gets a basic block from an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// A basic from the collection at the given coordinates. + IBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a basic block within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// A basic acting as a reference directly into the container at the given coordinates. + IBlock GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in an unbounded block container with data from an existing object. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The to copy basic data from. + void SetBlock (int x, int y, int z, IBlock block); + + /// + /// Gets a block's id (type) from an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The block id (type) from the block container at the given coordinates. + int GetID (int x, int y, int z); + + /// + /// Sets a block's id (type) within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The id (type) to assign to a block at the given coordinates. + void SetID (int x, int y, int z, int id); + + /// + /// Gets info and attributes on a block's type within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// A instance for the block's type. + BlockInfo GetInfo (int x, int y, int z); + } + + /// + /// An unbounded container of blocks supporting data fields. + /// + /// + public interface IDataBlockCollection : IBlockCollection + { + /// + /// Gets a block with data field from an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// An from the collection at the given coordinates. + new IDataBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a block with data field within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// An acting as a reference directly into the container at the given coordinates. + new IDataBlock GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in an unbounded block container with data from an existing object. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The to copy data from. + void SetBlock (int x, int y, int z, IDataBlock block); + + /// + /// Gets a block's data field from an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The data field of a block at the given coordinates. + int GetData (int x, int y, int z); + + /// + /// Sets a block's data field within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The data field to assign to a block at the given coordinates. + void SetData (int x, int y, int z, int data); + } + + /// + /// An unbounded container of blocks supporting dual-source lighting. + /// + /// + public interface ILitBlockCollection : IBlockCollection + { + /// + /// Gets a block with lighting information from an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// An from the collection at the given coordinates. + new ILitBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a block with lighting information within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// An acting as a reference directly into the container at the given coordinates. + new ILitBlock GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in an unbounded block container with data from an existing object. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The to copy data from. + void SetBlock (int x, int y, int z, ILitBlock block); + + /// + /// Gets a block's block-source light value from an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The block-source light value of a block at the given coordinates. + int GetBlockLight (int x, int y, int z); + + /// + /// Gets a block's sky-source light value from an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The sky-source light value of a block at the given coordinates. + int GetSkyLight (int x, int y, int z); + + /// + /// Sets a block's block-source light value within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The block-source light value to assign to a block at the given coordinates. + void SetBlockLight (int x, int y, int z, int light); + + /// + /// Sets a block's sky-source light value within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The sky-source light value to assign to a block at the given coordinates. + void SetSkyLight (int x, int y, int z, int light); + + /// + /// Gets the Y-coordinate of the lowest block with unobstructed view of the sky at the given coordinates within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Z-coordinate of a block. + /// The height value of an X-Z coordinate pair in the block container. + /// The height value represents the lowest block with an unobstructed view of the sky. This is the lowest block with + /// a maximum-value sky-light value. Fully transparent blocks, like glass, do not count as an obstruction. + int GetHeight (int x, int z); + + /// + /// Sets the Y-coordinate of the lowest block with unobstructed view of the sky at the given coordinates within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Z-coordinate of a block. + /// The height value of an X-Z coordinate pair in the block container. + /// Minecraft lighting algorithms rely heavily on this value being correct. Setting this value too low may result in + /// rooms that can never get dark, for example. + void SetHeight (int x, int z, int height); + + /// + /// Recalculates the block-source light value of a single block within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The lighting of the block will be updated to be consistent with the lighting in neighboring blocks. + /// If the block is itself a light source, many nearby blocks may be updated to maintain consistent lighting. These + /// updates may also touch neighboring objects, if they can be resolved. + /// This function assumes that the entire and neighboring s + /// already have consistent lighting, with the exception of the block being updated. If this assumption is violated, + /// lighting may fail to converge correctly. + void UpdateBlockLight (int x, int y, int z); + + /// + /// Recalculates the sky-source light value of a single block within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The lighting of the block will be updated to be consistent with the lighting in neighboring blocks. + /// If the block is itself a light source, many nearby blocks may be updated to maintain consistent lighting. These + /// updates may also touch neighboring objects, if they can be resolved. + /// This function assumes that the entire and neighboring s + /// already have consistent lighting, with the exception of the block being updated. If this assumption is violated, + /// lighting may fail to converge correctly. + void UpdateSkyLight (int x, int y, int z); + } + + /// + /// An unbounded container for blocks supporting additional properties. + /// + /// + public interface IPropertyBlockCollection : IBlockCollection + { + /// + /// Gets a block supporting extra properties from an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// An from the collection at the given coordinates. + new IPropertyBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a block supporting extra properties within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// An acting as a reference directly into the container at the given coordinates. + new IPropertyBlock GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in an unbounded block container with data from an existing object. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The to copy data from. + void SetBlock (int x, int y, int z, IPropertyBlock block); + + /// + /// Gets the record of a block within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// A record attached to a block at the given coordinates, or null if no tile entity is set. + TileEntity GetTileEntity (int x, int y, int z); + + /// + /// Sets a record to a block within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The record to assign to the given block. + /// Thrown when an incompatible is added to a block. + /// Thrown when a is added to a block that does not use tile entities. + void SetTileEntity (int x, int y, int z, TileEntity te); + + /// + /// Creates a new default record for a block within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// Thrown when a is created for a block that does not use tile entities. + /// Thrown when the tile entity type associated with the given block has not been registered with . + void CreateTileEntity (int x, int y, int z); + + /// + /// Deletes a record associated with a block within an unbounded block container, if it exists. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + void ClearTileEntity (int x, int y, int z); + } + + /// + /// An unbounded container of blocks supporting data, lighting, and properties. + /// + /// + public interface IAlphaBlockCollection : IDataBlockCollection, ILitBlockCollection, IPropertyBlockCollection + { + /// + /// Gets a context-insensitive Alpha-compatible block from an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// An from the collection at the given coordinates. + new AlphaBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a context-insensitive Alpha-compatible block within an unbounded block container. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// An acting as a reference directly into the container at the given coordinates. + new AlphaBlockRef GetBlockRef (int x, int y, int z); + + /// + /// Updates a block in an unbounded block container with data from an existing object. + /// + /// The global X-coordinate of a block. + /// The global Y-coordinate of a block. + /// The global Z-coordinate of a block. + /// The to copy data from. + void SetBlock (int x, int y, int z, AlphaBlock block); + } +} diff --git a/Substrate/SubstrateCS/Source/Entities/EntityItem.cs b/Substrate/SubstrateCS/Source/Entities/EntityItem.cs index fbea83d..e15c189 100644 --- a/Substrate/SubstrateCS/Source/Entities/EntityItem.cs +++ b/Substrate/SubstrateCS/Source/Entities/EntityItem.cs @@ -13,7 +13,7 @@ namespace Substrate.Entities new SchemaNodeString("id", "Item"), new SchemaNodeScaler("Health", TagType.TAG_SHORT), new SchemaNodeScaler("Age", TagType.TAG_SHORT), - new SchemaNodeCompound("Item", Item.ItemSchema), + new SchemaNodeCompound("Item", Item.Schema), }); private short _health; diff --git a/Substrate/SubstrateCS/Source/Entities/EntityMinecartChest.cs b/Substrate/SubstrateCS/Source/Entities/EntityMinecartChest.cs index 41a4552..ac708f2 100644 --- a/Substrate/SubstrateCS/Source/Entities/EntityMinecartChest.cs +++ b/Substrate/SubstrateCS/Source/Entities/EntityMinecartChest.cs @@ -1,16 +1,15 @@ using System; using System.Collections.Generic; -using System.Text; +using Substrate.Core; +using Substrate.Nbt; namespace Substrate.Entities { - using Substrate.Nbt; - public class EntityMinecartChest : EntityMinecart, IItemContainer { public static readonly SchemaNodeCompound MinecartChestSchema = MinecartSchema.MergeInto(new SchemaNodeCompound("") { - new SchemaNodeList("Items", TagType.TAG_COMPOUND, ItemCollection.InventorySchema), + new SchemaNodeList("Items", TagType.TAG_COMPOUND, ItemCollection.Schema), }); private static int _CAPACITY = 27; diff --git a/Substrate/SubstrateCS/Source/ImportExport/Schematic.cs b/Substrate/SubstrateCS/Source/ImportExport/Schematic.cs new file mode 100644 index 0000000..a87a27c --- /dev/null +++ b/Substrate/SubstrateCS/Source/ImportExport/Schematic.cs @@ -0,0 +1,195 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Substrate.Core; +using Substrate.Nbt; + +namespace Substrate.ImportExport +{ + public class Schematic + { + private static SchemaNodeCompound _schema = new SchemaNodeCompound() + { + new SchemaNodeScaler("Width", TagType.TAG_SHORT), + new SchemaNodeScaler("Length", TagType.TAG_SHORT), + new SchemaNodeScaler("Height", TagType.TAG_SHORT), + new SchemaNodeString("Materials", "Alpha"), + new SchemaNodeArray("Blocks"), + new SchemaNodeArray("Data"), + new SchemaNodeList("Entities", TagType.TAG_COMPOUND, Entity.Schema), + new SchemaNodeList("TileEntities", TagType.TAG_COMPOUND, TileEntity.Schema), + }; + + private XZYByteArray _blocks; + private XZYNibbleArray _data; + private XZYNibbleArray _blockLight; + private XZYNibbleArray _skyLight; + private ZXByteArray _heightMap; + + private TagNodeList _entities; + private TagNodeList _tileEntities; + + private AlphaBlockCollection _blockset; + private EntityCollection _entityset; + + private Schematic () + { + } + + public Schematic (AlphaBlockCollection blocks, EntityCollection entities) + { + _blockset = blocks; + _entityset = entities; + } + + public Schematic (int xdim, int ydim, int zdim) + { + _blocks = new XZYByteArray(xdim, ydim, zdim); + _data = new XZYNibbleArray(xdim, ydim, zdim); + _blockLight = new XZYNibbleArray(xdim, ydim, zdim); + _skyLight = new XZYNibbleArray(xdim, ydim, zdim); + _heightMap = new ZXByteArray(xdim, zdim); + + _entities = new TagNodeList(TagType.TAG_COMPOUND); + _tileEntities = new TagNodeList(TagType.TAG_COMPOUND); + + _blockset = new AlphaBlockCollection(_blocks, _data, _blockLight, _skyLight, _heightMap, _tileEntities); + _entityset = new EntityCollection(_entities); + } + + #region Properties + + public AlphaBlockCollection Blocks + { + get { return _blockset; } + set { _blockset = value; } + } + + public EntityCollection Entities + { + get { return _entityset; } + set { _entityset = value; } + } + + #endregion + + public static Schematic Import (string path) + { + NBTFile schematicFile = new NBTFile(path); + if (!schematicFile.Exists()) { + return null; + } + + Stream nbtStream = schematicFile.GetDataInputStream(); + if (nbtStream == null) { + return null; + } + + NbtTree tree = new NbtTree(nbtStream); + + NbtVerifier v = new NbtVerifier(tree.Root, _schema); + if (!v.Verify()) { + return null; + } + + //TagNodeCompound schematic = tree.Root["Schematic"] as TagNodeCompound; + TagNodeCompound schematic = tree.Root; + int xdim = schematic["Width"].ToTagShort(); + int zdim = schematic["Length"].ToTagShort(); + int ydim = schematic["Height"].ToTagShort(); + + Schematic self = new Schematic(xdim, ydim, zdim); + + // Damnit, schematic is YZX ordering. + YZXByteArray schemaBlocks = new YZXByteArray(xdim, ydim, zdim, schematic["Blocks"].ToTagByteArray()); + YZXByteArray schemaData = new YZXByteArray(xdim, ydim, zdim, schematic["Data"].ToTagByteArray()); + + for (int x = 0; x < xdim; x++) { + for (int y = 0; y < ydim; y++) { + for (int z = 0; z < zdim; z++) { + self._blocks[x, y, z] = schemaBlocks[x, y, z]; + self._data[x, y, z] = schemaData[x, y, z]; + } + } + } + + TagNodeList entities = schematic["Entities"] as TagNodeList; + foreach (TagNode e in entities) { + self._entities.Add(e); + } + + TagNodeList tileEntities = schematic["TileEntities"] as TagNodeList; + foreach (TagNode te in tileEntities) { + self._tileEntities.Add(te); + } + + self._blockset.Refresh(); + + return self; + } + + public void Export (string path) + { + int xdim = _blockset.XDim; + int ydim = _blockset.YDim; + int zdim = _blockset.ZDim; + + byte[] blockData = new byte[xdim * ydim * zdim]; + byte[] dataData = new byte[xdim * ydim * zdim]; + + YZXByteArray schemaBlocks = new YZXByteArray(_blockset.XDim, _blockset.YDim, _blockset.ZDim, blockData); + YZXByteArray schemaData = new YZXByteArray(_blockset.XDim, _blockset.YDim, _blockset.ZDim, dataData); + + TagNodeList entities = new TagNodeList(TagType.TAG_COMPOUND); + TagNodeList tileEntities = new TagNodeList(TagType.TAG_COMPOUND); + + for (int x = 0; x < xdim; x++) { + for (int z = 0; z < zdim; z++) { + for (int y = 0; y < ydim; y++) { + AlphaBlock block = _blockset.GetBlock(x, y, z); + schemaBlocks[x, y, z] = (byte)block.ID; + schemaData[x, y, z] = (byte)block.Data; + + TileEntity te = block.GetTileEntity(); + if (te != null) { + te.X = x; + te.Y = y; + te.Z = z; + + tileEntities.Add(te.BuildTree()); + } + } + } + } + + foreach (EntityTyped e in _entityset) { + entities.Add(e.BuildTree()); + } + + TagNodeCompound schematic = new TagNodeCompound(); + schematic["Width"] = new TagNodeShort((short)xdim); + schematic["Length"] = new TagNodeShort((short)zdim); + schematic["Height"] = new TagNodeShort((short)ydim); + + schematic["Entities"] = entities; + schematic["TileEntities"] = tileEntities; + + schematic["Materials"] = new TagNodeString("Alpha"); + + schematic["Blocks"] = new TagNodeByteArray(blockData); + schematic["Data"] = new TagNodeByteArray(dataData); + + NBTFile schematicFile = new NBTFile(path); + + Stream nbtStream = schematicFile.GetDataOutputStream(); + if (nbtStream == null) { + return; + } + + NbtTree tree = new NbtTree(schematic, "Schematic"); + tree.WriteTo(nbtStream); + + nbtStream.Close(); + } + } +} diff --git a/Substrate/SubstrateCS/Source/Item.cs b/Substrate/SubstrateCS/Source/Item.cs index cd0c010..dafc6f0 100644 --- a/Substrate/SubstrateCS/Source/Item.cs +++ b/Substrate/SubstrateCS/Source/Item.cs @@ -6,14 +6,12 @@ using Substrate.Nbt; namespace Substrate { - public interface IItemContainer - { - ItemCollection Items { get; } - } - + /// + /// Represents an item (or item stack) within an item slot. + /// public class Item : INbtObject, ICopyable { - public static readonly SchemaNodeCompound ItemSchema = new SchemaNodeCompound("") + private static readonly SchemaNodeCompound _schema = new SchemaNodeCompound("") { new SchemaNodeScaler("id", TagType.TAG_SHORT), new SchemaNodeScaler("Damage", TagType.TAG_SHORT), @@ -24,40 +22,73 @@ namespace Substrate private byte _count; private short _damage; + /// + /// Constructs an empty instance. + /// + public Item () + { + } + + /// + /// Constructs an instance representing the given item id. + /// + /// An item id. + public Item (int id) + { + _id = (short)id; + } + + #region Properties + + /// + /// Gets an entry for this item's type. + /// public ItemInfo Info { get { return ItemInfo.ItemTable[_id]; } } + /// + /// Gets or sets the current type (id) of the item. + /// public int ID { get { return _id; } set { _id = (short)value; } } + /// + /// Gets or sets the damage value of the item. + /// + /// The damage value may represent a generic data value for some items. public int Damage { get { return _damage; } set { _damage = (short)value; } } + /// + /// Gets or sets the number of this item stacked together in an item slot. + /// public int Count { get { return _count; } set { _count = (byte)value; } } - public Item () + /// + /// Gets a representing the schema of an item. + /// + public static SchemaNodeCompound Schema { + get { return _schema; } } - public Item (int id) - { - _id = (short)id; - } + #endregion #region ICopyable Members + /// public Item Copy () { Item item = new Item(); @@ -72,6 +103,7 @@ namespace Substrate #region INBTObject Members + /// public Item LoadTree (TagNode tree) { TagNodeCompound ctree = tree as TagNodeCompound; @@ -86,6 +118,7 @@ namespace Substrate return this; } + /// public Item LoadTreeSafe (TagNode tree) { if (!ValidateTree(tree)) { @@ -95,6 +128,7 @@ namespace Substrate return LoadTree(tree); } + /// public TagNode BuildTree () { TagNodeCompound tree = new TagNodeCompound(); @@ -105,42 +139,66 @@ namespace Substrate return tree; } + /// public bool ValidateTree (TagNode tree) { - return new NbtVerifier(tree, ItemSchema).Verify(); + return new NbtVerifier(tree, _schema).Verify(); } #endregion } + /// + /// Represents a collection of items, such as a chest or an inventory. + /// + /// ItemCollections have a limited number of slots that depends on where they are used. public class ItemCollection : INbtObject, ICopyable { - public static readonly SchemaNodeCompound InventorySchema = Item.ItemSchema.MergeInto(new SchemaNodeCompound("") + private static readonly SchemaNodeCompound _schema = Item.Schema.MergeInto(new SchemaNodeCompound("") { new SchemaNodeScaler("Slot", TagType.TAG_BYTE), }); - public static readonly SchemaNodeList ListSchema = new SchemaNodeList("", TagType.TAG_COMPOUND, InventorySchema); + private static readonly SchemaNodeList _listSchema = new SchemaNodeList("", TagType.TAG_COMPOUND, _schema); - protected Dictionary _items; - protected int _capacity; + private Dictionary _items; + private int _capacity; + /// + /// Constructs an with at most item slots. + /// + /// The upper bound on item slots available. + /// The parameter does not necessarily indicate the true capacity of an item collection. + /// The player object, for example, contains a conventional inventory, a range of invalid slots, and then equipment. Capacity in + /// this case would refer to the highest equipment slot. public ItemCollection (int capacity) { _capacity = capacity; _items = new Dictionary(); } + #region Properties + + /// + /// Gets the capacity of the item collection. + /// public int Capacity { get { return _capacity; } } + /// + /// Gets the current number of item slots actually used in the collection. + /// public int Count { get { return _items.Count; } } + /// + /// Gets or sets an item in a given item slot. + /// + /// The item slot to query or insert an item or item stack into. public Item this [int slot] { get @@ -159,16 +217,39 @@ namespace Substrate } } + /// + /// Gets a representing the schema of an item collection. + /// + public static SchemaNodeCompound Schema + { + get { return _schema; } + } + + #endregion + + /// + /// Checks if an item exists in the given item slot. + /// + /// The item slot to check. + /// True if an item or stack of items exists in the given slot. public bool ItemExists (int slot) { return _items.ContainsKey(slot); } + /// + /// Removes an item from the given item slot, if it exists. + /// + /// The item slot to clear. + /// True if an item was removed; false otherwise. public bool Clear (int slot) { return _items.Remove(slot); } + /// + /// Removes all items from the item collection. + /// public void ClearAllItems () { _items.Clear(); @@ -176,6 +257,7 @@ namespace Substrate #region ICopyable Members + /// public ItemCollection Copy () { ItemCollection ic = new ItemCollection(_capacity); @@ -189,6 +271,7 @@ namespace Substrate #region INBTObject Members + /// public ItemCollection LoadTree (TagNode tree) { TagNodeList ltree = tree as TagNodeList; @@ -204,6 +287,7 @@ namespace Substrate return this; } + /// public ItemCollection LoadTreeSafe (TagNode tree) { if (!ValidateTree(tree)) { @@ -213,6 +297,7 @@ namespace Substrate return LoadTree(tree); } + /// public TagNode BuildTree () { TagNodeList list = new TagNodeList(TagType.TAG_COMPOUND); @@ -226,9 +311,10 @@ namespace Substrate return list; } + /// public bool ValidateTree (TagNode tree) { - return new NbtVerifier(tree, ListSchema).Verify(); + return new NbtVerifier(tree, _listSchema).Verify(); } #endregion diff --git a/Substrate/SubstrateCS/Source/Nbt/NbtTree.cs b/Substrate/SubstrateCS/Source/Nbt/NbtTree.cs index 8192c15..1758caf 100644 --- a/Substrate/SubstrateCS/Source/Nbt/NbtTree.cs +++ b/Substrate/SubstrateCS/Source/Nbt/NbtTree.cs @@ -19,6 +19,7 @@ namespace Substrate.Nbt { private Stream _stream = null; private TagNodeCompound _root = null; + private string _rootName = ""; private static TagNodeNull _nulltag = new TagNodeNull(); @@ -30,6 +31,15 @@ namespace Substrate.Nbt get { return _root; } } + /// + /// Gets or sets the name of the tree's root node. + /// + public string Name + { + get { return _rootName; } + set { _rootName = value; } + } + /// /// Constructs a wrapper around a new NBT tree with an empty root node. /// @@ -47,6 +57,17 @@ namespace Substrate.Nbt _root = tree; } + /// + /// Constructs a wrapper around another NBT tree and gives it a name. + /// + /// The root node of an NBT tree. + /// The name for the root node. + public NbtTree (TagNodeCompound tree, string name) + { + _root = tree; + _rootName = name; + } + /// /// Constructs and wrapper around a new NBT tree parsed from a source data stream. /// @@ -79,7 +100,7 @@ namespace Substrate.Nbt _stream = s; if (_root != null) { - WriteTag("", _root); + WriteTag(_rootName, _root); } _stream = null; diff --git a/Substrate/SubstrateCS/Source/Player.cs b/Substrate/SubstrateCS/Source/Player.cs index 984002a..a465cac 100644 --- a/Substrate/SubstrateCS/Source/Player.cs +++ b/Substrate/SubstrateCS/Source/Player.cs @@ -20,7 +20,7 @@ namespace Substrate new SchemaNodeScaler("Health", TagType.TAG_SHORT), new SchemaNodeScaler("HurtTime", TagType.TAG_SHORT), new SchemaNodeScaler("Dimension", TagType.TAG_INT), - new SchemaNodeList("Inventory", TagType.TAG_COMPOUND, ItemCollection.InventorySchema), + new SchemaNodeList("Inventory", TagType.TAG_COMPOUND, ItemCollection.Schema), new SchemaNodeScaler("World", TagType.TAG_STRING, SchemaOptions.OPTIONAL), new SchemaNodeScaler("Sleeping", TagType.TAG_BYTE, SchemaOptions.CREATE_ON_MISSING), new SchemaNodeScaler("SleepTimer", TagType.TAG_SHORT, SchemaOptions.CREATE_ON_MISSING), diff --git a/Substrate/SubstrateCS/Source/TileEntities/TileEntityChest.cs b/Substrate/SubstrateCS/Source/TileEntities/TileEntityChest.cs index f13c899..39c4ddd 100644 --- a/Substrate/SubstrateCS/Source/TileEntities/TileEntityChest.cs +++ b/Substrate/SubstrateCS/Source/TileEntities/TileEntityChest.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; -using System.Text; +using Substrate.Core; +using Substrate.Nbt; namespace Substrate.TileEntities { - using Substrate.Nbt; - public class TileEntityChest : TileEntity, IItemContainer { public static readonly SchemaNodeCompound ChestSchema = TileEntity.Schema.MergeInto(new SchemaNodeCompound("") { new SchemaNodeString("id", "Chest"), - new SchemaNodeList("Items", TagType.TAG_COMPOUND, ItemCollection.InventorySchema), + new SchemaNodeList("Items", TagType.TAG_COMPOUND, ItemCollection.Schema), }); private const int _CAPACITY = 27; diff --git a/Substrate/SubstrateCS/Source/TileEntities/TileEntityFurnace.cs b/Substrate/SubstrateCS/Source/TileEntities/TileEntityFurnace.cs index fe37537..c025773 100644 --- a/Substrate/SubstrateCS/Source/TileEntities/TileEntityFurnace.cs +++ b/Substrate/SubstrateCS/Source/TileEntities/TileEntityFurnace.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; -using System.Text; +using Substrate.Core; +using Substrate.Nbt; namespace Substrate.TileEntities { - using Substrate.Nbt; - public class TileEntityFurnace : TileEntity, IItemContainer { public static readonly SchemaNodeCompound FurnaceSchema = TileEntity.Schema.MergeInto(new SchemaNodeCompound("") @@ -13,7 +12,7 @@ namespace Substrate.TileEntities new SchemaNodeString("id", "Furnace"), new SchemaNodeScaler("BurnTime", TagType.TAG_SHORT), new SchemaNodeScaler("CookTime", TagType.TAG_SHORT), - new SchemaNodeList("Items", TagType.TAG_COMPOUND, ItemCollection.InventorySchema), + new SchemaNodeList("Items", TagType.TAG_COMPOUND, ItemCollection.Schema), }); private const int _CAPACITY = 3; diff --git a/Substrate/SubstrateCS/Source/TileEntities/TileEntityMobSpawner.cs b/Substrate/SubstrateCS/Source/TileEntities/TileEntityMobSpawner.cs index c39bb18..c59850d 100644 --- a/Substrate/SubstrateCS/Source/TileEntities/TileEntityMobSpawner.cs +++ b/Substrate/SubstrateCS/Source/TileEntities/TileEntityMobSpawner.cs @@ -66,7 +66,7 @@ namespace Substrate.TileEntities } _delay = ctree["Delay"].ToTagShort(); - _entityID = ctree["EntityID"].ToTagString(); + _entityID = ctree["EntityId"].ToTagString(); return this; } @@ -74,7 +74,7 @@ namespace Substrate.TileEntities public override TagNode BuildTree () { TagNodeCompound tree = base.BuildTree() as TagNodeCompound; - tree["EntityID"] = new TagNodeString(_entityID); + tree["EntityId"] = new TagNodeString(_entityID); tree["Delay"] = new TagNodeShort(_delay); return tree; diff --git a/Substrate/SubstrateCS/Source/TileEntities/TileEntityTrap.cs b/Substrate/SubstrateCS/Source/TileEntities/TileEntityTrap.cs index 5906b2a..91bf0ad 100644 --- a/Substrate/SubstrateCS/Source/TileEntities/TileEntityTrap.cs +++ b/Substrate/SubstrateCS/Source/TileEntities/TileEntityTrap.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; -using System.Text; +using Substrate.Core; +using Substrate.Nbt; namespace Substrate.TileEntities { - using Substrate.Nbt; - public class TileEntityTrap : TileEntity, IItemContainer { public static readonly SchemaNodeCompound TrapSchema = TileEntity.Schema.MergeInto(new SchemaNodeCompound("") { new SchemaNodeString("id", "Trap"), - new SchemaNodeList("Items", TagType.TAG_COMPOUND, ItemCollection.InventorySchema), + new SchemaNodeList("Items", TagType.TAG_COMPOUND, ItemCollection.Schema), }); private const int _CAPACITY = 8; diff --git a/Substrate/SubstrateCS/Substrate.csproj b/Substrate/SubstrateCS/Substrate.csproj index 8c97685..9bc519f 100644 --- a/Substrate/SubstrateCS/Substrate.csproj +++ b/Substrate/SubstrateCS/Substrate.csproj @@ -65,9 +65,12 @@ + + - + +