reconnect, 30% fixes from test feedback
This commit is contained in:
+146
-21
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user