mirror of
https://github.com/Dadechin/Unity-WebSocket.git
synced 2025-07-03 20:04:33 +00:00
217 lines
7.7 KiB
C#
217 lines
7.7 KiB
C#
using System.Runtime.CompilerServices;
|
|
|
|
namespace FishNet.Managing.Timing
|
|
{
|
|
public class EstimatedTick
|
|
{
|
|
#region Types.
|
|
/// <summary>
|
|
/// How to handle old ticks, specifically related to EstimatedTick.
|
|
/// </summary>
|
|
public enum OldTickOption : byte
|
|
{
|
|
/// <summary>
|
|
/// Completely ignore old ticks.
|
|
/// </summary>
|
|
Discard = 0,
|
|
/// <summary>
|
|
/// Set LastRemoteTick but do not update RemoteTick.
|
|
/// </summary>
|
|
SetLastRemoteTick = 1,
|
|
/// <summary>
|
|
/// Set LastRemoteTick and RemoteTick.
|
|
/// </summary>
|
|
SetRemoteTick = 2,
|
|
}
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Local tick when this was last updated.
|
|
/// </summary>
|
|
public uint LocalTick { get; private set; } = TimeManager.UNSET_TICK;
|
|
/// <summary>
|
|
/// Last remote tick this was updated with that was not out of order or a duplicate.
|
|
/// </summary>
|
|
public uint RemoteTick { get; private set; } = TimeManager.UNSET_TICK;
|
|
/// <summary>
|
|
/// Last remote tick received regardless if it was out of order or a duplicate.
|
|
/// </summary>
|
|
public uint LastRemoteTick { get; private set; } = TimeManager.UNSET_TICK;
|
|
/// <summary>
|
|
/// True if LastRemoteTick is equal to RemoteTick.
|
|
/// This would indicate that the LastRemoteTick did not arrive out of order.
|
|
/// </summary>
|
|
public bool IsLastRemoteTickOrdered => (LastRemoteTick == RemoteTick);
|
|
/// <summary>
|
|
/// True if value is unset.
|
|
/// </summary>
|
|
//Only need to check one value for unset as they all would be if not set.
|
|
public bool IsUnset => (LocalTick == TimeManager.UNSET_TICK);
|
|
/// <summary>
|
|
/// Last TimeManager specified during an Update call.
|
|
/// </summary>
|
|
private TimeManager _updateTimeManager;
|
|
/// <summary>
|
|
/// LocalTick when Value was last reset.
|
|
/// </summary>
|
|
private uint _valueLocalTick = TimeManager.UNSET_TICK;
|
|
|
|
|
|
/// <summary>
|
|
/// Number of ticks LocalTick is being current LocalTick.
|
|
/// </summary>
|
|
public uint LocalTickDifference(TimeManager tm = null)
|
|
{
|
|
if (!TryAssignTimeManager(ref tm))
|
|
return TimeManager.UNSET_TICK;
|
|
|
|
long value = (tm.LocalTick - LocalTick);
|
|
//Shouldn't be possible to be less than 0.
|
|
if (value < 0)
|
|
return TimeManager.UNSET_TICK;
|
|
else if (value > uint.MaxValue)
|
|
value = uint.MaxValue;
|
|
|
|
return (uint)value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// True if values were updated this tick.
|
|
/// </summary>
|
|
public bool IsCurrent(TimeManager tm = null)
|
|
{
|
|
if (!TryAssignTimeManager(ref tm))
|
|
return false;
|
|
|
|
return (!IsUnset && LocalTick == tm.LocalTick);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Current estimated value.
|
|
/// </summary>
|
|
/// <param name="nm">NetworkManager to use. When null default value will be returned.</param>
|
|
public uint Value(TimeManager tm = null)
|
|
{
|
|
if (!TryAssignTimeManager(ref tm))
|
|
return TimeManager.UNSET_TICK;
|
|
|
|
return Value(out _, tm);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Current estimated value. Outputs if value is current.
|
|
/// </summary>
|
|
/// <param name="nm">NetworkManager to use. When null default value will be returned.</param>
|
|
/// <param name="isCurrent">True if the value was updated this local tick.</param>
|
|
public uint Value(out bool isCurrent, TimeManager tm = null)
|
|
{
|
|
//Default value.
|
|
isCurrent = false;
|
|
|
|
if (!TryAssignTimeManager(ref tm))
|
|
return TimeManager.UNSET_TICK;
|
|
if (IsUnset)
|
|
return TimeManager.UNSET_TICK;
|
|
|
|
isCurrent = IsCurrent(tm);
|
|
|
|
uint diff = (tm.LocalTick - _valueLocalTick);
|
|
return (diff + RemoteTick);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Initializes this EstimatedTick with values.
|
|
/// </summary>
|
|
public void Initialize(TimeManager tm, uint remoteTick = 0, uint lastRemoteTick = 0, uint localTick = 0)
|
|
{
|
|
_updateTimeManager = tm;
|
|
RemoteTick = remoteTick;
|
|
LastRemoteTick = lastRemoteTick;
|
|
LocalTick = localTick;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates values.
|
|
/// </summary>
|
|
/// <param name="tm">TimeManager to use.</param>
|
|
/// <param name="remoteTick">Remote tick being updated.</param>
|
|
/// <param name="oldTickOption">How to handle remoteTick if it is old.</param>
|
|
/// /// <param name="resetValue">True to reset Value based on this information. False will allow Value to continue to to estimate tick based on the last reset.</param>
|
|
/// <returns>True if was able to update values.</returns>
|
|
public bool Update(TimeManager tm, uint remoteTick, OldTickOption oldTickOption = OldTickOption.Discard, bool resetValue = true)
|
|
{
|
|
_updateTimeManager = tm;
|
|
//Always set LastRemoteTick even if out of order.
|
|
LastRemoteTick = remoteTick;
|
|
//If cannot update with old values return.
|
|
if (oldTickOption != OldTickOption.SetRemoteTick && remoteTick <= RemoteTick)
|
|
return false;
|
|
|
|
//nm is assumed set here.
|
|
LocalTick = tm.LocalTick;
|
|
if (resetValue)
|
|
_valueLocalTick = LocalTick;
|
|
RemoteTick = remoteTick;
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates values.
|
|
/// </summary>
|
|
/// <param name="remoteTick">Remote tick being updated.</param>
|
|
/// <param name="oldTickOption">How to handle remoteTick if it is old.</param>
|
|
/// <param name="resetValue">True to reset Value based on this information. False will allow Value to continue to to estimate tick based on the last reset.</param>
|
|
/// <returns>True if was able to update values.</returns>
|
|
public bool Update(uint remoteTick, OldTickOption oldTickOption = OldTickOption.Discard, bool resetValue = true)
|
|
{
|
|
TimeManager tm = null;
|
|
if (!TryAssignTimeManager(ref tm))
|
|
return false;
|
|
|
|
return Update(tm, remoteTick, oldTickOption);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Updates Value based on current ticks.
|
|
/// This is typically used when you want to control when Value is reset through the Update methods.
|
|
/// </summary>
|
|
public void UpdateValue()
|
|
{
|
|
_valueLocalTick = LocalTick;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Assigns a TimeManager reference to UpdateTimeManager if was null.
|
|
/// </summary>
|
|
/// <returns>True if the reference has value or was assigned value. False if the reference remains null.</returns>
|
|
private bool TryAssignTimeManager(ref TimeManager tm)
|
|
{
|
|
if (tm == null)
|
|
tm = _updateTimeManager;
|
|
|
|
return (tm != null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Resets values to unset and clears the NetworkManager.
|
|
/// </summary>
|
|
public void Reset()
|
|
{
|
|
ResetTicks();
|
|
_updateTimeManager = null;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Resets only tick values, leaving type references.
|
|
/// </summary>
|
|
public void ResetTicks()
|
|
{
|
|
LocalTick = TimeManager.UNSET_TICK;
|
|
RemoteTick = TimeManager.UNSET_TICK;
|
|
LastRemoteTick = TimeManager.UNSET_TICK;
|
|
_valueLocalTick = TimeManager.UNSET_TICK;
|
|
}
|
|
}
|
|
} |