PlayerManager.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. using Rokid.MRC;
  2. using System;
  3. using System.Collections.Generic;
  4. using Unity.Netcode;
  5. using UnityEngine;
  6. //客户端玩家数据管理,不允许一个客户端登录两次,用于后续公司账号
  7. public class PlayerManager
  8. {
  9. PlayerManager()
  10. {
  11. PlayerDataDic = new Dictionary<string, PlayerData>();
  12. m_ClientIDToPlayerId = new Dictionary<ulong, string>();
  13. }
  14. public static PlayerManager Instance => s_Instance ??= new PlayerManager();
  15. static PlayerManager s_Instance;
  16. //PlayerID——SessionPlayerData
  17. public Dictionary<string, PlayerData> PlayerDataDic;
  18. //ClientId——PlayerID
  19. private Dictionary<ulong, string> m_ClientIDToPlayerId;
  20. private bool m_HasSessionStarted;
  21. //客户端断开连接
  22. public void DisconnectClient(ulong clientId)
  23. {
  24. if(m_HasSessionStarted)
  25. {
  26. //将客户端标记为断线,但是不移除数据。便于后续重连
  27. if(m_ClientIDToPlayerId.TryGetValue(clientId, out var playerId))
  28. {
  29. if(GetPlayerData(playerId)?.ClientId == clientId)
  30. {
  31. var clientData = PlayerDataDic[playerId];
  32. clientData.IsConnected = false;
  33. PlayerDataDic[playerId] = clientData;
  34. }
  35. }
  36. }
  37. else
  38. {
  39. //未初始化管理器。移除数据(无需保存数据)
  40. if(m_ClientIDToPlayerId.TryGetValue(clientId, out var playerId))
  41. {
  42. m_ClientIDToPlayerId.Remove(clientId);
  43. PlayerData data = GetPlayerData(playerId);
  44. if(data != null)
  45. {
  46. if(data.IsVideoClient)
  47. {
  48. CameraController.Instance.ShutDownComposition();
  49. }
  50. if(data.ClientId == clientId)
  51. {
  52. PlayerDataDic.Remove(playerId);
  53. }
  54. }
  55. }
  56. }
  57. }
  58. //该客户端是否已连接
  59. public bool IsDuplicateConnection(string playerId)
  60. {
  61. return PlayerDataDic.ContainsKey(playerId) && PlayerDataDic[playerId].IsConnected;
  62. }
  63. //关键方法,当客户端连接(重连)到服务端,则保存(更新)客户端数据。playerId是客户端生成并发送到服务端的Guid
  64. public void SetupConnectingPlayerSessionData(ulong clientId, string playerId, PlayerData sessionPlayerData)
  65. {
  66. var isReconnecting = false;
  67. //判断是否同一客户端
  68. if(IsDuplicateConnection(playerId))
  69. {
  70. Debug.LogError($"Player ID {playerId} already exists. This is a duplicate connection. Rejecting this session data.");
  71. return;
  72. }
  73. //判断是否重连
  74. if(PlayerDataDic.ContainsKey(playerId))
  75. {
  76. if(!PlayerDataDic[playerId].IsConnected)
  77. {
  78. isReconnecting = true;
  79. }
  80. }
  81. //重连,则更新客户端数据
  82. if(isReconnecting)
  83. {
  84. sessionPlayerData = PlayerDataDic[playerId];
  85. sessionPlayerData.ClientId = clientId;
  86. sessionPlayerData.IsConnected = true;
  87. }
  88. //缓存数据
  89. m_ClientIDToPlayerId[clientId] = playerId;
  90. PlayerDataDic[playerId] = sessionPlayerData;
  91. }
  92. //根据ClientId,获取PlayerId
  93. public string GetPlayerId(ulong clientId)
  94. {
  95. if(m_ClientIDToPlayerId.TryGetValue(clientId, out string playerId))
  96. {
  97. return playerId;
  98. }
  99. Debug.Log($"No client player ID found mapped to the given client ID: {clientId}");
  100. return null;
  101. }
  102. //根据ClientId获取客户端数据SessionPlayerData
  103. public PlayerData GetPlayerData(ulong clientId)
  104. {
  105. var playerId = GetPlayerId(clientId);
  106. if(playerId != null)
  107. {
  108. return GetPlayerData(playerId);
  109. }
  110. Debug.Log($"No client player ID found mapped to the given client ID: {clientId}");
  111. return null;
  112. }
  113. public PlayerData GetPlayerData(string playerId)
  114. {
  115. if(PlayerDataDic.TryGetValue(playerId, out PlayerData data))
  116. {
  117. return data;
  118. }
  119. Debug.Log($"No PlayerData of matching player ID found: {playerId}");
  120. return null;
  121. }
  122. public PlayerData GetConnectedPlayerData()
  123. {
  124. foreach(var playerData in PlayerDataDic.Values)
  125. {
  126. if(playerData.IsConnected && playerData.ClientId != NetworkManager.Singleton.LocalClientId)
  127. {
  128. return playerData;
  129. }
  130. }
  131. return null;
  132. }
  133. //更新某个ClientId的客户端数据SessionPlayerData
  134. public void SetPlayerData(ulong clientId, PlayerData sessionPlayerData)
  135. {
  136. if(m_ClientIDToPlayerId.TryGetValue(clientId, out string playerId))
  137. {
  138. PlayerDataDic[playerId] = sessionPlayerData;
  139. }
  140. else
  141. {
  142. Debug.LogError($"No client player ID found mapped to the given client ID: {clientId}");
  143. }
  144. }
  145. //断开所有客户端
  146. public void CloseAllClient()
  147. {
  148. foreach(var playerData in PlayerDataDic.Values)
  149. {
  150. NetworkManager.Singleton?.DisconnectClient(playerData.ClientId);
  151. }
  152. OnServerEnded();
  153. }
  154. //标记管理器已经启动。可以缓存已断开连接的客户端数据
  155. public void OnSessionStarted()
  156. {
  157. m_HasSessionStarted = true;
  158. }
  159. //重新初始化已连接的客户端。清空所有断开的客户端数据(下次连上,则标识为新客户端)
  160. public void OnSessionEnded()
  161. {
  162. ClearDisconnectedPlayersData();
  163. ReinitializePlayersData();
  164. m_HasSessionStarted = false;
  165. }
  166. //服务端关闭,清空所有数据
  167. public void OnServerEnded()
  168. {
  169. PlayerDataDic.Clear();
  170. m_ClientIDToPlayerId.Clear();
  171. m_HasSessionStarted = false;
  172. }
  173. //重新初始化已连接的客户端。调用每个客户端的SessionPlayerData.Reinitialize方法
  174. void ReinitializePlayersData()
  175. {
  176. foreach(var id in m_ClientIDToPlayerId.Keys)
  177. {
  178. string playerId = m_ClientIDToPlayerId[id];
  179. PlayerData sessionPlayerData = PlayerDataDic[playerId];
  180. sessionPlayerData.Reinitialize();
  181. PlayerDataDic[playerId] = sessionPlayerData;
  182. }
  183. }
  184. //清空所有断开的客户端数据
  185. void ClearDisconnectedPlayersData()
  186. {
  187. //收集所有断开连接的客户端
  188. List<ulong> idsToClear = new List<ulong>();
  189. foreach(var id in m_ClientIDToPlayerId.Keys)
  190. {
  191. var data = GetPlayerData(id);
  192. if(data is { IsConnected: false })
  193. {
  194. idsToClear.Add(id);
  195. }
  196. }
  197. //移除数据
  198. foreach(var id in idsToClear)
  199. {
  200. string playerId = m_ClientIDToPlayerId[id];
  201. if(GetPlayerData(playerId)?.ClientId == id)
  202. {
  203. PlayerDataDic.Remove(playerId);
  204. }
  205. m_ClientIDToPlayerId.Remove(id);
  206. }
  207. }
  208. public bool HaveAnchorPlayer()
  209. {
  210. foreach(var client in PlayerDataDic)
  211. {
  212. PlayerData playerData = client.Value;
  213. if(playerData.IsConnected && playerData.Anchor != null)
  214. {
  215. return true;
  216. }
  217. }
  218. return false;
  219. }
  220. public bool HaveVideoPlayer()
  221. {
  222. foreach(var client in PlayerDataDic)
  223. {
  224. PlayerData playerData = client.Value;
  225. if(playerData.IsConnected && playerData.IsVideoClient)
  226. {
  227. return true;
  228. }
  229. }
  230. return false;
  231. }
  232. public PlayerData GetVideoPlayer()
  233. {
  234. foreach(var client in PlayerDataDic)
  235. {
  236. PlayerData playerData = client.Value;
  237. if(playerData.IsConnected && playerData.IsVideoClient)
  238. {
  239. return playerData;
  240. }
  241. }
  242. return null;
  243. }
  244. public bool HavePlayer()
  245. {
  246. foreach(var client in PlayerDataDic)
  247. {
  248. PlayerData playerData = client.Value;
  249. if(playerData.IsConnected && playerData.ClientId != 0)
  250. {
  251. return true;
  252. }
  253. }
  254. return false;
  255. }
  256. }