reconnect, 30% fixes from test feedback

This commit is contained in:
2026-05-01 18:56:37 +05:30
parent 1da7c052f8
commit e3aa51d3e7
383 changed files with 41074 additions and 98 deletions
+146 -21
View File
@@ -1,11 +1,32 @@
using System.Collections;
using UnityEngine;
using Mirror;
using UnityEngine.Networking;
public class NetManager : NetworkManager
{
const float InitialReconnectDelaySeconds = 2f;
const float ReopenTriggerDelaySeconds = 15f;
[SerializeField] float reconnectIntervalSeconds = 15f;
Coroutine reconnectCoroutine;
bool reopenRequestedThisDisconnect;
bool reopenRequestInFlight;
[SerializeField] private CanvasGroup reconnectCanvasGroup;
static bool s_IntentionalClientDisconnect;
public static void MarkIntentionalClientDisconnect()
{
s_IntentionalClientDisconnect = true;
}
public override void OnApplicationQuit()
{
MarkIntentionalClientDisconnect();
StopReconnectLoop();
base.OnApplicationQuit();
}
public override void OnStopServer()
{
@@ -13,37 +34,103 @@ public class NetManager : NetworkManager
base.OnStopServer();
}
public override void OnStopClient()
{
base.OnStopClient();
TryStartReconnectLoop();
}
public override void OnClientConnect()
{
base.OnClientConnect();
Logger.Log("Client connected");
reopenRequestedThisDisconnect = false;
reopenRequestInFlight = false;
StopReconnectLoop();
}
void TryStartReconnectLoop()
public override void OnClientDisconnect()
{
if (!ShouldReconnect() || reconnectCoroutine != null)
return;
base.OnClientDisconnect();
Logger.Log("Client disconnected");
if (ShouldReconnect())
{
if (reconnectCoroutine == null)
reconnectCoroutine = StartCoroutine(ReconnectLoopCoroutine());
else
SetReconnectCanvasVisible(true);
}
else
SetReconnectCanvasVisible(false);
}
reconnectCoroutine = StartCoroutine(CoroutineReconnectLoop());
public override void OnStopClient()
{
s_IntentionalClientDisconnect = false;
base.OnStopClient();
}
void StopReconnectLoop()
{
if (reconnectCoroutine == null)
{
SetReconnectCanvasVisible(false);
return;
}
StopCoroutine(reconnectCoroutine);
reconnectCoroutine = null;
SetReconnectCanvasVisible(false);
}
void SetReconnectCanvasVisible(bool visible)
{
if (reconnectCanvasGroup == null)
return;
reconnectCanvasGroup.alpha = visible ? 1f : 0f;
reconnectCanvasGroup.interactable = visible;
reconnectCanvasGroup.blocksRaycasts = visible;
}
IEnumerator ReconnectLoopCoroutine()
{
SetReconnectCanvasVisible(true);
reopenRequestedThisDisconnect = false;
reopenRequestInFlight = false;
float reconnectStartedAt = Time.realtimeSinceStartup;
float initialWaitEnd = Time.realtimeSinceStartup + InitialReconnectDelaySeconds;
while (ShouldReconnect() && Time.realtimeSinceStartup < initialWaitEnd)
yield return null;
while (ShouldReconnect())
{
if (!reopenRequestedThisDisconnect && !reopenRequestInFlight
&& Time.realtimeSinceStartup - reconnectStartedAt >= ReopenTriggerDelaySeconds)
{
reopenRequestedThisDisconnect = true;
StartCoroutine(CoRequestReopenForCurrentPort());
}
if (NetworkClient.active && !NetworkClient.isConnected)
{
StopClient();
yield return null;
continue;
}
if (!NetworkClient.active)
{
Logger.Log("Reconnect: attempting StartClient");
StartClient();
}
float waitEnd = Time.realtimeSinceStartup + reconnectIntervalSeconds;
while (ShouldReconnect() && Time.realtimeSinceStartup < waitEnd)
yield return null;
}
reconnectCoroutine = null;
SetReconnectCanvasVisible(false);
}
bool ShouldReconnect()
{
if (s_IntentionalClientDisconnect)
return false;
if (NetworkServer.active)
return false;
if (NetworkClient.isConnected)
@@ -54,20 +141,58 @@ public class NetManager : NetworkManager
return true;
}
IEnumerator CoroutineReconnectLoop()
IEnumerator CoRequestReopenForCurrentPort()
{
while (ShouldReconnect())
{
if (!NetworkClient.active)
{
Debug.Log("Client disconnected. Reconnecting...");
StartClient();
yield return new WaitForSeconds(reconnectIntervalSeconds);
}
reopenRequestInFlight = true;
yield return new WaitForSeconds(1);
int port = Cupid.RoomPort;
if (port <= 0)
{
Logger.Log("Reconnect: skipping /reopen because room port is invalid");
reopenRequestInFlight = false;
yield break;
}
reconnectCoroutine = null;
string baseUri = Cupid.CupidURI;
string password = Cupid.SettingsPassword;
if (string.IsNullOrWhiteSpace(baseUri) || string.IsNullOrEmpty(password))
{
Logger.Log("Reconnect: skipping /reopen because Cupid URI/password is not available");
reopenRequestInFlight = false;
yield break;
}
string query = "?password=" + UnityWebRequest.EscapeURL(password) + "&port=" + port;
string[] endpointCandidates =
{
baseUri.TrimEnd('/') + "/internal/admin/reopen" + query,
baseUri.TrimEnd('/') + "/reopen" + query
};
bool success = false;
for (int i = 0; i < endpointCandidates.Length; i++)
{
string url = endpointCandidates[i];
using (UnityWebRequest req = UnityWebRequest.Get(url))
{
req.downloadHandler = new DownloadHandlerBuffer();
yield return req.SendWebRequest();
string body = req.downloadHandler != null ? req.downloadHandler.text : "";
if (req.result == UnityWebRequest.Result.Success && req.responseCode >= 200 && req.responseCode < 300)
{
Logger.Log("Reconnect: /reopen success on port " + port + ". Response: " + body);
success = true;
break;
}
Logger.Log("Reconnect: /reopen failed at " + url + " status " + req.responseCode + " error: " + req.error + " body: " + body);
}
}
if (!success)
Logger.Log("Reconnect: all /reopen endpoint attempts failed.");
reopenRequestInFlight = false;
}
}