Documenting and refactoring blocks, chunks. Updated some inconsistencies in entities and tile entities.

This commit is contained in:
Justin Aquadro 2011-07-07 04:27:48 +00:00
parent e952a14b4f
commit 325472a00a
17 changed files with 752 additions and 215 deletions

View file

@ -1,5 +1,6 @@
using System;
using Substrate;
using Substrate.Core;
// This example will reset and rebuild the lighting (heightmap, block light,
// skylight) for all chunks in a map.
@ -24,13 +25,15 @@ namespace Relight
string dest = args[0];
// Load the world, supporting either alpha or beta format
INBTWorld world;
/*INBTWorld world;
if (args.Length >= 2 && args[1] == "alpha") {
world = AlphaWorld.Open(dest);
}
else {
world = BetaWorld.Open(dest);
}
}*/
NbtWorld world = NbtWorld.Open(dest);
// Grab a generic chunk manager reference
IChunkManager cm = world.GetChunkManager();

View file

@ -4,11 +4,15 @@ using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using Substrate.Core;
using Substrate.Nbt;
namespace Substrate.Core
namespace Substrate
{
public class ChunkFileManager : IChunkManager
/// <summary>
/// Represents an Alpha-compatible interface for globally managing chunks.
/// </summary>
public class AlphaChunkManager : IChunkManager
{
private string _mapPath;
@ -16,24 +20,31 @@ namespace Substrate.Core
private LRUCache<ChunkKey, ChunkRef> _cache;
private Dictionary<ChunkKey, ChunkRef> _dirty;
/// <summary>
/// Gets the path to the base directory containing the chunk directory structure.
/// </summary>
public string ChunkPath
{
get { return _mapPath; }
}
public ChunkFileManager (string mapDir)
/// <summary>
/// Creates a new <see cref="AlphaChunkManager"/> instance for the give chunk base directory.
/// </summary>
/// <param name="mapDir">The path to the chunk base directory.</param>
public AlphaChunkManager (string mapDir)
{
_mapPath = mapDir;
_cache = new LRUCache<ChunkKey, ChunkRef>(256);
_dirty = new Dictionary<ChunkKey, ChunkRef>();
}
protected ChunkFile GetChunkFile (int cx, int cz)
private ChunkFile GetChunkFile (int cx, int cz)
{
return new ChunkFile(_mapPath, cx, cz);
}
protected NbtTree GetChunkTree (int cx, int cz)
private NbtTree GetChunkTree (int cx, int cz)
{
ChunkFile cf = GetChunkFile(cx, cz);
Stream nbtstr = cf.GetDataInputStream();
@ -44,7 +55,7 @@ namespace Substrate.Core
return new NbtTree(nbtstr);
}
protected bool SaveChunkTree (int cx, int cz, NbtTree tree)
private bool SaveChunkTree (int cx, int cz, NbtTree tree)
{
ChunkFile cf = GetChunkFile(cx, cz);
Stream zipstr = cf.GetDataOutputStream();
@ -58,33 +69,38 @@ namespace Substrate.Core
return true;
}
protected Stream GetChunkOutStream (int cx, int cz)
private Stream GetChunkOutStream (int cx, int cz)
{
return new ChunkFile(_mapPath, cx, cz).GetDataOutputStream();
}
#region IChunkContainer Members
/// <inheritdoc/>
public int ChunkGlobalX (int cx)
{
return cx;
}
/// <inheritdoc/>
public int ChunkGlobalZ (int cz)
{
return cz;
}
/// <inheritdoc/>
public int ChunkLocalX (int cx)
{
return cx;
}
/// <inheritdoc/>
public int ChunkLocalZ (int cz)
{
return cz;
}
/// <inheritdoc/>
public Chunk GetChunk (int cx, int cz)
{
if (!ChunkExists(cx, cz)) {
@ -94,6 +110,7 @@ namespace Substrate.Core
return Chunk.CreateVerified(GetChunkTree(cx, cz));
}
/// <inheritdoc/>
public ChunkRef GetChunkRef (int cx, int cz)
{
ChunkKey k = new ChunkKey(cx, cz);
@ -113,6 +130,7 @@ namespace Substrate.Core
return c;
}
/// <inheritdoc/>
public ChunkRef CreateChunk (int cx, int cz)
{
DeleteChunk(cx, cz);
@ -126,11 +144,13 @@ namespace Substrate.Core
return cr;
}
/// <inheritdoc/>
public bool ChunkExists (int cx, int cz)
{
return new ChunkFile(_mapPath, cx, cz).Exists();
}
/// <inheritdoc/>
public bool DeleteChunk (int cx, int cz)
{
new ChunkFile(_mapPath, cx, cz).Delete();
@ -142,6 +162,7 @@ namespace Substrate.Core
return true;
}
/// <inheritdoc/>
public ChunkRef SetChunk (int cx, int cz, Chunk chunk)
{
DeleteChunk(cx, cz);
@ -155,6 +176,7 @@ namespace Substrate.Core
return cr;
}
/// <inheritdoc/>
public int Save ()
{
foreach (KeyValuePair<ChunkKey, ChunkRef> e in _cache) {
@ -177,6 +199,7 @@ namespace Substrate.Core
return saved;
}
/// <inheritdoc/>
public bool SaveChunk (Chunk chunk)
{
if (chunk.Save(GetChunkOutStream(ChunkGlobalX(chunk.X), ChunkGlobalZ(chunk.Z)))) {
@ -187,41 +210,20 @@ namespace Substrate.Core
return false;
}
/// <inheritdoc/>
public bool CanDelegateCoordinates
{
get { return true; }
}
#endregion
/*#region IChunkCache Members
public bool MarkChunkDirty (ChunkRef chunk)
{
int cx = chunk.X;
int cz = chunk.Z;
ChunkKey k = new ChunkKey(cx, cz);
if (!_dirty.ContainsKey(k)) {
_dirty.Add(k, GetChunkRef(cx, cz));
return true;
}
return false;
}
public bool MarkChunkClean (ChunkRef chunk)
{
int cx = chunk.X;
int cz = chunk.Z;
ChunkKey k = new ChunkKey(cx, cz);
if (_dirty.ContainsKey(k)) {
_dirty.Remove(k);
return true;
}
return false;
}
#endregion*/
#region IEnumerable<ChunkRef> Members
/// <summary>
/// Gets an enumerator that iterates through all the chunks in the world.
/// </summary>
/// <returns>An enumerator for this manager.</returns>
public IEnumerator<ChunkRef> GetEnumerator ()
{
return new Enumerator(this);
@ -241,7 +243,7 @@ namespace Substrate.Core
private class Enumerator : IEnumerator<ChunkRef>
{
protected ChunkFileManager _cm;
protected AlphaChunkManager _cm;
protected Queue<string> _tld;
protected Queue<string> _sld;
protected Queue<ChunkRef> _chunks;
@ -250,7 +252,7 @@ namespace Substrate.Core
private string _cursld;
private ChunkRef _curchunk;
public Enumerator (ChunkFileManager cfm)
public Enumerator (AlphaChunkManager cfm)
{
_cm = cfm;

View file

@ -19,14 +19,14 @@ namespace Substrate
private Level _level;
private Dictionary<int, ChunkFileManager> _chunkMgrs;
private Dictionary<int, AlphaChunkManager> _chunkMgrs;
private Dictionary<int, BlockManager> _blockMgrs;
private PlayerManager _playerMan;
private AlphaWorld ()
{
_chunkMgrs = new Dictionary<int, ChunkFileManager>();
_chunkMgrs = new Dictionary<int, AlphaChunkManager>();
_blockMgrs = new Dictionary<int, BlockManager>();
}
@ -44,7 +44,7 @@ namespace Substrate
/// <returns>A <see cref="BlockManager"/> tied to the default dimension in this world.</returns>
/// <remarks>Get a <see cref="BlockManager"/> if you need to manage blocks as a global, unbounded matrix. This abstracts away
/// any higher-level organizational divisions. If your task is going to be heavily performance-bound, consider getting a
/// <see cref="ChunkManager"/> instead and working with blocks on a chunk-local level.</remarks>
/// <see cref="BetaChunkManager"/> instead and working with blocks on a chunk-local level.</remarks>
public new BlockManager GetBlockManager ()
{
return GetBlockManagerVirt(Dimension.DEFAULT) as BlockManager;
@ -57,31 +57,31 @@ namespace Substrate
/// <returns>A <see cref="BlockManager"/> tied to the given dimension in this world.</returns>
/// <remarks>Get a <see cref="BlockManager"/> if you need to manage blocks as a global, unbounded matrix. This abstracts away
/// any higher-level organizational divisions. If your task is going to be heavily performance-bound, consider getting a
/// <see cref="ChunkManager"/> instead and working with blocks on a chunk-local level.</remarks>
/// <see cref="BetaChunkManager"/> instead and working with blocks on a chunk-local level.</remarks>
public new BlockManager GetBlockManager (int dim)
{
return GetBlockManagerVirt(dim) as BlockManager;
}
/// <summary>
/// Gets a <see cref="ChunkManager"/> for the default dimension.
/// Gets a <see cref="BetaChunkManager"/> for the default dimension.
/// </summary>
/// <returns>A <see cref="ChunkManager"/> tied to the default dimension in this world.</returns>
/// <remarks>Get a <see cref="ChunkManager"/> if you you need to work with easily-digestible, bounded chunks of blocks.</remarks>
public new ChunkFileManager GetChunkManager ()
/// <returns>A <see cref="BetaChunkManager"/> tied to the default dimension in this world.</returns>
/// <remarks>Get a <see cref="BetaChunkManager"/> if you you need to work with easily-digestible, bounded chunks of blocks.</remarks>
public new AlphaChunkManager GetChunkManager ()
{
return GetChunkManagerVirt(Dimension.DEFAULT) as ChunkFileManager;
return GetChunkManagerVirt(Dimension.DEFAULT) as AlphaChunkManager;
}
/// <summary>
/// Gets a <see cref="ChunkManager"/> for the given dimension.
/// Gets a <see cref="BetaChunkManager"/> for the given dimension.
/// </summary>
/// <param name="dim">The id of the dimension to look up.</param>
/// <returns>A <see cref="ChunkManager"/> tied to the given dimension in this world.</returns>
/// <remarks>Get a <see cref="ChunkManager"/> if you you need to work with easily-digestible, bounded chunks of blocks.</remarks>
public new ChunkFileManager GetChunkManager (int dim)
/// <returns>A <see cref="BetaChunkManager"/> tied to the given dimension in this world.</returns>
/// <remarks>Get a <see cref="BetaChunkManager"/> if you you need to work with easily-digestible, bounded chunks of blocks.</remarks>
public new AlphaChunkManager GetChunkManager (int dim)
{
return GetChunkManagerVirt(dim) as ChunkFileManager;
return GetChunkManagerVirt(dim) as AlphaChunkManager;
}
/// <summary>
@ -101,7 +101,7 @@ namespace Substrate
{
_level.Save();
foreach (KeyValuePair<int, ChunkFileManager> cm in _chunkMgrs) {
foreach (KeyValuePair<int, AlphaChunkManager> cm in _chunkMgrs) {
cm.Value.Save();
}
}
@ -111,7 +111,7 @@ namespace Substrate
/// </summary>
/// <param name="path">The path to the directory containing the world's level.dat, or the path to level.dat itself.</param>
/// <returns>A new <see cref="AlphaWorld"/> object representing an existing world on disk.</returns>
public static AlphaWorld Open (string path)
public static new AlphaWorld Open (string path)
{
return new AlphaWorld().OpenWorld(path) as AlphaWorld;
}
@ -143,7 +143,7 @@ namespace Substrate
/// <exclude/>
protected override IChunkManager GetChunkManagerVirt (int dim)
{
ChunkFileManager rm;
AlphaChunkManager rm;
if (_chunkMgrs.TryGetValue(dim, out rm)) {
return rm;
}
@ -176,7 +176,7 @@ namespace Substrate
Directory.CreateDirectory(path);
}
ChunkFileManager cm = new ChunkFileManager(path);
AlphaChunkManager cm = new AlphaChunkManager(path);
BlockManager bm = new BlockManager(cm);
_chunkMgrs[dim] = cm;

View file

@ -5,60 +5,80 @@ using Substrate.Core;
namespace Substrate
{
public class ChunkManager : IChunkManager, IEnumerable<ChunkRef>
/// <summary>
/// Represents a Beta-compatible interface for globally managing chunks.
/// </summary>
public class BetaChunkManager : IChunkManager, IEnumerable<ChunkRef>
{
public const int REGION_XLEN = 32;
public const int REGION_ZLEN = 32;
private const int REGION_XLEN = 32;
private const int REGION_ZLEN = 32;
public const int REGION_XLOG = 5;
public const int REGION_ZLOG = 5;
private const int REGION_XLOG = 5;
private const int REGION_ZLOG = 5;
public const int REGION_XMASK = 0x1F;
public const int REGION_ZMASK = 0x1F;
private const int REGION_XMASK = 0x1F;
private const int REGION_ZMASK = 0x1F;
protected RegionManager _regionMan;
private RegionManager _regionMan;
//protected Dictionary<RegionKey, Region> _cache;
//protected Dictionary<RegionKey, Region> _dirty;
private ChunkCache _cache;
protected ChunkCache _cache;
public ChunkManager (RegionManager rm, ChunkCache cache)
/// <summary>
/// Creates a new <see cref="BetaChunkManager"/> instance given a backing <see cref="RegionManager"/> and <see cref="ChunkCache"/>.
/// </summary>
/// <param name="rm">A <see cref="RegionManager"/> exposing access to regions.</param>
/// <param name="cache">A shared cache for storing chunks read in.</param>
public BetaChunkManager (RegionManager rm, ChunkCache cache)
{
_regionMan = rm;
_cache = cache;
//_cache = new Dictionary<RegionKey, Region>();
//_dirty = new Dictionary<RegionKey, Region>();
}
public ChunkManager (ChunkManager cm)
/// <summary>
/// Creates a new <see cref="BetaChunkManager"/> instance from another.
/// </summary>
/// <param name="cm">A <see cref="BetaChunkManager"/> to get a <see cref="RegionManager"/> and <see cref="ChunkCache"/> from.</param>
public BetaChunkManager (BetaChunkManager cm)
{
_regionMan = cm._regionMan;
_cache = cm._cache;
//_cache = new Dictionary<RegionKey, Region>();
//_dirty = new Dictionary<RegionKey, Region>();
}
/// <summary>
/// Gets the <see cref="RegionManager"/> backing this manager.
/// </summary>
public RegionManager RegionManager
{
get { return _regionMan; }
}
#region IChunkContainer
/// <inheritdoc/>
public int ChunkGlobalX (int cx)
{
return cx;
}
/// <inheritdoc/>
public int ChunkGlobalZ (int cz)
{
return cz;
}
/// <inheritdoc/>
public int ChunkLocalX (int cx)
{
return cx & REGION_XMASK;
}
/// <inheritdoc/>
public int ChunkLocalZ (int cz)
{
return cz & REGION_ZMASK;
}
/// <inheritdoc/>
public Chunk GetChunk (int cx, int cz)
{
Region r = GetRegion(cx, cz);
@ -69,6 +89,7 @@ namespace Substrate
return r.GetChunk(cx & REGION_XMASK, cz & REGION_ZMASK);
}
/// <inheritdoc/>
public ChunkRef GetChunkRef (int cx, int cz)
{
Region r = GetRegion(cx, cz);
@ -79,6 +100,7 @@ namespace Substrate
return r.GetChunkRef(cx & REGION_XMASK, cz & REGION_ZMASK);
}
/// <inheritdoc/>
public bool ChunkExists (int cx, int cz)
{
Region r = GetRegion(cx, cz);
@ -89,6 +111,7 @@ namespace Substrate
return r.ChunkExists(cx & REGION_XMASK, cz & REGION_ZMASK);
}
/// <inheritdoc/>
public ChunkRef CreateChunk (int cx, int cz)
{
Region r = GetRegion(cx, cz);
@ -101,28 +124,7 @@ namespace Substrate
return r.CreateChunk(cx & REGION_XMASK, cz & REGION_ZMASK);
}
public ChunkRef CopyChunk (int src_cx, int src_cz, int dst_cx, int dst_cz)
{
Region src_r = GetRegion(src_cx, src_cz);
if (src_r == null) {
return null;
}
Region dst_r = GetRegion(dst_cx, dst_cz);
if (dst_r == null) {
int rx = dst_cx >> REGION_XLOG;
int rz = dst_cz >> REGION_ZLOG;
dst_r = _regionMan.CreateRegion(rx, rz);
}
Chunk c = src_r.GetChunk(src_cx & REGION_XMASK, src_cz & REGION_ZMASK).Copy();
c.SetLocation(dst_cx, dst_cz);
dst_r.SaveChunk(c);
return dst_r.GetChunkRef(dst_cx & REGION_XMASK, dst_cz & REGION_ZMASK);
}
/// <inheritdoc/>
public ChunkRef SetChunk (int cx, int cz, Chunk chunk)
{
Region r = GetRegion(cx, cz);
@ -138,6 +140,7 @@ namespace Substrate
return r.GetChunkRef(cx & REGION_XMASK, cz & REGION_ZMASK);
}
/// <inheritdoc/>
public int Save ()
{
_cache.SyncDirty();
@ -160,6 +163,7 @@ namespace Substrate
return saved;
}
/// <inheritdoc/>
public bool SaveChunk (Chunk chunk)
{
Region r = GetRegion(chunk.X, chunk.Z);
@ -170,6 +174,7 @@ namespace Substrate
return r.SaveChunk(chunk);
}
/// <inheritdoc/>
public bool DeleteChunk (int cx, int cz)
{
Region r = GetRegion(cx, cz);
@ -188,6 +193,47 @@ namespace Substrate
return true;
}
/// <inheritdoc/>
public bool CanDelegateCoordinates
{
get { return true; }
}
#endregion
/// <summary>
/// Copies a chunk from one location to another.
/// </summary>
/// <param name="src_cx">The global X-coordinate of the source chunk.</param>
/// <param name="src_cz">The global Z-coordinate of the source chunk.</param>
/// <param name="dst_cx">The global X-coordinate of the destination chunk.</param>
/// <param name="dst_cz">The global Z-coordinate of the destination chunk.</param>
/// <returns>A <see cref="ChunkRef"/> for the destination chunk.</returns>
public ChunkRef CopyChunk (int src_cx, int src_cz, int dst_cx, int dst_cz)
{
Region src_r = GetRegion(src_cx, src_cz);
if (src_r == null) {
return null;
}
Region dst_r = GetRegion(dst_cx, dst_cz);
if (dst_r == null) {
int rx = dst_cx >> REGION_XLOG;
int rz = dst_cz >> REGION_ZLOG;
dst_r = _regionMan.CreateRegion(rx, rz);
}
Chunk c = src_r.GetChunk(src_cx & REGION_XMASK, src_cz & REGION_ZMASK).Copy();
c.SetLocation(dst_cx, dst_cz);
dst_r.SaveChunk(c);
return dst_r.GetChunkRef(dst_cx & REGION_XMASK, dst_cz & REGION_ZMASK);
}
/// <summary>
/// Performs a full chunk relight sequence on all modified chunks.
/// </summary>
public void RelightDirtyChunks ()
{
//List<ChunkRef> dirty = new List<ChunkRef>();
@ -238,19 +284,14 @@ namespace Substrate
}
}
public RegionManager GetRegionManager ()
{
return _regionMan;
}
public ChunkRef GetChunkRefInRegion (Region r, int lcx, int lcz)
private ChunkRef GetChunkRefInRegion (Region r, int lcx, int lcz)
{
int cx = r.X * REGION_XLEN + lcx;
int cz = r.Z * REGION_ZLEN + lcz;
return GetChunkRef(cx, cz);
}
protected Region GetRegion (int cx, int cz)
private Region GetRegion (int cx, int cz)
{
cx >>= REGION_XLOG;
cz >>= REGION_ZLOG;
@ -260,6 +301,10 @@ namespace Substrate
#region IEnumerable<ChunkRef> Members
/// <summary>
/// Returns an enumerator that iterates through all chunks in all regions of the world.
/// </summary>
/// <returns>An enumerator for this manager.</returns>
public IEnumerator<ChunkRef> GetEnumerator ()
{
return new Enumerator(this);
@ -270,6 +315,7 @@ namespace Substrate
#region IEnumerable Members
/// <inheritdoc/>
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator ()
{
return new Enumerator(this);
@ -280,7 +326,7 @@ namespace Substrate
private class Enumerator : IEnumerator<ChunkRef>
{
private ChunkManager _cm;
private BetaChunkManager _cm;
private IEnumerator<Region> _enum;
private Region _region;
@ -289,10 +335,10 @@ namespace Substrate
private int _x = 0;
private int _z = -1;
public Enumerator (ChunkManager cm)
public Enumerator (BetaChunkManager cm)
{
_cm = cm;
_enum = _cm.GetRegionManager().GetEnumerator();
_enum = _cm.RegionManager.GetEnumerator();
_enum.MoveNext();
_region = _enum.Current;
}
@ -304,7 +350,7 @@ namespace Substrate
}
else {
while (true) {
if (_x >= ChunkManager.REGION_XLEN) {
if (_x >= BetaChunkManager.REGION_XLEN) {
if (!_enum.MoveNext()) {
return false;
}
@ -322,8 +368,8 @@ namespace Substrate
protected bool MoveNextInRegion ()
{
for (; _x < ChunkManager.REGION_XLEN; _x++) {
for (_z++; _z < ChunkManager.REGION_ZLEN; _z++) {
for (; _x < BetaChunkManager.REGION_XLEN; _x++) {
for (_z++; _z < BetaChunkManager.REGION_ZLEN; _z++) {
if (_region.ChunkExists(_x, _z)) {
goto FoundNext;
}
@ -333,7 +379,7 @@ namespace Substrate
FoundNext:
return (_x < ChunkManager.REGION_XLEN);
return (_x < BetaChunkManager.REGION_XLEN);
}
public void Reset ()
@ -369,7 +415,7 @@ namespace Substrate
{
get
{
if (_x >= ChunkManager.REGION_XLEN) {
if (_x >= BetaChunkManager.REGION_XLEN) {
throw new InvalidOperationException();
}
return _chunk;

View file

@ -22,7 +22,7 @@ namespace Substrate
private Level _level;
private Dictionary<int, RegionManager> _regionMgrs;
private Dictionary<int, ChunkManager> _chunkMgrs;
private Dictionary<int, BetaChunkManager> _chunkMgrs;
private Dictionary<int, BlockManager> _blockMgrs;
private PlayerManager _playerMan;
@ -30,7 +30,7 @@ namespace Substrate
private BetaWorld ()
{
_regionMgrs = new Dictionary<int, RegionManager>();
_chunkMgrs = new Dictionary<int, ChunkManager>();
_chunkMgrs = new Dictionary<int, BetaChunkManager>();
_blockMgrs = new Dictionary<int, BlockManager>();
}
@ -48,7 +48,7 @@ namespace Substrate
/// <returns>A <see cref="BlockManager"/> tied to the default dimension in this world.</returns>
/// <remarks>Get a <see cref="BlockManager"/> if you need to manage blocks as a global, unbounded matrix. This abstracts away
/// any higher-level organizational divisions. If your task is going to be heavily performance-bound, consider getting a
/// <see cref="ChunkManager"/> instead and working with blocks on a chunk-local level.</remarks>
/// <see cref="BetaChunkManager"/> instead and working with blocks on a chunk-local level.</remarks>
public new BlockManager GetBlockManager ()
{
return GetBlockManagerVirt(Dimension.DEFAULT) as BlockManager;
@ -61,31 +61,31 @@ namespace Substrate
/// <returns>A <see cref="BlockManager"/> tied to the given dimension in this world.</returns>
/// <remarks>Get a <see cref="BlockManager"/> if you need to manage blocks as a global, unbounded matrix. This abstracts away
/// any higher-level organizational divisions. If your task is going to be heavily performance-bound, consider getting a
/// <see cref="ChunkManager"/> instead and working with blocks on a chunk-local level.</remarks>
/// <see cref="BetaChunkManager"/> instead and working with blocks on a chunk-local level.</remarks>
public new BlockManager GetBlockManager (int dim)
{
return GetBlockManagerVirt(dim) as BlockManager;
}
/// <summary>
/// Gets a <see cref="ChunkManager"/> for the default dimension.
/// Gets a <see cref="BetaChunkManager"/> for the default dimension.
/// </summary>
/// <returns>A <see cref="ChunkManager"/> tied to the default dimension in this world.</returns>
/// <remarks>Get a <see cref="ChunkManager"/> if you you need to work with easily-digestible, bounded chunks of blocks.</remarks>
public new ChunkManager GetChunkManager ()
/// <returns>A <see cref="BetaChunkManager"/> tied to the default dimension in this world.</returns>
/// <remarks>Get a <see cref="BetaChunkManager"/> if you you need to work with easily-digestible, bounded chunks of blocks.</remarks>
public new BetaChunkManager GetChunkManager ()
{
return GetChunkManagerVirt(Dimension.DEFAULT) as ChunkManager;
return GetChunkManagerVirt(Dimension.DEFAULT) as BetaChunkManager;
}
/// <summary>
/// Gets a <see cref="ChunkManager"/> for the given dimension.
/// Gets a <see cref="BetaChunkManager"/> for the given dimension.
/// </summary>
/// <param name="dim">The id of the dimension to look up.</param>
/// <returns>A <see cref="ChunkManager"/> tied to the given dimension in this world.</returns>
/// <remarks>Get a <see cref="ChunkManager"/> if you you need to work with easily-digestible, bounded chunks of blocks.</remarks>
public new ChunkManager GetChunkManager (int dim)
/// <returns>A <see cref="BetaChunkManager"/> tied to the given dimension in this world.</returns>
/// <remarks>Get a <see cref="BetaChunkManager"/> if you you need to work with easily-digestible, bounded chunks of blocks.</remarks>
public new BetaChunkManager GetChunkManager (int dim)
{
return GetChunkManagerVirt(dim) as ChunkManager;
return GetChunkManagerVirt(dim) as BetaChunkManager;
}
/// <summary>
@ -93,7 +93,7 @@ namespace Substrate
/// </summary>
/// <returns>A <see cref="RegionManager"/> tied to the defaul dimension in this world.</returns>
/// <remarks>Regions are a higher-level unit of organization for blocks unique to worlds created in Beta 1.3 and beyond.
/// Consider using the <see cref="ChunkManager"/> if you are interested in working with blocks.</remarks>
/// Consider using the <see cref="BetaChunkManager"/> if you are interested in working with blocks.</remarks>
public RegionManager GetRegionManager ()
{
return GetRegionManager(Dimension.DEFAULT);
@ -105,7 +105,7 @@ namespace Substrate
/// <param name="dim">The id of the dimension to look up.</param>
/// <returns>A <see cref="RegionManager"/> tied to the given dimension in this world.</returns>
/// <remarks>Regions are a higher-level unit of organization for blocks unique to worlds created in Beta 1.3 and beyond.
/// Consider using the <see cref="ChunkManager"/> if you are interested in working with blocks.</remarks>
/// Consider using the <see cref="BetaChunkManager"/> if you are interested in working with blocks.</remarks>
public RegionManager GetRegionManager (int dim)
{
RegionManager rm;
@ -134,7 +134,7 @@ namespace Substrate
{
_level.Save();
foreach (KeyValuePair<int, ChunkManager> cm in _chunkMgrs) {
foreach (KeyValuePair<int, BetaChunkManager> cm in _chunkMgrs) {
cm.Value.Save();
}
}
@ -144,7 +144,7 @@ namespace Substrate
/// </summary>
/// <param name="path">The path to the directory containing the world's level.dat, or the path to level.dat itself.</param>
/// <returns>A new <see cref="BetaWorld"/> object representing an existing world on disk.</returns>
public static BetaWorld Open (string path)
public static new BetaWorld Open (string path)
{
return new BetaWorld().OpenWorld(path) as BetaWorld;
}
@ -176,7 +176,7 @@ namespace Substrate
/// <exclude/>
protected override IChunkManager GetChunkManagerVirt (int dim)
{
ChunkManager rm;
BetaChunkManager rm;
if (_chunkMgrs.TryGetValue(dim, out rm)) {
return rm;
}
@ -216,7 +216,7 @@ namespace Substrate
ChunkCache cc = new ChunkCache();
RegionManager rm = new RegionManager(path, cc);
ChunkManager cm = new ChunkManager(rm, cc);
BetaChunkManager cm = new BetaChunkManager(rm, cc);
BlockManager bm = new BlockManager(cm);
_regionMgrs[dim] = rm;

View file

@ -44,6 +44,7 @@ namespace Substrate
public const int PISTON = 33;
public const int PISTON_HEAD = 34;
public const int WOOL = 35;
public const int PISTON_MOVING = 36;
public const int YELLOW_FLOWER = 37;
public const int RED_ROSE = 38;
public const int BROWN_MUSHROOM = 39;
@ -365,6 +366,7 @@ namespace Substrate
public static BlockInfo Piston;
public static BlockInfo PistonHead;
public static BlockInfo Wool;
public static BlockInfoEx PistonMoving;
public static BlockInfo YellowFlower;
public static BlockInfo RedRose;
public static BlockInfo BrownMushroom;
@ -472,6 +474,7 @@ namespace Substrate
Piston = new BlockInfo(33, "Piston").SetOpacity(0);
PistonHead = new BlockInfo(34, "Piston Head").SetOpacity(0);
Wool = new BlockInfo(35, "Wool");
PistonMoving = (BlockInfoEx)new BlockInfoEx(36, "Piston Moving").SetOpacity(0);
YellowFlower = new BlockInfo(37, "Yellow Flower").SetOpacity(0).SetState(BlockState.NONSOLID);
RedRose = new BlockInfo(38, "Red Rose").SetOpacity(0).SetState(BlockState.NONSOLID);
BrownMushroom = new BlockInfo(39, "Brown Mushroom").SetOpacity(0).SetLuminance(1).SetState(BlockState.NONSOLID);
@ -558,6 +561,7 @@ namespace Substrate
Dispenser.SetTileEntity("Trap");
NoteBlock.SetTileEntity("Music");
PistonMoving.SetTileEntity("Piston");
MonsterSpawner.SetTileEntity("MobSpawner");
Chest.SetTileEntity("Chest");
Furnace.SetTileEntity("Furnace");

View file

@ -10,52 +10,163 @@ namespace Substrate.Core
SOUTH = 3
}
/// <summary>
/// A basic block type.
/// </summary>
public interface IBlock
{
/// <summary>
/// Gets a variety of info and attributes on the block's type.
/// </summary>
BlockInfo Info { get; }
/// <summary>
/// Gets or sets the block's id (type).
/// </summary>
int ID { get; set; }
}
/// <summary>
/// A block type supporting a data field.
/// </summary>
public interface IDataBlock : IBlock
{
/// <summary>
/// Gets or sets a data value on the block.
/// </summary>
int Data { get; set; }
}
/// <summary>
/// A block type supporting dual-source lighting.
/// </summary>
public interface ILitBlock : IBlock
{
/// <summary>
/// Gets or sets the block-source light value on this block.
/// </summary>
int BlockLight { get; set; }
/// <summary>
/// Gets or sets the sky-source light value on this block.
/// </summary>
int SkyLight { get; set; }
}
/// <summary>
/// A block type supporting properties.
/// </summary>
public interface IPropertyBlock : IBlock
{
/// <summary>
/// Gets a tile entity attached to this block.
/// </summary>
/// <returns>A <see cref="TileEntity"/> for this block, or null if this block type does not support a tile entity.</returns>
TileEntity GetTileEntity ();
/// <summary>
/// Sets the tile entity attached to this block.
/// </summary>
/// <param name="te">A <see cref="TileEntity"/> supported by this block type.</param>
/// <exception cref="ArgumentException">Thrown when the <see cref="TileEntity"/> being passed is of the wrong type for the given block.</exception>
/// <exception cref="InvalidOperationException">Thrown when the given block is of a type that does not support a <see cref="TileEntity"/> record.</exception>
void SetTileEntity (TileEntity te);
/// <summary>
/// Creates a default tile entity for this block consistent with its type.
/// </summary>
/// <remarks>This method will overwrite any existing <see cref="TileEntity"/> attached to the block.</remarks>
/// <exception cref="InvalidOperationException">Thrown when the given block is of a type that does not support a <see cref="TileEntity"/> record.</exception>
/// <exception cref="UnknownTileEntityException">Thrown when the block type requests a <see cref="TileEntity"/> that has not been registered with the <see cref="TileEntityFactory"/>.</exception>
void CreateTileEntity ();
/// <summary>
/// Deletes the tile entity attached to this block if one exists.
/// </summary>
void ClearTileEntity ();
}
/// <summary>
/// An Alpha-compatible context-free block type supporting data and properties.
/// </summary>
public interface IAlphaBlock : IDataBlock, IPropertyBlock
{
}
/// <summary>
/// An Alpha-compatible block reference type supporting data, lighting, and properties.
/// </summary>
public interface IAlphaBlockRef : IDataBlock, ILitBlock, IPropertyBlock
{
/// <summary>
/// Checks if the reference and its backing container are currently valid.
/// </summary>
bool IsValid { get; }
}
/// <summary>
/// A basic unconstrained container of blocks.
/// </summary>
public interface IBlockCollection
{
/// <summary>
/// Gets a basic block from a block container..
/// </summary>
/// <param name="x">The X-coordinate of a block.</param>
/// <param name="y">The Y-coordinate of a block.</param>
/// <param name="z">The Z-coordinate of a block.</param>
/// <returns>A basic <see cref="IBlock"/> from the collection at the given coordinates.</returns>
IBlock GetBlock (int x, int y, int z);
/// <summary>
/// Gets a reference object to a basic within a block container.
/// </summary>
/// <param name="x">The X-coordinate of a block.</param>
/// <param name="y">The Y-coordinate of a block.</param>
/// <param name="z">The Z-coordinate of a block.</param>
/// <returns>A basic <see cref="IBlock"/> acting as a reference directly into the container at the given coordinates.</returns>
IBlock GetBlockRef (int x, int y, int z);
/// <summary>
/// Updates a block in a block container with data from an existing <see cref="IBlock"/> object.
/// </summary>
/// <param name="x">The X-coordinate of a block.</param>
/// <param name="y">The Y-coordinate of a block.</param>
/// <param name="z">The Z-coordinate of a block.</param>
/// <param name="block">The <see cref="IBlock"/> to copy basic data from.</param>
void SetBlock (int x, int y, int z, IBlock block);
/// <summary>
/// Gets a block's id (type) from a block container.
/// </summary>
/// <param name="x">The X-coordinate of a block.</param>
/// <param name="y">The Y-coordinate of a block.</param>
/// <param name="z">The Z-coordinate of a block.</param>
/// <returns>The block id (type) from the block container at the given coordinates.</returns>
int GetID (int x, int y, int z);
/// <summary>
/// Sets a block's id (type) within a block container.
/// </summary>
/// <param name="x">The X-coordinate of a block.</param>
/// <param name="y">The Y-coordinate of a block.</param>
/// <param name="z">The Z-coordinate of a block.</param>
/// <param name="id">The id (type) to assign to a block at the given coordinates.</param>
void SetID (int x, int y, int z, int id);
/// <summary>
/// Gets info and attributes on a block's type within a block container.
/// </summary>
/// <param name="x">The X-coordinate of a block.</param>
/// <param name="y">The Y-coordinate of a block.</param>
/// <param name="z">The Z-coordinate of a block.</param>
/// <returns>A <see cref="BlockInfo"/> instance for the block's type.</returns>
BlockInfo GetInfo (int x, int y, int z);
}
/// <summary>
/// A container of blocks with set dimensions.
/// </summary>
public interface IBoundedBlockCollection : IBlockCollection
{
int XDim { get; }
@ -65,6 +176,9 @@ namespace Substrate.Core
int CountByID (int id);
}
/// <summary>
/// An unbounded container of blocks supporting data fields.
/// </summary>
public interface IDataBlockCollection : IBlockCollection
{
new IDataBlock GetBlock (int x, int y, int z);
@ -76,11 +190,17 @@ namespace Substrate.Core
void SetData (int x, int y, int z, int data);
}
/// <summary>
/// A bounded version of the <see cref="IDataBlockCollection"/> interface.
/// </summary>
public interface IBoundedDataBlockCollection : IDataBlockCollection, IBoundedBlockCollection
{
int CountByData (int id, int data);
}
/// <summary>
/// An unbounded container of blocks supporting dual-source lighting.
/// </summary>
public interface ILitBlockCollection : IBlockCollection
{
new ILitBlock GetBlock (int x, int y, int z);
@ -103,6 +223,9 @@ namespace Substrate.Core
void UpdateSkyLight (int x, int y, int z);
}
/// <summary>
/// A bounded version of the <see cref="ILitBlockCollection"/> interface.
/// </summary>
public interface IBoundedLitBlockCollection : ILitBlockCollection, IBoundedBlockCollection
{
// Zero out light in entire collection
@ -122,6 +245,9 @@ namespace Substrate.Core
void StitchSkyLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge);
}
/// <summary>
/// An unbounded container for blocks supporting additional properties.
/// </summary>
public interface IPropertyBlockCollection : IBlockCollection
{
new IPropertyBlock GetBlock (int x, int y, int z);
@ -136,10 +262,16 @@ namespace Substrate.Core
void ClearTileEntity (int x, int y, int z);
}
/// <summary>
/// A bounded version of the <see cref="IPropertyBlockCollection"/> interface.
/// </summary>
public interface IBoundedPropertyBlockCollection : IPropertyBlockCollection, IBoundedBlockCollection
{
}
/// <summary>
/// An unbounded container of blocks supporting data, lighting, and properties.
/// </summary>
public interface IAlphaBlockCollection : IDataBlockCollection, ILitBlockCollection, IPropertyBlockCollection
{
new AlphaBlock GetBlock (int x, int y, int z);
@ -148,10 +280,16 @@ namespace Substrate.Core
void SetBlock (int x, int y, int z, AlphaBlock block);
}
/// <summary>
/// A bounded version of the <see cref="IAlphaBlockCollection"/> interface.
/// </summary>
public interface IBoundedAlphaBlockCollection : IAlphaBlockCollection, IBoundedDataBlockCollection, IBoundedLitBlockCollection, IBoundedPropertyBlockCollection
{
}
/// <summary>
/// Provides a common interface for block containers that provide global management.
/// </summary>
public interface IBlockManager : IAlphaBlockCollection
{
}

View file

@ -5,64 +5,173 @@ using System.IO;
namespace Substrate.Core
{
/*public interface IChunk : IBoundedBlockContainer, IAlphaBlockContainer, IEntityContainer
{
int X { get; }
int Z { get; }
bool IsTerrainPopulated { get; set; }
bool Save (Stream outStream);
int CountBlockID (int id);
int CountBlockData (int id, int data);
int CountEntities ();
int GetHeight (int lx, int lz);
}*/
/// <summary>
/// Provides a common interface for accessing Alpha-compatible chunk data.
/// </summary>
public interface IChunk
{
/// <summary>
/// Gets the global X-coordinate of a chunk.
/// </summary>
int X { get; }
/// <summary>
/// Gets the global Z-coordinate of a chunk.
/// </summary>
int Z { get; }
/// <summary>
/// Gets access to an <see cref="AlphaBlockCollection"/> representing all block data of a chunk.
/// </summary>
AlphaBlockCollection Blocks { get; }
/// <summary>
/// Gets access to an <see cref="EntityCollection"/> representing all entity data of a chunk.
/// </summary>
EntityCollection Entities { get; }
/// <summary>
/// Gets or sets the flag indicating that the terrain generator has created terrain features.
/// </summary>
/// <remarks>Terrain features include ores, water and lava sources, dungeons, trees, flowers, etc.</remarks>
bool IsTerrainPopulated { get; set; }
/// <summary>
/// Writes out the chunk's data to an output stream.
/// </summary>
/// <param name="outStream">A valid, open output stream.</param>
/// <returns>True if the chunk could be saved; false otherwise.</returns>
bool Save (Stream outStream);
}
/*public interface IChunkCache
{
bool MarkChunkDirty (ChunkRef chunk);
bool MarkChunkClean (ChunkRef chunk);
}*/
/// <summary>
/// Provides a common interface to any object that acts as a physical or abstract chunk container.
/// </summary>
public interface IChunkContainer
{
/// <summary>
/// Returns a global chunk X-coordinate, given a container-defined X-coordinate.
/// </summary>
/// <param name="cx">An X-coordinate internally assigned to a <see cref="ChunkRef"/> by a <see cref="IChunkContainer"/>.</param>
/// <returns>A corresponding global X-coordinate.</returns>
/// <remarks>This is largely intended for internal use. If an <see cref="IChunk"/> is assigned coordinates by an
/// <see cref="IChunkContainer"/>, the interpretation of those coordinates is ambiguous. This method ensures the coordinate
/// returned is interpreted as a global coordinate.</remarks>
int ChunkGlobalX (int cx);
/// <summary>
/// Returns a global chunk Z-coordinate, given a container-defined Z-coordinate.
/// </summary>
/// <param name="cz">A Z-coordinate internally assigned to a <see cref="ChunkRef"/> by a <see cref="IChunkContainer"/>.</param>
/// <returns>A corresponding global Z-coordinate.</returns>
/// <remarks>This is largely intended for internal use. If an <see cref="IChunk"/> is assigned coordinates by an
/// <see cref="IChunkContainer"/>, the interpretation of those coordinates is ambiguous. This method ensures the coordinate
/// returned is interpreted as a global coordinate.</remarks>
int ChunkGlobalZ (int cz);
/// <summary>
/// Returns a local chunk X-coordinate, given a container-defined X-coordinate.
/// </summary>
/// <param name="cx">An X-coordinate internally assigned to a <see cref="ChunkRef"/> by a <see cref="IChunkContainer"/>.</param>
/// <returns>A corresponding local X-coordinate.</returns>
/// <remarks>This is largely intended for internal use. If an <see cref="IChunk"/> is assigned coordinates by an
/// <see cref="IChunkContainer"/>, the interpretation of those coordinates is ambiguous. This method ensures the coordinate
/// returned is interpreted as a local coordinate.</remarks>
int ChunkLocalX (int cx);
/// <summary>
/// Returns a local chunk Z-coordinate, given a container-defined Z-coordinate.
/// </summary>
/// <param name="cz">A Z-coordinate internally assigned to a <see cref="ChunkRef"/> by a <see cref="IChunkContainer"/>.</param>
/// <returns>A corresponding global X-coordinate.</returns>
/// <remarks>This is largely intended for internal use. If an <see cref="IChunk"/> is assigned coordinates by an
/// <see cref="IChunkContainer"/>, the interpretation of those coordinates is ambiguous. This method ensures the coordinate
/// returned is interpreted as a local coordinate.</remarks>
int ChunkLocalZ (int cz);
/// <summary>
/// Gets an unwrapped <see cref="Chunk"/> object for the given container-local coordinates.
/// </summary>
/// <param name="cx">The container-local X-coordinate of a chunk.</param>
/// <param name="cz">The container-local Z-coordinate of a chunk.</param>
/// <returns>A <see cref="Chunk"/> for the given coordinates, or null if no chunk exists at those coordinates.</returns>
Chunk GetChunk (int cx, int cz);
/// <summary>
/// Gets a <see cref="ChunkRef"/> binding a chunk to this container for the given container-local coordinates.
/// </summary>
/// <param name="cx">The container-local X-coordinate of a chunk.</param>
/// <param name="cz">The container-local Z-coordinate of a chunk.</param>
/// <returns>A <see cref="ChunkRef"/> for the given coordinates binding a <see cref="Chunk"/> to this container, or null if
/// no chunk exists at the given coordinates.</returns>
ChunkRef GetChunkRef (int cx, int cz);
/// <summary>
/// Creates an empty chunk at the given coordinates, if no chunk previously exists.
/// </summary>
/// <param name="cx">The container-local X-coordinate of a chunk.</param>
/// <param name="cz">The container-local Z-coordinate of a chunk.</param>
/// <returns>A <see cref="ChunkRef"/> for the newly created chunk if no previous chunk existed; a <see cref="ChunkRef"/>
/// to the existing chunk otherwise.</returns>
/// <remarks>This method ensures that an empty/default chunk is written out to the underlying data store before returning.</remarks>
ChunkRef CreateChunk (int cx, int cz);
/// <summary>
/// Saves an unwrapped <see cref="Chunk"/> to the container at the given container-local coordinates.
/// </summary>
/// <param name="cx">The container-local X-coordinate to save the chunk to.</param>
/// <param name="cz">The container-local Z-coordinate to save the chunk to.</param>
/// <param name="chunk">The <see cref="Chunk"/> to save at the given coordinates.</param>
/// <returns>A <see cref="ChunkRef"/> binding <paramref name="chunk"/> to this container at the given location.</returns>
/// <remarks><para>The <see cref="Chunk"/> argument will be updated to reflect new global coordinates corresponding to
/// the given location in this container. It is up to the developer to ensure that no competing <see cref="ChunkRef"/>
/// has a handle to the <see cref="Chunk"/> argument, or an inconsistency could develop where the chunk held by the
/// other <see cref="ChunkRef"/> is written to the underlying data store with invalid coordinates.</para>
/// <para>The <see cref="ChunkRef"/> specification is designed to avoid this situation from occuring, but
/// class hierarchy extensions could violate these safeguards.</para></remarks>
ChunkRef SetChunk (int cx, int cz, Chunk chunk);
/// <summary>
/// Checks if a chunk exists at the given container-local coordinates.
/// </summary>
/// <param name="cx">The container-local X-coordinate of a chunk.</param>
/// <param name="cz">The container-local Z-coordinate of a chunk.</param>
/// <returns>True if a chunk exists at the given coordinates; false otherwise.</returns>
bool ChunkExists (int cx, int cz);
/// <summary>
/// Deletes a chunk at the given container-local coordinates if it exists.
/// </summary>
/// <param name="cx">The container-local X-coordinate of a chunk.</param>
/// <param name="cz">The container-local Z-coordinate of a chunk.</param>
/// <returns>True if a chunk existed and was deleted; false otherwise.</returns>
bool DeleteChunk (int cx, int cz);
/// <summary>
/// Saves any chunks in the container that currently have unsaved changes.
/// </summary>
/// <returns>The number of chunks that were saved.</returns>
/// <remarks>If this container supports delegating out-of-bounds coordinates to other containers, then any chunk
/// modified by an action on this container that was delegated to another container will not be saved. The foreign
/// containers must be individually saved, but are guaranteed to know about the unsaved changes originating from
/// an action in another container.</remarks>
int Save ();
// TODO: Check that this doesn't violate borders
/// <exclude/>
bool SaveChunk (Chunk chunk);
/// <summary>
/// Checks if this container supports delegating an action on out-of-bounds coordinates to another container.
/// </summary>
/// <remarks>If a container does not support this property, it is expected to throw <see cref="ArgumentOutOfRangeException"/>
/// for any action on out-of-bounds coordinates.</remarks>
bool CanDelegateCoordinates { get; }
}
/// <summary>
/// Provides a common interface for chunk containers that provide global management.
/// </summary>
public interface IChunkManager : IChunkContainer, IEnumerable<ChunkRef>
{

View file

@ -26,7 +26,7 @@ namespace Substrate.Core
private int sizeDelta;
private long lastModified = 0;
protected bool _disposed = false;
private bool _disposed = false;
public RegionFile(string path) {
offsets = new int[SECTOR_INTS];

View file

@ -11,8 +11,17 @@ namespace Substrate.Entities
public static readonly SchemaNodeCompound CreeperSchema = MobSchema.MergeInto(new SchemaNodeCompound("")
{
new SchemaNodeString("id", "Creeper"),
new SchemaNodeScaler("powered", TagType.TAG_BYTE, SchemaOptions.OPTIONAL),
});
private bool? _powered;
public bool Powered
{
get { return _powered ?? false; }
set { _powered = value; }
}
public EntityCreeper ()
: base("Creeper")
{
@ -21,11 +30,40 @@ namespace Substrate.Entities
public EntityCreeper (EntityTyped e)
: base(e)
{
EntityCreeper e2 = e as EntityCreeper;
if (e2 != null) {
_powered = e2._powered;
}
}
#region INBTObject<Entity> Members
public override EntityTyped LoadTree (TagNode tree)
{
TagNodeCompound ctree = tree as TagNodeCompound;
if (ctree == null || base.LoadTree(tree) == null) {
return null;
}
if (ctree.ContainsKey("powered")) {
_powered = ctree["powered"].ToTagByte() == 1;
}
return this;
}
public override TagNode BuildTree ()
{
TagNodeCompound tree = base.BuildTree() as TagNodeCompound;
if (_powered != null) {
tree["powered"] = new TagNodeByte((byte)((_powered ?? false) ? 1 : 0));
}
return tree;
}
public override bool ValidateTree (TagNode tree)
{
return new NbtVerifier(tree, CreeperSchema).Verify();

View file

@ -18,7 +18,7 @@ namespace Substrate.Entities
public static readonly SchemaNodeCompound MinecartSchema = EntityTyped.Schema.MergeInto(new SchemaNodeCompound("")
{
new SchemaNodeString("id", "Minecart"),
new SchemaNodeScaler("Type", TagType.TAG_BYTE),
new SchemaNodeScaler("Type", TagType.TAG_INT),
});
private CartType _type;
@ -52,7 +52,7 @@ namespace Substrate.Entities
return null;
}
_type = (CartType)ctree["Type"].ToTagByte().Data;
_type = (CartType)ctree["Type"].ToTagInt().Data;
switch (_type) {
case CartType.EMPTY:
@ -69,7 +69,7 @@ namespace Substrate.Entities
public override TagNode BuildTree ()
{
TagNodeCompound tree = base.BuildTree() as TagNodeCompound;
tree["Type"] = new TagNodeByte((byte)_type);
tree["Type"] = new TagNodeInt((int)_type);
return tree;
}

View file

@ -20,17 +20,17 @@ namespace Substrate.Entities
{
new SchemaNodeString("id", "Painting"),
new SchemaNodeScaler("Dir", TagType.TAG_BYTE),
new SchemaNodeScaler("TileX", TagType.TAG_SHORT),
new SchemaNodeScaler("TileY", TagType.TAG_SHORT),
new SchemaNodeScaler("TileZ", TagType.TAG_SHORT),
new SchemaNodeScaler("TileX", TagType.TAG_INT),
new SchemaNodeScaler("TileY", TagType.TAG_INT),
new SchemaNodeScaler("TileZ", TagType.TAG_INT),
new SchemaNodeScaler("Motive", TagType.TAG_STRING),
});
private DirectionType _dir;
private string _motive;
private short _xTile;
private short _yTile;
private short _zTile;
private int _xTile;
private int _yTile;
private int _zTile;
public DirectionType Direction
{
@ -47,19 +47,19 @@ namespace Substrate.Entities
public int TileX
{
get { return _xTile; }
set { _xTile = (short)value; }
set { _xTile = value; }
}
public int TileY
{
get { return _yTile; }
set { _yTile = (short)value; }
set { _yTile = value; }
}
public int TileZ
{
get { return _zTile; }
set { _zTile = (short)value; }
set { _zTile = value; }
}
public EntityPainting ()
@ -92,9 +92,9 @@ namespace Substrate.Entities
_dir = (DirectionType) ctree["Dir"].ToTagByte().Data;
_motive = ctree["Motive"].ToTagString();
_xTile = ctree["TileX"].ToTagShort();
_yTile = ctree["TileY"].ToTagShort();
_zTile = ctree["TileZ"].ToTagShort();
_xTile = ctree["TileX"].ToTagInt();
_yTile = ctree["TileY"].ToTagInt();
_zTile = ctree["TileZ"].ToTagInt();
return this;
}
@ -104,9 +104,9 @@ namespace Substrate.Entities
TagNodeCompound tree = base.BuildTree() as TagNodeCompound;
tree["Dir"] = new TagNodeByte((byte)_dir);
tree["Motive"] = new TagNodeString(_motive);
tree["TileX"] = new TagNodeShort(_xTile);
tree["TileY"] = new TagNodeShort(_yTile);
tree["TileZ"] = new TagNodeShort(_zTile);
tree["TileX"] = new TagNodeInt(_xTile);
tree["TileY"] = new TagNodeInt(_yTile);
tree["TileZ"] = new TagNodeInt(_zTile);
return tree;
}

View file

@ -11,8 +11,17 @@ namespace Substrate.Entities
public static readonly SchemaNodeCompound PigZombieSchema = MobSchema.MergeInto(new SchemaNodeCompound("")
{
new SchemaNodeString("id", "PigZombie"),
new SchemaNodeScaler("Anger", TagType.TAG_SHORT),
});
private short _anger;
public int Anger
{
get { return _anger; }
set { _anger = (short)value; }
}
public EntityPigZombie ()
: base("PigZombie")
{
@ -21,11 +30,35 @@ namespace Substrate.Entities
public EntityPigZombie (EntityTyped e)
: base(e)
{
EntityPigZombie e2 = e as EntityPigZombie;
if (e2 != null) {
_anger = e2._anger;
}
}
#region INBTObject<Entity> Members
public override EntityTyped LoadTree (TagNode tree)
{
TagNodeCompound ctree = tree as TagNodeCompound;
if (ctree == null || base.LoadTree(tree) == null) {
return null;
}
_anger = ctree["Anger"].ToTagShort();
return this;
}
public override TagNode BuildTree ()
{
TagNodeCompound tree = base.BuildTree() as TagNodeCompound;
tree["Anger"] = new TagNodeShort(_anger);
return tree;
}
public override bool ValidateTree (TagNode tree)
{
return new NbtVerifier(tree, PigZombieSchema).Verify();

View file

@ -299,8 +299,8 @@ namespace Substrate
RegionFile rf = GetRegionFile();
int count = 0;
for (int x = 0; x < ChunkManager.REGION_XLEN; x++) {
for (int z = 0; z < ChunkManager.REGION_ZLEN; z++) {
for (int x = 0; x < XDIM; x++) {
for (int z = 0; z < ZDIM; z++) {
if (rf.HasChunk(x, z)) {
count++;
}
@ -319,7 +319,7 @@ namespace Substrate
/// <returns>A <see cref="ChunkRef"/> at the given local coordinates, or null if no chunk exists.</returns>
/// <remarks>The local coordinates do not strictly need to be within the bounds of the region. If coordinates are detected
/// as being out of bounds, the lookup will be delegated to the correct region and the lookup will be performed there
/// instead. This allows any <see cref="Region"/> to perform a similar task to <see cref="ChunkManager"/>, but with a
/// instead. This allows any <see cref="Region"/> to perform a similar task to <see cref="BetaChunkManager"/>, but with a
/// region-local frame of reference instead of a global frame of reference.</remarks>
public ChunkRef GetChunkRef (int lcx, int lcz)
{
@ -328,8 +328,8 @@ namespace Substrate
return (alt == null) ? null : alt.GetChunkRef(ForeignX(lcx), ForeignZ(lcz));
}
int cx = lcx + _rx * ChunkManager.REGION_XLEN;
int cz = lcz + _rz * ChunkManager.REGION_ZLEN;
int cx = lcx + _rx * XDIM;
int cz = lcz + _rz * ZDIM;
ChunkKey k = new ChunkKey(cx, cz);
ChunkRef c = _cache.Fetch(k);
@ -362,8 +362,8 @@ namespace Substrate
DeleteChunk(lcx, lcz);
int cx = lcx + _rx * ChunkManager.REGION_XLEN;
int cz = lcz + _rz * ChunkManager.REGION_ZLEN;
int cx = lcx + _rx * XDIM;
int cz = lcz + _rz * ZDIM;
Chunk c = Chunk.Create(cx, cz);
c.Save(GetChunkOutStream(lcx, lcz));
@ -385,17 +385,17 @@ namespace Substrate
/// <returns>The global X-coordinate of the corresponding chunk.</returns>
public int ChunkGlobalX (int cx)
{
return _rx * ChunkManager.REGION_XLEN + cx;
return _rx * XDIM + cx;
}
/// <summary>
/// Gets the global Z-coordinate of a chunk given an internal coordinate handed out by a <see cref="Region"/> container.
/// </summary>
/// <param name="cx">An internal Z-coordinate given to a <see cref="ChunkRef"/> by any instance of a <see cref="Region"/> container.</param>
/// <param name="cz">An internal Z-coordinate given to a <see cref="ChunkRef"/> by any instance of a <see cref="Region"/> container.</param>
/// <returns>The global Z-coordinate of the corresponding chunk.</returns>
public int ChunkGlobalZ (int cz)
{
return _rz * ChunkManager.REGION_ZLEN + cz;
return _rz * ZDIM + cz;
}
/// <summary>
@ -411,7 +411,7 @@ namespace Substrate
/// <summary>
/// Gets the region-local Z-coordinate of a chunk given an internal coordinate handed out by a <see cref="Region"/> container.
/// </summary>
/// <param name="cx">An internal Z-coordinate given to a <see cref="ChunkRef"/> by any instance of a <see cref="Region"/> container.</param>
/// <param name="cz">An internal Z-coordinate given to a <see cref="ChunkRef"/> by any instance of a <see cref="Region"/> container.</param>
/// <returns>The region-local Z-coordinate of the corresponding chunk.</returns>
public int ChunkLocalZ (int cz)
{
@ -509,8 +509,8 @@ namespace Substrate
DeleteChunk(lcx, lcz);
int cx = lcx + _rx * ChunkManager.REGION_XLEN;
int cz = lcz + _rz * ChunkManager.REGION_ZLEN;
int cx = lcx + _rx * XDIM;
int cz = lcz + _rz * ZDIM;
chunk.SetLocation(cx, cz);
chunk.Save(GetChunkOutStream(lcx, lcz));
@ -555,6 +555,11 @@ namespace Substrate
return chunk.Save(GetChunkOutStream(ForeignX(chunk.X), ForeignZ(chunk.Z)));
}
public bool CanDelegateCoordinates
{
get { return true; }
}
#endregion
private bool LocalBoundsCheck (int lcx, int lcz)

View file

@ -6,15 +6,22 @@ using Substrate.Core;
namespace Substrate
{
/// <summary>
/// Manages the regions of a Beta-compatible world.
/// </summary>
public class RegionManager : IRegionManager
{
protected string _regionPath;
private string _regionPath;
protected Dictionary<RegionKey, Region> _cache;
private Dictionary<RegionKey, Region> _cache;
protected ChunkCache _chunkCache;
private ChunkCache _chunkCache;
/// <summary>
/// Creates a new instance of a <see cref="RegionManager"/> for the given region directory and chunk cache.
/// </summary>
/// <param name="regionDir">The path to a directory containing region files.</param>
/// <param name="cache">The shared chunk cache to hold chunk data in.</param>
public RegionManager (string regionDir, ChunkCache cache)
{
_regionPath = regionDir;
@ -22,6 +29,12 @@ namespace Substrate
_cache = new Dictionary<RegionKey, Region>();
}
/// <summary>
/// Gets a <see cref="Region"/> at the given coordinates.
/// </summary>
/// <param name="rx">The global X-coordinate of a region.</param>
/// <param name="rz">The global Z-coordinate of a region.</param>
/// <returns>A <see cref="Region"/> representing a region at the given coordinates, or null if the region does not exist.</returns>
public Region GetRegion (int rx, int rz)
{
RegionKey k = new RegionKey(rx, rz);
@ -40,12 +53,24 @@ namespace Substrate
}
}
/// <summary>
/// Determines if a region exists at the given coordinates.
/// </summary>
/// <param name="rx">The global X-coordinate of a region.</param>
/// <param name="rz">The global Z-coordinate of a region.</param>
/// <returns>True if a region exists at the given global region coordinates; false otherwise.</returns>
public bool RegionExists (int rx, int rz)
{
Region r = GetRegion(rx, rz);
return r != null;
}
/// <summary>
/// Creates a new empty region at the given coordinates, if no region exists.
/// </summary>
/// <param name="rx">The global X-coordinate of a region.</param>
/// <param name="rz">The global Z-coordinate of a region.</param>
/// <returns>A new empty <see cref="Region"/> object for the given coordinates, or an existing <see cref="Region"/> if one exists.</returns>
public Region CreateRegion (int rx, int rz)
{
Region r = GetRegion(rx, rz);
@ -64,7 +89,11 @@ namespace Substrate
return r;
}
/// <summary>
/// Gets a <see cref="Region"/> for the given region filename.
/// </summary>
/// <param name="filename">The filename of the region to get.</param>
/// <returns>A <see cref="Region"/> corresponding to the coordinates encoded in the filename.</returns>
public Region GetRegion (string filename)
{
int rx, rz;
@ -75,12 +104,22 @@ namespace Substrate
return GetRegion(rx, rz);
}
/// <summary>
/// Get the current region directory path.
/// </summary>
/// <returns>The path to the region directory.</returns>
public string GetRegionPath ()
{
return _regionPath;
}
// XXX: Exceptions
/// <summary>
/// Deletes a region at the given coordinates.
/// </summary>
/// <param name="rx">The global X-coordinate of a region.</param>
/// <param name="rz">The global Z-coordinate of a region.</param>
/// <returns>True if a region was deleted; false otherwise.</returns>
public bool DeleteRegion (int rx, int rz)
{
Region r = GetRegion(rx, rz);
@ -104,19 +143,12 @@ namespace Substrate
return true;
}
/*public int Save ()
{
int saved = 0;
foreach (Region r in _cache.Values) {
saved += r.Save();
}
return saved;
}*/
#region IEnumerable<Region> Members
/// <summary>
/// Returns an enumerator that iterates over all of the regions in the underlying dimension.
/// </summary>
/// <returns>An enumerator instance.</returns>
public IEnumerator<Region> GetEnumerator ()
{
return new Enumerator(this);
@ -126,6 +158,10 @@ namespace Substrate
#region IEnumerable Members
/// <summary>
/// Returns an enumerator that iterates over all of the regions in the underlying dimension.
/// </summary>
/// <returns>An enumerator instance.</returns>
IEnumerator IEnumerable.GetEnumerator ()
{
return new Enumerator(this);
@ -139,12 +175,6 @@ namespace Substrate
private List<Region> _regions;
private int _pos;
/*public Enumerator (List<Region> regs)
{
_regions = regs;
_pos = -1;
}*/
public Enumerator (RegionManager rm)
{
_regions = new List<Region>();

View file

@ -0,0 +1,128 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Substrate.TileEntities
{
using Substrate.Nbt;
public class TileEntityPiston : TileEntity
{
public static readonly SchemaNodeCompound PistonSchema = TileEntity.Schema.MergeInto(new SchemaNodeCompound("")
{
new SchemaNodeString("id", "Piston"),
new SchemaNodeScaler("blockId", TagType.TAG_INT),
new SchemaNodeScaler("blockData", TagType.TAG_INT),
new SchemaNodeScaler("facing", TagType.TAG_INT),
new SchemaNodeScaler("progress", TagType.TAG_FLOAT),
new SchemaNodeScaler("extending", TagType.TAG_BYTE),
});
private int? _record = null;
private byte _extending;
private int _blockId;
private int _blockData;
private int _facing;
private float _progress;
public bool Extending
{
get { return _extending != 0; }
set { _extending = (byte)(value ? 1 : 0); }
}
public int BlockId
{
get { return _blockId; }
set { _blockId = value; }
}
public int BlockData
{
get { return _blockData; }
set { _blockData = value; }
}
public int Facing
{
get { return _facing; }
set { _facing = value; }
}
public float Progress
{
get { return _progress; }
set { _progress = value; }
}
public TileEntityPiston ()
: base("Piston")
{
}
public TileEntityPiston (TileEntity te)
: base(te)
{
TileEntityPiston tes = te as TileEntityPiston;
if (tes != null) {
_blockId = tes._blockId;
_blockData = tes._blockData;
_facing = tes._facing;
_progress = tes._progress;
_extending = tes._extending;
}
}
#region ICopyable<TileEntity> Members
public override TileEntity Copy ()
{
return new TileEntityPiston(this);
}
#endregion
#region INBTObject<TileEntity> Members
public override TileEntity LoadTree (TagNode tree)
{
TagNodeCompound ctree = tree as TagNodeCompound;
if (ctree == null || base.LoadTree(tree) == null) {
return null;
}
_blockId = ctree["blockId"].ToTagInt();
_blockData = ctree["blockData"].ToTagInt();
_facing = ctree["facing"].ToTagInt();
_progress = ctree["progress"].ToTagFloat();
_extending = ctree["extending"].ToTagByte();
return this;
}
public override TagNode BuildTree ()
{
TagNodeCompound tree = base.BuildTree() as TagNodeCompound;
if (_record != null) {
tree["blockId"] = new TagNodeInt(_blockId);
tree["blockData"] = new TagNodeInt(_blockData);
tree["facing"] = new TagNodeInt(_facing);
tree["progress"] = new TagNodeFloat(_progress);
tree["extending"] = new TagNodeByte(_extending);
}
return tree;
}
public override bool ValidateTree (TagNode tree)
{
return new NbtVerifier(tree, PistonSchema).Verify();
}
#endregion
}
}

View file

@ -63,6 +63,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Source\AlphaWorld.cs" />
<Compile Include="Source\BetaChunkManager.cs" />
<Compile Include="Source\BetaWorld.cs" />
<Compile Include="Source\Core\OpenWorldEvent.cs" />
<Compile Include="Source\Core\RegionInterface.cs" />
@ -123,10 +124,9 @@
<Compile Include="Source\BlockManager.cs" />
<Compile Include="Source\Chunk.cs" />
<Compile Include="Source\Core\ChunkFile.cs" />
<Compile Include="Source\Core\ChunkFileManager.cs" />
<Compile Include="Source\AlphaChunkManager.cs" />
<Compile Include="Source\Core\ChunkInterface.cs" />
<Compile Include="Source\Core\ChunkKey.cs" />
<Compile Include="Source\ChunkManager.cs" />
<Compile Include="Source\ChunkRef.cs" />
<Compile Include="Source\Entities\EntityArrow.cs" />
<Compile Include="Source\Entities\EntityBoat.cs" />
@ -170,6 +170,7 @@
<Compile Include="Source\TileEntities\TileEntityChest.cs" />
<Compile Include="Source\TileEntities\TileEntityFurnace.cs" />
<Compile Include="Source\TileEntities\TileEntityMobSpawner.cs" />
<Compile Include="Source\TileEntities\TileEntityPiston.cs" />
<Compile Include="Source\TileEntities\TileEntityMusic.cs" />
<Compile Include="Source\TileEntities\TileEntityRecordPlayer.cs" />
<Compile Include="Source\TileEntities\TileEntitySign.cs" />