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