Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding an automatic reconnection process to RoomClient for recovery a… #33

Merged
merged 3 commits into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Unity/Assets/Editor/Rooms/RoomClientEditor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ public override void OnInspectorGUI()
EditorGUILayout.HelpBox("Joined Room " + component.Room.UUID, MessageType.Info);
}

EditorGUILayout.PropertyField(serializedObject.FindProperty("reconnectBehaviour"));

foldoutRooms = EditorGUILayout.BeginFoldoutHeaderGroup(foldoutRooms, "Available Rooms");

if (foldoutRooms)
Expand Down
33 changes: 21 additions & 12 deletions Unity/Assets/Runtime/Messaging/NetworkScene.cs
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,26 @@ public void AddConnection(INetworkConnection connection)
connections.Add(connection);
}

/// <summary>
/// Public method instructing the network scene to drop all current connections and dispose of them.
/// Used to recover from a connection loss to Nexus.
/// </summary>
public void ClearConnections()
{
foreach (var c in connections)
{
try
{
c.Dispose();
}
catch
{

}
}
connections.Clear();
}

private void Update()
{
OnUpdate.Invoke();
Expand Down Expand Up @@ -329,18 +349,7 @@ public void SendJson<T>(NetworkId objectid, T message)

private void OnDestroy()
{
foreach (var c in connections)
{
try
{
c.Dispose();
}
catch
{

}
}
connections.Clear();
ClearConnections();
}
}
}
91 changes: 87 additions & 4 deletions Unity/Assets/Runtime/Rooms/RoomClient.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Ubiq.Dictionaries;
using Ubiq.Messaging;
using Ubiq.Networking;
using Ubiq.Rooms.Messages;
using Ubiq.XR.Notifications;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace Ubiq.Rooms
{
Expand Down Expand Up @@ -240,6 +240,18 @@ public IEnumerable<IPeer> Peers
private float heartbeatSent => Time.realtimeSinceStartup - pingSent;
public static float HeartbeatTimeout = 5f;
public static float HeartbeatInterval = 1f;

public enum ReconnectBehaviour
{
None,
Reconnect,
ReconnectAndReloadScenes
}

public ReconnectBehaviour reconnectBehaviour = ReconnectBehaviour.None;
public static float reconnectTimeout = 10.0f;
private float nextReconnectTimeout = reconnectTimeout;

private PeerInterfaceFriend me = new PeerInterfaceFriend(Guid.NewGuid().ToString());
private RoomInterfaceFriend room = new RoomInterfaceFriend();
private NetworkScene scene;
Expand All @@ -262,7 +274,15 @@ public override string Message
{
get
{
return $"No Connection ({ client.heartbeatReceived.ToString("0") } seconds ago)";
if (client.reconnectBehaviour == ReconnectBehaviour.None)
{
return $"Connection lost ({ client.heartbeatReceived.ToString("0") } seconds ago)";
}
else
{
var timeToReconnect = Mathf.Max(0,client.nextReconnectTimeout - client.heartbeatReceived);
return $"Connection lost (Next reconnect attempt in { timeToReconnect.ToString("0") } seconds)";
}
}
}
}
Expand Down Expand Up @@ -547,7 +567,7 @@ protected void ProcessMessage(ReferenceCountedSceneGraphMessage message)
case "Ping":
{
pingReceived = Time.realtimeSinceStartup;
PlayerNotifications.Delete(ref notification);

var response = JsonUtility.FromJson<PingResponseArgs>(container.args);
OnPingResponse(response);
}
Expand Down Expand Up @@ -635,6 +655,38 @@ public void Connect(ConnectionDefinition connection)
scene.AddConnection(Connections.Resolve(connection));
}

/// <summary>
/// Method to reset all current connections and reconnect to the ones defined by the user in the Unity UI.
/// </summary>
public void ResetAndReconnect()
{
ResetAndReconnect(servers);
}

/// <summary>
/// Method to reset all current connections and reconnect to the ones defined in the connection definition passed as argument.
/// </summary>
/// <param name="connectionDefinitions">The connection definition that will be connected after the reset.</param>
public void ResetAndReconnect(ConnectionDefinition[] connectionDefinitions)
{
// Drop all connections
scene.ClearConnections();

// Reconnect all connections
foreach (var item in connectionDefinitions)
{
try
{
Connect(item);
}
catch(Exception e)
{
Debug.LogError(e.ToString());
}
}
}


private void Update()
{
actions.ForEach(a => a());
Expand Down Expand Up @@ -674,10 +726,20 @@ private void Update()

if (heartbeatReceived > HeartbeatTimeout)
{
// There's been a long interval between server responses
// We may be disconnected, or there may be network issues

if (notification == null)
{
notification = PlayerNotifications.Show(new TimeoutNotification(this));
}

if (heartbeatReceived > nextReconnectTimeout
&& reconnectBehaviour != ReconnectBehaviour.None)
{
ResetAndReconnect();
nextReconnectTimeout += reconnectTimeout;
}
}
}

Expand Down Expand Up @@ -758,9 +820,30 @@ public void Ping()

private void OnPingResponse(PingResponseArgs args)
{
PlayerNotifications.Delete(ref notification);
nextReconnectTimeout = reconnectTimeout;

if(SessionId != args.sessionId && SessionId != null)
{
Join(name:"",publish:false); // The RoomClient has re-established connectivity with the RoomServer, but under a different state. So, leave the room and let the user code re-establish any state.
// The RoomClient has re-established connectivity with
// the RoomServer, but under a different state.
if (reconnectBehaviour == ReconnectBehaviour.ReconnectAndReloadScenes)
{
var scenes = new Scene[SceneManager.sceneCount];
for (int i = 0; i < SceneManager.sceneCount; i++)
{
scenes[i] = SceneManager.GetSceneAt(i);
}

var first = true;
for (int i = 0; i < scenes.Length; i++)
{
SceneManager.LoadScene(scenes[i].buildIndex,mode: first
? LoadSceneMode.Single
: LoadSceneMode.Additive);
first = false;
}
}
}

SessionId = args.sessionId;
Expand Down
7 changes: 7 additions & 0 deletions Unity/Assets/Samples/Start Here.unity
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@ MeshRenderer:
m_CastShadows: 1
m_ReceiveShadows: 1
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
Expand Down Expand Up @@ -461,6 +462,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: -1.214, y: 0.634, z: -0.99}
m_LocalScale: {x: 0.25361246, y: 0.25361246, z: 0.25361246}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 4
Expand Down Expand Up @@ -707,6 +709,11 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2642065778884258271, guid: 46c1f5d5a11cf5042886aabd56e7b9d7,
type: 3}
propertyPath: m_Enabled
value: 1
objectReference: {fileID: 0}
- target: {fileID: 2642065778884258271, guid: 46c1f5d5a11cf5042886aabd56e7b9d7,
type: 3}
propertyPath: servers.Array.size
Expand Down
7 changes: 7 additions & 0 deletions Unity/Assets/Samples/_Common/Prefabs/Network Scene.prefab
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 4
Expand Down Expand Up @@ -72,6 +73,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 0
Expand Down Expand Up @@ -118,6 +120,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 7068762446051028576}
- {fileID: 7068762446560339092}
Expand Down Expand Up @@ -160,6 +163,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
servers:
- {fileID: -7849211376014683480, guid: 1c91df7c43c1dbe4fb0fb303e71a2790, type: 2}
reconnectBehaviour: 2
--- !u!114 &7068762446378101731
MonoBehaviour:
m_ObjectHideFlags: 0
Expand Down Expand Up @@ -217,6 +221,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 1
Expand Down Expand Up @@ -260,6 +265,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 2
Expand Down Expand Up @@ -309,6 +315,7 @@ Transform:
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 7068762446378101729}
m_RootOrder: 3
Expand Down
Loading