using Rokid.MRC; using System; using System.Collections.Generic; using Unity.Collections; using Unity.Netcode; using UnityEngine; //连接状态 public enum ConnectStatus { Undefined, Success, ServerFull, //服务端连接数已满 LoggedInAgain, //其他客户端登录,掉线 UserRequestedDisconnect, //客户端主动断开连接 GenericDisconnect, //断开连接 Reconnecting, //断线重连 IncompatibleBuildType, //客户端的Build类型不符合服务端的要求。如果客户端是Debug版本,不允许连接 HostEndedSession, //Host服务端主动关闭连接 StartHostFailed, //启动Host服务端失败 StartClientFailed, //启动Client失败 AlreadyHaveVideoClient, //只能有一个视频流 } public struct ReconnectMessage { public int CurrentAttempt; public int MaxAttempt; public ReconnectMessage(int currentAttempt, int maxAttempt) { CurrentAttempt = currentAttempt; MaxAttempt = maxAttempt; } } public struct ConnectionEventMessage : INetworkSerializeByMemcpy { public ConnectStatus ConnectStatus; public string PlayerName; } public static class EventDefine { //网络连接 public static readonly string ServerConnectionEvent = "ServerConnectionEvent"; public static readonly string ClientReConnectionEvent = "ClientReConnectionEvent"; public static readonly string ClientDisConnectionEvent = "ClientDisConnectionEvent"; public static readonly string ConnectStatusEvent = "ConnectStatusEvent"; } //连接状态机管理器 public class ConnectionManager : Singleton { //当前的连接状态 [SerializeField] public ConnectionState m_CurrentState; public NetworkManager NetworkManager; //重连次数 public int ReconnectAttempts = 2; //最大连接数 public int MaxConnectedPlayers = 8; //初始化几个状态 internal readonly OfflineState m_Offline = new OfflineState(); //连接 public ConnectionMethodIP ConnectionMethod; private ProfileManager m_ProfileManager; //客户端:OfflineState——ClientConnectingState——ClientConnectedState——ClientReconnectingState(断线重连)/OfflineState(服务端被动断连)/DisconnectingWithReasonState(服务端主动断连) internal readonly ClientConnectingState m_ClientConnecting = new ClientConnectingState(); internal readonly ClientConnectedState m_ClientConnected = new ClientConnectedState(); internal readonly ClientReconnectingState m_ClientReconnecting = new ClientReconnectingState(); internal readonly DisconnectingWithReasonState m_DisconnectingWithReason = new DisconnectingWithReasonState(); //服务端:OfflineState——StartingHostState——OfflineState(启动失败)/HostingState(启动成功) internal readonly StartingHostState m_StartingHost = new StartingHostState(); internal readonly HostingState m_Hosting = new HostingState(); private List connectionStateList; public override void Init() { List connectionStateList = new List() { m_Offline, m_ClientConnecting, m_ClientConnected, m_ClientReconnecting, m_DisconnectingWithReason, m_StartingHost, m_Hosting }; //初始化每个状态 foreach(var state in connectionStateList) { state.m_ConnectionManager = this; } m_CurrentState = m_Offline; NetworkManager.OnClientConnectedCallback += OnClientConnectedCallback; NetworkManager.OnClientDisconnectCallback += OnClientDisconnectCallback; NetworkManager.OnServerStarted += OnServerStarted; NetworkManager.ConnectionApprovalCallback += ApprovalCheck; NetworkManager.OnTransportFailure += OnTransportFailure; ConnectionMethod = new ConnectionMethodIP(this, m_ProfileManager); } public void SetNetworkManager(NetworkManager manager) { NetworkManager = manager; } public override void OnDestroy() { base.OnDestroy(); NetworkManager.OnClientConnectedCallback -= OnClientConnectedCallback; NetworkManager.OnClientDisconnectCallback -= OnClientDisconnectCallback; NetworkManager.OnServerStarted -= OnServerStarted; NetworkManager.ConnectionApprovalCallback -= ApprovalCheck; NetworkManager.OnTransportFailure -= OnTransportFailure; } internal void ChangeState(ConnectionState nextState) { Debug.Log($"ChangeState: Changed connection state from {m_CurrentState.GetType().Name} to {nextState.GetType().Name}."); if(m_CurrentState != null) { m_CurrentState.Exit(); } m_CurrentState = nextState; m_CurrentState.Enter(); } void OnClientDisconnectCallback(ulong clientId) { m_CurrentState.OnClientDisconnect(clientId); } void OnClientConnectedCallback(ulong clientId) { m_CurrentState.OnClientConnected(clientId); } void OnServerStarted() { m_CurrentState.OnServerStarted(); } void ApprovalCheck(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response) { m_CurrentState.ApprovalCheck(request, response); } void OnTransportFailure() { m_CurrentState.OnTransportFailure(); } public void StartClientIp(string ipaddress, int port) { m_CurrentState.StartClientIP(ipaddress, port); } public void StartHostIp(string ipaddress, int port) { m_CurrentState.StartHostIP(ipaddress, port); } //外部调用,客户端主动发起断开 public void RequestShutdown() { m_CurrentState.OnUserRequestedShutdown(); } //-------------------------------自定义消息处理 //自定义的消息,当调用NetworkManager.StartClient方法,就会初始化NetworkSceneManager和CustomMessagingManager,同时回调此处方法 public void RegisterCustomMessages() { NetworkManager.CustomMessagingManager.RegisterNamedMessageHandler(nameof(ReceiveServerToClientSetDisconnectReason_CustomMessage), ReceiveServerToClientSetDisconnectReason_CustomMessage); } //客户端收到服务端的断开连接,并附加原因 void ReceiveServerToClientSetDisconnectReason_CustomMessage(ulong clientID, FastBufferReader reader) { reader.ReadValueSafe(out ConnectStatus status); m_CurrentState.OnDisconnectReasonReceived(status); } //发送DisconnectReason信息给所有客户端 public void SendServerToAllClientsSetDisconnectReason(ConnectStatus status) { var writer = new FastBufferWriter(sizeof(ConnectStatus), Allocator.Temp); writer.WriteValueSafe(status); NetworkManager.CustomMessagingManager.SendNamedMessageToAll(nameof(ReceiveServerToClientSetDisconnectReason_CustomMessage), writer); } //发送DisconnectReason信息给indicated客户端 public void SendServerToClientSetDisconnectReason(ulong clientID, ConnectStatus status) { var writer = new FastBufferWriter(sizeof(ConnectStatus), Allocator.Temp); writer.WriteValueSafe(status); NetworkManager.CustomMessagingManager.SendNamedMessage(nameof(ReceiveServerToClientSetDisconnectReason_CustomMessage), clientID, writer); } }