Timestamp is now float
This commit is contained in:
@@ -28,8 +28,10 @@ namespace Marro.PacManUdon
|
||||
// If user is not owner, this data is read into the same buffer and replayed based on the included timestamp.
|
||||
// Data replay is delayed with an offset on the timestamp to hide inconsistency in latency.
|
||||
|
||||
// The timestamp is transferred in ms as a 32 bit uint, which gives a maximum time of about 49 days.
|
||||
// The maximum allowed age of a VRChat instance is 7 days, so this should not cause issues.
|
||||
// Each event contains a header. The first part contains the size of the event as a ushort, allowing a maximum size of 65,536 bytes.
|
||||
// After that timestamp is transferred in seconds since the owner started the game as a float, matching Unity's time representation.
|
||||
// Afterwards is a message id, a single byte which increments (with overflow) for every event to confirm data completeness.
|
||||
// Lastly, a single byte indicates the type of event. 0 is a full sync, which is reserved for syncing up from any unknown state.
|
||||
|
||||
// A byte array is used as a DataList or DataDictionary can only be transmitted as JSON which is much less efficient.
|
||||
// As Udon does not support instantiating objects, I have not created classes to represent the data being sent.
|
||||
@@ -37,7 +39,7 @@ namespace Marro.PacManUdon
|
||||
|
||||
// An event has the following structure:
|
||||
// [0-1]: (ushort) Size of event.
|
||||
// [2-5]: (uint) Time in seconds at which event occured.
|
||||
// [2-5]: (float) Time in seconds at which event occured.
|
||||
// [6]: (byte) Message id, increments by one for each message with the same timestamp.
|
||||
// [7]: (byte) Type of event. 0 = Full Sync, which is used to sync up from an undefinted state.
|
||||
// [+]: Event-specific data.
|
||||
@@ -73,14 +75,6 @@ namespace Marro.PacManUdon
|
||||
/// </summary>
|
||||
private const ushort HeaderPartsCount = 4;
|
||||
|
||||
/// <summary>
|
||||
/// The multiplier from Unity time to a timestamp.
|
||||
/// </summary>
|
||||
private const int TimestampMultiplier = 1000;
|
||||
/// <summary>
|
||||
/// The zero value of a timestamp. Anything below this value is negative.
|
||||
/// </summary>
|
||||
private const uint TimestampZeroValue = 10000;
|
||||
/// <summary>
|
||||
/// The delay at which the receiving side replays events.
|
||||
/// </summary>
|
||||
@@ -120,7 +114,7 @@ namespace Marro.PacManUdon
|
||||
/// <summary>
|
||||
/// The timestamp of the most recent event created or received.
|
||||
/// </summary>
|
||||
private uint lastEventTimestamp;
|
||||
private float lastEventTimestamp;
|
||||
/// <summary>
|
||||
/// The message id of the most recent event created or received.
|
||||
/// </summary>
|
||||
@@ -290,7 +284,7 @@ namespace Marro.PacManUdon
|
||||
return;
|
||||
}
|
||||
|
||||
var timestamp = TimeToTimestamp(SyncedTime);
|
||||
var timestamp = SyncedTime;
|
||||
|
||||
var eventId = GetNextEventId(lastEventId);
|
||||
|
||||
@@ -330,7 +324,7 @@ namespace Marro.PacManUdon
|
||||
retriesWithoutSuccess = 0; // We had success!
|
||||
}
|
||||
|
||||
private static void InitializeEvent(NetworkEventType eventType, uint timestamp, byte eventId, int maxSize, out byte[][] data, out int index)
|
||||
private static void InitializeEvent(NetworkEventType eventType, float timestamp, byte eventId, int maxSize, out byte[][] data, out int index)
|
||||
{
|
||||
// Create header
|
||||
var timestampBytes = BitConverter.GetBytes(timestamp);
|
||||
@@ -573,10 +567,10 @@ namespace Marro.PacManUdon
|
||||
SyncedTime = newTime;
|
||||
}
|
||||
|
||||
private void SyncToTimestamp(uint timestamp, byte eventId)
|
||||
private void SyncToTimestamp(float timestamp, byte eventId)
|
||||
{
|
||||
var oldOffset = offsetTime;
|
||||
var timeToSyncTo = TimestampToTime(timestamp) - Delay;
|
||||
var timeToSyncTo = timestamp - Delay;
|
||||
offsetTime = Time.fixedTime - timeToSyncTo;
|
||||
|
||||
var delta = offsetTime - oldOffset;
|
||||
@@ -596,7 +590,7 @@ namespace Marro.PacManUdon
|
||||
return;
|
||||
}
|
||||
|
||||
var nextEventTime = TimestampToTime(GetTimestampFromHeader(NextEvent));
|
||||
var nextEventTime = GetTimestampFromHeader(NextEvent);
|
||||
if (ignoreOrder || nextEventTime >= this.nextEventTime)
|
||||
{
|
||||
this.nextEventTime = nextEventTime;
|
||||
@@ -608,16 +602,6 @@ namespace Marro.PacManUdon
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static uint TimeToTimestamp(float time)
|
||||
{
|
||||
return (uint)((time * TimestampMultiplier) + TimestampZeroValue);
|
||||
}
|
||||
|
||||
public static float TimestampToTime(uint timeStamp)
|
||||
{
|
||||
return (timeStamp - (long)TimestampZeroValue) / (float)TimestampMultiplier; // Use a long here to prevent an underflow
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Header
|
||||
@@ -639,8 +623,8 @@ namespace Marro.PacManUdon
|
||||
public static NetworkEventType GetEventTypeFromHeader(byte[] @event, int eventIndex = 0) =>
|
||||
(NetworkEventType)@event[eventIndex + HeaderEventTypeIndex];
|
||||
|
||||
public static uint GetTimestampFromHeader(byte[] @event, int eventIndex = 0) =>
|
||||
BitConverter.ToUInt32(@event, eventIndex + HeaderTimestampIndex);
|
||||
public static float GetTimestampFromHeader(byte[] @event, int eventIndex = 0) =>
|
||||
BitConverter.ToSingle(@event, eventIndex + HeaderTimestampIndex);
|
||||
|
||||
public static byte GetEventIdFromHeader(byte[] @event, int eventIndex = 0) =>
|
||||
@event[eventIndex + HeaderEventIdIndex];
|
||||
@@ -764,7 +748,7 @@ namespace Marro.PacManUdon
|
||||
#endregion
|
||||
|
||||
#region Debug
|
||||
public void SimulateSyncToTimestamp(uint timestamp)
|
||||
public void SimulateSyncToTimestamp(float timestamp)
|
||||
{
|
||||
SyncToTimestamp(timestamp, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user