713 lines
30 KiB
C#
713 lines
30 KiB
C#
using MessagePack;
|
||
using Microsoft.AspNetCore.DataProtection.KeyManagement;
|
||
using NanoidDotNet;
|
||
using System.Numerics;
|
||
using System.Threading.Tasks;
|
||
using XNet.Business.Dto;
|
||
using XNet.Business.Entity;
|
||
using XNet.Business.Net;
|
||
using XNet.Business.PathNavigation;
|
||
|
||
namespace XNet.Business.Tank.Manager
|
||
{
|
||
public class PlayerManager
|
||
{
|
||
private readonly WsConnectionManager _wsManager;
|
||
private readonly NavMeshManager _navMeshManager;
|
||
private readonly SceneAgent _sceneAgent;
|
||
private readonly List<string> RoleColor = new List<string>();
|
||
public PlayerManager(WsConnectionManager wsManager, NavMeshManager navMeshManager, SceneAgent sceneAgent)
|
||
{
|
||
_wsManager = wsManager;
|
||
_navMeshManager = navMeshManager;
|
||
_sceneAgent = sceneAgent;
|
||
RoleColor.AddRange(["#8CE929", "#FFBF5F", "#FFF45F", "#FF5F5F", "#5FECFF", "#EF5FFF",
|
||
"#497352","#736049","#6B7349","#734949","#495F73","#734972"]);
|
||
}
|
||
|
||
public async Task SubcribeRoom(string connId, byte[] data)
|
||
{
|
||
// 处理订阅实例请求
|
||
var subscribeReq = MessagePackSerializer.Deserialize<SubscribeRoom>(data);
|
||
if (subscribeReq != null)
|
||
{
|
||
//roomId为空时,新创建一个唯一房间ID
|
||
if (string.IsNullOrWhiteSpace(subscribeReq.RoomId))
|
||
{
|
||
subscribeReq.RoomId = Nanoid.Generate();
|
||
}
|
||
await _wsManager.SendSerializeMessageToPointWsSocket(connId,
|
||
new BaseRoomMsg<string>
|
||
{
|
||
Type = WsMsgType.SUBSCRIBE_ROOM,
|
||
RoomId = subscribeReq.RoomId,
|
||
SenderId = connId,
|
||
Data = string.Empty
|
||
}
|
||
);
|
||
}
|
||
}
|
||
|
||
public async Task ChangeRoomKey(string connId, byte[] data)
|
||
{
|
||
// 处理订阅实例请求
|
||
var changeRoomReq = MessagePackSerializer.Deserialize<SubscribeInstanceReq>(data);
|
||
if (changeRoomReq != null && !string.IsNullOrWhiteSpace(changeRoomReq.RoomId))
|
||
{
|
||
string createRoomId = changeRoomReq.RoomId;
|
||
await _wsManager.SubscribeInstance(connId, changeRoomReq.MapKey, false, createRoomId, true);//Map_Forest Test
|
||
}
|
||
}
|
||
|
||
public async Task LockTarget(string connId, byte[] data)
|
||
{
|
||
var playerInfo = _wsManager.GetConnectionInfo(connId);
|
||
if (playerInfo == null) return;
|
||
|
||
// 处理锁定实例请求
|
||
var lockReq = MessagePackSerializer.Deserialize<LockTargetReq>(data);
|
||
await _wsManager.SendMessageToRoomBatchAsync(playerInfo.FirstRoomId, playerInfo.PlayerId, WsMsgType.ROOM_MSG, lockReq);
|
||
}
|
||
|
||
public async Task CreateOrJoinRoom(string connId, byte[] data)
|
||
{
|
||
var playerInfo = _wsManager.GetConnectionInfo(connId);
|
||
if (playerInfo == null) return;
|
||
|
||
// 处理订阅实例请求
|
||
var roomReq = MessagePackSerializer.Deserialize<CreateOrJoinRoomReq>(data);
|
||
if (roomReq != null)
|
||
{
|
||
//roomId为空时,新创建一个唯一房间ID
|
||
if (string.IsNullOrWhiteSpace(roomReq.RoomId))
|
||
{
|
||
roomReq.RoomId = Nanoid.Generate();
|
||
}
|
||
string createRoomId = roomReq.RoomId;
|
||
createRoomId = (await _wsManager.SubscribeInstance(connId, roomReq.MapKey, true, createRoomId, false))!;//Map_Forest Test
|
||
if (playerInfo != null)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(playerInfo.PlayerId))
|
||
{
|
||
playerInfo.PlayerId = connId;// string.IsNullOrWhiteSpace(roomReq.PlayerId) ? connId : roomReq.PlayerId;
|
||
playerInfo.IsAI = false;
|
||
}
|
||
playerInfo.HeadImageUrl = roomReq.HeadImageUrl;
|
||
playerInfo.NickName = roomReq.NickName;
|
||
}
|
||
|
||
var room = _wsManager.GetPlayerRoomInfo(roomReq.RoomId, connId);
|
||
if (room != null)
|
||
{
|
||
room.RoomName = roomReq.RoomName;
|
||
InitSets(room, connId, roomReq.AICount);
|
||
|
||
await _wsManager.SendBaseSingleMessage(connId, WsMsgType.PRIVATGE,
|
||
new EnterRoomReply
|
||
{
|
||
Type = WsMsgType.CHANGE_ROOM_KEY_NAME,
|
||
MapKey = room.MapKey
|
||
}
|
||
);
|
||
|
||
ControlPlayer? self = _wsManager.GetConnectionInfo(connId);
|
||
await _wsManager.SendMessageToRoomBatchAsync(room.RoomId, connId, WsMsgType.PRIVATGE, new RoomUserSync
|
||
{
|
||
Type = WsMsgType.CREATE_OR_JOIN_ROOM,
|
||
RoomId = room.RoomId,
|
||
PlayerId = connId,
|
||
HeadImageUrl = self?.HeadImageUrl,
|
||
SetIdx = self?.SetIdx ?? 0,
|
||
IsPublic = room.IsPublic
|
||
});
|
||
|
||
if (_wsManager.InstanceSubscribers.TryGetValue(room.RoomId, out var roomUsers))
|
||
{
|
||
foreach (var userKv in roomUsers)
|
||
{
|
||
var other = _wsManager.GetConnectionInfo(userKv.Key);
|
||
if (other != null && other.PlayerId != connId)
|
||
{
|
||
await _wsManager.SendBaseSingleMessage(connId, WsMsgType.PRIVATGE,
|
||
new RoomUserSync
|
||
{
|
||
Type = WsMsgType.CREATE_OR_JOIN_ROOM,
|
||
RoomId = room.RoomId,
|
||
PlayerId = connId,
|
||
NickName = other.NickName,
|
||
HeadImageUrl = other.HeadImageUrl,
|
||
SetIdx = other.SetIdx,
|
||
IsPublic = room.IsPublic
|
||
}
|
||
);
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
private void InitSets(PlayerRoomInfo<ControlPlayer> room, string connId, int aiCount)
|
||
{
|
||
ControlPlayer self = _wsManager.GetConnectionInfo(connId)!;
|
||
// 初始化座位数组,长度为房间最大人数,默认填充null
|
||
List<RoomSet?> sets = new List<RoomSet?>();
|
||
for (int i = 0; i < room.MaxPlayerCount; i++)
|
||
{
|
||
sets.Add(null);
|
||
}
|
||
|
||
// 初始化座位索引为-1(无可用座位)
|
||
int setIdx = -1;
|
||
|
||
// 如果已有座位数据,遍历填充座位数组并重新分配索引
|
||
if (room.Sets.Count > 0)
|
||
{
|
||
int tmpIndex = 0;
|
||
// 遍历所有已存在的座位键值对 (对应TS: state.sets.forEach)
|
||
foreach (var kvp in room.Sets)
|
||
{
|
||
string key = kvp.Key;
|
||
RoomSet set = kvp.Value;
|
||
|
||
// 从玩家集合中获取当前玩家 (对应TS: state.players.get(key))
|
||
ControlPlayer? playerItem = _wsManager.GetConnectionInfo(key);
|
||
|
||
if (playerItem == null)
|
||
{
|
||
sets[tmpIndex] = null;
|
||
}
|
||
else
|
||
{
|
||
sets[tmpIndex] = set;
|
||
playerItem.SetIdx = (byte)tmpIndex; // uint8对应byte,强转
|
||
}
|
||
tmpIndex++;
|
||
}
|
||
|
||
// 查找第一个空座位 或 当前客户端sessionId对应的座位 (对应TS: sets.findIndex)
|
||
setIdx = sets.FindIndex(s => s == null || s.PlayerId == connId);
|
||
}
|
||
else
|
||
{
|
||
// 没有任何座位数据,默认分配第0个座位
|
||
setIdx = 0;
|
||
}
|
||
|
||
// 如果获取到有效座位索引
|
||
if (setIdx != -1)
|
||
{
|
||
// 第一个进房间的玩家,将房主标识置空 (对应TS逻辑)
|
||
if (setIdx == 0)
|
||
{
|
||
room.Host = null;
|
||
}
|
||
|
||
// 给当前玩家赋值座位索引
|
||
self.SetIdx = (byte)setIdx;
|
||
|
||
// 更新/新增座位数据到状态集合中
|
||
if (room.Sets.ContainsKey(connId))
|
||
{
|
||
// 已存在该玩家的座位,更新信息
|
||
RoomSet roomSet = room.Sets[connId];
|
||
roomSet.PlayerId = connId;
|
||
roomSet.SetIdx = (byte)setIdx;
|
||
}
|
||
else
|
||
{
|
||
// 不存在则新建座位对象,添加到集合
|
||
RoomSet roomSet = new RoomSet();
|
||
roomSet.PlayerId = connId;
|
||
roomSet.SetIdx = (byte)setIdx;
|
||
room.Sets.Add(connId, roomSet);
|
||
}
|
||
}
|
||
|
||
// AI数量初始化逻辑:消息中存在aiCount 且 未初始化过AI数量,赋值
|
||
if (aiCount > 0 && room.AIPlayerCount == 0)
|
||
{
|
||
room.AIPlayerCount = aiCount;
|
||
}
|
||
}
|
||
|
||
|
||
public async Task SendMessageToRoomOthers(string connId, byte[] data)
|
||
{
|
||
var playerState = _wsManager.GetConnectionInfo(connId);
|
||
if (playerState != null)
|
||
{
|
||
await _wsManager.SendMessageToRoomBatchAsync(playerState.FirstRoomId, data, [connId]);
|
||
}
|
||
}
|
||
public async Task SendMessageToRoom(string connId, byte[] data)
|
||
{
|
||
var playerState = _wsManager.GetConnectionInfo(connId);
|
||
if (playerState != null)
|
||
{
|
||
await _wsManager.SendMessageToRoomBatchAsync(playerState.FirstRoomId, data);
|
||
}
|
||
}
|
||
public async Task SendMessageToSelf(string connId, byte[] data)
|
||
{
|
||
var playerState = _wsManager.GetConnectionInfo(connId);
|
||
if (playerState != null)
|
||
{
|
||
await _wsManager.SendBaseSingleMessage(connId, WsMsgType.TO_SELF, data);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
public async Task RequestPath(string connId, byte[] data)
|
||
{
|
||
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);
|
||
|
||
if (room != null)
|
||
{
|
||
//客户端传上来的位置,角度等为了省流量,存成整形,这里处理成单精度浮点型要除以 LocationMultiply,默认除以1000
|
||
var toPt = new Vector3(posReq.EndPos.X, posReq.EndPos.Y, posReq.EndPos.Z) / Global.LocationMultiply;
|
||
var closetPt = _navMeshManager.GetClosetPoint(room.RoomId!, toPt,out long startRef);
|
||
if (closetPt != null)
|
||
{
|
||
room.Crowd?.RequestMoveTarget(playerState.Agent, startRef, closetPt.Value);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
await Task.CompletedTask;
|
||
}
|
||
|
||
public async Task RequestInit(string connId, byte[] data)
|
||
{
|
||
// 处理订阅实例请求
|
||
var message = MessagePackSerializer.Deserialize<PlayerInitReq>(data);
|
||
if (message != null)
|
||
{
|
||
var player = _wsManager.GetConnectionInfo(connId);
|
||
if (player == null) return;
|
||
|
||
var room = _wsManager.GetPlayerRoomInfo(player.FirstRoomId, connId);
|
||
if (room != null)
|
||
{
|
||
if (room.EndTime == null)
|
||
{
|
||
room.EndTime = DateTime.Now.AddMilliseconds(PlayerRoomInfo<ControlPlayer>.GameMillisecond);
|
||
}
|
||
if (room.WillEndTime == null)
|
||
{
|
||
room.WillEndTime = DateTime.Now.AddMilliseconds(PlayerRoomInfo<ControlPlayer>.GameMillisecond - PlayerRoomInfo<ControlPlayer>.GameWillEndMillisecond);
|
||
}
|
||
if (room.StartGameTime == null)
|
||
{
|
||
room.StartGameTime = DateTime.Now;
|
||
}
|
||
|
||
if (message.IsAI)
|
||
{
|
||
message.PlayerId = Nanoid.Generate();
|
||
}
|
||
else
|
||
{
|
||
message.PlayerId = player.PlayerId;
|
||
}
|
||
|
||
await RequestInitPlayer(room!, room?.MapKey!, player, message);
|
||
|
||
//可以移动了
|
||
await SetPlayerIsCanControl(room?.RoomId!, player, true, null);
|
||
|
||
//开始无敌
|
||
SetPlayerIsCanHit(connId, false);
|
||
|
||
_ = Task.Delay(5000).ContinueWith((t) =>
|
||
{
|
||
//5秒后会收到伤害
|
||
SetPlayerIsCanHit(connId, true);
|
||
});
|
||
|
||
|
||
var pos = player.CurrentPos * Global.LocationMultiply;
|
||
var convertPos = new Vec3((int)pos.X, (int)pos.Y, (int)pos.Z);
|
||
|
||
var euler = player.CurrentEuler * Global.LocationMultiply;
|
||
var convertEuler = new Vec3((int)euler.X, (int)euler.Y, (int)euler.Z);
|
||
|
||
await _wsManager.SendBaseSingleMessage(connId, WsMsgType.PRIVATGE, new RequestInitMsg
|
||
{
|
||
Type = WsMsgType.REQUEST_INIT,
|
||
PlayerId = player.PlayerId,
|
||
Pos = convertPos,
|
||
Euler = convertEuler,
|
||
IsAI = message.IsAI,
|
||
GameTime = (long)(PlayerRoomInfo<ControlPlayer>.GameMillisecond - (DateTime.Now - room!.StartGameTime.Value).TotalMilliseconds)
|
||
});
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
|
||
public async Task Login(string connId, byte[] data)
|
||
{
|
||
var loginReq = MessagePackSerializer.Deserialize<PlayerLoginReq>(data);
|
||
if (loginReq != null)
|
||
{
|
||
var player = _wsManager.GetConnectionInfo(connId);
|
||
if (player != null)
|
||
{
|
||
//await _wsManager.RemoveConnection(connId);
|
||
player.NickName = loginReq.NickName;
|
||
player.HeadImageUrl = loginReq.HeadImageUrl;
|
||
player.DeviceColor = loginReq.DeviceColor;
|
||
player.IsAI = false;
|
||
|
||
var room = _wsManager.GetPlayerRoomInfo(player.FirstRoomId, connId);
|
||
|
||
if (room != null)
|
||
{
|
||
player.PlayerId = connId;
|
||
player.IsAI = false;
|
||
|
||
room.Players[connId] = player;
|
||
if (room.Players.Count == 1)
|
||
{
|
||
room.Host = null;
|
||
}
|
||
float blood = await CheckLoginAndCreateHostAI(connId, room, loginReq.MapKey, loginReq);
|
||
|
||
await _wsManager.SendBaseSingleMessage(connId, WsMsgType.PRIVATGE, new LoginResultMsg
|
||
{
|
||
Type = WsMsgType.LOGIN,
|
||
PlayerId = player.PlayerId,
|
||
Result = LoginResult.Success,
|
||
Blood = player.Blood,
|
||
DeviceColor = player.DeviceColor
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public void SetPlayerIsCanHit(string connId, bool isCanHit)
|
||
{
|
||
var player = _wsManager.GetConnectionInfo(connId);
|
||
if (player != null)
|
||
{
|
||
player.IsCanHit = isCanHit;
|
||
}
|
||
}
|
||
|
||
public bool GetPlayerIsCanHit(string connId)
|
||
{
|
||
var player = _wsManager.GetConnectionInfo(connId);
|
||
if (player != null)
|
||
{
|
||
return player.IsCanHit;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
|
||
private async Task<float> CheckLoginAndCreateHostAI(string connId, PlayerRoomInfo<ControlPlayer> room, string mapKey, PlayerLoginReq loginReq)
|
||
{
|
||
bool isFirstPlayer = room.Host == null;
|
||
bool hasAI = room.Players.Any(p => p.Value.IsAI);
|
||
if (isFirstPlayer)
|
||
{
|
||
if (room.Players.TryGetValue(connId, out var loginClient))
|
||
{
|
||
room.Host = loginClient;
|
||
loginClient.BirthPositions.Clear();
|
||
if (loginReq.BirthPositions != null)
|
||
{
|
||
for (int i = 0; i < loginReq.BirthPositions.Length; i++)
|
||
{
|
||
loginClient.BirthPositions.Add(loginReq.BirthPositions[i]);
|
||
}
|
||
}
|
||
if (!hasAI && loginReq.HasAI)
|
||
{
|
||
var deviceInfo = DeviceManager.Instance.DeviceInfo;
|
||
for (int i = 0; i < Global.AICount; i++)
|
||
{
|
||
int bodyIdx = new Random().Next(0, Global.MaxPartKindCount);
|
||
int weaponIdx = new Random().Next(0, Global.MaxPartKindCount);
|
||
int armorIdx = new Random().Next(0, Global.MaxPartKindCount);
|
||
int chassisIdx = new Random().Next(0, Global.MaxPartKindCount);
|
||
var startPos = loginClient.BirthPositions[new Random().Next(0, loginClient.BirthPositions.Count)];
|
||
var message = new PlayerInitReq
|
||
{
|
||
IsAI = true,
|
||
PlayerId = Nanoid.Generate(),
|
||
BodyIdx = bodyIdx,
|
||
WeaponIdx = weaponIdx,
|
||
ArmorIdx = armorIdx,
|
||
ChassisIdx = chassisIdx,
|
||
DeviceColor = RoleColor[new Random().Next(0, RoleColor.Count)],
|
||
FindFaceDistance = deviceInfo.Weapon[weaponIdx].FindFaceDistance,
|
||
AttackPower = deviceInfo.Weapon[weaponIdx].AttackPower,
|
||
Armor = deviceInfo.Armor[armorIdx].Armor,
|
||
Speed = deviceInfo.Chassis[chassisIdx].Speed,
|
||
Radius = loginReq.Radius,
|
||
StartPos = startPos,
|
||
Euler = new Vec3(0, 0, 0)
|
||
//CurrentEuler = new Dto.Vec3(),
|
||
//NickName = loginReq.NickName,
|
||
};
|
||
|
||
var aiPlayer = new ControlPlayer
|
||
{
|
||
PlayerId = message.PlayerId,
|
||
IsAI = true,
|
||
IsEnterMap = false
|
||
};
|
||
|
||
await this.RequestInitPlayer(room, mapKey, aiPlayer, message);
|
||
|
||
//可以移动了
|
||
await SetPlayerIsCanControl(room.RoomId, aiPlayer, true, null);
|
||
|
||
//开始无敌
|
||
SetPlayerIsCanHit(connId, false);
|
||
|
||
_ = Task.Delay(5000).ContinueWith((t) =>
|
||
{
|
||
//5秒后会收到伤害
|
||
SetPlayerIsCanHit(connId, true);
|
||
});
|
||
|
||
}
|
||
}
|
||
return loginClient.MaxBlood;
|
||
}
|
||
}
|
||
return 0f;
|
||
}
|
||
|
||
private async Task RequestInitPlayer(PlayerRoomInfo<ControlPlayer> room, string mapKey, ControlPlayer loginPlayer, PlayerInitReq message)
|
||
{
|
||
if (loginPlayer == null || loginPlayer.IsEnterMap)
|
||
{
|
||
return;
|
||
}
|
||
|
||
loginPlayer.IsAI = message.IsAI;
|
||
loginPlayer.PlayerId = message.PlayerId;
|
||
loginPlayer.NickName = message.NickName;
|
||
|
||
var deviceInfo = DeviceManager.Instance.DeviceInfo;
|
||
|
||
var armorInfo = deviceInfo.Armor[message.ArmorIdx];
|
||
var weaponInfo = deviceInfo.Weapon[message.WeaponIdx];
|
||
var chassisInfo = deviceInfo.Chassis[message.ChassisIdx];
|
||
|
||
loginPlayer.MaxBlood = armorInfo.Blood;
|
||
loginPlayer.Blood = armorInfo.Blood;
|
||
|
||
loginPlayer.BodyIdx = message.BodyIdx;
|
||
loginPlayer.WeaponIdx = message.WeaponIdx;
|
||
loginPlayer.ArmorIdx = message.ArmorIdx;
|
||
loginPlayer.ChassisIdx = message.ChassisIdx;
|
||
|
||
loginPlayer.FindFaceDistance = weaponInfo.FindFaceDistance;
|
||
loginPlayer.AttackPower = weaponInfo.AttackPower;
|
||
loginPlayer.Armor = armorInfo.Armor;
|
||
loginPlayer.Speed = chassisInfo.Speed;
|
||
loginPlayer.Radius = message.Radius;
|
||
loginPlayer.DeviceColor = message.DeviceColor;
|
||
|
||
loginPlayer.CurrentPos = new Vector3(message.StartPos!.X, message.StartPos.Y, message.StartPos.Z)!;
|
||
loginPlayer.CurrentEuler = new Vector3(message.Euler!.X, message.Euler.Y, message.Euler.Z)!;
|
||
|
||
float speedScale = 1f;
|
||
if (loginPlayer.IsAI)
|
||
{
|
||
speedScale = 0.5f;//AI速度减为一半
|
||
loginPlayer.Skill1Level = (byte)new Random().Next(1, 4);
|
||
loginPlayer.Skill2Level = (byte)new Random().Next(1, 4);
|
||
loginPlayer.Skill3Level = (byte)new Random().Next(1, 4);
|
||
loginPlayer.Skill4Level = (byte)new Random().Next(1, 4);
|
||
}
|
||
|
||
var startPos = _navMeshManager.GetClosetPoint(room.RoomId, loginPlayer.CurrentPos / 1000, out long startRef);
|
||
if (startPos != null)
|
||
{
|
||
loginPlayer.CurrentPos = startPos.Value;
|
||
loginPlayer.Agent = _sceneAgent.AddAgent(room.RoomId, loginPlayer.CurrentPos, loginPlayer.Radius, loginPlayer.Radius, loginPlayer.PlayerId, loginPlayer.Speed * speedScale * 2, loginPlayer.Speed * speedScale);
|
||
}
|
||
|
||
loginPlayer.TmpPos = loginPlayer.CurrentPos;
|
||
_sceneAgent.AgentTeleport(room.RoomId, loginPlayer.Agent.idx, loginPlayer.CurrentPos);
|
||
|
||
loginPlayer.IsEnterMap = true;
|
||
if (!loginPlayer.IsAI)
|
||
{
|
||
//同步其他玩家的信息给自己
|
||
await SyncOtherPlayerInfoToSelf(room.RoomId, loginPlayer);
|
||
|
||
//向其他玩家发送自己的信息
|
||
await SyncSelfInfoToOtherPlayer(room.RoomId, loginPlayer);
|
||
|
||
//同步AI信息给登录玩家
|
||
await SyncAIToOthersPlayer(room.RoomId, loginPlayer);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 同步其他玩家的信息给自己
|
||
/// </summary>
|
||
/// <param name="roomId"></param>
|
||
/// <param name="client"></param>
|
||
private async Task SyncOtherPlayerInfoToSelf(string roomId, ControlPlayer client)
|
||
{
|
||
var room = _wsManager.GetPlayerRoomInfo(roomId, client.PlayerId);
|
||
if (room != null)
|
||
{
|
||
foreach (var playerKv in room.Players)
|
||
{
|
||
var player = playerKv.Value;
|
||
if (!player.IsAI && player.IsEnterMap && player.PlayerId != client.PlayerId)
|
||
{
|
||
var pos = player.CurrentPos * Global.LocationMultiply;
|
||
var convertPos = new Vec3((int)pos.X, (int)pos.Y, (int)pos.Z);
|
||
|
||
var euler = player.CurrentEuler * Global.LocationMultiply;
|
||
var convertEuler = new Vec3((int)euler.X, (int)euler.Y, (int)euler.Z);
|
||
|
||
await _wsManager.SendBaseSingleMessage(client.PlayerId, WsMsgType.PRIVATGE, new PlayerInitSync
|
||
{
|
||
Type = WsMsgType.ADD_OR_UPDATE_PLAYER,
|
||
PlayerId = player.PlayerId,
|
||
IsAI = player.IsAI,
|
||
NickName = player.NickName,
|
||
Blood = player.MaxBlood,
|
||
BodyIdx = player.BodyIdx,
|
||
ArmorIdx = player.ArmorIdx,
|
||
ChassisIdx = player.ChassisIdx,
|
||
DeviceColor = player.DeviceColor,
|
||
HeadImageUrl = player.HeadImageUrl,
|
||
Position = convertPos,
|
||
EulerAngles = convertEuler,
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// //向其他玩家发送自己的信息
|
||
/// </summary>
|
||
/// <param name="roomId"></param>
|
||
/// <param name="client"></param>
|
||
private async Task SyncSelfInfoToOtherPlayer(string roomId, ControlPlayer client)
|
||
{
|
||
var room = _wsManager.GetPlayerRoomInfo(roomId, client.PlayerId);
|
||
if (room != null)
|
||
{
|
||
foreach (var playerKv in room.Players)
|
||
{
|
||
var player = playerKv.Value;
|
||
if (!player.IsAI && player.IsEnterMap && player.PlayerId != client.PlayerId)
|
||
{
|
||
var pos = client.CurrentPos * Global.LocationMultiply;
|
||
var convertPos = new Vec3((int)pos.X, (int)pos.Y, (int)pos.Z);
|
||
|
||
var euler = client.CurrentEuler * Global.LocationMultiply;
|
||
var convertEuler = new Vec3((int)euler.X, (int)euler.Y, (int)euler.Z);
|
||
|
||
await _wsManager.SendBaseSingleMessage(player.PlayerId, WsMsgType.PRIVATGE, new PlayerInitSync
|
||
{
|
||
Type = WsMsgType.ADD_OR_UPDATE_PLAYER,
|
||
PlayerId = client.PlayerId,
|
||
IsAI = false,
|
||
NickName = client.NickName,
|
||
Blood = client.MaxBlood,
|
||
BodyIdx = client.BodyIdx,
|
||
ArmorIdx = client.ArmorIdx,
|
||
ChassisIdx = client.ChassisIdx,
|
||
DeviceColor = client.DeviceColor,
|
||
HeadImageUrl = client.HeadImageUrl,
|
||
Position = convertPos,
|
||
EulerAngles = convertEuler,
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 同步AI给登录玩家
|
||
/// </summary>
|
||
/// <param name="roomId"></param>
|
||
/// <param name="client"></param>
|
||
private async Task SyncAIToOthersPlayer(string roomId, ControlPlayer client)
|
||
{
|
||
var room = _wsManager.GetPlayerRoomInfo(roomId, client.PlayerId);
|
||
if (room != null)
|
||
{
|
||
foreach (var playerKv in room.Players)
|
||
{
|
||
var player = playerKv.Value;
|
||
if (player.IsAI && player.IsEnterMap)
|
||
{
|
||
var pos = client.CurrentPos * Global.LocationMultiply;
|
||
var convertPos = new Vec3((int)pos.X, (int)pos.Y, (int)pos.Z);
|
||
|
||
var euler = client.CurrentEuler * Global.LocationMultiply;
|
||
var convertEuler = new Vec3((int)euler.X, (int)euler.Y, (int)euler.Z);
|
||
|
||
await _wsManager.SendBaseSingleMessage(player.PlayerId, WsMsgType.PRIVATGE, new PlayerInitSync
|
||
{
|
||
Type = WsMsgType.ADD_OR_UPDATE_PLAYER,
|
||
PlayerId = client.PlayerId,
|
||
IsAI = false,
|
||
NickName = client.NickName,
|
||
Blood = client.MaxBlood,
|
||
BodyIdx = client.BodyIdx,
|
||
ArmorIdx = client.ArmorIdx,
|
||
ChassisIdx = client.ChassisIdx,
|
||
DeviceColor = client.DeviceColor,
|
||
HeadImageUrl = client.HeadImageUrl,
|
||
Position = convertPos,
|
||
EulerAngles = convertEuler,
|
||
});
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public async Task SetPlayerIsCanControl(string roomId, ControlPlayer client, bool isCanControl, PlayerLocationSyncReq? locationSyncReq)
|
||
{
|
||
client.IsCanControl = true;
|
||
if (locationSyncReq != null)
|
||
{
|
||
var pos = locationSyncReq.Pos;
|
||
var convertPos = new Vector3((int)(pos!.X / Global.LocationMultiply), (int)(pos.Y / Global.LocationMultiply), (int)(pos.Z / Global.LocationMultiply));
|
||
|
||
var euler = client.CurrentEuler * Global.LocationMultiply;
|
||
var convertEuler = new Vector3((int)(euler!.X / Global.LocationMultiply), (int)(euler.Y / Global.LocationMultiply), (int)(euler.Z / Global.LocationMultiply));
|
||
|
||
var closetPos = _navMeshManager.GetClosetPoint(roomId, convertPos, out long startRef);
|
||
if (closetPos != null)
|
||
{
|
||
_sceneAgent.AgentTeleport(roomId, client.Agent.idx, closetPos.Value);
|
||
}
|
||
client.CurrentEuler = convertEuler;
|
||
}
|
||
}
|
||
}
|
||
}
|