ChatAuthenticator.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /*
  5. Documentation: https://mirror-networking.gitbook.io/docs/components/network-authenticators
  6. API Reference: https://mirror-networking.com/docs/api/Mirror.NetworkAuthenticator.html
  7. */
  8. namespace Mirror.Examples.Chat
  9. {
  10. [AddComponentMenu("")]
  11. public class ChatAuthenticator : NetworkAuthenticator
  12. {
  13. readonly HashSet<NetworkConnection> connectionsPendingDisconnect = new HashSet<NetworkConnection>();
  14. [Header("Client Username")]
  15. public string playerName;
  16. #region Messages
  17. public struct AuthRequestMessage : NetworkMessage
  18. {
  19. // use whatever credentials make sense for your game
  20. // for example, you might want to pass the accessToken if using oauth
  21. public string authUsername;
  22. }
  23. public struct AuthResponseMessage : NetworkMessage
  24. {
  25. public byte code;
  26. public string message;
  27. }
  28. #endregion
  29. #region Server
  30. /// <summary>
  31. /// Called on server from StartServer to initialize the Authenticator
  32. /// <para>Server message handlers should be registered in this method.</para>
  33. /// </summary>
  34. public override void OnStartServer()
  35. {
  36. // register a handler for the authentication request we expect from client
  37. NetworkServer.RegisterHandler<AuthRequestMessage>(OnAuthRequestMessage, false);
  38. }
  39. /// <summary>
  40. /// Called on server from StopServer to reset the Authenticator
  41. /// <para>Server message handlers should be registered in this method.</para>
  42. /// </summary>
  43. public override void OnStopServer()
  44. {
  45. // unregister the handler for the authentication request
  46. NetworkServer.UnregisterHandler<AuthRequestMessage>();
  47. }
  48. /// <summary>
  49. /// Called on server from OnServerConnectInternal when a client needs to authenticate
  50. /// </summary>
  51. /// <param name="conn">Connection to client.</param>
  52. public override void OnServerAuthenticate(NetworkConnectionToClient conn)
  53. {
  54. // do nothing...wait for AuthRequestMessage from client
  55. }
  56. /// <summary>
  57. /// Called on server when the client's AuthRequestMessage arrives
  58. /// </summary>
  59. /// <param name="conn">Connection to client.</param>
  60. /// <param name="msg">The message payload</param>
  61. public void OnAuthRequestMessage(NetworkConnectionToClient conn, AuthRequestMessage msg)
  62. {
  63. Debug.Log($"Authentication Request: {msg.authUsername}");
  64. if (connectionsPendingDisconnect.Contains(conn)) return;
  65. // check the credentials by calling your web server, database table, playfab api, or any method appropriate.
  66. if (!Player.playerNames.Contains(msg.authUsername))
  67. {
  68. // Add the name to the HashSet
  69. Player.playerNames.Add(msg.authUsername);
  70. // Store username in authenticationData
  71. // This will be read in Player.OnStartServer
  72. // to set the playerName SyncVar.
  73. conn.authenticationData = msg.authUsername;
  74. // create and send msg to client so it knows to proceed
  75. AuthResponseMessage authResponseMessage = new AuthResponseMessage
  76. {
  77. code = 100,
  78. message = "Success"
  79. };
  80. conn.Send(authResponseMessage);
  81. // Accept the successful authentication
  82. ServerAccept(conn);
  83. }
  84. else
  85. {
  86. connectionsPendingDisconnect.Add(conn);
  87. // create and send msg to client so it knows to disconnect
  88. AuthResponseMessage authResponseMessage = new AuthResponseMessage
  89. {
  90. code = 200,
  91. message = "Username already in use...try again"
  92. };
  93. conn.Send(authResponseMessage);
  94. // must set NetworkConnection isAuthenticated = false
  95. conn.isAuthenticated = false;
  96. // disconnect the client after 1 second so that response message gets delivered
  97. StartCoroutine(DelayedDisconnect(conn, 1f));
  98. }
  99. }
  100. IEnumerator DelayedDisconnect(NetworkConnectionToClient conn, float waitTime)
  101. {
  102. yield return new WaitForSeconds(waitTime);
  103. // Reject the unsuccessful authentication
  104. ServerReject(conn);
  105. yield return null;
  106. // remove conn from pending connections
  107. connectionsPendingDisconnect.Remove(conn);
  108. }
  109. #endregion
  110. #region Client
  111. // Called by UI element UsernameInput.OnValueChanged
  112. public void SetPlayername(string username)
  113. {
  114. playerName = username;
  115. LoginUI.instance.errorText.text = string.Empty;
  116. LoginUI.instance.errorText.gameObject.SetActive(false);
  117. }
  118. /// <summary>
  119. /// Called on client from StartClient to initialize the Authenticator
  120. /// <para>Client message handlers should be registered in this method.</para>
  121. /// </summary>
  122. public override void OnStartClient()
  123. {
  124. // register a handler for the authentication response we expect from server
  125. NetworkClient.RegisterHandler<AuthResponseMessage>(OnAuthResponseMessage, false);
  126. }
  127. /// <summary>
  128. /// Called on client from StopClient to reset the Authenticator
  129. /// <para>Client message handlers should be unregistered in this method.</para>
  130. /// </summary>
  131. public override void OnStopClient()
  132. {
  133. // unregister the handler for the authentication response
  134. NetworkClient.UnregisterHandler<AuthResponseMessage>();
  135. }
  136. /// <summary>
  137. /// Called on client from OnClientConnectInternal when a client needs to authenticate
  138. /// </summary>
  139. public override void OnClientAuthenticate()
  140. {
  141. AuthRequestMessage authRequestMessage = new AuthRequestMessage
  142. {
  143. authUsername = playerName,
  144. };
  145. NetworkClient.connection.Send(authRequestMessage);
  146. }
  147. /// <summary>
  148. /// Called on client when the server's AuthResponseMessage arrives
  149. /// </summary>
  150. /// <param name="msg">The message payload</param>
  151. public void OnAuthResponseMessage(AuthResponseMessage msg)
  152. {
  153. if (msg.code == 100)
  154. {
  155. Debug.Log($"Authentication Response: {msg.message}");
  156. // Authentication has been accepted
  157. ClientAccept();
  158. }
  159. else
  160. {
  161. Debug.LogError($"Authentication Response: {msg.message}");
  162. // Authentication has been rejected
  163. // StopHost works for both host client and remote clients
  164. NetworkManager.singleton.StopHost();
  165. // Do this AFTER StopHost so it doesn't get cleared / hidden by OnClientDisconnect
  166. LoginUI.instance.errorText.text = msg.message;
  167. LoginUI.instance.errorText.gameObject.SetActive(true);
  168. }
  169. }
  170. #endregion
  171. }
  172. }