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