forked from mirrors/NBTExplorer
190 lines
6.3 KiB
C#
190 lines
6.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.IO;
|
|
using Substrate.Nbt;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace Substrate.Data
|
|
{
|
|
/// <summary>
|
|
/// Functions to manage all <see cref="Map"/> data resources.
|
|
/// </summary>
|
|
/// <remarks>This manager is intended for map files stored in standard compressed NBT format.</remarks>
|
|
public class MapManager : IMapManager, IEnumerable<Map>
|
|
{
|
|
private NbtWorld _world;
|
|
|
|
/// <summary>
|
|
/// Create a new <see cref="MapManager"/> for a given world.
|
|
/// </summary>
|
|
/// <param name="world">World containing data files.</param>
|
|
public MapManager (NbtWorld world)
|
|
{
|
|
_world = world;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a <see cref="MapFile"/> representing the backing NBT data stream.
|
|
/// </summary>
|
|
/// <param name="id">The id of the map to fetch.</param>
|
|
/// <returns>A <see cref="MapFile"/> for the given map.</returns>
|
|
protected MapFile GetMapFile (int id)
|
|
{
|
|
return new MapFile(Path.Combine(_world.Path, _world.DataDirectory), id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a raw <see cref="NbtTree"/> of data for the given map.
|
|
/// </summary>
|
|
/// <param name="id">The id of the map to fetch.</param>
|
|
/// <returns>An <see cref="NbtTree"/> containing the given map's raw data.</returns>
|
|
/// <exception cref="NbtIOException">Thrown when the manager cannot read in an NBT data stream.</exception>
|
|
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);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves a raw <see cref="NbtTree"/> representing a map to the given map's file.
|
|
/// </summary>
|
|
/// <param name="id">The id of the map to write data to.</param>
|
|
/// <param name="tree">The map's data as an <see cref="NbtTree"/>.</param>
|
|
/// <exception cref="NbtIOException">Thrown when the manager cannot initialize an NBT data stream for output.</exception>
|
|
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
|
|
|
|
/// <inherit />
|
|
/// <exception cref="DataIOException">Thrown when the manager cannot read in a map that should exist.</exception>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <inherit />
|
|
/// <exception cref="DataIOException">Thrown when the manager cannot write out the map</exception>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Saves a <see cref="Map"/> object's data back to file given the id set in the <see cref="Map"/> object.
|
|
/// </summary>
|
|
/// <param name="map">The <see cref="Map"/> object containing the data to write back.</param>
|
|
/// <exception cref="DataIOException">Thrown when the manager cannot write out the map</exception>
|
|
public void SetMap (Map map)
|
|
{
|
|
SetMap(map.Id, map);
|
|
}
|
|
|
|
/// <inherit />
|
|
public bool MapExists (int id)
|
|
{
|
|
return new MapFile(Path.Combine(_world.Path, _world.DataDirectory), id).Exists();
|
|
}
|
|
|
|
/// <inherit />
|
|
/// <exception cref="DataIOException">Thrown when the manager cannot delete the map.</exception>
|
|
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<Map> Members
|
|
|
|
/// <summary>
|
|
/// Gets an enumerator that iterates through all the maps in the world's data directory.
|
|
/// </summary>
|
|
/// <returns>An enumerator for this manager.</returns>
|
|
public IEnumerator<Map> 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$");
|
|
}
|
|
}
|