using System; using System.Collections.Generic; using System.Text; using System.IO; using Substrate.Core; using Substrate.Nbt; using System.Text.RegularExpressions; using System.Collections; namespace Substrate { /// /// Functions to manage multiple entities and files in multiplayer settings. /// /// This manager is intended for player files stored in standard compressed NBT format. public class PlayerManager : IPlayerManager, IEnumerable { private string _playerPath; /// /// Create a new for a given file path. /// /// Path to a directory containing player data files. public PlayerManager (string playerDir) { _playerPath = playerDir; } /// /// Gets a representing the backing NBT data stream. /// /// The name of the player to fetch. /// A for the given player. protected PlayerFile GetPlayerFile (string name) { return new PlayerFile(_playerPath, name); } /// /// Gets a raw of data for the given player. /// /// The name of the player to fetch. /// An containing the given player's raw data. /// Thrown when the manager cannot read in an NBT data stream. public NbtTree GetPlayerTree (string name) { PlayerFile pf = GetPlayerFile(name); Stream nbtstr = pf.GetDataInputStream(); if (nbtstr == null) { throw new NbtIOException("Failed to initialize NBT data stream for input."); } return new NbtTree(nbtstr); } /// /// Saves a raw representing a player to the given player's file. /// /// The name of the player to write data to. /// The player's data as an . /// Thrown when the manager cannot initialize an NBT data stream for output. public void SetPlayerTree (string name, NbtTree tree) { PlayerFile pf = GetPlayerFile(name); Stream zipstr = pf.GetDataOutputStream(); if (zipstr == null) { throw new NbtIOException("Failed to initialize NBT data stream for output."); } tree.WriteTo(zipstr); zipstr.Close(); } /// /// Gets a object for the given player. /// /// The name of the player to fetch. /// A object for the given player, or null if the player could not be found. /// Thrown when the manager cannot read in a player that should exist. public Player GetPlayer (string name) { if (!PlayerExists(name)) { return null; } try { Player p = new Player().LoadTreeSafe(GetPlayerTree(name).Root); p.Name = name; return p; } catch (Exception ex) { PlayerIOException pex = new PlayerIOException("Could not load player", ex); pex.Data["PlayerName"] = name; throw pex; } } /// /// Saves a object's data back to the given player's file. /// /// The name of the player to write back to. /// The object containing data to write back. /// Thrown when the manager cannot write out the player. public void SetPlayer (string name, Player player) { try { SetPlayerTree(name, new NbtTree(player.BuildTree() as TagNodeCompound)); } catch (Exception ex) { PlayerIOException pex = new PlayerIOException("Could not save player", ex); pex.Data["PlayerName"] = name; throw pex; } } /// /// Saves a object's data back to file given the name set in the object. /// /// The object containing the data to write back. /// Thrown when the manager cannot write out the player. public void SetPlayer (Player player) { SetPlayer(player.Name, player); } /// /// Checks if data for a player with the given name exists. /// /// The name of the player to look up. /// True if player data was found; false otherwise. public bool PlayerExists (string name) { return new PlayerFile(_playerPath, name).Exists(); } /// /// Deletes a player with the given name from the underlying data store. /// /// The name of the player to delete. /// Thrown when the manager cannot delete the player. public void DeletePlayer (string name) { try { new PlayerFile(_playerPath, name).Delete(); } catch (Exception ex) { PlayerIOException pex = new PlayerIOException("Could not remove player", ex); pex.Data["PlayerName"] = name; throw pex; } } #region IEnumerable Members /// /// Gets an enumerator that iterates through all the players in the world. /// /// An enumerator for this manager. public IEnumerator GetEnumerator () { return new Enumerator(this); } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator () { return new Enumerator(this); } #endregion private class Enumerator : IEnumerator { protected PlayerManager _pm; protected Queue _names; protected Player _curPlayer; public Enumerator (PlayerManager cfm) { _pm = cfm; _names = new Queue(); if (!Directory.Exists(_pm._playerPath)) { throw new DirectoryNotFoundException(); } Reset(); } public bool MoveNext () { if (_names.Count == 0) { return false; } string name = _names.Dequeue(); _curPlayer = _pm.GetPlayer(name); _curPlayer.Name = name; return true; } public void Reset () { _names.Clear(); _curPlayer = null; string[] files = Directory.GetFiles(_pm._playerPath); foreach (string file in files) { string basename = Path.GetFileName(file); if (!ParseFileName(basename)) { continue; } _names.Enqueue(PlayerFile.NameFromFilename(basename)); } } void IDisposable.Dispose () { } object IEnumerator.Current { get { return Current; } } Player IEnumerator.Current { get { return Current; } } public Player Current { get { if (_curPlayer == null) { throw new InvalidOperationException(); } return _curPlayer; } } private bool ParseFileName (string filename) { Match match = _namePattern.Match(filename); if (!match.Success) { return false; } return true; } protected static Regex _namePattern = new Regex(".+\\.dat$"); } } }