forked from mirrors/NBTExplorer
Made PlayerManager enumerable.
This commit is contained in:
parent
ca56f70379
commit
ac9c88773c
6 changed files with 334 additions and 10 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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$");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue