diff --git a/XNet.Business/Dto/SyncMsg.cs b/XNet.Business/Dto/SyncMsg.cs
index 8c74c10..9a02e1f 100644
--- a/XNet.Business/Dto/SyncMsg.cs
+++ b/XNet.Business/Dto/SyncMsg.cs
@@ -140,6 +140,19 @@ namespace XNet.Business
public string PlayerId { get; set; } = string.Empty;
}
+
+ [MessagePackObject]
+ public class PlayerPosReq
+ {
+ [Key("roomId")]
+ public string RoomId { get; set; } = string.Empty;
+ [Key("isAI")]
+ public bool IsAI { get; set; } = false;
+ [Key("endPos")]
+ public Vec3? EndPos { get; set; }
+ }
+
+
[MessagePackObject]
public class PlayerInitReq
{
diff --git a/XNet.Business/Entity/ControlPlayer.cs b/XNet.Business/Entity/ControlPlayer.cs
index 70852e8..e7cdd0e 100644
--- a/XNet.Business/Entity/ControlPlayer.cs
+++ b/XNet.Business/Entity/ControlPlayer.cs
@@ -50,10 +50,5 @@ namespace XNet.Business.Entity
/// 当前线性插值欧拉角,角色朝向
///
public Vec3 CurrentEuler { get; set; } = new Vec3();
-
- ///
- /// 路径导航索引下标
- ///
- public int AgentIndex { get; set; } = 0;
}
}
diff --git a/XNet.Business/Entity/PlayerStateInfo.cs b/XNet.Business/Entity/PlayerStateInfo.cs
index cbbd00a..adf12dc 100644
--- a/XNet.Business/Entity/PlayerStateInfo.cs
+++ b/XNet.Business/Entity/PlayerStateInfo.cs
@@ -1,4 +1,5 @@
-using System.Collections.Concurrent;
+using DotRecast.Detour.Crowd;
+using System.Collections.Concurrent;
using System.Net.WebSockets;
namespace XNet.Business.Entity
@@ -14,5 +15,12 @@ namespace XNet.Business.Entity
public bool IsAI { get; set; } = false;
public byte SetIdx { get; set; }
+
+ public bool IsCanControl { get; set; } = false;
+
+ ///
+ /// 路径导航索引
+ ///
+ public DtCrowdAgent Agent { get; set; } = null!;
}
}
diff --git a/XNet.Business/Global.cs b/XNet.Business/Global.cs
new file mode 100644
index 0000000..cf0d3a1
--- /dev/null
+++ b/XNet.Business/Global.cs
@@ -0,0 +1,10 @@
+namespace XNet.Business
+{
+ public class Global
+ {
+ ///
+ /// 客户端传上来的位置,角度等为了省流量,存成整形,这里处理成单精度浮点型要除以 LocationMultiply
+ ///
+ public const float LocationMultiply = 1000f;
+ }
+}
diff --git a/XNet.Business/Net/WsServer.cs b/XNet.Business/Net/WsServer.cs
index 68a6f6a..a34915e 100644
--- a/XNet.Business/Net/WsServer.cs
+++ b/XNet.Business/Net/WsServer.cs
@@ -1,5 +1,6 @@
using MessagePack;
using System.Net.WebSockets;
+using XNet.Business.PathNavigation;
using XNet.Business.Tank.Manager;
namespace XNet.Business.Net
@@ -8,11 +9,11 @@ namespace XNet.Business.Net
{
private static ActionManager? ActionManager = null;
// 启动WebSocket监听
- public static void MapWebSocketServer(this WebApplication app, WsConnectionManager wsManager)
+ public static void MapWebSocketServer(this WebApplication app, WsConnectionManager wsManager, NavMeshManager navMeshManager)
{
if (ActionManager == null)
{
- ActionManager = new ActionManager(wsManager);
+ ActionManager = new ActionManager(wsManager, navMeshManager);
}
app.Map("/ws", async context =>
{
diff --git a/XNet.Business/PathNavigation/NavMeshManager.cs b/XNet.Business/PathNavigation/NavMeshManager.cs
index 6e484b0..d30fa73 100644
--- a/XNet.Business/PathNavigation/NavMeshManager.cs
+++ b/XNet.Business/PathNavigation/NavMeshManager.cs
@@ -149,12 +149,12 @@ namespace XNet.Business.PathNavigation
/// 获取指定副本实例底层的 NavMesh 和 Query 对象
/// 注意:返回的对象是共享资源,请勿 Dispose,也请勿修改其拓扑结构
///
- public bool GetNavMeshAndQuery(string instanceId, out DtNavMesh navMesh, out DtNavMeshQuery query)
+ public bool GetNavMeshAndQuery(string roomId, out DtNavMesh navMesh, out DtNavMeshQuery query)
{
navMesh = null!;
query = null!;
- if (!_instanceMap.TryGetValue(instanceId, out var templateId)) return false;
+ if (!_instanceMap.TryGetValue(roomId, out var templateId)) return false;
if (!_templates.TryGetValue(templateId, out var template)) return false;
navMesh = template.NavMesh;
@@ -162,13 +162,24 @@ namespace XNet.Business.PathNavigation
return true;
}
+ public RcVec3f? GetClosetPoint(string roomId, Vector3 originPt)
+ {
+ if (!_instanceMap.TryGetValue(roomId, out var templateId)) return null;
+ if (!_templates.TryGetValue(templateId, out var template)) return null;
+ var query = template.Query;
+ var startPos = new RcVec3f(originPt.X, originPt.Y, originPt.Z);
+ query.FindNearestPoly(startPos, _extents, _filter, out long startRef, out var startPt, out var _);
+
+ return startPt;
+ }
+
// ==========================================
// 4. 高性能寻路
// ==========================================
- public List? FindPath(string instanceId, Vector3 start, Vector3 end)
+ public List? FindPath(string roomId, Vector3 start, Vector3 end)
{
- if (!_instanceMap.TryGetValue(instanceId, out var templateId)) return null;
+ if (!_instanceMap.TryGetValue(roomId, out var templateId)) return null;
if (!_templates.TryGetValue(templateId, out var template)) return null;
const int MAX_POLYS = 256;
diff --git a/XNet.Business/Tank/Manager/ActionManager.cs b/XNet.Business/Tank/Manager/ActionManager.cs
index 0eeca8e..669583f 100644
--- a/XNet.Business/Tank/Manager/ActionManager.cs
+++ b/XNet.Business/Tank/Manager/ActionManager.cs
@@ -1,5 +1,6 @@
using System.Collections.Concurrent;
using XNet.Business.Net;
+using XNet.Business.PathNavigation;
namespace XNet.Business.Tank.Manager
{
@@ -11,10 +12,12 @@ namespace XNet.Business.Tank.Manager
private readonly PlayerManager _playerManager;
private readonly WsConnectionManager _wsManager;
- public ActionManager(WsConnectionManager wsManager)
+ private readonly NavMeshManager _navMeshManager;
+ public ActionManager(WsConnectionManager wsManager, NavMeshManager navMeshManager)
{
- _playerManager = new PlayerManager(wsManager);
+ _navMeshManager = navMeshManager;
_wsManager = wsManager;
+ _playerManager = new PlayerManager(wsManager, navMeshManager);
Init();
}
diff --git a/XNet.Business/Tank/Manager/PlayerManager.cs b/XNet.Business/Tank/Manager/PlayerManager.cs
index fafbdf0..eaf8516 100644
--- a/XNet.Business/Tank/Manager/PlayerManager.cs
+++ b/XNet.Business/Tank/Manager/PlayerManager.cs
@@ -4,15 +4,18 @@ using NanoidDotNet;
using System.Numerics;
using XNet.Business.Entity;
using XNet.Business.Net;
+using XNet.Business.PathNavigation;
namespace XNet.Business.Tank.Manager
{
public class PlayerManager
{
private readonly WsConnectionManager _wsManager;
- public PlayerManager(WsConnectionManager wsManager)
+ private readonly NavMeshManager _navMeshManager;
+ public PlayerManager(WsConnectionManager wsManager, NavMeshManager navMeshManager)
{
_wsManager = wsManager;
+ _navMeshManager = navMeshManager;
}
public async Task SubcribeRoom(string connId, byte[] data)
@@ -239,11 +242,26 @@ namespace XNet.Business.Tank.Manager
public async Task RequestPath(string connId, byte[] data)
{
- //var playerState = _wsManager.GetConnectionInfo(connId);
- //if (playerState != null)
- //{
- // await _wsManager.SendMessageToRoomBatchAsync(playerState.FirstRoomId, data, [connId]);
- //}
+ var posReq = MessagePackSerializer.Deserialize(data);
+ if (posReq != null)
+ {
+ var playerState = _wsManager.GetConnectionInfo(connId);
+ //if (playerState != null)
+ //{
+ // await _wsManager.SendMessageToRoomBatchAsync(playerState.FirstRoomId, data, [connId]);
+ //}
+ if (playerState != null && playerState.IsCanControl && posReq.EndPos != null)
+ {
+ var room = _wsManager.GetPlayerRoomInfo(playerState.FirstRoomId, connId);
+
+ var toPt = new Vector3(posReq.EndPos.X, posReq.EndPos.Y, posReq.EndPos.Z) / Global.LocationMultiply;
+ var closetPt = _navMeshManager.GetClosetPoint(room?.RoomId!, toPt);
+ if (closetPt != null)
+ {
+ room?.Crowd?.RequestMoveTarget(playerState.Agent, 1, closetPt.Value);
+ }
+ }
+ }
await Task.CompletedTask;
}
}
diff --git a/XNet/Program.cs b/XNet/Program.cs
index ea12edf..88dd6c7 100644
--- a/XNet/Program.cs
+++ b/XNet/Program.cs
@@ -46,7 +46,7 @@ app.UseStaticFiles();
app.UseWebSockets();
// WebSocket
-app.MapWebSocketServer(app.Services.GetRequiredService());
+app.MapWebSocketServer(app.Services.GetRequiredService(), app.Services.GetRequiredService());
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())