using System;
using System.Collections.Generic;
using System.Text;
using CommonAI.Zone.Instance;
using CommonAI.Zone;
using CommonLang.Property;
using System.Globalization;
using CommonAI.Zone.Attributes;
using CommonLang.Xml;
using System.Xml;
using CommonLang.Log;

using CommonLang.IO;
using CommonLang;
using CommonAI.ZoneEditor;
using CommonLang.IO.Attribute;
using CommonLang.Vector;

namespace CommonAI.Zone.ZoneEditor
{

    // ----------------------------------------------------------------------------------
    #region SceneObjectData

    [TableClassAttribute("Name")]
    public abstract class SceneObjectData : IExternalizable
    {
        [DescAttribute("Name", "", false)]
        public string Name;

        [DescAttribute("别名")]
        public string Alias;

        [DescAttribute("坐标X")]
        public float X;
        [DescAttribute("坐标Y")]
        public float Y;
        [DescAttribute("", "", false)]
        public string SavePath;
        [ColorValueAttribute]
        [DescAttribute("Color(ARGB)", "扩展", true, null)]
        public int Color = ColorValueAttribute.COLOR_GREEN;
        [DescAttribute("扩展属性", "扩展")]
        public string[] Attributes;

        [DescAttribute("逻辑开关", "扩展")]
        public bool Enable = true;

        [DescAttribute("地图显示", "地图显示")]
        public bool MapShow = false;
        [DescAttribute("地图名称", "地图显示")]
        public string UnitName = "";
        [DescAttribute("地图icon", "地图显示")]
        public string UnitIcon = "";
        [DescAttribute("坐标OffsetX", "地图显示")]
        public float OffsetX = 0;
        [DescAttribute("坐标OffsetX", "地图显示")]
        public float OffsetY = 0;
        [DescAttribute("坐标LableOffsetX", "地图显示")]
        public float LableOffsetX = 0;
        [DescAttribute("坐标LableOffsetY", "地图显示")]
        public float LableOffsetY = 15;
        [ColorValueAttribute]
        [DescAttribute("Color(ARGB)", "地图显示", true, null)]
        public int LableColor = ColorValueAttribute. FromARGB(0xff, 0xff, 0xff, 0xff);
        [DescAttribute("字号", "地图显示")]
        public int LableSize = 20;
        [DescAttribute("是否描边", "地图显示")]
        public bool LableOutline = false;


        [DescAttribute("事件", "事件")]
        [SceneScriptIDAttribute]
        public string Script;

        [DescAttribute("Tag")]
        public string Tag;


        public abstract float Radius { get; }

        public abstract IEnumerable<AbilityData> GetAbilities();

        public T GetAbilityOf<T>() where T : AbilityData
        {
            foreach (var ab in this.GetAbilities())
            {
                if (ab is T)
                {
                    return ab as T;
                }
            }
            return null;
        }

        public override string ToString()
        {
            return Name + "";
        }

        public virtual void WriteExternal(IOutputStream output)
        {
            output.PutUTF(this.Name);
            output.PutUTF(this.Alias);
            output.PutF32(this.X);
            output.PutF32(this.Y);
            output.PutUTF(this.SavePath);
            output.PutS32(this.Color);
            output.PutArray(this.Attributes, output.PutUTF);
            output.PutBool(this.Enable);
            output.PutBool(this.MapShow);
            output.PutUTF(this.UnitName);
            output.PutUTF(this.UnitIcon);
            output.PutF32(this.OffsetX);
            output.PutF32(this.OffsetY);
            output.PutF32(this.LableOffsetX);
            output.PutF32(this.LableOffsetY);
            output.PutS32(this.LableColor);
            output.PutS32(this.LableSize);
            output.PutBool(this.LableOutline);
            output.PutUTF(this.Script);
            output.PutUTF(this.Tag);
        }

        public virtual void ReadExternal(IInputStream input)
        {
            this.Name = input.GetUTF();
            this.Alias = input.GetUTF();
            this.X = input.GetF32();
            this.Y = input.GetF32();
            this.SavePath = input.GetUTF();
            this.Color = input.GetS32();
            this.Attributes = input.GetUTFArray();
            this.Enable = input.GetBool();
            this.MapShow = input.GetBool();
            this.UnitName = input.GetUTF();
            this.UnitIcon = input.GetUTF();
            this.OffsetX = input.GetF32();
            this.OffsetY = input.GetF32();
            this.LableOffsetX = input.GetF32();
            this.LableOffsetY = input.GetF32();
            this.LableColor = input.GetS32();
            this.LableSize = input.GetS32();
            this.LableOutline = input.GetBool();
            this.Script = input.GetUTF();
            this.Tag = input.GetUTF();
        }
    }

    [MessageType(0x4301)]
    [DescAttribute("场景区域数据")]
    public class RegionData : SceneObjectData
    {
        public enum Shape
        {
            RECTANGLE,
            ROUND,
            STRIP,
        }

        public bool IsRound { get { return RegionType == Shape.ROUND; } }

        [DescAttribute("区域类型")]
        public RegionData.Shape RegionType = RegionData.Shape.ROUND;
        [DescAttribute("宽度")]
        public float W = 10;
        [DescAttribute("长度")]
        [DependOnProperty("IsRound", false)]
        public float H = 10;

        [DescAttribute("区域方向")]
        [DependOnProperty("ShapDirectionality")]
        public float StripDirection;

        [DescAttribute("绑定的能力", "能力")]
        [ListAttribute(typeof(RegionAbilityData))]
        public List<RegionAbilityData> Abilities = new List<RegionAbilityData>();

        public bool ShapDirectionality { get { return RegionType == Shape.STRIP; } }

        public override float Radius
        {
            get { return ((IsRound) ? W : Math.Max(W, H)) / 2; }
        }

        public override IEnumerable<AbilityData> GetAbilities() { return Abilities.ToArray(); }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32((int)RegionType);
            output.PutF32(W);
            output.PutF32(H);
            output.PutList(this.Abilities, output.PutExt);
            output.PutF32(this.StripDirection);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.RegionType = (RegionData.Shape)input.GetS32();
            this.W = input.GetF32();
            this.H = input.GetF32();
            this.Abilities = input.GetListAny<RegionAbilityData>();
            this.StripDirection = input.GetF32();
        }
    }

    [MessageType(0x4302)]
    [DescAttribute("场景路点数据")]
    public class PointData : SceneObjectData
    {
        [DescAttribute("临近的所有点")]
        [NotNull]
        public List<string> NextNames = new List<string>();

        [DescAttribute("绑定的能力", "能力")]
        [ListAttribute(typeof(PointAbilityData))]
        public List<PointAbilityData> Abilities = new List<PointAbilityData>();

        public override IEnumerable<AbilityData> GetAbilities() { return Abilities.ToArray(); }

        public override float Radius
        {
            get { return 1; }
        }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutList(NextNames, output.PutUTF);
            output.PutList(Abilities, output.PutExt);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.NextNames = input.GetUTFList();
            this.Abilities = input.GetListAny<PointAbilityData>();
        }
    }

    [MessageType(0x4303)]
    [DescAttribute("场景装饰物")]
    public class DecorationData : SceneObjectData
    {
        public enum Shape
        {
            RECTANGLE,
            ROUND,
            STRIP,
        }

        [DescAttribute("区域类型", "基础")]
        public Shape RegionType = Shape.ROUND;
        [DescAttribute("宽度", "基础")]
        public float W = 10;
        [DescAttribute("长度", "基础")]
        public float H = 10;
        [DescAttribute("高度", "基础")]
        public float Height;
        [DescAttribute("区域方向", "基础")]
        [DependOnProperty("ShapDirectionality")]
        public float StripDirection;

        public bool ShapDirectionality { get { return RegionType == Shape.STRIP; } }

        [DescAttribute("是否为阻挡", "阻挡")]
        public bool Blockable = false;
        [ColorValueAttribute]
        [DependOnProperty("Blockable")]
        [DescAttribute("若为阻挡,则阻挡值(ARGB)", "阻挡", true, null)]
        public int BlockValue = ColorValueAttribute.COLOR_GREEN;

        [DescAttribute("空气墙内部平铺网格(宽)", "显示")]
        public float GridSizeW;
        [DescAttribute("空气墙内部平铺网格(高)", "显示")]
        public float GridSizeH;

        [DescAttribute("对应的模型文件名", "显示")]
        [ResourceIDAttribute]
        public string ResourceID;
        [DescAttribute("出生特效", "显示")]
        [ResourceIDAttribute]
        public string ResourceID_Enabled;
        [DescAttribute("消亡特效", "显示")]
        [ResourceIDAttribute]
        public string ResourceID_Disabled;
        [DescAttribute("特效方向", "显示")]
        public float Direction;
        [DescAttribute("当前动画名字", "显示")]
        public string AnimName;
        [DescAttribute("缩放", "显示")]
        public float Scale;

        [DescAttribute("环境音效", "声音")]
        [ResourceIDAttribute]
        public string SoundAmbient;

        [DescAttribute("绑定的能力", "能力")]
        [ListAttribute(typeof(DecorationAbilityData))]
        public List<DecorationAbilityData> Abilities = new List<DecorationAbilityData>();

        public override float Radius
        {
            get { return ((RegionType == Shape.ROUND) ? W : Math.Max(W, H)) / 2; }
        }

        public override IEnumerable<AbilityData> GetAbilities() { return Abilities.ToArray(); }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32((int)this.RegionType);
            output.PutF32(this.W);
            output.PutF32(this.H);
            output.PutF32(this.Height);
            output.PutF32(this.StripDirection);
            output.PutBool(this.Blockable);
            output.PutS32(this.BlockValue);
            output.PutF32(this.GridSizeW);
            output.PutF32(this.GridSizeH);
            output.PutUTF(this.ResourceID);
            output.PutUTF(this.ResourceID_Enabled);
            output.PutUTF(this.ResourceID_Disabled);
            output.PutUTF(this.AnimName);
            output.PutF32(this.Direction);
            output.PutF32(this.Scale);
            output.PutUTF(this.SoundAmbient);
            output.PutList(Abilities, output.PutExt);            
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.RegionType = (DecorationData.Shape)input.GetS32();
            this.W = input.GetF32();
            this.H = input.GetF32();
            this.Height = input.GetF32();
            this.StripDirection = input.GetF32();
            this.Blockable = input.GetBool();
            this.BlockValue = input.GetS32();
            this.GridSizeW = input.GetF32();
            this.GridSizeH = input.GetF32();
            this.ResourceID = input.GetUTF();
            this.ResourceID_Enabled = input.GetUTF();
            this.ResourceID_Disabled = input.GetUTF();
            this.AnimName = input.GetUTF();
            this.Direction = input.GetF32();
            this.Scale = input.GetF32();
            this.SoundAmbient = input.GetUTF();
            this.Abilities = input.GetListAny<DecorationAbilityData>();
        }

        public void GetResourcePoints(List<CommonLang.Geometry.Vector2> list)
        {
            switch (RegionType)
            {
                case Shape.RECTANGLE:
                    ForEachExpand(this.GridSizeW, this.W, (rx) =>
                    {
                        ForEachExpand(this.GridSizeH, this.H, (ry) =>
                        {
                            list.Add(new CommonLang.Geometry.Vector2(rx, ry));
                        });
                    });
                    break;
                case Shape.ROUND:
                    ForEachExpand(this.GridSizeW, this.W, (rx) =>
                    {
                        ForEachExpand(this.GridSizeH, this.H, (ry) =>
                        {
                            if (CMath.includeEllipsePoint(0, 0, W / 2, H / 2, rx, ry))
                            {
                                list.Add(new CommonLang.Geometry.Vector2(rx, ry));
                            }
                        });
                    });
                    break;
                case Shape.STRIP:
                    ForEachExpand(this.GridSizeW, this.W, (rx) =>
                    {
                        ForEachExpand(this.GridSizeH, this.H, (ry) =>
                        {
                            list.Add(new CommonLang.Geometry.Vector2(ry, rx));
                        });
                    });
                    break;
            }
        }
        public static void ForEachExpand(float cell, float len, Action<float> action)
        {
            action(0);
            if (cell > 0 && len > 0)
            {
                float half = len / 2;
                for (float r = cell; r < half; r += cell)
                {
                    action(+r);
                    action(-r);
                }
            }
        }
    }

    [MessageType(0x4304)]
    [DescAttribute("场景单位数据")]
    public class UnitData : SceneObjectData
    {
        [DescAttribute("单位模板ID")]
        [TemplateIDAttribute(typeof(UnitInfo))]
        public int UnitTemplateID;
        [DescAttribute("等级")]
        [TemplateLevelAttribute]
        public int UnitLevel;
        [DescAttribute("阵营")]
        public byte Force;
        [DescAttribute("单位方向")]
        public float Direction;
        [DescAttribute("单位尺寸")]
        public float Scale = 1;
        [DescAttribute("单位标记")]
        public string UnitTag;
        [SceneObjectIDAttribute(typeof(PointData))]
        [DescAttribute("单位初始路点")]
        public string StartPointName;

        [DescAttribute("绑定的能力", "能力")]
        [ListAttribute(typeof(UnitAbilityData))]
        public List<UnitAbilityData> Abilities = new List<UnitAbilityData>();

        public override float Radius
        {
            get { return 1; }
        }

        public override IEnumerable<AbilityData> GetAbilities() { return Abilities.ToArray(); }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(UnitTemplateID);
            output.PutS32(UnitLevel);
            output.PutU8(Force);
            output.PutF32(Direction);
            output.PutF32(Scale);
            output.PutUTF(UnitTag);
            output.PutUTF(StartPointName);
            output.PutList(Abilities, output.PutExt);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.UnitTemplateID = input.GetS32();
            this.UnitLevel = input.GetS32();
            this.Force = input.GetU8();
            this.Direction = input.GetF32();
            this.Scale = input.GetF32();
            this.UnitTag = input.GetUTF();
            this.StartPointName = input.GetUTF();
            this.Abilities = input.GetListAny<UnitAbilityData>();
        }
    }

    [MessageType(0x4305)]
    [DescAttribute("场景物品数据")]
    public class ItemData : SceneObjectData
    {
        [DescAttribute("物品模板ID")]
        [TemplateIDAttribute(typeof(ItemTemplate))]
        public int ItemTemplateID;
        [DescAttribute("阵营")]
        public byte Force;
        [DescAttribute("方向")]
        public float Direction;

        [DescAttribute("绑定的能力", "能力")]
        [ListAttribute(typeof(ItemAbilityData))]
        public List<ItemAbilityData> Abilities = new List<ItemAbilityData>();

        public override float Radius
        {
            get { return 1; }
        }

        public override IEnumerable<AbilityData> GetAbilities() { return Abilities.ToArray(); }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutS32(ItemTemplateID);
            output.PutU8(Force);
            output.PutF32(Direction);
            output.PutList(Abilities, output.PutExt);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.ItemTemplateID = input.GetS32();
            this.Force = input.GetU8();
            this.Direction = input.GetF32();
            this.Abilities = input.GetListAny<ItemAbilityData>();
        }
    }

    [MessageType(0x4306)]
    [DescAttribute("场景Area标识数据")]
    public class AreaData : SceneObjectData
    {
        [DescAttribute("阵营")]
        public byte Force;
        [LocalizationTextAttribute]
        [DescAttribute("显示名字")]
        public string DisplayName;

        [DescAttribute("宽度", "基础")]
        public float W = 10;
        [DescAttribute("长度", "基础")]
        public float H = 10;

        [DescAttribute("绑定的能力", "能力")]
        [ListAttribute(typeof(AreaAbilityData))]
        public List<AreaAbilityData> Abilities = new List<AreaAbilityData>();

        public override float Radius
        {
            get { return Math.Max(W, H) / 2; }
        }

        public override IEnumerable<AbilityData> GetAbilities() { return Abilities.ToArray(); }

        public override void WriteExternal(IOutputStream output)
        {
            base.WriteExternal(output);
            output.PutU8(Force);
            output.PutUTF(DisplayName);
            output.PutF32(W);
            output.PutF32(H);
            output.PutList(Abilities, output.PutExt);
        }
        public override void ReadExternal(IInputStream input)
        {
            base.ReadExternal(input);
            this.Force = input.GetU8();
            this.DisplayName = input.GetUTF();
            this.W = input.GetF32();
            this.H = input.GetF32();
            this.Abilities = input.GetListAny<AreaAbilityData>();
        }
    }

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

    [MessageType(0x4310)]
    [DescAttribute("地形数据")]
    public class TerrainData : IExternalizable
    {
        //---------------------------------------------------------
        [DescAttribute("宽(格子)", "地形", false)]
        public int XCount = 100;
        [DescAttribute("高(格子)", "地形", false)]
        public int YCount = 100;
        [DescAttribute("每格宽", "地形", false)]
        public int GridCellW = 32;
        [DescAttribute("每格高", "地形", false)]
        public int GridCellH = 32;
        [DescAttribute("地形数据", "地形", false)]
        public string TerrainTextData;
        //---------------------------------------------------------
        private ZoneInfo mZoneData;
        public ZoneInfo ZoneData
        {
            get
            {
                if (mZoneData == null)
                    mZoneData = ToZoneData();
                return mZoneData;
            }
        }
        //---------------------------------------------------------
        public void SetTerrain(ZoneInfo zonedata)
        {
            mZoneData = zonedata;
            int[,] terrain = zonedata.TerrainMatrix;
            int gridW = zonedata.GridCellW;
            int gridH = zonedata.GridCellH;

            StringBuilder sb = new StringBuilder();
            sb.AppendLine();
            this.GridCellW = gridW;
            this.GridCellH = gridH;
            this.XCount = terrain.GetLength(0);
            this.YCount = terrain.GetLength(1);
            for (int y = 0; y < YCount; y++)
            {
                sb.Append("{");
                for (int x = 0; x < XCount; x++)
                {
                    sb.Append(terrain[x, y].ToString("X"));
                    if (x < XCount - 1)
                    {
                        sb.Append(',');
                    }
                }
                sb.Append("},");
                sb.AppendLine();
            }
            this.TerrainTextData = sb.ToString();
        }

        private ZoneInfo ToZoneData()
        {
            ZoneInfo info = new ZoneInfo(XCount, YCount, GridCellW, GridCellH);
            if (TerrainTextData != null)
            {
                int pos = 1;
                for (int y = 0; y < YCount; y++)
                {
                    ReadLineY(y, info, ref pos);
                }
            }
            return info;
        }
        private void ReadLineY(int y, ZoneInfo info, ref int pos)
        {
            pos = TerrainTextData.IndexOf('{', pos);
            if (pos >= 0)
            {
                int old_pos = pos + 1;
                int len = 0;
                string num = null;
                int last_x = XCount - 1;
                for (int x = 0; x < XCount; x++)
                {
                    if (x == last_x)
                    {
                        pos = TerrainTextData.IndexOf('}', old_pos);
                    }
                    else
                    {
                        pos = TerrainTextData.IndexOf(',', old_pos);
                    }
                    if (pos > old_pos)
                    {
                        len = pos - old_pos;
                        num = TerrainTextData.Substring(old_pos, len);
                        info.mTerrainMatrix[x, y] = int.Parse(num, NumberStyles.HexNumber);
                    }
                    pos += 1;
                    old_pos = pos;
                }
            }
        }

        public void WriteExternal(IOutputStream output)
        {
            output.PutS32(this.XCount);
            output.PutS32(this.YCount);
            output.PutS32(this.GridCellW);
            output.PutS32(this.GridCellH);

            output.PutExt(this.ZoneData);
        }

        public void ReadExternal(IInputStream input)
        {
            this.XCount = input.GetS32();
            this.YCount = input.GetS32();
            this.GridCellW = input.GetS32();
            this.GridCellH = input.GetS32();

            this.SetTerrain(input.GetExt<ZoneInfo>());
        }
    }

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

    [MessageType(0x4300)]
    [DescAttribute("关卡数据")]
    [TableClassAttribute("ID")]
    public class SceneData : ITemplateData, IExternalizable
    {
        public int TemplateID { get { return ID; } }
        [XmlSerializable()]
        public string EditorPath { get; set; }

        [DescAttribute("阻挡检测,寻找附近点的最大半径(目前仅客户端用)", "属性", true)]
        public float BlockSeekCritical = 5.0f;

        [DescAttribute("", "属性", false)]
        public int ID;

        [DescAttribute("场景资源", "属性", true)]
        [ResourceIDAttribute]
        public string FileName;

        [DescAttribute("场景背景音乐", "属性", true)]
        [ResourceIDAttribute]
        public string BGM;


        [DescAttribute("游戏总时间,0表示无限制", "属性", true)]
        public int TotalTimeLimitSEC;

        [DescAttribute("场景资源属性", "属性", true)]
        public string ResourceProperty;

        [LocalizationTextAttribute]
        [DescAttribute("场景名字", "属性", true)]
        public string Name;
        [DescAttribute("是否可以骑马,编辑器填写无效", "属性", true)]
        public bool canRiding=true;

		[LocalizationTextAttribute]
        [DescAttribute("场景简介", "属性", true)]
        public string Desc;

        [DescAttribute("自定义字段", "属性", true)]
        public string[] Attributes;

        [DescAttribute("", "", false)]
        public TerrainData Terrain = new TerrainData();

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

        [DescAttribute("最大支持玩家数量-废弃", "战斗")]
        public int MaxPlayer = 10;
        [DescAttribute("最大单位数量", "战斗")]
        public int MaxUnit = 500;

		[DescAttribute("连斩时间间隔", "战斗")]
		public int killInterval = 0;
        [DescAttribute("连斩上限", "战斗")]
        public int killMax = 0;
        [DescAttribute("连斩上限后,连斩数冷却时间", "战斗")]
        public int killMaxCoolTime = 0;

        [DescAttribute("是否是队伍", "战斗")]
        public bool isTeam = false;

        [DescAttribute("场景类型", "场景")]
        public CommonAI.Data.SceneType sceneType = CommonAI.Data.SceneType.Normal;

        //---------------------------------------------------------
        [DescAttribute("单位掉线即离开场景", "网络")]
        public bool RemoveUnitOnDisconnect = false;
        [DescAttribute("客户端同步范围", "网络")]
        public float ClientSyncRange = 20;
        //---------------------------------------------------------

        [DescAttribute("默认单位等级", "单位 - 某个单位")]
        [TemplateLevelAttribute]
        public int DefaultUnitLevel = 0;
        [DescAttribute("每层怪物属性增加比率", "单位 - 某个单位")]
        public double MonsterAddPropPercentWithFloor = 0;
        [DescAttribute("怪物每等级属性成长系数", "单位 - 某个单位")]
        public double MonsterAddPropRatioWithLv = 0;
        //---------------------------------------------------------s
        [DescAttribute("所有路点", "单位", false)]
        public List<PointData> Points = new List<PointData>();
        [DescAttribute("所有区域", "单位", false)]
        public List<RegionData> Regions = new List<RegionData>();
        [DescAttribute("所有装饰物", "单位", false)]
        public List<DecorationData> Decorations = new List<DecorationData>();
        [DescAttribute("所有单位", "单位", false)]
        public List<UnitData> Units = new List<UnitData>();
        [DescAttribute("所有物品", "单位", false)]
        public List<ItemData> Items = new List<ItemData>();
        [DescAttribute("所有区域", "单位", false)]
        public List<AreaData> Areas = new List<AreaData>();
        //---------------------------------------------------------

        [DescAttribute("所有能力", "能力 - 服务端", false)]
        public List<SceneAbilityData> Abilities = new List<SceneAbilityData>();

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

        [DescAttribute("脚本", "事件 - 服务端", false)]
        [SceneScriptIDAttribute]
        public string Script;

        [DescAttribute("事件", "事件 - 服务端", false)]
        public List<ZoneEvent> Events = new List<ZoneEvent>();

        [DescAttribute("事件", "事件 - 服务端", false)]
        public List<ZoneVar> EnvironmentVars = new List<ZoneVar>();

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

        [DescAttribute("扩展属性", "扩展")]
        [Expandable]
        [NotNull]
        public ISceneProperties Properties = TemplateManager.Factory.CreateSceneProperties();


        //---------------------------------------------------------
        public int GetID()
        {
            return ID;
        }
        public override string ToString()
        {
            return Name + "(" + ID + ")";
        }

        public void SetTerrain(ZoneInfo zonedata)
        {
            this.Terrain.SetTerrain(zonedata);
        }

        public ZoneInfo ZoneData
        {
            get
            {
                return this.Terrain.ZoneData;
            }
        }

        public HashMap<int, RegionData> GetStartRegions()
        {
            HashMap<int, RegionData> ret = new HashMap<int, RegionData>();
            foreach (RegionData rdata in this.Regions)
            {
                if (rdata.Abilities != null)
                {
                    foreach (AbilityData td in rdata.Abilities)
                    {
                        if (td is PlayerStartAbilityData)
                        {
                            PlayerStartAbilityData tgd = td as PlayerStartAbilityData;
                            ret.Put(tgd.START_Force, rdata);
                        }
                    }
                }
            }
            return ret;
        }

        public List<RegionData> GetStartRegionsList()
        {
            List<RegionData> ret = new List<RegionData>();
            foreach (RegionData rdata in this.Regions)
            {
                if (rdata.Abilities != null)
                {
                    foreach (AbilityData td in rdata.Abilities)
                    {
                        if (td is PlayerStartAbilityData)
                        {
                            PlayerStartAbilityData tgd = td as PlayerStartAbilityData;
                            ret.Add(rdata);
                        }
                    }
                }
            }
            return ret;
        }

        public T GetAbilityOf<T>() where T : AbilityData
        {
            foreach (var ab in this.Abilities)
            {
                if (ab is T)
                {
                    return ab as T;
                }
            }
            return null;
        }
        //---------------------------------------------------------
        [DescAttribute("仅在保存时,用于缓存当前场景所有SN序列号", "", false)]
        private List<ISNData> serial_datas;
        public List<ISNData> GetSerialDatas()
        {
            if (serial_datas == null)
            {
                this.serial_datas = new List<ISNData>();
                PropertyUtil.CollectFieldTypeValues<ISNData>(this, serial_datas);
            }
            return serial_datas;
        }

        //---------------------------------------------------------
        public void WriteExternal(IOutputStream output)
        {
            output.PutUTF(this.EditorPath);
            output.PutF32(this.BlockSeekCritical);
            output.PutS32(this.ID);
            output.PutUTF(this.FileName);
            output.PutUTF(this.BGM);
            output.PutS32(this.TotalTimeLimitSEC);
            output.PutUTF(this.ResourceProperty);
            output.PutUTF(this.Name);
            output.PutUTF(this.Desc);
            output.PutArray<string>(this.Attributes, output.PutUTF);
            output.PutExt(this.Terrain);
            output.PutS32(this.MaxPlayer);
            output.PutS32(this.MaxUnit);
            output.PutS32(this.DefaultUnitLevel);
            output.PutBool(this.RemoveUnitOnDisconnect);
            output.PutF32(this.ClientSyncRange);
            output.PutList<PointData>(this.Points, output.PutExt);
            output.PutList<RegionData>(this.Regions, output.PutExt);
            output.PutList<DecorationData>(this.Decorations, output.PutExt);
            output.PutList<UnitData>(this.Units, output.PutExt);
            output.PutList<ItemData>(this.Items, output.PutExt);
            output.PutList<AreaData>(this.Areas, output.PutExt);
            output.PutExt(this.Properties);
            {
                this.serial_datas = new List<ISNData>();
                PropertyUtil.CollectFieldTypeValues<ISNData>(this, serial_datas);
                output.PutList(GetSerialDatas(), output.PutExt);
            }
            output.PutList<SceneAbilityData>(this.Abilities, output.PutExt);
            output.PutUTF(this.Script);
            output.PutList<ZoneEvent>(this.Events, output.PutExt);
            output.PutList<ZoneVar>(this.EnvironmentVars, output.PutExt);

        }
        public void ReadExternalByClient(IInputStream input)
        {
            this.EditorPath = input.GetUTF();
            this.BlockSeekCritical = input.GetF32();
            this.ID = input.GetS32();
            this.FileName = input.GetUTF();
            this.BGM = input.GetUTF();
            this.TotalTimeLimitSEC = input.GetS32();
            this.ResourceProperty = input.GetUTF();
            this.Name = input.GetUTF();
            this.Desc = input.GetUTF();
            this.Attributes = input.GetUTFArray();
            this.Terrain = input.GetExt<TerrainData>();
            this.MaxPlayer = input.GetS32();
            this.MaxUnit = input.GetS32();
            this.DefaultUnitLevel = input.GetS32();
            this.RemoveUnitOnDisconnect = input.GetBool();
            this.ClientSyncRange = input.GetF32();
            this.Points = input.GetList<PointData>(input.GetExt<PointData>);
            this.Regions = input.GetList<RegionData>(input.GetExt<RegionData>);
            this.Decorations = input.GetList<DecorationData>(input.GetExt<DecorationData>);
            this.Units = input.GetList<UnitData>(input.GetExt<UnitData>);
            this.Items = input.GetList<ItemData>(input.GetExt<ItemData>);
            this.Areas = input.GetList<AreaData>(input.GetExt<AreaData>);
            this.Properties = input.GetExt<ISceneProperties>(this.Properties);
            {
                this.serial_datas = input.GetListAny<ISNData>();
            }
        }
        public void ReadExternal(IInputStream input)
        {
            ReadExternalByClient(input);
            this.Abilities = input.GetListAny<SceneAbilityData>();
            this.Script = input.GetUTF();
            this.Events = input.GetList<ZoneEvent>(input.GetExt<ZoneEvent>);
            this.EnvironmentVars = input.GetList<ZoneVar>(input.GetExt<ZoneVar>);
        }

    }

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

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


}