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 /// /// 2个单位是否碰撞 /// /// /// /// 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; } /// /// 单位和地图碰撞检测 /// /// /// public virtual bool TouchMap(InstanceZoneObject o) { return path_finder.TouchMapBlock( (int)((o.X) / m_TerrainSrc.GridCellW), (int)((o.Y) / m_TerrainSrc.GridCellH)); } /// /// 单位尝试用心的坐标和地图碰撞 /// /// /// /// /// public virtual bool TryTouchMap(InstanceZoneObject o, float x, float y) { return path_finder.TouchMapBlock( (int)((x) / m_TerrainSrc.GridCellW), (int)((y) / m_TerrainSrc.GridCellH)); } /// /// 单位尝试移动,并自动对齐到地图边界 /// /// /// /// /// /// /// 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; } /// /// 单位视线是否和地图相交 /// /// /// /// /// /// /// 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)); } /// /// 当前单位是否和建筑碰撞 /// /// /// 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; } /// /// 包含身体高度和建筑碰撞 /// /// /// 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; } /// /// 当前单位是否和单位碰撞 /// /// /// 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; } } /// /// 按坐标取分割块 /// /// /// /// public SpaceDivision.SpaceCellNode GetSpaceCellNode(float x, float y) { return mSpaceDiv.GetSpaceCellNode(x, y); } /// /// 按格取分割块 /// /// /// /// public SpaceDivision.SpaceCellNode GetSpaceCellNodeByBlock(int bx, int by) { return mSpaceDiv.GetSpaceCellNodeByBlock(bx, by); } public List ListSpaceCellNodes() { return mSpaceDiv.ListSpaceCellNodes(); } /// /// 刷新空间分割位置为有改变 /// /// internal void nearChange(InstanceZoneObject obj) { mSpaceDiv.NearChange(obj.mCurCellNode); } /// /// 清除空间位置 /// /// 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); } } /// /// 判断是否附近有位置变化 /// /// /// /// 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); } /// /// 获取当前坐标附近的所有单位容量 /// /// /// /// public int getNearObjectsCapacity(float x, float y) { return mSpaceDiv.GetNearObjectsCapacity(x, y); } /** * 以目标点为中心,circle为半径,找可行走区域。找到了返回true;找不到返回false; * sx, sy 起始位置 * dstx, dsty 目标位置 * circle 搜寻半径 * outx, outy修改后的目标点 */ public bool GetNearWay(float sx, float sy, float dstx, float dsty, float circle, ref float outx, ref float outy) { //以目标点为中心,一圈一圈向外查找可行走的块 //起始点与终点连线方向上的点优先 int W = Terrain.GridCellW; int H = Terrain.GridCellH; float squCircle = circle * circle; int dr = ((int)circle) / W; float vx = sx > dstx ? 1 : -1; float vy = sy > dsty ? 1 : -1; bool f = true; for (int r = 1; r <= dr; r++) { for (int v = 1; v <= 4; v++) { float xx = dstx + W * r * vx; float yy = dsty + H * r * vy; for (int dx = f ? 0 : 1; f ? dx <= r : dx < r; dx++) { float x = dstx + dx * W * vx; if (MathVector.getDistanceSquare(x, yy, dstx, dsty) < squCircle) { if (!path_finder.TouchMapBlock(((int)x) / W, ((int)yy) / H) && findPath(sx, sy, x, yy) != null) { outx = x; outy = yy; return true; } } } for (int dy = f ? 1 : 0; f ? dy < r : dy <= r; dy++) { float y = dsty + dy * H * vy; if (MathVector.getDistanceSquare(xx, y, dstx, dsty) < squCircle) { if (!path_finder.TouchMapBlock(((int)xx) / W, ((int)y) / H) && findPath(sx, sy, xx, y) != null) { outx = xx; outy = y; return true; } } } if (f) vy *= -1; else vx *= -1; f = !f; } } outx = -1; outy = -1; return false; } //--------------------------------------------------------------------------------------------------------------- #region _Deprecated_ /// /// 获取当前坐标附近的所有单位 /// /// /// /// [Obsolete("use {@link #ForEachNearObjects} for best performance!")] public List getNearObjects(float x, float y) { List list = new List(getNearObjectsCapacity(x, y)); getNearObjects(x, y, list); return list; } /// /// 获取当前圆形坐标附近所有单位 /// /// /// /// /// [Obsolete("use {@link #ForEachNearObjects} for best performance!")] public List getNearObjects(float x, float y, float r) { List list = new List(getNearObjectsCapacity(x, y)); getNearObjects(x, y, r, list); return list; } /// /// 获取当前矩形附近所有单位 /// /// /// /// /// /// [Obsolete("use {@link #ForEachNearObjectsRect} for best performance!")] public List getNearObjectsRect(float x1, float y1, float x2, float y2) { List list = new List(); getNearObjectsRect(x1, y1, x2, y2, list); return list; } //---------------------------------------------------------------------------------------------------------------------------- /// /// 获取当前坐标附近的所有单位 /// /// /// /// [Obsolete] private void getNearObjects(float x, float y, List list) { SpaceDivision.SpaceCellNode node = mSpaceDiv.GetSpaceCellNode(x, y); if (node != null) { list.AddRange(node.AsChildList()); for (int i = node.nears.Count - 1; i >= 0; --i) { list.AddRange(node.nears[i].AsChildList()); } } } /// /// 获取当前坐标附近的所有单位 /// /// /// /// /// [Obsolete] private void getNearObjects(float x, float y, float r, List list) { if (r < mSpaceDiv.SpaceCellW && r < mSpaceDiv.SpaceCellH) { SpaceDivision.SpaceCellNode node = mSpaceDiv.GetSpaceCellNode(x, y); if (node != null) { list.AddRange(node.AsChildList()); for (int i = node.nears.Count - 1; i >= 0; --i) { list.AddRange(node.nears[i].AsChildList()); } } } 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()); } } } } /// /// 获取当前坐标附近的所有单位 /// /// /// /// /// /// [Obsolete] private void getNearObjectsRect(float x1, float y1, float x2, float y2, List 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()); } } } #endregion //---------------------------------------------------------------------------------------------------------------------------- /// /// 获取当前坐标附近的所有单位 /// /// /// /// /// is cancel public bool ForEachNearObjects(float x, float y, SpaceDivision.ObjectForEachAction indexer) where T : InstanceZoneObject { return mSpaceDiv.ForEachNearObjects(x, y, indexer); } /// /// 获取当前坐标附近的所有单位 /// /// /// /// /// /// is cancel public bool ForEachNearObjects(float x, float y, float r, SpaceDivision.ObjectForEachAction indexer) where T : InstanceZoneObject { return mSpaceDiv.ForEachNearObjects(x, y, r, indexer); } /// /// 获取当前坐标附近的所有单位 /// /// /// /// /// /// /// is cancel public bool ForEachNearObjectsRect(float x1, float y1, float x2, float y2, SpaceDivision.ObjectForEachAction indexer) where T : InstanceZoneObject { return mSpaceDiv.ForEachNearObjectsRect(x1, y1, x2, y2, indexer); } //---------------------------------------------------------------------------------------------------------------------------- /// /// 获取【矩形】范围内的所有单位 /// /// /// /// /// /// /// /// /// /// public int getObjectsRectRange( Collider.ObjectBodyTouchRect func, float x1, float y1, float x2, float y2, List 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)) { if (list != null) list.Add(o as T); count++; } }); return count; } [Obsolete] public List getObjectsRectRange( Collider.ObjectBodyTouchRect func, float x1, float y1, float x2, float y2, ObjectAoiStatus aoi) where T : InstanceZoneObject { List ret = new List(getNearObjectsCapacity(x1, y1)); getObjectsRectRange(func, x1, y1, x2, y2, ret, aoi); return ret; } public int getObjectsCountRectRange( Collider.ObjectBodyTouchRect func, float x1, float y1, float x2, float y2, ObjectAoiStatus aoi) where T : InstanceZoneObject { return getObjectsRectRange(func, x1, y1, x2, y2, null, aoi); } /// /// 获取【圆形】范围内的所有单位 /// /// /// /// /// /// /// /// /// public int getObjectsRoundRange( Collider.ObjectBodyTouchRound func, float x, float y, float r, List 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(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 getObjectsRoundRange( Collider.ObjectBodyTouchRound func, float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceZoneObject { List ret = new List(getNearObjectsCapacity(x, y)); getObjectsRoundRange(func, x, y, r, ret, aoi); return ret; } public int getObjectsCountRoundRange( Collider.ObjectBodyTouchRound func, float x, float y, float r, ObjectAoiStatus aoi) where T : InstanceZoneObject { return getObjectsRoundRange(func, x, y, r, null, aoi); } /// /// 获取【扇形】范围内的所有单位,扇形范围为【弧度】 /// /// /// /// /// /// /// /// /// /// /// public int getObjectsFanRange( Collider.ObjectBodyTouchFan func, float x, float y, float distance, float startAngle, float endAngle, List 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 getObjectsFanRange( Collider.ObjectBodyTouchFan func, float x, float y, float distance, float startAngle, float endAngle, ObjectAoiStatus aoi) where T : InstanceZoneObject { List ret = new List(getNearObjectsCapacity(x, y)); getObjectsFanRange(func, x, y, distance, startAngle, endAngle, ret, aoi); return ret; } /// /// 获取【直线】穿过范围内的所有单位(粗线段) /// /// /// /// /// /// /// /// /// /// /// public int getObjectsRectLineRange( Collider.ObjectBodyTouchRectLine func, float x1, float y1, float x2, float y2, float line_r, List 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 getObjectsRectLineRange( Collider.ObjectBodyTouchRectLine func, float x1, float y1, float x2, float y2, float line_r, ObjectAoiStatus aoi) where T : InstanceZoneObject { List ret = new List(getNearObjectsCapacity(x1, y1)); getObjectsRectLineRange(func, x1, y1, x2, y2, line_r, ret, aoi); return ret; } /// /// 单位【运动轨迹】从A点移动到B点经过的碰撞 /// /// /// /// /// /// /// /// /// /// /// public int getObjectsRoundLineRange( Collider.ObjectBodyTouchRoundLine func, float sx, float sy, float dx, float dy, float line_r, List 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 getObjectsRoundLineRange( Collider.ObjectBodyTouchRoundLine func, float sx, float sy, float dx, float dy, float line_r, ObjectAoiStatus aoi) where T : InstanceZoneObject { List ret = new List(getNearObjectsCapacity(sx, sy)); getObjectsRoundLineRange(func, sx, sy, dx, dy, line_r, ret , aoi); return ret; } #endregion //-------------------------------------------------------------------------------------------------------// protected List m_UnitsPos = new List(); protected List m_UnitsStates = new List(); #region SYNC_POS /// /// 获得场景当前所有装饰物状态 /// /// 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; } /// /// 获得所有单位同步信息,一般在进入场景时同步 /// /// /// 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; } /// /// 获得半径内所有单位同步信息 /// /// /// /// /// /// 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; } /// /// 获得空间分割块所有单位同步信息 /// /// /// /// /// 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 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; } /// /// 得到半径范围内的所有移动信息 /// /// /// /// /// public SyncPosEvent GetSyncPosEventInRange(float x, float y, float range) { using (var units = ListObjectPool.AllocAutoRelease()) using (var units_st = ListObjectPool.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; } /// /// 得到空间分割块范围内的所有移动信息 /// /// /// /// public SyncPosEvent GetSyncPosEventBySpace(int bx, int by) { SpaceDivision.SpaceCellNode space = GetSpaceCellNodeByBlock(bx, by); if (space != null) { List units = new List(space.Count); List units_st = new List(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 objs, InstancePlayer Actor, PlayerClientObject playerClient) { if (objs.Count > 0) { //using (var units = ListObjectPool.AllocAutoRelease()) //using (var units_st = ListObjectPool.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 units = new List(); 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.AllocAutoRelease()) using (var units_st = ListObjectPool.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 } }