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$");
}
}
}