From 325472a00a776c0f993a99bfa2deb2de4ccc0654 Mon Sep 17 00:00:00 2001 From: Justin Aquadro Date: Thu, 7 Jul 2011 04:27:48 +0000 Subject: [PATCH] Documenting and refactoring blocks, chunks. Updated some inconsistencies in entities and tile entities. --- .../SubstrateCS/Examples/Relight/Program.cs | 7 +- ...unkFileManager.cs => AlphaChunkManager.cs} | 82 ++++----- Substrate/SubstrateCS/Source/AlphaWorld.cs | 36 ++-- .../{ChunkManager.cs => BetaChunkManager.cs} | 156 ++++++++++++------ Substrate/SubstrateCS/Source/BetaWorld.cs | 40 ++--- Substrate/SubstrateCS/Source/BlockInfo.cs | 4 + .../SubstrateCS/Source/Core/BlockInterface.cs | 138 ++++++++++++++++ .../SubstrateCS/Source/Core/ChunkInterface.cs | 155 ++++++++++++++--- .../SubstrateCS/Source/Core/RegionFile.cs | 2 +- .../Source/Entities/EntityCreeper.cs | 38 +++++ .../Source/Entities/EntityMinecart.cs | 6 +- .../Source/Entities/EntityPainting.cs | 30 ++-- .../Source/Entities/EntityPigZombie.cs | 33 ++++ Substrate/SubstrateCS/Source/Region.cs | 31 ++-- Substrate/SubstrateCS/Source/RegionManager.cs | 76 ++++++--- .../Source/TileEntities/TileEntityPiston.cs | 128 ++++++++++++++ Substrate/SubstrateCS/Substrate.csproj | 5 +- 17 files changed, 752 insertions(+), 215 deletions(-) rename Substrate/SubstrateCS/Source/{Core/ChunkFileManager.cs => AlphaChunkManager.cs} (81%) rename Substrate/SubstrateCS/Source/{ChunkManager.cs => BetaChunkManager.cs} (71%) create mode 100644 Substrate/SubstrateCS/Source/TileEntities/TileEntityPiston.cs diff --git a/Substrate/SubstrateCS/Examples/Relight/Program.cs b/Substrate/SubstrateCS/Examples/Relight/Program.cs index 59f429a..27a1e2b 100644 --- a/Substrate/SubstrateCS/Examples/Relight/Program.cs +++ b/Substrate/SubstrateCS/Examples/Relight/Program.cs @@ -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(); diff --git a/Substrate/SubstrateCS/Source/Core/ChunkFileManager.cs b/Substrate/SubstrateCS/Source/AlphaChunkManager.cs similarity index 81% rename from Substrate/SubstrateCS/Source/Core/ChunkFileManager.cs rename to Substrate/SubstrateCS/Source/AlphaChunkManager.cs index 8af6070..f1c6cab 100644 --- a/Substrate/SubstrateCS/Source/Core/ChunkFileManager.cs +++ b/Substrate/SubstrateCS/Source/AlphaChunkManager.cs @@ -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 + /// + /// Represents an Alpha-compatible interface for globally managing chunks. + /// + public class AlphaChunkManager : IChunkManager { private string _mapPath; @@ -16,24 +20,31 @@ namespace Substrate.Core private LRUCache _cache; private Dictionary _dirty; + /// + /// Gets the path to the base directory containing the chunk directory structure. + /// public string ChunkPath { get { return _mapPath; } } - public ChunkFileManager (string mapDir) + /// + /// Creates a new instance for the give chunk base directory. + /// + /// The path to the chunk base directory. + public AlphaChunkManager (string mapDir) { _mapPath = mapDir; _cache = new LRUCache(256); _dirty = new Dictionary(); } - 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 + /// public int ChunkGlobalX (int cx) { return cx; } + /// public int ChunkGlobalZ (int cz) { return cz; } + /// public int ChunkLocalX (int cx) { return cx; } + /// public int ChunkLocalZ (int cz) { return cz; } + /// public Chunk GetChunk (int cx, int cz) { if (!ChunkExists(cx, cz)) { @@ -94,6 +110,7 @@ namespace Substrate.Core return Chunk.CreateVerified(GetChunkTree(cx, cz)); } + /// public ChunkRef GetChunkRef (int cx, int cz) { ChunkKey k = new ChunkKey(cx, cz); @@ -113,6 +130,7 @@ namespace Substrate.Core return c; } + /// public ChunkRef CreateChunk (int cx, int cz) { DeleteChunk(cx, cz); @@ -126,11 +144,13 @@ namespace Substrate.Core return cr; } + /// public bool ChunkExists (int cx, int cz) { return new ChunkFile(_mapPath, cx, cz).Exists(); } + /// public bool DeleteChunk (int cx, int cz) { new ChunkFile(_mapPath, cx, cz).Delete(); @@ -142,6 +162,7 @@ namespace Substrate.Core return true; } + /// public ChunkRef SetChunk (int cx, int cz, Chunk chunk) { DeleteChunk(cx, cz); @@ -155,6 +176,7 @@ namespace Substrate.Core return cr; } + /// public int Save () { foreach (KeyValuePair e in _cache) { @@ -177,6 +199,7 @@ namespace Substrate.Core return saved; } + /// public bool SaveChunk (Chunk chunk) { if (chunk.Save(GetChunkOutStream(ChunkGlobalX(chunk.X), ChunkGlobalZ(chunk.Z)))) { @@ -187,41 +210,20 @@ namespace Substrate.Core return false; } + /// + 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 Members + /// + /// Gets an enumerator that iterates through all the chunks in the world. + /// + /// An enumerator for this manager. public IEnumerator GetEnumerator () { return new Enumerator(this); @@ -241,7 +243,7 @@ namespace Substrate.Core private class Enumerator : IEnumerator { - protected ChunkFileManager _cm; + protected AlphaChunkManager _cm; protected Queue _tld; protected Queue _sld; protected Queue _chunks; @@ -250,7 +252,7 @@ namespace Substrate.Core private string _cursld; private ChunkRef _curchunk; - public Enumerator (ChunkFileManager cfm) + public Enumerator (AlphaChunkManager cfm) { _cm = cfm; diff --git a/Substrate/SubstrateCS/Source/AlphaWorld.cs b/Substrate/SubstrateCS/Source/AlphaWorld.cs index 04ae168..e1c28b6 100644 --- a/Substrate/SubstrateCS/Source/AlphaWorld.cs +++ b/Substrate/SubstrateCS/Source/AlphaWorld.cs @@ -19,14 +19,14 @@ namespace Substrate private Level _level; - private Dictionary _chunkMgrs; + private Dictionary _chunkMgrs; private Dictionary _blockMgrs; private PlayerManager _playerMan; private AlphaWorld () { - _chunkMgrs = new Dictionary(); + _chunkMgrs = new Dictionary(); _blockMgrs = new Dictionary(); } @@ -44,7 +44,7 @@ namespace Substrate /// A tied to the default dimension in this world. /// Get a 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 - /// instead and working with blocks on a chunk-local level. + /// instead and working with blocks on a chunk-local level. public new BlockManager GetBlockManager () { return GetBlockManagerVirt(Dimension.DEFAULT) as BlockManager; @@ -57,31 +57,31 @@ namespace Substrate /// A tied to the given dimension in this world. /// Get a 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 - /// instead and working with blocks on a chunk-local level. + /// instead and working with blocks on a chunk-local level. public new BlockManager GetBlockManager (int dim) { return GetBlockManagerVirt(dim) as BlockManager; } /// - /// Gets a for the default dimension. + /// Gets a for the default dimension. /// - /// A tied to the default dimension in this world. - /// Get a if you you need to work with easily-digestible, bounded chunks of blocks. - public new ChunkFileManager GetChunkManager () + /// A tied to the default dimension in this world. + /// Get a if you you need to work with easily-digestible, bounded chunks of blocks. + public new AlphaChunkManager GetChunkManager () { - return GetChunkManagerVirt(Dimension.DEFAULT) as ChunkFileManager; + return GetChunkManagerVirt(Dimension.DEFAULT) as AlphaChunkManager; } /// - /// Gets a for the given dimension. + /// Gets a for the given dimension. /// /// The id of the dimension to look up. - /// A tied to the given dimension in this world. - /// Get a if you you need to work with easily-digestible, bounded chunks of blocks. - public new ChunkFileManager GetChunkManager (int dim) + /// A tied to the given dimension in this world. + /// Get a if you you need to work with easily-digestible, bounded chunks of blocks. + public new AlphaChunkManager GetChunkManager (int dim) { - return GetChunkManagerVirt(dim) as ChunkFileManager; + return GetChunkManagerVirt(dim) as AlphaChunkManager; } /// @@ -101,7 +101,7 @@ namespace Substrate { _level.Save(); - foreach (KeyValuePair cm in _chunkMgrs) { + foreach (KeyValuePair cm in _chunkMgrs) { cm.Value.Save(); } } @@ -111,7 +111,7 @@ namespace Substrate /// /// The path to the directory containing the world's level.dat, or the path to level.dat itself. /// A new object representing an existing world on disk. - 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 /// 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; diff --git a/Substrate/SubstrateCS/Source/ChunkManager.cs b/Substrate/SubstrateCS/Source/BetaChunkManager.cs similarity index 71% rename from Substrate/SubstrateCS/Source/ChunkManager.cs rename to Substrate/SubstrateCS/Source/BetaChunkManager.cs index 18155bf..c4ce37b 100644 --- a/Substrate/SubstrateCS/Source/ChunkManager.cs +++ b/Substrate/SubstrateCS/Source/BetaChunkManager.cs @@ -5,60 +5,80 @@ using Substrate.Core; namespace Substrate { - public class ChunkManager : IChunkManager, IEnumerable + /// + /// Represents a Beta-compatible interface for globally managing chunks. + /// + public class BetaChunkManager : IChunkManager, IEnumerable { - 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 _cache; - //protected Dictionary _dirty; + private ChunkCache _cache; - protected ChunkCache _cache; - - public ChunkManager (RegionManager rm, ChunkCache cache) + /// + /// Creates a new instance given a backing and . + /// + /// A exposing access to regions. + /// A shared cache for storing chunks read in. + public BetaChunkManager (RegionManager rm, ChunkCache cache) { _regionMan = rm; _cache = cache; - //_cache = new Dictionary(); - //_dirty = new Dictionary(); } - public ChunkManager (ChunkManager cm) + /// + /// Creates a new instance from another. + /// + /// A to get a and from. + public BetaChunkManager (BetaChunkManager cm) { _regionMan = cm._regionMan; _cache = cm._cache; - //_cache = new Dictionary(); - //_dirty = new Dictionary(); } + /// + /// Gets the backing this manager. + /// + public RegionManager RegionManager + { + get { return _regionMan; } + } + + #region IChunkContainer + + /// public int ChunkGlobalX (int cx) { return cx; } + /// public int ChunkGlobalZ (int cz) { return cz; } + /// public int ChunkLocalX (int cx) { return cx & REGION_XMASK; } + /// public int ChunkLocalZ (int cz) { return cz & REGION_ZMASK; } + /// 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); } + /// 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); } + /// 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); } + /// 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); - } - + /// 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); } + /// public int Save () { _cache.SyncDirty(); @@ -160,6 +163,7 @@ namespace Substrate return saved; } + /// public bool SaveChunk (Chunk chunk) { Region r = GetRegion(chunk.X, chunk.Z); @@ -170,6 +174,7 @@ namespace Substrate return r.SaveChunk(chunk); } + /// public bool DeleteChunk (int cx, int cz) { Region r = GetRegion(cx, cz); @@ -188,6 +193,47 @@ namespace Substrate return true; } + /// + public bool CanDelegateCoordinates + { + get { return true; } + } + + #endregion + + /// + /// Copies a chunk from one location to another. + /// + /// The global X-coordinate of the source chunk. + /// The global Z-coordinate of the source chunk. + /// The global X-coordinate of the destination chunk. + /// The global Z-coordinate of the destination chunk. + /// A for the destination chunk. + 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); + } + + /// + /// Performs a full chunk relight sequence on all modified chunks. + /// public void RelightDirtyChunks () { //List dirty = new List(); @@ -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 Members + /// + /// Returns an enumerator that iterates through all chunks in all regions of the world. + /// + /// An enumerator for this manager. public IEnumerator GetEnumerator () { return new Enumerator(this); @@ -270,6 +315,7 @@ namespace Substrate #region IEnumerable Members + /// System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () { return new Enumerator(this); @@ -280,7 +326,7 @@ namespace Substrate private class Enumerator : IEnumerator { - private ChunkManager _cm; + private BetaChunkManager _cm; private IEnumerator _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; diff --git a/Substrate/SubstrateCS/Source/BetaWorld.cs b/Substrate/SubstrateCS/Source/BetaWorld.cs index e72866c..b8c8ac5 100644 --- a/Substrate/SubstrateCS/Source/BetaWorld.cs +++ b/Substrate/SubstrateCS/Source/BetaWorld.cs @@ -22,7 +22,7 @@ namespace Substrate private Level _level; private Dictionary _regionMgrs; - private Dictionary _chunkMgrs; + private Dictionary _chunkMgrs; private Dictionary _blockMgrs; private PlayerManager _playerMan; @@ -30,7 +30,7 @@ namespace Substrate private BetaWorld () { _regionMgrs = new Dictionary(); - _chunkMgrs = new Dictionary(); + _chunkMgrs = new Dictionary(); _blockMgrs = new Dictionary(); } @@ -48,7 +48,7 @@ namespace Substrate /// A tied to the default dimension in this world. /// Get a 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 - /// instead and working with blocks on a chunk-local level. + /// instead and working with blocks on a chunk-local level. public new BlockManager GetBlockManager () { return GetBlockManagerVirt(Dimension.DEFAULT) as BlockManager; @@ -61,31 +61,31 @@ namespace Substrate /// A tied to the given dimension in this world. /// Get a 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 - /// instead and working with blocks on a chunk-local level. + /// instead and working with blocks on a chunk-local level. public new BlockManager GetBlockManager (int dim) { return GetBlockManagerVirt(dim) as BlockManager; } /// - /// Gets a for the default dimension. + /// Gets a for the default dimension. /// - /// A tied to the default dimension in this world. - /// Get a if you you need to work with easily-digestible, bounded chunks of blocks. - public new ChunkManager GetChunkManager () + /// A tied to the default dimension in this world. + /// Get a if you you need to work with easily-digestible, bounded chunks of blocks. + public new BetaChunkManager GetChunkManager () { - return GetChunkManagerVirt(Dimension.DEFAULT) as ChunkManager; + return GetChunkManagerVirt(Dimension.DEFAULT) as BetaChunkManager; } /// - /// Gets a for the given dimension. + /// Gets a for the given dimension. /// /// The id of the dimension to look up. - /// A tied to the given dimension in this world. - /// Get a if you you need to work with easily-digestible, bounded chunks of blocks. - public new ChunkManager GetChunkManager (int dim) + /// A tied to the given dimension in this world. + /// Get a if you you need to work with easily-digestible, bounded chunks of blocks. + public new BetaChunkManager GetChunkManager (int dim) { - return GetChunkManagerVirt(dim) as ChunkManager; + return GetChunkManagerVirt(dim) as BetaChunkManager; } /// @@ -93,7 +93,7 @@ namespace Substrate /// /// A tied to the defaul dimension in this world. /// Regions are a higher-level unit of organization for blocks unique to worlds created in Beta 1.3 and beyond. - /// Consider using the if you are interested in working with blocks. + /// Consider using the if you are interested in working with blocks. public RegionManager GetRegionManager () { return GetRegionManager(Dimension.DEFAULT); @@ -105,7 +105,7 @@ namespace Substrate /// The id of the dimension to look up. /// A tied to the given dimension in this world. /// Regions are a higher-level unit of organization for blocks unique to worlds created in Beta 1.3 and beyond. - /// Consider using the if you are interested in working with blocks. + /// Consider using the if you are interested in working with blocks. public RegionManager GetRegionManager (int dim) { RegionManager rm; @@ -134,7 +134,7 @@ namespace Substrate { _level.Save(); - foreach (KeyValuePair cm in _chunkMgrs) { + foreach (KeyValuePair cm in _chunkMgrs) { cm.Value.Save(); } } @@ -144,7 +144,7 @@ namespace Substrate /// /// The path to the directory containing the world's level.dat, or the path to level.dat itself. /// A new object representing an existing world on disk. - 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 /// 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; diff --git a/Substrate/SubstrateCS/Source/BlockInfo.cs b/Substrate/SubstrateCS/Source/BlockInfo.cs index 0fe59e3..48cb416 100644 --- a/Substrate/SubstrateCS/Source/BlockInfo.cs +++ b/Substrate/SubstrateCS/Source/BlockInfo.cs @@ -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"); diff --git a/Substrate/SubstrateCS/Source/Core/BlockInterface.cs b/Substrate/SubstrateCS/Source/Core/BlockInterface.cs index 9b803e3..eb4dd91 100644 --- a/Substrate/SubstrateCS/Source/Core/BlockInterface.cs +++ b/Substrate/SubstrateCS/Source/Core/BlockInterface.cs @@ -10,52 +10,163 @@ namespace Substrate.Core SOUTH = 3 } + /// + /// A basic block type. + /// public interface IBlock { + /// + /// Gets a variety of info and attributes on the block's type. + /// BlockInfo Info { get; } + + /// + /// Gets or sets the block's id (type). + /// int ID { get; set; } } + /// + /// A block type supporting a data field. + /// public interface IDataBlock : IBlock { + /// + /// Gets or sets a data value on the block. + /// int Data { get; set; } } + /// + /// A block type supporting dual-source lighting. + /// public interface ILitBlock : IBlock { + /// + /// Gets or sets the block-source light value on this block. + /// int BlockLight { get; set; } + + /// + /// Gets or sets the sky-source light value on this block. + /// int SkyLight { get; set; } } + /// + /// A block type supporting properties. + /// public interface IPropertyBlock : IBlock { + /// + /// Gets a tile entity attached to this block. + /// + /// A for this block, or null if this block type does not support a tile entity. TileEntity GetTileEntity (); + + /// + /// Sets the tile entity attached to this block. + /// + /// A supported by this block type. + /// Thrown when the being passed is of the wrong type for the given block. + /// Thrown when the given block is of a type that does not support a record. void SetTileEntity (TileEntity te); + + /// + /// Creates a default tile entity for this block consistent with its type. + /// + /// This method will overwrite any existing attached to the block. + /// Thrown when the given block is of a type that does not support a record. + /// Thrown when the block type requests a that has not been registered with the . + void CreateTileEntity (); + + /// + /// Deletes the tile entity attached to this block if one exists. + /// void ClearTileEntity (); } + /// + /// An Alpha-compatible context-free block type supporting data and properties. + /// public interface IAlphaBlock : IDataBlock, IPropertyBlock { } + /// + /// An Alpha-compatible block reference type supporting data, lighting, and properties. + /// public interface IAlphaBlockRef : IDataBlock, ILitBlock, IPropertyBlock { + /// + /// Checks if the reference and its backing container are currently valid. + /// bool IsValid { get; } } + /// + /// A basic unconstrained container of blocks. + /// public interface IBlockCollection { + /// + /// Gets a basic block from a block container.. + /// + /// The X-coordinate of a block. + /// The Y-coordinate of a block. + /// The Z-coordinate of a block. + /// A basic from the collection at the given coordinates. IBlock GetBlock (int x, int y, int z); + + /// + /// Gets a reference object to a basic within a block container. + /// + /// The X-coordinate of a block. + /// The Y-coordinate of a block. + /// The Z-coordinate of a block. + /// A basic acting as a reference directly into the container at the given coordinates. IBlock GetBlockRef (int x, int y, int z); + /// + /// Updates a block in a block container with data from an existing object. + /// + /// The X-coordinate of a block. + /// The Y-coordinate of a block. + /// The Z-coordinate of a block. + /// The to copy basic data from. void SetBlock (int x, int y, int z, IBlock block); + /// + /// Gets a block's id (type) from a block container. + /// + /// The X-coordinate of a block. + /// The Y-coordinate of a block. + /// The Z-coordinate of a block. + /// The block id (type) from the block container at the given coordinates. int GetID (int x, int y, int z); + + /// + /// Sets a block's id (type) within a block container. + /// + /// The X-coordinate of a block. + /// The Y-coordinate of a block. + /// The Z-coordinate of a block. + /// The id (type) to assign to a block at the given coordinates. void SetID (int x, int y, int z, int id); + /// + /// Gets info and attributes on a block's type within a block container. + /// + /// The X-coordinate of a block. + /// The Y-coordinate of a block. + /// The Z-coordinate of a block. + /// A instance for the block's type. BlockInfo GetInfo (int x, int y, int z); } + /// + /// A container of blocks with set dimensions. + /// public interface IBoundedBlockCollection : IBlockCollection { int XDim { get; } @@ -65,6 +176,9 @@ namespace Substrate.Core int CountByID (int id); } + /// + /// An unbounded container of blocks supporting data fields. + /// 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); } + /// + /// A bounded version of the interface. + /// public interface IBoundedDataBlockCollection : IDataBlockCollection, IBoundedBlockCollection { int CountByData (int id, int data); } + /// + /// An unbounded container of blocks supporting dual-source lighting. + /// public interface ILitBlockCollection : IBlockCollection { new ILitBlock GetBlock (int x, int y, int z); @@ -103,6 +223,9 @@ namespace Substrate.Core void UpdateSkyLight (int x, int y, int z); } + /// + /// A bounded version of the interface. + /// public interface IBoundedLitBlockCollection : ILitBlockCollection, IBoundedBlockCollection { // Zero out light in entire collection @@ -122,6 +245,9 @@ namespace Substrate.Core void StitchSkyLight (IBoundedLitBlockCollection blockset, BlockCollectionEdge edge); } + /// + /// An unbounded container for blocks supporting additional properties. + /// public interface IPropertyBlockCollection : IBlockCollection { new IPropertyBlock GetBlock (int x, int y, int z); @@ -136,10 +262,16 @@ namespace Substrate.Core void ClearTileEntity (int x, int y, int z); } + /// + /// A bounded version of the interface. + /// public interface IBoundedPropertyBlockCollection : IPropertyBlockCollection, IBoundedBlockCollection { } + /// + /// An unbounded container of blocks supporting data, lighting, and properties. + /// public interface IAlphaBlockCollection : IDataBlockCollection, ILitBlockCollection, IPropertyBlockCollection { new AlphaBlock GetBlock (int x, int y, int z); @@ -148,10 +280,16 @@ namespace Substrate.Core void SetBlock (int x, int y, int z, AlphaBlock block); } + /// + /// A bounded version of the interface. + /// public interface IBoundedAlphaBlockCollection : IAlphaBlockCollection, IBoundedDataBlockCollection, IBoundedLitBlockCollection, IBoundedPropertyBlockCollection { } + /// + /// Provides a common interface for block containers that provide global management. + /// public interface IBlockManager : IAlphaBlockCollection { } diff --git a/Substrate/SubstrateCS/Source/Core/ChunkInterface.cs b/Substrate/SubstrateCS/Source/Core/ChunkInterface.cs index cf4bc80..78e2772 100644 --- a/Substrate/SubstrateCS/Source/Core/ChunkInterface.cs +++ b/Substrate/SubstrateCS/Source/Core/ChunkInterface.cs @@ -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); - }*/ - + /// + /// Provides a common interface for accessing Alpha-compatible chunk data. + /// public interface IChunk { + /// + /// Gets the global X-coordinate of a chunk. + /// int X { get; } + + /// + /// Gets the global Z-coordinate of a chunk. + /// int Z { get; } + /// + /// Gets access to an representing all block data of a chunk. + /// AlphaBlockCollection Blocks { get; } + + /// + /// Gets access to an representing all entity data of a chunk. + /// EntityCollection Entities { get; } + /// + /// Gets or sets the flag indicating that the terrain generator has created terrain features. + /// + /// Terrain features include ores, water and lava sources, dungeons, trees, flowers, etc. bool IsTerrainPopulated { get; set; } + /// + /// Writes out the chunk's data to an output stream. + /// + /// A valid, open output stream. + /// True if the chunk could be saved; false otherwise. bool Save (Stream outStream); } - /*public interface IChunkCache - { - bool MarkChunkDirty (ChunkRef chunk); - bool MarkChunkClean (ChunkRef chunk); - }*/ - + /// + /// Provides a common interface to any object that acts as a physical or abstract chunk container. + /// public interface IChunkContainer { + /// + /// Returns a global chunk X-coordinate, given a container-defined X-coordinate. + /// + /// An X-coordinate internally assigned to a by a . + /// A corresponding global X-coordinate. + /// This is largely intended for internal use. If an is assigned coordinates by an + /// , the interpretation of those coordinates is ambiguous. This method ensures the coordinate + /// returned is interpreted as a global coordinate. int ChunkGlobalX (int cx); + + /// + /// Returns a global chunk Z-coordinate, given a container-defined Z-coordinate. + /// + /// A Z-coordinate internally assigned to a by a . + /// A corresponding global Z-coordinate. + /// This is largely intended for internal use. If an is assigned coordinates by an + /// , the interpretation of those coordinates is ambiguous. This method ensures the coordinate + /// returned is interpreted as a global coordinate. int ChunkGlobalZ (int cz); + /// + /// Returns a local chunk X-coordinate, given a container-defined X-coordinate. + /// + /// An X-coordinate internally assigned to a by a . + /// A corresponding local X-coordinate. + /// This is largely intended for internal use. If an is assigned coordinates by an + /// , the interpretation of those coordinates is ambiguous. This method ensures the coordinate + /// returned is interpreted as a local coordinate. int ChunkLocalX (int cx); + + /// + /// Returns a local chunk Z-coordinate, given a container-defined Z-coordinate. + /// + /// A Z-coordinate internally assigned to a by a . + /// A corresponding global X-coordinate. + /// This is largely intended for internal use. If an is assigned coordinates by an + /// , the interpretation of those coordinates is ambiguous. This method ensures the coordinate + /// returned is interpreted as a local coordinate. int ChunkLocalZ (int cz); + /// + /// Gets an unwrapped object for the given container-local coordinates. + /// + /// The container-local X-coordinate of a chunk. + /// The container-local Z-coordinate of a chunk. + /// A for the given coordinates, or null if no chunk exists at those coordinates. Chunk GetChunk (int cx, int cz); + + /// + /// Gets a binding a chunk to this container for the given container-local coordinates. + /// + /// The container-local X-coordinate of a chunk. + /// The container-local Z-coordinate of a chunk. + /// A for the given coordinates binding a to this container, or null if + /// no chunk exists at the given coordinates. ChunkRef GetChunkRef (int cx, int cz); + + /// + /// Creates an empty chunk at the given coordinates, if no chunk previously exists. + /// + /// The container-local X-coordinate of a chunk. + /// The container-local Z-coordinate of a chunk. + /// A for the newly created chunk if no previous chunk existed; a + /// to the existing chunk otherwise. + /// This method ensures that an empty/default chunk is written out to the underlying data store before returning. ChunkRef CreateChunk (int cx, int cz); + /// + /// Saves an unwrapped to the container at the given container-local coordinates. + /// + /// The container-local X-coordinate to save the chunk to. + /// The container-local Z-coordinate to save the chunk to. + /// The to save at the given coordinates. + /// A binding to this container at the given location. + /// The 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 + /// has a handle to the argument, or an inconsistency could develop where the chunk held by the + /// other is written to the underlying data store with invalid coordinates. + /// The specification is designed to avoid this situation from occuring, but + /// class hierarchy extensions could violate these safeguards. ChunkRef SetChunk (int cx, int cz, Chunk chunk); + /// + /// Checks if a chunk exists at the given container-local coordinates. + /// + /// The container-local X-coordinate of a chunk. + /// The container-local Z-coordinate of a chunk. + /// True if a chunk exists at the given coordinates; false otherwise. bool ChunkExists (int cx, int cz); + /// + /// Deletes a chunk at the given container-local coordinates if it exists. + /// + /// The container-local X-coordinate of a chunk. + /// The container-local Z-coordinate of a chunk. + /// True if a chunk existed and was deleted; false otherwise. bool DeleteChunk (int cx, int cz); + /// + /// Saves any chunks in the container that currently have unsaved changes. + /// + /// The number of chunks that were saved. + /// 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. int Save (); + + // TODO: Check that this doesn't violate borders + /// bool SaveChunk (Chunk chunk); + + /// + /// Checks if this container supports delegating an action on out-of-bounds coordinates to another container. + /// + /// If a container does not support this property, it is expected to throw + /// for any action on out-of-bounds coordinates. + bool CanDelegateCoordinates { get; } } + /// + /// Provides a common interface for chunk containers that provide global management. + /// public interface IChunkManager : IChunkContainer, IEnumerable { diff --git a/Substrate/SubstrateCS/Source/Core/RegionFile.cs b/Substrate/SubstrateCS/Source/Core/RegionFile.cs index 349b755..b459afb 100644 --- a/Substrate/SubstrateCS/Source/Core/RegionFile.cs +++ b/Substrate/SubstrateCS/Source/Core/RegionFile.cs @@ -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]; diff --git a/Substrate/SubstrateCS/Source/Entities/EntityCreeper.cs b/Substrate/SubstrateCS/Source/Entities/EntityCreeper.cs index c8bd85a..1025339 100644 --- a/Substrate/SubstrateCS/Source/Entities/EntityCreeper.cs +++ b/Substrate/SubstrateCS/Source/Entities/EntityCreeper.cs @@ -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 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(); diff --git a/Substrate/SubstrateCS/Source/Entities/EntityMinecart.cs b/Substrate/SubstrateCS/Source/Entities/EntityMinecart.cs index 88ecb7f..5138038 100644 --- a/Substrate/SubstrateCS/Source/Entities/EntityMinecart.cs +++ b/Substrate/SubstrateCS/Source/Entities/EntityMinecart.cs @@ -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; } diff --git a/Substrate/SubstrateCS/Source/Entities/EntityPainting.cs b/Substrate/SubstrateCS/Source/Entities/EntityPainting.cs index 43c4185..c48efc9 100644 --- a/Substrate/SubstrateCS/Source/Entities/EntityPainting.cs +++ b/Substrate/SubstrateCS/Source/Entities/EntityPainting.cs @@ -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; } diff --git a/Substrate/SubstrateCS/Source/Entities/EntityPigZombie.cs b/Substrate/SubstrateCS/Source/Entities/EntityPigZombie.cs index 220e1cf..6ecf578 100644 --- a/Substrate/SubstrateCS/Source/Entities/EntityPigZombie.cs +++ b/Substrate/SubstrateCS/Source/Entities/EntityPigZombie.cs @@ -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 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(); diff --git a/Substrate/SubstrateCS/Source/Region.cs b/Substrate/SubstrateCS/Source/Region.cs index 9288226..ff3512e 100644 --- a/Substrate/SubstrateCS/Source/Region.cs +++ b/Substrate/SubstrateCS/Source/Region.cs @@ -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 /// A at the given local coordinates, or null if no chunk exists. /// 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 to perform a similar task to , but with a + /// instead. This allows any to perform a similar task to , but with a /// region-local frame of reference instead of a global frame of reference. 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 /// The global X-coordinate of the corresponding chunk. public int ChunkGlobalX (int cx) { - return _rx * ChunkManager.REGION_XLEN + cx; + return _rx * XDIM + cx; } /// /// Gets the global Z-coordinate of a chunk given an internal coordinate handed out by a container. /// - /// An internal Z-coordinate given to a by any instance of a container. + /// An internal Z-coordinate given to a by any instance of a container. /// The global Z-coordinate of the corresponding chunk. public int ChunkGlobalZ (int cz) { - return _rz * ChunkManager.REGION_ZLEN + cz; + return _rz * ZDIM + cz; } /// @@ -411,7 +411,7 @@ namespace Substrate /// /// Gets the region-local Z-coordinate of a chunk given an internal coordinate handed out by a container. /// - /// An internal Z-coordinate given to a by any instance of a container. + /// An internal Z-coordinate given to a by any instance of a container. /// The region-local Z-coordinate of the corresponding chunk. 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) diff --git a/Substrate/SubstrateCS/Source/RegionManager.cs b/Substrate/SubstrateCS/Source/RegionManager.cs index e0a065e..c8e7a6e 100644 --- a/Substrate/SubstrateCS/Source/RegionManager.cs +++ b/Substrate/SubstrateCS/Source/RegionManager.cs @@ -6,15 +6,22 @@ using Substrate.Core; namespace Substrate { - + /// + /// Manages the regions of a Beta-compatible world. + /// public class RegionManager : IRegionManager { - protected string _regionPath; + private string _regionPath; - protected Dictionary _cache; + private Dictionary _cache; - protected ChunkCache _chunkCache; + private ChunkCache _chunkCache; + /// + /// Creates a new instance of a for the given region directory and chunk cache. + /// + /// The path to a directory containing region files. + /// The shared chunk cache to hold chunk data in. public RegionManager (string regionDir, ChunkCache cache) { _regionPath = regionDir; @@ -22,6 +29,12 @@ namespace Substrate _cache = new Dictionary(); } + /// + /// Gets a at the given coordinates. + /// + /// The global X-coordinate of a region. + /// The global Z-coordinate of a region. + /// A representing a region at the given coordinates, or null if the region does not exist. public Region GetRegion (int rx, int rz) { RegionKey k = new RegionKey(rx, rz); @@ -40,12 +53,24 @@ namespace Substrate } } + /// + /// Determines if a region exists at the given coordinates. + /// + /// The global X-coordinate of a region. + /// The global Z-coordinate of a region. + /// True if a region exists at the given global region coordinates; false otherwise. public bool RegionExists (int rx, int rz) { Region r = GetRegion(rx, rz); return r != null; } + /// + /// Creates a new empty region at the given coordinates, if no region exists. + /// + /// The global X-coordinate of a region. + /// The global Z-coordinate of a region. + /// A new empty object for the given coordinates, or an existing if one exists. public Region CreateRegion (int rx, int rz) { Region r = GetRegion(rx, rz); @@ -64,7 +89,11 @@ namespace Substrate return r; } - + /// + /// Gets a for the given region filename. + /// + /// The filename of the region to get. + /// A corresponding to the coordinates encoded in the filename. public Region GetRegion (string filename) { int rx, rz; @@ -75,12 +104,22 @@ namespace Substrate return GetRegion(rx, rz); } - + /// + /// Get the current region directory path. + /// + /// The path to the region directory. public string GetRegionPath () { return _regionPath; } + // XXX: Exceptions + /// + /// Deletes a region at the given coordinates. + /// + /// The global X-coordinate of a region. + /// The global Z-coordinate of a region. + /// True if a region was deleted; false otherwise. 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 Members + /// + /// Returns an enumerator that iterates over all of the regions in the underlying dimension. + /// + /// An enumerator instance. public IEnumerator GetEnumerator () { return new Enumerator(this); @@ -126,6 +158,10 @@ namespace Substrate #region IEnumerable Members + /// + /// Returns an enumerator that iterates over all of the regions in the underlying dimension. + /// + /// An enumerator instance. IEnumerator IEnumerable.GetEnumerator () { return new Enumerator(this); @@ -139,12 +175,6 @@ namespace Substrate private List _regions; private int _pos; - /*public Enumerator (List regs) - { - _regions = regs; - _pos = -1; - }*/ - public Enumerator (RegionManager rm) { _regions = new List(); diff --git a/Substrate/SubstrateCS/Source/TileEntities/TileEntityPiston.cs b/Substrate/SubstrateCS/Source/TileEntities/TileEntityPiston.cs new file mode 100644 index 0000000..d140819 --- /dev/null +++ b/Substrate/SubstrateCS/Source/TileEntities/TileEntityPiston.cs @@ -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 Members + + public override TileEntity Copy () + { + return new TileEntityPiston(this); + } + + #endregion + + + #region INBTObject 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 + } +} \ No newline at end of file diff --git a/Substrate/SubstrateCS/Substrate.csproj b/Substrate/SubstrateCS/Substrate.csproj index 07c0e9b..8c97685 100644 --- a/Substrate/SubstrateCS/Substrate.csproj +++ b/Substrate/SubstrateCS/Substrate.csproj @@ -63,6 +63,7 @@ + @@ -123,10 +124,9 @@ - + - @@ -170,6 +170,7 @@ +