From 362b7804d9ac4aa0aff12cd987024960f75bd1be Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 11 Nov 2020 00:46:35 +0100 Subject: [PATCH] Fix issues with .NET 5. --- Robust.Client/ClientIoC.cs | 1 - Robust.Client/ClientSignalHandler.cs | 16 --- Robust.Client/GameController.cs | 3 - .../GameObjects/ClientEntityManager.cs | 4 +- .../Graphics/Clyde/Clyde.LightRendering.cs | 10 +- Robust.Client/Input/InputManager.cs | 17 ++- .../Placement/Modes/AlignWallProper.cs | 2 +- .../ResourceTypes/RSIResource.cs | 2 +- .../UserInterface/AttachedProperty.cs | 29 +++- .../UserInterface/Controls/TabContainer.cs | 4 +- .../UserInterface/FileDialogManager.cs | 2 +- .../ViewVariables/ViewVariablesTrait.cs | 2 - Robust.Physics/Robust.Physics.csproj | 6 +- Robust.Server/Console/SystemConsoleManager.cs | 2 +- Robust.Server/Program.cs | 2 - Robust.Server/ServerIoC.cs | 1 - Robust.Server/ServerSignalHandler.cs | 16 --- Robust.Server/ServerStatus/WatchdogApi.cs | 3 +- Robust.Shared/ContentPack/AppDomainExt.cs | 2 +- Robust.Shared/ContentPack/PackLoader.cs | 5 +- Robust.Shared/ContentPack/PathHelpers.cs | 15 +- Robust.Shared/IoC/DependencyCollection.cs | 2 +- Robust.Shared/Log/FileLogHandler.cs | 2 +- Robust.Shared/SignalHandler.cs | 128 ------------------ Robust.Shared/Utility/UniqueIndex.cs | 21 ++- .../RobustIntegrationTest.NetManager.cs | 9 +- 26 files changed, 93 insertions(+), 213 deletions(-) delete mode 100644 Robust.Client/ClientSignalHandler.cs delete mode 100644 Robust.Server/ServerSignalHandler.cs delete mode 100644 Robust.Shared/SignalHandler.cs diff --git a/Robust.Client/ClientIoC.cs b/Robust.Client/ClientIoC.cs index fc13da8ab3..4edcfcb6e1 100644 --- a/Robust.Client/ClientIoC.cs +++ b/Robust.Client/ClientIoC.cs @@ -113,7 +113,6 @@ namespace Robust.Client IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); - IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); } diff --git a/Robust.Client/ClientSignalHandler.cs b/Robust.Client/ClientSignalHandler.cs deleted file mode 100644 index 8c4a6432ef..0000000000 --- a/Robust.Client/ClientSignalHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Robust.Client.Interfaces; -using Robust.Shared; -using Robust.Shared.IoC; - -namespace Robust.Client -{ - internal sealed class ClientSignalHandler : SignalHandler - { - [Dependency] private readonly IGameController _gameController = default!; - - protected override void OnReceiveTerminationSignal(string signal) - { - _gameController.Shutdown($"{signal} received"); - } - } -} diff --git a/Robust.Client/GameController.cs b/Robust.Client/GameController.cs index 5dc11c7bcb..d6f907cb2b 100644 --- a/Robust.Client/GameController.cs +++ b/Robust.Client/GameController.cs @@ -63,7 +63,6 @@ namespace Robust.Client [Dependency] private readonly IClydeInternal _clyde = default!; [Dependency] private readonly IFontManagerInternal _fontManager = default!; [Dependency] private readonly IModLoader _modLoader = default!; - [Dependency] private readonly ISignalHandler _signalHandler = default!; [Dependency] private readonly IClientConGroupController _conGroupController = default!; [Dependency] private readonly IScriptClient _scriptClient = default!; [Dependency] private readonly IComponentManager _componentManager = default!; @@ -119,8 +118,6 @@ namespace Robust.Client _configurationManager.OverrideConVars(_commandLineArgs.CVars); } - _signalHandler.MaybeStart(); - _resourceCache.Initialize(LoadConfigAndUserData ? userDataDir : null); #if FULL_RELEASE diff --git a/Robust.Client/GameObjects/ClientEntityManager.cs b/Robust.Client/GameObjects/ClientEntityManager.cs index b04db4a833..2e484cbfc4 100644 --- a/Robust.Client/GameObjects/ClientEntityManager.cs +++ b/Robust.Client/GameObjects/ClientEntityManager.cs @@ -58,8 +58,8 @@ namespace Robust.Client.GameObjects } else //Unknown entities { - var metaState = (MetaDataComponentState) es.ComponentStates - .FirstOrDefault(c => c.NetID == NetIDs.META_DATA); + var metaState = (MetaDataComponentState?) es.ComponentStates + ?.FirstOrDefault(c => c.NetID == NetIDs.META_DATA); if (metaState == null) { throw new InvalidOperationException($"Server sent new entity state for {es.Uid} without metadata component!"); diff --git a/Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs b/Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs index e810106ebf..48bfced8fd 100644 --- a/Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs +++ b/Robust.Client/Graphics/Clyde/Clyde.LightRendering.cs @@ -871,15 +871,15 @@ namespace Robust.Client.Graphics.Clyde BindVertexArray(_occlusionVao.Handle); CheckGlError(); - _occlusionVbo.Reallocate(arrayBuffer.AsSpan(..ai)); - _occlusionVIVbo.Reallocate(arrayVIBuffer.AsSpan(..avi)); - _occlusionEbo.Reallocate(indexBuffer.AsSpan(..ii)); + _occlusionVbo.Reallocate(arrayBuffer.AsSpan(0, ai)); + _occlusionVIVbo.Reallocate(arrayVIBuffer.AsSpan(0, avi)); + _occlusionEbo.Reallocate(indexBuffer.AsSpan(0, ii)); BindVertexArray(_occlusionMaskVao.Handle); CheckGlError(); - _occlusionMaskVbo.Reallocate(arrayMaskBuffer.AsSpan(..ami)); - _occlusionMaskEbo.Reallocate(indexMaskBuffer.AsSpan(..imi)); + _occlusionMaskVbo.Reallocate(arrayMaskBuffer.AsSpan(0, ami)); + _occlusionMaskEbo.Reallocate(indexMaskBuffer.AsSpan(0, imi)); } finally { diff --git a/Robust.Client/Input/InputManager.cs b/Robust.Client/Input/InputManager.cs index 9926938274..785c4ee5b7 100644 --- a/Robust.Client/Input/InputManager.cs +++ b/Robust.Client/Input/InputManager.cs @@ -144,8 +144,8 @@ namespace Robust.Client.Input var version = 1; ser.DataField(ref version, "version", 1); - ser.DataField(ref modifiedBindings, "binds", null); - ser.DataField(ref leaveEmpty, "leaveEmpty", null); + ser.DataField(ref modifiedBindings, "binds", Array.Empty()); + ser.DataField(ref leaveEmpty, "leaveEmpty", Array.Empty()); var path = new ResourcePath(KeybindsPath); using var writer = new StreamWriter(_resourceMan.UserData.Create(path)); @@ -159,7 +159,18 @@ namespace Robust.Client.Input // the diff does not have to be symmetrical, otherwise instead of 'A \ B' we allocate all the things with '(A \ B) ∪ (B \ A)' // It should be OK to artificially keyup these, because in the future the organic keyup will be blocked (either the context // does not have the binding, or the double keyup check in UpBind will block it). - foreach (var function in args.OldContext.Except(args.NewContext)) + if (args.OldContext == null) + { + return; + } + + IEnumerable enumerable = args.OldContext; + if (args.NewContext != null) + { + enumerable = enumerable.Except(args.NewContext); + } + + foreach (var function in enumerable) { var bind = _bindings.Find(binding => binding.Function == function); if (bind == null || bind.State == BoundKeyState.Up) diff --git a/Robust.Client/Placement/Modes/AlignWallProper.cs b/Robust.Client/Placement/Modes/AlignWallProper.cs index 8ff7eccb97..7e40df8a4d 100644 --- a/Robust.Client/Placement/Modes/AlignWallProper.cs +++ b/Robust.Client/Placement/Modes/AlignWallProper.cs @@ -36,7 +36,7 @@ namespace Robust.Client.Placement.Modes var closestNode = offsets .Select(o => tileCoordinates.Offset(o)) .OrderBy(node => node.TryDistance(pManager.EntityManager, MouseCoords, out var distance) ? distance : (float?) null) - .First(f => f != null); + .First(); MouseCoords = closestNode; } diff --git a/Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs b/Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs index 4215d72ad2..de635dee34 100644 --- a/Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs +++ b/Robust.Client/ResourceManagement/ResourceTypes/RSIResource.cs @@ -338,7 +338,7 @@ namespace Robust.Client.ResourceManagement var size = manifestJson["size"]!.ToObject(); var states = new List(); - foreach (var stateObject in manifestJson["states"].Cast()) + foreach (var stateObject in manifestJson["states"]!.Cast()) { var stateName = stateObject["name"]!.ToObject()!; var dirValue = stateObject["directions"]!.ToObject(); diff --git a/Robust.Client/UserInterface/AttachedProperty.cs b/Robust.Client/UserInterface/AttachedProperty.cs index d77c8ffd94..27903098f1 100644 --- a/Robust.Client/UserInterface/AttachedProperty.cs +++ b/Robust.Client/UserInterface/AttachedProperty.cs @@ -89,7 +89,7 @@ namespace Robust.Client.UserInterface public new T DefaultValue { get; } - internal AttachedProperty(string name, Type owningType, T defaultValue = default, + internal AttachedProperty(string name, Type owningType, T defaultValue, Func? validate = null, AttachedPropertyChangedCallback? changed = null) : base(name, owningType, typeof(T), defaultValue, validate != null ? o => validate!((T) o!) : (Func?) null, @@ -103,12 +103,37 @@ namespace Robust.Client.UserInterface } public static AttachedProperty Create(string name, Type owningType, - T defaultValue = default, + T defaultValue = default!, Func? validate = null, AttachedPropertyChangedCallback? changed = null) { + if (!typeof(T).IsValueType && defaultValue == null) + { + throw new ArgumentNullException(nameof(defaultValue), + "Got defaultValue that is null for reference type." + + "If this is a non-nullable reference type," + + "make sure to fill in a default value with the parameter." + + "If this is intended to be nullable," + + "use the CreateNull() overload (and make sure to set the type nullability correctly!)."); + } + return new AttachedProperty(name, owningType, defaultValue, validate, changed); } + + // TODO: C# 9: use nullable T on the returned attached property here. + public static AttachedProperty CreateNull(string name, Type owningType, + T defaultValue = default!, + Func? validate = null, + AttachedPropertyChangedCallback? changed = null) + { + if (typeof(T).IsValueType) + { + throw new ArgumentException("Type must not be a value type. Use regular create for that" + + " (yes, even for nullable value types)."); + } + return new AttachedProperty(name, owningType, defaultValue, validate, changed); + } + } /// diff --git a/Robust.Client/UserInterface/Controls/TabContainer.cs b/Robust.Client/UserInterface/Controls/TabContainer.cs index fa0434d027..f7c70d42e4 100644 --- a/Robust.Client/UserInterface/Controls/TabContainer.cs +++ b/Robust.Client/UserInterface/Controls/TabContainer.cs @@ -11,7 +11,7 @@ namespace Robust.Client.UserInterface.Controls public class TabContainer : Container { public static readonly AttachedProperty TabVisibleProperty = AttachedProperty.Create("TabVisible", typeof(TabContainer), true); - public static readonly AttachedProperty TabTitleProperty = AttachedProperty.Create("TabTitle", typeof(TabContainer)); + public static readonly AttachedProperty TabTitleProperty = AttachedProperty.CreateNull("TabTitle", typeof(TabContainer)); public const string StylePropertyTabStyleBox = "tab-stylebox"; public const string StylePropertyTabStyleBoxInactive = "tab-stylebox-inactive"; @@ -80,7 +80,7 @@ namespace Robust.Client.UserInterface.Controls return title ?? control.Name ?? Loc.GetString("No title"); } - public static string GetTabTitle(Control control) + public static string? GetTabTitle(Control control) { return control.GetValue(TabTitleProperty); } diff --git a/Robust.Client/UserInterface/FileDialogManager.cs b/Robust.Client/UserInterface/FileDialogManager.cs index 8b6e8a78f2..fc112ca2dc 100644 --- a/Robust.Client/UserInterface/FileDialogManager.cs +++ b/Robust.Client/UserInterface/FileDialogManager.cs @@ -278,7 +278,7 @@ namespace Robust.Client.UserInterface DebugTools.AssertNotNull(process); - await process.WaitForExitAsync(); + await process!.WaitForExitAsync(); // Cancel hit. if (process.ExitCode == 1) diff --git a/Robust.Client/ViewVariables/ViewVariablesTrait.cs b/Robust.Client/ViewVariables/ViewVariablesTrait.cs index 16f5cf6ab6..6f4303b887 100644 --- a/Robust.Client/ViewVariables/ViewVariablesTrait.cs +++ b/Robust.Client/ViewVariables/ViewVariablesTrait.cs @@ -1,5 +1,3 @@ -using System.Runtime.InteropServices.WindowsRuntime; -using System.Threading.Tasks; using Robust.Client.ViewVariables.Instances; namespace Robust.Client.ViewVariables diff --git a/Robust.Physics/Robust.Physics.csproj b/Robust.Physics/Robust.Physics.csproj index 1cea55e535..b13a84b9fa 100644 --- a/Robust.Physics/Robust.Physics.csproj +++ b/Robust.Physics/Robust.Physics.csproj @@ -1,9 +1,11 @@ - + - netcoreapp3.1 + + $(TargetFramework) enable + true diff --git a/Robust.Server/Console/SystemConsoleManager.cs b/Robust.Server/Console/SystemConsoleManager.cs index 0584aa6434..e2b582181e 100644 --- a/Robust.Server/Console/SystemConsoleManager.cs +++ b/Robust.Server/Console/SystemConsoleManager.cs @@ -198,7 +198,7 @@ namespace Robust.Server.Console return result; } - private void CancelKeyHandler(object sender, ConsoleCancelEventArgs args) + private void CancelKeyHandler(object? sender, ConsoleCancelEventArgs args) { // Handle process exiting ourselves. args.Cancel = true; diff --git a/Robust.Server/Program.cs b/Robust.Server/Program.cs index 7f9df457d2..f421ce0ab7 100644 --- a/Robust.Server/Program.cs +++ b/Robust.Server/Program.cs @@ -84,8 +84,6 @@ namespace Robust.Server string strVersion = Assembly.GetExecutingAssembly().GetName().Version!.ToString(); Logger.Info("Server Version " + strVersion + " -> Ready"); - IoCManager.Resolve().MaybeStart(); - server.MainLoop(); Logger.Info("Goodbye."); diff --git a/Robust.Server/ServerIoC.cs b/Robust.Server/ServerIoC.cs index f30a3f73b1..412ca0bd96 100644 --- a/Robust.Server/ServerIoC.cs +++ b/Robust.Server/ServerIoC.cs @@ -66,7 +66,6 @@ namespace Robust.Server IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); - IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); diff --git a/Robust.Server/ServerSignalHandler.cs b/Robust.Server/ServerSignalHandler.cs deleted file mode 100644 index 2d4a25e8ed..0000000000 --- a/Robust.Server/ServerSignalHandler.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Robust.Server.Interfaces; -using Robust.Shared; -using Robust.Shared.IoC; - -namespace Robust.Server -{ - internal sealed class ServerSignalHandler : SignalHandler - { - [Dependency] private readonly IBaseServer _baseServer = default!; - - protected override void OnReceiveTerminationSignal(string signal) - { - _baseServer.Shutdown($"{signal} received"); - } - } -} diff --git a/Robust.Server/ServerStatus/WatchdogApi.cs b/Robust.Server/ServerStatus/WatchdogApi.cs index 487b8ce311..2303e567c0 100644 --- a/Robust.Server/ServerStatus/WatchdogApi.cs +++ b/Robust.Server/ServerStatus/WatchdogApi.cs @@ -156,7 +156,8 @@ namespace Robust.Server.ServerStatus try { - await _httpClient.PostAsync(new Uri(_baseUri, $"server_api/{_watchdogKey}/ping"), null); + // Passing null as content works so... + await _httpClient.PostAsync(new Uri(_baseUri, $"server_api/{_watchdogKey}/ping"), null!); } catch (HttpRequestException e) { diff --git a/Robust.Shared/ContentPack/AppDomainExt.cs b/Robust.Shared/ContentPack/AppDomainExt.cs index a079c137b7..a4a9177bd6 100644 --- a/Robust.Shared/ContentPack/AppDomainExt.cs +++ b/Robust.Shared/ContentPack/AppDomainExt.cs @@ -14,7 +14,7 @@ namespace Robust.Shared.ContentPack /// public static Assembly GetAssemblyByName(this AppDomain domain, string name) { - return domain.GetAssemblies().SingleOrDefault(assembly => assembly.GetName().Name == name); + return domain.GetAssemblies().Single(assembly => assembly.GetName().Name == name); } } } diff --git a/Robust.Shared/ContentPack/PackLoader.cs b/Robust.Shared/ContentPack/PackLoader.cs index 4f0e3bf158..c52db5f20a 100644 --- a/Robust.Shared/ContentPack/PackLoader.cs +++ b/Robust.Shared/ContentPack/PackLoader.cs @@ -43,7 +43,10 @@ namespace Robust.Shared.ContentPack } else { - _zip = new ZipArchive(_stream, ZipArchiveMode.Read); + // Stream constructor. + DebugTools.AssertNotNull(_stream); + + _zip = new ZipArchive(_stream!, ZipArchiveMode.Read); } } diff --git a/Robust.Shared/ContentPack/PathHelpers.cs b/Robust.Shared/ContentPack/PathHelpers.cs index 2492139799..9139074fd8 100644 --- a/Robust.Shared/ContentPack/PathHelpers.cs +++ b/Robust.Shared/ContentPack/PathHelpers.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Reflection; using System.Runtime.InteropServices; namespace Robust.Shared.ContentPack @@ -19,18 +18,14 @@ namespace Robust.Shared.ContentPack // TODO: remove this shitty hack, either through making it less hardcoded into shared, // or by making our file structure less spaghetti somehow. var assembly = typeof(PathHelpers).Assembly; - if (assembly.CodeBase == null) + var location = assembly.Location; + if (location == string.Empty) { + // See https://docs.microsoft.com/en-us/dotnet/api/system.reflection.assembly.location?view=net-5.0#remarks + // This doesn't apply to us really because we don't do that kind of publishing, but whatever. throw new InvalidOperationException("Cannot find path of executable."); } - - var pathUri = new Uri(assembly.CodeBase); - var path = pathUri.LocalPath; - if (pathUri.Fragment != "") - { - path += pathUri.Fragment; - } - return Path.GetDirectoryName(path)!; + return Path.GetDirectoryName(location)!; } /// diff --git a/Robust.Shared/IoC/DependencyCollection.cs b/Robust.Shared/IoC/DependencyCollection.cs index 23eb0d176d..6a0c1cda91 100644 --- a/Robust.Shared/IoC/DependencyCollection.cs +++ b/Robust.Shared/IoC/DependencyCollection.cs @@ -143,7 +143,7 @@ namespace Robust.Shared.IoC // Find a potential dupe by checking other registered types that have already been instantiated that have the same instance type. // Can't catch ourselves because we're not instantiated. // Ones that aren't yet instantiated are about to be and will find us instead. - var (type, _) = _resolveTypes.FirstOrDefault(p => _services.ContainsKey(p.Key) && p.Value == value); + var (type, _) = _resolveTypes.FirstOrDefault(p => _services.ContainsKey(p.Key) && p.Value == value)!; // Interface key can't be null so since KeyValuePair<> is a struct, // this effectively checks whether we found something. diff --git a/Robust.Shared/Log/FileLogHandler.cs b/Robust.Shared/Log/FileLogHandler.cs index be456921ee..0df32b3b5a 100644 --- a/Robust.Shared/Log/FileLogHandler.cs +++ b/Robust.Shared/Log/FileLogHandler.cs @@ -12,7 +12,7 @@ namespace Robust.Shared.Log public FileLogHandler(string path) { - Directory.CreateDirectory(Path.GetDirectoryName(path)); + Directory.CreateDirectory(Path.GetDirectoryName(path)!); writer = TextWriter.Synchronized(new StreamWriter(path, true, EncodingHelpers.UTF8)); } diff --git a/Robust.Shared/SignalHandler.cs b/Robust.Shared/SignalHandler.cs deleted file mode 100644 index e34bb95140..0000000000 --- a/Robust.Shared/SignalHandler.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using System.Threading; -using Robust.Shared.Asynchronous; -using Robust.Shared.Interfaces.Configuration; -using Robust.Shared.IoC; -using Robust.Shared.Log; - -namespace Robust.Shared -{ - internal abstract class SignalHandler : ISignalHandler, IDisposable - { - [Dependency] private readonly ITaskManager _taskManager = default!; -#pragma warning disable 414 - [Dependency] private readonly IConfigurationManager _configurationManager = default!; -#pragma warning restore 414 - - private Thread? _signalThread; - - public void MaybeStart() - { - // I actually did try to implement a onValueChanged handler but couldn't make it work well. - // The problem is that shutting down the thread does not restore the default exit behavior. -#if UNIX - if (_configurationManager.GetCVar(CVars.SignalsHandle)) - { - Start(); - } -#endif - } - - [SuppressMessage("ReSharper", "IdentifierTypo")] - [SuppressMessage("ReSharper", "InconsistentNaming")] - [SuppressMessage("ReSharper", "CommentTypo")] - private void Start() - { - var runningOnMono = Type.GetType("Mono.Runtime") != null; - if (!runningOnMono) - { - return; - } - - try - { - // Reflection is fun. - var assembly = FindMonoPosix(); - Logger.Debug("Successfully loaded Mono.Posix. Registering signal handlers..."); - - var signalType = assembly.GetType("Mono.Unix.UnixSignal")!; - // Mono.Unix.UnixSignal[] - var signalArrayType = signalType.MakeArrayType(); - var signumType = assembly.GetType("Mono.Unix.Native.Signum")!; - - var SIGTERM = Enum.Parse(signumType, "SIGTERM"); - var SIGINT = Enum.Parse(signumType, "SIGINT"); - - // int UnixSignal.WaitAny(UnixSignal[]) - var WaitAny = signalType.GetMethod("WaitAny", new Type[] {signalArrayType})!; - // UnixSignal.Signum - var Signum = signalType.GetProperty("Signum")!; - - var signals = Array.CreateInstance(signalType, 2); - signals.SetValue(Activator.CreateInstance(signalType, SIGTERM), 0); - signals.SetValue(Activator.CreateInstance(signalType, SIGINT), 1); - - _signalThread = new Thread(() => - { - while (true) - { - var args = new object[] {signals}; - // int UnixSignal.WaitAny(UnixSignal[]) - // ReSharper disable once PossibleNullReferenceException - var index = (int) WaitAny.Invoke(null, args)!; - // signals[index].Signum - // ReSharper disable once PossibleNullReferenceException - var signum = Signum.GetValue(signals.GetValue(index), null)!.ToString(); - - // Can't use switch with reflection. Shame. - // Tried to compare the objects directly. Didn't work. - // String it is. - if (signum == "SIGINT" || signum == "SIGTERM") - { - _taskManager.RunOnMainThread(() => OnReceiveTerminationSignal(signum)); - } - } - - // ReSharper disable once FunctionNeverReturns - }) - { - IsBackground = true, - Name = "signal handler" - }; - - _signalThread.Start(); - } - catch (Exception e) - { - Logger.Error("Running on mono but couldn't register signal handlers: {0}", e); - } - } - - private void Stop() - { - _signalThread?.Abort(); - _signalThread = null; - } - - protected abstract void OnReceiveTerminationSignal(string signal); - - private static Assembly FindMonoPosix() - { - // This works don't touch it. - // Well it works on MacOS. Can't speak about Linux. - return Assembly.Load("../Mono.Posix.dll"); - } - - public void Dispose() - { - Stop(); - } - } - - internal interface ISignalHandler - { - void MaybeStart(); - } -} diff --git a/Robust.Shared/Utility/UniqueIndex.cs b/Robust.Shared/Utility/UniqueIndex.cs index 2ca0eff807..6e1fcbbe6a 100644 --- a/Robust.Shared/Utility/UniqueIndex.cs +++ b/Robust.Shared/Utility/UniqueIndex.cs @@ -29,15 +29,15 @@ namespace Robust.Shared.Utility public struct UniqueIndex : IUniqueIndex where TKey : notnull { - private ImmutableDictionary> _index; + private ImmutableDictionary>? _index; /// - public int KeyCount => _index.Count; + public int KeyCount => _index?.Count ?? 0; /// public bool Add(TKey key, TValue value) { - ISet set; + ISet? set; if (_index is null) { @@ -58,7 +58,7 @@ namespace Robust.Shared.Utility /// public int AddRange(TKey key, IEnumerable values) { - ISet set; + ISet? set; if (_index is null) { @@ -190,12 +190,11 @@ namespace Robust.Shared.Utility _index = ImmutableDictionary.CreateRange(index); } - /// public ISet this[TKey key] { get { - ISet set; + ISet? set; if (_index is null) { @@ -217,7 +216,15 @@ namespace Robust.Shared.Utility /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public IEnumerator>> GetEnumerator() => _index.GetEnumerator(); + public IEnumerator>> GetEnumerator() + { + if (_index != null) + { + return _index.GetEnumerator(); + } + + return Enumerable.Empty>>().GetEnumerator(); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); diff --git a/Robust.UnitTesting/RobustIntegrationTest.NetManager.cs b/Robust.UnitTesting/RobustIntegrationTest.NetManager.cs index 1242b7b232..bca9092851 100644 --- a/Robust.UnitTesting/RobustIntegrationTest.NetManager.cs +++ b/Robust.UnitTesting/RobustIntegrationTest.NetManager.cs @@ -290,7 +290,7 @@ namespace Robust.UnitTesting channel.Disconnect(reason); } - INetChannel IClientNetManager.ServerChannel => ServerChannel; + INetChannel? IClientNetManager.ServerChannel => ServerChannel; public ClientConnectionState ClientConnectState => ClientConnectionState.NotConnecting; public event Action? ClientConnectStateChanged @@ -299,7 +299,7 @@ namespace Robust.UnitTesting remove { } } - private IntegrationNetChannel ServerChannel + private IntegrationNetChannel? ServerChannel { get { @@ -328,6 +328,11 @@ namespace Robust.UnitTesting public void ClientDisconnect(string reason) { DebugTools.Assert(IsClient); + if (ServerChannel == null) + { + return; + } + Disconnect?.Invoke(this, new NetDisconnectedArgs(ServerChannel, reason)); Shutdown(reason); }