using System; using System.Collections.Generic; using System.Text; using System.IO; using Substrate.Nbt; using System.Text.RegularExpressions; namespace Substrate.Data { /// /// Functions to manage all data resources. /// /// This manager is intended for map files stored in standard compressed NBT format. public class MapManager : IMapManager, IEnumerable { private NbtWorld _world; /// /// Create a new for a given world. /// /// World containing data files. public MapManager (NbtWorld world) { _world = world; } /// /// Gets a representing the backing NBT data stream. /// /// The id of the map to fetch. /// A for the given map. protected MapFile GetMapFile (int id) { return new MapFile(Path.Combine(_world.Path, _world.DataDirectory), id); } /// /// Gets a raw of data for the given map. /// /// The id of the map to fetch. /// An containing the given map's raw data. /// Thrown when the manager cannot read in an NBT data stream. public NbtTree GetMapTree (int id) { MapFile mf = GetMapFile(id); Stream nbtstr = mf.GetDataInputStream(); if (nbtstr == null) { throw new NbtIOException("Failed to initialize NBT data stream for input."); } return new NbtTree(nbtstr); } /// /// Saves a raw representing a map to the given map's file. /// /// The id of the map to write data to. /// The map's data as an . /// Thrown when the manager cannot initialize an NBT data stream for output. public void SetMapTree (int id, NbtTree tree) { MapFile mf = GetMapFile(id); Stream zipstr = mf.GetDataOutputStream(); if (zipstr == null) { throw new NbtIOException("Failed to initialize NBT data stream for output."); } tree.WriteTo(zipstr); zipstr.Close(); } #region IMapManager Members /// /// Thrown when the manager cannot read in a map that should exist. public Map GetMap (int id) { if (!MapExists(id)) { return null; } try { Map m = new Map().LoadTreeSafe(GetMapTree(id).Root); m.Id = id; return m; } catch (Exception ex) { DataIOException pex = new DataIOException("Could not load map", ex); pex.Data["MapId"] = id; throw pex; } } /// /// Thrown when the manager cannot write out the map public void SetMap (int id, Map map) { try { SetMapTree(id, new NbtTree(map.BuildTree() as TagNodeCompound)); } catch (Exception ex) { DataIOException pex = new DataIOException("Could not save map", ex); pex.Data["MapId"] = id; throw pex; } } /// /// Saves a object's data back to file given the id set in the object. /// /// The object containing the data to write back. /// Thrown when the manager cannot write out the map public void SetMap (Map map) { SetMap(map.Id, map); } /// public bool MapExists (int id) { return new MapFile(Path.Combine(_world.Path, _world.DataDirectory), id).Exists(); } /// /// Thrown when the manager cannot delete the map. public void DeleteMap (int id) { try { new MapFile(Path.Combine(_world.Path, _world.DataDirectory), id).Delete(); } catch (Exception ex) { DataIOException pex = new DataIOException("Could not remove map", ex); pex.Data["MapId"] = id; throw pex; } } #endregion #region IEnumerable Members /// /// Gets an enumerator that iterates through all the maps in the world's data directory. /// /// An enumerator for this manager. public IEnumerator GetEnumerator () { string path = Path.Combine(_world.Path, _world.DataDirectory); if (!Directory.Exists(path)) { throw new DirectoryNotFoundException(); } string[] files = Directory.GetFiles(path); foreach (string file in files) { string basename = Path.GetFileName(file); if (!ParseFileName(basename)) { continue; } int id = MapFile.IdFromFilename(basename); yield return GetMap(id); } } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () { return GetEnumerator(); } #endregion private bool ParseFileName (string filename) { Match match = _namePattern.Match(filename); if (!match.Success) { return false; } return true; } private static Regex _namePattern = new Regex("^map_[0-9]+\\.dat$"); } }