This commit is contained in:
wuyanchen 2025-12-30 17:55:08 +08:00
parent 4824e84575
commit 01c68cc0b4
9 changed files with 80 additions and 21 deletions

View File

@ -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
{

View File

@ -50,10 +50,5 @@ namespace XNet.Business.Entity
/// 当前线性插值欧拉角,角色朝向
/// </summary>
public Vec3 CurrentEuler { get; set; } = new Vec3();
/// <summary>
/// 路径导航索引下标
/// </summary>
public int AgentIndex { get; set; } = 0;
}
}

View File

@ -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;
/// <summary>
/// 路径导航索引
/// </summary>
public DtCrowdAgent Agent { get; set; } = null!;
}
}

10
XNet.Business/Global.cs Normal file
View File

@ -0,0 +1,10 @@
namespace XNet.Business
{
public class Global
{
/// <summary>
/// 客户端传上来的位置,角度等为了省流量,存成整形,这里处理成单精度浮点型要除以 LocationMultiply
/// </summary>
public const float LocationMultiply = 1000f;
}
}

View File

@ -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 =>
{

View File

@ -149,12 +149,12 @@ namespace XNet.Business.PathNavigation
/// 获取指定副本实例底层的 NavMesh 和 Query 对象
/// 注意:返回的对象是共享资源,请勿 Dispose也请勿修改其拓扑结构
/// </summary>
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<Vector3>? FindPath(string instanceId, Vector3 start, Vector3 end)
public List<Vector3>? 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;

View File

@ -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();
}

View File

@ -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<PlayerPosReq>(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;
}
}

View File

@ -46,7 +46,7 @@ app.UseStaticFiles();
app.UseWebSockets();
// 启动WebSocket服务
app.MapWebSocketServer(app.Services.GetRequiredService<WsConnectionManager>());
app.MapWebSocketServer(app.Services.GetRequiredService<WsConnectionManager>(), app.Services.GetRequiredService<NavMeshManager>());
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())