forked from mirrors/NBTExplorer
Region documentation, various tweaks, prepping for possible region refactoring.
This commit is contained in:
parent
b7b6f88fbe
commit
e952a14b4f
9 changed files with 327 additions and 37 deletions
|
@ -30,7 +30,7 @@ namespace Substrate
|
||||||
new SchemaNodeArray("SkyLight", 16384),
|
new SchemaNodeArray("SkyLight", 16384),
|
||||||
new SchemaNodeArray("BlockLight", 16384),
|
new SchemaNodeArray("BlockLight", 16384),
|
||||||
new SchemaNodeArray("HeightMap", 256),
|
new SchemaNodeArray("HeightMap", 256),
|
||||||
new SchemaNodeList("Entities", TagType.TAG_COMPOUND, 0, 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 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),
|
||||||
|
|
|
@ -8,6 +8,11 @@ namespace Substrate.Core
|
||||||
{
|
{
|
||||||
protected readonly byte[] dataArray;
|
protected readonly byte[] dataArray;
|
||||||
|
|
||||||
|
public ByteArray (int length)
|
||||||
|
{
|
||||||
|
dataArray = new byte[length];
|
||||||
|
}
|
||||||
|
|
||||||
public ByteArray (byte[] data)
|
public ByteArray (byte[] data)
|
||||||
{
|
{
|
||||||
dataArray = data;
|
dataArray = data;
|
||||||
|
@ -51,6 +56,14 @@ namespace Substrate.Core
|
||||||
private readonly int _ydim;
|
private readonly int _ydim;
|
||||||
private readonly int _zdim;
|
private readonly int _zdim;
|
||||||
|
|
||||||
|
public XZYByteArray (int xdim, int ydim, int zdim)
|
||||||
|
: base(xdim * ydim * zdim)
|
||||||
|
{
|
||||||
|
_xdim = xdim;
|
||||||
|
_ydim = ydim;
|
||||||
|
_zdim = zdim;
|
||||||
|
}
|
||||||
|
|
||||||
public XZYByteArray (int xdim, int ydim, int zdim, byte[] data)
|
public XZYByteArray (int xdim, int ydim, int zdim, byte[] data)
|
||||||
: base(data)
|
: base(data)
|
||||||
{
|
{
|
||||||
|
@ -122,11 +135,102 @@ namespace Substrate.Core
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public sealed class YZXByteArray : ByteArray
|
||||||
|
{
|
||||||
|
private readonly int _xdim;
|
||||||
|
private readonly int _ydim;
|
||||||
|
private readonly int _zdim;
|
||||||
|
|
||||||
|
public YZXByteArray (int xdim, int ydim, int zdim)
|
||||||
|
: base(xdim * ydim * zdim)
|
||||||
|
{
|
||||||
|
_xdim = xdim;
|
||||||
|
_ydim = ydim;
|
||||||
|
_zdim = zdim;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YZXByteArray (int xdim, int ydim, int zdim, byte[] data)
|
||||||
|
: base(data)
|
||||||
|
{
|
||||||
|
_xdim = xdim;
|
||||||
|
_ydim = ydim;
|
||||||
|
_zdim = zdim;
|
||||||
|
|
||||||
|
if (xdim * ydim * zdim != data.Length) {
|
||||||
|
throw new ArgumentException("Product of dimensions must equal length of data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte this[int x, int y, int z]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
int index = _xdim * (y * _zdim + z) + x;
|
||||||
|
return dataArray[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
int index = _xdim * (y * _zdim + z) + x;
|
||||||
|
dataArray[index] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int XDim
|
||||||
|
{
|
||||||
|
get { return _xdim; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int YDim
|
||||||
|
{
|
||||||
|
get { return _ydim; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ZDim
|
||||||
|
{
|
||||||
|
get { return _zdim; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int GetIndex (int x, int y, int z)
|
||||||
|
{
|
||||||
|
return _xdim * (y * _zdim + z) + x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetMultiIndex (int index, out int x, out int y, out int z)
|
||||||
|
{
|
||||||
|
int xzdim = _xdim * _zdim;
|
||||||
|
y = index / xzdim;
|
||||||
|
|
||||||
|
int zx = index - (y * xzdim);
|
||||||
|
z = zx / _xdim;
|
||||||
|
x = zx - (z * _xdim);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region ICopyable<YZXByteArray> Members
|
||||||
|
|
||||||
|
public override ByteArray Copy ()
|
||||||
|
{
|
||||||
|
byte[] data = new byte[dataArray.Length];
|
||||||
|
dataArray.CopyTo(data, 0);
|
||||||
|
|
||||||
|
return new YZXByteArray(_xdim, _ydim, _zdim, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
public sealed class ZXByteArray : ByteArray
|
public sealed class ZXByteArray : ByteArray
|
||||||
{
|
{
|
||||||
private readonly int _xdim;
|
private readonly int _xdim;
|
||||||
private readonly int _zdim;
|
private readonly int _zdim;
|
||||||
|
|
||||||
|
public ZXByteArray (int xdim, int zdim)
|
||||||
|
: base(xdim * zdim)
|
||||||
|
{
|
||||||
|
_xdim = xdim;
|
||||||
|
_zdim = zdim;
|
||||||
|
}
|
||||||
|
|
||||||
public ZXByteArray (int xdim, int zdim, byte[] data)
|
public ZXByteArray (int xdim, int zdim, byte[] data)
|
||||||
: base(data)
|
: base(data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,6 +9,11 @@ namespace Substrate.Core
|
||||||
{
|
{
|
||||||
protected readonly byte[] _data = null;
|
protected readonly byte[] _data = null;
|
||||||
|
|
||||||
|
public NibbleArray (int length)
|
||||||
|
{
|
||||||
|
_data = new byte[length / 2];
|
||||||
|
}
|
||||||
|
|
||||||
public NibbleArray (byte[] data)
|
public NibbleArray (byte[] data)
|
||||||
{
|
{
|
||||||
_data = data;
|
_data = data;
|
||||||
|
@ -78,6 +83,14 @@ namespace Substrate.Core
|
||||||
private readonly int _ydim;
|
private readonly int _ydim;
|
||||||
private readonly int _zdim;
|
private readonly int _zdim;
|
||||||
|
|
||||||
|
public XZYNibbleArray (int xdim, int ydim, int zdim)
|
||||||
|
: base(xdim * ydim * zdim)
|
||||||
|
{
|
||||||
|
_xdim = xdim;
|
||||||
|
_ydim = ydim;
|
||||||
|
_zdim = zdim;
|
||||||
|
}
|
||||||
|
|
||||||
public XZYNibbleArray (int xdim, int ydim, int zdim, byte[] data)
|
public XZYNibbleArray (int xdim, int ydim, int zdim, byte[] data)
|
||||||
: base(data)
|
: base(data)
|
||||||
{
|
{
|
||||||
|
|
20
Substrate/SubstrateCS/Source/Core/RegionInterface.cs
Normal file
20
Substrate/SubstrateCS/Source/Core/RegionInterface.cs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Substrate.Core
|
||||||
|
{
|
||||||
|
public interface IRegionContainer
|
||||||
|
{
|
||||||
|
bool RegionExists (int rx, int rz);
|
||||||
|
|
||||||
|
Region GetRegion (int rx, int rz);
|
||||||
|
Region CreateRegion (int rx, int rz);
|
||||||
|
|
||||||
|
bool DeleteRegion (int rx, int rz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IRegionManager : IRegionContainer, IEnumerable<Region>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ namespace Substrate
|
||||||
/// Entities of Minecraft are registered with the factory at startup and bound to their respective 'id' fields.</remarks>
|
/// Entities of Minecraft are registered with the factory at startup and bound to their respective 'id' fields.</remarks>
|
||||||
public class EntityFactory
|
public class EntityFactory
|
||||||
{
|
{
|
||||||
private static Dictionary<string, Type> _registry;
|
private static Dictionary<string, Type> _registry = new Dictionary<string, Type>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new instance of a concrete <see cref="EntityTyped"/> type by name.
|
/// Create a new instance of a concrete <see cref="EntityTyped"/> type by name.
|
||||||
|
@ -79,8 +79,6 @@ namespace Substrate
|
||||||
|
|
||||||
static EntityFactory ()
|
static EntityFactory ()
|
||||||
{
|
{
|
||||||
_registry = new Dictionary<string, Type>();
|
|
||||||
|
|
||||||
_registry["Arrow"] = typeof(EntityArrow);
|
_registry["Arrow"] = typeof(EntityArrow);
|
||||||
_registry["Boat"] = typeof(EntityBoat);
|
_registry["Boat"] = typeof(EntityBoat);
|
||||||
_registry["Chicken"] = typeof(EntityChicken);
|
_registry["Chicken"] = typeof(EntityChicken);
|
||||||
|
|
|
@ -8,6 +8,9 @@ using Substrate.Core;
|
||||||
|
|
||||||
namespace Substrate
|
namespace Substrate
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a single region containing 32x32 chunks.
|
||||||
|
/// </summary>
|
||||||
public class Region : IDisposable, IChunkContainer
|
public class Region : IDisposable, IChunkContainer
|
||||||
{
|
{
|
||||||
private const int XDIM = 32;
|
private const int XDIM = 32;
|
||||||
|
@ -17,41 +20,62 @@ namespace Substrate
|
||||||
private const int XLOG = 5;
|
private const int XLOG = 5;
|
||||||
private const int ZLOG = 5;
|
private const int ZLOG = 5;
|
||||||
|
|
||||||
protected int _rx;
|
private int _rx;
|
||||||
protected int _rz;
|
private int _rz;
|
||||||
protected bool _disposed = false;
|
private bool _disposed = false;
|
||||||
|
|
||||||
protected RegionManager _regionMan;
|
private RegionManager _regionMan;
|
||||||
|
|
||||||
protected static Regex _namePattern = new Regex("r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mcr$");
|
private static Regex _namePattern = new Regex("r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mcr$");
|
||||||
|
|
||||||
protected WeakReference _regionFile;
|
private WeakReference _regionFile;
|
||||||
|
|
||||||
//protected Dictionary<ChunkKey, WeakReference> _cache;
|
private ChunkCache _cache;
|
||||||
//protected Dictionary<ChunkKey, ChunkRef> _dirty;
|
|
||||||
|
|
||||||
protected ChunkCache _cache;
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the global X-coordinate of the region.
|
||||||
|
/// </summary>
|
||||||
public int X
|
public int X
|
||||||
{
|
{
|
||||||
get { return _rx; }
|
get { return _rx; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the global Z-coordinate of the region.
|
||||||
|
/// </summary>
|
||||||
public int Z
|
public int Z
|
||||||
{
|
{
|
||||||
get { return _rz; }
|
get { return _rz; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the X-dimension of the region in chunks.
|
||||||
|
/// </summary>
|
||||||
public int XDim
|
public int XDim
|
||||||
{
|
{
|
||||||
get { return XDIM; }
|
get { return XDIM; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the length of the Z-dimension of the region in chunks.
|
||||||
|
/// </summary>
|
||||||
public int ZDim
|
public int ZDim
|
||||||
{
|
{
|
||||||
get { return ZDIM; }
|
get { return ZDIM; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of a <see cref="Region"/> for a given set of coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rm">The <see cref="RegionManager"/> that should be managing this region.</param>
|
||||||
|
/// <param name="cache">A shared cache for holding chunks.</param>
|
||||||
|
/// <param name="rx">The global X-coordinate of the region.</param>
|
||||||
|
/// <param name="rz">The global Z-coordinate of the region.</param>
|
||||||
|
/// <remarks><para>The constructor will not actually open or parse any region files. Given just the region coordinates, the
|
||||||
|
/// region will be able to determien the correct region file to look for based on the naming pattern for regions:
|
||||||
|
/// r.x.z.mcr, given x and z are integers representing the region's coordinates.</para>
|
||||||
|
/// <para>Regions require a <see cref="ChunkCache"/> to be provided because they do not actually store any chunks or references
|
||||||
|
/// to chunks on their own. This allows regions to easily pass off requests outside of their bounds, if necessary.</para></remarks>
|
||||||
public Region (RegionManager rm, ChunkCache cache, int rx, int rz)
|
public Region (RegionManager rm, ChunkCache cache, int rx, int rz)
|
||||||
{
|
{
|
||||||
_regionMan = rm;
|
_regionMan = rm;
|
||||||
|
@ -60,14 +84,22 @@ namespace Substrate
|
||||||
_rx = rx;
|
_rx = rx;
|
||||||
_rz = rz;
|
_rz = rz;
|
||||||
|
|
||||||
//_cache = new Dictionary<ChunkKey, WeakReference>();
|
|
||||||
//_dirty = new Dictionary<ChunkKey, ChunkRef>();
|
|
||||||
|
|
||||||
if (!File.Exists(GetFilePath())) {
|
if (!File.Exists(GetFilePath())) {
|
||||||
throw new FileNotFoundException();
|
throw new FileNotFoundException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of a <see cref="Region"/> for the given region file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rm">The <see cref="RegionManager"/> that should be managing this region.</param>
|
||||||
|
/// <param name="cache">A shared cache for holding chunks.</param>
|
||||||
|
/// <param name="filename">The region file to derive the region from.</param>
|
||||||
|
/// <remarks><para>The constructor will not actually open or parse the region file. It will only read the file's name in order
|
||||||
|
/// to derive the region's coordinates, based on a strict naming pattern for regions: r.x.z.mcr, given x and z are integers
|
||||||
|
/// representing the region's coordinates.</para>
|
||||||
|
/// <para>Regions require a <see cref="ChunkCache"/> to be provided because they do not actually store any chunks or references
|
||||||
|
/// to chunks on their own. This allows regions to easily pass off requests outside of their bounds, if necessary.</para></remarks>
|
||||||
public Region (RegionManager rm, ChunkCache cache, string filename)
|
public Region (RegionManager rm, ChunkCache cache, string filename)
|
||||||
{
|
{
|
||||||
_regionMan = rm;
|
_regionMan = rm;
|
||||||
|
@ -81,17 +113,27 @@ namespace Substrate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Region finalizer that ensures any resources are cleaned up
|
||||||
|
/// </summary>
|
||||||
~Region ()
|
~Region ()
|
||||||
{
|
{
|
||||||
Dispose(false);
|
Dispose(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disposes any managed and unmanaged resources held by the region.
|
||||||
|
/// </summary>
|
||||||
public void Dispose ()
|
public void Dispose ()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
System.GC.SuppressFinalize(this);
|
System.GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Conditionally dispose managed or unmanaged resources.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">True if the call to Dispose was explicit.</param>
|
||||||
protected virtual void Dispose (bool disposing)
|
protected virtual void Dispose (bool disposing)
|
||||||
{
|
{
|
||||||
if (!_disposed) {
|
if (!_disposed) {
|
||||||
|
@ -109,12 +151,21 @@ namespace Substrate
|
||||||
_disposed = true;
|
_disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the appropriate filename for this region.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The filename of the region with encoded coordinates.</returns>
|
||||||
public string GetFileName ()
|
public string GetFileName ()
|
||||||
{
|
{
|
||||||
return "r." + _rx + "." + _rz + ".mcr";
|
return "r." + _rx + "." + _rz + ".mcr";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests if the given filename conforms to the general naming pattern for any region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename">The filename to test.</param>
|
||||||
|
/// <returns>True if the filename is a valid region name; false if it does not conform to the pattern.</returns>
|
||||||
public static bool TestFileName (string filename)
|
public static bool TestFileName (string filename)
|
||||||
{
|
{
|
||||||
Match match = _namePattern.Match(filename);
|
Match match = _namePattern.Match(filename);
|
||||||
|
@ -125,6 +176,13 @@ namespace Substrate
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses the given filename to extract encoded region coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename">The region filename to parse.</param>
|
||||||
|
/// <param name="x">This parameter will contain the X-coordinate of a region.</param>
|
||||||
|
/// <param name="z">This parameter will contain the Z-coordinate of a region.</param>
|
||||||
|
/// <returns>True if the filename could be correctly parse; false otherwise.</returns>
|
||||||
public static bool ParseFileName (string filename, out int x, out int z)
|
public static bool ParseFileName (string filename, out int x, out int z)
|
||||||
{
|
{
|
||||||
x = 0;
|
x = 0;
|
||||||
|
@ -140,12 +198,16 @@ namespace Substrate
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the full path of the region's backing file.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Gets the path of the region's file based on the <see cref="RegionManager"/>'s region path and the region's on filename.</returns>
|
||||||
public string GetFilePath ()
|
public string GetFilePath ()
|
||||||
{
|
{
|
||||||
return System.IO.Path.Combine(_regionMan.GetRegionPath(), GetFileName());
|
return System.IO.Path.Combine(_regionMan.GetRegionPath(), GetFileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RegionFile GetRegionFile ()
|
private RegionFile GetRegionFile ()
|
||||||
{
|
{
|
||||||
RegionFile rf = _regionFile.Target as RegionFile;
|
RegionFile rf = _regionFile.Target as RegionFile;
|
||||||
if (rf == null) {
|
if (rf == null) {
|
||||||
|
@ -156,6 +218,12 @@ namespace Substrate
|
||||||
return rf;
|
return rf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="NbtTree"/> for a chunk given local coordinates into the region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcx">The local X-coordinate of a chunk within the region.</param>
|
||||||
|
/// <param name="lcz">The local Z-coordinate of a chunk within the region.</param>
|
||||||
|
/// <returns>An <see cref="NbtTree"/> for a local chunk, or null if there is no chunk at the given coordinates.</returns>
|
||||||
public NbtTree GetChunkTree (int lcx, int lcz)
|
public NbtTree GetChunkTree (int lcx, int lcz)
|
||||||
{
|
{
|
||||||
if (!LocalBoundsCheck(lcx, lcz)) {
|
if (!LocalBoundsCheck(lcx, lcz)) {
|
||||||
|
@ -175,6 +243,16 @@ namespace Substrate
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: Exceptions
|
||||||
|
/// <summary>
|
||||||
|
/// Saves an <see cref="NbtTree"/> for a chunk back to the region's data store at the given local coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcx">The local X-coordinate of the chunk within the region.</param>
|
||||||
|
/// <param name="lcz">The local Z-coordinate of the chunk within the region.</param>
|
||||||
|
/// <param name="tree">The <see cref="NbtTree"/> of a chunk to write back to the region.</param>
|
||||||
|
/// <returns>True if the save succeeded.</returns>
|
||||||
|
/// <remarks>It is up to the programmer to ensure that the global coordinates defined within the chunk's tree
|
||||||
|
/// are consistent with the local coordinates of the region being written into.</remarks>
|
||||||
public bool SaveChunkTree (int lcx, int lcz, NbtTree tree)
|
public bool SaveChunkTree (int lcx, int lcz, NbtTree tree)
|
||||||
{
|
{
|
||||||
if (!LocalBoundsCheck(lcx, lcz)) {
|
if (!LocalBoundsCheck(lcx, lcz)) {
|
||||||
|
@ -194,6 +272,13 @@ namespace Substrate
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an output stream for replacing chunk data at the given coordinates within the region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcx">The local X-coordinate of the chunk to replace within the region.</param>
|
||||||
|
/// <param name="lcz">The local Z-coordinate of the chunk to replace within the region.</param>
|
||||||
|
/// <returns>An output stream that can be written to on demand.</returns>
|
||||||
|
/// <remarks>There is no guarantee that any data will be saved until the stream is closed.</remarks>
|
||||||
public Stream GetChunkOutStream (int lcx, int lcz)
|
public Stream GetChunkOutStream (int lcx, int lcz)
|
||||||
{
|
{
|
||||||
if (!LocalBoundsCheck(lcx, lcz)) {
|
if (!LocalBoundsCheck(lcx, lcz)) {
|
||||||
|
@ -205,6 +290,10 @@ namespace Substrate
|
||||||
return rf.GetChunkDataOutputStream(lcx, lcz);
|
return rf.GetChunkDataOutputStream(lcx, lcz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the count of valid chunks stored in this region.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The count of currently stored chunks.</returns>
|
||||||
public int ChunkCount ()
|
public int ChunkCount ()
|
||||||
{
|
{
|
||||||
RegionFile rf = GetRegionFile();
|
RegionFile rf = GetRegionFile();
|
||||||
|
@ -221,6 +310,17 @@ namespace Substrate
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: Consider revising foreign lookup support
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a <see cref="ChunkRef"/> for a chunk at the given local coordinates relative to this region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcx">The local X-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <param name="lcz">The local Z-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <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
|
||||||
|
/// region-local frame of reference instead of a global frame of reference.</remarks>
|
||||||
public ChunkRef GetChunkRef (int lcx, int lcz)
|
public ChunkRef GetChunkRef (int lcx, int lcz)
|
||||||
{
|
{
|
||||||
if (!LocalBoundsCheck(lcx, lcz)) {
|
if (!LocalBoundsCheck(lcx, lcz)) {
|
||||||
|
@ -245,6 +345,14 @@ namespace Substrate
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new chunk at the given local coordinates relative to this region and returns a new <see cref="ChunkRef"/> for it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcx">The local X-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <param name="lcz">The local Z-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <returns>A <see cref="ChunkRef"/> for the newly created chunk.</returns>
|
||||||
|
/// <remarks>If the local coordinates are out of bounds for this region, the action will be forwarded to the correct region
|
||||||
|
/// transparently.</remarks>
|
||||||
public ChunkRef CreateChunk (int lcx, int lcz)
|
public ChunkRef CreateChunk (int lcx, int lcz)
|
||||||
{
|
{
|
||||||
if (!LocalBoundsCheck(lcx, lcz)) {
|
if (!LocalBoundsCheck(lcx, lcz)) {
|
||||||
|
@ -269,26 +377,55 @@ namespace Substrate
|
||||||
|
|
||||||
#region IChunkCollection Members
|
#region IChunkCollection Members
|
||||||
|
|
||||||
|
// XXX: This also feels dirty.
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the global X-coordinate of a chunk given an internal coordinate handed out by a <see cref="Region"/> container.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cx">An internal X-coordinate given to a <see cref="ChunkRef"/> by any instance of a <see cref="Region"/> container.</param>
|
||||||
|
/// <returns>The global X-coordinate of the corresponding chunk.</returns>
|
||||||
public int ChunkGlobalX (int cx)
|
public int ChunkGlobalX (int cx)
|
||||||
{
|
{
|
||||||
return _rx * ChunkManager.REGION_XLEN + cx;
|
return _rx * ChunkManager.REGION_XLEN + 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>
|
||||||
|
/// <returns>The global Z-coordinate of the corresponding chunk.</returns>
|
||||||
public int ChunkGlobalZ (int cz)
|
public int ChunkGlobalZ (int cz)
|
||||||
{
|
{
|
||||||
return _rz * ChunkManager.REGION_ZLEN + cz;
|
return _rz * ChunkManager.REGION_ZLEN + cz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the region-local X-coordinate of a chunk given an internal coordinate handed out by a <see cref="Region"/> container.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cx">An internal X-coordinate given to a <see cref="ChunkRef"/> by any instance of a <see cref="Region"/> container.</param>
|
||||||
|
/// <returns>The region-local X-coordinate of the corresponding chunk.</returns>
|
||||||
public int ChunkLocalX (int cx)
|
public int ChunkLocalX (int cx)
|
||||||
{
|
{
|
||||||
return cx;
|
return cx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
/// <returns>The region-local Z-coordinate of the corresponding chunk.</returns>
|
||||||
public int ChunkLocalZ (int cz)
|
public int ChunkLocalZ (int cz)
|
||||||
{
|
{
|
||||||
return cz;
|
return cz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="Chunk"/> given local coordinates relative to this region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcx">The local X-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <param name="lcz">The local Z-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <returns>A <see cref="Chunk"/> object for the given coordinates, or null if the chunk does not exist.</returns>
|
||||||
|
/// <remarks>If the local coordinates are out of bounds for this region, the action will be forwarded to the correct region
|
||||||
|
/// transparently. The returned <see cref="Chunk"/> object may either come from cache, or be regenerated from disk.</remarks>
|
||||||
public Chunk GetChunk (int lcx, int lcz)
|
public Chunk GetChunk (int lcx, int lcz)
|
||||||
{
|
{
|
||||||
if (!LocalBoundsCheck(lcx, lcz)) {
|
if (!LocalBoundsCheck(lcx, lcz)) {
|
||||||
|
@ -303,6 +440,14 @@ namespace Substrate
|
||||||
return Chunk.CreateVerified(GetChunkTree(lcx, lcz));
|
return Chunk.CreateVerified(GetChunkTree(lcx, lcz));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a chunk exists at the given local coordinates relative to this region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcx">The local X-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <param name="lcz">The local Z-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <returns>True if there is a chunk at the given coordinates; false otherwise.</returns>
|
||||||
|
/// <remarks>If the local coordinates are out of bounds for this region, the action will be forwarded to the correct region
|
||||||
|
/// transparently.</remarks>
|
||||||
public bool ChunkExists (int lcx, int lcz)
|
public bool ChunkExists (int lcx, int lcz)
|
||||||
{
|
{
|
||||||
if (!LocalBoundsCheck(lcx, lcz)) {
|
if (!LocalBoundsCheck(lcx, lcz)) {
|
||||||
|
@ -314,6 +459,14 @@ namespace Substrate
|
||||||
return rf.HasChunk(lcx, lcz);
|
return rf.HasChunk(lcx, lcz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes a chunk from the underlying data store at the given local coordinates relative to this region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcx">The local X-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <param name="lcz">The local Z-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <returns>True if there is a chunk was deleted; false otherwise.</returns>
|
||||||
|
/// <remarks>If the local coordinates are out of bounds for this region, the action will be forwarded to the correct region
|
||||||
|
/// transparently.</remarks>
|
||||||
public bool DeleteChunk (int lcx, int lcz)
|
public bool DeleteChunk (int lcx, int lcz)
|
||||||
{
|
{
|
||||||
if (!LocalBoundsCheck(lcx, lcz)) {
|
if (!LocalBoundsCheck(lcx, lcz)) {
|
||||||
|
@ -338,6 +491,15 @@ namespace Substrate
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves an existing <see cref="Chunk"/> to the region at the given local coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="lcx">The local X-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <param name="lcz">The local Z-coordinate of a chunk relative to this region.</param>
|
||||||
|
/// <param name="chunk">A <see cref="Chunk"/> to save to the given location.</param>
|
||||||
|
/// <returns>A <see cref="ChunkRef"/> represneting the <see cref="Chunk"/> at its new location.</returns>
|
||||||
|
/// <remarks>If the local coordinates are out of bounds for this region, the action will be forwarded to the correct region
|
||||||
|
/// transparently. The <see cref="Chunk"/>'s internal global coordinates will be updated to reflect the new location.</remarks>
|
||||||
public ChunkRef SetChunk (int lcx, int lcz, Chunk chunk)
|
public ChunkRef SetChunk (int lcx, int lcz, Chunk chunk)
|
||||||
{
|
{
|
||||||
if (!LocalBoundsCheck(lcx, lcz)) {
|
if (!LocalBoundsCheck(lcx, lcz)) {
|
||||||
|
@ -359,6 +521,10 @@ namespace Substrate
|
||||||
return cr;
|
return cr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves all chunks within this region that have been marked as dirty.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The number of chunks that were saved.</returns>
|
||||||
public int Save ()
|
public int Save ()
|
||||||
{
|
{
|
||||||
_cache.SyncDirty();
|
_cache.SyncDirty();
|
||||||
|
@ -381,6 +547,8 @@ namespace Substrate
|
||||||
return saved;
|
return saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: Allows a chunk not part of this region to be saved to it
|
||||||
|
/// <exclude/>
|
||||||
public bool SaveChunk (Chunk chunk)
|
public bool SaveChunk (Chunk chunk)
|
||||||
{
|
{
|
||||||
//Console.WriteLine("Region[{0}, {1}].Save({2}, {3})", _rx, _rz, ForeignX(chunk.X),ForeignZ(chunk.Z));
|
//Console.WriteLine("Region[{0}, {1}].Save({2}, {3})", _rx, _rz, ForeignX(chunk.X),ForeignZ(chunk.Z));
|
||||||
|
|
|
@ -6,20 +6,7 @@ using Substrate.Core;
|
||||||
|
|
||||||
namespace Substrate
|
namespace Substrate
|
||||||
{
|
{
|
||||||
public interface IRegionContainer
|
|
||||||
{
|
|
||||||
bool RegionExists (int rx, int rz);
|
|
||||||
|
|
||||||
Region GetRegion (int rx, int rz);
|
|
||||||
Region CreateRegion (int rx, int rz);
|
|
||||||
|
|
||||||
bool DeleteRegion (int rx, int rz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface IRegionManager : IRegionContainer, IEnumerable<Region>
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public class RegionManager : IRegionManager
|
public class RegionManager : IRegionManager
|
||||||
{
|
{
|
||||||
protected string _regionPath;
|
protected string _regionPath;
|
||||||
|
@ -152,11 +139,11 @@ namespace Substrate
|
||||||
private List<Region> _regions;
|
private List<Region> _regions;
|
||||||
private int _pos;
|
private int _pos;
|
||||||
|
|
||||||
public Enumerator (List<Region> regs)
|
/*public Enumerator (List<Region> regs)
|
||||||
{
|
{
|
||||||
_regions = regs;
|
_regions = regs;
|
||||||
_pos = -1;
|
_pos = -1;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
public Enumerator (RegionManager rm)
|
public Enumerator (RegionManager rm)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,7 @@ namespace Substrate
|
||||||
/// Tile Entities of Minecraft are registered with the factory at startup and bound to their respective 'id' fields.</remarks>
|
/// Tile Entities of Minecraft are registered with the factory at startup and bound to their respective 'id' fields.</remarks>
|
||||||
public class TileEntityFactory
|
public class TileEntityFactory
|
||||||
{
|
{
|
||||||
private static Dictionary<string, Type> _registry;
|
private static Dictionary<string, Type> _registry = new Dictionary<string, Type>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new instance of a concrete <see cref="TileEntity"/> type by name.
|
/// Create a new instance of a concrete <see cref="TileEntity"/> type by name.
|
||||||
|
@ -77,8 +77,6 @@ namespace Substrate
|
||||||
|
|
||||||
static TileEntityFactory ()
|
static TileEntityFactory ()
|
||||||
{
|
{
|
||||||
_registry = new Dictionary<string, Type>();
|
|
||||||
|
|
||||||
_registry["Chest"] = typeof(TileEntityChest);
|
_registry["Chest"] = typeof(TileEntityChest);
|
||||||
_registry["Furnace"] = typeof(TileEntityFurnace);
|
_registry["Furnace"] = typeof(TileEntityFurnace);
|
||||||
_registry["MobSpawner"] = typeof(TileEntityMobSpawner);
|
_registry["MobSpawner"] = typeof(TileEntityMobSpawner);
|
||||||
|
|
|
@ -65,6 +65,8 @@
|
||||||
<Compile Include="Source\AlphaWorld.cs" />
|
<Compile Include="Source\AlphaWorld.cs" />
|
||||||
<Compile Include="Source\BetaWorld.cs" />
|
<Compile Include="Source\BetaWorld.cs" />
|
||||||
<Compile Include="Source\Core\OpenWorldEvent.cs" />
|
<Compile Include="Source\Core\OpenWorldEvent.cs" />
|
||||||
|
<Compile Include="Source\Core\RegionInterface.cs" />
|
||||||
|
<Compile Include="Source\IO\Schematic.cs" />
|
||||||
<Compile Include="Source\LevelIOException.cs" />
|
<Compile Include="Source\LevelIOException.cs" />
|
||||||
<Compile Include="Source\AlphaBlock.cs" />
|
<Compile Include="Source\AlphaBlock.cs" />
|
||||||
<Compile Include="Source\AlphaBlockRef.cs" />
|
<Compile Include="Source\AlphaBlockRef.cs" />
|
||||||
|
|
Loading…
Reference in a new issue