From 895178d5d39043ab24054db6985d6e9ecf29e9bc Mon Sep 17 00:00:00 2001 From: Justin Aquadro Date: Sun, 3 Apr 2011 08:40:27 +0000 Subject: [PATCH] Chunk caching moved into regions, region is now the primary chunk container of chunkrefs. Caching seems to have degraded with the transition, may need to implement explicit caching. --- NBToolkit/NBToolkit/Map/Block.cs | 13 -- NBToolkit/NBToolkit/Map/BlockInterface.cs | 52 ++++++ NBToolkit/NBToolkit/Map/BlockManager.cs | 16 +- NBToolkit/NBToolkit/Map/BlockRef.cs | 10 +- NBToolkit/NBToolkit/Map/Chunk.cs | 59 +------ NBToolkit/NBToolkit/Map/ChunkInterface.cs | 47 ++++++ NBToolkit/NBToolkit/Map/ChunkManager.cs | 182 +++++++++----------- NBToolkit/NBToolkit/Map/ChunkRef.cs | 78 ++++----- NBToolkit/NBToolkit/Map/Region.cs | 193 ++++++++++++++++------ 9 files changed, 366 insertions(+), 284 deletions(-) create mode 100644 NBToolkit/NBToolkit/Map/BlockInterface.cs create mode 100644 NBToolkit/NBToolkit/Map/ChunkInterface.cs diff --git a/NBToolkit/NBToolkit/Map/Block.cs b/NBToolkit/NBToolkit/Map/Block.cs index e1027e7..40baf9a 100644 --- a/NBToolkit/NBToolkit/Map/Block.cs +++ b/NBToolkit/NBToolkit/Map/Block.cs @@ -7,19 +7,6 @@ namespace NBToolkit.Map using NBT; using Utility; - public interface IBlock - { - BlockInfo Info { get; } - int ID { get; set; } - int Data { get; set; } - int BlockLight { get; set; } - int SkyLight { get; set; } - - TileEntity GetTileEntity (); - bool SetTileEntity (TileEntity te); - bool ClearTileEntity (); - } - public class Block : IBlock, ICopyable { private int _id; diff --git a/NBToolkit/NBToolkit/Map/BlockInterface.cs b/NBToolkit/NBToolkit/Map/BlockInterface.cs new file mode 100644 index 0000000..1facac9 --- /dev/null +++ b/NBToolkit/NBToolkit/Map/BlockInterface.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NBToolkit.Map +{ + + public interface IBlock + { + BlockInfo Info { get; } + int ID { get; set; } + int Data { get; set; } + int BlockLight { get; set; } + int SkyLight { get; set; } + + TileEntity GetTileEntity (); + bool SetTileEntity (TileEntity te); + bool ClearTileEntity (); + } + + public interface IBlockContainer + { + int BlockGlobalX (int x); + int BlockGlobalY (int y); + int BlockGlobalZ (int z); + + int BlockLocalX (int x); + int BlockLocalY (int y); + int BlockLocalZ (int z); + + Block GetBlock (int lx, int ly, int lz); + BlockRef GetBlockRef (int lx, int ly, int lz); + + BlockInfo GetBlockInfo (int lx, int ly, int lz); + + int GetBlockID (int lx, int ly, int lz); + int GetBlockData (int lx, int ly, int lz); + int GetBlockLight (int lx, int ly, int lz); + int GetBlockSkyLight (int lx, int ly, int lz); + + void SetBlock (int lx, int ly, int lz, Block block); + + bool SetBlockID (int lx, int ly, int lz, int id); + bool SetBlockData (int lx, int ly, int lz, int data); + bool SetBlockLight (int lx, int ly, int lz, int light); + bool SetBlockSkyLight (int lx, int ly, int lz, int light); + + TileEntity GetTileEntity (int lx, int ly, int lz); + bool SetTileEntity (int lx, int ly, int lz, TileEntity te); + bool ClearTileEntity (int lx, int ly, int lz); + } +} diff --git a/NBToolkit/NBToolkit/Map/BlockManager.cs b/NBToolkit/NBToolkit/Map/BlockManager.cs index fa603a3..b4253e1 100644 --- a/NBToolkit/NBToolkit/Map/BlockManager.cs +++ b/NBToolkit/NBToolkit/Map/BlockManager.cs @@ -50,32 +50,32 @@ namespace NBToolkit.Map _chunkMan = bm._chunkMan; } - public int GlobalX (int x) + public int BlockGlobalX (int x) { return x; } - public int GlobalY (int y) + public int BlockGlobalY (int y) { return y; } - public int GlobalZ (int z) + public int BlockGlobalZ (int z) { return z; } - public int LocalX (int x) + public int BlockLocalX (int x) { return x & CHUNK_XMASK; } - public int LocalY (int y) + public int BlockLocalY (int y) { return y & CHUNK_YMASK; } - public int LocalZ (int z) + public int BlockLocalZ (int z) { return z & CHUNK_ZMASK; } @@ -87,7 +87,7 @@ namespace NBToolkit.Map return null; } - return new Block(_cache, x & CHUNK_XMASK, y, z & CHUNK_ZMASK); + return _cache.GetBlock(x & CHUNK_XMASK, y, z & CHUNK_ZMASK); } public virtual BlockRef GetBlockRef (int x, int y, int z) @@ -97,7 +97,7 @@ namespace NBToolkit.Map return null; } - return new BlockRef(_cache, x, y, z); + return _cache.GetBlockRef(x & CHUNK_XMASK, y, z & CHUNK_ZMASK); } public virtual BlockInfo GetBlockInfo (int x, int y, int z) diff --git a/NBToolkit/NBToolkit/Map/BlockRef.cs b/NBToolkit/NBToolkit/Map/BlockRef.cs index ca4a3c3..eaaa198 100644 --- a/NBToolkit/NBToolkit/Map/BlockRef.cs +++ b/NBToolkit/NBToolkit/Map/BlockRef.cs @@ -14,27 +14,27 @@ namespace NBToolkit.Map public int X { - get { return _container.GlobalX(_x); } + get { return _container.BlockGlobalX(_x); } } public int Y { - get { return _container.GlobalY(_y); } + get { return _container.BlockGlobalY(_y); } } public int Z { - get { return _container.GlobalZ(_z); } + get { return _container.BlockGlobalZ(_z); } } public int LocalX { - get { return _container.LocalX(_x); } + get { return _container.BlockLocalX(_x); } } public int LocalY { - get { return _container.LocalZ(_z); } + get { return _container.BlockLocalZ(_z); } } public int LocalZ diff --git a/NBToolkit/NBToolkit/Map/Chunk.cs b/NBToolkit/NBToolkit/Map/Chunk.cs index 39838d0..a986704 100644 --- a/NBToolkit/NBToolkit/Map/Chunk.cs +++ b/NBToolkit/NBToolkit/Map/Chunk.cs @@ -6,53 +6,6 @@ namespace NBToolkit.Map using NBT; using Utility; - public interface IBlockContainer - { - int GlobalX (int x); - int GlobalY (int y); - int GlobalZ (int z); - - int LocalX (int x); - int LocalY (int y); - int LocalZ (int z); - - Block GetBlock (int lx, int ly, int lz); - BlockRef GetBlockRef (int lx, int ly, int lz); - - BlockInfo GetBlockInfo (int lx, int ly, int lz); - - int GetBlockID (int lx, int ly, int lz); - int GetBlockData (int lx, int ly, int lz); - int GetBlockLight (int lx, int ly, int lz); - int GetBlockSkyLight (int lx, int ly, int lz); - - void SetBlock (int lx, int ly, int lz, Block block); - - bool SetBlockID (int lx, int ly, int lz, int id); - bool SetBlockData (int lx, int ly, int lz, int data); - bool SetBlockLight (int lx, int ly, int lz, int light); - bool SetBlockSkyLight (int lx, int ly, int lz, int light); - - TileEntity GetTileEntity (int lx, int ly, int lz); - bool SetTileEntity (int lx, int ly, int lz, TileEntity te); - bool ClearTileEntity (int lx, int ly, int lz); - } - - public interface IChunk : IBlockContainer - { - 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 GetHeight (int lx, int lz); - } - public class Chunk : IChunk, ICopyable { private NBT_Tree _tree; @@ -149,32 +102,32 @@ namespace NBToolkit.Map _tree.Root.Add("Level", level); } - public int GlobalX (int x) + public int BlockGlobalX (int x) { return _cx * BlockManager.CHUNK_XLEN + x; } - public int GlobalY (int y) + public int BlockGlobalY (int y) { return y; } - public int GlobalZ (int z) + public int BlockGlobalZ (int z) { return _cz * BlockManager.CHUNK_ZLEN + z; } - public int LocalX (int x) + public int BlockLocalX (int x) { return x; } - public int LocalY (int y) + public int BlockLocalY (int y) { return y; } - public int LocalZ (int z) + public int BlockLocalZ (int z) { return z; } diff --git a/NBToolkit/NBToolkit/Map/ChunkInterface.cs b/NBToolkit/NBToolkit/Map/ChunkInterface.cs new file mode 100644 index 0000000..f560b5b --- /dev/null +++ b/NBToolkit/NBToolkit/Map/ChunkInterface.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NBToolkit.Map +{ + + public interface IChunk : IBlockContainer + { + 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 GetHeight (int lx, int lz); + } + + public interface IChunkCache + { + bool MarkChunkDirty (ChunkRef chunk); + bool MarkChunkClean (int cx, int cz); + } + + public interface IChunkContainer + { + int ChunkGlobalX (int cx); + int ChunkGlobalZ (int cz); + + int ChunkLocalX (int cx); + int ChunkLocalZ (int cz); + + Chunk GetChunk (int cx, int cz); + ChunkRef GetChunkRef (int cx, int cz); + + bool ChunkExists (int cx, int cz); + + bool DeleteChunk (int cx, int cz); + + int Save (); + bool SaveChunk (Chunk chunk); + } +} diff --git a/NBToolkit/NBToolkit/Map/ChunkManager.cs b/NBToolkit/NBToolkit/Map/ChunkManager.cs index 59f5eb3..1c22326 100644 --- a/NBToolkit/NBToolkit/Map/ChunkManager.cs +++ b/NBToolkit/NBToolkit/Map/ChunkManager.cs @@ -4,27 +4,8 @@ using System.Text; namespace NBToolkit.Map { - public interface IChunkManager - { - Chunk GetChunk (int cx, int cz); - ChunkRef GetChunkRef (int cx, int cz); - bool ChunkExists (int cx, int cz); - - bool MarkChunkDirty (int cx, int cz); - bool MarkChunkClean (int cx, int cz); - - int Save (); - bool Save (Chunk chunk); - - ChunkRef CreateChunk (int cx, int cz); - bool DeleteChunk (int cx, int cz); - - bool CopyChunk (int cx1, int cz1, int cx2, int cz2); - bool MoveChunk (int cx1, int cz1, int cx2, int cz2); - } - - public class ChunkManager + public class ChunkManager : IChunkContainer, IChunkCache { public const int REGION_XLEN = 32; public const int REGION_ZLEN = 32; @@ -37,55 +18,54 @@ namespace NBToolkit.Map protected RegionManager _regionMan; - protected Dictionary _cache; - protected Dictionary _dirty; + protected Dictionary _cache; + protected Dictionary _dirty; public ChunkManager (RegionManager rm) { _regionMan = rm; - _cache = new Dictionary(); - _dirty = new Dictionary(); + _cache = new Dictionary(); + _dirty = new Dictionary(); + } + + 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) { - int lcx = cx & REGION_XMASK; - int lcz = cz & REGION_ZMASK; - Region r = GetRegion(cx, cz); - if (r == null || !r.ChunkExists(lcx, lcz)) { + if (r == null) { return null; } - return new Chunk(r.GetChunkTree(lcx, lcz)); + return r.GetChunk(cx & REGION_XMASK, cz & REGION_ZMASK); } public ChunkRef GetChunkRef (int cx, int cz) { - ChunkKey k = new ChunkKey(cx, cz); - - ChunkRef c = null; - - WeakReference chunkref = null; - if (_cache.TryGetValue(k, out chunkref)) { - c = chunkref.Target as ChunkRef; - } - else { - _cache.Add(k, new WeakReference(null)); - } - - if (c != null) { - return c; - } - - try { - c = new ChunkRef(this, cx, cz); - _cache[k].Target = c; - return c; - } - catch (MissingChunkException) { + Region r = GetRegion(cx, cz); + if (r == null) { return null; } + + return r.GetChunkRef(cx & REGION_XMASK, cz & REGION_ZMASK, this); } public bool ChunkExists (int cx, int cz) @@ -98,55 +78,51 @@ namespace NBToolkit.Map return r.ChunkExists(cx & REGION_XMASK, cz & REGION_ZMASK); } - public bool MarkChunkDirty (int cx, int cz) - { - ChunkKey k = new ChunkKey(cx, cz); - if (!_dirty.ContainsKey(k)) { - _dirty.Add(k, GetChunkRef(cx, cz)); - return true; - } - return false; - } - - public bool MarkChunkClean (int cx, int cz) - { - ChunkKey k = new ChunkKey(cx, cz); - if (_dirty.ContainsKey(k)) { - _dirty.Remove(k); - return true; - } - return false; - } - - public int Save () - { - int saved = 0; - foreach (ChunkRef c in _dirty.Values) { - int lcx = ChunkLocalX(c.X); - int lcz = ChunkLocalZ(c.Z); - - Region r = GetRegion(c.X, c.Z); - if (r == null || !r.ChunkExists(lcx, lcz)) { - throw new MissingChunkException(); - } - - if (c.Save(r.GetChunkOutStream(lcx, lcz))) { - saved++; - } - } - - _dirty.Clear(); - return saved; - } - - public bool Save (Chunk chunk) + public bool MarkChunkDirty (ChunkRef chunk) { Region r = GetRegion(chunk.X, chunk.Z); if (r == null) { return false; } - return chunk.Save(r.GetChunkOutStream(chunk.X & REGION_XLEN, chunk.Z & REGION_ZLEN)); + RegionKey k = new RegionKey(r.X, r.Z); + _dirty[k] = r; + + r.MarkChunkDirty(chunk); + + return true; + } + + public bool MarkChunkClean (int cx, int cz) + { + Region r = GetRegion(cx, cz); + if (r == null) { + return false; + } + + RegionKey k = new RegionKey(r.X, r.Z); + return _dirty.Remove(k); + } + + public int Save () + { + int saved = 0; + foreach (Region r in _dirty.Values) { + saved += r.Save(); + } + + _dirty.Clear(); + return saved; + } + + public bool SaveChunk (Chunk chunk) + { + Region r = GetRegion(chunk.X, chunk.Z); + if (r == null) { + return false; + } + + return r.SaveChunk(chunk); } public bool DeleteChunk (int cx, int cz) @@ -160,11 +136,11 @@ namespace NBToolkit.Map return false; } - ChunkKey k = new ChunkKey(cx, cz); - _cache.Remove(k); - _dirty.Remove(k); - if (r.ChunkCount() == 0) { + RegionKey k = new RegionKey(r.X, r.Z); + _cache.Remove(k); + _dirty.Remove(k); + _regionMan.DeleteRegion(r.X, r.Z); } @@ -183,16 +159,6 @@ namespace NBToolkit.Map return GetChunkRef(cx, cz); } - protected int ChunkLocalX (int cx) - { - return cx & REGION_XMASK; - } - - protected int ChunkLocalZ (int cz) - { - return cz & REGION_ZMASK; - } - protected Region GetRegion (int cx, int cz) { cx >>= REGION_XLOG; diff --git a/NBToolkit/NBToolkit/Map/ChunkRef.cs b/NBToolkit/NBToolkit/Map/ChunkRef.cs index 9159dca..d1dbbf5 100644 --- a/NBToolkit/NBToolkit/Map/ChunkRef.cs +++ b/NBToolkit/NBToolkit/Map/ChunkRef.cs @@ -9,7 +9,8 @@ namespace NBToolkit.Map public class ChunkRef : IChunk { - private ChunkManager _chunkMan; + private IChunkContainer _container; + private IChunkCache _cache; private Chunk _chunk; private int _cx; @@ -19,51 +20,62 @@ namespace NBToolkit.Map public int X { - get { return _cx; } + get { return _container.ChunkGlobalX(_cx); } } public int Z { - get { return _cz; } + get { return _container.ChunkGlobalZ(_cz); } } - public ChunkRef (ChunkManager cm, int cx, int cz) + public int LocalX { - _chunkMan = cm; + get { return _container.ChunkLocalX(_cx); } + } + + public int LocalZ + { + get { return _container.ChunkLocalZ(_cz); } + } + + public ChunkRef (IChunkContainer container, IChunkCache cache, int cx, int cz) + { + _container = container; + _cache = cache; _cx = cx; _cz = cz; - if (!_chunkMan.ChunkExists(cx, cz)) { + if (!_container.ChunkExists(cx, cz)) { throw new MissingChunkException(); } } - public int GlobalX (int x) + public int BlockGlobalX (int x) { - return _cx * BlockManager.CHUNK_XLEN + x; + return _container.ChunkGlobalX(_cx) * BlockManager.CHUNK_XLEN + x; } - public int GlobalY (int y) + public int BlockGlobalY (int y) { return y; } - public int GlobalZ (int z) + public int BlockGlobalZ (int z) { - return _cz * BlockManager.CHUNK_ZLEN + z; + return _container.ChunkGlobalZ(_cz) * BlockManager.CHUNK_ZLEN + z; } - public int LocalX (int x) + public int BlockLocalX (int x) { return x; } - public int LocalY (int y) + public int BlockLocalY (int y) { return y; } - public int LocalZ (int z) + public int BlockLocalZ (int z) { return z; } @@ -71,20 +83,11 @@ namespace NBToolkit.Map private Chunk GetChunk () { if (_chunk == null) { - _chunk = _chunkMan.GetChunk(_cx, _cz); + _chunk = _container.GetChunk(_cx, _cz); } return _chunk; } - /*private NBT_Tree GetTree () - { - if (!_chunkMan.ChunkExists(_cx, _cz)) { - throw new MissingChunkException(); - } - - return r.GetChunkTree(LocalX, LocalZ); - }*/ - private bool MarkDirty () { if (_dirty) { @@ -92,45 +95,28 @@ namespace NBToolkit.Map } _dirty = true; - _chunkMan.MarkChunkDirty(_cx, _cz); + _cache.MarkChunkDirty(this); return true; } - /*public bool Save () - { - if (_dirty) { - Region r = _chunkMan.GetRegion(_cx, _cz); - if (r == null || !r.ChunkExists(LocalX, LocalZ)) { - throw new MissingChunkException(); - } - - if (GetChunk().Save(r.GetChunkOutStream(_cx, _cz))) { - _dirty = false; - return true; - } - return false; - } - return true; - }*/ - public ChunkRef GetNorthNeighbor () { - return _chunkMan.GetChunkRef(_cx - 1, _cz); + return _container.GetChunkRef(_cx - 1, _cz); } public ChunkRef GetSouthNeighbor () { - return _chunkMan.GetChunkRef(_cx + 1, _cz); + return _container.GetChunkRef(_cx + 1, _cz); } public ChunkRef GetEastNeighbor () { - return _chunkMan.GetChunkRef(_cx, _cz - 1); + return _container.GetChunkRef(_cx, _cz - 1); } public ChunkRef GetWestNeighbor () { - return _chunkMan.GetChunkRef(_cx, _cz + 1); + return _container.GetChunkRef(_cx, _cz + 1); } public Chunk GetChunkCopy () diff --git a/NBToolkit/NBToolkit/Map/Region.cs b/NBToolkit/NBToolkit/Map/Region.cs index 3815f66..19dcbc1 100644 --- a/NBToolkit/NBToolkit/Map/Region.cs +++ b/NBToolkit/NBToolkit/Map/Region.cs @@ -8,37 +8,7 @@ namespace NBToolkit.Map { using NBT; - public interface IChunkContainer - { - int GlobalX (int cx); - int GlobalZ (int cz); - - int LocalX (int cx); - int LocalZ (int cz); - - Chunk GetChunk (int cx, int cz); - ChunkRef GetChunkRef (int cx, int cz); - - bool ChunkExists (int cx, int cz); - - bool DeleteChunk (int cx, int cz); - - bool Save (); - bool SaveChunk (Chunk chunk); - - bool MarkChunkDirty (int cx, int cz); - bool MarkChunkClean (int cx, int cz); - } - - public interface IRegion : IChunkContainer - { - int X { get; } - int Z { get; } - - int ChunkCount (); - } - - public class Region : IDisposable + public class Region : IDisposable, IChunkContainer, IChunkCache { protected int _rx; protected int _rz; @@ -50,6 +20,9 @@ namespace NBToolkit.Map protected WeakReference _regionFile; + protected Dictionary _cache; + protected Dictionary _dirty; + public int X { get { return _rx; } @@ -67,6 +40,9 @@ namespace NBToolkit.Map _rx = rx; _rz = rz; + _cache = new Dictionary(); + _dirty = new Dictionary(); + if (!File.Exists(GetFilePath())) { throw new FileNotFoundException(); } @@ -112,20 +88,6 @@ namespace NBToolkit.Map _disposed = true; } - public Chunk GetChunk (int lcx, int lcz) - { - if (!ChunkExists(lcx, lcz)) { - return null; - } - - return new Chunk(GetChunkTree(lcx, lcz)); - } - - //public ChunkRef GetChunkRef (int lcx, int lcz) - //{ - - //} - public string GetFileName () { return "r." + _rx + "." + _rz + ".mcr"; @@ -204,12 +166,6 @@ namespace NBToolkit.Map return rf.GetChunkDataOutputStream(lcx, lcz); } - public bool ChunkExists (int lcx, int lcz) - { - RegionFile rf = GetRegionFile(); - return rf.HasChunk(lcx, lcz); - } - public int ChunkCount () { RegionFile rf = GetRegionFile(); @@ -226,6 +182,77 @@ namespace NBToolkit.Map return count; } + public ChunkRef GetChunkRef (int lcx, int lcz, IChunkCache cache) + { + ChunkKey k = new ChunkKey(lcx, lcz); + + ChunkRef c = null; + + WeakReference chunkref = null; + if (_cache.TryGetValue(k, out chunkref)) { + c = chunkref.Target as ChunkRef; + } + else { + _cache.Add(k, new WeakReference(null)); + } + + if (c != null) { + return c; + } + + try { + c = new ChunkRef(this, cache, lcx, lcz); + _cache[k].Target = c; + return c; + } + catch (MissingChunkException) { + return null; + } + } + + + #region IChunkCollection Members + + public int ChunkGlobalX (int cx) + { + return cx; + } + + public int ChunkGlobalZ (int cz) + { + return cz; + } + + public int ChunkLocalX (int cx) + { + return cx & ChunkManager.REGION_XMASK; + } + + public int ChunkLocalZ (int cz) + { + return cz & ChunkManager.REGION_ZMASK; + } + + public Chunk GetChunk (int lcx, int lcz) + { + if (!ChunkExists(lcx, lcz)) { + return null; + } + + return new Chunk(GetChunkTree(lcx, lcz)); + } + + public ChunkRef GetChunkRef (int lcx, int lcz) + { + return GetChunkRef(lcx, lcz, this); + } + + public bool ChunkExists (int lcx, int lcz) + { + RegionFile rf = GetRegionFile(); + return rf.HasChunk(lcx, lcz); + } + public bool DeleteChunk (int lcx, int lcz) { RegionFile rf = GetRegionFile(); @@ -234,7 +261,71 @@ namespace NBToolkit.Map } rf.DeleteChunk(lcx, lcz); + + ChunkKey k = new ChunkKey(lcx, lcz); + _cache.Remove(k); + _dirty.Remove(k); + + if (ChunkCount() == 0) { + _regionMan.DeleteRegion(X, Z); + } + return true; } + + public int Save () + { + int saved = 0; + foreach (ChunkRef c in _dirty.Values) { + int lcx = ChunkLocalX(c.X); + int lcz = ChunkLocalZ(c.Z); + + if (!ChunkExists(lcx, lcz)) { + throw new MissingChunkException(); + } + + if (c.Save(GetChunkOutStream(lcx, lcz))) { + saved++; + } + } + + _dirty.Clear(); + return saved; + } + + public bool SaveChunk (Chunk chunk) + { + return chunk.Save(GetChunkOutStream(ChunkLocalX(chunk.X), ChunkLocalZ(chunk.Z))); + } + + #endregion + + + #region IChunkCache Members + + public bool MarkChunkDirty (ChunkRef chunk) + { + int lcx = chunk.LocalX; + int lcz = chunk.LocalZ; + + ChunkKey k = new ChunkKey(lcx, lcz); + if (!_dirty.ContainsKey(k)) { + _dirty.Add(k, GetChunkRef(lcx, lcz)); + return true; + } + return false; + } + + public bool MarkChunkClean (int lcx, int lcz) + { + ChunkKey k = new ChunkKey(lcx, lcz); + if (_dirty.ContainsKey(k)) { + _dirty.Remove(k); + return true; + } + return false; + } + + #endregion } }