using System.Runtime.CompilerServices;
namespace FishNet.Managing.Timing
{
public struct EstimatedTick
{
///
/// How to handle old ticks, specifically related to EstimatedTick.
///
public enum OldTickOption : byte
{
///
/// Completely ignore old ticks.
///
Discard = 0,
///
/// Set LastRemoteTick but do not update RemoteTick.
///
SetLastRemoteTick = 1,
///
/// Set LastRemoteTick and RemoteTick.
///
SetRemoteTick = 2,
}
///
/// Local tick when this was last updated.
///
public uint LocalTick;
///
/// Last remote tick this was updated with that was not out of order or a duplicate.
///
public uint RemoteTick;
///
/// Last remote tick received regardless if it was out of order or a duplicate.
///
public uint LastRemoteTick;
///
/// True if the value was updated this tick.
///
public bool IsCurrent(TimeManager tm) => (!IsUnset && LocalTick == tm.LocalTick);
///
/// True if value is unset.
///
//Only need to check one value for unset as they all would be if not set.
public bool IsUnset => (LocalTick == 0);
///
/// Number of ticks LocalTick is being current LocalTick.
///
public uint LocalTickDifference(TimeManager tm)
{
long value = (tm.LocalTick - LocalTick);
//Shouldn't be possible to be less than 0.
if (value < 0)
return 0;
else if (value > uint.MaxValue)
value = uint.MaxValue;
return (uint)value;
}
///
/// Updates values.
///
/// NetworkManager to use.
/// Remote tick being updated.
/// True to not update if remote tick is older or equal to the last updated value.
/// True if was able to update values.
public bool Update(TimeManager tm, uint remoteTick, OldTickOption oldTickOption = OldTickOption.Discard)
{
//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;
RemoteTick = remoteTick;
return true;
}
///
/// Current estimated value.
///
/// NetworkManager to use. When null default value will be returned.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint Value(TimeManager tm)
{
return Value(tm, out _);
}
///
/// Current estimated value. Outputs if value is current.
///
/// NetworkManager to use. When null default value will be returned.
/// True if the value was updated this local tick.
public uint Value(TimeManager tm, out bool isCurrent)
{
isCurrent = IsCurrent(tm);
if (tm == null)
return 0;
if (IsUnset)
return 0;
uint diff = (tm.LocalTick - LocalTick);
return (diff + RemoteTick);
}
///
/// Resets values to unset.
///
public void Reset()
{
LocalTick = 0;
RemoteTick = 0;
LastRemoteTick = 0;
}
}
}