using Rokid.MRC; using System; using System.Collections.Generic; using Unity.Netcode; using UnityEngine; //客户端玩家数据管理,不允许一个客户端登录两次,用于后续公司账号 public class PlayerManager { PlayerManager() { PlayerDataDic = new Dictionary(); m_ClientIDToPlayerId = new Dictionary(); } public static PlayerManager Instance => s_Instance ??= new PlayerManager(); static PlayerManager s_Instance; //PlayerID——SessionPlayerData public Dictionary PlayerDataDic; //ClientId——PlayerID private Dictionary m_ClientIDToPlayerId; private bool m_HasSessionStarted; //客户端断开连接 public void DisconnectClient(ulong clientId) { if(m_HasSessionStarted) { //将客户端标记为断线,但是不移除数据。便于后续重连 if(m_ClientIDToPlayerId.TryGetValue(clientId, out var playerId)) { if(GetPlayerData(playerId)?.ClientId == clientId) { var clientData = PlayerDataDic[playerId]; clientData.IsConnected = false; PlayerDataDic[playerId] = clientData; } } } else { //未初始化管理器。移除数据(无需保存数据) if(m_ClientIDToPlayerId.TryGetValue(clientId, out var playerId)) { m_ClientIDToPlayerId.Remove(clientId); PlayerData data = GetPlayerData(playerId); if(data != null) { if(data.IsVideoClient) { CameraController.Instance.ShutDownComposition(); } if(data.ClientId == clientId) { PlayerDataDic.Remove(playerId); } } } } } //该客户端是否已连接 public bool IsDuplicateConnection(string playerId) { return PlayerDataDic.ContainsKey(playerId) && PlayerDataDic[playerId].IsConnected; } //关键方法,当客户端连接(重连)到服务端,则保存(更新)客户端数据。playerId是客户端生成并发送到服务端的Guid public void SetupConnectingPlayerSessionData(ulong clientId, string playerId, PlayerData sessionPlayerData) { var isReconnecting = false; //判断是否同一客户端 if(IsDuplicateConnection(playerId)) { Debug.LogError($"Player ID {playerId} already exists. This is a duplicate connection. Rejecting this session data."); return; } //判断是否重连 if(PlayerDataDic.ContainsKey(playerId)) { if(!PlayerDataDic[playerId].IsConnected) { isReconnecting = true; } } //重连,则更新客户端数据 if(isReconnecting) { sessionPlayerData = PlayerDataDic[playerId]; sessionPlayerData.ClientId = clientId; sessionPlayerData.IsConnected = true; } //缓存数据 m_ClientIDToPlayerId[clientId] = playerId; PlayerDataDic[playerId] = sessionPlayerData; } //根据ClientId,获取PlayerId public string GetPlayerId(ulong clientId) { if(m_ClientIDToPlayerId.TryGetValue(clientId, out string playerId)) { return playerId; } Debug.Log($"No client player ID found mapped to the given client ID: {clientId}"); return null; } //根据ClientId获取客户端数据SessionPlayerData public PlayerData GetPlayerData(ulong clientId) { var playerId = GetPlayerId(clientId); if(playerId != null) { return GetPlayerData(playerId); } Debug.Log($"No client player ID found mapped to the given client ID: {clientId}"); return null; } public PlayerData GetPlayerData(string playerId) { if(PlayerDataDic.TryGetValue(playerId, out PlayerData data)) { return data; } Debug.Log($"No PlayerData of matching player ID found: {playerId}"); return null; } public PlayerData GetConnectedPlayerData() { foreach(var playerData in PlayerDataDic.Values) { if(playerData.IsConnected && playerData.ClientId != NetworkManager.Singleton.LocalClientId) { return playerData; } } return null; } //更新某个ClientId的客户端数据SessionPlayerData public void SetPlayerData(ulong clientId, PlayerData sessionPlayerData) { if(m_ClientIDToPlayerId.TryGetValue(clientId, out string playerId)) { PlayerDataDic[playerId] = sessionPlayerData; } else { Debug.LogError($"No client player ID found mapped to the given client ID: {clientId}"); } } //断开所有客户端 public void CloseAllClient() { foreach(var playerData in PlayerDataDic.Values) { NetworkManager.Singleton?.DisconnectClient(playerData.ClientId); } OnServerEnded(); } //标记管理器已经启动。可以缓存已断开连接的客户端数据 public void OnSessionStarted() { m_HasSessionStarted = true; } //重新初始化已连接的客户端。清空所有断开的客户端数据(下次连上,则标识为新客户端) public void OnSessionEnded() { ClearDisconnectedPlayersData(); ReinitializePlayersData(); m_HasSessionStarted = false; } //服务端关闭,清空所有数据 public void OnServerEnded() { PlayerDataDic.Clear(); m_ClientIDToPlayerId.Clear(); m_HasSessionStarted = false; } //重新初始化已连接的客户端。调用每个客户端的SessionPlayerData.Reinitialize方法 void ReinitializePlayersData() { foreach(var id in m_ClientIDToPlayerId.Keys) { string playerId = m_ClientIDToPlayerId[id]; PlayerData sessionPlayerData = PlayerDataDic[playerId]; sessionPlayerData.Reinitialize(); PlayerDataDic[playerId] = sessionPlayerData; } } //清空所有断开的客户端数据 void ClearDisconnectedPlayersData() { //收集所有断开连接的客户端 List idsToClear = new List(); foreach(var id in m_ClientIDToPlayerId.Keys) { var data = GetPlayerData(id); if(data is { IsConnected: false }) { idsToClear.Add(id); } } //移除数据 foreach(var id in idsToClear) { string playerId = m_ClientIDToPlayerId[id]; if(GetPlayerData(playerId)?.ClientId == id) { PlayerDataDic.Remove(playerId); } m_ClientIDToPlayerId.Remove(id); } } public bool HaveAnchorPlayer() { foreach(var client in PlayerDataDic) { PlayerData playerData = client.Value; if(playerData.IsConnected && playerData.Anchor != null) { return true; } } return false; } public bool HaveVideoPlayer() { foreach(var client in PlayerDataDic) { PlayerData playerData = client.Value; if(playerData.IsConnected && playerData.IsVideoClient) { return true; } } return false; } public PlayerData GetVideoPlayer() { foreach(var client in PlayerDataDic) { PlayerData playerData = client.Value; if(playerData.IsConnected && playerData.IsVideoClient) { return playerData; } } return null; } public bool HavePlayer() { foreach(var client in PlayerDataDic) { PlayerData playerData = client.Value; if(playerData.IsConnected && playerData.ClientId != 0) { return true; } } return false; } }