using System; using System.Collections; using System.Collections.Generic; using System.IO; using Substrate.Core; namespace Substrate.Core { /// /// Manages the regions of a Beta-compatible world. /// public abstract class RegionManager : IRegionManager { protected string _regionPath; protected Dictionary _cache; protected ChunkCache _chunkCache; protected abstract IRegion CreateRegionCore (int rx, int rz); protected abstract RegionFile CreateRegionFileCore (int rx, int rz); protected abstract void DeleteRegionCore (IRegion region); public abstract IRegion GetRegion (string filename); /// /// 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; _chunkCache = cache; _cache = new Dictionary(); } /// public IRegion GetRegion (int rx, int rz) { RegionKey k = new RegionKey(rx, rz); IRegion r; try { if (_cache.TryGetValue(k, out r) == false) { r = CreateRegionCore(rx, rz); _cache.Add(k, r); } return r; } catch (FileNotFoundException) { _cache.Add(k, null); return null; } } /// public bool RegionExists (int rx, int rz) { IRegion r = GetRegion(rx, rz); return r != null; } /// public IRegion CreateRegion (int rx, int rz) { IRegion r = GetRegion(rx, rz); if (r == null) { string fp = "r." + rx + "." + rz + ".mca"; using (RegionFile rf = CreateRegionFileCore(rx, rz)) { } r = CreateRegionCore(rx, rz); RegionKey k = new RegionKey(rx, rz); _cache[k] = r; } return r; } /// /// Get the current region directory path. /// /// The path to the region directory. public string GetRegionPath () { return _regionPath; } // XXX: Exceptions /// public bool DeleteRegion (int rx, int rz) { IRegion r = GetRegion(rx, rz); if (r == null) { return false; } RegionKey k = new RegionKey(rx, rz); _cache.Remove(k); DeleteRegionCore(r); try { File.Delete(r.GetFilePath()); } catch (Exception e) { Console.WriteLine("NOTICE: " + e.Message); return false; } return true; } #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); } #endregion #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); } #endregion private struct Enumerator : IEnumerator { private List _regions; private int _pos; public Enumerator (RegionManager rm) { _regions = new List(); _pos = -1; if (!Directory.Exists(rm.GetRegionPath())) { throw new DirectoryNotFoundException(); } string[] files = Directory.GetFiles(rm.GetRegionPath()); _regions.Capacity = files.Length; foreach (string file in files) { try { IRegion r = rm.GetRegion(file); _regions.Add(r); } catch (ArgumentException) { continue; } } } public bool MoveNext () { _pos++; return (_pos < _regions.Count); } public void Reset () { _pos = -1; } void IDisposable.Dispose () { } object IEnumerator.Current { get { return Current; } } IRegion IEnumerator.Current { get { return Current; } } public IRegion Current { get { try { return _regions[_pos]; } catch (IndexOutOfRangeException) { throw new InvalidOperationException(); } } } } } }