diff --git a/Robust.Client/GameStates/ClientGameStateManager.cs b/Robust.Client/GameStates/ClientGameStateManager.cs index 7394554548b..251667f21fb 100644 --- a/Robust.Client/GameStates/ClientGameStateManager.cs +++ b/Robust.Client/GameStates/ClientGameStateManager.cs @@ -296,7 +296,7 @@ public void ApplyGameState() var hasPendingInput = pendingInputEnumerator.MoveNext(); var hasPendingMessage = pendingMessagesEnumerator.MoveNext(); - var ping = _network.ServerChannel!.Ping / 1000f + PredictLagBias; // seconds. + var ping = (_network.ServerChannel?.Ping ?? 0) / 1000f + PredictLagBias; // seconds. var targetTick = _timing.CurTick.Value + _processor.TargetBufferSize + (int) Math.Ceiling(_timing.TickRate * ping) + PredictTickBias; diff --git a/Robust.Client/Player/PlayerManager.cs b/Robust.Client/Player/PlayerManager.cs index bf4e29d53b8..561c50403e6 100644 --- a/Robust.Client/Player/PlayerManager.cs +++ b/Robust.Client/Player/PlayerManager.cs @@ -143,7 +143,6 @@ private void UpdateAttachedEntity(EntityUid? entity) { return; } - if (entity == null) { LocalPlayer.DetachEntity(); diff --git a/Robust.Shared/Prototypes/PrototypeManager.cs b/Robust.Shared/Prototypes/PrototypeManager.cs index b886f0c183f..f2e2cda11ec 100644 --- a/Robust.Shared/Prototypes/PrototypeManager.cs +++ b/Robust.Shared/Prototypes/PrototypeManager.cs @@ -155,6 +155,12 @@ public interface IPrototypeManager /// void ResolveResults(); + /// + /// Reload the changes from LoadString + /// + /// Changes from load string + void ReloadPrototypes(Dictionary> prototypes); + /// /// Registers a specific prototype name to be ignored. /// @@ -315,7 +321,7 @@ protected void ReloadPrototypes(IEnumerable filePaths) #endif } - internal void ReloadPrototypes(Dictionary> prototypes) + public void ReloadPrototypes(Dictionary> prototypes) { #if !FULL_RELEASE var prototypeTypeOrder = prototypes.Keys.ToList(); @@ -609,7 +615,10 @@ public void RemoveString(string prototypes) foreach (var node in root.Cast()) { var typeString = node.GetNode("type").AsString(); - var type = _prototypeTypes[typeString]; + if (!_prototypeTypes.TryGetValue(typeString, out var type)) + { + continue; + } var id = node.GetNode("id").AsString(); @@ -618,7 +627,10 @@ public void RemoveString(string prototypes) tree.RemoveId(id); } - _prototypes[type].Remove(id); + if (_prototypes.TryGetValue(type, out var prototypeIds)) + { + prototypeIds.Remove(id); + } } } } diff --git a/Robust.Shared/Serialization/Manager/SerializationManager.cs b/Robust.Shared/Serialization/Manager/SerializationManager.cs index 445af19501b..7a6127d6025 100644 --- a/Robust.Shared/Serialization/Manager/SerializationManager.cs +++ b/Robust.Shared/Serialization/Manager/SerializationManager.cs @@ -11,6 +11,7 @@ using JetBrains.Annotations; using Robust.Shared.IoC; using Robust.Shared.Log; +using Robust.Shared.Network; using Robust.Shared.Reflection; using Robust.Shared.Serialization.Manager.Attributes; using Robust.Shared.Serialization.Manager.Definition; @@ -34,7 +35,7 @@ public sealed partial class SerializationManager : ISerializationManager private bool _initialized; // Using CWT<,> here in case we ever want assembly unloading. - private static readonly ConditionalWeakTable DataDefinitions = new(); + private readonly ConditionalWeakTable DataDefinitions = new(); private readonly HashSet _copyByRefRegistrations = new(); public IDependencyCollection DependencyCollection { get; private set; } = default!; diff --git a/Robust.UnitTesting/RobustIntegrationTest.NetManager.cs b/Robust.UnitTesting/RobustIntegrationTest.NetManager.cs index 8006af64b08..3cf4a7bfe3d 100644 --- a/Robust.UnitTesting/RobustIntegrationTest.NetManager.cs +++ b/Robust.UnitTesting/RobustIntegrationTest.NetManager.cs @@ -5,6 +5,7 @@ using System.Net; using System.Threading.Channels; using System.Threading.Tasks; +using Robust.Shared.Asynchronous; using Robust.Shared.IoC; using Robust.Shared.Network; using Robust.Shared.Timing; @@ -17,6 +18,7 @@ public partial class RobustIntegrationTest internal sealed class IntegrationNetManager : IClientNetManager, IServerNetManager { [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly ITaskManager _taskManager = default!; public bool IsServer { get; private set; } public bool IsClient => !IsServer; public bool IsRunning { get; private set; } @@ -106,7 +108,7 @@ public void ProcessPackets() { DebugTools.Assert(IsServer); - async void DoConnect() + async Task DoConnect() { var writer = connect.ChannelWriter; @@ -139,7 +141,7 @@ async void DoConnect() Connected?.Invoke(this, new NetChannelArgs(channel)); } - DoConnect(); + _taskManager.BlockWaitOnTask(DoConnect()); break; } diff --git a/Robust.UnitTesting/RobustIntegrationTest.cs b/Robust.UnitTesting/RobustIntegrationTest.cs index 2382d2e21a3..a641048d98f 100644 --- a/Robust.UnitTesting/RobustIntegrationTest.cs +++ b/Robust.UnitTesting/RobustIntegrationTest.cs @@ -361,7 +361,17 @@ private async Task WaitIdleImplAsync(bool throwOnUnhandled, CancellationToken ca { while (_isAlive && _currentTicksId != _ackTicksId) { - var msg = await _fromInstanceReader.ReadAsync(cancellationToken); + object msg = default!; + try + { + msg = await _fromInstanceReader.ReadAsync(cancellationToken); + } + catch(OperationCanceledException ex) + { + _unhandledException = ex; + _isAlive = false; + break; + } switch (msg) { case ShutDownMessage shutDownMessage: @@ -475,6 +485,7 @@ public void Stop() // Won't get ack'd directly but the shutdown is convincing enough. _currentTicksId += 1; _toInstanceWriter.TryWrite(new StopMessage()); + _toInstanceWriter.TryComplete(); } /// @@ -526,7 +537,7 @@ public void Dispose() public sealed class ServerIntegrationInstance : IntegrationInstance { - internal ServerIntegrationInstance(ServerIntegrationOptions? options) : base(options) + public ServerIntegrationInstance(ServerIntegrationOptions? options) : base(options) { ServerOptions = options; DependencyCollection = new DependencyCollection(); @@ -654,7 +665,7 @@ private BaseServer Init() public sealed class ClientIntegrationInstance : IntegrationInstance { - internal ClientIntegrationInstance(ClientIntegrationOptions? options) : base(options) + public ClientIntegrationInstance(ClientIntegrationOptions? options) : base(options) { ClientOptions = options; DependencyCollection = new DependencyCollection(); @@ -839,8 +850,12 @@ public void Run() while (Running) { - _channelReader.WaitToReadAsync().AsTask().Wait(); - + var readerNotDone = _channelReader.WaitToReadAsync().AsTask().GetAwaiter().GetResult(); + if (!readerNotDone) + { + Running = false; + return; + } SingleThreadRunUntilEmpty(); } }