From 2d5cab50b0bd59c6786d5f6fcd7a36443a91fe24 Mon Sep 17 00:00:00 2001 From: JLChnToZ Date: Mon, 22 Apr 2024 23:53:39 +0800 Subject: [PATCH] Enhance late joiner flow (hopefully) Enable double-click resync to request owner serialize current state --- .../idv.jlchntoz.vvmw/Runtime/VVMW/Core.asset | 209 +++++++++++++++--- .../idv.jlchntoz.vvmw/Runtime/VVMW/Core.cs | 25 ++- 2 files changed, 205 insertions(+), 29 deletions(-) diff --git a/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/Core.asset b/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/Core.asset index 969b54d..d511c8d 100644 --- a/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/Core.asset +++ b/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/Core.asset @@ -44,7 +44,7 @@ MonoBehaviour: Data: - Name: Entry: 12 - Data: 62 + Data: 65 - Name: Entry: 7 Data: @@ -3298,10 +3298,163 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: url + Data: isOwnerSyncRequested - Name: $v Entry: 7 Data: 186|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: isOwnerSyncRequested + - Name: k__BackingField + Entry: 9 + Data: 46 + - Name: k__BackingField + Entry: 9 + Data: 46 + - Name: k__BackingField + Entry: 7 + Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib + - Name: + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 5 + Data: false + - Name: _fieldAttributes + Entry: 7 + Data: 187|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], + mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: lastSyncTime + - Name: $v + Entry: 7 + Data: 188|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: lastSyncTime + - Name: k__BackingField + Entry: 7 + Data: 189|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.DateTime, mscorlib + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 9 + Data: 189 + - Name: k__BackingField + Entry: 7 + Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib + - Name: + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 5 + Data: false + - Name: _fieldAttributes + Entry: 7 + Data: 190|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], + mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: lastClickResyncTime + - Name: $v + Entry: 7 + Data: 191|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: lastClickResyncTime + - Name: k__BackingField + Entry: 9 + Data: 189 + - Name: k__BackingField + Entry: 9 + Data: 189 + - Name: k__BackingField + Entry: 7 + Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib + - Name: + Entry: 6 + Data: + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 5 + Data: false + - Name: _fieldAttributes + Entry: 7 + Data: 192|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], + mscorlib + - Name: + Entry: 12 + Data: 0 + - Name: + Entry: 13 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 8 + Data: + - Name: + Entry: 7 + Data: + - Name: $k + Entry: 1 + Data: url + - Name: $v + Entry: 7 + Data: 193|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: url @@ -3325,14 +3478,14 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 187|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], + Data: 194|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 1 - Name: Entry: 7 - Data: 188|System.NonSerializedAttribute, mscorlib + Data: 195|System.NonSerializedAttribute, mscorlib - Name: Entry: 8 Data: @@ -3356,13 +3509,13 @@ MonoBehaviour: Data: author - Name: $v Entry: 7 - Data: 189|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 196|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: author - Name: k__BackingField Entry: 7 - Data: 190|System.RuntimeType, mscorlib + Data: 197|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.String, mscorlib @@ -3371,7 +3524,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 9 - Data: 190 + Data: 197 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -3386,20 +3539,20 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 191|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], + Data: 198|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 2 - Name: Entry: 7 - Data: 192|System.NonSerializedAttribute, mscorlib + Data: 199|System.NonSerializedAttribute, mscorlib - Name: Entry: 8 Data: - Name: Entry: 7 - Data: 193|UdonSharp.FieldChangeCallbackAttribute, UdonSharp.Runtime + Data: 200|UdonSharp.FieldChangeCallbackAttribute, UdonSharp.Runtime - Name: Entry: 8 Data: @@ -3423,16 +3576,16 @@ MonoBehaviour: Data: title - Name: $v Entry: 7 - Data: 194|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 201|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: title - Name: k__BackingField Entry: 9 - Data: 190 + Data: 197 - Name: k__BackingField Entry: 9 - Data: 190 + Data: 197 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -3447,20 +3600,20 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 195|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], + Data: 202|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 2 - Name: Entry: 7 - Data: 196|System.NonSerializedAttribute, mscorlib + Data: 203|System.NonSerializedAttribute, mscorlib - Name: Entry: 8 Data: - Name: Entry: 7 - Data: 197|UdonSharp.FieldChangeCallbackAttribute, UdonSharp.Runtime + Data: 204|UdonSharp.FieldChangeCallbackAttribute, UdonSharp.Runtime - Name: Entry: 8 Data: @@ -3484,16 +3637,16 @@ MonoBehaviour: Data: viewCount - Name: $v Entry: 7 - Data: 198|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 205|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: viewCount - Name: k__BackingField Entry: 9 - Data: 190 + Data: 197 - Name: k__BackingField Entry: 9 - Data: 190 + Data: 197 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -3508,20 +3661,20 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 199|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], + Data: 206|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 2 - Name: Entry: 7 - Data: 200|System.NonSerializedAttribute, mscorlib + Data: 207|System.NonSerializedAttribute, mscorlib - Name: Entry: 8 Data: - Name: Entry: 7 - Data: 201|UdonSharp.FieldChangeCallbackAttribute, UdonSharp.Runtime + Data: 208|UdonSharp.FieldChangeCallbackAttribute, UdonSharp.Runtime - Name: Entry: 8 Data: @@ -3545,16 +3698,16 @@ MonoBehaviour: Data: description - Name: $v Entry: 7 - Data: 202|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 209|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: description - Name: k__BackingField Entry: 9 - Data: 190 + Data: 197 - Name: k__BackingField Entry: 9 - Data: 190 + Data: 197 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -3569,20 +3722,20 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 203|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], + Data: 210|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 2 - Name: Entry: 7 - Data: 204|System.NonSerializedAttribute, mscorlib + Data: 211|System.NonSerializedAttribute, mscorlib - Name: Entry: 8 Data: - Name: Entry: 7 - Data: 205|UdonSharp.FieldChangeCallbackAttribute, UdonSharp.Runtime + Data: 212|UdonSharp.FieldChangeCallbackAttribute, UdonSharp.Runtime - Name: Entry: 8 Data: diff --git a/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/Core.cs b/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/Core.cs index 07d8329..cbaafc1 100644 --- a/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/Core.cs +++ b/Packages/idv.jlchntoz.vvmw/Runtime/VVMW/Core.cs @@ -19,6 +19,8 @@ namespace JLChnToZ.VRC.VVMW { [DefaultExecutionOrder(0)] [HelpURL("https://github.com/JLChnToZ/VVMW/blob/main/Packages/idv.jlchntoz.vvmw/README.md#vvmw-game-object")] public class Core : UdonSharpEventSender { + const long OWNER_SYNC_COOLDOWN_TICKS = 3 * TimeSpan.TicksPerSecond; + const long DOUBLE_CLICK_THRESHOLD_TICKS = 500 * TimeSpan.TicksPerMillisecond; const byte IDLE = 0, LOADING = 1, PLAYING = 2, PAUSED = 3; [HideInInspector, SerializeField] string[] trustedUrlDomains = new string[0]; // This list will be fetched on build, via VRChat SDK Vector4 normalST = new Vector4(1, 1, 0, 0), flippedST = new Vector4(1, -1, 0, 1); @@ -86,6 +88,8 @@ public class Core : UdonSharpEventSender { AudioSource assignedAudioSource; bool isRealtimeGIUpdaterRunning; internal bool afterFirstRun; + bool isOwnerSyncRequested; + DateTime lastSyncTime, lastClickResyncTime; // Yttl Receivers [NonSerialized] public VRCUrl url; @@ -350,6 +354,7 @@ void OnEnable() { screenTargetPropertyBlock = new MaterialPropertyBlock(); UpdateVolume(); if (!synced || Networking.IsOwner(gameObject)) SendCustomEventDelayedSeconds(nameof(_PlayDefaultUrl), autoPlayDelay); + else if (synced) SendCustomEventDelayedSeconds(nameof(_RequestOwnerSync), autoPlayDelay + 3); afterFirstRun = true; } @@ -462,6 +467,18 @@ public void GlobalSync() { public void LocalSync() { if (synced) { + var currentTime = Networking.GetNetworkDateTime(); + if (lastClickResyncTime < currentTime) { + if ((currentTime - lastClickResyncTime).Ticks < DOUBLE_CLICK_THRESHOLD_TICKS) { + lastClickResyncTime = currentTime + TimeSpan.FromTicks(OWNER_SYNC_COOLDOWN_TICKS); + if (!isOwnerSyncRequested) { + isOwnerSyncRequested = true; + SendCustomEventDelayedFrames(nameof(_RequestOwnerSync), 0); + } + return; + } + lastClickResyncTime = currentTime; + } #if UNITY_ANDROID if (IsUrlValid(questUrl)) localUrl = questUrl; @@ -696,6 +713,7 @@ public void _UpdateRealtimeGI() { public override void OnPreSerialization() { if (!synced || isLocalReloading) return; + lastSyncTime = Networking.GetNetworkDateTime(); if (activeHandler == null) { activePlayer = 0; state = IDLE; @@ -864,10 +882,15 @@ void SyncTime() { bool IsUrlValid(VRCUrl url) => Utilities.IsValid(url) && !url.Equals(VRCUrl.Empty); - public void _RequestOwnerSync() => SendCustomNetworkEvent(NetworkEventTarget.Owner, nameof(OwnerSync)); + public void _RequestOwnerSync() { + isOwnerSyncRequested = false; + if (!synced) return; + SendCustomNetworkEvent(NetworkEventTarget.Owner, nameof(OwnerSync)); + } public void OwnerSync() { if (!Networking.IsOwner(gameObject) || !synced) return; + if ((Networking.GetNetworkDateTime() - lastSyncTime).Ticks < OWNER_SYNC_COOLDOWN_TICKS) return; RequestSerialization(); }