Added TileTick infrastructure

This commit is contained in:
Justin Aquadro 2012-01-28 01:42:08 -05:00
parent 1400ef1d55
commit 6473402fab
14 changed files with 1163 additions and 304 deletions

View file

@ -30,8 +30,8 @@ using System.Runtime.InteropServices;
// Build Number // Build Number
// Revision // Revision
// //
[assembly: AssemblyVersion("1.0.3.0")] [assembly: AssemblyVersion("1.1.0.0")]
[assembly: AssemblyFileVersion("1.0.3.0")] [assembly: AssemblyFileVersion("1.1.0.0")]
// This library is compatible with all CLS-compliant .NET programming languages. // This library is compatible with all CLS-compliant .NET programming languages.
[assembly: CLSCompliant(true)] [assembly: CLSCompliant(true)]

View file

@ -13,12 +13,13 @@ namespace Substrate
/// offers a relatively compact footprint for storing the unique identity of a block's manifestation in the world.</para> /// offers a relatively compact footprint for storing the unique identity of a block's manifestation in the world.</para>
/// <para>A single <see cref="AlphaBlock"/> object may also provide a convenient way to paste a block into many locations in /// <para>A single <see cref="AlphaBlock"/> object may also provide a convenient way to paste a block into many locations in
/// a block collection type.</para></remarks> /// a block collection type.</para></remarks>
public class AlphaBlock : IDataBlock, IPropertyBlock, ICopyable<AlphaBlock> public class AlphaBlock : IDataBlock, IPropertyBlock, IActiveBlock, ICopyable<AlphaBlock>
{ {
private int _id; private int _id;
private int _data; private int _data;
private TileEntity _tileEntity; private TileEntity _tileEntity;
private TileTick _tileTick;
/// <summary> /// <summary>
/// Create a new <see cref="AlphaBlock"/> instance of the given type with default data. /// Create a new <see cref="AlphaBlock"/> instance of the given type with default data.
@ -175,6 +176,65 @@ namespace Substrate
#endregion #endregion
#region IActiveBlock Members
public int TileTickValue
{
get
{
if (_tileTick == null)
return 0;
return _tileTick.Ticks;
}
set
{
if (_tileTick == null)
CreateTileTick();
_tileTick.Ticks = value;
}
}
/// <summary>
/// Gets the <see cref="TileTick"/> record of the block if it has one.
/// </summary>
/// <returns>The <see cref="TileTick"/> attached to this block, or null if the block type does not require a Tile Entity.</returns>
public TileTick GetTileTick ()
{
return _tileTick;
}
/// <summary>
/// Sets a new <see cref="TileTick"/> record for the block.
/// </summary>
/// <param name="tt">A <see cref="TileTick"/> record compatible with the block's type.</param>
public void SetTileTick (TileTick tt)
{
_tileTick = tt;
}
/// <summary>
/// Creates a default <see cref="TileTick"/> record appropriate for the block.
/// </summary>
public void CreateTileTick ()
{
_tileTick = new TileTick()
{
ID = _id,
};
}
/// <summary>
/// Removes any <see cref="TileTick"/> currently attached to the block.
/// </summary>
public void ClearTileTick ()
{
_tileTick = null;
}
#endregion
#region ICopyable<Block> Members #region ICopyable<Block> Members
/// <summary> /// <summary>

View file

@ -11,7 +11,7 @@ namespace Substrate
/// <remarks>An <see cref="AlphaBlockCollection"/> is a wrapper around existing pieces of data. Although it /// <remarks>An <see cref="AlphaBlockCollection"/> is a wrapper around existing pieces of data. Although it
/// holds references to data, it does not "own" the data in the same way that a <see cref="Chunk"/> does. An /// holds references to data, it does not "own" the data in the same way that a <see cref="Chunk"/> does. An
/// <see cref="AlphaBlockCollection"/> simply overlays a higher-level interface on top of existing data.</remarks> /// <see cref="AlphaBlockCollection"/> simply overlays a higher-level interface on top of existing data.</remarks>
public class AlphaBlockCollection : IBoundedAlphaBlockCollection public class AlphaBlockCollection : IBoundedAlphaBlockCollection, IBoundedActiveBlockCollection
{ {
private readonly int _xdim; private readonly int _xdim;
private readonly int _ydim; private readonly int _ydim;
@ -24,14 +24,17 @@ namespace Substrate
private ZXByteArray _heightMap; private ZXByteArray _heightMap;
private TagNodeList _tileEntities; private TagNodeList _tileEntities;
private TagNodeList _tileTicks;
private BlockLight _lightManager; private BlockLight _lightManager;
private BlockFluid _fluidManager; private BlockFluid _fluidManager;
private BlockTileEntities _tileEntityManager; private BlockTileEntities _tileEntityManager;
private BlockTileTicks _tileTickManager;
private bool _dirty = false; private bool _dirty = false;
private bool _autoLight = true; private bool _autoLight = true;
private bool _autoFluid = false; private bool _autoFluid = false;
private bool _autoTick = false;
public delegate AlphaBlockCollection NeighborLookupHandler (int relx, int rely, int relz); public delegate AlphaBlockCollection NeighborLookupHandler (int relx, int rely, int relz);
@ -49,6 +52,7 @@ namespace Substrate
_skyLight = new XZYNibbleArray(xdim, ydim, zdim); _skyLight = new XZYNibbleArray(xdim, ydim, zdim);
_heightMap = new ZXByteArray(xdim, zdim); _heightMap = new ZXByteArray(xdim, zdim);
_tileEntities = new TagNodeList(TagType.TAG_COMPOUND); _tileEntities = new TagNodeList(TagType.TAG_COMPOUND);
_tileTicks = new TagNodeList(TagType.TAG_COMPOUND);
_xdim = xdim; _xdim = xdim;
_ydim = ydim; _ydim = ydim;
@ -73,6 +77,28 @@ namespace Substrate
XZYNibbleArray skyLight, XZYNibbleArray skyLight,
ZXByteArray heightMap, ZXByteArray heightMap,
TagNodeList tileEntities) TagNodeList tileEntities)
: this(blocks, data, blockLight, skyLight, heightMap, tileEntities, null)
{
}
/// <summary>
/// Creates a new <see cref="AlphaBlockCollection"/> overlay on top of Alpha-specific units of data.
/// </summary>
/// <param name="blocks">An array of Block IDs.</param>
/// <param name="data">An array of data nibbles.</param>
/// <param name="blockLight">An array of block light nibbles.</param>
/// <param name="skyLight">An array of sky light nibbles.</param>
/// <param name="heightMap">An array of height map values.</param>
/// <param name="tileEntities">A list of tile entities corresponding to blocks in this collection.</param>
/// <param name="tileTicks">A list of tile ticks corresponding to blocks in this collection.</param>
public AlphaBlockCollection (
XZYByteArray blocks,
XZYNibbleArray data,
XZYNibbleArray blockLight,
XZYNibbleArray skyLight,
ZXByteArray heightMap,
TagNodeList tileEntities,
TagNodeList tileTicks)
{ {
_blocks = blocks; _blocks = blocks;
_data = data; _data = data;
@ -80,6 +106,10 @@ namespace Substrate
_skyLight = skyLight; _skyLight = skyLight;
_heightMap = heightMap; _heightMap = heightMap;
_tileEntities = tileEntities; _tileEntities = tileEntities;
_tileTicks = tileTicks;
if (_tileTicks == null)
_tileTicks = new TagNodeList(TagType.TAG_COMPOUND);
_xdim = _blocks.XDim; _xdim = _blocks.XDim;
_ydim = _blocks.YDim; _ydim = _blocks.YDim;
@ -96,6 +126,12 @@ namespace Substrate
_lightManager = new BlockLight(this); _lightManager = new BlockLight(this);
_fluidManager = new BlockFluid(this); _fluidManager = new BlockFluid(this);
_tileEntityManager = new BlockTileEntities(_blocks, _tileEntities); _tileEntityManager = new BlockTileEntities(_blocks, _tileEntities);
_tileTickManager = new BlockTileTicks(_blocks, _tileTicks);
}
internal TagNodeList TileTicks
{
get { return _tileTicks; }
} }
#region Events #region Events
@ -150,6 +186,15 @@ namespace Substrate
set { _autoFluid = value; } set { _autoFluid = value; }
} }
/// <summary>
/// Gets or sets a value indicating whether changes to blocks will create tile tick entries.
/// </summary>
public bool AutoTileTick
{
get { return _autoTick; }
set { _autoTick = value; }
}
/// <summary> /// <summary>
/// Gets or sets a value indicating whether this <see cref="AlphaBlockCollection"/> needs to be saved. /// Gets or sets a value indicating whether this <see cref="AlphaBlockCollection"/> needs to be saved.
/// </summary> /// </summary>
@ -208,6 +253,11 @@ namespace Substrate
if (te != null) { if (te != null) {
SetTileEntity(x, y, z, te.Copy()); SetTileEntity(x, y, z, te.Copy());
} }
TileTick tt = block.GetTileTick();
if (tt != null) {
SetTileTick(x, y, z, tt.Copy());
}
} }
#region IBoundedBlockCollection Members #region IBoundedBlockCollection Members
@ -327,6 +377,17 @@ namespace Substrate
} }
} }
// TileTick consistency
if (_autoTick) {
if (info1.ID != info2.ID) {
ClearTileTick(x, y, z);
if (info2.Tick > 0) {
SetTileTickValue(x, y, z, info2.Tick);
}
}
}
_dirty = true; _dirty = true;
} }
@ -674,6 +735,123 @@ namespace Substrate
#endregion #endregion
#region IBoundedActiveBlockCollection Members
IActiveBlock IBoundedActiveBlockCollection.GetBlock (int x, int y, int z)
{
return GetBlock(x, y, z);
}
IActiveBlock IBoundedActiveBlockCollection.GetBlockRef (int x, int y, int z)
{
return GetBlockRef(x, y, z);
}
/// <inheritdoc/>
public void SetBlock (int x, int y, int z, IActiveBlock block)
{
SetID(x, y, z, block.ID);
SetTileTick(x, y, z, block.GetTileTick().Copy());
}
/// <inheritdoc/>
public int GetTileTickValue (int x, int y, int z)
{
return _tileTickManager.GetTileTickValue(x, y, z);
}
internal int GetTileTickValue (int index)
{
int x, y, z;
_blocks.GetMultiIndex(index, out x, out y, out z);
return _tileTickManager.GetTileTickValue(x, y, z);
}
/// <inheritdoc/>
public void SetTileTickValue (int x, int y, int z, int tickValue)
{
_tileTickManager.SetTileTickValue(x, y, z, tickValue);
_dirty = true;
}
internal void SetTileTickValue (int index, int tickValue)
{
int x, y, z;
_blocks.GetMultiIndex(index, out x, out y, out z);
_tileTickManager.SetTileTickValue(x, y, z, tickValue);
_dirty = true;
}
/// <inheritdoc/>
public TileTick GetTileTick (int x, int y, int z)
{
return _tileTickManager.GetTileTick(x, y, z);
}
internal TileTick GetTileTick (int index)
{
int x, y, z;
_blocks.GetMultiIndex(index, out x, out y, out z);
return _tileTickManager.GetTileTick(x, y, z);
}
/// <inheritdoc/>
public void SetTileTick (int x, int y, int z, TileTick tt)
{
_tileTickManager.SetTileTick(x, y, z, tt);
_dirty = true;
}
internal void SetTileTick (int index, TileTick tt)
{
int x, y, z;
_blocks.GetMultiIndex(index, out x, out y, out z);
_tileTickManager.SetTileTick(x, y, z, tt);
_dirty = true;
}
/// <inheritdoc/>
public void CreateTileTick (int x, int y, int z)
{
_tileTickManager.CreateTileTick(x, y, z);
_dirty = true;
}
internal void CreateTileTick (int index)
{
int x, y, z;
_blocks.GetMultiIndex(index, out x, out y, out z);
_tileTickManager.CreateTileTick(x, y, z);
_dirty = true;
}
/// <inheritdoc/>
public void ClearTileTick (int x, int y, int z)
{
_tileTickManager.ClearTileTick(x, y, z);
_dirty = true;
}
internal void ClearTileTick (int index)
{
int x, y, z;
_blocks.GetMultiIndex(index, out x, out y, out z);
_tileTickManager.ClearTileTick(x, y, z);
_dirty = true;
}
#endregion
/// <summary>
/// Resets all fluid blocks in the collection to their inactive type.
/// </summary>
public void ResetFluid () public void ResetFluid ()
{ {
_fluidManager.ResetWater(_blocks, _data); _fluidManager.ResetWater(_blocks, _data);
@ -681,6 +859,12 @@ namespace Substrate
_dirty = true; _dirty = true;
} }
/// <summary>
/// Performs fluid simulation on all fluid blocks on this container.
/// </summary>
/// <remarks>Simulation will cause inactive fluid blocks to convert into and spread active fluid blocks according
/// to the fluid calculation rules in Minecraft. Fluid calculation may spill into neighboring block collections
/// (and beyond).</remarks>
public void RebuildFluid () public void RebuildFluid ()
{ {
_fluidManager.RebuildWater(); _fluidManager.RebuildWater();
@ -688,6 +872,12 @@ namespace Substrate
_dirty = true; _dirty = true;
} }
/// <summary>
/// Recalculates fluid starting from a given fluid block in this collection.
/// </summary>
/// <param name="x">Local X-coordinate of block.</param>
/// <param name="y">Local Y-coordinate of block.</param>
/// <param name="z">Local Z-coordiante of block.</param>
public void UpdateFluid (int x, int y, int z) public void UpdateFluid (int x, int y, int z)
{ {
bool autofluid = _autoFluid; bool autofluid = _autoFluid;
@ -707,264 +897,6 @@ namespace Substrate
_autoFluid = autofluid; _autoFluid = autofluid;
} }
#region Unbounded Container Implementations
/*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);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
IBlock IBlockCollection.GetBlockRef (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetBlockRef(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void IBlockCollection.SetBlock (int x, int y, int z, IBlock block)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetBlock(x, y, z, block);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
BlockInfo IBlockCollection.GetInfo (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetInfo(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
int IBlockCollection.GetID (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetID(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void IBlockCollection.SetID (int x, int y, int z, int id)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetID(x, y, z, id);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
IDataBlock IDataBlockCollection.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);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
IDataBlock IDataBlockCollection.GetBlockRef (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetBlockRef(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void IDataBlockCollection.SetBlock (int x, int y, int z, IDataBlock block)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetBlock(x, y, z, block);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
int IDataBlockCollection.GetData (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetData(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void IDataBlockCollection.SetData (int x, int y, int z, int data)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetData(x, y, z, data);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
ILitBlock ILitBlockCollection.GetBlock (int x, int y, int z)
{
throw new NotImplementedException();
}
ILitBlock ILitBlockCollection.GetBlockRef (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetBlockRef(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void ILitBlockCollection.SetBlock (int x, int y, int z, ILitBlock block)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetBlock(x, y, z, block);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
int ILitBlockCollection.GetBlockLight (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetBlockLight(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void ILitBlockCollection.SetBlockLight (int x, int y, int z, int light)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetBlockLight(x, y, z, light);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
int ILitBlockCollection.GetSkyLight (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetSkyLight(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void ILitBlockCollection.SetSkyLight (int x, int y, int z, int light)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetSkyLight(x, y, z, light);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
int ILitBlockCollection.GetHeight (int x, int z)
{
if (x >= 0 && x < _xdim && z >= 0 && z < ZDim) {
return GetHeight(x, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : "z");
}
void ILitBlockCollection.SetHeight (int x, int z, int height)
{
if (x >= 0 && x < _xdim && z >= 0 && z < ZDim) {
SetHeight(x, z, height);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : "z");
}
void ILitBlockCollection.UpdateBlockLight (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
UpdateBlockLight(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void ILitBlockCollection.UpdateSkyLight (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
UpdateSkyLight(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
IPropertyBlock IPropertyBlockCollection.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);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
IPropertyBlock IPropertyBlockCollection.GetBlockRef (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetBlockRef(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void IPropertyBlockCollection.SetBlock (int x, int y, int z, IPropertyBlock block)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetBlock(x, y, z, block);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
TileEntity IPropertyBlockCollection.GetTileEntity (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetTileEntity(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void IPropertyBlockCollection.SetTileEntity (int x, int y, int z, TileEntity te)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetTileEntity(x, y, z, te);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void IPropertyBlockCollection.CreateTileEntity (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
CreateTileEntity(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void IPropertyBlockCollection.ClearTileEntity (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
ClearTileEntity(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
AlphaBlock IAlphaBlockCollection.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);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
AlphaBlockRef IAlphaBlockCollection.GetBlockRef (int x, int y, int z)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
return GetBlockRef(x, y, z);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}
void IAlphaBlockCollection.SetBlock (int x, int y, int z, AlphaBlock block)
{
if (x >= 0 && x < _xdim && y >= 0 && y < _ydim && z >= 0 && z < ZDim) {
SetBlock(x, y, z, block);
}
throw new ArgumentOutOfRangeException(x < 0 || x >= _xdim ? "x" : y < 0 || y >= _ydim ? "y" : "z");
}*/
#endregion
/*#region IEnumerable<AlphaBlockRef> Members /*#region IEnumerable<AlphaBlockRef> Members
public IEnumerator<AlphaBlockRef> GetEnumerator () public IEnumerator<AlphaBlockRef> GetEnumerator ()

View file

@ -24,7 +24,7 @@ namespace Substrate
/// <see cref="BlockManager"/> (or similar) directly would incur the expensive lookup on each operation. See NBToolkit for an example of this /// <see cref="BlockManager"/> (or similar) directly would incur the expensive lookup on each operation. See NBToolkit for an example of this
/// use case.</para> /// use case.</para>
/// <para>Unlike the <see cref="AlphaBlock"/> object, this type exposed access to context-dependent data such as lighting.</para></remarks> /// <para>Unlike the <see cref="AlphaBlock"/> object, this type exposed access to context-dependent data such as lighting.</para></remarks>
public struct AlphaBlockRef : IAlphaBlockRef public struct AlphaBlockRef : IVersion10BlockRef
{ {
private readonly AlphaBlockCollection _collection; private readonly AlphaBlockCollection _collection;
private readonly int _index; private readonly int _index;
@ -160,5 +160,50 @@ namespace Substrate
} }
#endregion #endregion
#region IActiveBlock Members
public int TileTickValue
{
get { return _collection.GetTileTickValue(_index); }
set { _collection.SetTileTickValue(_index, value); }
}
/// <summary>
/// Gets the <see cref="TileTick"/> record of the block if it has one.
/// </summary>
/// <returns>The <see cref="TileTick"/> attached to this block, or null if the block type does not require a Tile Entity.</returns>
public TileTick GetTileTick ()
{
return _collection.GetTileTick(_index);
}
/// <summary>
/// Sets a new <see cref="TileTick"/> record for the block.
/// </summary>
/// <param name="te">A <see cref="TileTick"/> record compatible with the block's type.</param>
public void SetTileTick (TileTick te)
{
_collection.SetTileTick(_index, te);
}
/// <summary>
/// Creates a default <see cref="TileTick"/> record appropriate for the block.
/// </summary>
public void CreateTileTick ()
{
_collection.CreateTileTick(_index);
}
/// <summary>
/// Removes any <see cref="TileTick"/> currently attached to the block.
/// </summary>
public void ClearTileTick ()
{
_collection.ClearTileTick(_index);
}
#endregion
} }
} }

View file

@ -253,6 +253,7 @@ namespace Substrate
private int _id = 0; private int _id = 0;
private string _name = ""; private string _name = "";
private int _tick = 0;
private int _opacity = MAX_OPACITY; private int _opacity = MAX_OPACITY;
private int _luminance = MIN_LUMINANCE; private int _luminance = MIN_LUMINANCE;
private bool _transmitLight = false; private bool _transmitLight = false;
@ -366,6 +367,11 @@ namespace Substrate
get { return _registered; } get { return _registered; }
} }
public int Tick
{
get { return _tick; }
}
internal BlockInfo (int id) internal BlockInfo (int id)
{ {
_id = id; _id = id;
@ -392,6 +398,7 @@ namespace Substrate
/// </summary> /// </summary>
/// <param name="opacity">A new opacity value.</param> /// <param name="opacity">A new opacity value.</param>
/// <returns>The object instance used to invoke this method.</returns> /// <returns>The object instance used to invoke this method.</returns>
/// <seealso cref="AlphaBlockCollection.AutoLight"/>
public BlockInfo SetOpacity (int opacity) public BlockInfo SetOpacity (int opacity)
{ {
_opacity = MIN_OPACITY + opacity; _opacity = MIN_OPACITY + opacity;
@ -412,6 +419,7 @@ namespace Substrate
/// </summary> /// </summary>
/// <param name="luminance">A new luminance value.</param> /// <param name="luminance">A new luminance value.</param>
/// <returns>The object instance used to invoke this method.</returns> /// <returns>The object instance used to invoke this method.</returns>
/// <seealso cref="AlphaBlockCollection.AutoLight"/>
public BlockInfo SetLuminance (int luminance) public BlockInfo SetLuminance (int luminance)
{ {
_luminance = luminance; _luminance = luminance;
@ -424,6 +432,7 @@ namespace Substrate
/// </summary> /// </summary>
/// <param name="transmit">True if this block type can transmit light to neighbors, false otherwise.</param> /// <param name="transmit">True if this block type can transmit light to neighbors, false otherwise.</param>
/// <returns>The object instance used to invoke this method.</returns> /// <returns>The object instance used to invoke this method.</returns>
/// <seealso cref="AlphaBlockCollection.AutoLight"/>
public BlockInfo SetLightTransmission (bool transmit) public BlockInfo SetLightTransmission (bool transmit)
{ {
_transmitLight = transmit; _transmitLight = transmit;
@ -467,12 +476,26 @@ namespace Substrate
/// </summary> /// </summary>
/// <param name="blocks">True if this block type blocks fluids, false otherwise.</param> /// <param name="blocks">True if this block type blocks fluids, false otherwise.</param>
/// <returns>The object instance used to invoke this method.</returns> /// <returns>The object instance used to invoke this method.</returns>
/// <seealso cref="AlphaBlockCollection.AutoFluid"/>
public BlockInfo SetBlocksFluid (bool blocks) public BlockInfo SetBlocksFluid (bool blocks)
{ {
_blocksFluid = blocks; _blocksFluid = blocks;
return this; return this;
} }
/// <summary>
/// Sets the default tick rate/delay used for updating this block.
/// </summary>
/// <remarks>Set <paramref name="tick"/> to <c>0</c> to indicate that this block is not processed by tick updates.</remarks>
/// <param name="tick">The tick rate in frames between scheduled updates on this block.</param>
/// <returns>The object instance used to invoke this method.</returns>
/// <seealso cref="AlphaBlockCollection.AutoTileTick"/>
public BlockInfo SetTick (int tick)
{
_tick = tick;
return this;
}
/// <summary> /// <summary>
/// Tests if the given data value is valid for this block type. /// Tests if the given data value is valid for this block type.
/// </summary> /// </summary>
@ -623,33 +646,33 @@ namespace Substrate
Air = new BlockInfo(0, "Air").SetOpacity(0).SetState(BlockState.NONSOLID); Air = new BlockInfo(0, "Air").SetOpacity(0).SetState(BlockState.NONSOLID);
Stone = new BlockInfo(1, "Stone"); Stone = new BlockInfo(1, "Stone");
Grass = new BlockInfo(2, "Grass"); Grass = new BlockInfo(2, "Grass").SetTick(10);
Dirt = new BlockInfo(3, "Dirt"); Dirt = new BlockInfo(3, "Dirt");
Cobblestone = new BlockInfo(4, "Cobblestone"); Cobblestone = new BlockInfo(4, "Cobblestone");
WoodPlank = new BlockInfo(5, "Wooden Plank"); WoodPlank = new BlockInfo(5, "Wooden Plank");
Sapling = new BlockInfo(6, "Sapling").SetOpacity(0).SetState(BlockState.NONSOLID); Sapling = new BlockInfo(6, "Sapling").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
Bedrock = new BlockInfo(7, "Bedrock"); Bedrock = new BlockInfo(7, "Bedrock");
Water = new BlockInfo(8, "Water").SetOpacity(3).SetState(BlockState.FLUID); Water = new BlockInfo(8, "Water").SetOpacity(3).SetState(BlockState.FLUID).SetTick(5);
StationaryWater = new BlockInfo(9, "Stationary Water").SetOpacity(3).SetState(BlockState.FLUID); StationaryWater = new BlockInfo(9, "Stationary Water").SetOpacity(3).SetState(BlockState.FLUID);
Lava = new BlockInfo(10, "Lava").SetOpacity(0).SetLuminance(MAX_LUMINANCE).SetState(BlockState.FLUID); Lava = new BlockInfo(10, "Lava").SetOpacity(0).SetLuminance(MAX_LUMINANCE).SetState(BlockState.FLUID).SetTick(30);
StationaryLava = new BlockInfo(11, "Stationary Lava").SetOpacity(0).SetLuminance(MAX_LUMINANCE).SetState(BlockState.FLUID); StationaryLava = new BlockInfo(11, "Stationary Lava").SetOpacity(0).SetLuminance(MAX_LUMINANCE).SetState(BlockState.FLUID).SetTick(10);
Sand = new BlockInfo(12, "Sand"); Sand = new BlockInfo(12, "Sand").SetTick(3);
Gravel = new BlockInfo(13, "Gravel"); Gravel = new BlockInfo(13, "Gravel").SetTick(3);
GoldOre = new BlockInfo(14, "Gold Ore"); GoldOre = new BlockInfo(14, "Gold Ore");
IronOre = new BlockInfo(15, "Iron Ore"); IronOre = new BlockInfo(15, "Iron Ore");
CoalOre = new BlockInfo(16, "Coal Ore"); CoalOre = new BlockInfo(16, "Coal Ore");
Wood = new BlockInfo(17, "Wood"); Wood = new BlockInfo(17, "Wood");
Leaves = new BlockInfo(18, "Leaves").SetOpacity(1); Leaves = new BlockInfo(18, "Leaves").SetOpacity(1).SetTick(10);
Sponge = new BlockInfo(19, "Sponge"); Sponge = new BlockInfo(19, "Sponge");
Glass = new BlockInfo(20, "Glass").SetOpacity(0); Glass = new BlockInfo(20, "Glass").SetOpacity(0);
LapisOre = new BlockInfo(21, "Lapis Lazuli Ore"); LapisOre = new BlockInfo(21, "Lapis Lazuli Ore");
LapisBlock = new BlockInfo(22, "Lapis Lazuli Block"); LapisBlock = new BlockInfo(22, "Lapis Lazuli Block");
Dispenser = new BlockInfoEx(23, "Dispenser"); Dispenser = (BlockInfoEx)new BlockInfoEx(23, "Dispenser").SetTick(4);
Sandstone = new BlockInfo(24, "Sandstone"); Sandstone = new BlockInfo(24, "Sandstone");
NoteBlock = new BlockInfoEx(25, "Note Block"); NoteBlock = new BlockInfoEx(25, "Note Block");
Bed = new BlockInfo(26, "Bed").SetOpacity(0); Bed = new BlockInfo(26, "Bed").SetOpacity(0);
PoweredRail = new BlockInfo(27, "Powered Rail").SetOpacity(0).SetState(BlockState.NONSOLID); PoweredRail = new BlockInfo(27, "Powered Rail").SetOpacity(0).SetState(BlockState.NONSOLID);
DetectorRail = new BlockInfo(28, "Detector Rail").SetOpacity(0).SetState(BlockState.NONSOLID); DetectorRail = new BlockInfo(28, "Detector Rail").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(20);
StickyPiston = new BlockInfo(29, "Sticky Piston").SetOpacity(0); StickyPiston = new BlockInfo(29, "Sticky Piston").SetOpacity(0);
Cobweb = new BlockInfo(30, "Cobweb").SetOpacity(0).SetState(BlockState.NONSOLID); Cobweb = new BlockInfo(30, "Cobweb").SetOpacity(0).SetState(BlockState.NONSOLID);
TallGrass = new BlockInfo(31, "Tall Grass").SetOpacity(0).SetState(BlockState.NONSOLID); TallGrass = new BlockInfo(31, "Tall Grass").SetOpacity(0).SetState(BlockState.NONSOLID);
@ -658,10 +681,10 @@ namespace Substrate
PistonHead = new BlockInfo(34, "Piston Head").SetOpacity(0); PistonHead = new BlockInfo(34, "Piston Head").SetOpacity(0);
Wool = new BlockInfo(35, "Wool"); Wool = new BlockInfo(35, "Wool");
PistonMoving = (BlockInfoEx)new BlockInfoEx(36, "Piston Moving").SetOpacity(0); PistonMoving = (BlockInfoEx)new BlockInfoEx(36, "Piston Moving").SetOpacity(0);
YellowFlower = new BlockInfo(37, "Yellow Flower").SetOpacity(0).SetState(BlockState.NONSOLID); YellowFlower = new BlockInfo(37, "Yellow Flower").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
RedRose = new BlockInfo(38, "Red Rose").SetOpacity(0).SetState(BlockState.NONSOLID); RedRose = new BlockInfo(38, "Red Rose").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
BrownMushroom = new BlockInfo(39, "Brown Mushroom").SetOpacity(0).SetLuminance(1).SetState(BlockState.NONSOLID); BrownMushroom = new BlockInfo(39, "Brown Mushroom").SetOpacity(0).SetLuminance(1).SetState(BlockState.NONSOLID).SetTick(10);
RedMushroom = new BlockInfo(40, "Red Mushroom").SetOpacity(0).SetState(BlockState.NONSOLID); RedMushroom = new BlockInfo(40, "Red Mushroom").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
GoldBlock = new BlockInfo(41, "Gold Block"); GoldBlock = new BlockInfo(41, "Gold Block");
IronBlock = new BlockInfo(42, "Iron Block"); IronBlock = new BlockInfo(42, "Iron Block");
DoubleSlab = new BlockInfo(43, "Double Slab"); DoubleSlab = new BlockInfo(43, "Double Slab");
@ -671,8 +694,8 @@ namespace Substrate
Bookshelf = new BlockInfo(47, "Bookshelf"); Bookshelf = new BlockInfo(47, "Bookshelf");
MossStone = new BlockInfo(48, "Moss Stone"); MossStone = new BlockInfo(48, "Moss Stone");
Obsidian = new BlockInfo(49, "Obsidian"); Obsidian = new BlockInfo(49, "Obsidian");
Torch = new BlockInfo(50, "Torch").SetOpacity(0).SetLuminance(MAX_LUMINANCE - 1).SetState(BlockState.NONSOLID); Torch = new BlockInfo(50, "Torch").SetOpacity(0).SetLuminance(MAX_LUMINANCE - 1).SetState(BlockState.NONSOLID).SetTick(10);
Fire = new BlockInfo(51, "Fire").SetOpacity(0).SetLuminance(MAX_LUMINANCE).SetState(BlockState.NONSOLID); Fire = new BlockInfo(51, "Fire").SetOpacity(0).SetLuminance(MAX_LUMINANCE).SetState(BlockState.NONSOLID).SetTick(40);
MonsterSpawner = (BlockInfoEx)new BlockInfoEx(52, "Monster Spawner").SetOpacity(0); MonsterSpawner = (BlockInfoEx)new BlockInfoEx(52, "Monster Spawner").SetOpacity(0);
WoodStairs = new BlockInfo(53, "Wooden Stairs").SetOpacity(0); WoodStairs = new BlockInfo(53, "Wooden Stairs").SetOpacity(0);
Chest = (BlockInfoEx)new BlockInfoEx(54, "Chest").SetOpacity(0); Chest = (BlockInfoEx)new BlockInfoEx(54, "Chest").SetOpacity(0);
@ -680,8 +703,8 @@ namespace Substrate
DiamondOre = new BlockInfo(56, "Diamond Ore"); DiamondOre = new BlockInfo(56, "Diamond Ore");
DiamondBlock = new BlockInfo(57, "Diamond Block"); DiamondBlock = new BlockInfo(57, "Diamond Block");
CraftTable = new BlockInfo(58, "Crafting Table"); CraftTable = new BlockInfo(58, "Crafting Table");
Crops = new BlockInfo(59, "Crops").SetOpacity(0).SetState(BlockState.NONSOLID); Crops = new BlockInfo(59, "Crops").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
Farmland = new BlockInfo(60, "Farmland").SetOpacity(0); Farmland = new BlockInfo(60, "Farmland").SetOpacity(0).SetTick(10);
Furnace = new BlockInfoEx(61, "Furnace"); Furnace = new BlockInfoEx(61, "Furnace");
BurningFurnace = (BlockInfoEx)new BlockInfoEx(62, "Burning Furnace").SetLuminance(MAX_LUMINANCE - 1); BurningFurnace = (BlockInfoEx)new BlockInfoEx(62, "Burning Furnace").SetLuminance(MAX_LUMINANCE - 1);
SignPost = (BlockInfoEx)new BlockInfoEx(63, "Sign Post").SetOpacity(0).SetState(BlockState.NONSOLID); SignPost = (BlockInfoEx)new BlockInfoEx(63, "Sign Post").SetOpacity(0).SetState(BlockState.NONSOLID);
@ -691,20 +714,20 @@ namespace Substrate
CobbleStairs = new BlockInfo(67, "Cobblestone Stairs").SetOpacity(0); CobbleStairs = new BlockInfo(67, "Cobblestone Stairs").SetOpacity(0);
WallSign = (BlockInfoEx)new BlockInfoEx(68, "Wall Sign").SetOpacity(0).SetState(BlockState.NONSOLID); WallSign = (BlockInfoEx)new BlockInfoEx(68, "Wall Sign").SetOpacity(0).SetState(BlockState.NONSOLID);
Lever = new BlockInfo(69, "Lever").SetOpacity(0).SetState(BlockState.NONSOLID); Lever = new BlockInfo(69, "Lever").SetOpacity(0).SetState(BlockState.NONSOLID);
StonePlate = new BlockInfo(70, "Stone Pressure Plate").SetOpacity(0).SetState(BlockState.NONSOLID); StonePlate = new BlockInfo(70, "Stone Pressure Plate").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(20);
IronDoor = new BlockInfo(71, "Iron Door").SetOpacity(0); IronDoor = new BlockInfo(71, "Iron Door").SetOpacity(0);
WoodPlate = new BlockInfo(72, "Wooden Pressure Plate").SetOpacity(0).SetState(BlockState.NONSOLID); WoodPlate = new BlockInfo(72, "Wooden Pressure Plate").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(20);
RedstoneOre = new BlockInfo(73, "Redstone Ore"); RedstoneOre = new BlockInfo(73, "Redstone Ore").SetTick(30);
GlowRedstoneOre = new BlockInfo(74, "Glowing Redstone Ore").SetLuminance(9); GlowRedstoneOre = new BlockInfo(74, "Glowing Redstone Ore").SetLuminance(9).SetTick(30);
RedstoneTorch = new BlockInfo(75, "Redstone Torch (Off)").SetOpacity(0).SetState(BlockState.NONSOLID); RedstoneTorch = new BlockInfo(75, "Redstone Torch (Off)").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(2);
RedstoneTorchOn = new BlockInfo(76, "Redstone Torch (On)").SetOpacity(0).SetLuminance(7).SetState(BlockState.NONSOLID); RedstoneTorchOn = new BlockInfo(76, "Redstone Torch (On)").SetOpacity(0).SetLuminance(7).SetState(BlockState.NONSOLID).SetTick(2);
StoneButton = new BlockInfo(77, "Stone Button").SetOpacity(0).SetState(BlockState.NONSOLID); StoneButton = new BlockInfo(77, "Stone Button").SetOpacity(0).SetState(BlockState.NONSOLID);
Snow = new BlockInfo(78, "Snow").SetOpacity(0).SetState(BlockState.NONSOLID); Snow = new BlockInfo(78, "Snow").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
Ice = new BlockInfo(79, "Ice").SetOpacity(3); Ice = new BlockInfo(79, "Ice").SetOpacity(3).SetTick(10);
SnowBlock = new BlockInfo(80, "Snow Block"); SnowBlock = new BlockInfo(80, "Snow Block").SetTick(10);
Cactus = new BlockInfo(81, "Cactus").SetOpacity(0); Cactus = new BlockInfo(81, "Cactus").SetOpacity(0).SetTick(10);
ClayBlock = new BlockInfo(82, "Clay Block"); ClayBlock = new BlockInfo(82, "Clay Block");
SugarCane = new BlockInfo(83, "Sugar Cane").SetOpacity(0).SetState(BlockState.NONSOLID); SugarCane = new BlockInfo(83, "Sugar Cane").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
Jukebox = new BlockInfo(84, "Jukebox"); Jukebox = new BlockInfo(84, "Jukebox");
Fence = new BlockInfo(85, "Fence").SetOpacity(0); Fence = new BlockInfo(85, "Fence").SetOpacity(0);
Pumpkin = new BlockInfo(86, "Pumpkin"); Pumpkin = new BlockInfo(86, "Pumpkin");
@ -714,9 +737,9 @@ namespace Substrate
Portal = new BlockInfo(90, "Portal").SetOpacity(0).SetLuminance(11).SetState(BlockState.NONSOLID); Portal = new BlockInfo(90, "Portal").SetOpacity(0).SetLuminance(11).SetState(BlockState.NONSOLID);
JackOLantern = new BlockInfo(91, "Jack-O-Lantern").SetLuminance(MAX_LUMINANCE); JackOLantern = new BlockInfo(91, "Jack-O-Lantern").SetLuminance(MAX_LUMINANCE);
CakeBlock = new BlockInfo(92, "Cake Block").SetOpacity(0); CakeBlock = new BlockInfo(92, "Cake Block").SetOpacity(0);
RedstoneRepeater = new BlockInfo(93, "Redstone Repeater (Off)").SetOpacity(0); RedstoneRepeater = new BlockInfo(93, "Redstone Repeater (Off)").SetOpacity(0).SetTick(10);
RedstoneRepeaterOn = new BlockInfo(94, "Redstone Repeater (On)").SetOpacity(0).SetLuminance(7); RedstoneRepeaterOn = new BlockInfo(94, "Redstone Repeater (On)").SetOpacity(0).SetLuminance(7).SetTick(10);
LockedChest = (BlockInfoEx)new BlockInfoEx(95, "Locked Chest").SetLuminance(MAX_LUMINANCE); LockedChest = (BlockInfoEx)new BlockInfoEx(95, "Locked Chest").SetLuminance(MAX_LUMINANCE).SetTick(10);
Trapdoor = new BlockInfo(96, "Trapdoor").SetOpacity(0); Trapdoor = new BlockInfo(96, "Trapdoor").SetOpacity(0);
SilverfishStone = new BlockInfo(97, "Stone with Silverfish"); SilverfishStone = new BlockInfo(97, "Stone with Silverfish");
StoneBrick = new BlockInfo(98, "Stone Brick"); StoneBrick = new BlockInfo(98, "Stone Brick");
@ -725,25 +748,25 @@ namespace Substrate
IronBars = new BlockInfo(101, "Iron Bars").SetOpacity(0); IronBars = new BlockInfo(101, "Iron Bars").SetOpacity(0);
GlassPane = new BlockInfo(102, "Glass Pane").SetOpacity(0); GlassPane = new BlockInfo(102, "Glass Pane").SetOpacity(0);
Melon = new BlockInfo(103, "Melon"); Melon = new BlockInfo(103, "Melon");
PumpkinStem = new BlockInfo(104, "Pumpkin Stem").SetOpacity(0).SetState(BlockState.NONSOLID); PumpkinStem = new BlockInfo(104, "Pumpkin Stem").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
MelonStem = new BlockInfo(105, "Melon Stem").SetOpacity(0).SetState(BlockState.NONSOLID); MelonStem = new BlockInfo(105, "Melon Stem").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
Vines = new BlockInfo(106, "Vines").SetOpacity(0).SetState(BlockState.NONSOLID); Vines = new BlockInfo(106, "Vines").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
FenceGate = new BlockInfo(107, "Fence Gate").SetOpacity(0); FenceGate = new BlockInfo(107, "Fence Gate").SetOpacity(0);
BrickStairs = new BlockInfo(108, "Brick Stairs").SetOpacity(0); BrickStairs = new BlockInfo(108, "Brick Stairs").SetOpacity(0);
StoneBrickStairs = new BlockInfo(109, "Stone Brick Stairs").SetOpacity(0); StoneBrickStairs = new BlockInfo(109, "Stone Brick Stairs").SetOpacity(0);
Mycelium = new BlockInfo(110, "Mycelium"); Mycelium = new BlockInfo(110, "Mycelium").SetTick(10);
LillyPad = new BlockInfo(111, "Lilly Pad").SetOpacity(0).SetState(BlockState.NONSOLID); LillyPad = new BlockInfo(111, "Lilly Pad").SetOpacity(0).SetState(BlockState.NONSOLID);
NetherBrick = new BlockInfo(112, "Nether Brick"); NetherBrick = new BlockInfo(112, "Nether Brick");
NetherBrickFence = new BlockInfo(113, "Nether Brick Fence").SetOpacity(0); NetherBrickFence = new BlockInfo(113, "Nether Brick Fence").SetOpacity(0);
NetherBrickStairs = new BlockInfo(114, "Nether Brick Stairs").SetOpacity(0); NetherBrickStairs = new BlockInfo(114, "Nether Brick Stairs").SetOpacity(0);
NetherWart = new BlockInfo(115, "Nether Wart").SetOpacity(0).SetState(BlockState.NONSOLID); NetherWart = new BlockInfo(115, "Nether Wart").SetOpacity(0).SetState(BlockState.NONSOLID).SetTick(10);
EnchantmentTable = (BlockInfoEx)new BlockInfoEx(116, "Enchantment Table").SetOpacity(0); EnchantmentTable = (BlockInfoEx)new BlockInfoEx(116, "Enchantment Table").SetOpacity(0);
BrewingStand = (BlockInfoEx)new BlockInfoEx(117, "Brewing Stand").SetOpacity(0); BrewingStand = (BlockInfoEx)new BlockInfoEx(117, "Brewing Stand").SetOpacity(0);
Cauldron = new BlockInfo(118, "Cauldron").SetOpacity(0); Cauldron = new BlockInfo(118, "Cauldron").SetOpacity(0);
EndPortal = (BlockInfoEx)new BlockInfoEx(119, "End Portal").SetOpacity(0).SetLuminance(MAX_LUMINANCE).SetState(BlockState.NONSOLID); EndPortal = (BlockInfoEx)new BlockInfoEx(119, "End Portal").SetOpacity(0).SetLuminance(MAX_LUMINANCE).SetState(BlockState.NONSOLID);
EndPortalFrame = new BlockInfo(120, "End Portal Frame").SetLuminance(MAX_LUMINANCE); EndPortalFrame = new BlockInfo(120, "End Portal Frame").SetLuminance(MAX_LUMINANCE);
EndStone = new BlockInfo(121, "End Stone"); EndStone = new BlockInfo(121, "End Stone");
DragonEgg = new BlockInfo(122, "Dragon Egg").SetOpacity(0).SetLuminance(1); DragonEgg = new BlockInfo(122, "Dragon Egg").SetOpacity(0).SetLuminance(1).SetTick(3);
for (int i = 0; i < MAX_BLOCKS; i++) { for (int i = 0; i < MAX_BLOCKS; i++) {
if (_blockTable[i] == null) { if (_blockTable[i] == null) {

View file

@ -6,7 +6,7 @@ namespace Substrate
/// <summary> /// <summary>
/// Represents an Alpha-compatible interface for globally managing blocks. /// Represents an Alpha-compatible interface for globally managing blocks.
/// </summary> /// </summary>
public class BlockManager : IBlockManager public class BlockManager : IVersion10BlockManager, IBlockManager
{ {
public const int MIN_X = -32000000; public const int MIN_X = -32000000;
public const int MAX_X = 32000000; public const int MAX_X = 32000000;
@ -441,5 +441,92 @@ namespace Substrate
} }
#endregion #endregion
#region IActiveBlockContainer Members
IActiveBlock IActiveBlockCollection.GetBlock (int x, int y, int z)
{
return GetBlock(x, y, z);
}
IActiveBlock IActiveBlockCollection.GetBlockRef (int x, int y, int z)
{
return GetBlockRef(x, y, z);
}
/// <inheritdoc/>
public void SetBlock (int x, int y, int z, IActiveBlock block)
{
cache.Blocks.SetBlock(x, y, z, block);
}
/// <inheritdoc/>
public int GetTileTickValue (int x, int y, int z)
{
cache = GetChunk(x, y, z);
if (cache == null || !Check(x, y, z)) {
return 0;
}
return cache.Blocks.GetTileTickValue(x & chunkXMask, y & chunkYMask, z & chunkZMask);
}
/// <inheritdoc/>
public void SetTileTickValue (int x, int y, int z, int tickValue)
{
cache = GetChunk(x, y, z);
if (cache == null || !Check(x, y, z)) {
return;
}
cache.Blocks.SetTileTickValue(x & chunkXMask, y & chunkYMask, z & chunkZMask, tickValue);
}
/// <inheritdoc/>
public TileTick GetTileTick (int x, int y, int z)
{
cache = GetChunk(x, y, z);
if (cache == null || !Check(x, y, z)) {
return null;
}
return cache.Blocks.GetTileTick(x & chunkXMask, y & chunkYMask, z & chunkZMask);
}
/// <inheritdoc/>
public void SetTileTick (int x, int y, int z, TileTick te)
{
cache = GetChunk(x, y, z);
if (cache == null || !Check(x, y, z)) {
return;
}
cache.Blocks.SetTileTick(x & chunkXMask, y & chunkYMask, z & chunkZMask, te);
}
/// <inheritdoc/>
public void CreateTileTick (int x, int y, int z)
{
cache = GetChunk(x, y, z);
if (cache == null || !Check(x, y, z)) {
return;
}
cache.Blocks.CreateTileTick(x & chunkXMask, y & chunkYMask, z & chunkZMask);
}
/// <inheritdoc/>
public void ClearTileTick (int x, int y, int z)
{
cache = GetChunk(x, y, z);
if (cache == null || !Check(x, y, z)) {
return;
}
cache.Blocks.ClearTileTick(x & chunkXMask, y & chunkYMask, z & chunkZMask);
}
#endregion
} }
} }

View file

@ -32,6 +32,7 @@ namespace Substrate
new SchemaNodeArray("HeightMap", 256), new SchemaNodeArray("HeightMap", 256),
new SchemaNodeList("Entities", TagType.TAG_COMPOUND, SchemaOptions.CREATE_ON_MISSING), new SchemaNodeList("Entities", TagType.TAG_COMPOUND, SchemaOptions.CREATE_ON_MISSING),
new SchemaNodeList("TileEntities", TagType.TAG_COMPOUND, TileEntity.Schema, 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("LastUpdate", TagType.TAG_LONG, SchemaOptions.CREATE_ON_MISSING),
new SchemaNodeScaler("xPos", TagType.TAG_INT), new SchemaNodeScaler("xPos", TagType.TAG_INT),
new SchemaNodeScaler("zPos", TagType.TAG_INT), new SchemaNodeScaler("zPos", TagType.TAG_INT),
@ -52,6 +53,7 @@ namespace Substrate
private TagNodeList _entities; private TagNodeList _entities;
private TagNodeList _tileEntities; private TagNodeList _tileEntities;
private TagNodeList _tileTicks;
private AlphaBlockCollection _blockManager; private AlphaBlockCollection _blockManager;
private EntityCollection _entityManager; private EntityCollection _entityManager;
@ -189,6 +191,25 @@ namespace Substrate
_tileEntities.Add(te.BuildTree()); _tileEntities.Add(te.BuildTree());
} }
// Update tile tick coordinates
if (_tileTicks != null) {
List<TileTick> tileTicks = new List<TileTick>();
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 // Update entity coordinates
List<TypedEntity> entities = new List<TypedEntity>(); List<TypedEntity> entities = new List<TypedEntity>();
@ -214,6 +235,8 @@ namespace Substrate
return false; return false;
} }
BuildConditional();
_tree.WriteTo(outStream); _tree.WriteTo(outStream);
outStream.Close(); outStream.Close();
@ -248,6 +271,11 @@ namespace Substrate
_entities = level["Entities"] as TagNodeList; _entities = level["Entities"] as TagNodeList;
_tileEntities = level["TileEntities"] 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 // List-type patch up
if (_entities.Count == 0) { if (_entities.Count == 0) {
level["Entities"] = new TagNodeList(TagType.TAG_COMPOUND); level["Entities"] = new TagNodeList(TagType.TAG_COMPOUND);
@ -259,10 +287,15 @@ namespace Substrate
_tileEntities = level["TileEntities"] as TagNodeList; _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(); _cx = level["xPos"].ToTagInt();
_cz = level["zPos"].ToTagInt(); _cz = level["zPos"].ToTagInt();
_blockManager = new AlphaBlockCollection(_blocks, _data, _blockLight, _skyLight, _heightMap, _tileEntities); _blockManager = new AlphaBlockCollection(_blocks, _data, _blockLight, _skyLight, _heightMap, _tileEntities, _tileTicks);
_entityManager = new EntityCollection(_entities); _entityManager = new EntityCollection(_entities);
return this; return this;
@ -288,6 +321,8 @@ namespace Substrate
/// <returns>The root node of the Chunk's NBT tree.</returns> /// <returns>The root node of the Chunk's NBT tree.</returns>
public TagNode BuildTree () public TagNode BuildTree ()
{ {
BuildConditional();
return _tree.Root; return _tree.Root;
} }
@ -319,6 +354,15 @@ namespace Substrate
#endregion #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 () private void BuildNBTTree ()
{ {
int elements2 = XDIM * ZDIM; int elements2 = XDIM * ZDIM;
@ -338,6 +382,7 @@ namespace Substrate
_entities = new TagNodeList(TagType.TAG_COMPOUND); _entities = new TagNodeList(TagType.TAG_COMPOUND);
_tileEntities = new TagNodeList(TagType.TAG_COMPOUND); _tileEntities = new TagNodeList(TagType.TAG_COMPOUND);
_tileTicks = new TagNodeList(TagType.TAG_COMPOUND);
TagNodeCompound level = new TagNodeCompound(); TagNodeCompound level = new TagNodeCompound();
level.Add("Blocks", blocks); level.Add("Blocks", blocks);
@ -347,6 +392,7 @@ namespace Substrate
level.Add("HeightMap", heightMap); level.Add("HeightMap", heightMap);
level.Add("Entities", _entities); level.Add("Entities", _entities);
level.Add("TileEntities", _tileEntities); level.Add("TileEntities", _tileEntities);
level.Add("TileTicks", _tileTicks);
level.Add("LastUpdate", new TagNodeLong(Timestamp())); level.Add("LastUpdate", new TagNodeLong(Timestamp()));
level.Add("xPos", new TagNodeInt(_cx)); level.Add("xPos", new TagNodeInt(_cx));
level.Add("zPos", new TagNodeInt(_cz)); level.Add("zPos", new TagNodeInt(_cz));

View file

@ -2,11 +2,29 @@
namespace Substrate.Core namespace Substrate.Core
{ {
/// <summary>
/// Represents the cardinal direction of a block collection's neighboring collection.
/// </summary>
public enum BlockCollectionEdge public enum BlockCollectionEdge
{ {
/// <summary>
/// Refers to a chunk/collection to the east of the current chunk/collection.
/// </summary>
EAST = 0, EAST = 0,
/// <summary>
/// Refers to a chunk/collection to the north of the current chunk/collection.
/// </summary>
NORTH = 1, NORTH = 1,
/// <summary>
/// Refers to a chunk/collection to the west of the current chunk/collection.
/// </summary>
WEST = 2, WEST = 2,
/// <summary>
/// Refers to a chunk/collection to the south of the current chunk/collection.
/// </summary>
SOUTH = 3 SOUTH = 3
} }
@ -86,6 +104,41 @@ namespace Substrate.Core
void ClearTileEntity (); void ClearTileEntity ();
} }
/// <summary>
/// A block type supporting active tick state.
/// </summary>
public interface IActiveBlock : IBlock
{
/// <summary>
/// Gets a <see cref="TileTick"/> entry attached to this block.
/// </summary>
/// <returns>A <see cref="TileTick"/> for this block, or null if one has not been created yet.</returns>
TileTick GetTileTick ();
/// <summary>
/// Sets the <see cref="TileTick"/> attached to this block.
/// </summary>
/// <param name="tt">A <see cref="TileTick"/> representing the delay until this block is next processed in-game.</param>
void SetTileTick (TileTick tt);
/// <summary>
/// Creates a default <see cref="TileTick"/> entry for this block.
/// </summary>
/// <remarks>This method will overwrite any existing <see cref="TileTick"/> attached to the block.</remarks>
void CreateTileTick ();
/// <summary>
/// Deletes the <see cref="TileTick"/> entry attached to this block, if one exists.
/// </summary>
void ClearTileTick ();
/// <summary>
/// Gets or sets the the actual tick delay associated with this block.
/// </summary>
/// <remarks>If no underlying <see cref="TileTick"/> entry exists for this block, one will be created.</remarks>
int TileTickValue { get; set; }
}
/// <summary> /// <summary>
/// An Alpha-compatible context-free block type supporting data and properties. /// An Alpha-compatible context-free block type supporting data and properties.
/// </summary> /// </summary>
@ -104,10 +157,31 @@ namespace Substrate.Core
bool IsValid { get; } bool IsValid { get; }
} }
/// <summary>
/// A version-1.0-compatible context-free block type supporting data, properties, and active tick state.
/// </summary>
public interface IVersion10Block : IAlphaBlock, IActiveBlock
{
}
/// <summary>
/// A version-1.0-compatible reference type supporting data, lighting, properties, and active tick state.
/// </summary>
public interface IVersion10BlockRef : IAlphaBlockRef, IActiveBlock
{
}
/// <summary> /// <summary>
/// Provides a common interface for block containers that provide global management. /// Provides a common interface for block containers that provide global management.
/// </summary> /// </summary>
public interface IBlockManager : IAlphaBlockCollection public interface IBlockManager : IAlphaBlockCollection
{ {
} }
/// <summary>
/// Provides a common interface for block containers that provide global management, extended through Version 1.0 capabilities.
/// </summary>
public interface IVersion10BlockManager : IBlockManager, IActiveBlockCollection
{
}
} }

View file

@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using Substrate.Nbt;
namespace Substrate.Core
{
public class BlockTileTicks
{
private XZYByteArray _blocks;
private TagNodeList _tileTicks;
private Dictionary<BlockKey, TagNodeCompound> _tileTickTable;
public event BlockCoordinateHandler TranslateCoordinates;
public BlockTileTicks (XZYByteArray blocks, TagNodeList tileTicks)
{
_blocks = blocks;
_tileTicks = tileTicks;
BuildTileTickCache();
}
public BlockTileTicks (BlockTileTicks bte)
{
_blocks = bte._blocks;
_tileTicks = bte._tileTicks;
BuildTileTickCache();
}
public int GetTileTickValue (int x, int y, int z)
{
BlockKey key = (TranslateCoordinates != null)
? TranslateCoordinates(x, y, z)
: new BlockKey(x, y, z);
TagNodeCompound te;
if (!_tileTickTable.TryGetValue(key, out te)) {
return 0;
}
if (!te.ContainsKey("t"))
return 0;
return te["t"].ToTagInt().Data;
}
public void SetTileTickValue (int x, int y, int z, int tickValue)
{
BlockKey key = (TranslateCoordinates != null)
? TranslateCoordinates(x, y, z)
: new BlockKey(x, y, z);
TagNodeCompound te;
if (!_tileTickTable.TryGetValue(key, out te)) {
TileTick tt = new TileTick()
{
ID = _blocks[x, y, z],
Ticks = tickValue,
X = key.x,
Y = key.y,
Z = key.z,
};
te = tt.BuildTree() as TagNodeCompound;
_tileTicks.Add(te);
_tileTickTable[key] = te;
}
else {
te["Ticks"].ToTagInt().Data = tickValue;
}
}
public TileTick GetTileTick (int x, int y, int z)
{
BlockKey key = (TranslateCoordinates != null)
? TranslateCoordinates(x, y, z)
: new BlockKey(x, y, z);
TagNodeCompound te;
if (!_tileTickTable.TryGetValue(key, out te)) {
return null;
}
if (!te.ContainsKey("i")) {
return null;
}
return TileTick.FromTreeSafe(te);
}
public void SetTileTick (int x, int y, int z, TileTick te)
{
if (te.ID != _blocks[x, y, z]) {
throw new ArgumentException("The TileTick type is not valid for this block.", "te");
}
BlockKey key = (TranslateCoordinates != null)
? TranslateCoordinates(x, y, z)
: new BlockKey(x, y, z);
TagNodeCompound oldte;
if (_tileTickTable.TryGetValue(key, out oldte)) {
_tileTicks.Remove(oldte);
}
te.X = key.x;
te.Y = key.y;
te.Z = key.z;
TagNodeCompound tree = te.BuildTree() as TagNodeCompound;
_tileTicks.Add(tree);
_tileTickTable[key] = tree;
}
public void CreateTileTick (int x, int y, int z)
{
TileTick te = new TileTick()
{
ID = _blocks[x, y, z],
};
BlockKey key = (TranslateCoordinates != null)
? TranslateCoordinates(x, y, z)
: new BlockKey(x, y, z);
TagNodeCompound oldte;
if (_tileTickTable.TryGetValue(key, out oldte)) {
_tileTicks.Remove(oldte);
}
te.X = key.x;
te.Y = key.y;
te.Z = key.z;
TagNodeCompound tree = te.BuildTree() as TagNodeCompound;
_tileTicks.Add(tree);
_tileTickTable[key] = tree;
}
public void ClearTileTick (int x, int y, int z)
{
BlockKey key = (TranslateCoordinates != null)
? TranslateCoordinates(x, y, z)
: new BlockKey(x, y, z);
TagNodeCompound te;
if (!_tileTickTable.TryGetValue(key, out te)) {
return;
}
_tileTicks.Remove(te);
_tileTickTable.Remove(key);
}
private void BuildTileTickCache ()
{
_tileTickTable = new Dictionary<BlockKey, TagNodeCompound>();
foreach (TagNodeCompound te in _tileTicks) {
int tex = te["x"].ToTagInt();
int tey = te["y"].ToTagInt();
int tez = te["z"].ToTagInt();
BlockKey key = new BlockKey(tex, tey, tez);
_tileTickTable[key] = te;
}
}
}
}

View file

@ -415,6 +415,92 @@ namespace Substrate.Core
void ClearTileEntity (int x, int y, int z); void ClearTileEntity (int x, int y, int z);
} }
/// <summary>
/// A bounded container for blocks supporting active processing properties.
/// </summary>
/// <seealso cref="IBoundedActiveBlockCollection"/>
public interface IBoundedActiveBlockCollection : IBoundedBlockCollection
{
/// <summary>
/// Gets a block supporting active processing properties from a bounded block container.
/// </summary>
/// <param name="x">The container-local X-coordinate of a block.</param>
/// <param name="y">The container-local Y-coordinate of a block.</param>
/// <param name="z">The container-local Z-coordinate of a block.</param>
/// <returns>An <see cref="IActiveBlock"/> from the collection at the given coordinates.</returns>
new IActiveBlock GetBlock (int x, int y, int z);
/// <summary>
/// Gets a reference object to a block supporting active processing properties within a bounded block container.
/// </summary>
/// <param name="x">The container-local X-coordinate of a block.</param>
/// <param name="y">The container-local Y-coordinate of a block.</param>
/// <param name="z">The container-local Z-coordinate of a block.</param>
/// <returns>An <see cref="IActiveBlock"/> acting as a reference directly into the container at the given coordinates.</returns>
new IActiveBlock GetBlockRef (int x, int y, int z);
/// <summary>
/// Updates a block in a bounded block container with data from an existing <see cref="IActiveBlock"/> object.
/// </summary>
/// <param name="x">The container-local X-coordinate of a block.</param>
/// <param name="y">The container-local Y-coordinate of a block.</param>
/// <param name="z">The container-local Z-coordinate of a block.</param>
/// <param name="block">The <see cref="IActiveBlock"/> to copy data from.</param>
void SetBlock (int x, int y, int z, IActiveBlock block);
/// <summary>
/// Gets the <see cref="TileTick"/> record of a block within a bounded block container.
/// </summary>
/// <param name="x">The container-local X-coordinate of a block.</param>
/// <param name="y">The container-local Y-coordinate of a block.</param>
/// <param name="z">The container-local Z-coordinate of a block.</param>
/// <returns>A <see cref="TileTick"/> record attached to a block at the given coordinates, or null if no tile entity is set.</returns>
TileTick GetTileTick (int x, int y, int z);
/// <summary>
/// Sets a <see cref="TileTick"/> record to a block within a bounded block container.
/// </summary>
/// <param name="x">The container-local X-coordinate of a block.</param>
/// <param name="y">The container-local Y-coordinate of a block.</param>
/// <param name="z">The container-local Z-coordinate of a block.</param>
/// <param name="tt">The <see cref="TileTick"/> record to assign to the given block.</param>
void SetTileTick (int x, int y, int z, TileTick tt);
/// <summary>
/// Creates a new default <see cref="TileTick"/> record for a block within a bounded block container.
/// </summary>
/// <param name="x">The container-local X-coordinate of a block.</param>
/// <param name="y">The container-local Y-coordinate of a block.</param>
/// <param name="z">The container-local Z-coordinate of a block.</param>
void CreateTileTick (int x, int y, int z);
/// <summary>
/// Deletes a <see cref="TileTick"/> record associated with a block within a bounded block container, if it exists.
/// </summary>
/// <param name="x">The container-local X-coordinate of a block.</param>
/// <param name="y">The container-local Y-coordinate of a block.</param>
/// <param name="z">The container-local Z-coordinate of a block.</param>
void ClearTileTick (int x, int y, int z);
/// <summary>
/// Gets the tick delay specified in a block's <see cref="TileTick"/> entry, if it exists.
/// </summary>
/// <param name="x">The container-local X-coordinate of a block.</param>
/// <param name="y">The container-local Y-coordinate of a block.</param>
/// <param name="z">The container-local Z-coordinate of a block.</param>
/// <returns>The tick delay in a block's <see cref="TileTick"/> entry, or <c>0</c> if no entry exists.</returns>
int GetTileTickValue (int x, int y, int z);
/// <summary>
/// Sets the tick delay in a block's <see cref="TileTick"/> entry.
/// </summary>
/// <param name="x">The container-local X-coordinate of a block.</param>
/// <param name="y">The container-local Y-coordinate of a block.</param>
/// <param name="z">The container-local Z-coordinate of a block.</param>
/// <param name="tickValue">The tick delay that specifies when this block should next be processed for update.</param>
void SetTileTickValue (int x, int y, int z, int tickValue);
}
/// <summary> /// <summary>
/// A bounded container of blocks supporting data, lighting, and properties. /// A bounded container of blocks supporting data, lighting, and properties.
/// </summary> /// </summary>

View file

@ -236,7 +236,7 @@ namespace Substrate.Core
} }
/// <summary> /// <summary>
/// An unbounded container for blocks supporting additional properties. /// An unbounded container for blocks supporting extra properties.
/// </summary> /// </summary>
/// <seealso cref="IBoundedPropertyBlockCollection"/> /// <seealso cref="IBoundedPropertyBlockCollection"/>
public interface IPropertyBlockCollection : IBlockCollection public interface IPropertyBlockCollection : IBlockCollection
@ -307,6 +307,92 @@ namespace Substrate.Core
void ClearTileEntity (int x, int y, int z); void ClearTileEntity (int x, int y, int z);
} }
/// <summary>
/// An unbounded container for blocks supporting active processing properties.
/// </summary>
/// <seealso cref="IBoundedActiveBlockCollection"/>
public interface IActiveBlockCollection : IBlockCollection
{
/// <summary>
/// Gets a block supporting active processing properties from an unbounded block container.
/// </summary>
/// <param name="x">The global X-coordinate of a block.</param>
/// <param name="y">The global Y-coordinate of a block.</param>
/// <param name="z">The global Z-coordinate of a block.</param>
/// <returns>An <see cref="IActiveBlock"/> from the collection at the given coordinates.</returns>
new IActiveBlock GetBlock (int x, int y, int z);
/// <summary>
/// Gets a reference object to a block supporting active processing properties within an unbounded block container.
/// </summary>
/// <param name="x">The global X-coordinate of a block.</param>
/// <param name="y">The global Y-coordinate of a block.</param>
/// <param name="z">The global Z-coordinate of a block.</param>
/// <returns>An <see cref="IActiveBlock"/> acting as a reference directly into the container at the given coordinates.</returns>
new IActiveBlock GetBlockRef (int x, int y, int z);
/// <summary>
/// Updates a block in an unbounded block container with data from an existing <see cref="IActiveBlock"/> object.
/// </summary>
/// <param name="x">The global X-coordinate of a block.</param>
/// <param name="y">The global Y-coordinate of a block.</param>
/// <param name="z">The global Z-coordinate of a block.</param>
/// <param name="block">The <see cref="IActiveBlock"/> to copy data from.</param>
void SetBlock (int x, int y, int z, IActiveBlock block);
/// <summary>
/// Gets the <see cref="TileTick"/> record of a block within an unbounded block container.
/// </summary>
/// <param name="x">The global X-coordinate of a block.</param>
/// <param name="y">The global Y-coordinate of a block.</param>
/// <param name="z">The global Z-coordinate of a block.</param>
/// <returns>A <see cref="TileTick"/> record attached to a block at the given coordinates, or null if no tile entity is set.</returns>
TileTick GetTileTick (int x, int y, int z);
/// <summary>
/// Sets a <see cref="TileTick"/> record to a block within an unbounded block container.
/// </summary>
/// <param name="x">The global X-coordinate of a block.</param>
/// <param name="y">The global Y-coordinate of a block.</param>
/// <param name="z">The global Z-coordinate of a block.</param>
/// <param name="tt">The <see cref="TileTick"/> record to assign to the given block.</param>
void SetTileTick (int x, int y, int z, TileTick tt);
/// <summary>
/// Creates a new default <see cref="TileTick"/> record for a block within an unbounded block container.
/// </summary>
/// <param name="x">The global X-coordinate of a block.</param>
/// <param name="y">The global Y-coordinate of a block.</param>
/// <param name="z">The global Z-coordinate of a block.</param>
void CreateTileTick (int x, int y, int z);
/// <summary>
/// Deletes a <see cref="TileTick"/> record associated with a block within an unbounded block container, if it exists.
/// </summary>
/// <param name="x">The global X-coordinate of a block.</param>
/// <param name="y">The global Y-coordinate of a block.</param>
/// <param name="z">The global Z-coordinate of a block.</param>
void ClearTileTick (int x, int y, int z);
/// <summary>
/// Gets the tick delay specified in a block's <see cref="TileTick"/> entry, if it exists.
/// </summary>
/// <param name="x">The global X-coordinate of a block.</param>
/// <param name="y">The global Y-coordinate of a block.</param>
/// <param name="z">The global Z-coordinate of a block.</param>
/// <returns>The tick delay in a block's <see cref="TileTick"/> entry, or <c>0</c> if no entry exists.</returns>
int GetTileTickValue (int x, int y, int z);
/// <summary>
/// Sets the tick delay in a block's <see cref="TileTick"/> entry.
/// </summary>
/// <param name="x">The global X-coordinate of a block.</param>
/// <param name="y">The global Y-coordinate of a block.</param>
/// <param name="z">The global Z-coordinate of a block.</param>
/// <param name="tickValue">The tick delay that specifies when this block should next be processed for update.</param>
void SetTileTickValue (int x, int y, int z, int tickValue);
}
/// <summary> /// <summary>
/// An unbounded container of blocks supporting data, lighting, and properties. /// An unbounded container of blocks supporting data, lighting, and properties.
/// </summary> /// </summary>

View file

@ -0,0 +1,237 @@
using System;
using System.Collections.Generic;
using System.Text;
using Substrate.Nbt;
using Substrate.Core;
namespace Substrate
{
/// <summary>
/// Represents a TileTick record, which is used to queue a block for processing in the future.
/// </summary>
public class TileTick : INbtObject<TileTick>, ICopyable<TileTick>
{
private static readonly SchemaNodeCompound _schema = new SchemaNodeCompound("")
{
new SchemaNodeScaler("i", TagType.TAG_INT),
new SchemaNodeScaler("t", TagType.TAG_INT),
new SchemaNodeScaler("x", TagType.TAG_INT),
new SchemaNodeScaler("y", TagType.TAG_INT),
new SchemaNodeScaler("z", TagType.TAG_INT),
};
private int _blockId;
private int _ticks;
private int _x;
private int _y;
private int _z;
private TagNodeCompound _source;
/// <summary>
/// Constructs an empty <see cref="TileTick"/> object.
/// </summary>
public TileTick ()
{
}
/// <summary>
/// Constructs a <see cref="TileTick"/> by copying an existing one.
/// </summary>
/// <param name="tt">The <see cref="TileTick"/> to copy.</param>
public TileTick (TileTick tt)
{
_blockId = tt._blockId;
_ticks = tt._ticks;
_x = tt._x;
_y = tt._y;
_z = tt._z;
if (tt._source != null) {
_source = tt._source.Copy() as TagNodeCompound;
}
}
/// <summary>
/// Gets or sets the ID (type) of the block that this <see cref="TileTick"/> is associated with.
/// </summary>
public int ID
{
get { return _blockId; }
set { _blockId = value; }
}
/// <summary>
/// Gets or sets the number of ticks remaining until the associated block is processed.
/// </summary>
public int Ticks
{
get { return _ticks; }
set { _ticks = value; }
}
/// <summary>
/// Gets or sets the global X-coordinate of the block that this <see cref="TileTick"/> is associated with.
/// </summary>
public int X
{
get { return _x; }
set { _x = value; }
}
/// <summary>
/// Gets or sets the global Y-coordinate of the block that this <see cref="TileTick"/> is associated with.
/// </summary>
public int Y
{
get { return _y; }
set { _y = value; }
}
/// <summary>
/// Gets or sets the global Z-coordinate of the block that this <see cref="TileTick"/> is associated with.
/// </summary>
public int Z
{
get { return _z; }
set { _z = value; }
}
/// <summary>
/// Checks whether the <see cref="TileTick"/> is located (associated with a block) at the specific global coordinates.
/// </summary>
/// <param name="x">The global X-coordinate to test.</param>
/// <param name="y">The global Y-coordinate to test.</param>
/// <param name="z">The global Z-coordinate to test.</param>
/// <returns>Status indicating whether the <see cref="TileTick"/> is located at the specified global coordinates.</returns>
public bool LocatedAt (int x, int y, int z)
{
return _x == x && _y == y && _z == z;
}
/// <summary>
/// Moves the <see cref="TileTick"/> by given block offsets.
/// </summary>
/// <param name="diffX">The X-offset to move by, in blocks.</param>
/// <param name="diffY">The Y-offset to move by, in blocks.</param>
/// <param name="diffZ">The Z-offset to move by, in blocks.</param>
public virtual void MoveBy (int diffX, int diffY, int diffZ)
{
_x += diffX;
_y += diffY;
_z += diffZ;
}
/// <summary>
/// Attempt to construct a new <see cref="TileTick"/> from a Tile Entity subtree without validation.
/// </summary>
/// <param name="tree">The root node of a <see cref="TileTick"/> subtree.</param>
/// <returns>A new <see cref="TileTick"/> on success, or null if the tree was unparsable.</returns>
public static TileTick FromTree (TagNode tree)
{
return new TileTick().LoadTree(tree);
}
/// <summary>
/// Attempt to construct a new <see cref="TileTick"/> from a Tile Entity subtree with validation.
/// </summary>
/// <param name="tree">The root node of a <see cref="TileTick"/> subtree.</param>
/// <returns>A new <see cref="TileTick"/> on success, or null if the tree failed validation.</returns>
public static TileTick FromTreeSafe (TagNode tree)
{
return new TileTick().LoadTreeSafe(tree);
}
#region INbtObject<TileTick> Members
/// <summary>
/// Gets a <see cref="SchemaNode"/> representing the basic schema of a <see cref="TileTick"/>.
/// </summary>
public static SchemaNodeCompound Schema
{
get { return _schema; }
}
/// <summary>
/// Attempt to load a <see cref="TileTick"/> subtree into the <see cref="TileTick"/> without validation.
/// </summary>
/// <param name="tree">The root node of a <see cref="TileTick"/> subtree.</param>
/// <returns>The <see cref="TileTick"/> returns itself on success, or null if the tree was unparsable.</returns>
public TileTick LoadTree (TagNode tree)
{
TagNodeCompound ctree = tree as TagNodeCompound;
if (ctree == null) {
return null;
}
_blockId = ctree["i"].ToTagInt();
_ticks = ctree["t"].ToTagInt();
_x = ctree["x"].ToTagInt();
_y = ctree["y"].ToTagInt();
_z = ctree["z"].ToTagInt();
_source = ctree.Copy() as TagNodeCompound;
return this;
}
/// <summary>
/// Attempt to load a <see cref="TileTick"/> subtree into the <see cref="TileTick"/> with validation.
/// </summary>
/// <param name="tree">The root node of a <see cref="TileTick"/> subtree.</param>
/// <returns>The <see cref="TileTick"/> returns itself on success, or null if the tree failed validation.</returns>
public TileTick LoadTreeSafe (TagNode tree)
{
if (!ValidateTree(tree)) {
return null;
}
return LoadTree(tree);
}
/// <summary>
/// Builds a <see cref="TileTick"/> subtree from the current data.
/// </summary>
/// <returns>The root node of a <see cref="TileTick"/> subtree representing the current data.</returns>
public TagNode BuildTree ()
{
TagNodeCompound tree = new TagNodeCompound();
tree["i"] = new TagNodeInt(_blockId);
tree["t"] = new TagNodeInt(_ticks);
tree["x"] = new TagNodeInt(_x);
tree["y"] = new TagNodeInt(_y);
tree["z"] = new TagNodeInt(_z);
if (_source != null) {
tree.MergeFrom(_source);
}
return tree;
}
/// <summary>
/// Validate a <see cref="TileTick"/> subtree against a basic schema.
/// </summary>
/// <param name="tree">The root node of a <see cref="TileTick"/> subtree.</param>
/// <returns>Status indicating whether the tree was valid against the internal schema.</returns>
public bool ValidateTree (TagNode tree)
{
return new NbtVerifier(tree, _schema).Verify();
}
#endregion
#region ICopyable<TileTick> Members
/// <summary>
/// Creates a deep-copy of the <see cref="TileTick"/> including any data defined in a subtype.
/// </summary>
/// <returns>A deep-copy of the <see cref="TileTick"/>.</returns>
public virtual TileTick Copy ()
{
return new TileTick(this);
}
#endregion
}
}

View file

@ -62,6 +62,7 @@
<Compile Include="Source\AlphaWorld.cs" /> <Compile Include="Source\AlphaWorld.cs" />
<Compile Include="Source\BetaChunkManager.cs" /> <Compile Include="Source\BetaChunkManager.cs" />
<Compile Include="Source\BetaWorld.cs" /> <Compile Include="Source\BetaWorld.cs" />
<Compile Include="Source\Core\BlockTileTicks.cs" />
<Compile Include="Source\Core\BoundedBlockInterface.cs" /> <Compile Include="Source\Core\BoundedBlockInterface.cs" />
<Compile Include="Source\Core\ItemInterface.cs" /> <Compile Include="Source\Core\ItemInterface.cs" />
<Compile Include="Source\Data\BetaDataManager.cs" /> <Compile Include="Source\Data\BetaDataManager.cs" />
@ -212,6 +213,7 @@
<Compile Include="Source\Core\Interface.cs" /> <Compile Include="Source\Core\Interface.cs" />
<Compile Include="Source\Core\LRUCache.cs" /> <Compile Include="Source\Core\LRUCache.cs" />
<Compile Include="Source\Core\NibbleArray.cs" /> <Compile Include="Source\Core\NibbleArray.cs" />
<Compile Include="Source\TileTick.cs" />
<Compile Include="Source\Vector.cs" /> <Compile Include="Source\Vector.cs" />
<Compile Include="Source\World.cs" /> <Compile Include="Source\World.cs" />
<Compile Include="Vendor\DotNetZip\Zlib\Crc32.cs" /> <Compile Include="Vendor\DotNetZip\Zlib\Crc32.cs" />

View file

@ -62,6 +62,7 @@
<Compile Include="Source\AlphaWorld.cs" /> <Compile Include="Source\AlphaWorld.cs" />
<Compile Include="Source\BetaChunkManager.cs" /> <Compile Include="Source\BetaChunkManager.cs" />
<Compile Include="Source\BetaWorld.cs" /> <Compile Include="Source\BetaWorld.cs" />
<Compile Include="Source\Core\BlockTileTicks.cs" />
<Compile Include="Source\Core\BoundedBlockInterface.cs" /> <Compile Include="Source\Core\BoundedBlockInterface.cs" />
<Compile Include="Source\Core\ItemInterface.cs" /> <Compile Include="Source\Core\ItemInterface.cs" />
<Compile Include="Source\Data\BetaDataManager.cs" /> <Compile Include="Source\Data\BetaDataManager.cs" />
@ -212,6 +213,7 @@
<Compile Include="Source\Core\Interface.cs" /> <Compile Include="Source\Core\Interface.cs" />
<Compile Include="Source\Core\LRUCache.cs" /> <Compile Include="Source\Core\LRUCache.cs" />
<Compile Include="Source\Core\NibbleArray.cs" /> <Compile Include="Source\Core\NibbleArray.cs" />
<Compile Include="Source\TileTick.cs" />
<Compile Include="Source\Vector.cs" /> <Compile Include="Source\Vector.cs" />
<Compile Include="Source\World.cs" /> <Compile Include="Source\World.cs" />
<Compile Include="Vendor\DotNetZip\Zlib\Crc32.cs" /> <Compile Include="Vendor\DotNetZip\Zlib\Crc32.cs" />