123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- /*
- Documentation: https://mirror-networking.gitbook.io/docs/components/network-authenticators
- API Reference: https://mirror-networking.com/docs/api/Mirror.NetworkAuthenticator.html
- */
- namespace Mirror.Examples.Chat
- {
- [AddComponentMenu("")]
- public class ChatAuthenticator : NetworkAuthenticator
- {
- readonly HashSet<NetworkConnection> connectionsPendingDisconnect = new HashSet<NetworkConnection>();
- internal static readonly HashSet<string> playerNames = new HashSet<string>();
- [Header("Client Username")]
- public string playerName;
- #region Messages
- public struct AuthRequestMessage : NetworkMessage
- {
- // use whatever credentials make sense for your game
- // for example, you might want to pass the accessToken if using oauth
- public string authUsername;
- }
- public struct AuthResponseMessage : NetworkMessage
- {
- public byte code;
- public string message;
- }
- #endregion
- #region Server
- // RuntimeInitializeOnLoadMethod -> fast playmode without domain reload
- [UnityEngine.RuntimeInitializeOnLoadMethod]
- static void ResetStatics()
- {
- playerNames.Clear();
- }
- /// <summary>
- /// Called on server from StartServer to initialize the Authenticator
- /// <para>Server message handlers should be registered in this method.</para>
- /// </summary>
- public override void OnStartServer()
- {
- // register a handler for the authentication request we expect from client
- NetworkServer.RegisterHandler<AuthRequestMessage>(OnAuthRequestMessage, false);
- }
- /// <summary>
- /// Called on server from StopServer to reset the Authenticator
- /// <para>Server message handlers should be registered in this method.</para>
- /// </summary>
- public override void OnStopServer()
- {
- // unregister the handler for the authentication request
- NetworkServer.UnregisterHandler<AuthRequestMessage>();
- }
- /// <summary>
- /// Called on server from OnServerConnectInternal when a client needs to authenticate
- /// </summary>
- /// <param name="conn">Connection to client.</param>
- public override void OnServerAuthenticate(NetworkConnectionToClient conn)
- {
- // do nothing...wait for AuthRequestMessage from client
- }
- /// <summary>
- /// Called on server when the client's AuthRequestMessage arrives
- /// </summary>
- /// <param name="conn">Connection to client.</param>
- /// <param name="msg">The message payload</param>
- public void OnAuthRequestMessage(NetworkConnectionToClient conn, AuthRequestMessage msg)
- {
- Debug.Log($"Authentication Request: {msg.authUsername}");
- if (connectionsPendingDisconnect.Contains(conn)) return;
- // check the credentials by calling your web server, database table, playfab api, or any method appropriate.
- if (!playerNames.Contains(msg.authUsername))
- {
- // Add the name to the HashSet
- playerNames.Add(msg.authUsername);
- // Store username in authenticationData
- // This will be read in Player.OnStartServer
- // to set the playerName SyncVar.
- conn.authenticationData = msg.authUsername;
- // create and send msg to client so it knows to proceed
- AuthResponseMessage authResponseMessage = new AuthResponseMessage
- {
- code = 100,
- message = "Success"
- };
- conn.Send(authResponseMessage);
- // Accept the successful authentication
- ServerAccept(conn);
- }
- else
- {
- connectionsPendingDisconnect.Add(conn);
- // create and send msg to client so it knows to disconnect
- AuthResponseMessage authResponseMessage = new AuthResponseMessage
- {
- code = 200,
- message = "Username already in use...try again"
- };
- conn.Send(authResponseMessage);
- // must set NetworkConnection isAuthenticated = false
- conn.isAuthenticated = false;
- // disconnect the client after 1 second so that response message gets delivered
- StartCoroutine(DelayedDisconnect(conn, 1f));
- }
- }
- IEnumerator DelayedDisconnect(NetworkConnectionToClient conn, float waitTime)
- {
- yield return new WaitForSeconds(waitTime);
- // Reject the unsuccessful authentication
- ServerReject(conn);
- yield return null;
- // remove conn from pending connections
- connectionsPendingDisconnect.Remove(conn);
- }
- #endregion
- #region Client
- // Called by UI element UsernameInput.OnValueChanged
- public void SetPlayername(string username)
- {
- playerName = username;
- LoginUI.instance.errorText.text = string.Empty;
- LoginUI.instance.errorText.gameObject.SetActive(false);
- }
- /// <summary>
- /// Called on client from StartClient to initialize the Authenticator
- /// <para>Client message handlers should be registered in this method.</para>
- /// </summary>
- public override void OnStartClient()
- {
- // register a handler for the authentication response we expect from server
- NetworkClient.RegisterHandler<AuthResponseMessage>(OnAuthResponseMessage, false);
- }
- /// <summary>
- /// Called on client from StopClient to reset the Authenticator
- /// <para>Client message handlers should be unregistered in this method.</para>
- /// </summary>
- public override void OnStopClient()
- {
- // unregister the handler for the authentication response
- NetworkClient.UnregisterHandler<AuthResponseMessage>();
- }
- /// <summary>
- /// Called on client from OnClientConnectInternal when a client needs to authenticate
- /// </summary>
- public override void OnClientAuthenticate()
- {
- NetworkClient.Send(new AuthRequestMessage { authUsername = playerName });
- }
- /// <summary>
- /// Called on client when the server's AuthResponseMessage arrives
- /// </summary>
- /// <param name="msg">The message payload</param>
- public void OnAuthResponseMessage(AuthResponseMessage msg)
- {
- if (msg.code == 100)
- {
- Debug.Log($"Authentication Response: {msg.code} {msg.message}");
- // Authentication has been accepted
- ClientAccept();
- }
- else
- {
- Debug.LogError($"Authentication Response: {msg.code} {msg.message}");
- // Authentication has been rejected
- // StopHost works for both host client and remote clients
- NetworkManager.singleton.StopHost();
- // Do this AFTER StopHost so it doesn't get cleared / hidden by OnClientDisconnect
- LoginUI.instance.errorText.text = msg.message;
- LoginUI.instance.errorText.gameObject.SetActive(true);
- }
- }
- #endregion
- }
- }
|