Made PlayerManager enumerable.

This commit is contained in:
Justin Aquadro 2011-08-14 16:27:52 +00:00
parent ca56f70379
commit ac9c88773c
6 changed files with 334 additions and 10 deletions

View file

@ -12,7 +12,7 @@ namespace Substrate
/// <summary>
/// Represents an Alpha-compatible interface for globally managing chunks.
/// </summary>
public class AlphaChunkManager : IChunkManager
public class AlphaChunkManager : IChunkManager, IEnumerable<ChunkRef>
{
private string _mapPath;

View file

@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
using Substrate.Nbt;
namespace Substrate
{
using Nbt;
/// <summary>
/// Provides named id values for known block types.
/// </summary>
public static class BlockType
{
public const int AIR = 0;
@ -107,20 +108,59 @@ namespace Substrate
public const int TRAPDOOR = 96;
}
/// <summary>
/// Represents the physical state of a block, such as solid or fluid.
/// </summary>
public enum BlockState
{
/// <summary>
/// A solid state that stops movement.
/// </summary>
SOLID,
/// <summary>
/// A nonsolid state that can be passed through.
/// </summary>
NONSOLID,
/// <summary>
/// A fluid state that flows and impedes movement.
/// </summary>
FLUID
}
/// <summary>
/// Provides information on a specific type of block.
/// </summary>
/// <remarks>By default, all known MC block types are already defined and registered, assuming Substrate
/// is up to date with the current MC version. All unknown blocks are given a default type and unregistered status.
/// New block types may be created and used at runtime, and will automatically populate various static lookup tables
/// in the <see cref="BlockInfo"/> class.</remarks>
public class BlockInfo
{
/// <summary>
/// The maximum number of sequential blocks starting at 0 that can be registered.
/// </summary>
public const int MAX_BLOCKS = 256;
/// <summary>
/// The maximum opacity value that can be assigned to a block (fully opaque).
/// </summary>
public const int MAX_OPACITY = 15;
/// <summary>
/// The minimum opacity value that can be assigned to a block (fully transparent).
/// </summary>
public const int MIN_OPACITY = 0;
/// <summary>
/// The maximum luminance value that can be assigned to a block.
/// </summary>
public const int MAX_LUMINANCE = 15;
/// <summary>
/// The minimum luminance value that can be assigned to a block.
/// </summary>
public const int MIN_LUMINANCE = 0;
private static readonly BlockInfo[] _blockTable;
@ -193,61 +233,100 @@ namespace Substrate
private static readonly CacheTableArray<int> _opacityTableCache;
private static readonly CacheTableArray<int> _luminanceTableCache;
/// <summary>
/// Gets the lookup table for id-to-info values.
/// </summary>
public static ICacheTable<BlockInfo> BlockTable
{
get { return _blockTableCache; }
}
/// <summary>
/// Gets the lookup table for id-to-opacity values.
/// </summary>
public static ICacheTable<int> OpacityTable
{
get { return _opacityTableCache; }
}
/// <summary>
/// Gets the lookup table for id-to-luminance values.
/// </summary>
public static ICacheTable<int> LuminanceTable
{
get { return _luminanceTableCache; }
}
/// <summary>
/// Get's the block's Id.
/// </summary>
public int ID
{
get { return _id; }
}
/// <summary>
/// Get's the name of the block type.
/// </summary>
public string Name
{
get { return _name; }
}
/// <summary>
/// Gets the block's opacity value. An opacity of 0 is fully transparent to light.
/// </summary>
public int Opacity
{
get { return _opacity; }
}
/// <summary>
/// Gets the block's luminance value.
/// </summary>
/// <remarks>Blocks with luminance act as light sources and transmit light to other blocks.</remarks>
public int Luminance
{
get { return _luminance; }
}
/// <summary>
/// Checks whether the block transmits light to neighboring blocks.
/// </summary>
/// <remarks>A block may stop the transmission of light, but still be illuminated.</remarks>
public bool TransmitsLight
{
get { return _transmitLight; }
}
/// <summary>
/// Checks whether the block partially or fully blocks the transmission of light.
/// </summary>
public bool ObscuresLight
{
get { return _opacity > MIN_OPACITY || !_transmitLight; }
}
/// <summary>
/// Checks whether the block stops fluid from passing through it.
/// </summary>
/// <remarks>A block that does not block fluids will be destroyed by fluid.</remarks>
public bool BlocksFluid
{
get { return _blocksFluid; }
}
/// <summary>
/// Gets the block's physical state type.
/// </summary>
public BlockState State
{
get { return _state; }
}
/// <summary>
/// Checks whether this block type has been registered as a known type.
/// </summary>
public bool Registered
{
get { return _registered; }
@ -260,6 +339,12 @@ namespace Substrate
_blockTable[_id] = this;
}
/// <summary>
/// Constructs a new <see cref="BlockInfo"/> record for a given block id and name.
/// </summary>
/// <param name="id">The id of the block.</param>
/// <param name="name">The name of the block.</param>
/// <remarks>All user-constructed <see cref="BlockInfo"/> objects are registered automatically.</remarks>
public BlockInfo (int id, string name)
{
_id = id;
@ -268,6 +353,11 @@ namespace Substrate
_registered = true;
}
/// <summary>
/// Sets a new opacity value for this block type.
/// </summary>
/// <param name="opacity">A new opacity value.</param>
/// <returns>The object instance used to invoke this method.</returns>
public BlockInfo SetOpacity (int opacity)
{
_opacity = MIN_OPACITY + opacity;
@ -283,6 +373,11 @@ namespace Substrate
return this;
}
/// <summary>
/// Sets a new luminance value for this block type.
/// </summary>
/// <param name="luminance">A new luminance value.</param>
/// <returns>The object instance used to invoke this method.</returns>
public BlockInfo SetLuminance (int luminance)
{
_luminance = luminance;
@ -290,18 +385,35 @@ namespace Substrate
return this;
}
/// <summary>
/// Sets whether or not this block type will transmit light to neigboring blocks.
/// </summary>
/// <param name="transmit">True if this block type can transmit light to neighbors, false otherwise.</param>
/// <returns>The object instance used to invoke this method.</returns>
public BlockInfo SetLightTransmission (bool transmit)
{
_transmitLight = transmit;
return this;
}
/// <summary>
/// Sets limitations on what data values are considered valid for this block type.
/// </summary>
/// <param name="low">The lowest valid integer value.</param>
/// <param name="high">The highest valid integer value.</param>
/// <param name="bitmask">A mask representing which bits are interpreted as a bitmask in the data value.</param>
/// <returns>The object instance used to invoke this method.</returns>
public BlockInfo SetDataLimits (int low, int high, int bitmask)
{
_dataLimits = new DataLimits(low, high, bitmask);
return this;
}
/// <summary>
/// Sets the physical state of the block type.
/// </summary>
/// <param name="state">A physical state.</param>
/// <returns>The object instance used to invoke this method.</returns>
public BlockInfo SetState (BlockState state)
{
_state = state;
@ -316,12 +428,23 @@ namespace Substrate
return this;
}
/// <summary>
/// Sets whether or not this block type blocks fluids.
/// </summary>
/// <param name="blocks">True if this block type blocks fluids, false otherwise.</param>
/// <returns>The object instance used to invoke this method.</returns>
public BlockInfo SetBlocksFluid (bool blocks)
{
_blocksFluid = blocks;
return this;
}
/// <summary>
/// Tests if the given data value is valid for this block type.
/// </summary>
/// <param name="data">A data value to test.</param>
/// <returns>True if the data value is valid, false otherwise.</returns>
/// <remarks>This method uses internal information set by <see cref="SetDataLimits"/>.</remarks>
public bool TestData (int data)
{
if (_dataLimits == null) {
@ -617,19 +740,36 @@ namespace Substrate
}
}
/// <summary>
/// An extended <see cref="BlockInfo"/> that includes <see cref="TileEntity"/> information.
/// </summary>
public class BlockInfoEx : BlockInfo
{
private string _tileEntityName;
/// <summary>
/// Gets the name of the <see cref="TileEntity"/> type associated with this block type.
/// </summary>
public string TileEntityName
{
get { return _tileEntityName; }
}
public BlockInfoEx (int id) : base(id) { }
internal BlockInfoEx (int id) : base(id) { }
/// <summary>
/// Constructs a new <see cref="BlockInfoEx"/> with a given block id and name.
/// </summary>
/// <param name="id">The id of the block type.</param>
/// <param name="name">The name of the block type.</param>
public BlockInfoEx (int id, string name) : base(id, name) { }
/// <summary>
/// Sets the name of the <see cref="TileEntity"/> type associated with this block type.
/// </summary>
/// <param name="name">The name of a registered <see cref="TileEntity"/> type.</param>
/// <returns>The object instance used to invoke this method.</returns>
/// <seealso cref="TileEntityFactory"/>
public BlockInfo SetTileEntity (string name) {
_tileEntityName = name;
return this;

View file

@ -23,5 +23,14 @@ namespace Substrate.Core
string file = name + ".dat";
FileName = Path.Combine(path, file);
}
public static string NameFromFilename (string filename)
{
if (filename.EndsWith(".dat")) {
return filename.Remove(filename.Length - 4);
}
return filename;
}
}
}

View file

@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
using Substrate.Nbt;
namespace Substrate
{
using Nbt;
/// <summary>
/// Provides named id values for known item types.
/// </summary>
public static class ItemType
{
public const int IRON_SHOVEL = 256;
@ -116,6 +117,13 @@ namespace Substrate
public const int GREEN_MUSIC_DISC = 2257;
}
/// <summary>
/// Provides information on a specific type of item.
/// </summary>
/// <remarks>By default, all known MC item types are already defined and registered, assuming Substrate
/// is up to date with the current MC version.
/// New item types may be created and used at runtime, and will automatically populate various static lookup tables
/// in the <see cref="ItemInfo"/> class.</remarks>
public class ItemInfo
{
private static Random _rand = new Random();
@ -150,32 +158,53 @@ namespace Substrate
private static readonly CacheTableDict<ItemInfo> _itemTableCache;
/// <summary>
/// Gets the lookup table for id-to-info values.
/// </summary>
public static ICacheTable<ItemInfo> ItemTable
{
get { return _itemTableCache; }
}
/// <summary>
/// Gets the id of the item type.
/// </summary>
public int ID
{
get { return _id; }
}
/// <summary>
/// Gets the name of the item type.
/// </summary>
public string Name
{
get { return _name; }
}
/// <summary>
/// Gets the maximum stack size allowed for this item type.
/// </summary>
public int StackSize
{
get { return _stack; }
}
/// <summary>
/// Constructs a new <see cref="ItemInfo"/> record for the given item id.
/// </summary>
/// <param name="id">The id of an item type.</param>
public ItemInfo (int id)
{
_id = id;
_itemTable[_id] = this;
}
/// <summary>
/// Constructs a new <see cref="ItemInfo"/> record for the given item id and name.
/// </summary>
/// <param name="id">The id of an item type.</param>
/// <param name="name">The name of an item type.</param>
public ItemInfo (int id, string name)
{
_id = id;
@ -183,12 +212,21 @@ namespace Substrate
_itemTable[_id] = this;
}
/// <summary>
/// Sets the maximum stack size for this item type.
/// </summary>
/// <param name="stack">A stack size between 1 and 64, inclusive.</param>
/// <returns>The object instance used to invoke this method.</returns>
public ItemInfo SetStackSize (int stack)
{
_stack = stack;
return this;
}
/// <summary>
/// Chooses a registered item type at random and returns it.
/// </summary>
/// <returns></returns>
public static ItemInfo GetRandomItem ()
{
List<ItemInfo> list = new List<ItemInfo>(_itemTable.Values);

View file

@ -44,6 +44,7 @@ namespace Substrate
private int? _spawnZ;
private string _world;
private string _name;
private ItemCollection _inventory;
@ -141,6 +142,15 @@ namespace Substrate
set { _world = value; }
}
/// <summary>
/// Gets or sets the name that is used when the player is read or written from a <see cref="PlayerManager"/>.
/// </summary>
public string Name
{
get { return _name; }
set { _name = value; }
}
/// <summary>
/// Creates a new <see cref="Player"/> object with reasonable default values.
/// </summary>

View file

@ -4,6 +4,8 @@ using System.Text;
using System.IO;
using Substrate.Core;
using Substrate.Nbt;
using System.Text.RegularExpressions;
using System.Collections;
namespace Substrate
{
@ -11,7 +13,7 @@ namespace Substrate
/// Functions to manage multiple <see cref="Player"/> entities and files in multiplayer settings.
/// </summary>
/// <remarks>This manager is intended for player files stored in standard compressed NBT format.</remarks>
public class PlayerManager : IPlayerManager
public class PlayerManager : IPlayerManager, IEnumerable<Player>
{
private string _playerPath;
@ -82,7 +84,9 @@ namespace Substrate
}
try {
return new Player().LoadTreeSafe(GetPlayerTree(name).Root);
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);
@ -109,6 +113,16 @@ namespace Substrate
}
}
/// <summary>
/// Saves a <see cref="Player"/> object's data back to file given the name set in the <see cref="Player"/> object.
/// </summary>
/// <param name="player">The <see cref="Player"/> object containing the data to write back.</param>
/// <exception cref="PlayerIOException">Thrown when the manager cannot write out the player.</exception>
public void SetPlayer (Player player)
{
SetPlayer(player.Name, player);
}
/// <summary>
/// Checks if data for a player with the given name exists.
/// </summary>
@ -135,5 +149,118 @@ namespace Substrate
throw pex;
}
}
#region IEnumerable<Player> Members
/// <summary>
/// Gets an enumerator that iterates through all the chunks in the world.
/// </summary>
/// <returns>An enumerator for this manager.</returns>
public IEnumerator<Player> 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<Player>
{
protected PlayerManager _pm;
protected Queue<string> _names;
protected Player _curPlayer;
public Enumerator (PlayerManager cfm)
{
_pm = cfm;
_names = new Queue<string>();
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<Player>.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$");
}
}
}