using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonLang;
using CommonAI.RTS.Manhattan;
using CommonAI.Zone.Helper;
using CommonAI.RTS;
using CommonLang.Vector;
using CommonAI.Zone.Interface;
using static CommonAI.ZoneServer.JSGModule.MSpaceNodeCache;
using CommonAI.ZoneServer.JSGModule;

namespace CommonAI.Zone.Instance
{
    partial class InstanceZone
    {
        #region COLLIDE


        /// <summary>
        /// 2个单位是否碰撞
        /// </summary>
        /// <param name="s"></param>
        /// <param name="d"></param>
        /// <returns></returns>
        public virtual bool TouchObject2(InstanceZoneObject s, InstanceZoneObject d)
        {
            if (s == d) return false;
            float w = s.X - d.X;
            float h = s.Y - d.Y;
            float r = s.BodyBlockSize + d.BodyBlockSize;
            if (w * w + h * h <= r * r)
            {
                return true;
            }
            return false;
        }
        /// <summary>
        /// 单位和地图碰撞检测
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public virtual bool TouchMap(InstanceZoneObject o)
        {
            return path_finder.TouchMapBlock(
                (int)((o.X) / m_TerrainSrc.GridCellW),
                (int)((o.Y) / m_TerrainSrc.GridCellH));
        }
        /// <summary>
        /// 单位尝试用心的坐标和地图碰撞
        /// </summary>
        /// <param name="o"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public virtual bool TryTouchMap(InstanceZoneObject o, float x, float y)
        {
            return path_finder.TouchMapBlock(
                (int)((x) / m_TerrainSrc.GridCellW),
                (int)((y) / m_TerrainSrc.GridCellH));
        }
        /// <summary>
        /// 单位尝试移动,并自动对齐到地图边界
        /// </summary>
        /// <param name="o"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <returns></returns>
        public virtual CommonAI.RTS.Manhattan.AstarManhattan.TryMoveToMapBorderResult TryMoveToMapBorder(InstanceZoneObject o, ref float x, ref float y, float dx, float dy)
        {
            return path_finder.TryMoveToMapBorder(ref x, ref y, dx, dy);
        }

		public virtual CommonAI.RTS.Manhattan.AstarManhattan.TryMoveToMapBorderResult TryMoveToMapBorder(InstanceZoneObject o, ref Vector2 pos, float dx, float dy)
		{
			float x = pos.X;
			float y = pos.Y;
			var result = path_finder.TryMoveToMapBorder(ref x, ref y, dx, dy);

			pos.SetX(x);
			pos.SetY(y);
			return result;
		}

		/// <summary>
		/// 单位视线是否和地图相交
		/// </summary>
		/// <param name="src"></param>
		/// <param name="sx"></param>
		/// <param name="sy"></param>
		/// <param name="dx"></param>
		/// <param name="dy"></param>
		/// <returns></returns>
		public virtual bool RaycastMap(InstanceUnit src, float sx, float sy, float dx, float dy)
        {
            if (CMath.includeRectPoint(0, 0, m_TerrainSrc.TotalWidth, m_TerrainSrc.TotalHeight, sx, sy) &&
                CMath.includeRectPoint(0, 0, m_TerrainSrc.TotalWidth, m_TerrainSrc.TotalHeight, dx, dy))
            {
                return path_finder.TouchMapLine(sx, sy, dx, dy);
            }
            return false;
        }

        public bool intersectMapByBlock(int bx, int by)
        {
            return path_finder.TouchMapBlock(bx, by);
        }
        public bool intersectMapByPos(float x, float y)
        {
            return path_finder.TouchMapBlock(
                (int)((x) / m_TerrainSrc.GridCellW),
                (int)((y) / m_TerrainSrc.GridCellH));
        }

        /// <summary>
        /// 当前单位是否和建筑碰撞
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        public InstanceZoneObject intersectNearStaticBlockable(InstanceZoneObject a)
        {
            InstanceZoneObject ret = null;
            ForEachNearObjects(a.X, a.Y, (InstanceZoneObject o, ref bool cancel) =>
            {
                if (o.IsStaticBlockable && o.IntersectObj && TouchObject2(a, o))
                {
                    ret = o;
                    cancel = true;
                }
            });
            return ret;
        }
        /// <summary>
        /// 包含身体高度和建筑碰撞
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        public InstanceZoneObject intersectNearStaticBlockableZ(InstanceZoneObject a)
        {
            InstanceZoneObject ret = null;
            ForEachNearObjects(a.X, a.Y, (InstanceZoneObject o, ref bool cancel) =>
            {
                if (o.IsStaticBlockable && o.IntersectObj)
                {
                    if (CMath.IsIntersect2(a.Z, a.BodyHeight, o.Z, o.BodyHeight) && TouchObject2(a, o))
                    {
                        ret = o;
                        cancel = true;
                    }
                }
            });
            return ret;
        }

        /// <summary>
        /// 当前单位是否和单位碰撞
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        public InstanceZoneObject intersectNearUnit(InstanceZoneObject a)
        {
            InstanceZoneObject ret = null;
            ForEachNearObjects(a.X, a.Y, (InstanceZoneObject o, ref bool cancel) =>
            {
                if ((o.IntersectObj) && TouchObject2(a, o))
                {
                    ret = o;
                    cancel = true;
                }
            });
            return ret;
        }



        #endregion

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

        #region MANHATTAN_MAP

        private ZoneManhattanMap path_terrain_data;
        private AstarManhattan path_finder;
        private ManhattanMapAreaGenerator path_terrain_area_gen;
		

		protected virtual void InitTerrain(ZoneEditor.SceneData data, int spaceDiv, out ZoneManhattanMap terrain_data, out AstarManhattan path_finder, out ManhattanMapAreaGenerator area_gen)
        {			
			terrain_data = new ZoneManhattanMap(m_TerrainSrc.Clone() as ZoneInfo, Templates.TerrainDefinition);
			path_finder = new AstarManhattan(data.TemplateID, terrain_data, true, spaceDiv);

			area_gen = new ManhattanMapAreaGenerator(terrain_data.Data);			
		}

        protected virtual void DisposeTerrain()
        {
            this.path_finder.Dispose();
            this.path_terrain_data.Dispose();
            this.path_finder = null;
            this.path_terrain_data = null;
            this.path_terrain_area_gen = null;
            this.sync_pos_list.Clear();
        }


        public AstarManhattan PathFinder
        {
            get { return path_finder; }
        }
        public ZoneManhattanMap PathFinderTerrain
        {
            get { return path_terrain_data; }
        }
        public ManhattanMapAreaGenerator TerrainAreaGenerator
        {
            get { return path_terrain_area_gen; }
        }


        public AstarManhattan.MWayPoint findPath(float sx, float sy, float dx, float dy)
        {
            AstarManhattan.MWayPoint ret;
            var result = path_finder.findPath(sx, sy, dx, dy, out ret);
            switch (result)
            {
                case AstarManhattan.FindPathResult.Cross:
                case AstarManhattan.FindPathResult.Destination:
                    return ret;
                default:
                    return null;
            }
        }
      
        public ZoneArea GetArea(float x, float y)
        {
            var node = PathFinder.GetMapNodeByPos(x, y) as ZoneMapNode;
            if (node != null)
            {
                return node.ServerArea;
            }
            return null;
        }
        public ZoneArea GetAreaByBlock(int bx, int by)
        {
            var node = PathFinder.GetMapNode(bx, by) as ZoneMapNode;
            if (node != null)
            {
                return node.ServerArea;
            }
            return null;
        }

        #endregion

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

        #region SPACE_DIVISION

        public int SpaceXCount { get { return mSpaceDiv.SpaceXCount; } }
        public int SpaceYCount { get { return mSpaceDiv.SpaceYCount; } }

        /// <summary>
        /// 按坐标取分割块
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public SpaceDivision.SpaceCellNode GetSpaceCellNode(float x, float y)
        {
            return mSpaceDiv.GetSpaceCellNode(x, y);
        }
        /// <summary>
        /// 按格取分割块
        /// </summary>
        /// <param name="bx"></param>
        /// <param name="by"></param>
        /// <returns></returns>
        public SpaceDivision.SpaceCellNode GetSpaceCellNodeByBlock(int bx, int by)
        {
            return mSpaceDiv.GetSpaceCellNodeByBlock(bx, by);
        }
        public List<SpaceDivision.SpaceCellNode> ListSpaceCellNodes()
        {
            return mSpaceDiv.ListSpaceCellNodes();
        }


        /// <summary>
        /// 刷新空间分割位置为有改变
        /// </summary>
        /// <param name="obj"></param>
        internal void nearChange(InstanceZoneObject obj)
        {
            mSpaceDiv.NearChange(obj.mCurCellNode);
        }

        /// <summary>
        /// 清除空间位置
        /// </summary>
        /// <param name="obj"></param>
        internal void clearSpace(InstanceZoneObject obj)
        {
            mSpaceDiv.ClearSpace(obj.mCurCellNode);
        }
        
        internal bool swapSpace(InstanceZoneObject obj, bool nearchange)
        {
            SpaceDivision.SpaceCellNode old_cell = obj.CurrentSpaceCellNode;
            if (mSpaceDiv.SwapSpace(obj.mCurCellNode, obj.X, obj.Y, nearchange))
            {
                if (mOnObjectSpaceChanged != null)
                {
                    SpaceDivision.SpaceCellNode new_cell = obj.CurrentSpaceCellNode;
                    mOnObjectSpaceChanged.Invoke(this, obj, old_cell, new_cell);
                }
                return true;
            }
            return false;
        }
        internal void swapArea(InstanceZoneObject obj, ZoneArea o, ZoneArea n)
        {
            if (o != null && o.Enable) { o.do_onUnitLeave(obj); }
            if (n != null && n.Enable) { n.do_onUnitEnter(obj); }
            if (mOnObjectAreaChanged != null)
            {
                mOnObjectAreaChanged.Invoke(this, obj, o, n);
            }
        }

        /// <summary>
        /// 判断是否附近有位置变化
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public bool IsNearChanged(float x, float y)
        {
            return mSpaceDiv.IsNearChanged(x, y);
        }
        public bool IsNearChanged(float x, float y, float r)
        {
            return mSpaceDiv.IsNearChanged(x, y, r);
        }
        public bool IsNearChanged(float x1, float y1, float x2, float y2)
        {
            return mSpaceDiv.IsNearChanged(x1, y1, x2, y2);
        }

        /// <summary>
        /// 获取当前坐标附近的所有单位容量
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public int getNearObjectsCapacity(float x, float y)
        {
            return mSpaceDiv.GetNearObjectsCapacity(x, y);
        }

        //---------------------------------------------------------------------------------------------------------------
        #region _Deprecated_
        /// <summary>
        /// 获取当前坐标附近的所有单位
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        [Obsolete("use {@link #ForEachNearObjects} for best performance!")]
        public List<InstanceZoneObject> getNearObjects(float x, float y)
        {
            List<InstanceZoneObject> list = new List<InstanceZoneObject>(getNearObjectsCapacity(x, y));
            getNearObjects(x, y, list);
            return list;
        }
        /// <summary>
        /// 获取当前圆形坐标附近所有单位
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="r"></param>
        /// <returns></returns>
        [Obsolete("use {@link #ForEachNearObjects} for best performance!")]
        public List<InstanceZoneObject> getNearObjects(float x, float y, float r)
        {
            List<InstanceZoneObject> list = new List<InstanceZoneObject>(getNearObjectsCapacity(x, y));
            getNearObjects(x, y, r, list);
            return list;
        }
        /// <summary>
        /// 获取当前矩形附近所有单位
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <returns></returns>
        [Obsolete("use {@link #ForEachNearObjectsRect} for best performance!")]
        public List<InstanceZoneObject> getNearObjectsRect(float x1, float y1, float x2, float y2)
        {
            List<InstanceZoneObject> list = new List<InstanceZoneObject>();
            getNearObjectsRect(x1, y1, x2, y2, list);
            return list;
        }
        
        //----------------------------------------------------------------------------------------------------------------------------
        
        /// <summary>
        /// 获取当前坐标附近的所有单位
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="list"></param>
        [Obsolete]
        private void getNearObjects(float x, float y, List<InstanceZoneObject> list)
        {
            SpaceDivision.SpaceCellNode node = mSpaceDiv.GetSpaceCellNode(x, y);
            if (node != null)
            {
                list.AddRange(node.AsChildList<InstanceZoneObject>());
                for (int i = node.nears.Count - 1; i >= 0; --i)
                {
                    list.AddRange(node.nears[i].AsChildList<InstanceZoneObject>());
                }
            }
        }

		/// <summary>
		/// 获取当前坐标附近的所有单位
		/// </summary>
		/// <param name="x"></param>
		/// <param name="y"></param>
		/// <param name="r"></param>
		/// <param name="list"></param>
		[Obsolete]
        private void getNearObjects(float x, float y, float r, List<InstanceZoneObject> list)
        {
            if (r < mSpaceDiv.SpaceCellW && r < mSpaceDiv.SpaceCellH)
            {
                SpaceDivision.SpaceCellNode node = mSpaceDiv.GetSpaceCellNode(x, y);
                if (node != null)
                {
                    list.AddRange(node.AsChildList<InstanceZoneObject>());
                    for (int i = node.nears.Count - 1; i >= 0; --i)
                    {
                        list.AddRange(node.nears[i].AsChildList<InstanceZoneObject>());
                    }
                }
            }
            else
            {
                int cx1 = ((int)((x - r) / mSpaceDiv.SpaceCellW)) - 1;
                int cy1 = ((int)((y - r) / mSpaceDiv.SpaceCellH)) - 1;
                int cx2 = ((int)((x + r) / mSpaceDiv.SpaceCellW)) + 1;
                int cy2 = ((int)((y + r) / mSpaceDiv.SpaceCellH)) + 1;
                cx1 = Math.Max(cx1, 0);
                cy1 = Math.Max(cy1, 0);
                cx2 = Math.Min(cx2, mSpaceDiv.SpaceXCount - 1);
                cy2 = Math.Min(cy2, mSpaceDiv.SpaceYCount - 1);
                for (int cx = cx1; cx <= cx2; ++cx)
                {
                    for (int cy = cy1; cy <= cy2; ++cy)
                    {
                        SpaceDivision.SpaceCellNode cn = mSpaceDiv.GetSpaceCellNodeByBlock(cx, cy);
                        list.AddRange(cn.AsChildList<InstanceZoneObject>());
                    }
                }
            }
        }

        /// <summary>
        /// 获取当前坐标附近的所有单位
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="list"></param>
        [Obsolete]
        private void getNearObjectsRect(float x1, float y1, float x2, float y2, List<InstanceZoneObject> list)
        {
            int cx1 = ((int)((Math.Min(x1, x2)) / mSpaceDiv.SpaceCellW)) - 1;
            int cy1 = ((int)((Math.Min(y1, y2)) / mSpaceDiv.SpaceCellH)) - 1;
            int cx2 = ((int)((Math.Max(x1, x2)) / mSpaceDiv.SpaceCellW)) + 1;
            int cy2 = ((int)((Math.Max(y1, y2)) / mSpaceDiv.SpaceCellH)) + 1;
            cx1 = Math.Max(cx1, 0);
            cy1 = Math.Max(cy1, 0);
            cx2 = Math.Min(cx2, mSpaceDiv.SpaceXCount - 1);
            cy2 = Math.Min(cy2, mSpaceDiv.SpaceYCount - 1);
            for (int cx = cx1; cx <= cx2; ++cx)
            {
                for (int cy = cy1; cy <= cy2; ++cy)
                {
                    SpaceDivision.SpaceCellNode cn = mSpaceDiv.GetSpaceCellNodeByBlock(cx, cy);
                    list.AddRange(cn.AsChildList<InstanceZoneObject>());
                }
            }
        }
        #endregion
        //----------------------------------------------------------------------------------------------------------------------------

        /// <summary>
        /// 获取当前坐标附近的所有单位
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="indexer"></param>
        /// <returns>is cancel</returns>
        public bool ForEachNearObjects<T>(float x, float y, SpaceDivision.ObjectForEachAction<T> indexer) where T : InstanceZoneObject
        {
            return mSpaceDiv.ForEachNearObjects(x, y, indexer);
        }


        /// <summary>
        /// 获取当前坐标附近的所有单位
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="r"></param>
        /// <param name="indexer"></param>
        /// <returns>is cancel</returns>
        public bool ForEachNearObjects<T>(float x, float y, float r, SpaceDivision.ObjectForEachAction<T> indexer) where T : InstanceZoneObject
        {
            return mSpaceDiv.ForEachNearObjects(x, y, r, indexer);
        }

        /// <summary>
        /// 获取当前坐标附近的所有单位
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="indexer"></param>
        /// <returns>is cancel</returns>
        public bool ForEachNearObjectsRect<T>(float x1, float y1, float x2, float y2, SpaceDivision.ObjectForEachAction<T> indexer) where T : InstanceZoneObject
        {
            return mSpaceDiv.ForEachNearObjectsRect(x1, y1, x2, y2, indexer);
        }


        //----------------------------------------------------------------------------------------------------------------------------
        /// <summary>
        /// 获取【矩形】范围内的所有单位
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="list"></param>
        /// <param name="aoi"></param>
        /// <returns></returns>
        public int getObjectsRectRange<T>(
          Collider.ObjectBodyTouchRect func,
          float x1, float y1,
          float x2, float y2,
          List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            int count = 0;
            ForEachNearObjectsRect<T>(x1, y1, x2, y2, (T o, ref bool cancel) =>
            {
                if (o.AoiStatus == aoi && func(o, x1, y1, x2, y2))
                {
                    if (list != null) list.Add(o as T);
                    count++;
                }
            });
            return count;
        }

        [Obsolete]
        public List<T> getObjectsRectRange<T>(
            Collider.ObjectBodyTouchRect func,
            float x1, float y1,
            float x2, float y2, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            List<T> ret = new List<T>(getNearObjectsCapacity(x1, y1));
            getObjectsRectRange<T>(func, x1, y1, x2, y2, ret, aoi);
            return ret;
        }

        public int getObjectsCountRectRange<T>(
            Collider.ObjectBodyTouchRect func,
            float x1, float y1,
            float x2, float y2, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            return getObjectsRectRange<T>(func, x1, y1, x2, y2, null, aoi);
        }

        /// <summary>
        /// 获取【圆形】范围内的所有单位
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="r"></param>
        /// <param name="list"></param>
        /// <param name="aoi"></param>   
        /// <returns></returns> 
        public int getObjectsRoundRange<T>(
            Collider.ObjectBodyTouchRound func,
            float x, float y, float r,
            List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            int count = 0;
            ForEachNearObjects(x, y, r, (T o, ref bool cancel) =>
            {
                if (o.AoiStatus == aoi && func(o, x, y, r))
                {
                    if (list != null) list.Add(o as T);
                    count++;
                }
            });
            return count;
        }

		//单位是否在范围内
		public InstanceUnit isUnitInRoundRange<T>(int unitID, float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceUnit
		{
			InstanceUnit unit = null;
            ForEachNearObjects(x, y, r, (T o, ref bool cancel) =>
			{
				if (o.AoiStatus == aoi && o.Info.TemplateID == unitID)
				{
					cancel = true;
					unit = o;
                }
			});

			return unit;
		}


		[Obsolete]
        public List<T> getObjectsRoundRange<T>(
            Collider.ObjectBodyTouchRound func,
            float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            List<T> ret = new List<T>(getNearObjectsCapacity(x, y));
            getObjectsRoundRange<T>(func, x, y, r, ret, aoi);
            return ret;
        }

        public int getObjectsCountRoundRange<T>(
            Collider.ObjectBodyTouchRound func,
            float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            return getObjectsRoundRange<T>(func, x, y, r, null, aoi);
        }


        /// <summary>
        /// 获取【扇形】范围内的所有单位,扇形范围为【弧度】
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="distance"></param>
        /// <param name="startAngle"></param>
        /// <param name="endAngle"></param>
        /// <param name="list"></param>
        /// <param name="aoi"></param> 
        /// <returns></returns>
        public int getObjectsFanRange<T>(
            Collider.ObjectBodyTouchFan func,
            float x, float y, float distance,
            float startAngle, float endAngle,
            List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            int count = 0;
            ForEachNearObjects(x, y, distance, (T o, ref bool cancel) =>
            {
                if (o.AoiStatus == aoi && func(o, x, y, distance, startAngle, endAngle))
                {
                    if (list != null) list.Add(o as T);
                    count++;
                }
            });
            return count;
        }

        [Obsolete]
        public List<T> getObjectsFanRange<T>(
            Collider.ObjectBodyTouchFan func,
            float x, float y, float distance,
            float startAngle, float endAngle, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            List<T> ret = new List<T>(getNearObjectsCapacity(x, y));
            getObjectsFanRange<T>(func, x, y, distance, startAngle, endAngle, ret, aoi);
            return ret;
        }

        /// <summary>
        /// 获取【直线】穿过范围内的所有单位(粗线段)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="line_r"></param>
        /// <param name="list"></param>
        /// <param name="aoi"></param>
        /// <returns></returns>
        public int getObjectsRectLineRange<T>(
            Collider.ObjectBodyTouchRectLine func,
            float x1, float y1, float x2, float y2, float line_r, 
            List<T> list, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            int count = 0;
            ForEachNearObjectsRect(x1, y1, x2, y2, (T o, ref bool cancel) =>
            {
                if (o.AoiStatus == aoi && func(o, x1, y1, x2, y2, line_r))
                {
                    if (list != null) list.Add(o as T);
                    count++;
                }
            });
            return count;
        }
        [Obsolete]
        public List<T> getObjectsRectLineRange<T>(
            Collider.ObjectBodyTouchRectLine func,
            float x1, float y1, float x2, float y2, float line_r, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            List<T> ret = new List<T>(getNearObjectsCapacity(x1, y1));
            getObjectsRectLineRange(func, x1, y1, x2, y2, line_r, ret, aoi);
            return ret;
        }

        /// <summary>
        /// 单位【运动轨迹】从A点移动到B点经过的碰撞
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <param name="sx"></param>
        /// <param name="sy"></param>
        /// <param name="dx"></param>
        /// <param name="dy"></param>
        /// <param name="line_r"></param>
        /// <param name="list"></param>
        /// <param name="aoi"></param>
        /// <returns></returns>
        public int getObjectsRoundLineRange<T>(
            Collider.ObjectBodyTouchRoundLine func,
            float sx, float sy, float dx, float dy, float line_r,
            List<T> list , ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            int count = 0;
            ForEachNearObjectsRect(sx, sy, dx, dy, (T o, ref bool cancel) =>
            {
                if (aoi == o.AoiStatus && func(o, sx, sy, dx, dy, line_r))
                {
                    if (list != null) list.Add(o as T);
                    count++;
                }
            });
            return count;
        }
        [Obsolete]
        public List<T> getObjectsRoundLineRange<T>(
            Collider.ObjectBodyTouchRoundLine func,
            float sx, float sy, float dx, float dy, float line_r, ObjectAoiStatus aoi) where T : InstanceZoneObject
        {
            List<T> ret = new List<T>(getNearObjectsCapacity(sx, sy));
            getObjectsRoundLineRange<T>(func, sx, sy, dx, dy, line_r, ret , aoi);
            return ret;
        }

		#endregion

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

		protected List<SyncPosEvent.UnitPos> m_UnitsPos = new List<SyncPosEvent.UnitPos>();
		protected List<SyncPosEvent.UnitState> m_UnitsStates = new List<SyncPosEvent.UnitState>();

		#region SYNC_POS

		/// <summary>
		/// 获得场景当前所有装饰物状态
		/// </summary>
		/// <returns></returns>
		public ZoneClient.SyncFlagsEvent GetSyncFlagsEvent()
        {
            var ret = new ZoneClient.SyncFlagsEvent();
            foreach (InstanceFlag flag in mFlags.Values)
            {
                if (flag is ZoneDecoration)
                {
                    ZoneDecoration d = flag as ZoneDecoration;
                    if (!d.Enable)
                    {
                        ret.ClosedDecorations.Add(d.Name);
                    }
                }
                if (flag.Tag != flag.SrcTag)
                {
                    ret.ChangedTags.Add(flag.Name, flag.Tag);
                }
            }
            return ret;
        }
        /// <summary>
        /// 获得所有单位同步信息,一般在进入场景时同步
        /// </summary>
        /// <param name="exclude"></param>
        /// <returns></returns>
        public ZoneClient.SyncObjectsEvent GetSyncUnitsEvent(InstanceUnit exclude = null)
        {
            var objs = mObjects.Objects;
            ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(mObjects.ObjectsCount);
            foreach (InstanceZoneObject o in objs)
            {
                if ((exclude == null || o != exclude) && o.ClientVisible)
                {
                    var sync = o.GenSyncInfo(true);
                    ret.Objects.Add(sync);
                }
            }
            return ret;
        }
        /// <summary>
        /// 获得半径内所有单位同步信息
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="r"></param>
        /// <param name="exclude"></param>
        /// <returns></returns>
        public ZoneClient.SyncObjectsEvent GetSyncUnitsEventInRange(float x, float y, float r, InstanceUnit exclude = null)
        {
            ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(getNearObjectsCapacity(x, y));
            ForEachNearObjects(x, y, r, (InstanceZoneObject o, ref bool cancel) =>
            {
                if ((exclude == null || o != exclude) && o.ClientVisible)
                {
                    if (Collider.Object_Pos_IncludeInRound(o, x, y, r))
                    {
                        var sync = o.GenSyncInfo(true);
                        ret.Objects.Add(sync);
                    }
                }
            });
            return ret;
        }
        /// <summary>
        /// 获得空间分割块所有单位同步信息
        /// </summary>
        /// <param name="bx"></param>
        /// <param name="by"></param>
        /// <param name="exclude"></param>
        /// <returns></returns>
        public ZoneClient.SyncObjectsEvent GetSyncUnitsEventBySpace(int bx, int by, InstanceUnit exclude = null)
        {
            SpaceDivision.SpaceCellNode space = GetSpaceCellNodeByBlock(bx, by);
            if (space != null)
            {
                ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(space.Count);
                space.ForEach((InstanceZoneObject o, ref bool cancel) =>
                {
                    if ((exclude == null || o != exclude) && o.ClientVisible)
                    {
                        var sync = o.GenSyncInfo(true);
                        ret.Objects.Add(sync);
                    }
                });
                return ret;
            }
            return null;
        }

        public ZoneClient.SyncObjectsEvent GetSyncObjectsEvent(ICollection<InstanceZoneObject> objs)
        {
            ZoneClient.SyncObjectsEvent ret = new ZoneClient.SyncObjectsEvent(objs.Count);
            foreach (InstanceZoneObject o in objs)
            {
                if (o.ClientVisible)
                {
                    var sync = o.GenSyncInfo(true);
                    ret.Objects.Add(sync);
                }
            }
            return ret;
        }

        /// <summary>
        /// 得到半径范围内的所有移动信息
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="range"></param>
        /// <returns></returns>
        public SyncPosEvent GetSyncPosEventInRange(float x, float y, float range)
        {
            using (var units = ListObjectPool<SyncPosEvent.UnitPos>.AllocAutoRelease())
            using (var units_st = ListObjectPool<SyncPosEvent.UnitState>.AllocAutoRelease())
            {
                SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
                SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
                ForEachNearObjects(x, y, range, (InstanceZoneObject u, ref bool cancel) =>
                {
                    if (u.ClientVisible && u.SyncPos && u.mCurCellNode.PosDirty())
                    {
                        if (Collider.Object_Pos_IncludeInRound(u, x, y, range))
                        {
                            if (u.GenSyncPos(ref pos))
                            {
                                units.Add(pos);
                            }
                            if (u is InstanceUnit)
                            {
                                InstanceUnit unit = u as InstanceUnit;
                                if (unit.GenSyncState(ref st))
                                {
                                    units_st.Add(st);
                                }
                            }
                        }
                    }
                });
                if (units.Count > 0 || units_st.Count > 0)
                {
                    SyncPosEvent ret = new SyncPosEvent(IsHalfSync, IsSyncZ, (uint)PassTimeMS);
                    ret.units_pos = units.ToArray();
                    ret.units_st = units_st.ToArray();
                    return ret;
                }
            }
            return null;
        }
        /// <summary>
        /// 得到空间分割块范围内的所有移动信息
        /// </summary>
        /// <param name="bx"></param>
        /// <param name="by"></param>
        /// <returns></returns>
        public SyncPosEvent GetSyncPosEventBySpace(int bx, int by)
        {
            SpaceDivision.SpaceCellNode space = GetSpaceCellNodeByBlock(bx, by);
            if (space != null)
            {
                List<SyncPosEvent.UnitPos> units = new List<SyncPosEvent.UnitPos>(space.Count);
                List<SyncPosEvent.UnitState> units_st = new List<SyncPosEvent.UnitState>(space.Count);
                SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
                SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
                space.ForEach((InstanceZoneObject u, ref bool cancel) =>
                {
                    if (u.mCurCellNode.PosDirty() && u.ClientVisible && u.SyncPos)
                    {
                        if (u.GenSyncPos(ref pos))
                        {
                            units.Add(pos);
                        }
                        if (u is InstanceUnit)
                        {
                            InstanceUnit unit = u as InstanceUnit;
                            if (unit.GenSyncState(ref st))
                            {
                                units_st.Add(st);
                            }
                        }
                    }
                });
                if (units.Count > 0 || units_st.Count > 0)
                {
                    SyncPosEvent ret = new SyncPosEvent(IsHalfSync, IsSyncZ, (uint)PassTimeMS);
                    ret.units_pos = units.ToArray();
                    ret.units_st = units_st.ToArray();
                    return ret;
                }
            }
            return null;
        }
        public SyncPosEvent GetSyncPosEvent(ICollection<InstanceZoneObject> objs, InstancePlayer Actor, PlayerClientObject playerClient)
        {
            if (objs.Count > 0)
            {
				//using (var units = ListObjectPool<SyncPosEvent.UnitPos>.AllocAutoRelease())
				//using (var units_st = ListObjectPool<SyncPosEvent.UnitState>.AllocAutoRelease())
				m_UnitsPos.Clear();
				m_UnitsStates.Clear();

				{
                    SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
                    SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
                    foreach (InstanceZoneObject u in objs)
                    {
						if (u.mCurCellNode.PosDirty() && u.ClientVisible && u.SyncPos)
                        {
							InstanceUnit unitTemp = u as InstanceUnit;
							if(unitTemp != null && unitTemp.CurrentActionSubstate != 0 && Actor.CurrentActionSubstate != unitTemp.CurrentActionSubstate)
							{
								if (playerClient.RemoveInRange(u))
								{
									continue;
								}
                            }
		
                            if (u.GenSyncPos(ref pos))
                            {
								m_UnitsPos.Add(pos);
                            }
                            if (u is InstanceUnit)
                            {
                                InstanceUnit unit = u as InstanceUnit;
                                if (unit.GenSyncState(ref st))
                                {
									m_UnitsStates.Add(st);
                                }
                            }
                        }
                    }
                    if (m_UnitsPos.Count > 0 || m_UnitsStates.Count > 0)
                    {
                        SyncPosEvent ret = new SyncPosEvent(IsHalfSync, IsSyncZ, PassTimeMS);
                        ret.units_pos = m_UnitsPos.ToArray();
                        ret.units_st = m_UnitsStates.ToArray();
                        return ret;
                    }
                }
            }
            return null;
        }


        readonly private PositionList sync_pos_list = new PositionList();

        internal class PositionList
        {
            public bool Enable = true;

            private List<InstanceZoneObject> units = new List<InstanceZoneObject>();

            public void Add(InstanceZoneObject u)
            {
                if (Enable)
                {
                    units.Add(u);
                }
            }

            public void Clear()
            {
                units.Clear();
            }

            public SyncPosEvent AsEvent(InstanceZone zone)
            {
                if (Enable)
                {
                    using (var units_pos = ListObjectPool<SyncPosEvent.UnitPos>.AllocAutoRelease())
                    using (var units_st = ListObjectPool<SyncPosEvent.UnitState>.AllocAutoRelease())
                    {
                        SyncPosEvent.UnitPos pos = new SyncPosEvent.UnitPos();
                        SyncPosEvent.UnitState st = new SyncPosEvent.UnitState();
                        for (int i = units.Count - 1; i >= 0; --i)
                        {
                            InstanceZoneObject obj = units[i];
                            if (obj.GenSyncPos(ref pos))
                            {
                                units_pos.Add(pos);
                            }
                            if (obj is InstanceUnit)
                            {
                                InstanceUnit unit = obj as InstanceUnit;
                                if (unit.GenSyncState(ref st))
                                {
                                    units_st.Add(st);
                                }
                            }
                        }
                        SyncPosEvent ret = new SyncPosEvent(zone.IsHalfSync, zone.IsSyncZ, (uint)zone.PassTimeMS);
                        ret.units_pos = units_pos.ToArray();
                        ret.units_st = units_st.ToArray();
                        return ret;
                    }
                }
                return null;
            }

            public int Count { get { return units.Count; } }

        }

        #endregion
    }
}