diff --git a/MLAPI/Data/NetworkConfig.cs b/MLAPI/Data/NetworkConfig.cs index 0a27b63..c49b806 100644 --- a/MLAPI/Data/NetworkConfig.cs +++ b/MLAPI/Data/NetworkConfig.cs @@ -135,6 +135,10 @@ namespace MLAPI.Data /// Wheter or not to enable scene switching /// public bool EnableSceneSwitching = true; + /// + /// If your logic uses the NetwokrTime, this should probably be turned off. If however it's needed to maximize accuracy, this is recommended to be turned on + /// + public bool EnableTimeResync = false; private byte[] ConfigHash = null; /// diff --git a/MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs b/MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs index 523b2a3..4d97a46 100644 --- a/MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs +++ b/MLAPI/MonoBehaviours/Core/NetworkedBehaviour.cs @@ -460,7 +460,7 @@ namespace MLAPI.MonoBehaviours.Core if (!syncVarInit) SyncVarInit(); SetDirtyness(); - if(Time.time - lastSyncTime >= SyncVarSyncDelay) + if(NetworkingManager.singleton.NetworkTime - lastSyncTime >= SyncVarSyncDelay) { byte dirtyCount = 0; for (byte i = 0; i < dirtyFields.Length; i++) @@ -557,7 +557,7 @@ namespace MLAPI.MonoBehaviours.Core } NetworkingManager.singleton.Send("MLAPI_SYNC_VAR_UPDATE", "MLAPI_INTERNAL", stream.ToArray()); } - lastSyncTime = Time.time; + lastSyncTime = NetworkingManager.singleton.NetworkTime; } } diff --git a/MLAPI/MonoBehaviours/Core/NetworkingManager.cs b/MLAPI/MonoBehaviours/Core/NetworkingManager.cs index 021640c..16a1753 100644 --- a/MLAPI/MonoBehaviours/Core/NetworkingManager.cs +++ b/MLAPI/MonoBehaviours/Core/NetworkingManager.cs @@ -311,6 +311,11 @@ namespace MLAPI.MonoBehaviours.Core { Name = "MLAPI_NAV_AGENT_CORRECTION", Type = QosType.StateUpdate + }, + new Channel() + { + Name = "MLAPI_TIME_SYNC", + Type = QosType.Unreliable } }; @@ -361,6 +366,7 @@ namespace MLAPI.MonoBehaviours.Core MessageManager.messageTypes.Add("MLAPI_CHANGE_OWNER", 8); MessageManager.messageTypes.Add("MLAPI_SYNC_VAR_UPDATE", 9); MessageManager.messageTypes.Add("MLAPI_ADD_OBJECTS", 10); + MessageManager.messageTypes.Add("MLAPI_TIME_SYNC", 11); List messageTypes = new List(NetworkConfig.MessageTypes) { @@ -656,11 +662,12 @@ namespace MLAPI.MonoBehaviours.Core private float lastReceiveTickTime; private float lastSendTickTime; private float lastEventTickTime; + private float lastTimeSyncTime; private void Update() { if(isListening) { - if((Time.time - lastSendTickTime >= (1f / NetworkConfig.SendTickrate)) || NetworkConfig.SendTickrate <= 0) + if((NetworkTime - lastSendTickTime >= (1f / NetworkConfig.SendTickrate)) || NetworkConfig.SendTickrate <= 0) { foreach (KeyValuePair pair in connectedClients) { @@ -671,9 +678,9 @@ namespace MLAPI.MonoBehaviours.Core byte error; NetworkTransport.SendQueuedMessages(netId.HostId, netId.ConnectionId, out error); } - lastSendTickTime = Time.time; + lastSendTickTime = NetworkTime; } - if((Time.time - lastReceiveTickTime >= (1f / NetworkConfig.ReceiveTickrate)) || NetworkConfig.ReceiveTickrate <= 0) + if((NetworkTime - lastReceiveTickTime >= (1f / NetworkConfig.ReceiveTickrate)) || NetworkConfig.ReceiveTickrate <= 0) { NetworkEventType eventType; int processedEvents = 0; @@ -766,23 +773,31 @@ namespace MLAPI.MonoBehaviours.Core } // Only do another iteration if: there are no more messages AND (there is no limit to max events or we have processed less than the maximum) } while (eventType != NetworkEventType.Nothing && (NetworkConfig.MaxReceiveEventsPerTickRate <= 0 || processedEvents < NetworkConfig.MaxReceiveEventsPerTickRate)); - lastReceiveTickTime = Time.time; + lastReceiveTickTime = NetworkTime; } - if (isServer && ((Time.time - lastEventTickTime >= (1f / NetworkConfig.EventTickrate)) || NetworkConfig.EventTickrate <= 0)) + + if (isServer && ((NetworkTime - lastEventTickTime >= (1f / NetworkConfig.EventTickrate)) || NetworkConfig.EventTickrate <= 0)) { LagCompensationManager.AddFrames(); NetworkedObject.InvokeSyncvarUpdate(); - lastEventTickTime = Time.time; + lastEventTickTime = NetworkTime; } + + if (NetworkConfig.EnableTimeResync && NetworkTime - lastTimeSyncTime >= 30) + { + SyncTime(); + lastTimeSyncTime = NetworkTime; + } + networkTime += Time.deltaTime; } } private IEnumerator ApprovalTimeout(uint clientId) { - float timeStarted = Time.time; + float timeStarted = NetworkTime; //We yield every frame incase a pending client disconnects and someone else gets its connection id - while (Time.time - timeStarted < NetworkConfig.ClientConnectionBufferTimeout && pendingClients.Contains(clientId)) + while (NetworkTime - timeStarted < NetworkConfig.ClientConnectionBufferTimeout && pendingClients.Contains(clientId)) { yield return null; } @@ -1335,6 +1350,26 @@ namespace MLAPI.MonoBehaviours.Core } } + break; + case 11: + if (isClient) + { + using (MemoryStream messageReadStream = new MemoryStream(incommingData)) + { + using (BinaryReader messageReader = new BinaryReader(messageReadStream)) + { + float netTime = messageReader.ReadSingle(); + int timestamp = messageReader.ReadInt32(); + + NetId netId = new NetId(clientId); + byte error; + int msDelay = NetworkTransport.GetRemoteDelayTimeMS(netId.HostId, netId.ConnectionId, timestamp, out error); + if ((NetworkError)error != NetworkError.Ok) + msDelay = 0; + networkTime = netTime + (msDelay / 1000f); + } + } + } break; } #endregion @@ -1725,6 +1760,24 @@ namespace MLAPI.MonoBehaviours.Core } } + private void SyncTime() + { + using (MemoryStream stream = new MemoryStream(8)) + { + using (BinaryWriter writer = new BinaryWriter(stream)) + { + writer.Write(NetworkTime); + int timestamp = NetworkTransport.GetNetworkTimestamp(); + writer.Write(timestamp); + } + + foreach (KeyValuePair pair in connectedClients) + { + Send("MLAPI_TIME_SYNC", "MLAPI_TIME_SYNC", stream.GetBuffer()); + } + } + } + private void HandleApproval(uint clientId, bool approved) { if(approved) diff --git a/MLAPI/MonoBehaviours/Core/TrackedObject.cs b/MLAPI/MonoBehaviours/Core/TrackedObject.cs index eecb992..716c2d5 100644 --- a/MLAPI/MonoBehaviours/Core/TrackedObject.cs +++ b/MLAPI/MonoBehaviours/Core/TrackedObject.cs @@ -48,7 +48,7 @@ namespace MLAPI.MonoBehaviours.Core { savedPosition = transform.position; savedRotation = transform.rotation; - float currentTime = Time.time; + float currentTime = NetworkingManager.singleton.NetworkTime; float targetTime = currentTime - secondsAgo; float previousTime = 0; float nextTime = 0; @@ -97,7 +97,7 @@ namespace MLAPI.MonoBehaviours.Core internal void AddFrame() { - float currentTime = Time.time; + float currentTime = NetworkingManager.singleton.NetworkTime; LinkedListNode node = Framekeys.First; LinkedListNode nextNode = node.Next; while (node != null && currentTime - node.Value >= NetworkingManager.singleton.NetworkConfig.SecondsHistory) @@ -107,12 +107,12 @@ namespace MLAPI.MonoBehaviours.Core Framekeys.RemoveFirst(); node = nextNode; } - FrameData.Add(Time.time, new TrackedPointData() + FrameData.Add(NetworkingManager.singleton.NetworkTime, new TrackedPointData() { position = transform.position, rotation = transform.rotation }); - Framekeys.AddLast(Time.time); + Framekeys.AddLast(NetworkingManager.singleton.NetworkTime); } } } diff --git a/MLAPI/MonoBehaviours/Prototyping/NetworkedAnimator.cs b/MLAPI/MonoBehaviours/Prototyping/NetworkedAnimator.cs index c968874..049e850 100644 --- a/MLAPI/MonoBehaviours/Prototyping/NetworkedAnimator.cs +++ b/MLAPI/MonoBehaviours/Prototyping/NetworkedAnimator.cs @@ -193,9 +193,9 @@ namespace MLAPI.MonoBehaviours.Prototyping private void CheckSendRate() { - if (sendMessagesAllowed && sendRate != 0 && sendTimer < Time.time) + if (sendMessagesAllowed && sendRate != 0 && sendTimer < NetworkingManager.singleton.NetworkTime) { - sendTimer = Time.time + sendRate; + sendTimer = NetworkingManager.singleton.NetworkTime + sendRate; using(MemoryStream stream = new MemoryStream()) { diff --git a/MLAPI/MonoBehaviours/Prototyping/NetworkedNavMeshAgent.cs b/MLAPI/MonoBehaviours/Prototyping/NetworkedNavMeshAgent.cs index 2958bc9..8fb2856 100644 --- a/MLAPI/MonoBehaviours/Prototyping/NetworkedNavMeshAgent.cs +++ b/MLAPI/MonoBehaviours/Prototyping/NetworkedNavMeshAgent.cs @@ -100,7 +100,7 @@ namespace MLAPI.MonoBehaviours.Prototyping } } - if(Time.time - lastCorrectionTime >= CorrectionDelay) + if(NetworkingManager.singleton.NetworkTime - lastCorrectionTime >= CorrectionDelay) { using (MemoryStream stream = new MemoryStream(correctionBuffer)) { @@ -130,7 +130,7 @@ namespace MLAPI.MonoBehaviours.Prototyping SendToClientsTarget(proximityClients, "MLAPI_OnNavMeshCorrectionUpdate", "MLAPI_NAV_AGENT_CORRECTION", correctionBuffer); } } - lastCorrectionTime = Time.time; + lastCorrectionTime = NetworkingManager.singleton.NetworkTime; } } diff --git a/MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs b/MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs index c453572..e6f2458 100644 --- a/MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs +++ b/MLAPI/MonoBehaviours/Prototyping/NetworkedTransform.cs @@ -101,9 +101,9 @@ namespace MLAPI.MonoBehaviours.Prototyping if(isOwner || isLocalPlayer || (new NetId(ownerClientId).IsInvalid() && isServer)) { //We own the object OR we are server and the object is not owned by anyone OR we are the object. - if(Time.time - lastSendTime >= timeForLerp && (Vector3.Distance(transform.position, lastSentPos) > MinMeters || Quaternion.Angle(transform.rotation, lastSentRot) > MinDegrees)) + if(NetworkingManager.singleton.NetworkTime - lastSendTime >= timeForLerp && (Vector3.Distance(transform.position, lastSentPos) > MinMeters || Quaternion.Angle(transform.rotation, lastSentRot) > MinDegrees)) { - lastSendTime = Time.time; + lastSendTime = NetworkingManager.singleton.NetworkTime; lastSentPos = transform.position; lastSentRot = transform.rotation; using (MemoryStream writeStream = new MemoryStream(positionUpdateBuffer))