Files
Test-Multiplayer/Assets/Scripts/Chat/ChatAuthenticator.cs
T
pelpanagiotisandClaude Opus 5.5 5fc9ebf1e6 Add practice range: shooting, AK47, intro cinematic, dressed warehouse scene
- PortalTestDestination practice range: Valorant-style hitscan rifle (recoil,
  spray/bloom, reload, controller support), debug HUD, practice-dummy targets
  with head/body hitboxes, hit/death/respawn animations, procedural SFX/FX
- AK47 model (Quaternius, CC0) held via Animator IK, with fire/reload/equip anims
- Intro cinematic (camera shots, title card, target beam-in, GO hand-off)
- Scene dressing editor pass: CC0 textures, props, warehouse roof, lighting and
  post-processing; custom stylized skybox shader
- CharacterMovement: camera recoil, shoulder offset, cinematic control lock
- Unity CLI pipeline package; plus in-progress chat/Rive/player changes

Asset credits: Assets/Models/Props/PROPS_CREDITS.txt (3 CC-BY 3.0 props),
Assets/Textures/Range/TEXTURES_LICENSE.txt, Assets/Resources/*/..._LICENSE.txt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 08:56:35 +03:00

174 lines
5.1 KiB
C#

using Mirror;
using Mirror.Examples.Chat;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ChatAuthenticator : NetworkAuthenticator
{
readonly HashSet<NetworkConnectionToClient> connectionsPendingDisconnect = new HashSet<NetworkConnectionToClient>();
internal static readonly HashSet<string> playerNames = new HashSet<string>();
[Header("Client Username")]
public string playerName;
#region Messages;
public struct AuthRequestMessage : NetworkMessage
{
public string authUsername;
}
public struct AuthResponseMessage : NetworkMessage
{
public byte code;
public string message;
}
#endregion
#region Server
[UnityEngine.RuntimeInitializeOnLoadMethod]
static void ResetStatics()
{
playerNames.Clear();
}
public override void OnStartServer()
{
Debug.Log("[ChatAuthenticator] Server authentication started.");
NetworkServer.RegisterHandler<AuthRequestMessage>(OnAuthRequestMessage, false);
}
public override void OnStopServer()
{
Debug.Log("[ChatAuthenticator] Server authentication stopped.");
NetworkServer.UnregisterHandler<AuthRequestMessage>();
}
public override void OnServerAuthenticate(NetworkConnectionToClient conn)
{
Debug.LogWarning($"[ChatAuthenticator] OnServerAuthenticate called for connection {conn.connectionId}; waiting for AuthRequestMessage.");
}
public void OnAuthRequestMessage(NetworkConnectionToClient conn, AuthRequestMessage msg)
{
Debug.Log($"[ChatAuthenticator] Authentication request received from connection {conn.connectionId}. Username length: {msg.authUsername?.Length ?? 0}");
if (connectionsPendingDisconnect.Contains(conn)) return;
if (!playerNames.Contains(msg.authUsername))
{
playerNames.Add(msg.authUsername);
conn.authenticationData = msg.authUsername;
AuthResponseMessage authResponseMessage = new AuthResponseMessage
{
code = 100,
message = "Success"
};
conn.Send(authResponseMessage);
Debug.Log($"[ChatAuthenticator] Authentication accepted for connection {conn.connectionId}.");
ServerAccept(conn);
}
else
{
connectionsPendingDisconnect.Add(conn);
AuthResponseMessage authResponseMessage = new AuthResponseMessage
{
code = 200,
message = "Username already in use... try again"
};
conn.Send(authResponseMessage);
conn.isAuthenticated = false;
Debug.LogWarning($"[ChatAuthenticator] Authentication rejected for connection {conn.connectionId}: username already in use.");
StartCoroutine(DelayedDisconnect(conn, 1f));
}
}
IEnumerator DelayedDisconnect(NetworkConnectionToClient conn, float waitTime)
{
yield return new WaitForSeconds(waitTime);
ServerReject(conn);
yield return null;
connectionsPendingDisconnect.Remove(conn);
}
#endregion
#region Client
public void SetPlayerName(string username)
{
playerName = username;
Debug.Log($"[ChatAuthenticator] Client username set. Length: {playerName?.Length ?? 0}");
if (LoginUI.instance != null && LoginUI.instance.errorText != null)
{
LoginUI.instance.errorText.text = string.Empty;
LoginUI.instance.errorText.gameObject.SetActive(false);
}
}
public override void OnStartClient()
{
Debug.Log("[ChatAuthenticator] Client authentication started.");
NetworkClient.RegisterHandler<AuthResponseMessage>(OnAuthResponseMessage, false);
}
public override void OnStopClient()
{
Debug.Log("[ChatAuthenticator] Client authentication stopped.");
NetworkClient.UnregisterHandler<AuthResponseMessage>();
}
public override void OnClientAuthenticate()
{
Debug.Log($"[ChatAuthenticator] Sending authentication request. Username length: {playerName?.Length ?? 0}");
NetworkClient.Send(new AuthRequestMessage { authUsername = playerName });
}
public void OnAuthResponseMessage(AuthResponseMessage msg)
{
Debug.Log($"[ChatAuthenticator] Authentication response received. Code: {msg.code}, Message: '{msg.message}'");
if (msg.code == 100)
{
ClientAccept();
Debug.Log("[ChatAuthenticator] Client accepted by server.");
}
else
{
Debug.LogError($"[ChatAuthenticator] Client authentication rejected. Code: {msg.code}, Message: '{msg.message}'");
NetworkManager.singleton.StopHost();
LoginUI.instance.errorText.text = msg.message;
LoginUI.instance.errorText.gameObject.SetActive(true);
}
}
#endregion
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}