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
}
}