mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
Network timing synchronization.
Lidgren NetTime.Now is now synchronized to IGameTiming.RealTime. NetChannel is now a nested class of NetManager. Add IGameTiming.ServerTime, INetChannel.RemoteTimeOffset, INetChannel.RemoteTime
This commit is contained in:
Submodule Lidgren.Network/Lidgren.Network updated: 4a5cedacb2...73554e6061
@@ -52,7 +52,7 @@ namespace Robust.Client.UserInterface.CustomControls
|
||||
|
||||
_contents.Text = $@"Paused: {_gameTiming.Paused}, CurTick: {_gameTiming.CurTick}/{_gameTiming.CurTick-1}, CurServerTick: {_gameState.CurServerTick}, Pred: {_gameTiming.CurTick.Value - _gameState.CurServerTick.Value-1}
|
||||
CurTime: {_gameTiming.CurTime:hh\:mm\:ss\.ff}, RealTime: {_gameTiming.RealTime:hh\:mm\:ss\.ff}, CurFrame: {_gameTiming.CurFrame}
|
||||
TickTimingAdjustment: {_gameTiming.TickTimingAdjustment}";
|
||||
ServerTime: {_gameTiming.ServerTime}, TickTimingAdjustment: {_gameTiming.TickTimingAdjustment}";
|
||||
|
||||
MinimumSizeChanged();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Net;
|
||||
using System;
|
||||
using System.Net;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Robust.Shared.Interfaces.Network
|
||||
@@ -34,6 +35,16 @@ namespace Robust.Shared.Interfaces.Network
|
||||
|
||||
LoginType AuthType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Offset between local RealTime and remote RealTime.
|
||||
/// </summary>
|
||||
TimeSpan RemoteTimeOffset { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Remote RealTime.
|
||||
/// </summary>
|
||||
TimeSpan RemoteTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Average round trip time in milliseconds between the remote peer and us.
|
||||
/// </summary>
|
||||
|
||||
@@ -31,6 +31,15 @@ namespace Robust.Shared.Interfaces.Timing
|
||||
/// </summary>
|
||||
TimeSpan RealTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="RealTime"/> of the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// 0 if we are the client and we are not connected to a server.
|
||||
/// <see cref="RealTime"/> if we are the server.
|
||||
/// </remarks>
|
||||
TimeSpan ServerTime { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The simulated time it took to render the last frame.
|
||||
/// </summary>
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
|
||||
namespace Robust.Shared.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// A network connection from this local peer to a remote peer.
|
||||
/// </summary>
|
||||
internal class NetChannel : INetChannel
|
||||
{
|
||||
private readonly NetManager _manager;
|
||||
private readonly NetConnection _connection;
|
||||
|
||||
/// <inheritdoc />
|
||||
public long ConnectionId => _connection.RemoteUniqueIdentifier;
|
||||
|
||||
/// <inheritdoc />
|
||||
public INetManager NetPeer => _manager;
|
||||
|
||||
public string UserName { get; }
|
||||
public LoginType AuthType { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public short Ping => (short) Math.Round(_connection.AverageRoundtripTime * 1000);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsConnected => _connection.Status == NetConnectionStatus.Connected;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IPEndPoint RemoteEndPoint => _connection.RemoteEndPoint;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes the lidgren connection.
|
||||
/// </summary>
|
||||
public NetConnection Connection => _connection;
|
||||
|
||||
public NetUserId UserId { get; }
|
||||
|
||||
// Only used on server, contains the encryption to use for this channel.
|
||||
public NetEncryption? Encryption { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of a NetChannel.
|
||||
/// </summary>
|
||||
/// <param name="manager">The server this channel belongs to.</param>
|
||||
/// <param name="connection">The raw NetConnection to the remote peer.</param>
|
||||
internal NetChannel(NetManager manager, NetConnection connection, NetUserId userId, string userName, LoginType loginType)
|
||||
{
|
||||
_manager = manager;
|
||||
_connection = connection;
|
||||
UserId = userId;
|
||||
UserName = userName;
|
||||
AuthType = loginType;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public T CreateNetMessage<T>()
|
||||
where T : NetMessage
|
||||
{
|
||||
return _manager.CreateNetMessage<T>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SendMessage(NetMessage message)
|
||||
{
|
||||
if (_manager.IsClient)
|
||||
{
|
||||
_manager.ClientSendMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
_manager.ServerSendMessage(message, this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Disconnect(string reason)
|
||||
{
|
||||
if (_connection.Status == NetConnectionStatus.Connected)
|
||||
_connection.Disconnect(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
87
Robust.Shared/Network/NetManager.NetChannel.cs
Normal file
87
Robust.Shared/Network/NetManager.NetChannel.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Net;
|
||||
using Lidgren.Network;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
|
||||
namespace Robust.Shared.Network
|
||||
{
|
||||
public partial class NetManager
|
||||
{
|
||||
private class NetChannel : INetChannel
|
||||
{
|
||||
private readonly NetManager _manager;
|
||||
private readonly NetConnection _connection;
|
||||
|
||||
/// <inheritdoc />
|
||||
public long ConnectionId => _connection.RemoteUniqueIdentifier;
|
||||
|
||||
/// <inheritdoc />
|
||||
public INetManager NetPeer => _manager;
|
||||
|
||||
public string UserName { get; }
|
||||
public LoginType AuthType { get; }
|
||||
public TimeSpan RemoteTimeOffset => TimeSpan.FromSeconds(_connection.RemoteTimeOffset);
|
||||
public TimeSpan RemoteTime => _manager._timing.RealTime + RemoteTimeOffset;
|
||||
|
||||
/// <inheritdoc />
|
||||
public short Ping => (short) Math.Round(_connection.AverageRoundtripTime * 1000);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsConnected => _connection.Status == NetConnectionStatus.Connected;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IPEndPoint RemoteEndPoint => _connection.RemoteEndPoint;
|
||||
|
||||
/// <summary>
|
||||
/// Exposes the lidgren connection.
|
||||
/// </summary>
|
||||
public NetConnection Connection => _connection;
|
||||
|
||||
public NetUserId UserId { get; }
|
||||
|
||||
// Only used on server, contains the encryption to use for this channel.
|
||||
public NetEncryption? Encryption { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of a NetChannel.
|
||||
/// </summary>
|
||||
/// <param name="manager">The server this channel belongs to.</param>
|
||||
/// <param name="connection">The raw NetConnection to the remote peer.</param>
|
||||
internal NetChannel(NetManager manager, NetConnection connection, NetUserId userId, string userName,
|
||||
LoginType loginType)
|
||||
{
|
||||
_manager = manager;
|
||||
_connection = connection;
|
||||
UserId = userId;
|
||||
UserName = userName;
|
||||
AuthType = loginType;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public T CreateNetMessage<T>()
|
||||
where T : NetMessage
|
||||
{
|
||||
return _manager.CreateNetMessage<T>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void SendMessage(NetMessage message)
|
||||
{
|
||||
if (_manager.IsClient)
|
||||
{
|
||||
_manager.ClientSendMessage(message);
|
||||
return;
|
||||
}
|
||||
|
||||
_manager.ServerSendMessage(message, this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Disconnect(string reason)
|
||||
{
|
||||
if (_connection.Status == NetConnectionStatus.Connected)
|
||||
_connection.Disconnect(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ using Prometheus;
|
||||
using Robust.Shared.Interfaces.Configuration;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Serialization;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Utility;
|
||||
@@ -112,6 +113,7 @@ namespace Robust.Shared.Network
|
||||
|
||||
[Dependency] private readonly IConfigurationManagerInternal _config = default!;
|
||||
[Dependency] private readonly IAuthManager _authManager = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Holds lookup table for NetMessage.Id -> NetMessage.Type
|
||||
@@ -235,6 +237,8 @@ namespace Robust.Shared.Network
|
||||
throw new InvalidOperationException("NetManager has already been initialized.");
|
||||
}
|
||||
|
||||
SynchronizeNetTime();
|
||||
|
||||
IsServer = isServer;
|
||||
|
||||
_config.OnValueChanged(CVars.NetVerbose, NetVerboseChanged);
|
||||
@@ -265,6 +269,24 @@ namespace Robust.Shared.Network
|
||||
}
|
||||
}
|
||||
|
||||
private void SynchronizeNetTime()
|
||||
{
|
||||
// Synchronize Lidgren NetTime with our RealTime.
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
// Try and set this in a loop to avoid any JIT hang fuckery or similar.
|
||||
// Loop until the time is within acceptable margin.
|
||||
// Fixing this "properly" would basically require re-architecturing Lidgren to do DI stuff
|
||||
// so we can more sanely wire these together.
|
||||
NetTime.SetNow(_timing.RealTime.TotalSeconds);
|
||||
var dev = TimeSpan.FromSeconds(NetTime.Now) - _timing.RealTime;
|
||||
|
||||
if (Math.Abs(dev.TotalMilliseconds) < 0.05)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateNetMessageFunctions(MsgStringTableEntries.Entry[] entries)
|
||||
{
|
||||
foreach (var entry in entries)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.Log;
|
||||
|
||||
namespace Robust.Shared.Timing
|
||||
{
|
||||
@@ -20,6 +20,8 @@ namespace Robust.Shared.Timing
|
||||
private readonly List<long> _realFrameTimes = new(NumFrames);
|
||||
private TimeSpan _lastRealTime;
|
||||
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor.
|
||||
/// </summary>
|
||||
@@ -87,6 +89,25 @@ namespace Robust.Shared.Timing
|
||||
/// </summary>
|
||||
public TimeSpan RealTime => _realTimer.Elapsed;
|
||||
|
||||
public TimeSpan ServerTime
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_netManager.IsServer)
|
||||
{
|
||||
return RealTime;
|
||||
}
|
||||
|
||||
var clientNetManager = (IClientNetManager) _netManager;
|
||||
if (clientNetManager.ServerChannel == null)
|
||||
{
|
||||
return TimeSpan.Zero;
|
||||
}
|
||||
|
||||
return clientNetManager.ServerChannel.RemoteTime;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The simulated time it took to render the last frame.
|
||||
/// </summary>
|
||||
|
||||
@@ -5,6 +5,8 @@ using System.Net;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
using Robust.Shared.Interfaces.Timing;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
@@ -14,6 +16,7 @@ namespace Robust.UnitTesting
|
||||
{
|
||||
internal sealed class IntegrationNetManager : IClientNetManager, IServerNetManager
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
public bool IsServer { get; private set; }
|
||||
public bool IsClient => !IsServer;
|
||||
public bool IsRunning { get; private set; }
|
||||
@@ -371,6 +374,8 @@ namespace Robust.UnitTesting
|
||||
public NetUserId UserId { get; }
|
||||
public string UserName { get; }
|
||||
public LoginType AuthType => LoginType.GuestAssigned;
|
||||
public TimeSpan RemoteTimeOffset => TimeSpan.Zero; // TODO: Fix this
|
||||
public TimeSpan RemoteTime => _owner._gameTiming.RealTime + RemoteTimeOffset;
|
||||
public short Ping => default;
|
||||
|
||||
public IntegrationNetChannel(IntegrationNetManager owner, ChannelWriter<object> otherChannel, int uid,
|
||||
|
||||
Reference in New Issue
Block a user