2011-05-13 03:09:57 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
|
|
|
|
using Substrate.Utility;
|
|
|
|
|
using Substrate.NBT;
|
|
|
|
|
|
|
|
|
|
namespace Substrate
|
|
|
|
|
{
|
|
|
|
|
public struct BlockData {
|
|
|
|
|
public XZYByteArray blocks;
|
|
|
|
|
|
|
|
|
|
public BlockData (XZYByteArray b)
|
|
|
|
|
{
|
|
|
|
|
blocks = b;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct BlockDataData {
|
|
|
|
|
public XZYNibbleArray data;
|
|
|
|
|
|
|
|
|
|
public BlockDataData (XZYNibbleArray d)
|
|
|
|
|
{
|
|
|
|
|
data = d;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct BlockLightData {
|
|
|
|
|
public XZYNibbleArray light;
|
|
|
|
|
public XZYNibbleArray skyLight;
|
|
|
|
|
public ZXByteArray heightMap;
|
|
|
|
|
|
|
|
|
|
public BlockLightData (XZYNibbleArray l, XZYNibbleArray s, ZXByteArray h)
|
|
|
|
|
{
|
|
|
|
|
light = l;
|
|
|
|
|
skyLight = s;
|
|
|
|
|
heightMap = h;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public struct BlockPropertyData {
|
|
|
|
|
public TagList tileEntities;
|
|
|
|
|
|
|
|
|
|
public BlockPropertyData (TagList t)
|
|
|
|
|
{
|
|
|
|
|
tileEntities = t;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class AlphaBlockCollection : IBoundedAlphaBlockCollection
|
|
|
|
|
{
|
|
|
|
|
private XZYByteArray _blocks;
|
|
|
|
|
private XZYNibbleArray _data;
|
|
|
|
|
private XZYNibbleArray _blockLight;
|
|
|
|
|
private XZYNibbleArray _skyLight;
|
|
|
|
|
private ZXByteArray _heightMap;
|
|
|
|
|
|
|
|
|
|
private TagList _tileEntities;
|
|
|
|
|
|
|
|
|
|
private BlockLight _lightManager;
|
|
|
|
|
private BlockTileEntities _tileEntityManager;
|
|
|
|
|
|
|
|
|
|
private bool _dirty = false;
|
|
|
|
|
private bool _autoLight = true;
|
|
|
|
|
|
|
|
|
|
public delegate AlphaBlockCollection NeighborLookupHandler (int relx, int rely, int relz);
|
|
|
|
|
|
|
|
|
|
public event NeighborLookupHandler ResolveNeighbor
|
|
|
|
|
{
|
|
|
|
|
add
|
|
|
|
|
{
|
|
|
|
|
_lightManager.ResolveNeighbor += delegate(int relx, int rely, int relz) {
|
|
|
|
|
return value(relx, rely, relz);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remove
|
|
|
|
|
{
|
|
|
|
|
_lightManager = new BlockLight(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public event BlockCoordinateHandler TranslateCoordinates
|
|
|
|
|
{
|
|
|
|
|
add { _tileEntityManager.TranslateCoordinates += value; }
|
|
|
|
|
remove { _tileEntityManager.TranslateCoordinates -= value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool AutoLight
|
|
|
|
|
{
|
|
|
|
|
get { return _autoLight; }
|
|
|
|
|
set { _autoLight = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool IsDirty
|
|
|
|
|
{
|
|
|
|
|
get { return _dirty; }
|
|
|
|
|
set { _dirty = value; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public AlphaBlockCollection (BlockData root, BlockDataData data, BlockLightData light, BlockPropertyData properties)
|
|
|
|
|
{
|
|
|
|
|
_blocks = root.blocks;
|
|
|
|
|
_data = data.data;
|
|
|
|
|
_blockLight = light.light;
|
|
|
|
|
_skyLight = light.skyLight;
|
|
|
|
|
_heightMap = light.heightMap;
|
|
|
|
|
_tileEntities = properties.tileEntities;
|
|
|
|
|
|
|
|
|
|
_lightManager = new BlockLight(this);
|
|
|
|
|
_tileEntityManager = new BlockTileEntities(_blocks, _tileEntities);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Block GetBlock (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return new Block(this, x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public BlockRef GetBlockRef (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return new BlockRef(this, x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetBlock (int x, int y, int z, Block block)
|
|
|
|
|
{
|
2011-05-13 03:21:53 +00:00
|
|
|
|
SetID(x, y, z, block.ID);
|
|
|
|
|
SetData(x, y, z, block.Data);
|
2011-05-13 03:09:57 +00:00
|
|
|
|
|
|
|
|
|
SetTileEntity(x, y, z, block.GetTileEntity().Copy());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#region IBlockCollection Members
|
|
|
|
|
|
|
|
|
|
public int XDim
|
|
|
|
|
{
|
|
|
|
|
get { return _blocks.XDim; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int YDim
|
|
|
|
|
{
|
|
|
|
|
get { return _blocks.YDim; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int ZDim
|
|
|
|
|
{
|
|
|
|
|
get { return _blocks.ZDim; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IBlock IBlockCollection.GetBlock (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return GetBlock(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IBlock IBlockCollection.GetBlockRef (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return GetBlockRef(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetBlock (int x, int y, int z, IBlock block)
|
|
|
|
|
{
|
2011-05-13 03:21:53 +00:00
|
|
|
|
SetID(x, y, z, block.ID);
|
2011-05-13 03:09:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public BlockInfo GetInfo (int x, int y, int z)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
return BlockInfo.BlockTable[_blocks[x, y, z]];
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public int GetID (int x, int y, int z)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
return _blocks[x, y, z];
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public void SetID (int x, int y, int z, int id)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
int oldid = _blocks[x, y, z];
|
|
|
|
|
if (oldid == id) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update value
|
|
|
|
|
|
|
|
|
|
_blocks[x, y, z] = (byte)id;
|
|
|
|
|
|
|
|
|
|
// Update tile entities
|
|
|
|
|
|
2011-05-13 03:44:05 +00:00
|
|
|
|
BlockInfo info1 = BlockInfo.BlockTable[oldid];
|
|
|
|
|
BlockInfo info2 = BlockInfo.BlockTable[id];
|
2011-05-13 03:09:57 +00:00
|
|
|
|
|
2011-05-13 03:44:05 +00:00
|
|
|
|
BlockInfoEx einfo1 = info1 as BlockInfoEx;
|
|
|
|
|
BlockInfoEx einfo2 = info2 as BlockInfoEx;
|
|
|
|
|
|
|
|
|
|
if (einfo1 != einfo2) {
|
|
|
|
|
if (einfo1 != null) {
|
2011-05-13 03:09:57 +00:00
|
|
|
|
ClearTileEntity(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:44:05 +00:00
|
|
|
|
if (einfo2 != null) {
|
2011-05-13 03:09:57 +00:00
|
|
|
|
CreateTileEntity(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Light consistency
|
|
|
|
|
|
|
|
|
|
if (_autoLight) {
|
2011-06-04 16:16:01 +00:00
|
|
|
|
if (info1.ObscuresLight != info2.ObscuresLight) {
|
|
|
|
|
_lightManager.UpdateHeightMap(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (info1.Luminance != info2.Luminance || info1.Opacity != info2.Opacity || info1.TransmitsLight != info2.TransmitsLight) {
|
2011-05-13 03:09:57 +00:00
|
|
|
|
UpdateBlockLight(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
2011-06-04 16:16:01 +00:00
|
|
|
|
if (info1.Opacity != info2.Opacity || info1.TransmitsLight != info2.TransmitsLight) {
|
2011-05-13 03:21:53 +00:00
|
|
|
|
UpdateSkyLight(x, y, z);
|
2011-05-13 03:09:57 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public int CountByID (int id)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
int c = 0;
|
|
|
|
|
for (int i = 0; i < _blocks.Length; i++) {
|
|
|
|
|
if (_blocks[i] == id) {
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region IDataBlockContainer Members
|
|
|
|
|
|
|
|
|
|
IDataBlock IDataBlockCollection.GetBlock (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return GetBlock(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IDataBlock IDataBlockCollection.GetBlockRef (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return GetBlockRef(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetBlock (int x, int y, int z, IDataBlock block)
|
|
|
|
|
{
|
2011-05-13 03:21:53 +00:00
|
|
|
|
SetID(x, y, z, block.ID);
|
|
|
|
|
SetData(x, y, z, block.Data);
|
2011-05-13 03:09:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public int GetData (int x, int y, int z)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
return _data[x, y, z];
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public void SetData (int x, int y, int z, int data)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
if (_data[x, y, z] != data) {
|
|
|
|
|
_data[x, y, z] = (byte)data;
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*if (BlockManager.EnforceDataLimits && BlockInfo.BlockTable[_blocks[index]] != null) {
|
|
|
|
|
if (!BlockInfo.BlockTable[_blocks[index]].TestData(data)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public int CountByData (int id, int data)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
int c = 0;
|
|
|
|
|
for (int i = 0; i < _blocks.Length; i++) {
|
|
|
|
|
if (_blocks[i] == id && _data[i] == data) {
|
|
|
|
|
c++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return c;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region ILitBlockCollection Members
|
|
|
|
|
|
|
|
|
|
ILitBlock ILitBlockCollection.GetBlock (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ILitBlock ILitBlockCollection.GetBlockRef (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return GetBlockRef(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetBlock (int x, int y, int z, ILitBlock block)
|
|
|
|
|
{
|
2011-05-13 03:21:53 +00:00
|
|
|
|
SetID(x, y, z, block.ID);
|
2011-05-13 03:09:57 +00:00
|
|
|
|
SetBlockLight(x, y, z, block.BlockLight);
|
2011-05-13 03:21:53 +00:00
|
|
|
|
SetSkyLight(x, y, z, block.SkyLight);
|
2011-05-13 03:09:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int GetBlockLight (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return _blockLight[x, y, z];
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public int GetSkyLight (int x, int y, int z)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
return _skyLight[x, y, z];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetBlockLight (int x, int y, int z, int light)
|
|
|
|
|
{
|
|
|
|
|
if (_blockLight[x, y, z] != light) {
|
|
|
|
|
_blockLight[x, y, z] = (byte)light;
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public void SetSkyLight (int x, int y, int z, int light)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
if (_skyLight[x, y, z] != light) {
|
|
|
|
|
_skyLight[x, y, z] = (byte)light;
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int GetHeight (int x, int z)
|
|
|
|
|
{
|
|
|
|
|
return _heightMap[x, z];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetHeight (int x, int z, int height)
|
|
|
|
|
{
|
|
|
|
|
_heightMap[x, z] = (byte)height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateBlockLight (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
_lightManager.UpdateBlockLight(x, y, z);
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public void UpdateSkyLight (int x, int y, int z)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
_lightManager.UpdateBlockSkyLight(x, y, z);
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ResetBlockLight ()
|
|
|
|
|
{
|
|
|
|
|
_blockLight.Clear();
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public void ResetSkyLight ()
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
_skyLight.Clear();
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RebuildBlockLight ()
|
|
|
|
|
{
|
|
|
|
|
_lightManager.RebuildBlockLight();
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public void RebuildSkyLight ()
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
_lightManager.RebuildBlockSkyLight();
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RebuildHeightMap ()
|
|
|
|
|
{
|
|
|
|
|
_lightManager.RebuildHeightMap();
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void StitchBlockLight ()
|
|
|
|
|
{
|
|
|
|
|
_lightManager.StitchBlockLight();
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public void StitchSkyLight ()
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
_lightManager.StitchBlockSkyLight();
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void StitchBlockLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge)
|
|
|
|
|
{
|
|
|
|
|
_lightManager.StitchBlockLight(blockset, edge);
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-13 03:21:53 +00:00
|
|
|
|
public void StitchSkyLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge)
|
2011-05-13 03:09:57 +00:00
|
|
|
|
{
|
|
|
|
|
_lightManager.StitchBlockSkyLight(blockset, edge);
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#region IPropertyBlockCollection Members
|
|
|
|
|
|
|
|
|
|
IPropertyBlock IPropertyBlockCollection.GetBlock (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return GetBlock(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
IPropertyBlock IPropertyBlockCollection.GetBlockRef (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return GetBlockRef(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetBlock (int x, int y, int z, IPropertyBlock block)
|
|
|
|
|
{
|
2011-05-13 03:21:53 +00:00
|
|
|
|
SetID(x, y, z, block.ID);
|
2011-05-13 03:09:57 +00:00
|
|
|
|
SetTileEntity(x, y, z, block.GetTileEntity().Copy());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public TileEntity GetTileEntity (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
return _tileEntityManager.GetTileEntity(x, y, z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SetTileEntity (int x, int y, int z, TileEntity te)
|
|
|
|
|
{
|
|
|
|
|
_tileEntityManager.SetTileEntity(x, y, z, te);
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CreateTileEntity (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
_tileEntityManager.CreateTileEntity(x, y, z);
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void ClearTileEntity (int x, int y, int z)
|
|
|
|
|
{
|
|
|
|
|
_tileEntityManager.ClearTileEntity(x, y, z);
|
|
|
|
|
_dirty = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|