From da0e6699e746ef2fc81b24f6c53bb9d1e29e3c7a Mon Sep 17 00:00:00 2001 From: Marro64 Date: Mon, 12 Jan 2026 21:00:49 +0100 Subject: [PATCH] Working well now I think? --- Assets/Scenes/PacMan.unity | 188 +++------ Assets/Scripts/NetworkManager.asset | 598 ++++++++++++++++----------- Assets/Scripts/NetworkManager.cs | 361 +++++++++------- Assets/Test stuff/TestBall.cs | 12 +- Assets/Test stuff/TestBallManager.cs | 2 +- 5 files changed, 609 insertions(+), 552 deletions(-) diff --git a/Assets/Scenes/PacMan.unity b/Assets/Scenes/PacMan.unity index 2d51eaa..d13f1fe 100644 --- a/Assets/Scenes/PacMan.unity +++ b/Assets/Scenes/PacMan.unity @@ -290,12 +290,12 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2841571} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 4.266148, y: 14.909718, z: -30.038902} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 297676220} + m_Father: {fileID: 712073434} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &6734103 PrefabInstance: @@ -9699,11 +9699,8 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: - - {fileID: 1897221841} - - {fileID: 2841572} - {fileID: 963448677} - - {fileID: 1334822256} - - {fileID: 1683006206} + - {fileID: 1381489908} m_Father: {fileID: 1886023632} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &300095180 @@ -22129,6 +22126,9 @@ Transform: - {fileID: 462995872} - {fileID: 339867315} - {fileID: 99960227} + - {fileID: 1334822256} + - {fileID: 1683006206} + - {fileID: 2841572} m_Father: {fileID: 1886023632} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!4 &712932630 stripped @@ -25080,6 +25080,7 @@ Transform: - {fileID: 196434888} - {fileID: 1933482823} - {fileID: 1959372908} + - {fileID: 1897221841} m_Father: {fileID: 1886023632} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &808835976 @@ -29223,37 +29224,6 @@ Transform: m_CorrespondingSourceObject: {fileID: 1315692994360949719, guid: 00a825a5aeafee94789192f61cbb3a5a, type: 3} m_PrefabInstance: {fileID: 230093841} m_PrefabAsset: {fileID: 0} ---- !u!1 &979503862 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 979503863} - m_Layer: 0 - m_Name: Smoothing when correcting for turns - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &979503863 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 979503862} - serializedVersion: 2 - 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: 1002127288} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &982882420 PrefabInstance: m_ObjectHideFlags: 0 @@ -30452,40 +30422,6 @@ Transform: m_CorrespondingSourceObject: {fileID: 1315692994360949719, guid: 00a825a5aeafee94789192f61cbb3a5a, type: 3} m_PrefabInstance: {fileID: 1789751918} m_PrefabAsset: {fileID: 0} ---- !u!1 &1002127287 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1002127288} - m_Layer: 0 - m_Name: Optional network optimising - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1002127288 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1002127287} - serializedVersion: 2 - 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: 1321513926} - - {fileID: 979503863} - - {fileID: 1983089941} - m_Father: {fileID: 1886023632} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1002272347 stripped GameObject: m_CorrespondingSourceObject: {fileID: 4099390335584803315, guid: 00a825a5aeafee94789192f61cbb3a5a, type: 3} @@ -41526,37 +41462,6 @@ Transform: m_CorrespondingSourceObject: {fileID: 1315692994360949719, guid: 00a825a5aeafee94789192f61cbb3a5a, type: 3} m_PrefabInstance: {fileID: 1008616612} m_PrefabAsset: {fileID: 0} ---- !u!1 &1321513925 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1321513926} - m_Layer: 0 - m_Name: Ghosts and pacman only try to turn at intersections - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1321513926 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1321513925} - serializedVersion: 2 - 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: 1002127288} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &1321862915 PrefabInstance: m_ObjectHideFlags: 0 @@ -41782,12 +41687,12 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1334822255} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 4.266148, y: 14.909718, z: -30.038902} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 297676220} + m_Father: {fileID: 712073434} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &1335132404 PrefabInstance: @@ -43042,6 +42947,37 @@ Transform: m_CorrespondingSourceObject: {fileID: 1315692994360949719, guid: 00a825a5aeafee94789192f61cbb3a5a, type: 3} m_PrefabInstance: {fileID: 321492582} m_PrefabAsset: {fileID: 0} +--- !u!1 &1381489907 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1381489908} + m_Layer: 0 + m_Name: FullSync with forced sync of id and time + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1381489908 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1381489907} + serializedVersion: 2 + 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: 297676220} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &1381602940 PrefabInstance: m_ObjectHideFlags: 0 @@ -51821,12 +51757,12 @@ Transform: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1683006205} serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 4.266148, y: 14.909718, z: -30.038902} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 297676220} + m_Father: {fileID: 712073434} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!4 &1683500364 stripped Transform: @@ -58950,7 +58886,6 @@ Transform: - {fileID: 1961479820} - {fileID: 2129311453} - {fileID: 2142346958} - - {fileID: 1002127288} - {fileID: 806746267} - {fileID: 1438618203} m_Father: {fileID: 0} @@ -59065,7 +59000,7 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] - m_Father: {fileID: 297676220} + m_Father: {fileID: 806746267} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &1898242099 stripped GameObject: @@ -61610,37 +61545,6 @@ Transform: m_CorrespondingSourceObject: {fileID: 1315692994360949719, guid: 00a825a5aeafee94789192f61cbb3a5a, type: 3} m_PrefabInstance: {fileID: 1728375025} m_PrefabAsset: {fileID: 0} ---- !u!1 &1983089940 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1983089941} - m_Layer: 0 - m_Name: Low-lag distance modes - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &1983089941 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1983089940} - serializedVersion: 2 - 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: 1002127288} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1001 &1988625401 PrefabInstance: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/NetworkManager.asset b/Assets/Scripts/NetworkManager.asset index 47fb49e..193b575 100644 --- a/Assets/Scripts/NetworkManager.asset +++ b/Assets/Scripts/NetworkManager.asset @@ -43,7 +43,7 @@ MonoBehaviour: Data: - Name: Entry: 12 - Data: 19 + Data: 21 - Name: Entry: 7 Data: @@ -265,118 +265,16 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: lastEventTimestamp + Data: retriesWithoutSuccess - Name: $v Entry: 7 Data: 14|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - - Name: k__BackingField - Entry: 1 - Data: lastEventTimestamp - - Name: k__BackingField - Entry: 9 - Data: 8 - - Name: k__BackingField - Entry: 9 - Data: 8 - - 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: 15|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: lastEventId - - Name: $v - Entry: 7 - Data: 16|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - - Name: k__BackingField - Entry: 1 - Data: lastEventId - - Name: k__BackingField - Entry: 7 - Data: 17|System.RuntimeType, mscorlib - - Name: - Entry: 1 - Data: System.Byte, mscorlib - - Name: - Entry: 8 - Data: - - Name: k__BackingField - Entry: 9 - Data: 17 - - 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: 18|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: retriesWithoutSuccess - - Name: $v - Entry: 7 - Data: 19|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: retriesWithoutSuccess - Name: k__BackingField Entry: 7 - Data: 20|System.RuntimeType, mscorlib + Data: 15|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Int32, mscorlib @@ -385,7 +283,109 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 9 - Data: 20 + Data: 15 + - 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: 16|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: hasFullSyncReady + - Name: $v + Entry: 7 + Data: 17|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: hasFullSyncReady + - Name: k__BackingField + Entry: 7 + Data: 18|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Boolean, mscorlib + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 9 + Data: 18 + - 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: 19|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: serializationRequested + - Name: $v + Entry: 7 + Data: 20|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: serializationRequested + - Name: k__BackingField + Entry: 9 + Data: 18 + - Name: k__BackingField + Entry: 9 + Data: 18 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -421,70 +421,16 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: fullSyncInQueue + Data: eventsQueue - Name: $v Entry: 7 Data: 22|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: fullSyncInQueue + Data: eventsQueue - Name: k__BackingField Entry: 7 Data: 23|System.RuntimeType, mscorlib - - Name: - Entry: 1 - Data: System.Boolean, mscorlib - - Name: - Entry: 8 - Data: - - Name: k__BackingField - Entry: 9 - Data: 23 - - 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: 24|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: buffer - - Name: $v - Entry: 7 - Data: 25|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - - Name: k__BackingField - Entry: 1 - Data: buffer - - Name: k__BackingField - Entry: 7 - Data: 26|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Byte[][], mscorlib @@ -493,7 +439,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 7 - Data: 27|System.RuntimeType, mscorlib + Data: 24|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Object[], mscorlib @@ -514,7 +460,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 28|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 25|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -535,19 +481,19 @@ MonoBehaviour: Data: - Name: $k Entry: 1 - Data: bufferIndex + Data: eventsQueueIndex - Name: $v Entry: 7 - Data: 29|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 26|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 - Data: bufferIndex + Data: eventsQueueIndex - Name: k__BackingField Entry: 9 - Data: 20 + Data: 15 - Name: k__BackingField Entry: 9 - Data: 20 + Data: 15 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -562,7 +508,211 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 30|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 27|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: eventsQueueIndexAtLastTransmission + - Name: $v + Entry: 7 + Data: 28|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: eventsQueueIndexAtLastTransmission + - Name: k__BackingField + Entry: 9 + Data: 15 + - Name: k__BackingField + Entry: 9 + Data: 15 + - 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: 29|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: eventTransmissionHistory + - Name: $v + Entry: 7 + Data: 30|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: eventTransmissionHistory + - Name: k__BackingField + Entry: 7 + Data: 31|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Int32[], mscorlib + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 9 + Data: 31 + - 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: 32|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: eventTransmissionHistoryIndex + - Name: $v + Entry: 7 + Data: 33|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: eventTransmissionHistoryIndex + - Name: k__BackingField + Entry: 9 + Data: 15 + - Name: k__BackingField + Entry: 9 + Data: 15 + - 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: 34|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: lastEventId + - Name: $v + Entry: 7 + Data: 35|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + - Name: k__BackingField + Entry: 1 + Data: lastEventId + - Name: k__BackingField + Entry: 7 + Data: 36|System.RuntimeType, mscorlib + - Name: + Entry: 1 + Data: System.Byte, mscorlib + - Name: + Entry: 8 + Data: + - Name: k__BackingField + Entry: 9 + Data: 36 + - 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: 37|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -586,13 +736,13 @@ MonoBehaviour: Data: networkedData - Name: $v Entry: 7 - Data: 31|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 38|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: networkedData - Name: k__BackingField Entry: 7 - Data: 32|System.RuntimeType, mscorlib + Data: 39|System.RuntimeType, mscorlib - Name: Entry: 1 Data: System.Byte[], mscorlib @@ -601,7 +751,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 9 - Data: 32 + Data: 39 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -616,13 +766,13 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 33|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 40|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 1 - Name: Entry: 7 - Data: 34|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime + Data: 41|UdonSharp.UdonSyncedAttribute, UdonSharp.Runtime - Name: Entry: 8 Data: @@ -646,16 +796,16 @@ MonoBehaviour: Data: k__BackingField - Name: $v Entry: 7 - Data: 35|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 42|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: k__BackingField - Name: k__BackingField Entry: 9 - Data: 23 + Data: 18 - Name: k__BackingField Entry: 9 - Data: 23 + Data: 18 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -670,7 +820,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 36|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 43|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -694,16 +844,16 @@ MonoBehaviour: Data: k__BackingField - Name: $v Entry: 7 - Data: 37|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 44|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: k__BackingField - Name: k__BackingField Entry: 9 - Data: 23 + Data: 18 - Name: k__BackingField Entry: 9 - Data: 23 + Data: 18 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -718,7 +868,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 38|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 45|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -742,7 +892,7 @@ MonoBehaviour: Data: k__BackingField - Name: $v Entry: 7 - Data: 39|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 46|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: k__BackingField @@ -766,7 +916,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 40|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 47|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -790,7 +940,7 @@ MonoBehaviour: Data:
k__BackingField - Name: $v Entry: 7 - Data: 41|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 48|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data:
k__BackingField @@ -814,7 +964,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 42|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 49|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -838,16 +988,16 @@ MonoBehaviour: Data: k__BackingField - Name: $v Entry: 7 - Data: 43|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 50|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: k__BackingField - Name: k__BackingField Entry: 9 - Data: 23 + Data: 18 - Name: k__BackingField Entry: 9 - Data: 23 + Data: 18 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -862,7 +1012,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 44|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 51|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -886,16 +1036,16 @@ MonoBehaviour: Data: k__BackingField - Name: $v Entry: 7 - Data: 45|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 52|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: k__BackingField - Name: k__BackingField Entry: 9 - Data: 23 + Data: 18 - Name: k__BackingField Entry: 9 - Data: 23 + Data: 18 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -910,55 +1060,7 @@ MonoBehaviour: Data: false - Name: _fieldAttributes Entry: 7 - Data: 46|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: indexAtLastSerialization - - Name: $v - Entry: 7 - Data: 47|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - - Name: k__BackingField - Entry: 1 - Data: indexAtLastSerialization - - Name: k__BackingField - Entry: 9 - Data: 20 - - Name: k__BackingField - Entry: 9 - Data: 20 - - 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: 48|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 53|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 0 @@ -982,13 +1084,13 @@ MonoBehaviour: Data: DebugImageToIndicateOwner - Name: $v Entry: 7 - Data: 49|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor + Data: 54|UdonSharp.Compiler.FieldDefinition, UdonSharp.Editor - Name: k__BackingField Entry: 1 Data: DebugImageToIndicateOwner - Name: k__BackingField Entry: 7 - Data: 50|System.RuntimeType, mscorlib + Data: 55|System.RuntimeType, mscorlib - Name: Entry: 1 Data: UnityEngine.Animator, UnityEngine.AnimationModule @@ -997,7 +1099,7 @@ MonoBehaviour: Data: - Name: k__BackingField Entry: 9 - Data: 50 + Data: 55 - Name: k__BackingField Entry: 7 Data: System.Nullable`1[[UdonSharp.UdonSyncMode, UdonSharp.Runtime]], mscorlib @@ -1012,13 +1114,13 @@ MonoBehaviour: Data: true - Name: _fieldAttributes Entry: 7 - Data: 51|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib + Data: 56|System.Collections.Generic.List`1[[System.Attribute, mscorlib]], mscorlib - Name: Entry: 12 Data: 1 - Name: Entry: 7 - Data: 52|UnityEngine.SerializeField, UnityEngine.CoreModule + Data: 57|UnityEngine.SerializeField, UnityEngine.CoreModule - Name: Entry: 8 Data: diff --git a/Assets/Scripts/NetworkManager.cs b/Assets/Scripts/NetworkManager.cs index 1099301..c559397 100644 --- a/Assets/Scripts/NetworkManager.cs +++ b/Assets/Scripts/NetworkManager.cs @@ -1,25 +1,20 @@ -using Cysharp.Threading.Tasks.Triggers; -using JetBrains.Annotations; -using System; -using System.Drawing; -using System.Linq; +using System; using System.Reflection; using System.Text; using TMPro; using UdonSharp; using UnityEngine; -using UnityEngine.UI; using VRC.SDK3.UdonNetworkCalling; using VRC.SDKBase; -using VRC.Udon.ClientBindings.Interfaces; using VRC.Udon.Common; namespace Marro.PacManUdon { public enum NetworkEventType { - FullSync = 0, - PacManTurn = 1, + FullSyncForced = 0, + FullSync = 1, + PacManTurn = 2, } public class NetworkManager : UdonSharpBehaviour @@ -76,6 +71,10 @@ namespace Marro.PacManUdon /// The delay at which the receiving side replays events. /// private const float Delay = 1f; + /// + /// The maximum amount of times a message is sent + /// + private const int MaxEventSendTries = 3; #endregion #region Private attributes @@ -98,33 +97,47 @@ namespace Marro.PacManUdon /// private float nextEventTime; - /// - /// The timestamp of the most recent event created or received. - /// - private float lastEventTimestamp; - /// - /// The message id of the most recent event created or received. - /// - private byte lastEventId; - /// /// Amounot of retries in a row without a successful sync. /// private int retriesWithoutSuccess; /// - /// True if there is a full sync in the queue and we are not currently synced. + /// For receiver: True if there's a full sync in the queue and we are not synced, otherwise false. + /// For transmitter: True if there's a full sync in the queue which has not yet been transmitted, otherwise false. /// - private bool fullSyncInQueue; + private bool hasFullSyncReady; + /// + /// True if serialization has been requestsed + /// + private bool serializationRequested; /// - /// Main buffer of data to be transmitted or processed + /// Queue of events to be transmitted or processed /// - private byte[][] buffer; + private byte[][] eventsQueue; /// - /// Index of . + /// Index of . /// - private int bufferIndex; + private int eventsQueueIndex; + + /// + /// The value of at the last transmission + /// + private int eventsQueueIndexAtLastTransmission; + /// + /// Counts of new events at recent transmissions + /// + private int[] eventTransmissionHistory; + /// + /// Index of + /// + private int eventTransmissionHistoryIndex; + + /// + /// The message id of the most recent event created or received. + /// + private byte lastEventId; /// /// Data which is currently available on the network. @@ -184,13 +197,11 @@ namespace Marro.PacManUdon SetOwner(Networking.IsOwner(gameObject)); - buffer = new byte[BufferMaxTotalEvents][]; - bufferIndex = 0; + ClearBuffer(); + Synced = IsOwner; // Owner is always synced retriesWithoutSuccess = 0; - lastEventTimestamp = 0; - lastEventId = 0; - fullSyncInQueue = false; + hasFullSyncReady = false; offsetTime = Time.fixedTime; internalTime = 0; @@ -259,7 +270,7 @@ namespace Marro.PacManUdon } else { - SendEvent(NetworkEventType.FullSync); + SendEvent(NetworkEventType.FullSyncForced); } } @@ -291,7 +302,7 @@ namespace Marro.PacManUdon var timestamp = SyncedTime; var eventId = GetNextEventId(lastEventId); - + InitializeEvent(eventType, timestamp, eventId, BufferMaxTotalEvents, out byte[][] data, out var index); foreach (var obj in syncedObjects) @@ -299,8 +310,6 @@ namespace Marro.PacManUdon obj.AppendSyncedData(data, ref index, eventType); } - var oldIndex = this.bufferIndex; - var result = Flatten(data, 0, index); // Validate and fill in event size @@ -316,13 +325,17 @@ namespace Marro.PacManUdon var eventSizeBytes = BitConverter.GetBytes((ushort)eventSize); Array.Copy(eventSizeBytes, 0, result, HeaderEventSizeIndex, eventSizeBytes.Length); + if (IsFullSync(eventType)) + { + hasFullSyncReady = true; + } + QueueEventInBuffer(result); - Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Prepared event with {eventSize} bytes and timestamp {timestamp} for serialization, index went from {oldIndex} to {this.bufferIndex}"); + Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Prepared event with {eventSize} bytes and timestamp {timestamp} for serialization, index is now {this.eventsQueueIndex}"); - RequestSerialization(); + RequestSerializationForEvents(); - lastEventTimestamp = timestamp; lastEventId = eventId; retriesWithoutSuccess = 0; // We had success! @@ -346,6 +359,12 @@ namespace Marro.PacManUdon index = 1; } + private void RequestSerializationForEvents() + { + RequestSerialization(); + serializationRequested = true; + } + [NetworkCallable] public void RequestEventReceived(NetworkEventType eventType) { @@ -354,8 +373,65 @@ namespace Marro.PacManUdon return; } + if (IsFullSync(eventType) && hasFullSyncReady) + { + return; // Don't send another full sync if we're already preparing to send one + } + + if (eventType == NetworkEventType.FullSyncForced) + { + SendEvent(NetworkEventType.FullSync); // Remote is not allowed to request a forced full sync + } + SendEvent(eventType); } + + public override void OnPreSerialization() + { + if (!Ready || !IsOwner || !serializationRequested || eventsQueue == null || eventsQueueIndex == 0) + { + return; + } + + networkedData = Flatten(eventsQueue, 0, eventsQueueIndex); + + eventTransmissionHistory[eventTransmissionHistoryIndex] = eventsQueueIndex - eventsQueueIndexAtLastTransmission; + eventTransmissionHistoryIndex += 1; + if (eventTransmissionHistoryIndex >= eventTransmissionHistory.Length) + { + eventTransmissionHistoryIndex = 0; + } + + serializationRequested = false; + + Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Serializing {eventsQueueIndex} event(s), eventTransmissionHistory is now {ArrayToString(eventTransmissionHistory)} with index {eventTransmissionHistoryIndex}"); + } + + public override void OnPostSerialization(SerializationResult result) + { + if (!Ready || !IsOwner || networkedData.Length == 0) + { + return; + } + + if (!result.success) + { + Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Serialization failed! Tried to send {result.byteCount} bytes."); + return; + } + + Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Serialized with {networkedData.Length} bytes.\nBytes sent:\n{ArrayToString(networkedData)}"); + + // Remove data from the buffer that no longer needs to be (re)transmitted + DequeueEventsFromBuffer(eventTransmissionHistory[eventTransmissionHistoryIndex]); + eventTransmissionHistory[eventTransmissionHistoryIndex] = 0; // Prevent trying to remove the same events again + eventsQueueIndexAtLastTransmission = eventsQueueIndex; + + networkedData = new byte[0]; + + // If there was a full sync in the queue, it has now been transmitted at least once + hasFullSyncReady = false; + } #endregion #region Receiver @@ -382,20 +458,13 @@ namespace Marro.PacManUdon return; // Nothing to store } - Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received {networkedData.Length} bytes!\nBytes received:\n{BytesToString(networkedData)}"); + Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Received {networkedData.Length} bytes!\nBytes received:\n{ArrayToString(networkedData)}"); var length = networkedData.Length; int index = 0; int eventSize = 0; // Store event size here so we can increment the index no matter how we increment the loop - while (true) + while ((index += eventSize) < length) { - index += eventSize; - - if (index >= length) - { - break; - } - if (length - index < HeaderLength) { Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) {nameof(StoreIncomingData)}: Remaining data in networkedData is not long enough to form a complete event! remaining: {length - index}."); @@ -421,38 +490,39 @@ namespace Marro.PacManUdon var @event = GetArrayPart(networkedData, index, eventSize); - var eventType = GetEventTypeFromHeader(@event); var timestamp = GetTimestampFromHeader(@event); var eventId = GetEventIdFromHeader(@event); - if (Synced || fullSyncInQueue) + if (Synced || hasFullSyncReady) { - if (timestamp == lastEventTimestamp - && eventId == lastEventId) + if (eventId != GetNextEventId(lastEventId)) { - Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Duplicate message of type {eventType}, timestamp: {timestamp}, messageId: {eventId}."); + if (index + eventSize >= length // If this is the last event of the batch + && eventId != lastEventId) // Unless the eventId is the same, then this is probably just a duplicate + { + // The last event of the batch has to be synced up with our current event id count, else we've missed an event + Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) EventIds were not sequential! Did we miss a serialization? Timestamp: {timestamp}, eventId: {eventId}, lastEventId: {lastEventId}."); + HandleError(false); + return; + } + + // We've likely already processed this event, ignore it continue; } - if (eventId != GetNextEventId(lastEventId)) - { - Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) EventIds were not sequential! Did we miss a serialization? Timestamp: {timestamp}, eventId: {eventId}, lastEventId: {lastEventId}."); - HandleError(false); - return; - } - QueueEventInBuffer(@event); + + Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)} Queued event with id {eventId}"); } else { // If we're not yet synced, we only care about full sync events. - if (eventType == NetworkEventType.FullSync) + if (IsFullSync(GetEventTypeFromHeader(@event))) { - QueueFullSyncInBuffer(@event); // Immediately process full sync + QueueFullSyncForReplay(@event); // Immediately process full sync } } - lastEventTimestamp = timestamp; lastEventId = eventId; } @@ -462,19 +532,16 @@ namespace Marro.PacManUdon } } - private void QueueFullSyncInBuffer(byte[] @event) + private void QueueFullSyncForReplay(byte[] @event) { - // Intentionally not doing a buffer size check here, since this is not appended to the buffer - // (and there is no good way to continue if this event is too large) - // Clear buffer and put the full sync into it ClearBuffer(); QueueEventInBuffer(@event); // Set this event to play after the default delay - nextEventTime = internalTime + Delay; + nextEventTime = internalTime + Delay; - fullSyncInQueue = true; + hasFullSyncReady = true; Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Queued full sync in buffer, should execute at {nextEventTime}."); } @@ -483,22 +550,30 @@ namespace Marro.PacManUdon { IsEventUpdate = true; - while (bufferIndex != 0 && nextEventTime <= internalTime) + while (eventsQueueIndex > 0 && nextEventTime <= internalTime) { - PerformEvent(buffer[0]); + var success = PerformEvent(eventsQueue[0]); + + if (!success) + { + return; + } + DequeueEventsFromBuffer(1); UpdateNextEventTime(); } } - private void PerformEvent(byte[] @event) + private bool PerformEvent(byte[] @event) { var timestamp = GetTimestampFromHeader(@event); var eventType = GetEventTypeFromHeader(@event); - if (eventType == NetworkEventType.FullSync) + var isFullSync = IsFullSync(eventType); + + if (!Synced || eventType == NetworkEventType.FullSyncForced) { - SyncToTimestamp(timestamp, GetEventIdFromHeader(@event)); + SyncToTimestamp(timestamp); } var index = (int)HeaderLength; // Skip header @@ -518,7 +593,7 @@ namespace Marro.PacManUdon { Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Malformed data reported by {obj.name} during event type {eventType}!"); HandleError(true); - return; + return false; } } @@ -527,49 +602,69 @@ namespace Marro.PacManUdon { Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Amount of data read does not match event size! Expected {eventSize}, read {index}."); HandleError(true); - return; + return false; } - if (!Synced && eventType == NetworkEventType.FullSync) + if (!Synced && isFullSync) { - fullSyncInQueue = false; + hasFullSyncReady = false; Synced = true; } Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Processed incoming event! Total {index} bytes."); retriesWithoutSuccess = 0; // We had success! + + return true; + } + + public override void OnDeserialization() + { + if (!Ready || IsOwner) + { + return; + } + + StoreIncomingData(); } #endregion #region Buffer private void ClearBuffer() { - buffer = new byte[BufferMaxTotalEvents][]; - bufferIndex = 0; + eventsQueue = new byte[BufferMaxTotalEvents][]; + eventsQueueIndex = 0; + eventTransmissionHistory = new int[MaxEventSendTries]; + eventTransmissionHistoryIndex = 0; + eventsQueueIndexAtLastTransmission = 0; + lastEventId = 0; } private void DequeueEventsFromBuffer(int eventCount) { - var oldBuffer = buffer; - bufferIndex -= eventCount; - buffer = new byte[BufferMaxTotalEvents][]; - Array.Copy(oldBuffer, eventCount, buffer, 0, bufferIndex); + if (eventCount > eventsQueueIndex) // Never remove more events than are in the queue + { + eventCount = eventsQueueIndex; + } + + var oldBuffer = eventsQueue; + eventsQueueIndex -= eventCount; + eventsQueue = new byte[BufferMaxTotalEvents][]; + Array.Copy(oldBuffer, eventCount, eventsQueue, 0, eventsQueueIndex); } private bool QueueEventInBuffer(byte[] @event) { - if (bufferIndex >= BufferMaxTotalEvents) + if (eventsQueueIndex >= BufferMaxTotalEvents) { Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Buffer not large enough to store event! Maximum event count: {BufferMaxTotalEvents}."); HandleError(true); return false; } - buffer[bufferIndex++] = @event; + eventsQueue[eventsQueueIndex++] = @event; return true; } - #endregion #region Time @@ -586,7 +681,7 @@ namespace Marro.PacManUdon SyncedTime = newTime; } - private void SyncToTimestamp(float timestamp, byte eventId) + private void SyncToTimestamp(float timestamp) { var oldOffset = offsetTime; offsetTime = Time.fixedTime - timestamp; @@ -596,20 +691,17 @@ namespace Marro.PacManUdon SyncedTime -= delta; nextEventTime -= delta; - lastEventTimestamp = timestamp; - lastEventId = eventId; - Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Synced to timestamp {timestamp}, current time is {Time.fixedTime}, offsetTime is now {offsetTime}, internalTime is now {internalTime}, SyncedTime is now {SyncedTime}, nextEventTime is now {nextEventTime}"); } private void UpdateNextEventTime() { - if (bufferIndex == 0) + if (eventsQueueIndex == 0) { return; } - var nextEventTime = GetTimestampFromHeader(buffer[0]); + var nextEventTime = GetTimestampFromHeader(eventsQueue[0]); if (nextEventTime >= this.nextEventTime) { this.nextEventTime = nextEventTime; @@ -636,6 +728,9 @@ namespace Marro.PacManUdon return currentEventId; } + private static bool IsFullSync(NetworkEventType eventType) + => eventType == NetworkEventType.FullSync || eventType == NetworkEventType.FullSyncForced; + private static ushort GetEventSizeFromHeader(byte[] @event, int eventIndex = 0) => BitConverter.ToUInt16(@event, eventIndex + HeaderEventSizeIndex); @@ -659,77 +754,28 @@ namespace Marro.PacManUdon SetOwner(newOwner == Networking.LocalPlayer); } - - private int indexAtLastSerialization = 0; - - public override void OnPreSerialization() - { - if (!Ready) - { - return; - } - - if (IsOwner) - { - if (buffer == null || bufferIndex == 0) - { - return; - } - - networkedData = Flatten(buffer, 0, bufferIndex); - indexAtLastSerialization = bufferIndex; - } - else - { - networkedData = new byte[0]; // Prevent exception loop in VRChat SDK - } - } - - public override void OnPostSerialization(SerializationResult result) - { - if (!Ready) - { - return; - } - - if (!result.success) - { - Debug.LogWarning($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Serialization failed! Tried to send {result.byteCount} bytes."); - return; - } - - if (!IsOwner || networkedData.Length == 0) - { - return; - } - - Debug.Log($"({nameof(PacManUdon)} {nameof(NetworkManager)}) Serialized with {networkedData.Length} bytes!\nBytes sent:\n{BytesToString(networkedData)}"); - - // Remove all transferred data from the buffer, leaving data that came in after serialization - DequeueEventsFromBuffer(indexAtLastSerialization); - networkedData = new byte[0]; - } - - public override void OnDeserialization() - { - if (!Ready || IsOwner) - { - return; - } - - StoreIncomingData(); - } #endregion #region Utils - public string BytesToString(byte[] bytes) + public string ArrayToString(byte[] bytes) { - var sb = new StringBuilder("new byte[] { "); + var sb = new StringBuilder("[ "); foreach (var b in bytes) { - sb.Append(b + ", "); + sb.Append(b + " "); } - sb.Append("}"); + sb.Append("]"); + return sb.ToString(); + } + + public string ArrayToString(int[] bytes) + { + var sb = new StringBuilder("[ "); + foreach (var b in bytes) + { + sb.Append(b + " "); + } + sb.Append("]"); return sb.ToString(); } @@ -774,7 +820,7 @@ namespace Marro.PacManUdon #region Debug public void SimulateSyncToTimestamp(float timestamp) { - SyncToTimestamp(timestamp, 0); + SyncToTimestamp(timestamp); } public void WriteDebugOutput(TMP_InputField debugOutput) @@ -783,12 +829,15 @@ namespace Marro.PacManUdon $"IsOwner: {IsOwner}\n" + $"Ready: {Ready}\n" + $"Synced: {Synced}\n" + - $"fullSyncInQueue: {fullSyncInQueue}\n" + + $"hasFullSyncReady: {hasFullSyncReady}\n" + + $"lastEventId: {lastEventId}" + $"Time.fixedTime: {Time.fixedTime}\n" + $"offsetTime: {offsetTime}\n" + $"internalTime: {internalTime}\n" + $"SyncedTime: {SyncedTime}\n" + $"Dt: {Dt}\n" + + $"BufferIndex: {eventsQueueIndex}\n" + + $"BufferIndexHistory: {ArrayToString(eventTransmissionHistory)}\n" + $"\n"; } diff --git a/Assets/Test stuff/TestBall.cs b/Assets/Test stuff/TestBall.cs index 5043834..dc5e0b5 100644 --- a/Assets/Test stuff/TestBall.cs +++ b/Assets/Test stuff/TestBall.cs @@ -132,7 +132,8 @@ public class TestBall : SyncedObject public override void AppendSyncedData(byte[][] data, ref int index, NetworkEventType eventType) { - if (eventType == 0) + if (eventType == NetworkEventType.FullSync + || eventType == NetworkEventType.FullSyncForced) { Debug.Log($"({nameof(TestBall)}) Sending sync data at progress {GetProgress()} and amountUp {amountUp}."); data[index++] = BitConverter.GetBytes(amountUp); @@ -142,18 +143,19 @@ public class TestBall : SyncedObject public override bool SetSyncedData(byte[] data, ref int index, NetworkEventType eventType) { - if (eventType == 0) + if (eventType == NetworkEventType.FullSync + || eventType == NetworkEventType.FullSyncForced) { amountUp = BitConverter.ToSingle(data, index); SetProgress(BitConverter.ToSingle(data, index + 4)); - Debug.Log($"({nameof(TestBall)}) Received sync event, synced to progress {GetProgress()} and amountUp {amountUp}."); + //Debug.Log($"({nameof(TestBall)}) Received sync event, synced to progress {GetProgress()} and amountUp {amountUp}."); index += 8; } else { - Debug.Log($"({nameof(TestBall)}) Received up event, jumped up at {GetProgress()} from {amountUp}."); + //Debug.Log($"({nameof(TestBall)}) Received up event, jumped up at {GetProgress()} from {amountUp}."); Jump(); - Debug.Log($"({nameof(TestBall)}) Received up event, jumped up at {GetProgress()} to {amountUp}."); + //Debug.Log($"({nameof(TestBall)}) Received up event, jumped up at {GetProgress()} to {amountUp}."); } return true; diff --git a/Assets/Test stuff/TestBallManager.cs b/Assets/Test stuff/TestBallManager.cs index e031823..4c2fb49 100644 --- a/Assets/Test stuff/TestBallManager.cs +++ b/Assets/Test stuff/TestBallManager.cs @@ -49,7 +49,7 @@ public class TestBallManager : UdonSharpBehaviour testBall.UpButtonPressed(); } - networkManager.SendEvent((NetworkEventType)1); + networkManager.SendEvent(NetworkEventType.PacManTurn); } public void SyncButtonPressed()