using System; using System.Collections.Generic; using System.Text; using Substrate.Core; using Substrate.Nbt; namespace Substrate { /// /// Represents a Player from either single- or multi-player Minecraft. /// /// Unlike objects, objects do not need to be added to chunks. They /// are stored individually or within level data. public class Player : Entity, INbtObject, ICopyable, IItemContainer { private static readonly SchemaNodeCompound _schema = Entity.Schema.MergeInto(new SchemaNodeCompound("") { new SchemaNodeScaler("AttackTime", TagType.TAG_SHORT), new SchemaNodeScaler("DeathTime", TagType.TAG_SHORT), new SchemaNodeScaler("Health", TagType.TAG_SHORT), new SchemaNodeScaler("HurtTime", TagType.TAG_SHORT), new SchemaNodeScaler("Dimension", TagType.TAG_INT), new SchemaNodeList("Inventory", TagType.TAG_COMPOUND, ItemCollection.Schema), new SchemaNodeScaler("World", TagType.TAG_STRING, SchemaOptions.OPTIONAL), new SchemaNodeScaler("Sleeping", TagType.TAG_BYTE, SchemaOptions.CREATE_ON_MISSING), new SchemaNodeScaler("SleepTimer", TagType.TAG_SHORT, SchemaOptions.CREATE_ON_MISSING), new SchemaNodeScaler("SpawnX", TagType.TAG_INT, SchemaOptions.OPTIONAL), new SchemaNodeScaler("SpawnY", TagType.TAG_INT, SchemaOptions.OPTIONAL), new SchemaNodeScaler("SpawnZ", TagType.TAG_INT, SchemaOptions.OPTIONAL), }); private const int _CAPACITY = 105; private short _attackTime; private short _deathTime; private short _health; private short _hurtTime; private int _dimension; private byte _sleeping; private short _sleepTimer; private int? _spawnX; private int? _spawnY; private int? _spawnZ; private string _world; private ItemCollection _inventory; /// /// Gets or sets the number of ticks left in the player's "invincibility shield" after last struck. /// public int AttackTime { get { return _attackTime; } set { _attackTime = (short)value; } } /// /// Gets or sets the number of ticks that the player has been dead for. /// public int DeathTime { get { return _deathTime; } set { _deathTime = (short)value; } } /// /// Gets or sets the amount of the player's health. /// public int Health { get { return _health; } set { _health = (short)value; } } /// /// Gets or sets the player's Hurt Time value. /// public int HurtTime { get { return _hurtTime; } set { _hurtTime = (short)value; } } /// /// Gets or sets the dimension that the player is currently in. /// public int Dimension { get { return _dimension; } set { _dimension = value; } } /// /// Gets or sets a value indicating whether the player is sleeping in a bed. /// public bool IsSleeping { get { return _sleeping == 1; } set { _sleeping = (byte)(value ? 1 : 0); } } /// /// Gets or sets the player's Sleep Timer value. /// public int SleepTimer { get { return _sleepTimer; } set { _sleepTimer = (short)value; } } /// /// Gets or sets the player's personal spawn point, set by sleeping in beds. /// public SpawnPoint Spawn { get { return new SpawnPoint(_spawnX ?? 0, _spawnY ?? 0, _spawnZ ?? 0); } set { _spawnX = value.X; _spawnY = value.Y; _spawnZ = value.Z; } } /// /// Tests if the player currently has a personal spawn point. /// public bool HasSpawn { get { return _spawnX != null && _spawnY != null && _spawnZ != null; } } /// /// Gets or sets the name of the world that the player is currently within. /// public string World { get { return _world; } set { _world = value; } } /// /// Creates a new object with reasonable default values. /// public Player () : base() { _inventory = new ItemCollection(_CAPACITY); // Sane defaults _dimension = 0; _sleeping = 0; _sleepTimer = 0; Air = 300; Health = 20; Fire = -20; } /// /// Creates a copy of a object. /// /// The to copy fields from. protected Player (Player p) : base(p) { _attackTime = p._attackTime; _deathTime = p._deathTime; _health = p._health; _hurtTime = p._hurtTime; _dimension = p._dimension; _sleeping = p._sleeping; _sleepTimer = p._sleepTimer; _spawnX = p._spawnX; _spawnY = p._spawnY; _spawnZ = p._spawnZ; _world = p._world; _inventory = p._inventory.Copy(); } /// /// Clears the player's personal spawn point. /// public void ClearSpawn () { _spawnX = null; _spawnY = null; _spawnZ = null; } #region INBTObject Members /// /// Gets a representing the schema of a Player. /// public static new SchemaNodeCompound Schema { get { return _schema; } } /// /// Attempt to load a Player subtree into the without validation. /// /// The root node of a Player subtree. /// The returns itself on success, or null if the tree was unparsable. public virtual new Player LoadTree (TagNode tree) { TagNodeCompound ctree = tree as TagNodeCompound; if (ctree == null || base.LoadTree(tree) == null) { return null; } _attackTime = ctree["AttackTime"].ToTagShort(); _deathTime = ctree["DeathTime"].ToTagShort(); _health = ctree["Health"].ToTagShort(); _hurtTime = ctree["HurtTime"].ToTagShort(); _dimension = ctree["Dimension"].ToTagInt(); _sleeping = ctree["Sleeping"].ToTagByte(); _sleepTimer = ctree["SleepTimer"].ToTagShort(); if (ctree.ContainsKey("SpawnX")) { _spawnX = ctree["SpawnX"].ToTagInt(); } if (ctree.ContainsKey("SpawnY")) { _spawnY = ctree["SpawnY"].ToTagInt(); } if (ctree.ContainsKey("SpawnZ")) { _spawnZ = ctree["SpawnZ"].ToTagInt(); } if (ctree.ContainsKey("World")) { _world = ctree["World"].ToTagString(); } _inventory.LoadTree(ctree["Inventory"].ToTagList()); return this; } /// /// Attempt to load a Player subtree into the with validation. /// /// The root node of a Player subtree. /// The returns itself on success, or null if the tree failed validation. public virtual new Player LoadTreeSafe (TagNode tree) { if (!ValidateTree(tree)) { return null; } return LoadTree(tree); } /// /// Builds a Player subtree from the current data. /// /// The root node of a Player subtree representing the current data. public virtual new TagNode BuildTree () { TagNodeCompound tree = base.BuildTree() as TagNodeCompound; tree["AttackTime"] = new TagNodeShort(_attackTime); tree["DeathTime"] = new TagNodeShort(_deathTime); tree["Health"] = new TagNodeShort(_health); tree["HurtTime"] = new TagNodeShort(_hurtTime); tree["Dimension"] = new TagNodeInt(_dimension); tree["Sleeping"] = new TagNodeByte(_sleeping); tree["SleepTimer"] = new TagNodeShort(_sleepTimer); if (_spawnX != null && _spawnY != null && _spawnZ != null) { tree["SpawnX"] = new TagNodeInt(_spawnX ?? 0); tree["SpawnY"] = new TagNodeInt(_spawnY ?? 0); tree["SpawnZ"] = new TagNodeInt(_spawnZ ?? 0); } if (_world != null) { tree["World"] = new TagNodeString(_world); } tree["Inventory"] = _inventory.BuildTree(); return tree; } /// /// Validate a Player subtree against a schema defintion. /// /// The root node of a Player subtree. /// Status indicating whether the tree was valid against the internal schema. public virtual new bool ValidateTree (TagNode tree) { return new NbtVerifier(tree, _schema).Verify(); } #endregion #region ICopyable Members /// /// Creates a deep-copy of the . /// /// A deep-copy of the . public virtual new Player Copy () { return new Player(this); } #endregion #region IItemContainer Members /// /// Gets access to an representing the player's equipment and inventory. /// public ItemCollection Items { get { return _inventory; } } #endregion } }