]> git.deb.at Git - rhonda/impostor.git/commitdiff
Fix warnings
authorjs6pak <kubastaron@hotmail.com>
Wed, 24 Mar 2021 15:38:23 +0000 (16:38 +0100)
committerjs6pak <kubastaron@hotmail.com>
Wed, 24 Mar 2021 15:38:23 +0000 (16:38 +0100)
89 files changed:
src/Impostor.Api/Events/IManualEventListener.cs
src/Impostor.Api/Exceptions/ImpostorConfigException.cs
src/Impostor.Api/Exceptions/ImpostorException.cs
src/Impostor.Api/Exceptions/ImpostorProtocolException.cs
src/Impostor.Api/Games/IGame.cs
src/Impostor.Api/Impostor.Api.csproj
src/Impostor.Api/Innersloth/DisconnectReason.cs
src/Impostor.Api/Innersloth/GameCodeParser.cs
src/Impostor.Api/Innersloth/GameOverReason.cs
src/Impostor.Api/Innersloth/RegionInfo.cs
src/Impostor.Api/Innersloth/ServerInfo.cs
src/Impostor.Api/Innersloth/SystemTypes.cs
src/Impostor.Api/Innersloth/TaskBarUpdate.cs
src/Impostor.Api/Net/IConnection.cs
src/Impostor.Api/Net/Inner/IGameNet.cs
src/Impostor.Api/Net/Inner/Objects/IInnerShipStatus.cs
src/Impostor.Api/Net/Inner/Objects/IInnerVoteBanSystem.cs
src/Impostor.Api/Net/Inner/RpcCalls.cs
src/Impostor.Api/ProjectRules.ruleset [deleted file]
src/Impostor.Benchmarks/Data/MessageWriter.cs
src/Impostor.Client.App/Impostor.Client.App.csproj
src/Impostor.Client/Impostor.Client.csproj
src/Impostor.Hazel/Impostor.Hazel.csproj
src/Impostor.Hazel/NetworkConnection.cs
src/Impostor.Hazel/Udp/UdpServerConnection.cs
src/Impostor.Patcher/Impostor.Patcher.Cli/Impostor.Patcher.Cli.csproj
src/Impostor.Patcher/Impostor.Patcher.Shared/Impostor.Patcher.Shared.csproj
src/Impostor.Patcher/Impostor.Patcher.WinForms/Impostor.Patcher.WinForms.csproj
src/Impostor.Plugins.Debugger/Impostor.Plugins.Debugger.csproj
src/Impostor.Plugins.Example/Impostor.Plugins.Example.csproj
src/Impostor.Server/Config/AnnouncementsServerConfig.cs
src/Impostor.Server/Config/DebugConfig.cs
src/Impostor.Server/Config/ServerConfig.cs
src/Impostor.Server/Config/ServerRedirectorConfig.cs
src/Impostor.Server/Config/ServerRedirectorNode.cs
src/Impostor.Server/Events/EventHandler.cs
src/Impostor.Server/Events/EventManager.cs
src/Impostor.Server/Events/Game/GameEndedEvent.cs
src/Impostor.Server/Events/Register/IRegisteredEventListener.cs
src/Impostor.Server/Events/Register/InvokedRegisteredEventListener.cs
src/Impostor.Server/Events/Register/ManualRegisteredEventListener.cs
src/Impostor.Server/Events/Register/RegisteredEventListener.cs
src/Impostor.Server/Events/Register/WrappedRegisteredEventListener.cs
src/Impostor.Server/Impostor.Server.csproj
src/Impostor.Server/Net/AnnouncementsService.cs
src/Impostor.Server/Net/Client.cs
src/Impostor.Server/Net/ClientBase.cs
src/Impostor.Server/Net/Hazel/HazelConnection.cs
src/Impostor.Server/Net/Inner/InnerNetObject.cs
src/Impostor.Server/Net/Inner/Objects/Components/InnerCustomNetworkTransform.Api.cs
src/Impostor.Server/Net/Inner/Objects/Components/InnerCustomNetworkTransform.cs
src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.Api.cs
src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.PlayerVoteArea.cs
src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.cs
src/Impostor.Server/Net/Inner/Objects/InnerPlayerControl.Api.cs
src/Impostor.Server/Net/Inner/Objects/InnerPlayerControl.cs
src/Impostor.Server/Net/Inner/Objects/InnerPlayerInfo.cs
src/Impostor.Server/Net/Inner/Objects/Systems/ShipStatus/DoorsSystemType.cs
src/Impostor.Server/Net/Manager/ClientManager.cs
src/Impostor.Server/Net/Manager/GameManager.cs
src/Impostor.Server/Net/Matchmaker.cs
src/Impostor.Server/Net/Redirector/INodeLocator.cs
src/Impostor.Server/Net/Redirector/NodeLocatorNoOp.cs
src/Impostor.Server/Net/Redirector/NodeLocatorRedis.cs
src/Impostor.Server/Net/Redirector/NodeLocatorUDP.cs
src/Impostor.Server/Net/Redirector/NodeLocatorUDPService.cs
src/Impostor.Server/Net/State/ClientPlayer.cs
src/Impostor.Server/Net/State/Game.Api.cs
src/Impostor.Server/Net/State/Game.Data.cs
src/Impostor.Server/Net/State/Game.Incoming.cs
src/Impostor.Server/Net/State/Game.State.cs
src/Impostor.Server/Net/State/Game.cs
src/Impostor.Server/Net/State/GameNet.Api.cs
src/Impostor.Server/Net/State/GameNet.cs
src/Impostor.Server/Plugins/AssemblyInformation.cs
src/Impostor.Server/Plugins/PluginInformation.cs
src/Impostor.Server/Plugins/PluginLoader.cs
src/Impostor.Server/Plugins/PluginLoaderException.cs
src/Impostor.Server/Plugins/PluginLoaderService.cs
src/Impostor.Server/Program.cs
src/Impostor.Server/ProjectRules.ruleset [deleted file]
src/Impostor.Server/Recorder/PacketRecorder.cs
src/Impostor.Server/Recorder/PacketSerializationContext.cs
src/Impostor.Server/Recorder/RecordedPacketType.cs
src/Impostor.Tests/Impostor.Tests.csproj
src/Impostor.Tools.Proxy/Impostor.Tools.Proxy.csproj
src/Impostor.Tools.ServerReplay/Impostor.Tools.ServerReplay.csproj
src/Impostor.Tools.ServerReplay/Mocks/MockHazelConnection.cs
src/ProjectRules.ruleset [new file with mode: 0644]

index b5c140ef88b74402ac1470a13867d63636ad10b5..1b054f7504592e0eaa9c2510eae2ff0372317354 100644 (file)
@@ -4,10 +4,10 @@ namespace Impostor.Api.Events
 {
     public interface IManualEventListener : IEventListener
     {
+        EventPriority Priority { get; set; }
+
         public bool CanExecute<T>();
 
         public ValueTask Execute(IEvent @event);
-
-        EventPriority Priority { get; set; }
     }
-}
\ No newline at end of file
+}
index 1e59a9baf141f975f4f40e2bedcc4fb78df663e1..01b20d4c67a3c69e1f457b7640a0f21cc071e9bb 100644 (file)
@@ -9,15 +9,15 @@ namespace Impostor.Api
         {
         }
 
-        protected ImpostorConfigException(SerializationInfo info, StreamingContext context) : base(info, context)
+        public ImpostorConfigException(string? message) : base(message)
         {
         }
 
-        public ImpostorConfigException(string? message) : base(message)
+        public ImpostorConfigException(string? message, Exception? innerException) : base(message, innerException)
         {
         }
 
-        public ImpostorConfigException(string? message, Exception? innerException) : base(message, innerException)
+        protected ImpostorConfigException(SerializationInfo info, StreamingContext context) : base(info, context)
         {
         }
     }
index 188c50e85dad95190b4104edb29e9b0ee8949acf..03891942d0f01b57808ce8c6319436fcd6929fa2 100644 (file)
@@ -9,16 +9,16 @@ namespace Impostor.Api
         {
         }
 
-        protected ImpostorException(SerializationInfo info, StreamingContext context) : base(info, context)
+        public ImpostorException(string? message) : base(message)
         {
         }
 
-        public ImpostorException(string? message) : base(message)
+        public ImpostorException(string? message, Exception? innerException) : base(message, innerException)
         {
         }
 
-        public ImpostorException(string? message, Exception? innerException) : base(message, innerException)
+        protected ImpostorException(SerializationInfo info, StreamingContext context) : base(info, context)
         {
         }
     }
-}
\ No newline at end of file
+}
index 864602d040b0bd90032f5a0f2f0d0a685f160b2e..513e590e45ccac88a1c7529a843d13c250fc68d2 100644 (file)
@@ -9,15 +9,15 @@ namespace Impostor.Api
         {
         }
 
-        protected ImpostorProtocolException(SerializationInfo info, StreamingContext context) : base(info, context)
+        public ImpostorProtocolException(string? message) : base(message)
         {
         }
 
-        public ImpostorProtocolException(string? message) : base(message)
+        public ImpostorProtocolException(string? message, Exception? innerException) : base(message, innerException)
         {
         }
 
-        public ImpostorProtocolException(string? message, Exception? innerException) : base(message, innerException)
+        protected ImpostorProtocolException(SerializationInfo info, StreamingContext context) : base(info, context)
         {
         }
     }
index 57c3fcd2551ca23935aebe441d36dac5d7974f62..58e92085f2a86837262510e93dd56a06a8c46b51 100644 (file)
@@ -37,7 +37,7 @@ namespace Impostor.Api.Games
 
         int HostId { get; }
 
-        IClientPlayer GetClientPlayer(int clientId);
+        IClientPlayer? GetClientPlayer(int clientId);
 
         T? FindObjectByNetId<T>(uint netId)
             where T : IInnerNetObject;
index 188f2a677704242674c994985b6f9f827b675936..33c2ea01e6f1a83d7ffbddef895161dc4b8147d6 100644 (file)
@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <TargetFramework>netstandard2.1</TargetFramework>
-    <CodeAnalysisRuleSet>ProjectRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSet>../ProjectRules.ruleset</CodeAnalysisRuleSet>
     <LangVersion>9</LangVersion>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <Nullable>enable</Nullable>
@@ -33,4 +33,4 @@
     </PackageReference>
   </ItemGroup>
 
-</Project>
\ No newline at end of file
+</Project>
index 9526f58b1bb8d104c94f62ef26365abf022a9269..21cdc944cdbada3d903a7e9f82440f0ee70aaa4a 100644 (file)
@@ -3,52 +3,66 @@
     public enum DisconnectReason
     {
         ExitGame = 0,
+        Destroy = 16,
+
         // The game you tried to join is full.
         // Check with the host to see if you can join next round.
         GameFull = 1,
+
         // The game you tried to join already started.
         // Check with the host to see if you can join next round.
         GameStarted = 2,
-        // Could not find the game you're looking for.
+
+        // Could not find the game you're looking for..
         GameMissing = 3,
         IncorrectGame = 18,
-        // For these a message can be given, specifying an empty message shows
+
+        // For this a message can be given, specifying an empty message shows
         // "An unknown error disconnected you from the server."
-        CustomMessage1 = 4,
+        // 4, 12, 13, 14, 15 also count as Custom
         Custom = 8,
-        // CustomMessage3 = 11,
-        // CustomMessage4 = 12,
-        // CustomMessage5 = 13,
-        // CustomMessage6 = 14,
-        // CustomMessage7 = 15,
+
         // You are running an older version of the game.
         // Please update to play with others.
         IncorrectVersion = 5,
+
+        // You were banned from { GameCode ?? "the room" }
         // You cannot rejoin that room.
-        // You were banned
         Banned = 6,
-        // You can rejoin if the room hasn't started
-        // You were kicked
+
+        // You were kicked from { GameCode ?? "the room" }
+        // You can rejoin if the room hasn't started.
         Kicked = 7,
+
         // You were banned for hacking.
         // Please stop.
         Hacking = 10,
-        Destroy = 16,
+
+        // GameModes.LocalGame:
         // You disconnected from the host.
         // If this happens often, check your WiFi strength.
         //
+        // GameModes.OnlineGame:
         // You disconnected from the server.
         // If this happens often, check your network strength.
         // This may also be a server issue.
         Error = 17,
+
         // The server stopped this game. Possibly due to inactivity.
         ServerRequest = 19,
+
         // The Among Us servers are overloaded.
         // Sorry! Please try again later!
         ServerFull = 20,
+
         FocusLostBackground = 207,
+
+        // You may not join another game for another { BanMinutesLeft } minutes after intentionally disconnecting.
         IntentionalLeaving = 208,
+
+        // You were disconnected because Among Us was suspended by another app.
         FocusLost = 209,
+
         NewConnection = 210,
     }
-}
\ No newline at end of file
+}
index 9717cff2301bb79df65195a3a62c91a6c6beffc5..f4743c5642dbfd09b8e2fffeaa0c842e757dae3d 100644 (file)
@@ -9,36 +9,11 @@ namespace Impostor.Api.Innersloth
     public static class GameCodeParser
     {
         private const string V2 = "QWXRTYLPESDFGHUJKZOCVBINMA";
-        private static readonly int[] V2Map = {
-            25,
-            21,
-            19,
-            10,
-            8,
-            11,
-            12,
-            13,
-            22,
-            15,
-            16,
-            6,
-            24,
-            23,
-            18,
-            7,
-            0,
-            3,
-            9,
-            4,
-            14,
-            20,
-            1,
-            2,
-            5,
-            17
-        };
+
+        private static readonly int[] V2Map = Enumerable.Range(65, 26).Select(v => V2.IndexOf((char)v)).ToArray();
+
         private static readonly RNGCryptoServiceProvider Random = new RNGCryptoServiceProvider();
-        
+
         public static string IntToGameName(int input)
         {
             // V2.
@@ -57,22 +32,6 @@ namespace Impostor.Api.Innersloth
 #endif
         }
 
-        private static string IntToGameNameV2(int input)
-        {
-            var a = input & 0x3FF;
-            var b = (input >> 10) & 0xFFFFF;
-
-            return new string(new []
-            {
-                V2[a % 26],
-                V2[a / 26],
-                V2[b % 26],
-                V2[b / 26 % 26],
-                V2[b / (26 * 26) % 26],
-                V2[b / (26 * 26 * 26) % 26]
-            });
-        }
-
         public static int GameNameToInt(string code)
         {
             var upper = code.ToUpperInvariant();
@@ -80,7 +39,7 @@ namespace Impostor.Api.Innersloth
             {
                 return -1;
             }
-            
+
             var len = code.Length;
             if (len == 6)
             {
@@ -91,23 +50,8 @@ namespace Impostor.Api.Innersloth
             {
                 return code[0] | ((code[1] | ((code[2] | (code[3] << 8)) << 8)) << 8);
             }
-            
-            return -1;
-        }
-        
-        private static int GameNameToIntV2(string code)
-        {
-            var a = V2Map[code[0] - 65];
-            var b = V2Map[code[1] - 65];
-            var c = V2Map[code[2] - 65];
-            var d = V2Map[code[3] - 65];
-            var e = V2Map[code[4] - 65];
-            var f = V2Map[code[5] - 65];
-
-            var one = (a + 26 * b) & 0x3FF;
-            var two = (c + 26 * (d + 26 * (e + 26 * f)));
 
-            return (int) (one | ((two << 10) & 0x3FFFFC00) | 0x80000000);
+            return -1;
         }
 
         public static int GenerateCode(int len)
@@ -116,7 +60,7 @@ namespace Impostor.Api.Innersloth
             {
                 throw new ArgumentException("should be 4 or 6", nameof(len));
             }
-            
+
             // Generate random bytes.
 #if NETSTANDARD2_0
             var data = new byte[len];
@@ -124,7 +68,7 @@ namespace Impostor.Api.Innersloth
             Span<byte> data = stackalloc byte[len];
 #endif
             Random.GetBytes(data);
-            
+
             // Convert to their char representation.
             Span<char> dataChar = stackalloc char[len];
             for (var i = 0; i < len; i++)
@@ -138,5 +82,36 @@ namespace Impostor.Api.Innersloth
             return GameNameToInt(new string(dataChar));
 #endif
         }
+
+        private static string IntToGameNameV2(int input)
+        {
+            var a = input & 0x3FF;
+            var b = (input >> 10) & 0xFFFFF;
+
+            return new string(new[]
+            {
+                V2[a % 26],
+                V2[a / 26],
+                V2[b % 26],
+                V2[(b / 26) % 26],
+                V2[(b / (26 * 26)) % 26],
+                V2[(b / (26 * 26 * 26)) % 26],
+            });
+        }
+
+        private static int GameNameToIntV2(string code)
+        {
+            var a = V2Map[code[0] - 65];
+            var b = V2Map[code[1] - 65];
+            var c = V2Map[code[2] - 65];
+            var d = V2Map[code[3] - 65];
+            var e = V2Map[code[4] - 65];
+            var f = V2Map[code[5] - 65];
+
+            var one = (a + (26 * b)) & 0x3FF;
+            var two = c + (26 * (d + (26 * (e + (26 * f)))));
+
+            return (int)(one | ((two << 10) & 0x3FFFFC00) | 0x80000000);
+        }
     }
-}
\ No newline at end of file
+}
index 6a95d3747bb7c3d3a8963983c7336d15fbea63d0..5c30036c5e03903382910f036de1a28ae33ed8e7 100644 (file)
@@ -7,9 +7,7 @@
         ImpostorByVote = 2,
         ImpostorByKill = 3,
         ImpostorBySabotage = 4,
-        
-        // Unused (?)
         ImpostorDisconnect = 5,
         HumansDisconnect = 6,
     }
-}
\ No newline at end of file
+}
index c78978bd561c6d24775b957f79a822df9fe5f032..51580db1a756eebe1820344f5aaeb63280f6d3c9 100644 (file)
@@ -13,21 +13,10 @@ namespace Impostor.Api.Innersloth
         }
 
         public string Name { get; }
-        public string Ping { get; }
-        public IReadOnlyList<ServerInfo> Servers { get; }
 
-        public void Serialize(BinaryWriter writer)
-        {
-            writer.Write(0);
-            writer.Write(Name);
-            writer.Write(Ping);
-            writer.Write(Servers.Count);
+        public string Ping { get; }
 
-            foreach (var server in Servers)
-            {
-                server.Serialize(writer);
-            }
-        }
+        public IReadOnlyList<ServerInfo> Servers { get; }
 
         public static RegionInfo Deserialize(BinaryReader reader)
         {
@@ -44,5 +33,18 @@ namespace Impostor.Api.Innersloth
 
             return new RegionInfo(name, ping, servers);
         }
+
+        public void Serialize(BinaryWriter writer)
+        {
+            writer.Write(0);
+            writer.Write(Name);
+            writer.Write(Ping);
+            writer.Write(Servers.Count);
+
+            foreach (var server in Servers)
+            {
+                server.Serialize(writer);
+            }
+        }
     }
-}
\ No newline at end of file
+}
index 7785823493a925628a9bc2fc6c6f33cca8b4fdb3..21ba1ea7cab37a46d8fec035ff541adbc81eb581 100644 (file)
@@ -5,24 +5,18 @@ namespace Impostor.Api.Innersloth
 {
     public class ServerInfo
     {
-        public string Name { get; }
-        public string Ip { get; }
-        public ushort Port { get; }
-
         public ServerInfo(string name, string ip, ushort port)
         {
             Name = name;
             Ip = ip;
             Port = port;
         }
-        
-        public void Serialize(BinaryWriter writer)
-        {
-            writer.Write(Name);
-            writer.Write(IPAddress.Parse(Ip).GetAddressBytes());
-            writer.Write(Port);
-            writer.Write(0);
-        }
+
+        public string Name { get; }
+
+        public string Ip { get; }
+
+        public ushort Port { get; }
 
         public static ServerInfo Deserialize(BinaryReader reader)
         {
@@ -30,8 +24,16 @@ namespace Impostor.Api.Innersloth
             var ip = new IPAddress(reader.ReadBytes(4)).ToString();
             var port = reader.ReadUInt16();
             var unknown = reader.ReadInt32();
-            
+
             return new ServerInfo(name, ip, port);
         }
+
+        public void Serialize(BinaryWriter writer)
+        {
+            writer.Write(Name);
+            writer.Write(IPAddress.Parse(Ip).GetAddressBytes());
+            writer.Write(Port);
+            writer.Write(0);
+        }
     }
-}
\ No newline at end of file
+}
index 7f91718b3b8e2b0961b0591eb2edf4d036372bc6..5de8bc94d58012ab9c65d33e1d2c2cc47b8d7b95 100644 (file)
@@ -3,40 +3,69 @@
     public enum SystemTypes : byte
     {
         Hallway = 0,
+
         Storage = 1,
+
         Cafeteria = 2,
+
         Reactor = 3,
+
         UpperEngine = 4,
+
         Nav = 5,
+
         Admin = 6,
+
         Electrical = 7,
+
         LifeSupp = 8,
+
         Shields = 9,
+
         MedBay = 10,
+
         Security = 11,
+
         Weapons = 12,
+
         LowerEngine = 13,
+
         Comms = 14,
+
         ShipTasks = 15,
+
         Doors = 16,
+
         Sabotage = 17,
+
         /// <summary>
         /// Decontam on Mira and bottom decontam on Polus
         /// </summary>
         Decontamination = 18,
+
         Launchpad = 19,
+
         LockerRoom = 20,
+
         Laboratory = 21,
+
         Balcony = 22,
+
         Office = 23,
+
         Greenhouse = 24,
+
         Dropship = 25,
+
         /// <summary>
         /// Top decontam on Polus
         /// </summary>
         Decontamination2 = 26,
+
         Outside = 27,
+
         Specimens = 28,
-        BoilerRoom = 29
+
+        BoilerRoom = 29,
     }
-}
\ No newline at end of file
+}
index f4d7c1f69681422b73f2a5455cfa8c698b1faf5a..ea9a5fc5bd6dc32536a99180a528b6769d19c2f5 100644 (file)
@@ -4,6 +4,6 @@
     {
         Always = 0,
         Meetings = 1,
-        Never = 2
+        Never = 2,
     }
-}
\ No newline at end of file
+}
index 94f9b8be380f95d6e72b2bae3a436493161fab70..fa998414fca3ee390c2dd63eedf571e763709d67 100644 (file)
@@ -2,6 +2,5 @@
 {
     public interface IConnection
     {
-        
     }
-}
\ No newline at end of file
+}
index 933a4de684e04b89506c8caa820fed977770c1d5..9cac0f2dbc4e864e33c7c849e51c4cfe0a0365e0 100644 (file)
@@ -7,12 +7,12 @@ namespace Impostor.Api.Net.Inner
     /// </summary>
     public interface IGameNet
     {
-        IInnerLobbyBehaviour LobbyBehaviour { get; }
+        IInnerLobbyBehaviour? LobbyBehaviour { get; }
 
-        IInnerGameData GameData { get; }
+        IInnerGameData? GameData { get; }
 
-        IInnerVoteBanSystem VoteBan { get; }
+        IInnerVoteBanSystem? VoteBan { get; }
 
-        IInnerShipStatus ShipStatus { get; }
+        IInnerShipStatus? ShipStatus { get; }
     }
-}
\ No newline at end of file
+}
index c0a05aeae276a7a8f8de9bc1cbec41cdcb13ee8a..79b9f964967bb9015a3f60d79c7dcc9a2ac48324 100644 (file)
@@ -2,6 +2,5 @@
 {
     public interface IInnerShipStatus : IInnerNetObject
     {
-
     }
-}
\ No newline at end of file
+}
index d0a816dc02d08431a5550eed002a57f102643f82..8d8b4ac69925f266dd180d751ac48d182699aa01 100644 (file)
@@ -2,6 +2,5 @@
 {
     public interface IInnerVoteBanSystem : IInnerNetObject
     {
-
     }
-}
\ No newline at end of file
+}
index f82d2e89e5eed0b997b0de09ced6118e9a761ad1..e75f80ec228323a78159ac5f50e0f562f1079357 100644 (file)
@@ -33,6 +33,6 @@
         RepairSystem = 28,
         SetTasks = 29,
         UpdateGameData = 30,
-        CustomRpc = byte.MaxValue
+        CustomRpc = byte.MaxValue,
     }
-}
\ No newline at end of file
+}
diff --git a/src/Impostor.Api/ProjectRules.ruleset b/src/Impostor.Api/ProjectRules.ruleset
deleted file mode 100644 (file)
index 51021f5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<RuleSet Name="Rules for Hello World project" Description="These rules focus on critical issues for the Hello World app." ToolsVersion="10.0">
-    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.OrderingRules">
-        <Rule Id="SA1200" Action="None" />
-    </Rules>
-    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.DocumentationRules">
-        <Rule Id="SA1600" Action="None" />
-        <Rule Id="SA1601" Action="None" />
-        <Rule Id="SA1602" Action="None" />
-        <Rule Id="SA1633" Action="None" />
-    </Rules>
-    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.ReadabilityRules">
-      <Rule Id="SA1101" Action="None" />
-      <Rule Id="SA1111" Action="None" />
-    </Rules>
-    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.NamingRules">
-        <Rule Id="SA1309" Action="None" />
-    </Rules>
-</RuleSet>
\ No newline at end of file
index 94ff4418ff56a5741849dfa3fad5ddb42993143f..42f452ac7b30d23a535e99366ee9d4def79e4dee 100644 (file)
@@ -9,8 +9,6 @@ namespace Impostor.Benchmarks.Data
 {
     public class MessageWriter
     {
-        private static int BufferSize = 64000;
-
         public MessageType SendOption { get; private set; }
 
         private Stack<int> messageStarts = new Stack<int>();
index 886e26e8033824e2ddceaf509afbe08adedfbdca..3e5adc84ffd5f078b7b488a6b1714e1f1dc835cf 100644 (file)
@@ -1,16 +1,16 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-    <PropertyGroup>
-        <OutputType>Exe</OutputType>
-        <TargetFramework>net5.0</TargetFramework>
-    </PropertyGroup>
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net5.0</TargetFramework>
+  </PropertyGroup>
 
-    <ItemGroup>
-      <ProjectReference Include="..\Impostor.Client\Impostor.Client.csproj" />
-    </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Impostor.Client\Impostor.Client.csproj" />
+  </ItemGroup>
 
-    <ItemGroup>
-      <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
-    </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
+  </ItemGroup>
 
 </Project>
index 28b6ed3cd24b2be1a3bd35698a18e0c8ab823dd8..cbde5b66210a3abbc765771ed4bb15b96eea7dec 100644 (file)
@@ -1,12 +1,12 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-    <PropertyGroup>
-        <TargetFramework>net5.0</TargetFramework>
-    </PropertyGroup>
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+  </PropertyGroup>
 
-    <ItemGroup>
-      <ProjectReference Include="..\Impostor.Api\Impostor.Api.csproj" />
-      <ProjectReference Include="..\Impostor.Hazel\Impostor.Hazel.csproj" />
-    </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Impostor.Api\Impostor.Api.csproj" />
+    <ProjectReference Include="..\Impostor.Hazel\Impostor.Hazel.csproj" />
+  </ItemGroup>
 
 </Project>
index 00997697c8109d0db4e4c5e3a121f967ee6c5c84..7ab52af6fbcde0930b6f4115cec3059ce04febdf 100644 (file)
@@ -1,18 +1,18 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-    <PropertyGroup>
-        <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
-        <TargetFramework>net5.0</TargetFramework>
-        <DefineConstants>HAZEL_BAG</DefineConstants>
-    </PropertyGroup>
+  <PropertyGroup>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <TargetFramework>net5.0</TargetFramework>
+    <DefineConstants>HAZEL_BAG</DefineConstants>
+  </PropertyGroup>
 
-    <ItemGroup>
-        <PackageReference Include="Microsoft.Extensions.ObjectPool" Version="5.0.0" />
-        <PackageReference Include="Serilog" Version="2.10.0" />
-    </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="Microsoft.Extensions.ObjectPool" Version="5.0.4" />
+    <PackageReference Include="Serilog" Version="2.10.0" />
+  </ItemGroup>
 
-    <ItemGroup>
-      <ProjectReference Include="..\Impostor.Api\Impostor.Api.csproj" />
-    </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Impostor.Api\Impostor.Api.csproj" />
+  </ItemGroup>
 
 </Project>
index 282fe10789a73c3e37a4f644442e9f8d16827666..9e81c5cc074252b16b8c9da546a7d63897c1f713 100644 (file)
@@ -37,15 +37,11 @@ namespace Impostor.Hazel
 
         public long GetIP4Address()
         {
-            if (IPMode == IPMode.IPv4)
-            {
-                return ((IPEndPoint)this.RemoteEndPoint).Address.Address;
-            }
-            else
-            {
-                var bytes = ((IPEndPoint)this.RemoteEndPoint).Address.GetAddressBytes();
-                return BitConverter.ToInt64(bytes, bytes.Length - 8);
-            }
+            var bytes = this.RemoteEndPoint.Address.GetAddressBytes();
+
+            return IPMode == IPMode.IPv4
+                ? (uint)((bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0]) & 0x0FFFFFFFF)
+                : BitConverter.ToInt64(bytes, bytes.Length - 8);
         }
 
         /// <summary>
index 22eed988f295413923f4f332cb2b6724d4feafbe..8d3426e38a2917f165a9ebac8ccd2590cc6472b7 100644 (file)
@@ -88,7 +88,7 @@ namespace Impostor.Hazel.Udp
 
             if (disposing)
             {
-                SendDisconnect();
+                _ = SendDisconnect();
             }
 
             base.Dispose(disposing);
index c59fa87849d001e6be46accfad65a9f9d6d49cfd..7835c4ffb2dce654afe202f395e03cdaf2ece288 100644 (file)
@@ -1,19 +1,19 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-    <PropertyGroup>
-        <AssemblyName>Impostor.Cli</AssemblyName>
-        <TargetFramework>net5.0</TargetFramework>
-        <RuntimeIdentifiers>win-x64;linux-x64;linux-arm;linux-arm64;osx-x64</RuntimeIdentifiers>
-        <OutputType>Exe</OutputType>
-        <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
-    </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyName>Impostor.Cli</AssemblyName>
+    <TargetFramework>net5.0</TargetFramework>
+    <RuntimeIdentifiers>win-x64;linux-x64;linux-arm;linux-arm64;osx-x64</RuntimeIdentifiers>
+    <OutputType>Exe</OutputType>
+    <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
+  </PropertyGroup>
 
-    <ItemGroup>
-        <ProjectReference Include="..\Impostor.Patcher.Shared\Impostor.Patcher.Shared.csproj" />
-    </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Impostor.Patcher.Shared\Impostor.Patcher.Shared.csproj" />
+  </ItemGroup>
 
-    <ItemGroup>
-        <PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20478.1" />
-    </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20478.1" />
+  </ItemGroup>
 
 </Project>
index 8d71e56cfa04f2185efe5f19f3f27d594c26bcce..3039810f947555a95d87a422af2285989295520c 100644 (file)
@@ -1,11 +1,11 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-    <PropertyGroup>
-        <TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
-    </PropertyGroup>
+  <PropertyGroup>
+    <TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Gameloop.Vdf" Version="0.6.1" />
+  </ItemGroup>
 
-    <ItemGroup>
-        <PackageReference Include="Gameloop.Vdf" Version="0.6.1" />
-    </ItemGroup>
-    
 </Project>
index 71494365f94729e215849634821ea2f4b3056aa0..83f6e269e8710f980d410b52f181c29cee8ad54d 100644 (file)
@@ -1,22 +1,22 @@
 <Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
-    
-    <PropertyGroup>
-        <AssemblyName>Impostor</AssemblyName>
-        <ProjectGuid>{804CF172-0C87-4423-9688-BD97D549891E}</ProjectGuid>
-        <OutputType>WinExe</OutputType>
-        <TargetFramework>net472</TargetFramework>
-        <UseWindowsForms>true</UseWindowsForms>
-        <Copyright>Copyright © AeonLucid 2020</Copyright>
-        <ApplicationIcon>icon.ico</ApplicationIcon>
-        <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
-        <GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
-    </PropertyGroup>
 
-    <ItemGroup>
-        <ProjectReference Include="..\Impostor.Patcher.Shared\Impostor.Patcher.Shared.csproj" />
-        <PackageReference Include="System.Resources.Extensions" Version="5.0.0" />
-        <Reference Include="System.Runtime.InteropServices.RuntimeInformation" />
-        <Reference Include="System.Windows.Forms" />
-    </ItemGroup>
+  <PropertyGroup>
+    <AssemblyName>Impostor</AssemblyName>
+    <ProjectGuid>{804CF172-0C87-4423-9688-BD97D549891E}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <TargetFramework>net472</TargetFramework>
+    <UseWindowsForms>true</UseWindowsForms>
+    <Copyright>Copyright © AeonLucid 2020</Copyright>
+    <ApplicationIcon>icon.ico</ApplicationIcon>
+    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
+  </PropertyGroup>
 
-</Project>
\ No newline at end of file
+  <ItemGroup>
+    <ProjectReference Include="..\Impostor.Patcher.Shared\Impostor.Patcher.Shared.csproj" />
+    <PackageReference Include="System.Resources.Extensions" Version="5.0.0" />
+    <Reference Include="System.Runtime.InteropServices.RuntimeInformation" />
+    <Reference Include="System.Windows.Forms" />
+  </ItemGroup>
+
+</Project>
index 9518e48e9709d3046dcbf10db5cbdc05a025c2cf..8fce4f8861e95d444d341317be2746001234cbf9 100644 (file)
@@ -1,16 +1,16 @@
 <Project Sdk="Microsoft.NET.Sdk.Web">
 
-    <PropertyGroup>
-        <TargetFramework>net5.0</TargetFramework>
-        <OutputType>Library</OutputType>
-    </PropertyGroup>
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+    <OutputType>Library</OutputType>
+  </PropertyGroup>
 
-    <ItemGroup>
-      <ProjectReference Include="..\Impostor.Api\Impostor.Api.csproj" />
-    </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Impostor.Api\Impostor.Api.csproj" />
+  </ItemGroup>
 
-    <ItemGroup>
-      <Folder Include="Properties\" />
-    </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Properties\" />
+  </ItemGroup>
 
-</Project>
\ No newline at end of file
+</Project>
index dd4724dc1b7e5cbf14785413baddca1411f9e557..f0ebef3dcff96b499ab6a20192111d2517c12b89 100644 (file)
@@ -3,7 +3,7 @@
   <PropertyGroup>
     <TargetFramework>netstandard2.1</TargetFramework>
   </PropertyGroup>
-  
+
   <ItemGroup>
     <ProjectReference Include="..\Impostor.Api\Impostor.Api.csproj" />
   </ItemGroup>
index 5d61ac04c60fc67b5c464fe4522f066cfa9c6c46..3ea3eb33a57170ca6cd76e1248d06956420d4f3f 100644 (file)
@@ -1,18 +1,27 @@
-using Impostor.Server.Utils;
+using System.Text.Json.Serialization;
+using Impostor.Server.Utils;
 
 namespace Impostor.Server.Config
 {
     internal class AnnouncementsServerConfig
     {
+        public const string Section = "AnnouncementsServer";
+
         private string? _resolvedListenIp;
 
-        public const string Section = "AnnouncementsServer";
+        [JsonConstructor]
+        public AnnouncementsServerConfig(bool enabled = true, string listenIp = "0.0.0.0", ushort listenPort = 22024)
+        {
+            Enabled = enabled;
+            ListenIp = listenIp;
+            ListenPort = listenPort;
+        }
 
-        public bool Enabled { get; set; } = true;
+        public bool Enabled { get; }
 
-        public string ListenIp { get; set; } = "0.0.0.0";
+        public string ListenIp { get; }
 
-        public ushort ListenPort { get; set; } = 22024;
+        public ushort ListenPort { get; }
 
         public string ResolveListenIp()
         {
index 630d1b488a2f494aec8591634639bd41ef9c87b0..ef37d3972da908a29cb981f3933a9efac32563a6 100644 (file)
@@ -1,11 +1,20 @@
-namespace Impostor.Server.Config
+using System.Text.Json.Serialization;
+
+namespace Impostor.Server.Config
 {
     public class DebugConfig
     {
         public const string Section = "Debug";
 
-        public bool GameRecorderEnabled { get; set; }
+        [JsonConstructor]
+        public DebugConfig(bool gameRecorderEnabled = false, string? gameRecorderPath = null)
+        {
+            GameRecorderEnabled = gameRecorderEnabled;
+            GameRecorderPath = gameRecorderPath;
+        }
+
+        public bool GameRecorderEnabled { get; }
 
-        public string GameRecorderPath { get; set; }
+        public string? GameRecorderPath { get; }
     }
-}
\ No newline at end of file
+}
index 1c584333f581225e9c3eb28bb4632b6d8a566013..7ed3ae64c0a42da7d8eba4bb5b59ddfbbfc45442 100644 (file)
@@ -4,11 +4,11 @@ namespace Impostor.Server.Config
 {
     internal class ServerConfig
     {
+        public const string Section = "Server";
+
         private string? _resolvedPublicIp;
         private string? _resolvedListenIp;
 
-        public const string Section = "Server";
-
         public string PublicIp { get; set; } = "127.0.0.1";
 
         public ushort PublicPort { get; set; } = 22023;
index 0ccfa0d4cc933a7b2feec6abbbdbf499585ce9dd..63285ad77271648fc8c920b15d38c8038631a91b 100644 (file)
@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using System.Text.Json.Serialization;
 
 namespace Impostor.Server.Config
 {
@@ -6,19 +7,35 @@ namespace Impostor.Server.Config
     {
         public const string Section = "ServerRedirector";
 
-        public bool Enabled { get; set; }
+        [JsonConstructor]
+        public ServerRedirectorConfig(bool enabled = false, bool master = false, NodeLocator? locator = null, List<ServerRedirectorNode>? nodes = null)
+        {
+            Enabled = enabled;
+            Master = master;
+            Locator = locator;
+            Nodes = nodes;
+        }
 
-        public bool Master { get; set; }
+        public bool Enabled { get; }
 
-        public NodeLocator Locator { get; set; }
+        public bool Master { get; }
 
-        public List<ServerRedirectorNode> Nodes { get; set; }
+        public NodeLocator? Locator { get; }
+
+        public List<ServerRedirectorNode>? Nodes { get; }
 
         public class NodeLocator
         {
-            public string Redis { get; set; }
+            [JsonConstructor]
+            public NodeLocator(string redis, string udpMasterEndpoint)
+            {
+                Redis = redis;
+                UdpMasterEndpoint = udpMasterEndpoint;
+            }
+
+            public string Redis { get; }
 
-            public string UdpMasterEndpoint { get; set; }
+            public string UdpMasterEndpoint { get; }
         }
     }
-}
\ No newline at end of file
+}
index d11b60ff31aa02054ab8495ed40f36123b675336..c5752bf6b08aa5123af042dce9e531f0dd7fa8d3 100644 (file)
@@ -1,9 +1,18 @@
-namespace Impostor.Server.Config
+using System.Text.Json.Serialization;
+
+namespace Impostor.Server.Config
 {
     public class ServerRedirectorNode
     {
-        public string Ip { get; set; }
+        [JsonConstructor]
+        public ServerRedirectorNode(string ip, ushort port)
+        {
+            Ip = ip;
+            Port = port;
+        }
+
+        public string Ip { get; }
 
-        public ushort Port { get; set; }
+        public ushort Port { get; }
     }
-}
\ No newline at end of file
+}
index 190f7f398918143bdf5a91e4eb0b95371d54a6b5..e185c9a1f8e965f97e67ce5848d7eef8210095cc 100644 (file)
@@ -5,20 +5,20 @@ namespace Impostor.Server.Events
 {
     internal readonly struct EventHandler
     {
-        public EventHandler(IEventListener o, IRegisteredEventListener listener)
+        public EventHandler(IEventListener? o, IRegisteredEventListener listener)
         {
             Object = o;
             Listener = listener;
         }
 
-        public IEventListener Object { get; }
+        public IEventListener? Object { get; }
 
         public IRegisteredEventListener Listener { get; }
 
-        public void Deconstruct(out IEventListener o, out IRegisteredEventListener listener)
+        public void Deconstruct(out IEventListener? o, out IRegisteredEventListener listener)
         {
             o = Object;
             listener = Listener;
         }
     }
-}
\ No newline at end of file
+}
index 0cc6e541efb424ecd16cd7dbdfe222f061169547..4ab2d15365465958a91848b96e2eb8f6ffc7471d 100644 (file)
@@ -27,7 +27,7 @@ namespace Impostor.Server.Events
         }
 
         /// <inheritdoc />
-        public IDisposable RegisterListener<TListener>(TListener listener, Func<Func<Task>, Task> invoker = null)
+        public IDisposable RegisterListener<TListener>(TListener listener, Func<Func<Task>, Task>? invoker = null)
             where TListener : IEventListener
         {
             if (listener == null)
index 4ec4dcf9214f15bf7e919f136baeaa0b51c05a3a..b0704cfc3dfecb615ffbd0d1460c6174ef7af02b 100644 (file)
@@ -13,7 +13,7 @@ namespace Impostor.Server.Events
         }
 
         public IGame Game { get; }
-        
+
         public GameOverReason GameOverReason { get; }
     }
 }
index 479a3f641fa732509b55244e2f0a9d14a55e62ae..3b39bc9b892c807ffc949ed7852b61ee512c0c7e 100644 (file)
@@ -10,6 +10,6 @@ namespace Impostor.Server.Events.Register
 
         EventPriority Priority { get; }
 
-        ValueTask InvokeAsync(object eventHandler, object @event, IServiceProvider provider);
+        ValueTask InvokeAsync(object? eventHandler, object @event, IServiceProvider provider);
     }
-}
\ No newline at end of file
+}
index a21c3b1f674bdb58e5f1a88845513dde256fb8e6..adec183b4424786631e34891a2dbbb410e85a2fa 100644 (file)
@@ -19,9 +19,9 @@ namespace Impostor.Server.Events.Register
 
         public EventPriority Priority => _innerObject.Priority;
 
-        public ValueTask InvokeAsync(object eventHandler, object @event, IServiceProvider provider)
+        public ValueTask InvokeAsync(object? eventHandler, object @event, IServiceProvider provider)
         {
             return new ValueTask(_invoker(() => _innerObject.InvokeAsync(eventHandler, @event, provider).AsTask()));
         }
     }
-}
\ No newline at end of file
+}
index e81e8f8447bee0d66ab4d156b095a2e3f79fdbe9..394f47d37ba4c7b37a90222076c4462734e8aef6 100644 (file)
@@ -6,8 +6,6 @@ namespace Impostor.Server.Events.Register
 {
     internal class ManualRegisteredEventListener : IRegisteredEventListener
     {
-        public Type EventType { get; } = typeof(object);
-
         private readonly IManualEventListener _manualEventListener;
 
         public ManualRegisteredEventListener(IManualEventListener manualEventListener)
@@ -15,9 +13,11 @@ namespace Impostor.Server.Events.Register
             _manualEventListener = manualEventListener;
         }
 
+        public Type EventType { get; } = typeof(object);
+
         public EventPriority Priority => _manualEventListener.Priority;
 
-        public ValueTask InvokeAsync(object eventHandler, object @event, IServiceProvider provider)
+        public ValueTask InvokeAsync(object? eventHandler, object @event, IServiceProvider provider)
         {
             if (@event is IEvent typedEvent)
             {
index 120a45ed365f0fbdb12ff737e588fd4da607c33f..6517aac8efdd0f6d382cd469a54f3374097054c5 100644 (file)
@@ -15,7 +15,7 @@ namespace Impostor.Server.Events.Register
         private static readonly PropertyInfo IsCancelledProperty = typeof(IEventCancelable).GetProperty(nameof(IEventCancelable.IsCancelled))!;
 
         private static readonly ConcurrentDictionary<Type, RegisteredEventListener[]> Instances = new ConcurrentDictionary<Type, RegisteredEventListener[]>();
-        private readonly Func<object, object, IServiceProvider, ValueTask> _invoker;
+        private readonly Func<object?, object, IServiceProvider, ValueTask> _invoker;
         private readonly Type _eventListenerType;
 
         public RegisteredEventListener(Type eventType, MethodInfo method, EventListenerAttribute attribute, Type eventListenerType)
@@ -38,12 +38,52 @@ namespace Impostor.Server.Events.Register
 
         public string Method { get; }
 
-        public ValueTask InvokeAsync(object eventHandler, object @event, IServiceProvider provider)
+        public static IReadOnlyList<RegisteredEventListener> FromType(Type type)
+        {
+            return Instances.GetOrAdd(type, t =>
+            {
+                return t.GetMethods()
+                    .Where(m => !m.IsStatic && m.GetCustomAttributes(typeof(EventListenerAttribute), false).Any())
+                    .SelectMany(m => FromMethod(t, m))
+                    .ToArray();
+            });
+        }
+
+        public static IEnumerable<RegisteredEventListener> FromMethod(Type listenerType, MethodInfo methodType)
+        {
+            // Get the return type.
+            var returnType = methodType.ReturnType;
+
+            if (returnType != typeof(void) && returnType != typeof(ValueTask))
+            {
+                throw new InvalidOperationException($"The method {methodType.GetFriendlyName()} does not return void or ValueTask.");
+            }
+
+            // Register the event.
+            foreach (var attribute in methodType.GetCustomAttributes<EventListenerAttribute>(false))
+            {
+                var eventType = attribute.Event;
+
+                if (eventType == null)
+                {
+                    if (methodType.GetParameters().Length == 0 || !typeof(IEvent).IsAssignableFrom(methodType.GetParameters()[0].ParameterType))
+                    {
+                        throw new InvalidOperationException($"The first parameter of the method {methodType.GetFriendlyName()} should be the type {nameof(IEvent)}.");
+                    }
+
+                    eventType = methodType.GetParameters()[0].ParameterType;
+                }
+
+                yield return new RegisteredEventListener(eventType, methodType, attribute, listenerType);
+            }
+        }
+
+        public ValueTask InvokeAsync(object? eventHandler, object @event, IServiceProvider provider)
         {
             return _invoker(eventHandler, @event, provider);
         }
 
-        private Func<object, object, IServiceProvider, ValueTask> CreateInvoker(MethodInfo method, bool ignoreCancelled)
+        private Func<object?, object, IServiceProvider, ValueTask> CreateInvoker(MethodInfo method, bool ignoreCancelled)
         {
             var instance = Expression.Parameter(typeof(object), "instance");
             var eventParameter = Expression.Parameter(typeof(object), "event");
@@ -119,48 +159,8 @@ namespace Impostor.Server.Events.Register
                 throw new InvalidOperationException($"The method {method.GetFriendlyName()} must return void or ValueTask.");
             }
 
-            return Expression.Lambda<Func<object, object, IServiceProvider, ValueTask>>(invoke,  instance, eventParameter, provider)
+            return Expression.Lambda<Func<object?, object, IServiceProvider, ValueTask>>(invoke,  instance, eventParameter, provider)
                 .Compile();
         }
-
-        public static IReadOnlyList<RegisteredEventListener> FromType(Type type)
-        {
-            return Instances.GetOrAdd(type, t =>
-            {
-                return t.GetMethods()
-                    .Where(m => !m.IsStatic && m.GetCustomAttributes(typeof(EventListenerAttribute), false).Any())
-                    .SelectMany(m => FromMethod(t, m))
-                    .ToArray();
-            });
-        }
-
-        public static IEnumerable<RegisteredEventListener> FromMethod(Type listenerType, MethodInfo methodType)
-        {
-            // Get the return type.
-            var returnType = methodType.ReturnType;
-
-            if (returnType != typeof(void) && returnType != typeof(ValueTask))
-            {
-                throw new InvalidOperationException($"The method {methodType.GetFriendlyName()} does not return void or ValueTask.");
-            }
-
-            // Register the event.
-            foreach (var attribute in methodType.GetCustomAttributes<EventListenerAttribute>(false))
-            {
-                var eventType = attribute.Event;
-
-                if (eventType == null)
-                {
-                    if (methodType.GetParameters().Length == 0 || !typeof(IEvent).IsAssignableFrom(methodType.GetParameters()[0].ParameterType))
-                    {
-                        throw new InvalidOperationException($"The first parameter of the method {methodType.GetFriendlyName()} should be the type {nameof(IEvent)}.");
-                    }
-
-                    eventType = methodType.GetParameters()[0].ParameterType;
-                }
-
-                yield return new RegisteredEventListener(eventType, methodType, attribute, listenerType);
-            }
-        }
     }
 }
index dd668c5ddf7d4056391db4a8dee91a093eb92733..d1a66ee84afb6ff414dab5b2ea13a50c841faf78 100644 (file)
@@ -19,9 +19,9 @@ namespace Impostor.Server.Events.Register
 
         public EventPriority Priority => _innerObject.Priority;
 
-        public ValueTask InvokeAsync(object eventHandler, object @event, IServiceProvider provider)
+        public ValueTask InvokeAsync(object? eventHandler, object @event, IServiceProvider provider)
         {
             return _innerObject.InvokeAsync(_object, @event, provider);
         }
     }
-}
\ No newline at end of file
+}
index 663f7af43bade6e32ee0b3174bb27d02ab202701..5cad72de69f6edf5767252c06e7caf6a7e80cede 100644 (file)
@@ -6,7 +6,7 @@
     <RuntimeIdentifiers>win-x64;linux-x64;linux-arm;linux-arm64;osx-x64</RuntimeIdentifiers>
     <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
     <ApplicationIcon>icon.ico</ApplicationIcon>
-    <CodeAnalysisRuleSet>ProjectRules.ruleset</CodeAnalysisRuleSet>
+    <CodeAnalysisRuleSet>../ProjectRules.ruleset</CodeAnalysisRuleSet>
     <Nullable>enable</Nullable>
     <SelfContained>false</SelfContained>
   </PropertyGroup>
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.1" />
     <PackageReference Include="Microsoft.Extensions.FileSystemGlobbing" Version="5.0.0" />
     <PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0" />
-    <PackageReference Include="Microsoft.Extensions.ObjectPool" Version="5.0.0" />
-    <PackageReference Include="Serilog.Extensions.Hosting" Version="3.1.0" />
+    <PackageReference Include="Microsoft.Extensions.ObjectPool" Version="5.0.4" />
+    <PackageReference Include="Serilog.Extensions.Hosting" Version="4.1.2" />
     <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
+    <PackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.333">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
index a58abf276fb6ea139cf171267a002ed9310e0856..6ca0bb9a12f41d2206d4995e745bd3b941489cb7 100644 (file)
@@ -24,7 +24,7 @@ namespace Impostor.Server.Net
         private readonly AnnouncementsServerConfig _config;
         private readonly ObjectPool<MessageReader> _readerPool;
         private readonly IEventManager _eventManager;
-        private UdpConnectionListener _connection;
+        private UdpConnectionListener? _connection;
 
         public AnnouncementsService(ILogger<AnnouncementsService> logger, IOptions<AnnouncementsServerConfig> config, ObjectPool<MessageReader> readerPool, IEventManager eventManager)
         {
@@ -42,7 +42,7 @@ namespace Impostor.Server.Net
             {
                 AddressFamily.InterNetwork => IPMode.IPv4,
                 AddressFamily.InterNetworkV6 => IPMode.IPv6,
-                _ => throw new InvalidOperationException()
+                _ => throw new InvalidOperationException(),
             };
 
             _connection = new UdpConnectionListener(endpoint, _readerPool, mode)
@@ -58,7 +58,11 @@ namespace Impostor.Server.Net
         public async Task StopAsync(CancellationToken cancellationToken)
         {
             _logger.LogWarning("Announcements server is shutting down!");
-            await _connection.DisposeAsync();
+
+            if (_connection != null)
+            {
+                await _connection.DisposeAsync();
+            }
         }
 
         private async ValueTask OnNewConnection(NewConnectionEventArgs e)
index f26de4026497d67c65abeacd491c02b643aef02b..45718e5830182a9659834b1b38c0b38548ef02d3 100644 (file)
@@ -131,7 +131,7 @@ namespace Impostor.Server.Net
                         return;
                     }
 
-                    await Player.Game.HandleStartGame(reader);
+                    await Player!.Game.HandleStartGame(reader);
                     break;
                 }
 
@@ -151,7 +151,7 @@ namespace Impostor.Server.Net
                         out var playerId,
                         out var reason);
 
-                    await Player.Game.HandleRemovePlayer(playerId, (DisconnectReason)reason);
+                    await Player!.Game.HandleRemovePlayer(playerId, (DisconnectReason)reason);
                     break;
                 }
 
@@ -168,7 +168,7 @@ namespace Impostor.Server.Net
                     // Handle packet.
                     using var readerCopy = reader.Copy();
 
-                    var verified = await Player.Game.HandleGameDataAsync(readerCopy, Player, toPlayer);
+                    var verified = await Player!.Game.HandleGameDataAsync(readerCopy, Player, toPlayer);
                     if (verified)
                     {
                         // Broadcast packet to all other players.
@@ -202,7 +202,7 @@ namespace Impostor.Server.Net
                         reader,
                         out var gameOverReason);
 
-                    await Player.Game.HandleEndGame(reader, gameOverReason);
+                    await Player!.Game.HandleEndGame(reader, gameOverReason);
                     break;
                 }
 
@@ -223,7 +223,7 @@ namespace Impostor.Server.Net
                         return;
                     }
 
-                    await Player.Game.HandleAlterGame(reader, Player, value);
+                    await Player!.Game.HandleAlterGame(reader, Player, value);
                     break;
                 }
 
@@ -239,7 +239,7 @@ namespace Impostor.Server.Net
                         out var playerId,
                         out var isBan);
 
-                    await Player.Game.HandleKickPlayer(playerId, isBan);
+                    await Player!.Game.HandleKickPlayer(playerId, isBan);
                     break;
                 }
 
index 7bff06efee2a74f861ba43f5886937d817a865be..78bcb9ec5807ba0d887933af8470598bf94c0e81 100644 (file)
@@ -64,7 +64,6 @@ namespace Impostor.Server.Net
 
         public abstract ValueTask HandleDisconnectAsync(string reason);
 
-
         public async ValueTask DisconnectAsync(DisconnectReason reason, string? message = null)
         {
             if (!Connection.IsConnected)
index 45d2be82741ba43f93297328111096e95b2b92ee..e663dec1bb28e6773179ff7e279c21f2a75c60d5 100644 (file)
@@ -25,14 +25,14 @@ namespace Impostor.Server.Net.Hazel
 
         public bool IsConnected => InnerConnection.State == ConnectionState.Connected;
 
-        public IClient Client { get; set; }
+        public IClient? Client { get; set; }
 
         public ValueTask SendAsync(IMessageWriter writer)
         {
             return InnerConnection.SendAsync(writer);
         }
 
-        public ValueTask DisconnectAsync(string reason)
+        public ValueTask DisconnectAsync(string? reason)
         {
             return InnerConnection.Disconnect(reason);
         }
index 9579fe0ad7d8f27864d685947c1ca7f203bf73c4..5b65f464cc4befbf6f340616e11f0db1c30dd0b9 100644 (file)
@@ -29,6 +29,7 @@ namespace Impostor.Server.Net.Inner
 
         public abstract ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader);
 
+        // TODO move to Reactor.Impostor plugin
         protected ValueTask<bool> HandleCustomRpc(IMessageReader reader, Game game)
         {
             var lengthOrShortId = reader.ReadPackedInt32();
@@ -39,8 +40,6 @@ namespace Impostor.Server.Net.Inner
 
             var id = reader.ReadPackedInt32();
 
-            // TODO handle custom rpcs
-
             return ValueTask.FromResult(true);
         }
     }
index 56ff96e5940c4a8c6b7387cd065bb377ddc61f9e..0e70bd64f12b74ae1b8e568273c1ad62b8649b66 100644 (file)
@@ -11,7 +11,7 @@ namespace Impostor.Server.Net.Inner.Objects.Components
             var minSid = (ushort)(_lastSequenceId + 5U);
 
             // Snap in the server.
-            await SnapToAsync(_game.GetClientPlayer(OwnerId), position, minSid);
+            await SnapToAsync(_game.GetClientPlayer(OwnerId)!, position, minSid);
 
             // Broadcast to all clients.
             using (var writer = _game.StartRpc(NetId, RpcCalls.SnapTo))
index 80dd6adf68c98f225eed7e13cd31a9c2b507d02f..0e475b8c20c938cfd42aae9706d0bac245aaec60 100644 (file)
@@ -23,10 +23,6 @@ namespace Impostor.Server.Net.Inner.Objects.Components
 
         private ushort _lastSequenceId;
 
-        public Vector2 Position { get; private set; }
-
-        public Vector2 Velocity { get; private set; }
-
         public InnerCustomNetworkTransform(ILogger<InnerCustomNetworkTransform> logger, InnerPlayerControl playerControl, Game game, IEventManager eventManager, ObjectPool<PlayerMovementEvent> pool)
         {
             _logger = logger;
@@ -37,14 +33,9 @@ namespace Impostor.Server.Net.Inner.Objects.Components
             _pool = pool;
         }
 
-        private static bool SidGreaterThan(ushort newSid, ushort prevSid)
-        {
-            var num = (ushort)(prevSid + (uint)short.MaxValue);
+        public Vector2 Position { get; private set; }
 
-            return (int)prevSid < (int)num
-                ? newSid > prevSid && newSid <= num
-                : newSid > prevSid || newSid <= num;
-        }
+        public Vector2 Velocity { get; private set; }
 
         public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
         {
@@ -120,6 +111,15 @@ namespace Impostor.Server.Net.Inner.Objects.Components
             _pool.Return(playerMovementEvent);
         }
 
+        private static bool SidGreaterThan(ushort newSid, ushort prevSid)
+        {
+            var num = (ushort)(prevSid + (uint)short.MaxValue);
+
+            return (int)prevSid < (int)num
+                ? newSid > prevSid && newSid <= num
+                : newSid > prevSid || newSid <= num;
+        }
+
         private ValueTask SnapToAsync(IClientPlayer sender, Vector2 position, ushort minSid)
         {
             if (!SidGreaterThan(minSid, _lastSequenceId))
index 5d120c5cf75916c0652c459e6c1f06825ff336d2..0219fbab20ba09ed5dc7756cc03ed52253af2aaf 100644 (file)
@@ -4,6 +4,5 @@ namespace Impostor.Server.Net.Inner.Objects
 {
     internal partial class InnerMeetingHud : IInnerMeetingHud
     {
-
     }
-}
\ No newline at end of file
+}
index fbf25102b9879ab8f905216bee5762b36954cc05..48f551b9a8d90205d01053c81487aaea1843fee7 100644 (file)
@@ -29,12 +29,6 @@ namespace Impostor.Server.Net.Inner.Objects
 
             public sbyte VotedFor { get; private set; }
 
-            internal void SetDead(bool didReport, bool isDead)
-            {
-                DidReport = didReport;
-                IsDead = isDead;
-            }
-
             public void Deserialize(IMessageReader reader)
             {
                 var num = reader.ReadByte();
@@ -44,6 +38,12 @@ namespace Impostor.Server.Net.Inner.Objects
                 DidVote = (num & VotedBit) > 0;
                 DidReport = (num & ReportedBit) > 0;
             }
+
+            internal void SetDead(bool didReport, bool isDead)
+            {
+                DidReport = didReport;
+                IsDead = isDead;
+            }
         }
     }
-}
\ No newline at end of file
+}
index 96d829fb87fa718a703abd8859495ccba9f5e76c..8f9c8f5e894087d038abc442eeb42228eade95e6 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Threading.Tasks;
 using Impostor.Api;
@@ -21,6 +22,8 @@ namespace Impostor.Server.Net.Inner.Objects
         private readonly IEventManager _eventManager;
         private readonly Game _game;
         private readonly GameNet _gameNet;
+
+        [AllowNull]
         private PlayerVoteArea[] _playerStates;
 
         public InnerMeetingHud(ILogger<InnerMeetingHud> logger, IEventManager eventManager, Game game)
@@ -36,18 +39,6 @@ namespace Impostor.Server.Net.Inner.Objects
 
         public byte ReporterId { get; private set; }
 
-        private void PopulateButtons(byte reporter)
-        {
-            _playerStates = _gameNet.GameData.Players
-                .Select(x =>
-                {
-                    var area = new PlayerVoteArea(this, x.Key);
-                    area.SetDead(x.Value.PlayerId == reporter, x.Value.Disconnected || x.Value.IsDead);
-                    return area;
-                })
-                .ToArray();
-        }
-
         public override ValueTask<bool> SerializeAsync(IMessageWriter writer, bool initialState)
         {
             throw new NotImplementedException();
@@ -142,12 +133,24 @@ namespace Impostor.Server.Net.Inner.Objects
             return true;
         }
 
+        private void PopulateButtons(byte reporter)
+        {
+            _playerStates = _gameNet.GameData!.Players
+                .Select(x =>
+                {
+                    var area = new PlayerVoteArea(this, x.Key);
+                    area.SetDead(x.Value.PlayerId == reporter, x.Value.Disconnected || x.Value.IsDead);
+                    return area;
+                })
+                .ToArray();
+        }
+
         private async ValueTask HandleVotingComplete(ClientPlayer sender, ReadOnlyMemory<byte> states, byte playerId, bool tie)
         {
             if (playerId != byte.MaxValue)
             {
-                var player = _game.GameNet.GameData.GetPlayerById(playerId);
-                if (player != null)
+                var player = _game.GameNet.GameData!.GetPlayerById(playerId);
+                if (player?.Controller != null)
                 {
                     player.Controller.Die(DeathReason.Exile);
                     await _eventManager.CallAsync(new PlayerExileEvent(_game, sender, player.Controller));
index e55f07920050ce696286ed39f00eabb74e80e5a1..604c6e644d02be7c9a4ed4f670008113714d94bf 100644 (file)
@@ -104,7 +104,7 @@ namespace Impostor.Server.Net.Inner.Objects
             Rpc12MurderPlayer.Serialize(writer, target);
             await _game.FinishRpcAsync(writer);
 
-            await _eventManager.CallAsync(new PlayerMurderEvent(_game, _game.GetClientPlayer(OwnerId), this, target));
+            await _eventManager.CallAsync(new PlayerMurderEvent(_game, _game.GetClientPlayer(OwnerId)!, this, target));
         }
 
         public async ValueTask ExileAsync()
@@ -123,7 +123,7 @@ namespace Impostor.Server.Net.Inner.Objects
             await _game.FinishRpcAsync(writer);
 
             // Notify plugins.
-            await _eventManager.CallAsync(new PlayerExileEvent(_game, _game.GetClientPlayer(OwnerId), this));
+            await _eventManager.CallAsync(new PlayerExileEvent(_game, _game.GetClientPlayer(OwnerId)!, this));
         }
     }
 }
index 8391ed08856bd0f3705be853ba3a7ac19cb06d13..8cd808dbbb1ca409ed0a909356b19f71902c4568 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Threading.Tasks;
 using Impostor.Api;
@@ -20,6 +21,8 @@ namespace Impostor.Server.Net.Inner.Objects
 {
     internal partial class InnerPlayerControl : InnerNetObject
     {
+        private static readonly byte ColorsCount = (byte)Enum.GetValues<ColorType>().Length;
+
         private readonly ILogger<InnerPlayerControl> _logger;
         private readonly IEventManager _eventManager;
         private readonly Game _game;
@@ -50,6 +53,7 @@ namespace Impostor.Server.Net.Inner.Objects
 
         public InnerCustomNetworkTransform NetworkTransform { get; }
 
+        [AllowNull]
         public InnerPlayerInfo PlayerInfo { get; internal set; }
 
         internal Queue<string> RequestedPlayerName { get; } = new Queue<string>();
@@ -76,12 +80,6 @@ namespace Impostor.Server.Net.Inner.Objects
             PlayerId = reader.ReadByte();
         }
 
-        internal void Die(DeathReason reason)
-        {
-            PlayerInfo.IsDead = true;
-            PlayerInfo.LastDeathReason = reason;
-        }
-
         public override async ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
         {
             switch (call)
@@ -297,6 +295,12 @@ namespace Impostor.Server.Net.Inner.Objects
             return true;
         }
 
+        internal void Die(DeathReason reason)
+        {
+            PlayerInfo.IsDead = true;
+            PlayerInfo.LastDeathReason = reason;
+        }
+
         private async ValueTask HandleCompleteTask(ClientPlayer sender, uint taskId)
         {
             var task = PlayerInfo.Tasks.ElementAtOrDefault((int)taskId);
@@ -316,7 +320,7 @@ namespace Impostor.Server.Net.Inner.Objects
         {
             for (var i = 0; i < infectedIds.Length; i++)
             {
-                var player = _game.GameNet.GameData.GetPlayerById(infectedIds.Span[i]);
+                var player = _game.GameNet.GameData!.GetPlayerById(infectedIds.Span[i]);
                 if (player != null)
                 {
                     player.IsImpostor = true;
@@ -428,8 +432,6 @@ namespace Impostor.Server.Net.Inner.Objects
             return true;
         }
 
-        private static readonly byte ColorsCount = (byte)Enum.GetValues<ColorType>().Length;
-
         private async ValueTask<bool> HandleCheckColor(ClientPlayer sender, ColorType color)
         {
             if ((byte)color > ColorsCount)
@@ -537,7 +539,7 @@ namespace Impostor.Server.Net.Inner.Objects
 
             PlayerInfo.LastMurder = _dateTimeProvider.UtcNow;
 
-            if (!target.PlayerInfo.IsDead)
+            if (target != null && !target.PlayerInfo.IsDead)
             {
                 ((InnerPlayerControl)target).Die(DeathReason.Kill);
                 await _eventManager.CallAsync(new PlayerMurderEvent(_game, sender, this, target));
@@ -556,8 +558,8 @@ namespace Impostor.Server.Net.Inner.Objects
 
         private async ValueTask HandleStartMeeting(byte targetId)
         {
-            var deadPlayer = _game.GameNet.GameData.GetPlayerById(targetId)?.Controller;
-            await _eventManager.CallAsync(new PlayerStartMeetingEvent(_game, _game.GetClientPlayer(this.OwnerId), this, deadPlayer));
+            var deadPlayer = _game.GameNet.GameData!.GetPlayerById(targetId)?.Controller;
+            await _eventManager.CallAsync(new PlayerStartMeetingEvent(_game, _game.GetClientPlayer(this.OwnerId)!, this, deadPlayer));
         }
 
         private async ValueTask<bool> HandleSetPet(ClientPlayer sender, PetType pet)
index 301fc08815189dd17fc0d4efa102e3542394623d..1d488fbdcd21a61aecb6201eccd742a044904cd7 100644 (file)
@@ -15,11 +15,11 @@ namespace Impostor.Server.Net.Inner.Objects
             PlayerId = playerId;
         }
 
-        public InnerPlayerControl Controller { get; internal set; }
+        public InnerPlayerControl? Controller { get; internal set; }
 
         public byte PlayerId { get; }
 
-        public string PlayerName { get; internal set; }
+        public string PlayerName { get; internal set; } = string.Empty;
 
         public ColorType Color { get; internal set; }
 
@@ -37,7 +37,7 @@ namespace Impostor.Server.Net.Inner.Objects
 
         public DeathReason LastDeathReason { get; internal set; }
 
-        public List<InnerGameData.TaskInfo> Tasks { get; internal set; }
+        public List<InnerGameData.TaskInfo> Tasks { get; internal set; } = new List<InnerGameData.TaskInfo>(0);
 
         public DateTimeOffset LastMurder { get; set; }
 
index 64b1f5f016543c95487eee1217eb081c0700bb51..df374bff60683c2b190a178582ad1e59d8b7fc86 100644 (file)
@@ -18,7 +18,7 @@ namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
                 MapTypes.Skeld => 13,
                 MapTypes.MiraHQ => 2,
                 MapTypes.Polus => 12,
-                _ => throw new ArgumentOutOfRangeException()
+                _ => throw new ArgumentOutOfRangeException(),
             };
 
             _doors = new Dictionary<int, bool>(doorCount);
@@ -57,4 +57,4 @@ namespace Impostor.Server.Net.Inner.Objects.Systems.ShipStatus
             }
         }
     }
-}
\ No newline at end of file
+}
index 32359f8fb4c1c249326758c404c7927347c328eb..6ee4515f464f366fa9c95486d26fb0163aa6f281 100644 (file)
@@ -18,12 +18,12 @@ namespace Impostor.Server.Net.Manager
 {
     internal partial class ClientManager
     {
-        private static HashSet<int> SupportedVersions { get; } = new HashSet<int>
+        private static readonly HashSet<int> SupportedVersions = new HashSet<int>
         {
             GameVersion.GetVersion(2021, 3, 5), // 2021.3.5
         };
 
-        private static string ServerBrand { get; } = $"Impostor {DotnetUtils.GetVersion()}";
+        private static readonly string ServerBrand = $"Impostor {DotnetUtils.GetVersion()}";
 
         private readonly ILogger<ClientManager> _logger;
         private readonly ConcurrentDictionary<int, ClientBase> _clients;
index 8d883a41258d794d4a32e8890c839ed2fbb8f4b3..eef5d53d90c0a3102ed222cfe4a6bfa6e41e31eb 100644 (file)
@@ -42,46 +42,9 @@ namespace Impostor.Server.Net.Manager
 
         IEnumerable<IGame> IGameManager.Games => _games.Select(kv => kv.Value);
 
-        IGame IGameManager.Find(GameCode code) => Find(code);
+        IGame? IGameManager.Find(GameCode code) => Find(code);
 
-        public async ValueTask<IGame> CreateAsync(GameOptionsData options)
-        {
-            // TODO: Prevent duplicates when using server redirector using INodeProvider.
-            var (success, game) = await TryCreateAsync(options);
-
-            for (int i = 0; i < 10 && !success; i++)
-            {
-                (success, game) = await TryCreateAsync(options);
-            }
-
-            if (!success)
-            {
-                throw new ImpostorException("Could not create new game"); // TODO: Fix generic exception.
-            }
-
-            return game;
-        }
-
-        private async ValueTask<(bool success, Game game)> TryCreateAsync(GameOptionsData options)
-        {
-            var gameCode = _gameCodeFactory.Create();
-            var gameCodeStr = gameCode.Code;
-            var game = ActivatorUtilities.CreateInstance<Game>(_serviceProvider, _publicIp, gameCode, options);
-
-            if (await _nodeLocator.ExistsAsync(gameCodeStr) || !_games.TryAdd(gameCode, game))
-            {
-                return (false, null);
-            }
-
-            await _nodeLocator.SaveAsync(gameCodeStr, _publicIp);
-            _logger.LogDebug("Created game with code {0}.", game.Code);
-
-            await _eventManager.CallAsync(new GameCreatedEvent(game));
-
-            return (true, game);
-        }
-
-        public Game Find(GameCode code)
+        public Game? Find(GameCode code)
         {
             _games.TryGetValue(code, out var game);
             return game;
@@ -146,5 +109,42 @@ namespace Impostor.Server.Net.Manager
 
             await _eventManager.CallAsync(new GameDestroyedEvent(game));
         }
+
+        public async ValueTask<IGame> CreateAsync(GameOptionsData options)
+        {
+            // TODO: Prevent duplicates when using server redirector using INodeProvider.
+            var (success, game) = await TryCreateAsync(options);
+
+            for (int i = 0; i < 10 && !success; i++)
+            {
+                (success, game) = await TryCreateAsync(options);
+            }
+
+            if (!success || game == null)
+            {
+                throw new ImpostorException("Could not create new game"); // TODO: Fix generic exception.
+            }
+
+            return game;
+        }
+
+        private async ValueTask<(bool Success, Game? Game)> TryCreateAsync(GameOptionsData options)
+        {
+            var gameCode = _gameCodeFactory.Create();
+            var gameCodeStr = gameCode.Code;
+            var game = ActivatorUtilities.CreateInstance<Game>(_serviceProvider, _publicIp, gameCode, options);
+
+            if (await _nodeLocator.ExistsAsync(gameCodeStr) || !_games.TryAdd(gameCode, game))
+            {
+                return (false, null);
+            }
+
+            await _nodeLocator.SaveAsync(gameCodeStr, _publicIp);
+            _logger.LogDebug("Created game with code {0}.", game.Code);
+
+            await _eventManager.CallAsync(new GameCreatedEvent(game));
+
+            return (true, game);
+        }
     }
 }
index e700703cadd28bd6efbbbe08375c5c6eaea7d322..a5518dc37f6245372ce4e03151cd002cbe06750a 100644 (file)
@@ -18,7 +18,7 @@ namespace Impostor.Server.Net
         private readonly ObjectPool<MessageReader> _readerPool;
         private readonly ILogger<Matchmaker> _logger;
         private readonly ILogger<HazelConnection> _connectionLogger;
-        private UdpConnectionListener _connection;
+        private UdpConnectionListener? _connection;
 
         public Matchmaker(
             ILogger<Matchmaker> logger,
@@ -38,18 +38,23 @@ namespace Impostor.Server.Net
             {
                 AddressFamily.InterNetwork => IPMode.IPv4,
                 AddressFamily.InterNetworkV6 => IPMode.IPv6,
-                _ => throw new InvalidOperationException()
+                _ => throw new InvalidOperationException(),
             };
 
-            _connection = new UdpConnectionListener(ipEndPoint, _readerPool, mode);
-            _connection.NewConnection = OnNewConnection;
+            _connection = new UdpConnectionListener(ipEndPoint, _readerPool, mode)
+            {
+                NewConnection = OnNewConnection,
+            };
 
             await _connection.StartAsync();
         }
 
         public async ValueTask StopAsync()
         {
-            await _connection.DisposeAsync();
+            if (_connection != null)
+            {
+                await _connection.DisposeAsync();
+            }
         }
 
         private async ValueTask OnNewConnection(NewConnectionEventArgs e)
index 12563b9a2949a2c1bd9daeb1f2f9217d91200543..1c3391a9dff0a6a607fc8647a0f5e015d2fee06d 100644 (file)
@@ -5,10 +5,10 @@ namespace Impostor.Server.Net.Redirector
 {
     public interface INodeLocator
     {
-        ValueTask<IPEndPoint> FindAsync(string gameCode);
+        ValueTask<IPEndPoint?> FindAsync(string gameCode);
 
         ValueTask SaveAsync(string gameCode, IPEndPoint endPoint);
 
         ValueTask RemoveAsync(string gameCode);
     }
-}
\ No newline at end of file
+}
index fd4cd56f7b309ea71251e577f5c16d51c907ee2b..baef6db4447882d92aeb580aa95c13587b7d905f 100644 (file)
@@ -5,10 +5,10 @@ namespace Impostor.Server.Net.Redirector
 {
     public class NodeLocatorNoOp : INodeLocator
     {
-        public ValueTask<IPEndPoint> FindAsync(string gameCode) => ValueTask.FromResult(default(IPEndPoint));
+        public ValueTask<IPEndPoint?> FindAsync(string gameCode) => ValueTask.FromResult(default(IPEndPoint));
 
         public ValueTask SaveAsync(string gameCode, IPEndPoint endPoint) => ValueTask.CompletedTask;
 
         public ValueTask RemoveAsync(string gameCode) => ValueTask.CompletedTask;
     }
-}
\ No newline at end of file
+}
index 0b6fdff81ee8222eb205775aa2270c4a3eeef9f2..f4595e353fa4de66fda763013db44d20f1b84568 100644 (file)
@@ -16,7 +16,7 @@ namespace Impostor.Server.Net.Redirector
             _cache = cache;
         }
 
-        public async ValueTask<IPEndPoint> FindAsync(string gameCode)
+        public async ValueTask<IPEndPoint?> FindAsync(string gameCode)
         {
             var entry = await _cache.GetStringAsync(gameCode);
             if (entry == null)
@@ -40,4 +40,4 @@ namespace Impostor.Server.Net.Redirector
             await _cache.RemoveAsync(gameCode);
         }
     }
-}
\ No newline at end of file
+}
index 2539a8f2d5ad865a24d1aa289c070ff81d58eec1..c75392adf5e466aacb7ce883ee8151f6a5e419ff 100644 (file)
@@ -14,9 +14,9 @@ namespace Impostor.Server.Net.Redirector
     {
         private readonly ILogger<NodeLocatorUdp> _logger;
         private readonly bool _isMaster;
-        private readonly IPEndPoint _server;
-        private readonly UdpClient _client;
-        private readonly ConcurrentDictionary<string, AvailableNode> _availableNodes;
+        private readonly IPEndPoint? _server;
+        private readonly UdpClient? _client;
+        private readonly ConcurrentDictionary<string, AvailableNode>? _availableNodes;
 
         public NodeLocatorUdp(ILogger<NodeLocatorUdp> logger, IOptions<ServerRedirectorConfig> config)
         {
@@ -31,7 +31,7 @@ namespace Impostor.Server.Net.Redirector
             {
                 _isMaster = false;
 
-                if (!IPEndPoint.TryParse(config.Value.Locator.UdpMasterEndpoint, out var endpoint))
+                if (!IPEndPoint.TryParse(config.Value.Locator!.UdpMasterEndpoint, out var endpoint))
                 {
                     throw new ArgumentException("UdpMasterEndpoint should be in the ip:port format.");
                 }
@@ -54,13 +54,9 @@ namespace Impostor.Server.Net.Redirector
         {
             _logger.LogDebug("Received update {0} -> {1}", gameCode, ip);
 
-            _availableNodes.AddOrUpdate(
+            _availableNodes!.AddOrUpdate(
                 gameCode,
-                s => new AvailableNode
-                {
-                    Endpoint = ip,
-                    LastUpdated = DateTimeOffset.UtcNow,
-                },
+                s => new AvailableNode(ip, DateTimeOffset.UtcNow),
                 (s, node) =>
                 {
                     node.Endpoint = ip;
@@ -78,14 +74,14 @@ namespace Impostor.Server.Net.Redirector
             }
         }
 
-        public ValueTask<IPEndPoint> FindAsync(string gameCode)
+        public ValueTask<IPEndPoint?> FindAsync(string gameCode)
         {
             if (!_isMaster)
             {
                 return ValueTask.FromResult(default(IPEndPoint));
             }
 
-            if (_availableNodes.TryGetValue(gameCode, out var node))
+            if (_availableNodes!.TryGetValue(gameCode, out var node))
             {
                 if (node.Expired)
                 {
@@ -93,7 +89,7 @@ namespace Impostor.Server.Net.Redirector
                     return ValueTask.FromResult(default(IPEndPoint));
                 }
 
-                return ValueTask.FromResult(node.Endpoint);
+                return ValueTask.FromResult(node.Endpoint)!;
             }
 
             return ValueTask.FromResult(default(IPEndPoint));
@@ -106,14 +102,14 @@ namespace Impostor.Server.Net.Redirector
                 return ValueTask.CompletedTask;
             }
 
-            _availableNodes.TryRemove(gameCode, out _);
+            _availableNodes!.TryRemove(gameCode, out _);
             return ValueTask.CompletedTask;
         }
 
         public ValueTask SaveAsync(string gameCode, IPEndPoint endPoint)
         {
             var data = Encoding.UTF8.GetBytes($"{gameCode},{endPoint}");
-            _client.Send(data, data.Length, _server);
+            _client!.Send(data, data.Length, _server);
             return ValueTask.CompletedTask;
         }
 
@@ -124,6 +120,12 @@ namespace Impostor.Server.Net.Redirector
 
         private class AvailableNode
         {
+            public AvailableNode(IPEndPoint endpoint, DateTimeOffset lastUpdated)
+            {
+                Endpoint = endpoint;
+                LastUpdated = lastUpdated;
+            }
+
             public IPEndPoint Endpoint { get; set; }
 
             public DateTimeOffset LastUpdated { get; set; }
index 3706bb49983d47d598f1c41e43601623d17ed617..781e91f316b8fe4eef2103468681028523104dcb 100644 (file)
@@ -25,7 +25,7 @@ namespace Impostor.Server.Net.Redirector
             _nodeLocator = (NodeLocatorUdp)nodeLocator;
             _logger = logger;
 
-            if (!IPEndPoint.TryParse(options.Value.Locator.UdpMasterEndpoint, out var endpoint))
+            if (!IPEndPoint.TryParse(options.Value.Locator!.UdpMasterEndpoint, out var endpoint))
             {
                 throw new ArgumentException("UdpMasterEndpoint should be in the ip:port format.");
             }
index ceb73b49eca5021d388782a5eb67d28c6a3a15a6..b615c064a3306e4af54bd8f4f713f364cbab41de 100644 (file)
@@ -17,7 +17,7 @@ namespace Impostor.Server.Net.State
         public ClientPlayer(ILogger<ClientPlayer> logger, ClientBase client, Game game)
         {
             _logger = logger;
-            _spawnTimeout = new Timer(RunSpawnTimeout, null, -1, -1);
+            _spawnTimeout = new Timer(RunSpawnTimeout!, null, -1, -1);
 
             Game = game;
             Client = client;
@@ -35,7 +35,7 @@ namespace Impostor.Server.Net.State
 
         public bool IsHost => Game?.Host == this;
 
-        public string Scene { get; internal set; }
+        public string? Scene { get; internal set; }
 
         public RuntimePlatform? Platform { get; internal set; }
 
index a2996915f2f8bc44d4ae0a6c74c79e6a174e5d02..44257e7636e7872a18b3054c92f15e55f8c9d1c8 100644 (file)
@@ -25,7 +25,7 @@ namespace Impostor.Server.Net.State
 
         public async ValueTask SyncSettingsAsync()
         {
-            if (Host.Character == null)
+            if (Host?.Character == null)
             {
                 throw new ImpostorException("Attempted to set infected when the host was not spawned.");
             }
index a2eaa09d33fc71474bd75b991868af0fa1560a93..b928a3c21ff0938340c102f5759018291e96672b 100644 (file)
@@ -47,124 +47,24 @@ namespace Impostor.Server.Net.State
         };
 
         private readonly List<InnerNetObject> _allObjects = new List<InnerNetObject>();
-        private readonly Dictionary<uint, InnerNetObject> _allObjectsFast = new Dictionary<uint, InnerNetObject>();
 
-        private int _gamedataInitialized;
+        private readonly Dictionary<uint, InnerNetObject> _allObjectsFast = new Dictionary<uint, InnerNetObject>();
 
-        private async ValueTask OnSpawnAsync(InnerNetObject netObj)
+        public T? FindObjectByNetId<T>(uint netId)
+            where T : IInnerNetObject
         {
-            switch (netObj)
+            if (_allObjectsFast.TryGetValue(netId, out var obj))
             {
-                case InnerLobbyBehaviour lobby:
-                {
-                    GameNet.LobbyBehaviour = lobby;
-                    break;
-                }
-
-                case InnerGameData data:
-                {
-                    GameNet.GameData = data;
-                    break;
-                }
-
-                case InnerVoteBanSystem voteBan:
-                {
-                    GameNet.VoteBan = voteBan;
-                    break;
-                }
-
-                case InnerShipStatus shipStatus:
-                {
-                    GameNet.ShipStatus = shipStatus;
-                    break;
-                }
-
-                case InnerPlayerControl control:
-                {
-                    // Hook up InnerPlayerControl <-> IClientPlayer.
-                    if (!TryGetPlayer(control.OwnerId, out var player))
-                    {
-                        throw new ImpostorException("Failed to find player that spawned the InnerPlayerControl");
-                    }
-
-                    player.Character = control;
-                    player.DisableSpawnTimeout();
-
-                    // Hook up InnerPlayerControl <-> InnerPlayerControl.PlayerInfo.
-                    control.PlayerInfo = GameNet.GameData.GetPlayerById(control.PlayerId)!;
-
-                    if (control.PlayerInfo == null)
-                    {
-                        GameNet.GameData.AddPlayer(control);
-                    }
-
-                    if (control.PlayerInfo != null)
-                    {
-                        control.PlayerInfo!.Controller = control;
-                    }
-
-                    await _eventManager.CallAsync(new PlayerSpawnedEvent(this, player, control));
-
-                    break;
-                }
-
-                case InnerMeetingHud meetingHud:
-                {
-                    await _eventManager.CallAsync(new MeetingStartedEvent(this, meetingHud));
-                    break;
-                }
+                return (T)(IInnerNetObject)obj;
             }
-        }
-
-        private async ValueTask OnDestroyAsync(InnerNetObject netObj)
-        {
-            switch (netObj)
-            {
-                case InnerLobbyBehaviour:
-                {
-                    GameNet.LobbyBehaviour = null;
-                    break;
-                }
-
-                case InnerGameData:
-                {
-                    GameNet.GameData = null;
-                    break;
-                }
-
-                case InnerVoteBanSystem:
-                {
-                    GameNet.VoteBan = null;
-                    break;
-                }
-
-                case InnerShipStatus:
-                {
-                    GameNet.ShipStatus = null;
-                    break;
-                }
 
-                case InnerPlayerControl control:
-                {
-                    // Remove InnerPlayerControl <-> IClientPlayer.
-                    if (TryGetPlayer(control.OwnerId, out var player))
-                    {
-                        player.Character = null;
-                    }
-
-                    await _eventManager.CallAsync(new PlayerDestroyedEvent(this, player, control));
-
-                    break;
-                }
-
-
-            }
+            return default;
         }
 
         public async ValueTask<bool> HandleGameDataAsync(IMessageReader parent, ClientPlayer sender, bool toPlayer)
         {
             // Find target player.
-            ClientPlayer target = null;
+            ClientPlayer? target = null;
 
             if (toPlayer)
             {
@@ -232,7 +132,7 @@ namespace Impostor.Server.Net.State
                         var objectId = reader.ReadPackedUInt32();
                         if (objectId < SpawnableObjects.Length)
                         {
-                            var innerNetObject = (InnerNetObject) ActivatorUtilities.CreateInstance(_serviceProvider, SpawnableObjects[objectId], this);
+                            var innerNetObject = (InnerNetObject)ActivatorUtilities.CreateInstance(_serviceProvider, SpawnableObjects[objectId], this);
                             var ownerClientId = reader.ReadPackedInt32();
 
                             // Prevent fake client from being broadcasted.
@@ -242,7 +142,7 @@ namespace Impostor.Server.Net.State
                                 return false;
                             }
 
-                            innerNetObject.SpawnFlags = (SpawnFlags) reader.ReadByte();
+                            innerNetObject.SpawnFlags = (SpawnFlags)reader.ReadByte();
 
                             var components = innerNetObject.GetComponentsInChildren<InnerNetObject>();
                             var componentsCount = reader.ReadPackedInt32();
@@ -393,6 +293,113 @@ namespace Impostor.Server.Net.State
             return true;
         }
 
+        private async ValueTask OnSpawnAsync(InnerNetObject netObj)
+        {
+            switch (netObj)
+            {
+                case InnerLobbyBehaviour lobby:
+                {
+                    GameNet.LobbyBehaviour = lobby;
+                    break;
+                }
+
+                case InnerGameData data:
+                {
+                    GameNet.GameData = data;
+                    break;
+                }
+
+                case InnerVoteBanSystem voteBan:
+                {
+                    GameNet.VoteBan = voteBan;
+                    break;
+                }
+
+                case InnerShipStatus shipStatus:
+                {
+                    GameNet.ShipStatus = shipStatus;
+                    break;
+                }
+
+                case InnerPlayerControl control:
+                {
+                    // Hook up InnerPlayerControl <-> IClientPlayer.
+                    if (!TryGetPlayer(control.OwnerId, out var player))
+                    {
+                        throw new ImpostorException("Failed to find player that spawned the InnerPlayerControl");
+                    }
+
+                    player.Character = control;
+                    player.DisableSpawnTimeout();
+
+                    // Hook up InnerPlayerControl <-> InnerPlayerControl.PlayerInfo.
+                    var playerInfo = GameNet.GameData!.GetPlayerById(control.PlayerId);
+
+                    if (playerInfo != null)
+                    {
+                        playerInfo.Controller = control;
+                        control.PlayerInfo = playerInfo;
+                    }
+                    else
+                    {
+                        GameNet.GameData.AddPlayer(control);
+                    }
+
+                    await _eventManager.CallAsync(new PlayerSpawnedEvent(this, player, control));
+
+                    break;
+                }
+
+                case InnerMeetingHud meetingHud:
+                {
+                    await _eventManager.CallAsync(new MeetingStartedEvent(this, meetingHud));
+                    break;
+                }
+            }
+        }
+
+        private async ValueTask OnDestroyAsync(InnerNetObject netObj)
+        {
+            switch (netObj)
+            {
+                case InnerLobbyBehaviour:
+                {
+                    GameNet.LobbyBehaviour = null;
+                    break;
+                }
+
+                case InnerGameData:
+                {
+                    GameNet.GameData = null;
+                    break;
+                }
+
+                case InnerVoteBanSystem:
+                {
+                    GameNet.VoteBan = null;
+                    break;
+                }
+
+                case InnerShipStatus:
+                {
+                    GameNet.ShipStatus = null;
+                    break;
+                }
+
+                case InnerPlayerControl control:
+                {
+                    // Remove InnerPlayerControl <-> IClientPlayer.
+                    if (TryGetPlayer(control.OwnerId, out var player))
+                    {
+                        player.Character = null;
+                        await _eventManager.CallAsync(new PlayerDestroyedEvent(this, player, control));
+                    }
+
+                    break;
+                }
+            }
+        }
+
         private bool AddNetObject(InnerNetObject obj)
         {
             if (_allObjectsFast.ContainsKey(obj.NetId))
@@ -417,16 +424,5 @@ namespace Impostor.Server.Net.State
 
             obj.NetId = uint.MaxValue;
         }
-
-        public T? FindObjectByNetId<T>(uint netId)
-            where T : IInnerNetObject
-        {
-            if (_allObjectsFast.TryGetValue(netId, out var obj))
-            {
-                return (T)(IInnerNetObject)obj;
-            }
-
-            return default;
-        }
     }
 }
index 547224db2bb166d0b6b0342465b67f0751d12afd..8f9df6263c21df81b8af2cd749ccce3e12796d35 100644 (file)
@@ -29,6 +29,74 @@ namespace Impostor.Server.Net.State
             await _eventManager.CallAsync(new GameStartingEvent(this));
         }
 
+        public async ValueTask HandleEndGame(IMessageReader message, GameOverReason gameOverReason)
+        {
+            GameState = GameStates.Ended;
+
+            // Broadcast end of the game.
+            using (var packet = MessageWriter.Get(MessageType.Reliable))
+            {
+                message.CopyTo(packet);
+                await SendToAllAsync(packet);
+            }
+
+            // Put all players in the correct limbo state.
+            foreach (var player in _players)
+            {
+                player.Value.Limbo = LimboStates.PreSpawn;
+            }
+
+            await _eventManager.CallAsync(new GameEndedEvent(this, gameOverReason));
+        }
+
+        public async ValueTask HandleAlterGame(IMessageReader message, IClientPlayer sender, bool isPublic)
+        {
+            IsPublic = isPublic;
+
+            using var packet = MessageWriter.Get(MessageType.Reliable);
+            message.CopyTo(packet);
+            await SendToAllExceptAsync(packet, sender.Client.Id);
+
+            await _eventManager.CallAsync(new GameAlterEvent(this, isPublic));
+        }
+
+        public async ValueTask HandleRemovePlayer(int playerId, DisconnectReason reason)
+        {
+            await PlayerRemove(playerId);
+
+            // It's possible that the last player was removed, so check if the game is still around.
+            if (GameState == GameStates.Destroyed)
+            {
+                return;
+            }
+
+            using var packet = MessageWriter.Get(MessageType.Reliable);
+            WriteRemovePlayerMessage(packet, false, playerId, reason);
+            await SendToAllExceptAsync(packet, playerId);
+        }
+
+        public async ValueTask HandleKickPlayer(int playerId, bool isBan)
+        {
+            _logger.LogInformation("{0} - Player {1} has left.", Code, playerId);
+
+            using var message = MessageWriter.Get(MessageType.Reliable);
+
+            // Send message to everyone that this player was kicked.
+            WriteKickPlayerMessage(message, false, playerId, isBan);
+
+            await SendToAllAsync(message);
+            await PlayerRemove(playerId, isBan);
+
+            // Remove the player from everyone's game.
+            WriteRemovePlayerMessage(
+                message,
+                true,
+                playerId,
+                isBan ? DisconnectReason.Banned : DisconnectReason.Kicked);
+
+            await SendToAllExceptAsync(message, playerId);
+        }
+
         public async ValueTask<GameJoinResult> AddClientAsync(ClientBase client)
         {
             var hasLock = false;
@@ -53,10 +121,34 @@ namespace Impostor.Server.Net.State
             return GameJoinResult.FromError(GameJoinError.InvalidClient);
         }
 
+        private async ValueTask HandleJoinGameNew(ClientPlayer sender, bool isNew)
+        {
+            _logger.LogInformation("{0} - Player {1} ({2}) is joining.", Code, sender.Client.Name, sender.Client.Id);
+
+            // Add player to the game.
+            if (isNew)
+            {
+                await PlayerAdd(sender);
+            }
+
+            sender.InitializeSpawnTimeout();
+
+            using (var message = MessageWriter.Get(MessageType.Reliable))
+            {
+                WriteJoinedGameMessage(message, false, sender);
+                WriteAlterGameMessage(message, false, IsPublic);
+
+                sender.Limbo = LimboStates.NotLimbo;
+
+                await SendToAsync(message, sender.Client.Id);
+                await BroadcastJoinMessage(message, true, sender);
+            }
+        }
+
         private async ValueTask<GameJoinResult> AddClientSafeAsync(ClientBase client)
         {
             // Check if the IP of the player is banned.
-            if (client.Connection != null && _bannedIps.Contains(client.Connection.EndPoint.Address))
+            if (_bannedIps.Contains(client.Connection.EndPoint.Address))
             {
                 return GameJoinResult.FromError(GameJoinError.Banned);
             }
@@ -132,98 +224,6 @@ namespace Impostor.Server.Net.State
             return GameJoinResult.CreateSuccess(player);
         }
 
-        public async ValueTask HandleEndGame(IMessageReader message, GameOverReason gameOverReason)
-        {
-            GameState = GameStates.Ended;
-
-            // Broadcast end of the game.
-            using (var packet = MessageWriter.Get(MessageType.Reliable))
-            {
-                message.CopyTo(packet);
-                await SendToAllAsync(packet);
-            }
-
-            // Put all players in the correct limbo state.
-            foreach (var player in _players)
-            {
-                player.Value.Limbo = LimboStates.PreSpawn;
-            }
-
-            await _eventManager.CallAsync(new GameEndedEvent(this, gameOverReason));
-        }
-
-        public async ValueTask HandleAlterGame(IMessageReader message, IClientPlayer sender, bool isPublic)
-        {
-            IsPublic = isPublic;
-
-            using var packet = MessageWriter.Get(MessageType.Reliable);
-            message.CopyTo(packet);
-            await SendToAllExceptAsync(packet, sender.Client.Id);
-
-            await _eventManager.CallAsync(new GameAlterEvent(this, isPublic));
-        }
-
-        public async ValueTask HandleRemovePlayer(int playerId, DisconnectReason reason)
-        {
-            await PlayerRemove(playerId);
-
-            // It's possible that the last player was removed, so check if the game is still around.
-            if (GameState == GameStates.Destroyed)
-            {
-                return;
-            }
-
-            using var packet = MessageWriter.Get(MessageType.Reliable);
-            WriteRemovePlayerMessage(packet, false, playerId, reason);
-            await SendToAllExceptAsync(packet, playerId);
-        }
-
-        public async ValueTask HandleKickPlayer(int playerId, bool isBan)
-        {
-            _logger.LogInformation("{0} - Player {1} has left.", Code, playerId);
-
-            using var message = MessageWriter.Get(MessageType.Reliable);
-
-            // Send message to everyone that this player was kicked.
-            WriteKickPlayerMessage(message, false, playerId, isBan);
-
-            await SendToAllAsync(message);
-            await PlayerRemove(playerId, isBan);
-
-            // Remove the player from everyone's game.
-            WriteRemovePlayerMessage(
-                message,
-                true,
-                playerId,
-                isBan ? DisconnectReason.Banned : DisconnectReason.Kicked);
-
-            await SendToAllExceptAsync(message, playerId);
-        }
-
-        private async ValueTask HandleJoinGameNew(ClientPlayer sender, bool isNew)
-        {
-            _logger.LogInformation("{0} - Player {1} ({2}) is joining.", Code, sender.Client.Name, sender.Client.Id);
-
-            // Add player to the game.
-            if (isNew)
-            {
-                await PlayerAdd(sender);
-            }
-
-            sender.InitializeSpawnTimeout();
-
-            using (var message = MessageWriter.Get(MessageType.Reliable))
-            {
-                WriteJoinedGameMessage(message, false, sender);
-                WriteAlterGameMessage(message, false, IsPublic);
-
-                sender.Limbo = LimboStates.NotLimbo;
-
-                await SendToAsync(message, sender.Client.Id);
-                await BroadcastJoinMessage(message, true, sender);
-            }
-        }
-
         private async ValueTask HandleJoinGameNext(ClientPlayer sender, bool isNew)
         {
             _logger.LogInformation("{0} - Player {1} ({2}) is rejoining.", Code, sender.Client.Name, sender.Client.Id);
index 927548e7299bd08f3c7c580d48ad775ecc0f22bb..9f9d90473a9aa9ff8e9a22379e68ac0cd2e24c26 100644 (file)
@@ -66,7 +66,7 @@ namespace Impostor.Server.Net.State
                 await MigrateHost();
             }
 
-            if (isBan && player.Client.Connection != null)
+            if (isBan)
             {
                 BanIp(player.Client.Connection.EndPoint.Address);
             }
index 6ca2fd6871d5432802f7490b9f209ebf9c32d47b..823c049f45b98101075c1f5d55b1cadd904affb6 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Net;
 using System.Numerics;
@@ -66,8 +67,6 @@ namespace Impostor.Server.Net.State
 
         public GameStates GameState { get; private set; }
 
-        internal GameNet GameNet { get; }
-
         public GameOptionsData Options { get; }
 
         public IDictionary<object, object> Items { get; }
@@ -78,7 +77,9 @@ namespace Impostor.Server.Net.State
 
         public IEnumerable<IClientPlayer> Players => _players.Select(p => p.Value);
 
-        public bool TryGetPlayer(int id, out ClientPlayer player)
+        internal GameNet GameNet { get; }
+
+        public bool TryGetPlayer(int id, [MaybeNullWhen(false)] out ClientPlayer player)
         {
             if (_players.TryGetValue(id, out var result))
             {
@@ -90,11 +91,16 @@ namespace Impostor.Server.Net.State
             return false;
         }
 
-        public IClientPlayer GetClientPlayer(int clientId)
+        public IClientPlayer? GetClientPlayer(int clientId)
         {
             return _players.TryGetValue(clientId, out var clientPlayer) ? clientPlayer : null;
         }
 
+        public ValueTask EndAsync()
+        {
+            return _gameManager.RemoveAsync(Code);
+        }
+
         internal async ValueTask StartedAsync()
         {
             if (GameState == GameStates.Starting)
@@ -111,11 +117,6 @@ namespace Impostor.Server.Net.State
             }
         }
 
-        public ValueTask EndAsync()
-        {
-            return _gameManager.RemoveAsync(Code);
-        }
-
         private ValueTask BroadcastJoinMessage(IMessageWriter message, bool clear, ClientPlayer player)
         {
             Message01JoinGameS2C.SerializeJoin(message, clear, Code, player.Client.Id, HostId);
@@ -127,7 +128,7 @@ namespace Impostor.Server.Net.State
         {
             return Players
                 .Where(filter)
-                .Select(p => p.Client.Connection);
+                .Select(p => p.Client.Connection)!;
         }
     }
 }
index 34ea0fe6410ce64dc7d307daa13637128fb79fba..4fed52763c8b9f7cddf2da2191a2fb7ef62aefac 100644 (file)
@@ -6,12 +6,12 @@ namespace Impostor.Server.Net.State
     /// <inheritdoc />
     internal partial class GameNet : IGameNet
     {
-        IInnerLobbyBehaviour IGameNet.LobbyBehaviour => LobbyBehaviour;
+        IInnerLobbyBehaviour? IGameNet.LobbyBehaviour => LobbyBehaviour;
 
-        IInnerGameData IGameNet.GameData => GameData;
+        IInnerGameData? IGameNet.GameData => GameData;
 
-        IInnerVoteBanSystem IGameNet.VoteBan => VoteBan;
+        IInnerVoteBanSystem? IGameNet.VoteBan => VoteBan;
 
-        IInnerShipStatus IGameNet.ShipStatus => ShipStatus;
+        IInnerShipStatus? IGameNet.ShipStatus => ShipStatus;
     }
-}
\ No newline at end of file
+}
index c5542f9d01ab53ffa137d75ca35f72acbfcffa12..37e0cbd91ca330d4588af867415ad0763bcb060d 100644 (file)
@@ -5,12 +5,12 @@ namespace Impostor.Server.Net.State
 {
     internal partial class GameNet
     {
-        public InnerLobbyBehaviour LobbyBehaviour { get; internal set; }
+        public InnerLobbyBehaviour? LobbyBehaviour { get; internal set; }
 
-        public InnerGameData GameData { get; internal set; }
+        public InnerGameData? GameData { get; internal set; }
 
-        public InnerVoteBanSystem VoteBan { get; internal set; }
+        public InnerVoteBanSystem? VoteBan { get; internal set; }
 
-        public InnerShipStatus ShipStatus { get; internal set; }
+        public InnerShipStatus? ShipStatus { get; internal set; }
     }
-}
\ No newline at end of file
+}
index 5f6aee1137d388b66f5cfc6dfd5f92ca36c635eb..df1bf84ea5e51727137a5068af7a1bd678477db5 100644 (file)
@@ -6,7 +6,7 @@ namespace Impostor.Server.Plugins
 {
     public class AssemblyInformation : IAssemblyInformation
     {
-        private Assembly _assembly;
+        private Assembly? _assembly;
 
         public AssemblyInformation(AssemblyName assemblyName, string path, bool isPlugin)
         {
@@ -35,4 +35,4 @@ namespace Impostor.Server.Plugins
             return _assembly;
         }
     }
-}
\ No newline at end of file
+}
index e6a5b6c81f06d6b9f8d92281ff9046e3186ecfa3..f9f61a1febdb74b3a7fb2610b78505d67c3f37d2 100644 (file)
@@ -8,9 +8,9 @@ namespace Impostor.Server.Plugins
     {
         private readonly ImpostorPluginAttribute _attribute;
 
-        public PluginInformation(IPluginStartup startup, Type pluginType)
+        public PluginInformation(IPluginStartup? startup, Type pluginType)
         {
-            _attribute = pluginType.GetCustomAttribute<ImpostorPluginAttribute>();
+            _attribute = pluginType.GetCustomAttribute<ImpostorPluginAttribute>()!;
 
             Startup = startup;
             PluginType = pluginType;
@@ -24,15 +24,15 @@ namespace Impostor.Server.Plugins
 
         public string Version => _attribute.Version;
 
-        public IPluginStartup Startup { get; }
+        public IPluginStartup? Startup { get; }
 
         public Type PluginType { get; }
 
-        public IPlugin Instance { get; set; }
+        public IPlugin? Instance { get; set; }
 
         public override string ToString()
         {
             return $"{Package} {Name} ({Version}) by {Author}";
         }
     }
-}
\ No newline at end of file
+}
index 4b5d07a5070cd1628078f6c607f613e53ff19c26..90b9caf8309b1eb94176f70c5cd36d963caaf833 100644 (file)
@@ -47,7 +47,7 @@ namespace Impostor.Server.Plugins
 
                 // Some plugins may be referencing another Impostor.Api version and try to load it.
                 // We want to only use the one shipped with the server.
-                if (name.Name.Equals("Impostor.Api"))
+                if (name.Name == "Impostor.Api")
                 {
                     return typeof(IPlugin).Assembly;
                 }
@@ -104,18 +104,18 @@ namespace Impostor.Server.Plugins
                     plugin.First()));
             }
 
-            foreach (var plugin in plugins.Where(plugin => plugin.Startup != null))
+            foreach (var plugin in plugins)
             {
-                plugin.Startup.ConfigureHost(builder);
+                plugin.Startup?.ConfigureHost(builder);
             }
 
             builder.ConfigureServices(services =>
             {
                 services.AddHostedService(provider => ActivatorUtilities.CreateInstance<PluginLoaderService>(provider, plugins));
 
-                foreach (var plugin in plugins.Where(plugin => plugin.Startup != null))
+                foreach (var plugin in plugins)
                 {
-                    plugin.Startup.ConfigureServices(services);
+                    plugin.Startup?.ConfigureServices(services);
                 }
             });
 
index 64424a14e2b9f51d21f88c099d6dfc3b35d85083..740cc46862995bbcb7768dac85377d92749e79e5 100644 (file)
@@ -10,16 +10,16 @@ namespace Impostor.Server.Plugins
         {
         }
 
-        protected PluginLoaderException(SerializationInfo info, StreamingContext context) : base(info, context)
+        public PluginLoaderException(string? message) : base(message)
         {
         }
 
-        public PluginLoaderException(string? message) : base(message)
+        public PluginLoaderException(string? message, Exception? innerException) : base(message, innerException)
         {
         }
 
-        public PluginLoaderException(string? message, Exception? innerException) : base(message, innerException)
+        protected PluginLoaderException(SerializationInfo info, StreamingContext context) : base(info, context)
         {
         }
     }
-}
\ No newline at end of file
+}
index 0afbc223918f67957e5e15566ca7e7bf1b29e168..84238f786a5a90cbcbd61c84e0e0bd9d98d12437 100644 (file)
@@ -32,7 +32,7 @@ namespace Impostor.Server.Plugins
                 _logger.LogInformation("Enabling plugin {0}.", plugin);
 
                 // Create instance and inject services.
-                plugin.Instance = (IPlugin) ActivatorUtilities.CreateInstance(_serviceProvider, plugin.PluginType);
+                plugin.Instance = (IPlugin)ActivatorUtilities.CreateInstance(_serviceProvider, plugin.PluginType);
 
                 // Enable plugin.
                 await plugin.Instance.EnableAsync();
@@ -41,20 +41,25 @@ namespace Impostor.Server.Plugins
             _logger.LogInformation(
                 _plugins.Count == 1
                     ? "Loaded {0} plugin."
-                    : "Loaded {0} plugins.", _plugins.Count);
+                    : "Loaded {0} plugins.",
+                _plugins.Count
+            );
         }
 
         public async Task StopAsync(CancellationToken cancellationToken)
         {
             // Disable all plugins with a valid instance set.
             // In the case of a failed startup, some can be null.
-            foreach (var plugin in _plugins.Where(plugin => plugin.Instance != null))
+            foreach (var plugin in _plugins)
             {
-                _logger.LogInformation("Disabling plugin {0}.", plugin);
+                if (plugin.Instance != null)
+                {
+                    _logger.LogInformation("Disabling plugin {0}.", plugin);
 
-                // Disable plugin.
-                await plugin.Instance.DisableAsync();
+                    // Disable plugin.
+                    await plugin.Instance.DisableAsync();
+                }
             }
         }
     }
-}
\ No newline at end of file
+}
index 109c6be01d200b7e9012733863896ed018093b17..ab582caaaf962ee22217b5a29c9d0e9f768b4704 100644 (file)
@@ -128,7 +128,7 @@ namespace Impostor.Server
 
                     if (redirector.Enabled)
                     {
-                        if (!string.IsNullOrEmpty(redirector.Locator.Redis))
+                        if (!string.IsNullOrEmpty(redirector.Locator?.Redis))
                         {
                             // When joining a game, it retrieves the game server ip from redis.
                             // When a game has been created on this node, it stores the game code with its ip in redis.
@@ -141,7 +141,7 @@ namespace Impostor.Server
                                 options.InstanceName = "ImpostorRedis";
                             });
                         }
-                        else if (!string.IsNullOrEmpty(redirector.Locator.UdpMasterEndpoint))
+                        else if (!string.IsNullOrEmpty(redirector.Locator?.UdpMasterEndpoint))
                         {
                             services.AddSingleton<INodeLocator, NodeLocatorUdp>();
 
diff --git a/src/Impostor.Server/ProjectRules.ruleset b/src/Impostor.Server/ProjectRules.ruleset
deleted file mode 100644 (file)
index fd6daac..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<RuleSet Name="Rules for Hello World project" Description="These rules focus on critical issues for the Hello World app." ToolsVersion="10.0">
-    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.OrderingRules">
-        <Rule Id="SA1200" Action="None" />
-    </Rules>
-    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.DocumentationRules">
-        <Rule Id="SA1600" Action="None" />
-        <Rule Id="SA1601" Action="None" />
-        <Rule Id="SA1615" Action="None" />
-        <Rule Id="SA1633" Action="None" />
-    </Rules>
-    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.ReadabilityRules">
-        <Rule Id="SA1101" Action="None" />
-        <Rule Id="SA1111" Action="None"/>
-    </Rules>
-    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.NamingRules">
-        <Rule Id="SA1309" Action="None" />
-    </Rules>
-    <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.SpacingRules">
-        <Rule Id="SA1003" Action="None" />
-        <Rule Id="SA1009" Action="None" />
-    </Rules>
-</RuleSet>
\ No newline at end of file
index c8efdb35a76007ef64553d0614dfa9fe67686a8b..c6531b45659837233dc87dee947162f11351641f 100644 (file)
@@ -31,7 +31,7 @@ namespace Impostor.Server.Recorder
         {
             var name = $"session_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}.dat";
 
-            _path = Path.Combine(options.Value.GameRecorderPath, name);
+            _path = Path.Combine(options.Value.GameRecorderPath!, name);
             _logger = logger;
             _pool = pool;
 
@@ -42,34 +42,6 @@ namespace Impostor.Server.Recorder
             });
         }
 
-        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
-        {
-            _startTime = DateTimeOffset.UtcNow;
-            _logger.LogInformation("PacketRecorder is enabled, writing packets to {0}.", _path);
-
-            var writer = File.Open(_path, FileMode.CreateNew, FileAccess.Write, FileShare.Read);
-
-            await WriteFileHeaderAsync();
-
-            // Handle messages.
-            try
-            {
-                while (!stoppingToken.IsCancellationRequested)
-                {
-                    var result = await _channel.Reader.ReadAsync(stoppingToken);
-
-                    await writer.WriteAsync(result, stoppingToken);
-                    await writer.FlushAsync(stoppingToken);
-                }
-            }
-            catch (TaskCanceledException)
-            {
-            }
-
-            // Clean up.
-            await writer.DisposeAsync();
-        }
-
         public async Task WriteConnectAsync(ClientRecorder client)
         {
             _logger.LogTrace("Writing Connect.");
@@ -82,7 +54,7 @@ namespace Impostor.Server.Recorder
                 WriteClient(context, client, true);
                 WriteLength(context);
 
-                await WriteAsync(context.Stream);
+                await WriteAsync(context.Stream!);
             }
             finally
             {
@@ -103,7 +75,7 @@ namespace Impostor.Server.Recorder
                 context.Writer.Write(reason);
                 WriteLength(context);
 
-                await WriteAsync(context.Stream);
+                await WriteAsync(context.Stream!);
             }
             finally
             {
@@ -124,7 +96,7 @@ namespace Impostor.Server.Recorder
                 WritePacket(context, reader, messageType);
                 WriteLength(context);
 
-                await WriteAsync(context.Stream);
+                await WriteAsync(context.Stream!);
             }
             finally
             {
@@ -145,7 +117,7 @@ namespace Impostor.Server.Recorder
                 WriteGameCode(context, gameCode);
                 WriteLength(context);
 
-                await WriteAsync(context.Stream);
+                await WriteAsync(context.Stream!);
             }
             finally
             {
@@ -153,6 +125,34 @@ namespace Impostor.Server.Recorder
             }
         }
 
+        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+        {
+            _startTime = DateTimeOffset.UtcNow;
+            _logger.LogInformation("PacketRecorder is enabled, writing packets to {0}.", _path);
+
+            var writer = File.Open(_path, FileMode.CreateNew, FileAccess.Write, FileShare.Read);
+
+            await WriteFileHeaderAsync();
+
+            // Handle messages.
+            try
+            {
+                while (!stoppingToken.IsCancellationRequested)
+                {
+                    var result = await _channel.Reader.ReadAsync(stoppingToken);
+
+                    await writer.WriteAsync(result, stoppingToken);
+                    await writer.FlushAsync(stoppingToken);
+                }
+            }
+            catch (TaskCanceledException)
+            {
+            }
+
+            // Clean up.
+            await writer.DisposeAsync();
+        }
+
         private async Task WriteFileHeaderAsync()
         {
             var context = _pool.Get();
@@ -163,7 +163,7 @@ namespace Impostor.Server.Recorder
                 context.Writer.Write(_startTime.ToUnixTimeMilliseconds());
                 context.Writer.Write(DotnetUtils.GetVersion());
 
-                await WriteAsync(context.Stream);
+                await WriteAsync(context.Stream!);
             }
             finally
             {
@@ -182,7 +182,7 @@ namespace Impostor.Server.Recorder
             context.Writer.Write((byte)type);
         }
 
-        private static void WriteClient(PacketSerializationContext context, ClientBase client, bool full)
+        private void WriteClient(PacketSerializationContext context, ClientBase client, bool full)
         {
             var address = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 12345);
             var addressBytes = address.Address.GetAddressBytes();
@@ -199,7 +199,7 @@ namespace Impostor.Server.Recorder
             }
         }
 
-        private static void WritePacket(PacketSerializationContext context, IMessageReader reader, MessageType messageType)
+        private void WritePacket(PacketSerializationContext context, IMessageReader reader, MessageType messageType)
         {
             context.Writer.Write((byte)messageType);
             context.Writer.Write((byte)reader.Tag);
@@ -207,12 +207,12 @@ namespace Impostor.Server.Recorder
             context.Writer.Write(reader.Buffer, reader.Offset, reader.Length);
         }
 
-        private static void WriteGameCode(PacketSerializationContext context, in GameCode gameCode)
+        private void WriteGameCode(PacketSerializationContext context, in GameCode gameCode)
         {
             context.Writer.Write(gameCode.Code);
         }
 
-        private static void WriteLength(PacketSerializationContext context)
+        private void WriteLength(PacketSerializationContext context)
         {
             var length = context.Stream.Position;
 
index 07755f6b0f68cd31c57730fcd12c66a7173b0b93..2290bcb42f470595aca9257bb5c8a2288e8eb562 100644 (file)
@@ -1,4 +1,5 @@
-using System.IO;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
 using System.Text;
 
 namespace Impostor.Server.Recorder
@@ -8,33 +9,25 @@ namespace Impostor.Server.Recorder
         private const int InitialStreamSize = 0x100;
         private const int MaximumStreamSize = 0x100000;
 
-        private MemoryStream _memory;
-        private BinaryWriter _writer;
+        private MemoryStream? _memory;
+        private BinaryWriter? _writer;
 
+        [AllowNull]
         public MemoryStream Stream
         {
             get
             {
-                if (_memory == null)
-                {
-                    _memory = new MemoryStream(InitialStreamSize);
-                }
-
-                return _memory;
+                return _memory ??= new MemoryStream(InitialStreamSize);
             }
             private set => _memory = value;
         }
 
+        [AllowNull]
         public BinaryWriter Writer
         {
             get
             {
-                if (_writer == null)
-                {
-                    _writer = new BinaryWriter(Stream, Encoding.UTF8, true);
-                }
-
-                return _writer;
+                return _writer ??= new BinaryWriter(Stream, Encoding.UTF8, true);
             }
             private set => _writer = value;
         }
@@ -53,4 +46,4 @@ namespace Impostor.Server.Recorder
             }
         }
     }
-}
\ No newline at end of file
+}
index a8a20bca2a994ab154a725af5d3e0a6f2a99ff21..336cd57e7dce915f73bbe971da2b9c0232835244 100644 (file)
@@ -5,6 +5,6 @@
         Connect = 1,
         Disconnect = 2,
         Message = 3,
-        GameCreated = 4
+        GameCreated = 4,
     }
-}
\ No newline at end of file
+}
index 3f96bf6b58b8d36b7b958dba77df77ce47b86057..a4ccd6bf62ad222c16ef1c60e0960dd6d6089099 100644 (file)
@@ -1,20 +1,23 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-    <PropertyGroup>
-        <TargetFramework>net5.0</TargetFramework>
-        <IsPackable>false</IsPackable>
-    </PropertyGroup>
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+    <IsPackable>false</IsPackable>
+  </PropertyGroup>
 
-    <ItemGroup>
-        <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.0" />
-        <PackageReference Include="xunit" Version="2.4.1" />
-        <PackageReference Include="xunit.runner.reporters" Version="2.4.1" />
-        <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
-        <PackageReference Include="coverlet.collector" Version="1.3.0" />
-    </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
+    <PackageReference Include="xunit" Version="2.4.1" />
+    <PackageReference Include="xunit.runner.reporters" Version="2.4.1" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
+    <PackageReference Include="coverlet.collector" Version="3.0.3">
+      <PrivateAssets>all</PrivateAssets>
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+    </PackageReference>
+  </ItemGroup>
 
-    <ItemGroup>
-      <ProjectReference Include="..\Impostor.Server\Impostor.Server.csproj" />
-    </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Impostor.Server\Impostor.Server.csproj" />
+  </ItemGroup>
 
 </Project>
index 8f523dc3859dbfa398462c8dee17e8ab1e00e64b..571d7b949ad785bf7eaa5b52ce2c4a777f458d50 100644 (file)
@@ -1,17 +1,19 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
-    <PropertyGroup>
-        <OutputType>Exe</OutputType>
-        <TargetFramework>net5.0</TargetFramework>
-    </PropertyGroup>
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net5.0</TargetFramework>
+  </PropertyGroup>
 
-    <ItemGroup>
-      <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.0" />
-      <PackageReference Include="Pcap.Net.x64" Version="1.0.4.1" />
-    </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
+    <PackageReference Include="Pcap.Net.x64" Version="1.0.4.1">
+      <NoWarn>NU1701</NoWarn>
+    </PackageReference>
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\Impostor.Hazel\Impostor.Hazel.csproj" />
+  </ItemGroup>
 
-    <ItemGroup>
-      <ProjectReference Include="..\Impostor.Hazel\Impostor.Hazel.csproj" />
-    </ItemGroup>
-    
 </Project>
index 98fa689f8f38e3b3cec9e035e503edf82d2e4cc5..3b46f3f87bd352e61cfedc1af0a4f222ab3cc899 100644 (file)
@@ -6,11 +6,11 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <ProjectReference Include="..\Impostor.Server\Impostor.Server.csproj"/>
+    <ProjectReference Include="..\Impostor.Server\Impostor.Server.csproj" />
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1"/>
+    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
   </ItemGroup>
 
 </Project>
index 43f0257b6dce3281e847b561bcbeb95cad646702..327296f12c53fec4841e7196034fc31172e67cf8 100644 (file)
@@ -16,7 +16,7 @@ namespace Impostor.Tools.ServerReplay.Mocks
 
         public IPEndPoint EndPoint { get; }
         public bool IsConnected { get; }
-        public IClient? Client { get; set; }
+        public IClient Client { get; set; }
 
         public ValueTask SendAsync(IMessageWriter writer)
         {
@@ -28,4 +28,4 @@ namespace Impostor.Tools.ServerReplay.Mocks
             return ValueTask.CompletedTask;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/ProjectRules.ruleset b/src/ProjectRules.ruleset
new file mode 100644 (file)
index 0000000..5102b80
--- /dev/null
@@ -0,0 +1,23 @@
+<RuleSet Name="Impostor" ToolsVersion="10.0">
+  <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.OrderingRules">
+    <Rule Id="SA1200" Action="None" />
+  </Rules>
+  <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.DocumentationRules">
+    <Rule Id="SA1600" Action="None" />
+    <Rule Id="SA1601" Action="None" />
+    <Rule Id="SA1602" Action="None" />
+    <Rule Id="SA1633" Action="None" />
+  </Rules>
+  <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.ReadabilityRules">
+    <Rule Id="SA1101" Action="None" />
+    <Rule Id="SA1111" Action="None" />
+    <Rule Id="SA1128" Action="None" />
+  </Rules>
+  <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.NamingRules">
+    <Rule Id="SA1309" Action="None" />
+  </Rules>
+  <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.SpacingRules">
+    <Rule Id="SA1003" Action="None" />
+    <Rule Id="SA1009" Action="None" />
+  </Rules>
+</RuleSet>