using System; using System.Collections.Generic; using System.Text; using Substrate.Core; using Substrate.Nbt; namespace Substrate { /// /// The base Entity type for Minecraft Entities, providing access to data common to all Minecraft Entities. /// public class Entity : INbtObject, ICopyable { private static readonly SchemaNodeCompound _schema = new SchemaNodeCompound("") { new SchemaNodeList("Pos", TagType.TAG_DOUBLE, 3), new SchemaNodeList("Motion", TagType.TAG_DOUBLE, 3), new SchemaNodeList("Rotation", TagType.TAG_FLOAT, 2), new SchemaNodeScaler("FallDistance", TagType.TAG_FLOAT), new SchemaNodeScaler("Fire", TagType.TAG_SHORT), new SchemaNodeScaler("Air", TagType.TAG_SHORT), new SchemaNodeScaler("OnGround", TagType.TAG_BYTE), }; private TagNodeCompound _source; private Vector3 _pos; private Vector3 _motion; private Orientation _rotation; private float _fallDistance; private short _fire; private short _air; private byte _onGround; /// /// Gets or sets the global position of the entity in fractional block coordinates. /// public Vector3 Position { get { return _pos; } set { _pos = value; } } /// /// Gets or sets the velocity of the entity. /// public Vector3 Motion { get { return _motion; } set { _motion = value; } } /// /// Gets or sets the orientation of the entity. /// public Orientation Rotation { get { return _rotation; } set { _rotation = value; } } /// /// Gets or sets the distance that the entity has fallen, if it is falling. /// public double FallDistance { get { return _fallDistance; } set { _fallDistance = (float)value; } } /// /// Gets or sets the fire counter of the entity. /// public int Fire { get { return _fire; } set { _fire = (short)value; } } /// /// Gets or sets the remaining air availale to the entity. /// public int Air { get { return _air; } set { _air = (short)value; } } /// /// Gets or sets a value indicating whether the entity is currently touch the ground. /// public bool IsOnGround { get { return _onGround == 1; } set { _onGround = (byte)(value ? 1 : 0); } } /// /// Gets the source used to create this if it exists. /// public TagNodeCompound Source { get { return _source; } } /// /// Constructs a new generic with default values. /// public Entity () { _pos = new Vector3(); _motion = new Vector3(); _rotation = new Orientation(); } /// /// Constructs a new generic by copying fields from another object. /// /// An to copy fields from. protected Entity (Entity e) { _pos = new Vector3(); _pos.X = e._pos.X; _pos.Y = e._pos.Y; _pos.Z = e._pos.Z; _motion = new Vector3(); _motion.X = e._motion.X; _motion.Y = e._motion.Y; _motion.Z = e._motion.Z; _rotation = new Orientation(); _rotation.Pitch = e._rotation.Pitch; _rotation.Yaw = e._rotation.Yaw; _fallDistance = e._fallDistance; _fire = e._fire; _air = e._air; _onGround = e._onGround; if (e._source != null) { _source = e._source.Copy() as TagNodeCompound; } } /// /// Moves the by given block offsets. /// /// The X-offset to move by, in blocks. /// The Y-offset to move by, in blocks. /// The Z-offset to move by, in blocks. public virtual void MoveBy (int diffX, int diffY, int diffZ) { _pos.X += diffX; _pos.Y += diffY; _pos.Z += diffZ; } #region INBTObject Members /// /// Gets a representing the basic schema of an Entity. /// public static SchemaNodeCompound Schema { get { return _schema; } } /// /// Attempt to load an Entity subtree into the without validation. /// /// The root node of an Entity subtree. /// The returns itself on success, or null if the tree was unparsable. public Entity LoadTree (TagNode tree) { TagNodeCompound ctree = tree as TagNodeCompound; if (ctree == null) { return null; } TagNodeList pos = ctree["Pos"].ToTagList(); _pos = new Vector3(); _pos.X = pos[0].ToTagDouble(); _pos.Y = pos[1].ToTagDouble(); _pos.Z = pos[2].ToTagDouble(); TagNodeList motion = ctree["Motion"].ToTagList(); _motion = new Vector3(); _motion.X = motion[0].ToTagDouble(); _motion.Y = motion[1].ToTagDouble(); _motion.Z = motion[2].ToTagDouble(); TagNodeList rotation = ctree["Rotation"].ToTagList(); _rotation = new Orientation(); _rotation.Yaw = rotation[0].ToTagFloat(); _rotation.Pitch = rotation[1].ToTagFloat(); _fire = ctree["Fire"].ToTagShort(); _air = ctree["Air"].ToTagShort(); _onGround = ctree["OnGround"].ToTagByte(); _source = ctree.Copy() as TagNodeCompound; return this; } /// /// Attempt to load an Entity subtree into the with validation. /// /// The root node of an Entity subtree. /// The returns itself on success, or null if the tree failed validation. public Entity LoadTreeSafe (TagNode tree) { if (!ValidateTree(tree)) { return null; } return LoadTree(tree); } /// /// Builds an Entity subtree from the current data. /// /// The root node of an Entity subtree representing the current data. public TagNode BuildTree () { TagNodeCompound tree = new TagNodeCompound(); TagNodeList pos = new TagNodeList(TagType.TAG_DOUBLE); pos.Add(new TagNodeDouble(_pos.X)); pos.Add(new TagNodeDouble(_pos.Y)); pos.Add(new TagNodeDouble(_pos.Z)); tree["Pos"] = pos; TagNodeList motion = new TagNodeList(TagType.TAG_DOUBLE); motion.Add(new TagNodeDouble(_motion.X)); motion.Add(new TagNodeDouble(_motion.Y)); motion.Add(new TagNodeDouble(_motion.Z)); tree["Motion"] = motion; TagNodeList rotation = new TagNodeList(TagType.TAG_FLOAT); rotation.Add(new TagNodeFloat((float)_rotation.Yaw)); rotation.Add(new TagNodeFloat((float)_rotation.Pitch)); tree["Rotation"] = rotation; tree["FallDistance"] = new TagNodeFloat(_fallDistance); tree["Fire"] = new TagNodeShort(_fire); tree["Air"] = new TagNodeShort(_air); tree["OnGround"] = new TagNodeByte(_onGround); if (_source != null) { tree.MergeFrom(_source); } return tree; } /// /// Validate an Entity subtree against a basic schema. /// /// The root node of an Entity subtree. /// Status indicating whether the tree was valid against the internal schema. public 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 Entity Copy () { return new Entity(this); } #endregion } /// /// A base entity type for all entities except entities. /// /// Generally, this class should be subtyped into new concrete Entity types, as this generic type is unable to /// capture any of the custom data fields. It is however still possible to create instances of objects, /// which may allow for graceful handling of unknown Entity types. public class TypedEntity : Entity, INbtObject, ICopyable { private static readonly SchemaNodeCompound _schema = Entity.Schema.MergeInto(new SchemaNodeCompound("") { new SchemaNodeScaler("id", TagType.TAG_STRING), }); private string _id; /// /// Gets the id (type) of the entity. /// public string ID { get { return _id; } } /// /// Creates a new generic with the given id. /// /// The id (name) of the Entity. public TypedEntity (string id) : base() { _id = id; } /// /// Constructs a new by copying an existing one. /// /// The to copy. protected TypedEntity (TypedEntity e) : base(e) { _id = e._id; } #region INBTObject Members /// /// Gets a representing the basic schema of an Entity. /// public static new SchemaNodeCompound Schema { get { return _schema; } } /// /// Attempt to load an Entity subtree into the without validation. /// /// The root node of an Entity subtree. /// The returns itself on success, or null if the tree was unparsable. public virtual new TypedEntity LoadTree (TagNode tree) { TagNodeCompound ctree = tree as TagNodeCompound; if (ctree == null || base.LoadTree(tree) == null) { return null; } _id = ctree["id"].ToTagString(); return this; } /// /// Attempt to load an Entity subtree into the with validation. /// /// The root node of an Entity subtree. /// The returns itself on success, or null if the tree failed validation. public virtual new TypedEntity LoadTreeSafe (TagNode tree) { if (!ValidateTree(tree)) { return null; } return LoadTree(tree); } /// /// Builds an Entity subtree from the current data. /// /// The root node of an Entity subtree representing the current data. public virtual new TagNode BuildTree () { TagNodeCompound tree = base.BuildTree() as TagNodeCompound; tree["id"] = new TagNodeString(_id); return tree; } /// /// Validate an Entity subtree against a basic schema. /// /// The root node of an Entity 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 TypedEntity Copy () { return new TypedEntity(this); } #endregion } }