diff --git a/Robust.Client/BaseClient.cs b/Robust.Client/BaseClient.cs
index 246b8ee50..0c631197a 100644
--- a/Robust.Client/BaseClient.cs
+++ b/Robust.Client/BaseClient.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Net;
using Robust.Client.Interfaces;
using Robust.Client.Interfaces.Debugging;
@@ -7,8 +7,8 @@ using Robust.Client.Interfaces.GameStates;
using Robust.Client.Interfaces.Utility;
using Robust.Client.Player;
using Robust.Shared;
+using Robust.Shared.Configuration;
using Robust.Shared.Enums;
-using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Interfaces.Map;
using Robust.Shared.Interfaces.Network;
using Robust.Shared.Interfaces.Timing;
@@ -25,7 +25,7 @@ namespace Robust.Client
{
[Dependency] private readonly IClientNetManager _net = default!;
[Dependency] private readonly IPlayerManager _playMan = default!;
- [Dependency] private readonly IConfigurationManager _configManager = default!;
+ [Dependency] private readonly INetConfigurationManager _configManager = default!;
[Dependency] private readonly IClientEntityManager _entityManager = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IDiscordRichPresence _discord = default!;
@@ -50,9 +50,7 @@ namespace Robust.Client
///
public void Initialize()
{
- _net.RegisterNetMessage(MsgServerInfo.NAME, HandleServerInfo);
_net.RegisterNetMessage(MsgSetTickRate.NAME, HandleSetTickRate);
- _net.RegisterNetMessage(MsgServerInfoReq.NAME);
_net.Connected += OnConnected;
_net.ConnectFailed += OnConnectFailed;
_net.Disconnect += OnNetDisconnect;
@@ -98,9 +96,44 @@ namespace Robust.Client
private void OnConnected(object? sender, NetChannelArgs args)
{
- // request base info about the server
- var msgInfo = _net.CreateNetMessage();
- _net.ClientSendMessage(msgInfo);
+ _configManager.SyncWithServer();
+ _configManager.ReceivedInitialNwVars += OnReceivedClientData;
+ }
+
+ private void OnReceivedClientData(object? sender, EventArgs e)
+ {
+ _configManager.ReceivedInitialNwVars -= OnReceivedClientData;
+
+ var info = GameInfo;
+
+ var serverName = _configManager.GetCVar("game.hostname");
+ if (info == null)
+ {
+ GameInfo = info = new ServerInfo(serverName);
+ }
+ else
+ {
+ info.ServerName = serverName;
+ }
+
+ var maxPlayers = _configManager.GetCVar("game.maxplayers");
+ info.ServerMaxPlayers = maxPlayers;
+
+ var tickrate = _configManager.GetCVar("net.tickrate");
+ info.TickRate = (byte) tickrate;
+ _timing.TickRate = (byte) tickrate;
+ Logger.InfoS("client", $"Tickrate changed to: {tickrate}");
+
+ var userName = _net.ServerChannel!.UserName;
+ var userId = _net.ServerChannel.UserId;
+ _discord.Update(info.ServerName, userName, info.ServerMaxPlayers.ToString());
+ // start up player management
+ _playMan.Startup(_net.ServerChannel!);
+
+ _playMan.LocalPlayer!.UserId = userId;
+ _playMan.LocalPlayer.Name = userName;
+
+ _playMan.LocalPlayer.StatusChanged += OnLocalStatusChanged;
}
///
@@ -152,6 +185,7 @@ namespace Robust.Client
LastDisconnectReason = args.Reason;
+ IoCManager.Resolve().FlushMessages();
_gameStates.Reset();
_playMan.Shutdown();
_entityManager.Shutdown();
@@ -160,36 +194,6 @@ namespace Robust.Client
Reset();
}
- private void HandleServerInfo(MsgServerInfo msg)
- {
- var info = GameInfo;
-
- if (info == null)
- {
- GameInfo = info = new ServerInfo(msg.ServerName);
- }
- else
- {
- info.ServerName = msg.ServerName;
- }
-
- info.ServerMaxPlayers = msg.ServerMaxPlayers;
- info.TickRate = msg.TickRate;
- _timing.TickRate = msg.TickRate;
- Logger.InfoS("client", $"Tickrate changed to: {msg.TickRate}");
-
- var userName = msg.MsgChannel.UserName;
- var userId = msg.MsgChannel.UserId;
- _discord.Update(info.ServerName, userName, info.ServerMaxPlayers.ToString());
- // start up player management
- _playMan.Startup(_net.ServerChannel!);
-
- _playMan.LocalPlayer!.UserId = userId;
- _playMan.LocalPlayer.Name = userName;
-
- _playMan.LocalPlayer.StatusChanged += OnLocalStatusChanged;
- }
-
private void HandleSetTickRate(MsgSetTickRate message)
{
_timing.TickRate = message.NewTickRate;
diff --git a/Robust.Client/GameController.cs b/Robust.Client/GameController.cs
index 12313b73b..e42f99205 100644
--- a/Robust.Client/GameController.cs
+++ b/Robust.Client/GameController.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
@@ -164,6 +164,7 @@ namespace Robust.Client
_userInterfaceManager.Initialize();
_networkManager.Initialize(false);
+ IoCManager.Resolve().SetupNetworking();
_serializer.Initialize();
_inputManager.Initialize();
_console.Initialize();
diff --git a/Robust.Client/GameStates/ClientGameStateManager.cs b/Robust.Client/GameStates/ClientGameStateManager.cs
index 7b8f288fd..7d6371eaa 100644
--- a/Robust.Client/GameStates/ClientGameStateManager.cs
+++ b/Robust.Client/GameStates/ClientGameStateManager.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using Robust.Client.GameObjects.EntitySystems;
using Robust.Client.Interfaces;
@@ -11,6 +11,7 @@ using Robust.Shared.IoC;
using Robust.Shared.Network.Messages;
using Robust.Client.Player;
using Robust.Shared;
+using Robust.Shared.Configuration;
using Robust.Shared.GameObjects;
using Robust.Shared.Input;
using Robust.Shared.Interfaces.Configuration;
@@ -41,7 +42,7 @@ namespace Robust.Client.GameStates
[Dependency] private readonly IBaseClient _client = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IGameTiming _timing = default!;
- [Dependency] private readonly IConfigurationManager _config = default!;
+ [Dependency] private readonly INetConfigurationManager _config = default!;
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
[Dependency] private readonly IComponentManager _componentManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
@@ -177,7 +178,7 @@ namespace Robust.Client.GameStates
var i = 0;
for (; i < applyCount; i++)
{
- _timing.CurTick = _lastProcessedTick + 1;
+ _timing.LastRealTick = _timing.CurTick = _lastProcessedTick + 1;
// TODO: We could theoretically communicate with the GameStateProcessor better here.
// Since game states are sliding windows, it is possible that we need less than applyCount applies here.
@@ -380,6 +381,7 @@ namespace Robust.Client.GameStates
private List ApplyGameState(GameState curState, GameState? nextState)
{
+ _config.TickProcessMessages();
_mapManager.ApplyGameStatePre(curState.MapData);
var createdEntities = _entities.ApplyEntityStates(curState.EntityStates, curState.EntityDeletions,
nextState?.EntityStates);
diff --git a/Robust.Server/BaseServer.cs b/Robust.Server/BaseServer.cs
index d89fa2922..67f7f330e 100644
--- a/Robust.Server/BaseServer.cs
+++ b/Robust.Server/BaseServer.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
@@ -288,6 +288,8 @@ namespace Robust.Server
// Initialize Tier 2 services
IoCManager.Resolve().InSimulation = true;
+
+ IoCManager.Resolve().SetupNetworking();
_stateManager.Initialize();
IoCManager.Resolve().Initialize(MaxPlayers);
@@ -487,6 +489,8 @@ namespace Robust.Server
// called right before main loop returns, do all saving/cleanup in here
private void Cleanup()
{
+ IoCManager.Resolve().FlushMessages();
+
// shut down networking, kicking all players.
_network.Shutdown($"Server shutting down: {_shutdownReason}");
@@ -540,6 +544,9 @@ namespace Robust.Server
ServerCurTick.Set(_time.CurTick.Value);
ServerCurTime.Set(_time.CurTime.TotalSeconds);
+ // These are always the same on the server, there is no prediction.
+ _time.LastRealTick = _time.CurTick;
+
UpdateTitle();
using (TickUsage.WithLabels("PreEngine").NewTimer())
@@ -547,6 +554,11 @@ namespace Robust.Server
_modLoader.BroadcastUpdate(ModUpdateLevel.PreEngine, frameEventArgs);
}
+ using (TickUsage.WithLabels("NetworkedCVar").NewTimer())
+ {
+ IoCManager.Resolve().TickProcessMessages();
+ }
+
using (TickUsage.WithLabels("Timers").NewTimer())
{
timerManager.UpdateTimers(frameEventArgs);
diff --git a/Robust.Server/Player/PlayerManager.cs b/Robust.Server/Player/PlayerManager.cs
index b3f903ec4..f04dc66ac 100644
--- a/Robust.Server/Player/PlayerManager.cs
+++ b/Robust.Server/Player/PlayerManager.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
@@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Prometheus;
using Robust.Server.Interfaces;
using Robust.Server.Interfaces.Player;
+using Robust.Shared.Configuration;
using Robust.Shared.Enums;
using Robust.Shared.GameStates;
using Robust.Shared.Input;
@@ -91,8 +92,6 @@ namespace Robust.Server.Player
MaxPlayers = maxPlayers;
- _network.RegisterNetMessage(MsgServerInfoReq.NAME, HandleWelcomeMessageReq);
- _network.RegisterNetMessage(MsgServerInfo.NAME);
_network.RegisterNetMessage(MsgPlayerListReq.NAME, HandlePlayerListReq);
_network.RegisterNetMessage(MsgPlayerList.NAME);
@@ -378,6 +377,8 @@ namespace Robust.Server.Player
}
PlayerCountMetric.Set(PlayerCount);
+
+ IoCManager.Resolve().SyncConnectingClient(args.Channel);
}
private void OnPlayerStatusChanged(IPlayerSession session, SessionStatus oldStatus, SessionStatus newStatus)
@@ -414,18 +415,6 @@ namespace Robust.Server.Player
Dirty();
}
- private void HandleWelcomeMessageReq(MsgServerInfoReq message)
- {
- var channel = message.MsgChannel;
- var netMsg = channel.CreateNetMessage();
-
- netMsg.ServerName = _baseServer.ServerName;
- netMsg.ServerMaxPlayers = _baseServer.MaxPlayers;
- netMsg.TickRate = _timing.TickRate;
-
- channel.SendMessage(netMsg);
- }
-
private void HandlePlayerListReq(MsgPlayerListReq message)
{
var channel = message.MsgChannel;
diff --git a/Robust.Shared/CVars.cs b/Robust.Shared/CVars.cs
index cde3253ec..9c5b95e62 100644
--- a/Robust.Shared/CVars.cs
+++ b/Robust.Shared/CVars.cs
@@ -165,10 +165,10 @@ namespace Robust.Shared
*/
public static readonly CVarDef GameMaxPlayers =
- CVarDef.Create("game.maxplayers", 32, CVar.ARCHIVE | CVar.SERVERONLY);
+ CVarDef.Create("game.maxplayers", 32, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER);
public static readonly CVarDef GameHostName =
- CVarDef.Create("game.hostname", "MyServer", CVar.ARCHIVE | CVar.SERVERONLY);
+ CVarDef.Create("game.hostname", "MyServer", CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER);
/*
* LOG
diff --git a/Robust.Shared/Configuration/ConfigurationManager.cs b/Robust.Shared/Configuration/ConfigurationManager.cs
index 1b4cb6fab..16e260771 100644
--- a/Robust.Shared/Configuration/ConfigurationManager.cs
+++ b/Robust.Shared/Configuration/ConfigurationManager.cs
@@ -1,4 +1,4 @@
-using Nett;
+using Nett;
using Robust.Shared.Interfaces.Configuration;
using Robust.Shared.Log;
using System;
@@ -13,12 +13,12 @@ namespace Robust.Shared.Configuration
///
/// Stores and manages global configuration variables.
///
- internal sealed class ConfigurationManager : IConfigurationManagerInternal
+ internal class ConfigurationManager : IConfigurationManagerInternal
{
private const char TABLE_DELIMITER = '.';
- private readonly Dictionary _configVars = new();
+ protected readonly Dictionary _configVars = new();
private string? _configFile;
- private bool _isServer;
+ protected bool _isServer;
///
/// Constructs a new ConfigurationManager.
@@ -79,6 +79,7 @@ namespace Robust.Shared.Configuration
else // this is a key, add CVar
{
// if the CVar has already been registered
+ var tomlValue = TypeConvert(obj);
if (_configVars.TryGetValue(tablePath, out var cfgVar))
{
if ((cfgVar.Flags & CVar.SECURE) != 0)
@@ -90,13 +91,14 @@ namespace Robust.Shared.Configuration
return;
}
// overwrite the value with the saved one
- cfgVar.Value = TypeConvert(obj);
+ cfgVar.Value = tomlValue;
cfgVar.ValueChanged?.Invoke(cfgVar.Value);
}
else
{
//or add another unregistered CVar
- cfgVar = new ConfigVar(tablePath, null, CVar.NONE) { Value = TypeConvert(obj) };
+ //Note: the defaultValue is arbitrarily 0, it will get overwritten when the cvar is registered.
+ cfgVar = new ConfigVar(tablePath, 0, CVar.NONE) { Value = tomlValue };
_configVars.Add(tablePath, cfgVar);
}
@@ -131,6 +133,8 @@ namespace Robust.Shared.Configuration
continue;
}
+ // Don't write if Archive flag is not set.
+ // Don't write if the cVar is the default value.
if (!cVar.ConfigModified &&
(cVar.Flags & CVar.ARCHIVE) == 0 || value.Equals(cVar.DefaultValue))
{
@@ -192,6 +196,7 @@ namespace Robust.Shared.Configuration
}
public void RegisterCVar(string name, T defaultValue, CVar flags = CVar.NONE, Action? onValueChanged = null)
+ where T : notnull
{
Action