using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using CommonAI.RTS;
using CommonLang.Vector;
using CommonLang.IO;
using CommonLang.ByteOrder;
using CommonLang.IO.Attribute;
using CommonLang;
using CommonLang.Protocol;
using CommonAI.Zone.Helper;
using CommonAI.ZoneClient;
using CommonAI.Zone.Instance;
using CommonLang.Log;
using CommonAI.ZoneServer.JSGModule;
using CommonAI.Data;

namespace CommonAI.Zone
{
    #region ABSTRACT

    /// <summary>
    /// 向服务器端发送的指令
    /// </summary>
    abstract public class Action : IMessage, BattleMessage
    {
        //private static int Inxexer = 0;

        public GameEntity sender;
        public int MessageID { get; set; }
        public Action() { }
        abstract public void WriteExternal(IOutputStream output);
        abstract public void ReadExternal(IInputStream input);
        virtual public void BeforeWrite(TemplateManager templates) { }
        virtual public void EndRead(TemplateManager templates) { }
    }
    /// <summary>
    /// 客户端接收到的消息
    /// </summary>
    abstract public class Event : IMessage, BattleMessage
    {
        public GameEntity sender;
        public int MessageID { get; set; }
        abstract public void WriteExternal(IOutputStream output);
        abstract public void ReadExternal(IInputStream input);
        virtual public void BeforeWrite(TemplateManager templates) { }
        virtual public void EndRead(TemplateManager templates) { }
    }

    public interface BattleMessage
    {
        void BeforeWrite(TemplateManager templates);
        void EndRead(TemplateManager templates);
    }

    /// <summary>
    /// 某个位置上的事件
    /// </summary>
    public interface PositionMessage
    {
        float X { get; }
        float Y { get; }
    }
    /// <summary>
    /// 主角的事件
    /// </summary>
    public interface ActorMessage
    {
        uint ObjectID { get; }
    }

	/** 单人事件 */
	public abstract class PlayerSingleMsg : ObjectEvent
	{

	}

    /// <summary>
    /// 系统消息
    /// </summary>
    public interface SystemMessage
    {
    }


    //--------------------------------------------------------------------------
    /// <summary>
    /// 向服务器端某个单位发送的指令
    /// </summary>
    abstract public class ObjectAction : Action
    {
        /// <summary>
        /// 不需要传输object_id, 使用sender对象来绑定Session和InstanceUnit的关联//
        /// </summary>
        public uint object_id;
        protected ObjectAction() { }
        protected ObjectAction(uint obj_id)
        {
            this.object_id = obj_id;
        }
        override public void WriteExternal(IOutputStream output)
        {
            // 不需要传输object_id, 使用sender对象来绑定Session和InstanceUnit//
        }
        override public void ReadExternal(IInputStream input)
        {
            // 不需要传输object_id, 使用sender对象来绑定Session和InstanceUnit//
        }
    }
    /// <summary>
    /// 某个单位的事件消息
    /// </summary>
    abstract public class ObjectEvent : Event
    {
        public uint object_id;
        public uint ObjectID { get { return object_id; } }
        protected ObjectEvent() { }
        protected ObjectEvent(uint obj_id)
        {
            this.object_id = obj_id;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutVU32(object_id);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.object_id = input.GetVU32();
        }
    }

    //--------------------------------------------------------------------------
    /// <summary>
    /// 向服务器端某个单位发送的请求
    /// </summary>
    abstract public class ActorRequest : ObjectAction
    {
        protected ActorRequest() { }
        protected ActorRequest(uint obj_id)
            : base(obj_id)
        {
        }
    }
    /// <summary>
    /// 向服务器端某个单位发送请求对应的回馈
    /// </summary>
    abstract public class ActorResponse : ObjectEvent, ActorMessage
    {
        protected ActorResponse() { }
        protected ActorResponse(uint obj_id)
            : base(obj_id)
        {
        }
    }

    #endregion

    //--------------------------------------------------------------------------
    #region ZONE_EVENTS_0x8000

    public abstract class ZoneEvent : Event
    {

    }

    /// <summary>
    /// 添加单位事件
    /// </summary>
    [MessageType(0x8001)]
    public class AddUnitEvent : ZoneEvent
    {
        public SyncUnitInfo Sync;
        public string ErrorMessage;
		public byte flag;					//标记:0:正常生成,1:归属某个服务器

        public uint unit_id
        {
            get
            {
                if (Sync != null)
                {
                    return Sync.ObjectID;
                }
                return 0;
            }
        }

        public AddUnitEvent() { }
        public AddUnitEvent(SyncUnitInfo sync)
        {
            this.Sync = sync;
        }

        override public void WriteExternal(IOutputStream output)
        {
            output.PutExt(Sync);
            output.PutUTF(ErrorMessage);
			output.PutU8(flag);
		}

        override public void ReadExternal(IInputStream input)
        {
            this.Sync = input.GetExt<SyncUnitInfo>();
            this.ErrorMessage = input.GetUTF();
			this.flag = input.GetU8();
        }
    }

    /// <summary>
    /// 添加法术/飞行道具效果事件
    /// </summary>
    [MessageType(0x8002)]
    public class AddSpellEvent : ZoneEvent
    {
        private BitSet8 mask = new BitSet8();
        public bool IsLauncherSender
        {
            get { return mask.Get(0); }
            private set { mask.Set(0, value); }
        }
        public bool IsTargetPos
        {
            get { return mask.Get(1); }
            private set { mask.Set(1, value); }
        }
        public bool IsTargetObject
        {
            get { return mask.Get(2); }
            private set { mask.Set(2, value); }
        }
        public bool IsHeight
        {
            get { return mask.Get(3); }
            private set { mask.Set(3, value); }
        }
        public bool IsSyncPos
        {
            get { return mask.Get(4); }
            private set { mask.Set(4, value); }
        }
        public bool IsHalf
        {
            get { return mask.Get(7); }
            private set { mask.Set(7, value); }
        }
        public int spell_template_id
        {
            get { return (launch_data != null) ? launch_data.SpellID : 0; }
        }
        public LaunchSpell LaunchData
        {
            get { return launch_data; }
        }
        private LaunchSpell launch_data;
        private uint launch_data_sn = 0;

        public uint spell_id;
        public uint launcher_unit_id;
        public uint sender_unit_id;
        public uint target_obj_id;
        public Vector2 target_pos;
        public float x;
        public float y;
        public float direction;
        public float height;
		public int SpellID;

        public AddSpellEvent() { }
        public AddSpellEvent(InstanceSpell spell)
        {
            this.launch_data = spell.LaunchData;
            this.spell_id = spell.ID;
            this.sender_unit_id = spell.SenderID;
            this.launcher_unit_id = spell.LauncherID;
            this.target_obj_id = spell.TargetID;
            this.target_pos = spell.TargetPos;

            this.x = spell.X;
            this.y = spell.Y;
            this.direction = spell.Direction;
            this.height = spell.Z;

            //mask//
            this.IsLauncherSender = (launcher_unit_id == sender_unit_id);
            this.IsTargetPos = (spell.Info.MType == SpellTemplate.MotionType.Cannon || spell.Info.MType == SpellTemplate.MotionType.CurveMissile) && (target_pos != null);
            this.IsTargetObject = (target_obj_id != 0);
            this.IsHeight = (height != 0);
            this.IsHalf = spell.Parent.IsHalfSync;
            this.IsSyncPos = spell.Info.IsLaunchSpellEventSyncPos;
			this.SpellID = this.launch_data.SpellID;
		}

        public override void BeforeWrite(TemplateManager templates)
        {
            base.BeforeWrite(templates);
            if (launch_data != null)
            {
                this.launch_data_sn = this.LaunchData.IsCodeCreate() ? uint.MaxValue: launch_data.SerialNumber;
            }
        }
        public override void EndRead(TemplateManager templates)
        {
            base.EndRead(templates);
			if(this.launch_data_sn == uint.MaxValue)
			{
				this.launch_data = JSGGlobalData.GetUnConfigSpellByID((int)this.SpellID);
				//System.Console.WriteLine("123123123: " + this.launch_data.SpellID + ", " + this.launch_data.FromUnitBody);
			}
			else
			{
				this.launch_data = templates.GetSnData<LaunchSpell>(launch_data_sn);
			}            
        }

        override public void WriteExternal(IOutputStream output)
        {
            output.PutU8(mask.Mask);
            output.PutVU32(spell_id);
            output.PutVU32(launch_data_sn);
            if (this.IsLauncherSender)
            {
                output.PutVU32(launcher_unit_id);
            }
            else
            {
                output.PutVU32(sender_unit_id);
                output.PutVU32(launcher_unit_id);
            }
            if (this.IsTargetObject)
            {
                output.PutVU32(target_obj_id);
            }
            if (this.IsTargetPos)
            {
                MoveHelper.WritePos(IsHalf, target_pos.X, target_pos.Y, output);
            }
            if (this.IsSyncPos)
            {
                MoveHelper.WritePosAndDirection(IsHalf, x, y, direction, output);
            }
            if (this.IsHeight)
            {
                MoveHelper.WritePos(IsHalf, height, output);
            }
			if (this.LaunchData.IsCodeCreate())
			{
				output.PutS32(this.SpellID);
			}
			//System.Console.WriteLine("AddSpell: " + this.launch_data.SpellID + ", ID: " + spell_id + ", XY:" + this.x + ", " + this.y + ", d:" + this.direction);
        }

        override public void ReadExternal(IInputStream input)
        {
            this.mask.Mask = input.GetU8();
            this.spell_id = input.GetVU32();
            this.launch_data_sn = input.GetVU32();
            if (this.IsLauncherSender)
            {
                this.launcher_unit_id = this.sender_unit_id = input.GetVU32();
            }
            else
            {
                this.sender_unit_id = input.GetVU32();
                this.launcher_unit_id = input.GetVU32();
            }
            if (this.IsTargetObject)
            {
                this.target_obj_id = input.GetVU32();
            }
            if (this.IsTargetPos)
            {
                this.target_pos = new Vector2();
                MoveHelper.ReadPos(IsHalf, ref target_pos, input);
            }
            if (this.IsSyncPos)
            {
                MoveHelper.ReadPosAndDirection(IsHalf, out x, out y, out direction, input);
            }
            if (this.IsHeight)
            {
                MoveHelper.ReadPos(IsHalf, out height, input);
            }
			if(this.launch_data_sn == uint.MaxValue)
			{
				this.SpellID = input.GetS32();
			}
        }
    }

    /// <summary>
    /// 单位动作中击中别的单位
    /// </summary>
    [MessageType(0x8003)]
    public class AddEffectEvent : ZoneEvent, PositionMessage
    {

        public uint hostId = 0;

        public float x;
        public float y;
        public float direction;
        private uint effect_sn = 0;

        public LaunchEffect effect { get; set; }
        public AddEffectEvent() { }
        public AddEffectEvent(uint hostId , float x, float y, float dir, LaunchEffect effect)
        {
            this.hostId = hostId;
            this.x = x;
            this.y = y;
            this.direction = dir;
            this.effect = effect;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutVU32(hostId);
            output.PutF32(x);
            output.PutF32(y);
            output.PutF32(direction);
            output.PutVU32(effect_sn);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.hostId = input.GetVU32();
            this.x = input.GetF32();
            this.y = input.GetF32();
            this.direction = input.GetF32();
            this.effect_sn = input.GetVU32();
        }
        public override void BeforeWrite(TemplateManager templates)
        {
            if (effect != null)
            {
                this.effect_sn = effect.SerialNumber;
            }
        }
        public override void EndRead(TemplateManager templates)
        {
            this.effect = templates.GetSnData<LaunchEffect>(effect_sn);
        }
        public float X { get { return x; } }
        public float Y { get { return y; } }
    }

    /// <summary>
    /// 添加道具事件
    /// </summary>
    [MessageType(0x8004)]
    public class AddItemEvent : ZoneEvent
    {
        public SyncItemInfo Sync;
        public string ErrorMessage;
        public uint unit_id
        {
            get { if (Sync != null) { return Sync.ObjectID; } return 0; }
        }

        public AddItemEvent() { }
        public AddItemEvent(SyncItemInfo sync)
        {
            this.Sync = sync;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutExt(Sync);
            output.PutUTF(ErrorMessage);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.Sync = input.GetExt<SyncItemInfo>();
            this.ErrorMessage = input.GetUTF();
        }
    }

    /// <summary>
    /// 某个对象从场景中移除
    /// </summary>
    [MessageType(0x8005)]
    public class RemoveObjectEvent : ZoneEvent
    {
        public uint object_id;

        public RemoveObjectEvent() { }
        public RemoveObjectEvent(uint oid)
        {
            this.object_id = oid;
        }
        override public void WriteExternal(IOutputStream output)
        {
            //Console.WriteLine(" - RemoveObjectEvent - " + this.object_id);
            output.PutVU32(object_id);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.object_id = input.GetVU32();
        }
    }

    /// <summary>
    /// 同步场景中移动单位的坐标
    /// </summary>
    [MessageType(0x8006)]
    public class SyncPosEvent : ZoneEvent
    {
        public struct UnitPos : IVector2
        {
            private uint m_ID;
            private float m_X;
            private float m_Y;
            private float m_Z;
            private float m_Direction;

            public uint ID { get { return m_ID; } }
            public float Direction { get { return m_Direction; } set { m_Direction = value; } }
            public float X { get { return m_X; } set { m_X = value; } }
            public float Y { get { return m_Y; } set { m_Y = value; } }
            public float Z { get { return m_Z; } set { m_Z = value; } }

            public void SetObject(InstanceZoneObject obj)
            {
                this.m_ID = obj.ID;
                this.m_X = obj.X;
                this.m_Y = obj.Y;
                this.m_Z = obj.Z;
                this.m_Direction = obj.Direction;
            }
            internal void Write(IOutputStream output, bool half, bool sync_z)
            {
                output.PutVU32(m_ID);
                if (half)
                {
                    output.PutU16(MoveHelper.ToPos16(m_X));
                    output.PutU16(MoveHelper.ToPos16(m_Y));
                    if (sync_z) output.PutU16(MoveHelper.ToPos16(m_Z));
                }
                else
                {
                    output.PutF32(m_X);
                    output.PutF32(m_Y);
                    if (sync_z) output.PutF32(m_Z);
                }
				
                output.PutU8(MoveHelper.ToDirectionD8(m_Direction));

				//if (m_ID == 2649)
				//{
				//	Console.WriteLine("SyncPos, " + TimeUtil.GetTimestampMS() + ", X: " + this.m_X + ",Y: " + this.m_Y);
				//}
			}
			internal void Read(IInputStream input, bool half, bool sync_z)
            {
                m_ID = input.GetVU32();
                if (half)
                {
                    m_X = MoveHelper.ToPosF32(input.GetU16());
                    m_Y = MoveHelper.ToPosF32(input.GetU16());
                    if (sync_z) m_Z = MoveHelper.ToPosF32(input.GetU16());
                }
                else
                {
                    m_X = input.GetF32();
                    m_Y = input.GetF32();
                    if (sync_z) m_Z = input.GetF32();
                }
                m_Direction = MoveHelper.ToDirectionF32(input.GetU8());
            }

			public void SetX(float value)
			{
				//throw new NotImplementedException();
			}

			public void SetY(float value)
			{
				//throw new NotImplementedException();
			}

			public void AddX(float value)
			{
				//throw new NotImplementedException();
			}

			public void AddY(float value)
			{
				//throw new NotImplementedException();
			}
		}

        public struct UnitState
        {
            private uint m_ID;
            private byte m_UnitMainState;
            private byte m_UnitSubState;

            public uint ID { get { return m_ID; } }
            public UnitActionStatus UnitMainState
            {
                get { return (UnitActionStatus)m_UnitMainState; }
                set { m_UnitMainState = (byte)value; }
            }
            public byte UnitSubState
            {
                get { return m_UnitSubState; }
                set { m_UnitSubState = value; }
            }
            public void SetObject(InstanceUnit obj)
            {
                this.m_ID = obj.ID;
                this.m_UnitMainState = (byte)obj.CurrentActionStatus;
                this.m_UnitSubState = (byte)obj.CurrentActionSubstate;
            }
            internal void Write(IOutputStream output)
            {              
                output.PutVU32(m_ID);
                output.PutU8(m_UnitMainState);
                output.PutU8(m_UnitSubState);
				//if (m_ID == 2649)
				//{
				//	Console.WriteLine("SyncPos - " + this.ID + ", m_UnitMainState = " + m_UnitMainState + ", m_UnitSubState = " + m_UnitSubState);
				//}
			}
            internal void Read(IInputStream input)
            {
                m_ID = input.GetVU32();
                m_UnitMainState = input.GetU8();
                m_UnitSubState = input.GetU8();
            }
        }

        private BitSet8 mask = new BitSet8();
        private long pass_time_ms;
        public UnitPos[] units_pos;
        public UnitState[] units_st;

        public bool IsHalf
        {
            get { return mask.Get(0); }
            private set { mask.Set(0, value); }
        }
        public bool IsSyncZ
        {
            get { return mask.Get(1); }
            private set { mask.Set(1, value); }
        }

        public long PassTimeMS { get { return pass_time_ms; } }
        public bool IsEmpty { get { return (units_pos == null || units_pos.Length == 0) && (units_st == null || units_st.Length == 0); } }
        public SyncPosEvent() { }
        public SyncPosEvent(bool half, bool sync_z, long passtime)
        {
            this.IsHalf = half;
            this.IsSyncZ = sync_z;
            this.pass_time_ms = passtime;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutU8(mask.Mask);
            output.PutVS64(pass_time_ms);
            bool syncz = IsSyncZ;
            bool half = IsHalf;
            if (units_pos != null)
            {
                output.PutVS32(units_pos.Length);
                for (int i = 0; i < units_pos.Length; i++)
                {
                    units_pos[i].Write(output, half, syncz);
                }
            }
            else
            {
                output.PutVS32(0);
            }
            if (units_st != null)
            {
                output.PutVS32(units_st.Length);
                for (int i = 0; i < units_st.Length; i++)
                {
                    units_st[i].Write(output);
                }
            }
            else
            {
                output.PutVS32(0);
            }
        }
        override public void ReadExternal(IInputStream input)
        {
            this.mask.Mask = input.GetU8();
            this.pass_time_ms = input.GetVS64();
            bool syncz = IsSyncZ;
            bool half = IsHalf;

            this.units_pos = new UnitPos[input.GetVS32()];
            for (int i = 0; i < units_pos.Length; i++)
            {
                units_pos[i].Read(input, half, syncz);
            }
            this.units_st = new UnitState[input.GetVS32()];
            for (int i = 0; i < units_st.Length; i++)
            {
                //UnityEngine.Debug.Log("m_ID = "+units_st[i].ID + "   UnitMainState = " +units_st[i].UnitMainState);
                units_st[i].Read(input);
            }
        }
    }

    /// <summary>
    /// 服务端通知客户端执行一段脚本
    /// </summary>
    [MessageType(0x8007)]
    public class DoScriptEvent : ZoneEvent
    {
        public string ScriptFileName;

        public DoScriptEvent() { }
        public DoScriptEvent(string filename)
        {
            this.ScriptFileName = filename;
        }

        override public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(ScriptFileName);

        }
        override public void ReadExternal(IInputStream input)
        {
            this.ScriptFileName = input.GetUTF();
        }
    }

    /// <summary>
    /// 脚本系统指令
    /// </summary>
    [MessageType(0x8008)]
    public class ScriptCommandEvent : ZoneEvent
    {
        public string message;

        public ScriptCommandEvent() { }
        public ScriptCommandEvent(string msg)
        {
            this.message = msg;
        }

        override public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(message);

        }
        override public void ReadExternal(IInputStream input)
        {
            this.message = input.GetUTF();
        }
    }

    /// <summary>
    /// 游戏结束指令
    /// </summary>
    [MessageType(0x8009)]
    public class GameOverEvent : ZoneEvent
    {
        public string message;
        public int WinForce;
        public GameOverEvent() { }
        public GameOverEvent(int force, string msg)
        {
            this.WinForce = force;
            this.message = msg;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(message);
            output.PutS32(WinForce);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.message = input.GetUTF();
            this.WinForce = input.GetS32();
        }
    }

    [MessageType(0x800A)]
    public class DecorationChangedEvent : ZoneEvent
    {
        public string Name;
        public bool Enable;

        public DecorationChangedEvent() { }
        public DecorationChangedEvent(string name, bool enable)
        {
            this.Name = name;
            this.Enable = enable;
        }

        override public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(Name);
            output.PutBool(Enable);
        }

        override public void ReadExternal(IInputStream input)
        {
            this.Name = input.GetUTF();
            this.Enable = input.GetBool();
        }
    }

    [MessageType(0x800B)]
    public class SyncEnvironmentVarEvent : ZoneEvent
    {
        public string Key;
        public object Value;

        public SyncEnvironmentVarEvent() { }
        public SyncEnvironmentVarEvent(string key, object value)
        {
            this.Key = key;
            this.Value = value;
        }

        override public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(Key);
            output.PutData(Value);
        }

        override public void ReadExternal(IInputStream input)
        {
            DataType dtype;
            this.Key = input.GetUTF();
            this.Value = input.GetData(out dtype);
        }
    }

    [MessageType(0x800C)]
    public class ChangeBGMEvent : ZoneEvent
    {
        public string FileName;

        public ChangeBGMEvent() { }
        public ChangeBGMEvent(string file)
        {
            this.FileName = file;
        }

        override public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(FileName);
        }

        override public void ReadExternal(IInputStream input)
        {
            this.FileName = input.GetUTF();
        }
    }



    [MessageType(0x800D)]
    public class FlagTagChangedEvent : ZoneEvent
    {
        public string Name;
        public string Tag;

        public FlagTagChangedEvent() { }
        public FlagTagChangedEvent(string name, string tag = null)
        {
            this.Name = name;
            this.Tag = tag;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(Name);
            output.PutUTF(Tag);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.Name = input.GetUTF();
            this.Tag = input.GetUTF();
        }
    }

    #endregion

    //--------------------------------------------------------------------------

    #region OBJECT_EVENTS_0x8100


    /// <summary>
    /// 同步单位数据,频繁需要改变的数据
    /// </summary>
    [MessageType(0x8100)]
    public class UnitFieldChangedEvent : ObjectEvent
    {
        public const uint MASK_ALL = 0xFFFF;

        public const uint MASK_HP = 1;
        public const uint MASK_MP = 1 << 1;
        public const uint MASK_MAX_HP = 1 << 2;
        public const uint MASK_MAX_MP = 1 << 3;
        public const uint MASK_SPEED = 1 << 4;
        public const uint MASK_SP = 1 << 5;
        public const uint MASK_MAX_SP = 1 << 6;
        public const uint MASK_FCR = 1 << 7;
        public const uint MASK_MONEY = 1 << 8;
        public const uint MASK_LEVEL = 1 << 9;
        public const uint MASK_DUMMY_0 = 1 << 10;
        public const uint MASK_DUMMY_1 = 1 << 11;
        public const uint MASK_DUMMY_2 = 1 << 12;
        public const uint MASK_DUMMY_3 = 1 << 13;
        public const uint MASK_DUMMY_4 = 1 << 14;
        public const uint MASK_DUMMY_5 = 1 << 15;

        //-- NEW Property
        public const uint MASK_SKILL_CD_ACC = 1 << 16;
        public const uint MASK_CONTROLED_ACC = 1 << 17;
  
        public uint mask = 0;
        public int currentHP;
        public int currentMP;
        public int maxHP;
        public int maxMP;
        public int currentSP;
        public int maxSP;
        public float currentSpeed;
        public float currentFCR;
        public int currentMoney;
        public int level;
        public int dummy_0;
        public int dummy_1;
        public int dummy_2;
        public int dummy_3;
        public int dummy_4;
        public int dummy_5;

        //-- NEW Property
        public int skill_cd_acc;
        public int controled_acc;


        public UnitFieldChangedEvent() { }
        public UnitFieldChangedEvent(uint unit_id, ushort mask)
            : base(unit_id)
        {
            this.mask = mask;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutVU32(mask);
            if ((mask & MASK_HP) != 0) output.PutS32(currentHP);
            if ((mask & MASK_MP) != 0) output.PutS32(currentMP);
            if ((mask & MASK_MAX_HP) != 0) output.PutS32(maxHP);
            if ((mask & MASK_MAX_MP) != 0) output.PutS32(maxMP);
            if ((mask & MASK_SP) != 0) output.PutS32(currentSP);
            if ((mask & MASK_MAX_SP) != 0) output.PutS32(maxSP);
            if ((mask & MASK_SPEED) != 0) output.PutF32(currentSpeed);
            if ((mask & MASK_FCR) != 0) output.PutF32(currentFCR);
            if ((mask & MASK_MONEY) != 0) output.PutS32(currentMoney);
            if ((mask & MASK_LEVEL) != 0) output.PutS32(level);
            if ((mask & MASK_DUMMY_0) != 0) output.PutS32(dummy_0);
            if ((mask & MASK_DUMMY_1) != 0) output.PutS32(dummy_1);
            if ((mask & MASK_DUMMY_2) != 0) output.PutS32(dummy_2);
            if ((mask & MASK_DUMMY_3) != 0) output.PutS32(dummy_3);
            if ((mask & MASK_DUMMY_4) != 0) output.PutS32(dummy_4);
            if ((mask & MASK_DUMMY_5) != 0) output.PutS32(dummy_5);
            //-- NEW Property
            if ((mask & MASK_SKILL_CD_ACC) != 0) output.PutS32(skill_cd_acc);
            if ((mask & MASK_CONTROLED_ACC) != 0) output.PutS32(controled_acc);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.mask = input.GetVU32();
            if ((mask & MASK_HP) != 0) this.currentHP = input.GetS32();
            if ((mask & MASK_MP) != 0) this.currentMP = input.GetS32();
            if ((mask & MASK_MAX_HP) != 0) this.maxHP = input.GetS32();
            if ((mask & MASK_MAX_MP) != 0) this.maxMP = input.GetS32();
            if ((mask & MASK_SP) != 0) this.currentSP = input.GetS32();
            if ((mask & MASK_MAX_SP) != 0) this.maxSP = input.GetS32();
            if ((mask & MASK_SPEED) != 0) this.currentSpeed = input.GetF32();
            if ((mask & MASK_FCR) != 0) this.currentFCR = input.GetF32();
            if ((mask & MASK_MONEY) != 0) this.currentMoney = input.GetS32();
            if ((mask & MASK_LEVEL) != 0) this.level = input.GetS32();
            if ((mask & MASK_DUMMY_0) != 0) this.dummy_0 = input.GetS32();
            if ((mask & MASK_DUMMY_1) != 0) this.dummy_1 = input.GetS32();
            if ((mask & MASK_DUMMY_2) != 0) this.dummy_2 = input.GetS32();
            if ((mask & MASK_DUMMY_3) != 0) this.dummy_3 = input.GetS32();
            if ((mask & MASK_DUMMY_4) != 0) this.dummy_4 = input.GetS32();
            if ((mask & MASK_DUMMY_5) != 0) this.dummy_5 = input.GetS32();
            //-- NEW Property
            if ((mask & MASK_SKILL_CD_ACC) != 0) this.skill_cd_acc = input.GetS32();
            if ((mask & MASK_CONTROLED_ACC) != 0) this.controled_acc = input.GetS32();
        }
    }

    /// <summary>
    /// 单位进入吟唱状态
    /// </summary>
    [MessageType(0x810a)]
    public class UnitChantSkillEvent : ObjectEvent
    {
        public int skill_id;
        public int chant_ms;
        public UnitChantSkillEvent() { }
        public UnitChantSkillEvent(uint unit_id, SkillTemplate sk)
            : base(unit_id)
        {
            this.skill_id = sk.TemplateID;
            this.chant_ms = sk.ChantTimeMS;

        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(skill_id);
            output.PutVS32(chant_ms);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.skill_id = input.GetS32();
            this.chant_ms = input.GetVS32();
        }
    }


    /// <summary>
    /// 单位进入技能状态
    /// </summary>
    [MessageType(0x810b)]
    public class UnitLaunchSkillEvent : ObjectEvent
    {
        public int skill_id { get; private set; }
        /// <summary>
        /// 如果是单一动作,则标识是哪一段攻击
        /// </summary>
        public byte action_index { get; private set; }
        /// <summary>
        /// 技能每段动作的时间,单一动作的话(SkillTemplate.IsSingleAction),长度为1
        /// </summary>
        public int[] action_time_array { get; private set; }
        public int TotalCDTimeMS { get; private set; }
        public float action_speed { get; private set; }
        public Vector2 spell_target_pos { get; private set; }
        public uint target_object_id { get; private set; }

        //节点动作加速(加法)
        public float [] action_speed_add { get; private set; }

        private BitSet8 bitMask = new BitSet8();

        public bool IsSingleAction
        {
            get { return bitMask.Get(0); }
            private set { bitMask.Set(0, value); }
        }

        public bool ActionSpeedAddition
        {
            get { return bitMask.Get(1); }
            private set { bitMask.Set(1, value); }
        }

        public bool IsActionSpeedUP
        {
            get { return bitMask.Get(2); }
            private set { bitMask.Set(2, value); }
        }
        public bool IsActionTimeChanged
        {
            get { return bitMask.Get(3); }
            private set { bitMask.Set(3, value); }
        }
        public bool IsAutoFocusNearTarget
        {
            get { return bitMask.Get(4); }
            private set { bitMask.Set(4, value); }
        }
        public bool IsSpellTargetPos
        {
            get { return bitMask.Get(5); }
            private set { bitMask.Set(5, value); }
        }
        public bool IsTargetObject
        {
            get { return bitMask.Get(6); }
            private set { bitMask.Set(6, value); }
        }
        public bool IsChangeTotalCDTime
        {
            get { return bitMask.Get(7); }
            private set { bitMask.Set(7, value); }
        }

       
        public int TotalActionTimeMS
        {
            get
            {
                int total = 0;
                if (action_time_array != null)
                {
                    foreach (int timeMS in action_time_array)
                    {
                        total += timeMS;
                    }
                }
                return total;
            }
        }

        public UnitLaunchSkillEvent() { }
        public UnitLaunchSkillEvent(
            uint unit_id,
            SkillTemplate sk,
            byte actionIndex,
            float actionSpeed,
            int totalCDTimeMS,
            bool isAutoFaceToTarget,
            Vector2 spellTargetPos,
            uint targetObjectID,
            int lockActionStep)
            : base(unit_id)
        {
            this.skill_id = sk.TemplateID;
            this.action_speed = actionSpeed;
            this.TotalCDTimeMS = totalCDTimeMS;
            this.spell_target_pos = spellTargetPos;
            this.target_object_id = targetObjectID;

            this.IsAutoFocusNearTarget = isAutoFaceToTarget;
            this.IsSingleAction = sk.IsSingleAction;
            this.IsActionSpeedUP = (actionSpeed != 1f);
            this.IsTargetObject = (targetObjectID != 0);
            this.IsSpellTargetPos = spellTargetPos != null;
            this.IsChangeTotalCDTime = totalCDTimeMS != sk.CoolDownMS;
       

            this.action_speed_add = new float[sk.ActionQueue.Count];
            for(int i = 0; i < sk.ActionQueue.Count; i++)
            {
                if(sk.ActionQueue[i].ActionSpeedRate != 0.0f)
                {
                    this.action_speed_add[i] = sk.ActionQueue[i].ActionSpeedRate;
                    this.ActionSpeedAddition = true;
                }
            }

            if (sk.IsSingleAction || lockActionStep >= 0)
            {
                this.action_index = actionIndex;
                this.action_time_array = new int[] { sk.ActionQueue[actionIndex].TotalTimeMS };
            }
            else
            {
                this.action_index = 0;
                this.action_time_array = sk.ActionQueueTimeArray;
            }
        }

        public override void BeforeWrite(TemplateManager templates)
        {
            base.BeforeWrite(templates);
            var orgin_temp = templates.getSkill(skill_id);
            if (this.action_time_array == null)
            {
                this.IsActionTimeChanged = false;
            }
            else if (this.IsSingleAction)
            {
                this.IsActionTimeChanged = (this.action_time_array[0] != orgin_temp.ActionQueue[action_index].TotalTimeMS);
            }
            else
            {
                this.IsActionTimeChanged = !CUtils.ArraysEqual<int>(this.action_time_array, orgin_temp.ActionQueueTimeArray);
            }
        }
        public override void EndRead(TemplateManager templates)
        {
            base.EndRead(templates);
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(skill_id);
            output.PutU8(bitMask.Mask);

            if (IsSingleAction)
            {
                output.PutU8(action_index);
                if (IsActionTimeChanged) output.PutS32(action_time_array[0]);
            }
            else
            {
                if (IsActionTimeChanged) output.PutArray<int>(action_time_array, output.PutS32);
            }

            if (IsActionSpeedUP)
            {
                output.PutF32(action_speed);
            }
            if (IsChangeTotalCDTime)
            {
                output.PutVS32(TotalCDTimeMS);
            }
            if (IsTargetObject)
            {
                output.PutU32(this.target_object_id);
            }
            if (IsSpellTargetPos)
            {
                output.PutF32(spell_target_pos.X);
                output.PutF32(spell_target_pos.Y);
            }

            if(ActionSpeedAddition)
            {
                output.PutArray<float>(this.action_speed_add, output.PutF32);
            }
			//System.Console.WriteLine("释放技能:" + this.skill_id + ", " + this.action_index);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.skill_id = input.GetS32();
            this.bitMask.Mask = input.GetU8();

            if (IsSingleAction)
            {
                this.action_index = input.GetU8();
                if (IsActionTimeChanged) this.action_time_array = new int[] { input.GetS32() };
            }
            else
            {
                if (IsActionTimeChanged) this.action_time_array = input.GetArray<int>(input.GetS32);
            }
            if (IsActionSpeedUP)
            {
                this.action_speed = input.GetF32();
            }
            else
            {
                this.action_speed = 1f;
            }
            if (IsChangeTotalCDTime)
            {
                this.TotalCDTimeMS = input.GetVS32();
            }
            if (IsTargetObject)
            {
                this.target_object_id = input.GetU32();
            }
            if (IsSpellTargetPos)
            {
                spell_target_pos = new Vector2();
                spell_target_pos.SetX(input.GetF32());
                spell_target_pos.SetY(input.GetF32());
            }

            if (ActionSpeedAddition)
            {
                this.action_speed_add = input.GetArray<float>(input.GetF32);
            }
        }
        public override string ToString()
        {
            return string.Format("LaunchSkill: {0}@{1}", skill_id, action_index);
        }
    }

    /// <summary>
    /// 单位动作中击中别的单位
    /// </summary>
    [MessageType(0x810d)]
    public class UnitEffectEvent : ObjectEvent
    {
        private uint effect_sn = 0;
        /// <summary>
        /// 特效名字
        /// </summary>
        public LaunchEffect effect { get; set; }

        public UnitEffectEvent() { }
        public UnitEffectEvent(uint unit_id, LaunchEffect effect)
            : base(unit_id)
        {
            this.effect = effect;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutVU32(effect_sn);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.effect_sn = input.GetVU32();
        }
        public override void BeforeWrite(TemplateManager templates)
        {
            if (effect != null)
            {
                this.effect_sn = effect.SerialNumber;
            }
        }
        public override void EndRead(TemplateManager templates)
        {
            this.effect = templates.GetSnData<LaunchEffect>(effect_sn);
        }
    }

    /// <summary>
    /// 单位仅做一个动作
    /// </summary>
    [MessageType(0x810e)]
    public class UnitDoActionEvent : ObjectEvent
    {
        public string ActionName;
        public UnitDoActionEvent() { }
        public UnitDoActionEvent(uint unit_id, string actionName)
            : base(unit_id)
        {
            this.ActionName = actionName;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutUTF(ActionName);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            ActionName = input.GetUTF();
        }
    }

	/// <summary>
	/// 单位被击中
	/// </summary>
	[MessageType(0x810f)]
    public class UnitHitEvent : ObjectEvent
    {
        public bool isDead
        {
            get { return BitMask.BitGetMask(bitMask, 0); }
            set { BitMask.BitSetMask(ref bitMask, 0, value); }
        }

		//特殊来源的伤害
		public bool isSpecialHit
		{
			get { return BitMask.BitGetMask(bitMask, 1); }
			set { BitMask.BitSetMask(ref bitMask, 1, value); }
		}

        public bool isCritical
        {
            get { return BitMask.BitGetMask(bitMask, 2); }
            set { BitMask.BitSetMask(ref bitMask, 2, value); }
        }
        public bool HasEffect
        {
            get { return BitMask.BitGetMask(bitMask, 3); }
            private set { BitMask.BitSetMask(ref bitMask, 3, value); }
        }
        public bool HasSourceAttack
        {
            get { return BitMask.BitGetMask(bitMask, 6); }
            private set { BitMask.BitSetMask(ref bitMask, 6, value); }
        }

        public uint senderId;		
        public int hp;
        public byte client_state;

        private byte bitMask = 0;
        private LaunchEffect biteffect;
        private uint biteffect_sn;
        private AttackProp sourceAttack;
        private uint sourceAttack_sn;

		// 伤害来源,非def才需要额外处理
		public DamageSource dmgSrc;

		//内部字段
		//针对特殊伤害的特殊处理
		public bool InViewForceSend = false;
		public uint senderMasterId;         //如果sender为召唤物,这个存放主人id(用来广播判断,非网络字段)
		public uint hitMasterId;            //单位的masterid

		public LaunchEffect effect
        {
            get { return biteffect; }
            set
            {
                this.biteffect = value;
                this.HasEffect = (value != null);
            }
        }
        public AttackProp SourceAttack
        {
            get { return sourceAttack; }
            set
            {
                this.sourceAttack = value;
                this.HasSourceAttack = (value != null);
            }
        }

        public UnitHitEvent() { }
        public UnitHitEvent(uint unit_id)
            : base(unit_id)
        {
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutVU32(senderId);
            output.PutVS32(hp);
            output.PutU8(client_state);
            output.PutU8(bitMask);
            if (HasEffect)
            {
                output.PutVU32(biteffect_sn);
            }
            if (HasSourceAttack)
            {
                output.PutVU32(sourceAttack_sn);
            }

			if(isSpecialHit)
			{
				output.PutEnum8(dmgSrc);
			}

			//Console.WriteLine("WWW.object_id: " + object_id + ", senderId: " + senderId + ", hp: " + this.hp + ", mask : " + this.bitMask);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.senderId = input.GetVU32();
            this.hp = input.GetVS32();
            this.client_state = input.GetU8();
            this.bitMask = input.GetU8();
            if (HasEffect)
            {
                this.biteffect_sn = input.GetVU32();
            }
            if (HasSourceAttack)
            {
                this.sourceAttack_sn = input.GetVU32();
            }
			if(isSpecialHit)
			{
				this.dmgSrc = input.GetEnum8<DamageSource>();
			}

			//System.Console.WriteLine("sdfasdf: " + isSpecialHit + ", " + this.dmgSrc);
			//UnityEngine.Debug.LogError("RRR.object_id: " + object_id + ", senderId: " + senderId + ", hp: " + this.hp + ", mask : " + this.bitMask);
		}
        public override void BeforeWrite(TemplateManager templates)
        {
            if (HasEffect)
            {
                this.biteffect_sn = biteffect.SerialNumber;
            }
            if (HasSourceAttack)
            {
                this.sourceAttack_sn = sourceAttack.SerialNumber;
            }
        }
        public override void EndRead(TemplateManager templates)
        {
            if (HasEffect)
            {
                this.biteffect = templates.GetSnData<LaunchEffect>(biteffect_sn);
            }
            if (HasSourceAttack)
            {
                this.sourceAttack = templates.GetSnData<AttackProp>(sourceAttack_sn);
            }
        }
    }

    /// <summary>
    /// 单位被击中
    /// </summary>
    [MessageType(0x8111)]
    public class UnitDeadEvent : ObjectEvent
    {
        public bool Crushed;
        public uint attacker_id;
        public int RebirthTimeMS;

        public UnitDeadEvent() { }
        public UnitDeadEvent(uint unit_id, uint attacker_id, bool crushed, int rebirthTimeMS)
            : base(unit_id)
        {
            this.Crushed = crushed;
            this.attacker_id = attacker_id;
            this.RebirthTimeMS = rebirthTimeMS;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutBool(Crushed);
            output.PutVU32(attacker_id);
            output.PutVS32(RebirthTimeMS);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.Crushed = input.GetBool();
            this.attacker_id = input.GetVU32();
            this.RebirthTimeMS = input.GetVS32();
        }
    }

    /// <summary>
    /// 单位中BUFF
    /// </summary>
    [MessageType(0x8112)]
    public class UnitLaunchBuffEvent : ObjectEvent
    {
        public bool IsEquip
        {
            get { return BitMask.BitGetMask(bitMask, 0); }
            set { BitMask.BitSetMask(ref bitMask, 0, value); }
        }
        public bool IsOverlayLevel
        {
            get { return BitMask.BitGetMask(bitMask, 1); }
            set { BitMask.BitSetMask(ref bitMask, 1, value); }
        }

        public bool IsHasExtData
        {
            get { return BitMask.BitGetMask(bitMask, 2); }
            set { BitMask.BitSetMask(ref bitMask, 2, value); }
        }

        private byte bitMask = 0;


        public int buffTemplateID;
        public int buffTimeMS;
        public byte overlayLevel;
        public uint senderID;
        public int buffExtData;             //buff的扩展字段,

        public UnitLaunchBuffEvent() { }
        public UnitLaunchBuffEvent(uint unit_id, int buffID, uint senderID, int timeMS, bool equip, byte overlayLevel, int extData)
            : base(unit_id)
        {
            this.buffTemplateID = buffID;
            this.buffTimeMS = timeMS;
            this.senderID = senderID;
            this.IsEquip = equip;
            if (overlayLevel > 0)
            {
                this.IsOverlayLevel = true;
                this.overlayLevel = overlayLevel;
            }

            if(extData > 0)
            {
                this.IsHasExtData = true;
                this.buffExtData = extData;
            }
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU8(bitMask);
            output.PutS32(buffTemplateID);
            output.PutVU32(senderID);
            if (!IsEquip)
            {
                output.PutVS32(buffTimeMS);
            }
            if (IsOverlayLevel)
            {
                output.PutU8(overlayLevel);
            }

            if (IsHasExtData)
            {
                output.PutVS32(buffExtData);
            }
			//System.Console.WriteLine("UnitLaunchBuffEvent: " + buffTemplateID + ", " + buffTimeMS);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.bitMask = input.GetU8();
            this.buffTemplateID = input.GetS32();
            this.senderID = input.GetVU32();
            if (!IsEquip)
            {
                this.buffTimeMS = input.GetVS32();
            }
            if (IsOverlayLevel)
            {
                this.overlayLevel = input.GetU8();
            }

            if (IsHasExtData)
            {
                this.buffExtData = input.GetVS32();
            }
        }
    }

    /// <summary>
    /// 单位停止BUFF
    /// </summary>
    [MessageType(0x8113)]
    public class UnitStopBuffEvent : ObjectEvent
    {
        public int buffTemplateID;
        public uint senderID;

        public UnitStopBuffEvent() { }
        public UnitStopBuffEvent(uint unit_id, int buffID, uint senderID)
            : base(unit_id)
        {
            this.buffTemplateID = buffID;
            this.senderID = senderID;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(buffTemplateID);
            output.PutVU32(senderID);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.buffTemplateID = input.GetS32();
            this.senderID = input.GetVU32();
        }
    }


    /// <summary>
    /// 单位同步【库存道具】
    /// </summary>
    [MessageType(0x8114)]
    public class UnitSyncInventoryItemEvent : ObjectEvent, ActorMessage
    {
        public int ItemTemplateID;
        public int Index;
        public int Count;

        public UnitSyncInventoryItemEvent() { }
        public UnitSyncInventoryItemEvent(uint unit_id, int itemID, int index, int count)
            : base(unit_id)
        {
            this.ItemTemplateID = itemID;
            this.Index = index;
            this.Count = count;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(ItemTemplateID);
            output.PutVS32(Index);
            output.PutVS32(Count);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.ItemTemplateID = input.GetS32();
            this.Index = input.GetVS32();
            this.Count = input.GetVS32();
        }
    }

    /// <summary>
    /// 单位使用道具
    /// </summary>
    [MessageType(0x8115)]
    public class UnitUseItemEvent : ObjectEvent, ActorMessage
    {
        public int ItemTemplateID;

        public UnitUseItemEvent() { }
        public UnitUseItemEvent(uint unit_id, int itemID)
            : base(unit_id)
        {
            this.ItemTemplateID = itemID;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(ItemTemplateID);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.ItemTemplateID = input.GetS32();
        }
    }

    [MessageType(0x8116)]
    public class UnitSyncMultiTimeLine : ObjectEvent
    {
        public List<bool> timelines;
        public UnitSyncMultiTimeLine() { }
        public UnitSyncMultiTimeLine(uint unit_id) : base(unit_id) { }
        public bool Update(List<MultiTimeLine> tlines)
        {
            bool ret = false;
            if (timelines == null)
            {
                timelines = new List<bool>(tlines.Count);
            }
            if (timelines.Count != tlines.Count)
            {
                CUtils.SetListSize<bool>(timelines, tlines.Count);
                ret = true;
            }
            for (int i = tlines.Count - 1; i >= 0; --i)
            {
                if (timelines[i] != tlines[i].Enable)
                {
                    timelines[i] = tlines[i].Enable;
                    ret = true;
                }
            }
            return ret;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutList(timelines, output.PutBool);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.timelines = input.GetList<bool>(input.GetBool);
        }
    }

    /// <summary>
    /// 单位复活
    /// </summary>
    [MessageType(0x8117)]
    public class UnitRebirthEvent : ObjectEvent
    {
        public UnitRebirthEvent() { }
        public UnitRebirthEvent(uint unit_id) : base(unit_id) { }
    }


	/// <summary>
	/// 用户连斩数
	/// </summary>
	[MessageType(0x8118)]
	public class UnitContinueKillValue : ObjectEvent
	{
		public short continuekills;
		public UnitContinueKillValue() { }
		public UnitContinueKillValue(uint unit_id, short continuekills)
			: base(unit_id)
		{
			this.continuekills = continuekills;
		}
		override public void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);
			output.PutS16(continuekills);
		}
		override public void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
			continuekills = input.GetS16();
		}
	}

	/// <summary>
	/// 单位受攻击
	/// </summary>
	[MessageType(0x8119)]
    public class UnitDamageEvent : ObjectEvent
    {
        public bool HasDamageTime
        {
            get { return mask.Get(0); }
            private set { mask.Set(0, value); }
        }
        public bool HasFly
        {
            get { return mask.Get(1); }
            private set { mask.Set(1, value); }
        }
        public bool HasZLimit
        {
            get { return mask.Get(2); }
            private set { mask.Set(2, value); }
        }
        public bool HasKnockDown
        {
            get { return mask.Get(3); }
            private set { mask.Set(3, value); }
        }
        public bool HasZGravity
        {
            get { return mask.Get(4); }
            private set { mask.Set(4, value); }
        }
        public bool HasMoveTime
        {
            get { return mask.Get(5); }
            private set { mask.Set(5, value); }
        }

        public AttackProp Source { get; private set; }

        /// <summary>
        /// 总共受击时间(位移时间+受击时间)
        /// </summary>
        public int TotalTimeMS
        {
            get { return MoveTimeMS + DamageTimeMS; }
        }
        /// <summary>
        /// 特殊受击动作
        /// </summary>
        public string DamageActionName
        {
            get { return Source.DamageActionName; }
        }
        /// <summary>
        /// 受击的特殊动作
        /// </summary>
        public bool HasDamageAction
        {
            get { return !string.IsNullOrEmpty(Source.DamageActionName); }
        }

        private BitSet8 mask = new BitSet8();
        private uint source_sn = 0;
        public int DamageTimeMS = 0;
        public int MoveTimeMS = 0;
        public float ZSpeedSEC = 0;
        public float ZLimit = 0;
        public float ZGravity = 0;

        public UnitDamageEvent() { }
        public UnitDamageEvent(uint unit_id, int damageTimeMS, int moveTimeMS, float zspeed, float zgravity, float zlimit, bool knockDown, AttackProp source)
            : base(unit_id)
        {
            this.Source = source;

            this.DamageTimeMS = damageTimeMS;

            this.MoveTimeMS = moveTimeMS;
            this.ZSpeedSEC = zspeed;
            this.ZLimit = zlimit;
            this.ZGravity = zgravity;

            this.HasDamageTime = (DamageTimeMS != 0);
            this.HasMoveTime = (MoveTimeMS != 0);
            this.HasFly = (zspeed != 0);
            this.HasZGravity = (zgravity != 0);
            this.HasZLimit = (zlimit > 0);
            this.HasKnockDown = knockDown;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU8(mask.Mask);
            output.PutVU32(source_sn);
            if (HasDamageTime)
            {
                output.PutVS32(DamageTimeMS);
            }
            if (HasMoveTime)
            {
                output.PutVS32(MoveTimeMS);
            }
            if (HasFly)
            {
                output.PutF32(ZSpeedSEC);
            }
            if (HasZLimit)
            {
                output.PutF32(ZLimit);
            }
            if (HasZGravity)
            {
                output.PutF32(ZGravity);
            }
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.mask.Mask = input.GetU8();
            this.source_sn = input.GetVU32();
            if (HasDamageTime)
            {
                this.DamageTimeMS = input.GetVS32();
            }
            if (HasMoveTime)
            {
                this.MoveTimeMS = input.GetVS32();
            }
            if (HasFly)
            {
                this.ZSpeedSEC = input.GetF32();
            }
            if (HasZLimit)
            {
                this.ZLimit = input.GetF32();
            }
            if (HasZGravity)
            {
                this.ZGravity = input.GetF32();
            }
        }
        public override void BeforeWrite(TemplateManager templates)
        {
            if (Source != null)
            {
                this.source_sn = Source.SerialNumber;
            }
        }
        public override void EndRead(TemplateManager templates)
        {
            if (source_sn != 0)
            {
                this.Source = templates.GetSnData<AttackProp>(source_sn);
            }
        }
    }

    /// <summary>
    /// 技能动作序列被意外取消
    /// </summary>
    [MessageType(0x811A)]
    public class UnitSkillActionChangeEvent : ObjectEvent
    {
        public byte ActionIndex;
        public UnitSkillActionChangeEvent() { }
        public UnitSkillActionChangeEvent(uint unit_id, byte index)
            : base(unit_id)
        {
            this.ActionIndex = index;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU8(ActionIndex);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.ActionIndex = input.GetU8();
        }
    }


    /// <summary>
    /// 单位开始检取道具读条
    /// </summary>
    [MessageType(0x811B)]
    public class UnitStartPickObjectEvent : ObjectEvent
    {
        public int PickTimeMS;
        public uint PickObjectID;
        public string PickStatus;
        public UnitStartPickObjectEvent() { }
        public UnitStartPickObjectEvent(uint unit_id, int pickTimeMS, uint pickObjID, string status)
            : base(unit_id)
        {
            this.PickTimeMS = pickTimeMS;
            this.PickObjectID = pickObjID;
            this.PickStatus = status;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutVS32(PickTimeMS);
            output.PutVU32(PickObjectID);
            output.PutUTF(PickStatus);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.PickTimeMS = input.GetVS32();
            this.PickObjectID = input.GetVU32();
            this.PickStatus = input.GetUTF();
        }
    }

    [MessageType(0x811C)]
    public class UnitStopPickObjectEvent : ObjectEvent
    {
        public string StopReason;
        public UnitStopPickObjectEvent() { }
        public UnitStopPickObjectEvent(uint unit_id, string reason)
            : base(unit_id)
        {
            this.StopReason = reason;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutUTF(StopReason);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.StopReason = input.GetUTF();
        }
    }

    /// <summary>
    /// 单位从场景中获得道具
    /// </summary>
    [MessageType(0x811D)]
    public class UnitGotInstanceItemEvent : ObjectEvent, ActorMessage
    {
        public uint ItemObjectID;
		public byte flag;			//0-后续可以继续采集,1-后续不可继续采集
        public UnitGotInstanceItemEvent() { }
        public UnitGotInstanceItemEvent(uint unit_id, uint pickObjID, byte flag = 0)
            : base(unit_id)
        {
            this.ItemObjectID = pickObjID;
			this.flag = flag;
		}
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU32(ItemObjectID);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.ItemObjectID = input.GetU32();
        }
    }

    /// <summary>
    /// 别的单位释放技能跳起
    /// </summary>
    [MessageType(0x811E)]
    public class UnitJumpEvent : ObjectEvent
    {
        public float ZSpeed;
        public float ZLimit;
        public float ZGravity;

        public UnitJumpEvent() { }
        public UnitJumpEvent(uint unit_id, float zspeed, float zgravity, float zlimit)
            : base(unit_id)
        {
            this.ZSpeed = zspeed;
            this.ZLimit = zlimit;
            this.ZGravity = zgravity;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutF32(ZSpeed);
            output.PutF32(ZLimit);
            output.PutF32(ZGravity);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.ZSpeed = input.GetF32();
            this.ZLimit = input.GetF32();
            this.ZGravity = input.GetF32();
        }
    }

    /// <summary>
    /// 立即同步客户端坐标,比如单位传送之类,用于MoveByClient的模式
    /// </summary>
    [MessageType(0x811F)]
    public class UnitForceSyncPosEvent : ObjectEvent
    {
        public float X;
        public float Y;
        public float Direction;
        public byte UnitMainState;
        public byte UnitSubState;

        public UnitForceSyncPosEvent() { }
        public UnitForceSyncPosEvent(uint unit_id, float x, float y, float d, byte state, byte sub_state)
            : base(unit_id)
        {
            this.X = x;
            this.Y = y;
            this.Direction = d;
            this.UnitMainState = state;
            this.UnitSubState = sub_state;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutF32(this.X);
            output.PutF32(this.Y);
            output.PutF32(this.Direction);
            output.PutU8(this.UnitMainState);
            output.PutU8(this.UnitSubState);

			//if (this.object_id == 2649)
			//{
			//	Console.WriteLine("ForceSync-" + this.object_id + ", X: " + this.X + ", \t Y: " + this.Y + ", " + this.UnitMainState + ", " + this.UnitSubState);
			//}
		}
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.X = input.GetF32();
            this.Y = input.GetF32();
            this.Direction = input.GetF32();
            this.UnitMainState = input.GetU8();
            this.UnitSubState = input.GetU8();
		}
    }


    /// <summary>
    /// 立即同步客户端坐标,比如单位传送之类,用于MoveByClient的模式
    /// </summary>
    [MessageType(0x8120)]
    public class ObjectForceSyncPosEvent : ObjectEvent
    {
        public float X;
        public float Y;
        public float Direction;

        public ObjectForceSyncPosEvent() { }
        public ObjectForceSyncPosEvent(uint unit_id, float x, float y, float d)
            : base(unit_id)
        {
            this.X = x;
            this.Y = y;
            this.Direction = d;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutF32(this.X);
            output.PutF32(this.Y);
            output.PutF32(this.Direction);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.X = input.GetF32();
            this.Y = input.GetF32();
            this.Direction = input.GetF32();
        }
    }




    /// <summary>
    /// Missile类法术,锁定单位时触发
    /// </summary>
    [MessageType(0x8130)]
    public class SpellLockTargetEvent : ObjectEvent, PositionMessage
    {
        public uint target_obj_id;
        private float x;
        private float y;
        public SpellLockTargetEvent() { }
        public SpellLockTargetEvent(uint spell_id, uint target_obj_id, float x, float y)
            : base(spell_id)
        {
            this.target_obj_id = target_obj_id;
            this.x = x;
            this.y = y;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutVU32(target_obj_id);
        }

        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.target_obj_id = input.GetVU32();
        }

        public float X { get { return x; } }
        public float Y { get { return y; } }
    }

    #endregion

    //--------------------------------------------------------------------------

    #region CONTROL_0x8200

    /// <summary>
    /// 单位待机
    /// </summary>
    [MessageType(0x8200)]
    public class UnitGuardAction : ObjectAction
    {
        public bool guard = false;
        public string reason = null;
        public bool forceNotify = false;

        public UnitGuardAction() { }
        public UnitGuardAction(uint unit_id, bool guard)
            : base(unit_id)
        {
            this.guard = guard;
        }

        public UnitGuardAction(uint unit_id, bool guard, string reason)
        : base(unit_id)
        {
            this.guard = guard;
            this.reason = reason;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutBool(guard);
            output.PutUTF(reason);
        }

        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.guard = input.GetBool();
            this.reason = input.GetUTF();
        }
    }

    /// <summary>
    /// A过去
    /// </summary>
    [MessageType(0x8206)]
    public class UnitAttackToAction : ObjectAction
    {
        public float targetX;
        public float targetY;
        public bool attack;

        public UnitAttackToAction() { }
        public UnitAttackToAction(uint unit_id, float x, float y, bool attack)
            : base(unit_id)
        {
            this.targetX = x;
            this.targetY = y;
            this.attack = attack;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutF32(targetX);
            output.PutF32(targetY);
            output.PutBool(attack);
        }

        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.targetX = input.GetF32();
            this.targetY = input.GetF32();
            this.attack = input.GetBool();
        }
    }

    /// <summary>
    /// 单位移动
    /// </summary>
    [MessageType(0x8201)]
    public class UnitMoveAction : ObjectAction
    {
        public float x;
        public float y;

        public UnitMoveAction() { }
        public UnitMoveAction(uint unit_id, float x, float y)
            : base(unit_id)
        {
            this.x = x;
            this.y = y;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutF32(x);
            output.PutF32(y);
        }

        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.x = input.GetF32();
            this.y = input.GetF32();
        }
    }

    /// <summary>
    /// 玩家选择朝向
    /// </summary>
    [MessageType(0x8202)]
    public class UnitFaceToAction : ObjectAction
    {
        public float Direction;

        public UnitFaceToAction() { }
        public UnitFaceToAction(uint unit_id, float d)
            : base(unit_id)
        {
            this.Direction = d;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutF32(Direction);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.Direction = input.GetF32();
        }
    }

    /// <summary>
    /// 单位移动
    /// </summary>
    [MessageType(0x8203)]
    public class UnitSlipAction : ObjectAction
    {
        public float x;
        public float y;

        public UnitSlipAction() { }
        public UnitSlipAction(uint unit_id, float x, float y)
            : base(unit_id)
        {
            this.x = x;
            this.y = y;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutF32(x);
            output.PutF32(y);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.x = input.GetF32();
            this.y = input.GetF32();
        }
    }

    /// <summary>
    /// 锁定目标
    /// </summary>
    [MessageType(0x8204)]
    public class UnitFocuseTargetAction : ObjectAction
    {
        public uint targetUnitID;

        public UnitFocuseTargetAction() { }
        public UnitFocuseTargetAction(uint unit_id, uint target_id)
            : base(unit_id)
        {
            this.targetUnitID = target_id;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU32(targetUnitID);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.targetUnitID = input.GetU32();
        }
    }

    /// <summary>
    /// 单位技能动作
    /// </summary>
    [MessageType(0x8205)]
    public class UnitLaunchSkillAction : ObjectAction
    {
        private BitSet8 mask = new BitSet8();
        public bool IsAutoFocusNearTarget
        {
            get { return mask.Get(0); }
            set { mask.Set(0, value); }
        }
        private bool IsTargetID
        {
            get { return mask.Get(1); }
            set { mask.Set(1, value); }
        }
        private bool IsTargetPos
        {
            get { return mask.Get(2); }
            set { mask.Set(2, value); }
        }
        public bool SyncDirection
        {
            get { return mask.Get(3); }
            set { mask.Set(3, value); }
        }

        public int SkillID;
        public uint TargetObjID = 0;
        public Vector2 SpellTargetPos = null;
        public float Direction = 0;

        public UnitLaunchSkillAction() { }
        public UnitLaunchSkillAction(uint unit_id, int skill_id, bool autoFocuseTarget = false, uint targetObjID = 0, Vector2 spellTargetPos = null, float direction = 0.0f)
            : base(unit_id)
        {
            this.SkillID = skill_id;
            this.TargetObjID = targetObjID;
            this.SpellTargetPos = spellTargetPos;
            this.IsAutoFocusNearTarget = autoFocuseTarget;
            this.Direction = direction;
        }
        override public void WriteExternal(IOutputStream output)
        {
            this.IsTargetID = (TargetObjID != 0);
            this.IsTargetPos = (SpellTargetPos != null);

            base.WriteExternal(output);
            mask.WriteExternal(output);
            output.PutS32(SkillID);
            if (SyncDirection)
            {
                output.PutF32(Direction);
            }
            

            if (IsTargetID)
            {
                output.PutU32(TargetObjID);
            }
            if (IsTargetPos)
            {
                output.PutF32(SpellTargetPos.X);
                output.PutF32(SpellTargetPos.Y);
            }
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            mask.ReadExternal(input);
            this.SkillID = input.GetS32();
            if (SyncDirection)
            {
                this.Direction = input.GetF32();
            }

            if (IsTargetID)
            {
                this.TargetObjID = input.GetU32();
            }
            if (IsTargetPos)
            {
                this.SpellTargetPos = new Vector2();
                this.SpellTargetPos.SetX(input.GetF32());
                this.SpellTargetPos.SetY(input.GetF32());
            }
        }
    }

    /// <summary>
    /// 客户端手动控制同步包
    /// </summary>
    [MessageType(0x8207)]
    public class UnitAxisAction : ObjectAction
    {
        public bool IsZero { get { return dx == 0 && dy == 0; } }
        public float dx;
        public float dy;

        public UnitAxisAction() { }
        public UnitAxisAction(uint unit_id)
            : base(unit_id)
        {
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            float angle = (float)Math.Atan2(dy, dx);
            output.PutS8((sbyte)(Math.Cos(angle) * 100f));
            output.PutS8((sbyte)(Math.Sin(angle) * 100f));
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.dx = input.GetS8() / 100f;
            this.dy = input.GetS8() / 100f;
        }
        public bool AxisEquals(UnitAxisAction obj)
        {
            if (obj == null) return false;
            return (obj.dx == this.dx) && (obj.dy == this.dy);
        }
    }

    /// <summary>
    /// 客户端手动控制同步包
    /// </summary>
    [MessageType(0x8208)]
    public class UnitStopMoveAction : ObjectAction
    {
        public UnitStopMoveAction() { }
        public UnitStopMoveAction(uint unit_id)
            : base(unit_id)
        {
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
        }
    }

    /// <summary>
    /// 单位使用道具
    /// </summary>
    [MessageType(0x8209)]
    public class UnitUseItemAction : ObjectAction
    {
        public int Index;
        public int Count;
        public UnitUseItemAction() { }
        public UnitUseItemAction(uint unit_id, int index, int count = 1)
            : base(unit_id)
        {
            this.Index = index;
            this.Count = count;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutVS32(this.Index);
            output.PutVS32(this.Count);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.Index = input.GetVS32();
            this.Count = input.GetVS32();
        }
    }

    /// <summary>
    /// 单位手动检取场景道具
    /// </summary>
    [MessageType(0x820A)]
    public class UnitPickObjectAction : ObjectAction
    {
        public uint PickableObjectID;
        public UnitPickObjectAction() { }
        public UnitPickObjectAction(uint unit_id, uint item_obj_id)
            : base(unit_id)
        {
            this.PickableObjectID = item_obj_id;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutVU32(this.PickableObjectID);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.PickableObjectID = input.GetVU32();
        }
    }

    /// <summary>
    /// 单位移动
    /// </summary>
    [MessageType(0x820B)]
    public class UnitUpdatePosAction : ObjectAction
    {
        public bool isHalf;
        public float x;
        public float y;
        public float d;
        public UnitActionStatus st;

        public UnitUpdatePosAction() { }
        public UnitUpdatePosAction(uint unit_id, bool isHalf, float x, float y, float d, UnitActionStatus s)
            : base(unit_id)
        {
            this.isHalf = isHalf;
            this.x = x;
            this.y = y;
            this.d = d;
            this.st = s;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutBool(isHalf);
            if (isHalf)
            {
                output.PutU16(MoveHelper.ToPos16(x));
                output.PutU16(MoveHelper.ToPos16(y));
                output.PutU8(MoveHelper.ToDirectionD8(d));
            }
            else
            {
                output.PutF32(x);
                output.PutF32(y);
                output.PutF32(d);
            }
            output.PutEnum8(st);
        }

        override public void ReadExternal(IInputStream input)
        {			
			base.ReadExternal(input);
            this.isHalf = input.GetBool();
            if (isHalf)
            {
                this.x = MoveHelper.ToPosF32(input.GetU16());
                this.y = MoveHelper.ToPosF32(input.GetU16());
                this.d = MoveHelper.ToDirectionF32(input.GetU8());
            }
            else
            {
                this.x = input.GetF32();
                this.y = input.GetF32();
                this.d = input.GetF32();
            }
            this.st = input.GetEnum8<UnitActionStatus>();

			//Console.WriteLine("-------------------UnitUpdatePosAction : " + TimeUtil.GetTimestampMS() + this.x + ", " + this.y + " \t \t" + this.st);
		}

        public bool DataEquals(UnitUpdatePosAction o)
        {
            if (o == null) return false;
            return o.x == this.x && o.y == this.y && o.d == this.d && o.st == this.st;
        }

        public void Set(UnitUpdatePosAction other)
        {
            this.object_id = other.object_id;
            this.isHalf = other.isHalf;
            this.x = other.x;
            this.y = other.y;
            this.d = other.d;
            this.st = other.st;
        }
    }

    [MessageType(0x820C)]
    public class UnitSetSyncModeAction : ObjectAction
    {
        public SyncMode Mode;
        public UnitSetSyncModeAction() { }
        public UnitSetSyncModeAction(uint unit_id, SyncMode mode)
            : base(unit_id)
        {
            this.Mode = mode;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutEnum8(Mode);
        }

        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.Mode = input.GetEnum8<SyncMode>();
        }
    }

    [MessageType(0x820D)]
    public class UnitCancelBuffAction : ObjectAction
    {
        public int BuffID;
        public UnitCancelBuffAction() { }
        public UnitCancelBuffAction(uint unit_id, int buffID)
            : base(unit_id)
        {
            this.BuffID = buffID;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(BuffID);
        }

        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.BuffID = input.GetS32();
        }
    }




    /// <summary>
    /// 单位统计数据
    /// </summary>
    public class UnitStatisticData : IExternalizable
    {
        public uint ObjectID;


        /// <summary>
        /// 死亡次数
        /// </summary>
        public int DeadCount;
        /// <summary>
        /// 总共杀死单位数量
        /// </summary>
        public int KillUnitCount;
        /// <summary>
        /// 总共杀死玩家数量
        /// </summary>
        public int KillPlayerCount;

        /// <summary>
        /// 承受伤害
        /// </summary>
        public long SelfDamage;
        /// <summary>
        /// 对所有单位造成的总伤害
        /// </summary>
        public long TotalDamage;
        /// <summary>
        /// 对玩家造成的总伤害
        /// </summary>
        public long PlayerDamage;

        /// <summary>
        /// 对所有单位输出的总治疗量
        /// </summary>
        public long TotalHealing;
        /// <summary>
        /// 对玩家输出的总治疗量
        /// </summary>
        public long PlayerHealing;

        public virtual void WriteExternal(IOutputStream output)
        {
            output.PutVU32(ObjectID);
            output.PutVS32(DeadCount);
            output.PutVS32(KillUnitCount);
            output.PutVS32(KillPlayerCount);
            output.PutVS64(SelfDamage);
            output.PutVS64(TotalDamage);
            output.PutVS64(PlayerDamage);
            output.PutVS64(TotalHealing);
            output.PutVS64(PlayerHealing);
        }

        public virtual void ReadExternal(IInputStream input)
        {
            ObjectID = input.GetVU32();
            DeadCount = input.GetVS32();
            KillUnitCount = input.GetVS32();
            KillPlayerCount = input.GetVS32();
            SelfDamage = input.GetVS64();
            TotalDamage = input.GetVS64();
            PlayerDamage = input.GetVS64();
            TotalHealing = input.GetVS64();
            PlayerHealing = input.GetVS64();
        }
    }

    [MessageType(0x8210)]
    public class UnitGetStatisticRequest : ActorRequest
    {
        public uint[] RequestObjectsID;
        public UnitGetStatisticRequest() { }
        public UnitGetStatisticRequest(uint objID, params uint[] objectsID) : base(objID)
        {
            this.RequestObjectsID = objectsID;
        }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(MessageID);
            output.PutArray(RequestObjectsID, output.PutU32);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.MessageID = input.GetS32();
            this.RequestObjectsID = input.GetArray<uint>(input.GetU32);
        }
    }

    [MessageType(0x8211)]
    public class UnitGetStatisticResponse : ActorResponse
    {
        public HashMap<uint, UnitStatisticData> Statistics = new HashMap<uint, UnitStatisticData>();

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(MessageID);
            output.PutVS32(Statistics.Count);
            foreach (KeyValuePair<uint, UnitStatisticData> e in Statistics)
            {
                output.PutU32(e.Key);
                output.PutExt(e.Value);
            }
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.MessageID = input.GetS32();
            int count = input.GetVS32();
            for (int i = 0; i < count; i++)
            {
                var key = input.GetU32();
                var data = input.GetExtAny() as UnitStatisticData;
                Statistics.Put(key, data);
            }
        }
    }

    /// <summary>
    /// 设置子动做
    /// </summary>
    [MessageType(0x8212)]
    public class UnitSetSubStateAction : ObjectAction
    {
        public byte UnitSubState;

        public UnitSetSubStateAction() { }
        public UnitSetSubStateAction(uint objID, byte state)
            : base(objID)
        {
            this.UnitSubState = state;
        }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU8(UnitSubState);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.UnitSubState = input.GetU8();
        }
    }

    /// <summary>
    /// 单位准备完毕
    /// </summary>
    [MessageType(0x8213)]
    public class UnitReadAction : ObjectAction
    {
        public UnitReadAction() { }
        public UnitReadAction(uint objID)
            : base(objID)
        {
        }
        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
        }
    }

    #endregion

    //--------------------------------------------------------------------------

    //--------------------------------------------------------------------------------------------------------------

    #region CLIENT_EVENTS_0x8300

    public abstract class ClientEvent : ZoneEvent
    {
    }

    /// <summary>
    /// 显示箭头
    /// </summary>
    [MessageType(0x8300)]
    public class LookAtEvent : ClientEvent
    {
        public string target;
        public float x;
        public float y;
        public LookAtEvent() { }
        public LookAtEvent(string target, float x, float y)
        {
            this.target = target;
            this.x = x;
            this.y = y;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(target);
            output.PutF32(x);
            output.PutF32(y);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.target = input.GetUTF();
            this.x = input.GetF32();
            this.y = input.GetF32();
        }
    }
    /// <summary>
    /// 改变游戏运行速度
    /// </summary>
    [MessageType(0x8301)]
    public class ChangeTimeScaleEvent : ClientEvent
    {
        /// <summary>
        /// 时间尺度百分比
        /// </summary>
        public float TimeScalePct = 100f;
        public ChangeTimeScaleEvent() { }
        public ChangeTimeScaleEvent(float pct)
        {
            this.TimeScalePct = pct;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutF32(TimeScalePct);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.TimeScalePct = input.GetF32();
        }
    }
    /// <summary>
    /// 暂停游戏
    /// </summary>
    [MessageType(0x8302)]
    public class GamePauseEvent : ClientEvent
    {
        /// <summary>
        /// 暂停多少秒,如果为0,则无限暂停
        /// </summary>
        public float Seconds = 0f;
        public GamePauseEvent() { }
        public GamePauseEvent(float sec)
        {
            this.Seconds = sec;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutF32(Seconds);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.Seconds = input.GetF32();
        }
    }
    /// <summary>
    /// 继续游戏
    /// </summary>
    [MessageType(0x8303)]
    public class GameResumeEvent : ClientEvent
    {
        public GameResumeEvent() { }
        public override void WriteExternal(IOutputStream output)
        {
        }
        public override void ReadExternal(IInputStream input)
        {
        }
    }
    /// <summary>
    /// 移动镜头到
    /// </summary>
    [MessageType(0x8304)]
    public class CameraMoveToEvent : ClientEvent
    {
        /// <summary>
        /// 镜头移动速度(每秒距离)
        /// </summary>
        public float MoveSpeedSec = 1f;
        /// <summary>
        /// 移动过去的总时间,如果为0,则按速度计算
        /// </summary>
        public int TimeMS = 0;
        public float x;
        public float y;
        public CameraMoveToEvent() { }
        public CameraMoveToEvent(float x, float y, float speed, int timeMS)
        {
            this.x = x;
            this.y = y;
            this.MoveSpeedSec = speed;
            this.TimeMS = timeMS;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutF32(x);
            output.PutF32(y);
            output.PutF32(MoveSpeedSec);
            output.PutS32(TimeMS);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.x = input.GetF32();
            this.y = input.GetF32();
            this.MoveSpeedSec = input.GetF32();
            this.TimeMS = input.GetS32();
        }
    }
    /// <summary>
    /// 锁定镜头到单位
    /// </summary>
    [MessageType(0x8305)]
    public class CameraFocusUnitEvent : ClientEvent
    {
        public uint ObjectID;
        public CameraFocusUnitEvent() { }
        public CameraFocusUnitEvent(uint oid)
        {
            this.ObjectID = oid;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutU32(ObjectID);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.ObjectID = input.GetU32();
        }
    }
    /// <summary>
    /// 拉近镜头
    /// </summary>
    [MessageType(0x8306)]
    public class CameraZoomToEvent : ClientEvent
    {
        /// <summary>
        /// 镜头拉近距离
        /// </summary>
        public float ZoomDistance = 10f;
        /// <summary>
        /// 镜头拉近速度(每秒距离)
        /// </summary>
        public float ZoomSpeedSec = 1f;

        public CameraZoomToEvent() { }
        public CameraZoomToEvent(float distance, float speed)
        {
            this.ZoomDistance = distance;
            this.ZoomSpeedSec = speed;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutF32(ZoomDistance);
            output.PutF32(ZoomSpeedSec);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.ZoomDistance = input.GetF32();
            this.ZoomSpeedSec = input.GetF32();
        }
    }
    /// <summary>
    /// 旋转镜头
    /// </summary>
    [MessageType(0x8307)]
    public class CameraRotateToEvent : ClientEvent
    {
        /// <summary>
        /// 镜头旋转角度(0~360)
        /// </summary>
        public float RotateAngle = 10f;
        /// <summary>
        /// 镜头旋转速度(每秒角度)
        /// </summary>
        public float RotateSpeedSec = 1f;

        public CameraRotateToEvent() { }
        public CameraRotateToEvent(float angle, float speed)
        {
            this.RotateAngle = angle;
            this.RotateSpeedSec = speed;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutF32(RotateAngle);
            output.PutF32(RotateSpeedSec);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.RotateAngle = input.GetF32();
            this.RotateSpeedSec = input.GetF32();
        }
    }
    /// <summary>
    /// 重置镜头
    /// </summary>
    [MessageType(0x8308)]
    public class CameraResetEvent : ClientEvent
    {
        public override void WriteExternal(IOutputStream output)
        {
        }
        public override void ReadExternal(IInputStream input)
        {
        }
    }

    /// <summary>
    /// 客户端动作序列
    /// </summary>
    [MessageType(0x8309)]
    public class ClientEventQueue : ClientEvent
    {
        public List<ClientEvent> EventQueue = new List<ClientEvent>();

        override public void WriteExternal(IOutputStream output)
        {
            output.PutU8((byte)EventQueue.Count);
            foreach (ClientEvent e in EventQueue)
            {
                output.PutExt(e);
            }
        }
        override public void ReadExternal(IInputStream input)
        {
            int count = input.GetU8();
            for (int i = 0; i < count; i++)
            {
                EventQueue.Add(input.GetExtAny() as ClientEvent);
            }
        }
    }

    /// <summary>
    /// 移动锁定一段时间
    /// </summary>
    [MessageType(0x830B)]
    public class CameraHoldEvent : ClientEvent
    {
        public float x;
        public float y;
        public int TimeMS;
        public CameraHoldEvent() { }
        public CameraHoldEvent(float x, float y, int timeMS)
        {
            this.x = x;
            this.y = y;
            this.TimeMS = timeMS;
        }
        override public void WriteExternal(IOutputStream output)
        {
            output.PutF32(x);
            output.PutF32(y);
            output.PutS32(TimeMS);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.x = input.GetF32();
            this.y = input.GetF32();
            this.TimeMS = input.GetS32();
        }
    }

    #endregion
    //--------------------------------------------------------------------------

    #region PLAYER_EVENTS_0x8400

    public abstract class PlayerEvent : ObjectEvent
    {
        public PlayerEvent() { }
        public PlayerEvent(uint objID) : base(objID) { }
    }

    [MessageType(0x8400)]
    public class PlayerCDEvent : PlayerEvent
    {
        private byte mask = 0;
        public bool is_all
        {
            get { return BitMask.BitGetMask(mask, 0); }
            set { BitMask.BitSetMask(ref mask, 0, value); }
        }
        public bool is_decrease_time
        {
            get { return BitMask.BitGetMask(mask, 1); }
            set { BitMask.BitSetMask(ref mask, 1, value); }
        }
        public bool is_decrease_pct
        {
            get { return BitMask.BitGetMask(mask, 2); }
            set { BitMask.BitSetMask(ref mask, 2, value); }
        }
        public bool is_clear
        {
            get { return BitMask.BitGetMask(mask, 3); }
            set { BitMask.BitSetMask(ref mask, 3, value); }
        }

        public int decrease_timeMS;
        public float decrease_pct;
        public int skill_template_id;

        public PlayerCDEvent() { }
        public PlayerCDEvent(uint unit_id) : base(unit_id) { }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU8(mask);
            if (is_all)
            {
                if (is_decrease_pct)
                    output.PutF32(decrease_pct);
                if (is_decrease_time)
                    output.PutVS32(decrease_timeMS);
            }
            else
            {
                output.PutS32(skill_template_id);
                if (is_decrease_pct)
                    output.PutF32(decrease_pct);
                if (is_decrease_time)
                    output.PutVS32(decrease_timeMS);
            }
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.mask = input.GetU8();
            if (is_all)
            {
                if (is_decrease_pct)
                    decrease_pct = input.GetF32();
                if (is_decrease_time)
                    decrease_timeMS = input.GetVS32();
            }
            else
            {
                skill_template_id = input.GetS32();
                if (is_decrease_pct)
                    decrease_pct = input.GetF32();
                if (is_decrease_time)
                    decrease_timeMS = input.GetVS32();
            }
        }
    }

    [MessageType(0x8401)]
    public class PlayerSkillChangedEvent : PlayerEvent
    {
        public SkillTemplate baseSkill;
        public List<SkillTemplate> skills = new List<SkillTemplate>();
        public float unitFastCastRate;
        public PlayerSkillChangedEvent() { }
        public PlayerSkillChangedEvent(uint unit_id) : base(unit_id) { }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutF32(this.unitFastCastRate);
            output.PutExt(this.baseSkill);
            output.PutList<SkillTemplate>(this.skills, output.PutExt);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.unitFastCastRate = input.GetF32();
            this.baseSkill = input.GetExt<SkillTemplate>();
            this.skills = input.GetList<SkillTemplate>(input.GetExt<SkillTemplate>);
        }
    }


    [MessageType(0x8402)]
    public class PlayerSyncEnvironmentVarEvent : PlayerEvent
    {
        public string Key;
        public object Value;

        public PlayerSyncEnvironmentVarEvent() { }
        public PlayerSyncEnvironmentVarEvent(uint unit_id, string key, object value)
            : base(unit_id)
        {
            this.Key = key;
            this.Value = value;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutUTF(Key);
            output.PutData(Value);
        }

        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            DataType dtype;
            this.Key = input.GetUTF();
            this.Value = input.GetData(out dtype);
        }
    }

    [MessageType(0x8403)]
    public class PlayerSkillStopEvent : PlayerEvent
    {
        public int SkillID;
        public PlayerSkillStopEvent() { }
        public PlayerSkillStopEvent(uint unit_id, int skillID)
            : base(unit_id)
        {
            this.SkillID = skillID;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(SkillID);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.SkillID = input.GetS32();
        }
    }

    [MessageType(0x8404)]
    public class PlayerSkillAddedEvent : PlayerEvent
    {
        public SkillTemplate Skill;
        public bool IsDefault;
        public PlayerSkillAddedEvent() { }
        public PlayerSkillAddedEvent(uint unit_id, SkillTemplate sk, bool isDefault)
            : base(unit_id)
        {
            this.Skill = sk;
            this.IsDefault = isDefault;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutExt(this.Skill);
            output.PutBool(this.IsDefault);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.Skill = input.GetExt<SkillTemplate>();
            this.IsDefault = input.GetBool();
        }
    }
    [MessageType(0x8405)]
    public class PlayerSkillRemovedEvent : PlayerEvent
    {
        public int SkillID;
        public PlayerSkillRemovedEvent() { }
        public PlayerSkillRemovedEvent(uint unit_id, int skillID)
            : base(unit_id)
        {
            this.SkillID = skillID;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(this.SkillID);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.SkillID = input.GetS32();
        }
    }


    /// <summary>
    /// 脚本系统指令
    /// </summary>
    [MessageType(0x8406)]
    public class PlayerScriptCommandEvent : PlayerEvent
    {
        public string message;

        public PlayerScriptCommandEvent() { }
        public PlayerScriptCommandEvent(uint unit_id, string msg)
            : base(unit_id)
        {
            this.message = msg;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutUTF(message);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.message = input.GetUTF();
        }
    }

    /// <summary>
    /// 技能可用性发生变化
    /// </summary>
    [MessageType(0x8407)]
    public class PlayerSkillActiveChangedEvent : PlayerEvent
    {
        public struct State
        {
            public int SkillTemplateID;
            public SkillActiveState ST;

            public bool IsActive { get { return ST == SkillActiveState.Active; } }
            public bool IsPauseOnDeactive { get { return ST == SkillActiveState.DeactiveAndPause; } }
        }
        public List<State> Skills;

        public PlayerSkillActiveChangedEvent() { this.Skills = new List<State>(); }
        public PlayerSkillActiveChangedEvent(uint unit_id, int skillCount) : base(unit_id)
        {
            this.Skills = new List<State>(skillCount);
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutVS32(Skills.Count);
            for (int i = 0; i < Skills.Count; i++)
            {
                State sat = Skills[i];
                output.PutS32(sat.SkillTemplateID);
                output.PutEnum8(sat.ST);
            }
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            int count = input.GetVS32();
            this.Skills.Capacity = count;
            for (int i = 0; i < count; i++)
            {
                State sat = new State();
                sat.SkillTemplateID = input.GetS32();
                sat.ST = input.GetEnum8<SkillActiveState>();
                this.Skills.Add(sat);
            }
        }
    }

    [MessageType(0x8408)]
    public class PlayerSkillTimeChangedEvent : PlayerEvent
    {
        public int SkillTemplateID;
        public int SkillPassTimeMS;
        public int SkillTotalTimeMS;

        public PlayerSkillTimeChangedEvent() { }
        public PlayerSkillTimeChangedEvent(uint unit_id, int skillID, int passTimeMS, int totalTimeMS)
            : base(unit_id)
        {
            this.SkillTemplateID = skillID;
            this.SkillPassTimeMS = passTimeMS;
            this.SkillTotalTimeMS = totalTimeMS;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(this.SkillTemplateID);
            output.PutVS32(this.SkillPassTimeMS);
            output.PutVS32(this.SkillTotalTimeMS);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.SkillTemplateID = input.GetS32();
            this.SkillPassTimeMS = input.GetVS32();
            this.SkillTotalTimeMS = input.GetVS32();
        }
    }

    /// <summary>
    /// 锁定目标
    /// </summary>
    [MessageType(0x8409)]
    public class PlayerFocuseTargetEvent : PlayerEvent
    {
        public uint targetUnitID;
        public SkillTemplate.CastTarget expectTarget;

        public PlayerFocuseTargetEvent() { }
        public PlayerFocuseTargetEvent(uint unit_id, uint target_id, SkillTemplate.CastTarget expect)
            : base(unit_id)
        {
            this.targetUnitID = target_id;
            this.expectTarget = expect;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU32(targetUnitID);
            output.PutEnum8(expectTarget);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.targetUnitID = input.GetU32();
            this.expectTarget = input.GetEnum8<SkillTemplate.CastTarget>();
        }
    }
    #endregion
    //--------------------------------------------------------------------------
    #region TEXT_0x8500

    public enum ChatMessageType : byte
    {
        SystemToAll,
        SystemToForce,
        SystemToPlayer,

        PlayerToAll,
        PlayerToForce,
        PlayerToPlayer,
    }

    [MessageType(0x8500)]
    public class ChatAction : ObjectAction
    {
        public string Message;
        public ChatMessageType To = ChatMessageType.SystemToAll;
        public string TargetPlayerUUID;
        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU8((byte)this.To);
            output.PutUTF(this.Message);
            output.PutUTF(this.TargetPlayerUUID);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.To = (ChatMessageType)input.GetU8();
            this.Message = input.GetUTF();
            this.TargetPlayerUUID = input.GetUTF();
        }
    }

    [MessageType(0x8501)]
    public class ChatEvent : ZoneEvent
    {
        public ChatMessageType To = ChatMessageType.SystemToAll;
        public int Force;
        public string FromPlayerUUID;
        public string ToPlayerUUID;
        public string Message;
        public uint KeepTimeMS;
        public ChatEvent() { }
        public ChatEvent(ChatMessageType to, uint timeMS = 2000)
        {
            this.To = to;
            KeepTimeMS = timeMS;
        }
        public override void WriteExternal(IOutputStream output)
        {
            output.PutU8((byte)this.To);
            output.PutVS32((int)KeepTimeMS);
            output.PutUTF(this.Message);
            switch (To)
            {
                case ChatMessageType.PlayerToAll:
                    output.PutUTF(this.FromPlayerUUID);
                    break;
                case ChatMessageType.PlayerToForce:
                    output.PutUTF(this.FromPlayerUUID);
                    output.PutVS32(this.Force);
                    break;
                case ChatMessageType.PlayerToPlayer:
                    output.PutUTF(this.FromPlayerUUID);
                    output.PutUTF(this.ToPlayerUUID);
                    break;
                case ChatMessageType.SystemToAll:
                    break;
                case ChatMessageType.SystemToForce:
                    output.PutVS32(this.Force);
                    break;
                case ChatMessageType.SystemToPlayer:
                    output.PutUTF(this.ToPlayerUUID);
                    break;
            }
        }
        public override void ReadExternal(IInputStream input)
        {
            this.To = (ChatMessageType)input.GetU8();
            this.KeepTimeMS = (uint)input.GetVS32();
            this.Message = input.GetUTF();
            switch (To)
            {
                case ChatMessageType.PlayerToAll:
                    this.FromPlayerUUID = input.GetUTF();
                    break;
                case ChatMessageType.PlayerToForce:
                    this.FromPlayerUUID = input.GetUTF();
                    this.Force = input.GetVS32();
                    break;
                case ChatMessageType.PlayerToPlayer:
                    this.FromPlayerUUID = input.GetUTF();
                    this.ToPlayerUUID = input.GetUTF();
                    break;
                case ChatMessageType.SystemToAll:
                    break;
                case ChatMessageType.SystemToForce:
                    this.Force = input.GetVS32();
                    break;
                case ChatMessageType.SystemToPlayer:
                    this.ToPlayerUUID = input.GetUTF();
                    break;
            }
        }
    }

    [MessageType(0x8502)]
    public class BubbleTalkEvent : ZoneEvent
    {
        public bool PauseBattle;
        public List<TalkInfo> TalkInfos = new List<TalkInfo>();

        public BubbleTalkEvent() { }

        override public void WriteExternal(IOutputStream output)
        {
            output.PutBool(PauseBattle);
            output.PutExtList<TalkInfo>(this.TalkInfos);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.PauseBattle = input.GetBool();
            this.TalkInfos = input.GetExtList<TalkInfo>();
        }

        public class TalkInfo : IExternalizable
        {
            public uint TalkUnit;
            public string TalkContent;
            public string TalkActionType;
            public int TalkDelayTimeMS;
            public int TalkKeepTimeMS;

            public TalkInfo() { }

            public TalkInfo(uint TalkUnit, string TalkContent, string TalkActionType, int TalkDelayTimeMS, int TalkKeepTimeMS)
            {
                this.TalkUnit = TalkUnit;
                this.TalkContent = TalkContent;
                this.TalkActionType = TalkActionType;
                this.TalkDelayTimeMS = TalkDelayTimeMS;
                this.TalkKeepTimeMS = TalkKeepTimeMS;
            }

            public void WriteExternal(IOutputStream output)
            {
                output.PutVU32(TalkUnit);
                output.PutUTF(TalkContent);
                output.PutUTF(TalkActionType);
                output.PutVS32(TalkDelayTimeMS);
                output.PutVS32(TalkKeepTimeMS);
            }

            public void ReadExternal(IInputStream input)
            {
                this.TalkUnit = input.GetVU32();
                this.TalkContent = input.GetUTF();
                this.TalkActionType = input.GetUTF();
                this.TalkDelayTimeMS = input.GetVS32();
                this.TalkKeepTimeMS = input.GetVS32();
            }
        }
    }


	[MessageType(0x8503)]
	public class PlayerSkillUseTimeChangedEvent : PlayerEvent
	{
		public int SkillTemplateID;
		public byte useTimes;
		public byte hasNext;			//0-不用继续叠层,1-继续增加叠层

		public PlayerSkillUseTimeChangedEvent() { }
		public PlayerSkillUseTimeChangedEvent(uint unit_id, int skillID, byte useTimes)
			: base(unit_id)
		{
			this.SkillTemplateID = skillID;
			this.useTimes = useTimes;
		}
		override public void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);
			output.PutS32(this.SkillTemplateID);
			output.PutU8(this.useTimes);
			output.PutU8(this.hasNext);
		}
		override public void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
			this.SkillTemplateID = input.GetS32();
			this.useTimes = input.GetU8();
			this.hasNext = input.GetU8();
		}
	}


    /// <summary>
    /// 单位中BUFF
    /// </summary>
    [MessageType(0x8504)]
    public class SyncUnitBuffState : ObjectEvent
    {
        public int buffTemplateID;
        public byte overlayLevel;
        public int buffExtData;             //buff的扩展字段,

        public SyncUnitBuffState() { }
        public SyncUnitBuffState(uint unit_id, int buffID, byte overlayLevel, int extData)
            : base(unit_id)
        {
            this.buffTemplateID = buffID;
            this.overlayLevel = overlayLevel;
            this.buffExtData = extData;
        }
        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutVS32(buffTemplateID);
            output.PutU8(overlayLevel);
            output.PutVS32(buffExtData);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.buffTemplateID = input.GetVS32();
            this.overlayLevel = input.GetU8();
            this.buffExtData = input.GetVS32();
        }
    }


	/// <summary>
	/// 单位触发能力
	/// </summary>
	[MessageType(0x8505)]
	public class UnitTriggerAblity : ObjectEvent
	{
		public int ablityID;

		public UnitTriggerAblity() { }
		public UnitTriggerAblity(uint unit_id, int id)
			: base(unit_id)
		{
			this.ablityID = id;
		}
		override public void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);
			output.PutVS32(ablityID);
		}
		override public void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
			this.ablityID = input.GetVS32();
		}
	}


	/// <summary>
	/// 单位触发破碎效果
	/// </summary>
	[MessageType(0x8506)]
	public class UnitHitBreak : ObjectEvent
	{
		public UnitHitBreak() { }
		public UnitHitBreak(uint unit_id)
			: base(unit_id)
		{
			
		}
		override public void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);
			//output.PutVS32(ablityID);
		}
		override public void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
			//this.ablityID = input.GetVS32();
		}
	}

	/// <summary>
	/// 单位触发隐身效果
	/// </summary>
	[MessageType(0x8507)]
	public class UnitStealthInfo : ObjectEvent
	{
		public byte stealth;
		public short flag;
		public UnitStealthInfo() { }
		public UnitStealthInfo(uint unit_id, byte stealth, short flag)
			: base(unit_id)
		{
			this.stealth = stealth;
			this.flag = flag;
		}

		override public void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);
			output.PutU8(this.stealth);
			output.PutS16(this.flag);

			//Console.WriteLine("UnitStealthInfo: " + this.stealth + ", " + flag);
		}

		override public void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
			this.stealth = input.GetU8();
			this.flag = input.GetS16();
		}
	}

	/// <summary>
	/// buff数据推送:针对单一buff事件内的信息变更
	/// </summary>
	[MessageType(0x8508)]
	public class BuffDataNotify : ObjectEvent
	{
		public int buffId;
		public uint senderId;
		public byte overlayLevel;

		public BuffDataNotify() { }
		public BuffDataNotify(uint unit_id, int buffId, uint senderId, int layer)
			: base(unit_id)
		{
			this.buffId = buffId;
			this.senderId = senderId;
			this.overlayLevel = (byte)layer;
		}
		override public void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);
			output.PutS32(this.buffId);
			output.PutU32(this.senderId);
			output.PutU8(this.overlayLevel);

			//System.Console.WriteLine("-----BuffDataNotify: " + buffId + ", " + this.object_id + ", " + overlayLevel);
		}
		override public void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
			this.buffId = input.GetS32();
			this.senderId = input.GetU32();
			this.overlayLevel = input.GetU8();
		}
	}
	#endregion
	//--------------------------------------------------------------------------
	#region SYSTEM_0x8600


	[MessageType(0x8600)]
    public class Ping : Action, SystemMessage
    {
        public uint DayOfMS;

        public Ping()
        {
            DayOfMS = (uint)CUtils.CurrentTimeMS;
        }
        public void Begin()
        {
            DayOfMS = (uint)CUtils.CurrentTimeMS;
        }

        public override void WriteExternal(IOutputStream output)
        {
            output.PutU32(DayOfMS);
        }
        public override void ReadExternal(IInputStream input)
        {
            DayOfMS = input.GetU32();
        }
    }

    [MessageType(0x8601)]
    public class Pong : Event, SystemMessage
    {
        public uint ClientTimeDayOfMS;
        public Pong() { }
        public Pong(Ping ping) { this.ClientTimeDayOfMS = ping.DayOfMS; }
        public override void WriteExternal(IOutputStream output)
        {
            output.PutU32(ClientTimeDayOfMS);
        }
        public override void ReadExternal(IInputStream input)
        {
            ClientTimeDayOfMS = input.GetU32();
        }
    }

    /// <summary>
    /// 打包一组消息,一次性发出
    /// </summary>
    [MessageType(0x8602)]
    public class PackEvent : Event, SystemMessage
    {
		protected static readonly Logger log = LoggerFactory.GetDefLogger();
		public int sequenceNo;
        public List<IMessage> events = new List<IMessage>();
        public override string ToString()
        {
            var sb = new StringBuilder("PackEvent: no=").Append(sequenceNo).AppendLine();
            foreach (IMessage e in events)
            {
                sb.AppendLine(e.ToString());
            }
            return sb.ToString();
        }

        public override void WriteExternal(IOutputStream output)
        {
            output.PutVS32(sequenceNo);
            output.PutVS32(events.Count);
#if JSGProfile
			long startSize = output.GetBuffPos();
#endif
            foreach (IMessage e in events)
            {
				//if (!e.ToString().EndsWith("Pong") && !e.ToString().EndsWith("SyncPosEvent"))
				//{
				//	Console.WriteLine("PackEvent: " + e);
				//}

				output.PutExt(e);

#if JSGProfile
                long tempSize = output.GetBuffPos();
				JSGServerProfile.RecordSend(output.GetTypeID(e), tempSize - startSize);
                startSize = tempSize;
#endif
            }
		}

		public override void ReadExternal(IInputStream input)
        {
			this.sequenceNo = input.GetVS32();
            int count = input.GetVS32();
            events.Clear();
            events.Capacity = count;

			for (int i = 0; i < count; i++)
            {
                try
                {
                    IMessage e = (IMessage)input.GetExtAny();
                    events.Add(e);
				}
				catch (Exception err)
                {
					log.Error("PackEvent readExt catch:" + err);
				}
            }
		}
		public override void BeforeWrite(TemplateManager templates)
        { 
            foreach (IMessage e in events)
            {
                if (e is BattleMessage)
                {
                    (e as BattleMessage).BeforeWrite(templates);
                }
            }
        }
        public override void EndRead(TemplateManager templates)
        {
            foreach (IMessage e in events)
            {
                if (e is BattleMessage)
                {
                    (e as BattleMessage).EndRead(templates);
                }
            }
        }
    }

    /// <summary>
    /// 系统消息框,测试用
    /// </summary>
    [MessageType(0x8603)]
    public class TestMessageBox : Event, SystemMessage
    {
        public string msg;

        public TestMessageBox() { }
        public TestMessageBox(string msg)
        {
            this.msg = msg;
        }
        public override void WriteExternal(IOutputStream output)
        {
            output.PutUTF(this.msg);
        }
        public override void ReadExternal(IInputStream input)
        {
            this.msg = input.GetUTF();
        }
    }

    /// <summary>
    /// 通知客户端服务器运行状态
    /// </summary>
    [MessageType(0x8604)]
    public class ServerStatusB2C : Event, SystemMessage
    {
        public int PID;
        public long PrivateMemorySize64;
        public int ActiveGameObjectCount;
        public int ActiveInstanceZoneCount;
        public int AllocGameObjectCount;
        public int AllocInstanceZoneCount;

        public ServerStatusB2C() { }
        public void Update(System.Diagnostics.Process p)
        {
            this.PID = p.Id;
            this.PrivateMemorySize64 = p.PrivateMemorySize64;
            this.ActiveGameObjectCount = InstanceZoneObject.ActiveObjectCount;
            this.ActiveInstanceZoneCount = InstanceZone.ActiveZoneCount;
            this.AllocGameObjectCount = InstanceZoneObject.AllocObjectCount;
            this.AllocInstanceZoneCount = InstanceZone.AllocZoneCount;
        }
        public override void WriteExternal(IOutputStream output)
        {
            output.PutVS32(this.PID);
            output.PutVS64(this.PrivateMemorySize64);
            output.PutVS32(this.ActiveGameObjectCount);
            output.PutVS32(this.ActiveInstanceZoneCount);
            output.PutVS32(this.AllocGameObjectCount);
            output.PutVS32(this.AllocInstanceZoneCount);
        }
        public override void ReadExternal(IInputStream input)
        {
            this.PID = input.GetVS32();
            this.PrivateMemorySize64 = input.GetVS64();
            this.ActiveGameObjectCount = input.GetVS32();
            this.ActiveInstanceZoneCount = input.GetVS32();
            this.AllocGameObjectCount = input.GetVS32();
            this.AllocInstanceZoneCount = input.GetVS32();
        }
    }

    /// <summary>
    /// 通知客户端服务器报错
    /// </summary>
    [MessageType(0x8605)]
    public class ServerExceptionB2C : Event, SystemMessage
    {
        public string Message;
        public string StackTrace;
        public ServerExceptionB2C() { }
        public ServerExceptionB2C(string message, string stackTrace)
        {
            this.Message = message;
            this.StackTrace = stackTrace;
        }
        public override void WriteExternal(IOutputStream output)
        {
            output.PutUTF(this.Message);
            output.PutUTF(this.StackTrace);
        }
        public override void ReadExternal(IInputStream input)
        {
            this.Message = input.GetUTF();
            this.StackTrace = input.GetUTF();
        }
    }

    [MessageType(0x8606)]
    public class UnitFollowAction : ObjectAction
    {
        public bool follow = false;
        public string reason = null;

        public UnitFollowAction() { }
        public UnitFollowAction(uint unit_id, bool guard)
            : base(unit_id)
        {
            this.follow = guard;
        }

        public UnitFollowAction(uint unit_id, bool guard, string reason)
        : base(unit_id)
        {
            this.follow = guard;
            this.reason = reason;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutBool(follow);
            output.PutUTF(reason);
        }

        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.follow = input.GetBool();
            this.reason = input.GetUTF();
        }
    }

#endregion

    //--------------------------------------------------------------------------

    /// <summary>
    /// 新增技能移动的协议
    /// </summary>
    [MessageType(0x8700)]
    public class SkillMove : ObjectAction
    {
        public int SkillID;
        public Vector2 SkillPos;

        public SkillMove() { }
        public SkillMove(uint unit_id, int skill_id, Vector2 vec):base(unit_id)
        {
            this.SkillID = skill_id;
            this.SkillPos = vec;
        }

        override public void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(SkillID);
            output.PutF32(SkillPos.X);
            output.PutF32(SkillPos.Y);
        }
        override public void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.SkillID = input.GetS32();
            this.SkillPos = new Vector2();
            this.SkillPos.SetX(input.GetF32());
            this.SkillPos.SetY(input.GetF32());
        }
    }

    /// <summary>
    /// 法术Dispose后,在播放一个过渡特效
    /// </summary>
    [MessageType(0x8701)]
    public class PlayDestoryEffect : ZoneEvent
    {
        public string EffectName;
        public float X;
        public float Y;
        public float Z;

        //rotation
        public float Direction;

        public PlayDestoryEffect() { }
        public PlayDestoryEffect(string effectName, float x, float y, float z, float direction)
        {
            EffectName = effectName;
            X = x;
            Y = y;
            Z = z;
            Direction = direction;
        }

        override public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(EffectName);
            output.PutF32(X);
            output.PutF32(Y);
            output.PutF32(Z);
            output.PutF32(Direction);
        }
        override public void ReadExternal(IInputStream input)
        {
            this.EffectName = input.GetUTF();
            this.X = input.GetF32();
            this.Y = input.GetF32();
            this.Z = input.GetF32();
            this.Direction = input.GetF32();
        }
    }
    
    /// <summary>
    /// 随从瞬移
    /// </summary>
    [MessageType(0x8702)]
    public class PlayPetTeleportAction : ObjectAction
    {
        public PlayPetTeleportAction() { }

        override public void WriteExternal(IOutputStream output)
        {

        }
        override public void ReadExternal(IInputStream input)
        {

        }
    }

	/// <summary>
	/// 刷新玩家天赋相关信息
	/// 
	/// </summary>
	[MessageType(0x8703)]
	public class RefreshTalnetInfo: PlayerSingleMsg
	{
		//根据不同职业,不同解读
		//战士:value:怒气值,lv:无
		//法师:value: 剑气值,lv:剑气层数
		public short value;						//天赋值,每秒降低,服务器刷新
		public byte lv;
		public int lvUpdateTime;                //等级最后刷新时间,变化不频繁,需要根据本地时间自己做进度效果(lv=0无)

		public RefreshTalnetInfo() { }
		public RefreshTalnetInfo(short value, byte lv = 0, int updateTime = 0)
		{
			this.value = value;
			this.lv = lv;
			this.lvUpdateTime = updateTime;
		}

		override public void WriteExternal(IOutputStream output)
		{
			output.PutS16(this.value);
			output.PutU8(this.lv);
			if(this.lv > 0)
			{
				output.PutS32(this.lvUpdateTime);
			}
		}

		override public void ReadExternal(IInputStream input)
		{
			this.value = input.GetS16();
			this.lv = input.GetU8();
			if(this.lv > 0)
			{
				this.lvUpdateTime = input.GetS32();
			}
			//System.Console.WriteLine("RefreshTalnetInfo: " + this.value + ", " + this.lv + ", " + this.lvUpdateTime);
		}
	}

	/// <summary>
	/// 刷新玩家卡牌珠相关信息
	/// </summary>
	[MessageType(0x8704)]
	public class RefreshCardInfo : PlayerSingleMsg
	{
		public byte[] cardData = new byte[(int)CardType.Max];		//0-3代表有

		public RefreshCardInfo()
		{
			for(int i = 0; i < (int)CardType.Max; i++)
			{
				cardData[i] = (byte)CardType.Max;
			}
		}

		override public void WriteExternal(IOutputStream output)
		{
			for(int i = 0; i < (int)CardType.Max; i++)
			{
				output.PutU8(cardData[i]);
			}
			//System.Console.WriteLine("--------RefreshCardInfo: " + cardData[0] + ", " + cardData[1] + ", " + cardData[2] + ", " + cardData[3]);
		}

		override public void ReadExternal(IInputStream input)
		{
			//System.Console.WriteLine("--------RefreshCardInfo");
			for (int i = 0; i < (int)CardType.Max; i++)
			{
				cardData[i] = input.GetU8();
			}

			//System.Console.WriteLine("--------RefreshCardInfo: " + cardData[0] + ", " + cardData[1] + ", " + cardData[2] + ", " + cardData[3]);
		}
	}

	/// <summary>
	/// 玩家卡牌释放逻辑
	/// </summary>
	[MessageType(0x8705)]
	public class PlayerLaunchCardSkill : PlayerSingleMsg
	{
		public int cardSkill;
		public CardType type;
		public byte layer;
		public byte[] cardData = new byte[(int)CardType.Max];       //0-3代表有

		public PlayerLaunchCardSkill() { }
		override public void WriteExternal(IOutputStream output)
		{
			output.PutS32(this.cardSkill);
			output.PutEnum8(type);
			output.PutU8(this.layer);

			for (int i = 0; i < (int)CardType.Max; i++)
			{
				output.PutU8(cardData[i]);
			}
			//System.Console.WriteLine("--------PlayerLaunchCardSkill: " + cardSkill + ", " + this.type);
		}

		override public void ReadExternal(IInputStream input)
		{
			//
			this.cardSkill = input.GetS32();
			this.type = input.GetEnum8<CardType>();
			this.layer = input.GetU8();
			for (int i = 0; i < (int)CardType.Max; i++)
			{
				cardData[i] = input.GetU8();
			}
			//System.Console.WriteLine("--------PlayerLaunchCardSkill: " + cardSkill + ", " + this.type);
		}
	}

	/// <summary>
	/// 刷新Boss卡牌珠相关信息
	/// </summary>
	[MessageType(0x8706)]
	public class RefreshBossCardInfo : ObjectEvent
	{
		public byte[] cardData = new byte[(int)CardType.Max];       //0-3代表有

		public RefreshBossCardInfo()
		{
			for (int i = 0; i < (int)CardType.Max; i++)
			{
				cardData[i] = (byte)CardType.Max;
			}
		}

		override public void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);
			for (int i = 0; i < (int)CardType.Max; i++)
			{
				output.PutU8(cardData[i]);
			}
			//System.Console.WriteLine("RefreshBossCardInfo: " + this.object_id +", " +  cardData[0] + ", " + cardData[1] + ", " + cardData[2] + ", " + cardData[3]);
		}

		override public void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
			for (int i = 0; i < (int)CardType.Max; i++)
			{
				cardData[i] = input.GetU8();
			}
			//System.Console.WriteLine("objectID: " + this.object_id);
			//System.Console.WriteLine("--------RefreshBossCardInfo: " + this.object_id + ", " + cardData[0] + ", " + cardData[1] + ", " + cardData[2] + ", " + cardData[3]);
		}
	}

	/// <summary>
	/// 玩家卡牌释放逻辑
	/// </summary>
	[MessageType(0x8707)]
	public class BossTriggerCardSkill : ObjectEvent
	{
		public int cardSkill;
		public CardType type;
		public byte layer;
		public byte[] cardData = new byte[(int)CardType.Max];       //0-3代表有

		public BossTriggerCardSkill() { }
		override public void WriteExternal(IOutputStream output)
		{
			base.WriteExternal(output);

			output.PutS32(this.cardSkill);
			output.PutEnum8(type);
			output.PutU8(this.layer);

			for (int i = 0; i < (int)CardType.Max; i++)
			{
				output.PutU8(cardData[i]);
			}

			//System.Console.WriteLine("BossTriggerCardSkill: " + this.object_id + ", " + cardData[0] + ", " + cardData[1] + ", " + cardData[2] + ", " + cardData[3]);
		}

		override public void ReadExternal(IInputStream input)
		{
			base.ReadExternal(input);
					
			this.cardSkill = input.GetS32();
			this.type = input.GetEnum8<CardType>();
			this.layer = input.GetU8();

			for (int i = 0; i < (int)CardType.Max; i++)
			{
				cardData[i] = input.GetU8();
			}

			//System.Console.WriteLine("BossTriggerCardSkill: " + this.object_id + ", " + cardData[0] + ", " + cardData[1] + ", " + cardData[2] + ", " + cardData[3]);
		}
	}
}