]> git.deb.at Git - rhonda/impostor.git/commitdiff
Add custom message support (#404)
authorjs6pak <kubastaron@hotmail.com>
Mon, 10 May 2021 11:08:26 +0000 (11:08 +0000)
committerGitHub <noreply@github.com>
Mon, 10 May 2021 11:08:26 +0000 (11:08 +0000)
48 files changed:
src/Impostor.Api/Events/Client/IClientConnectedEvent.cs [new file with mode: 0644]
src/Impostor.Api/Events/Client/IClientConnectionEvent.cs [new file with mode: 0644]
src/Impostor.Api/Events/Client/IClientEvent.cs [new file with mode: 0644]
src/Impostor.Api/Events/Game/IGamePlayerJoiningEvent.cs [new file with mode: 0644]
src/Impostor.Api/Events/MultiDisposable.cs [new file with mode: 0644]
src/Impostor.Api/Games/IGame.cs
src/Impostor.Api/IDateTimeProvider.cs [deleted file]
src/Impostor.Api/Net/Custom/ICustomMessage.cs [new file with mode: 0644]
src/Impostor.Api/Net/Custom/ICustomMessageManager.cs [new file with mode: 0644]
src/Impostor.Api/Net/Custom/ICustomRootMessage.cs [new file with mode: 0644]
src/Impostor.Api/Net/Custom/ICustomRpc.cs [new file with mode: 0644]
src/Impostor.Api/Net/Messages/IMessageWriter.cs
src/Impostor.Api/Utils/IDateTimeProvider.cs [new file with mode: 0644]
src/Impostor.Api/Utils/IServerEnvironment.cs [new file with mode: 0644]
src/Impostor.Server/Events/Client/ClientConnectedEvent.cs [new file with mode: 0644]
src/Impostor.Server/Events/Client/ClientConnectionEvent.cs [new file with mode: 0644]
src/Impostor.Server/Events/EventManager.cs
src/Impostor.Server/Events/Game/GamePlayerJoiningEvent.cs [new file with mode: 0644]
src/Impostor.Server/Events/MultiDisposable.cs [deleted file]
src/Impostor.Server/Net/Client.cs
src/Impostor.Server/Net/Custom/CustomMessageManager.cs [new file with mode: 0644]
src/Impostor.Server/Net/Inner/InnerNetObject.cs
src/Impostor.Server/Net/Inner/Objects/Components/InnerCustomNetworkTransform.cs
src/Impostor.Server/Net/Inner/Objects/Components/InnerPlayerPhysics.cs
src/Impostor.Server/Net/Inner/Objects/Components/InnerVoteBanSystem.cs
src/Impostor.Server/Net/Inner/Objects/InnerGameData.cs
src/Impostor.Server/Net/Inner/Objects/InnerLobbyBehaviour.cs
src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.cs
src/Impostor.Server/Net/Inner/Objects/InnerPlayerControl.cs
src/Impostor.Server/Net/Inner/Objects/InnerPlayerInfo.cs
src/Impostor.Server/Net/Inner/Objects/ShipStatus/InnerAirshipStatus.cs
src/Impostor.Server/Net/Inner/Objects/ShipStatus/InnerMiraShipStatus.cs
src/Impostor.Server/Net/Inner/Objects/ShipStatus/InnerPolusShipStatus.cs
src/Impostor.Server/Net/Inner/Objects/ShipStatus/InnerShipStatus.cs
src/Impostor.Server/Net/Inner/Objects/ShipStatus/InnerSkeldShipStatus.cs
src/Impostor.Server/Net/Manager/ClientManager.cs
src/Impostor.Server/Net/Matchmaker.cs
src/Impostor.Server/Net/State/Game.Data.cs
src/Impostor.Server/Net/State/Game.Incoming.cs
src/Impostor.Server/Net/State/Game.Outgoing.cs
src/Impostor.Server/Program.cs
src/Impostor.Server/RealDateTimeProvider.cs
src/Impostor.Server/Recorder/ClientRecorder.cs
src/Impostor.Server/Utils/RealDateTimeProvider.cs [new file with mode: 0644]
src/Impostor.Server/Utils/ServerEnvironment.cs
src/Impostor.Tools.ServerReplay/FakeDateTimeProvider.cs
src/Impostor.Tools.ServerReplay/Program.cs
src/ProjectRules.ruleset

diff --git a/src/Impostor.Api/Events/Client/IClientConnectedEvent.cs b/src/Impostor.Api/Events/Client/IClientConnectedEvent.cs
new file mode 100644 (file)
index 0000000..c638170
--- /dev/null
@@ -0,0 +1,12 @@
+using Impostor.Api.Net;
+
+namespace Impostor.Api.Events.Client
+{
+    /// <summary>
+    ///     Called just after a <see cref="IClient"/> is created and connected.
+    /// </summary>
+    public interface IClientConnectedEvent : IClientEvent
+    {
+        IClient Client { get; }
+    }
+}
diff --git a/src/Impostor.Api/Events/Client/IClientConnectionEvent.cs b/src/Impostor.Api/Events/Client/IClientConnectionEvent.cs
new file mode 100644 (file)
index 0000000..17aa8ec
--- /dev/null
@@ -0,0 +1,13 @@
+using Impostor.Api.Net;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Api.Events.Client
+{
+    /// <summary>
+    ///     Called just before a <see cref="IHazelConnection"/> is registered.
+    /// </summary>
+    public interface IClientConnectionEvent : IClientEvent
+    {
+        IMessageReader HandshakeData { get; }
+    }
+}
diff --git a/src/Impostor.Api/Events/Client/IClientEvent.cs b/src/Impostor.Api/Events/Client/IClientEvent.cs
new file mode 100644 (file)
index 0000000..69184bc
--- /dev/null
@@ -0,0 +1,9 @@
+using Impostor.Api.Net;
+
+namespace Impostor.Api.Events.Client
+{
+    public interface IClientEvent : IEvent
+    {
+        IHazelConnection Connection { get; }
+    }
+}
diff --git a/src/Impostor.Api/Events/Game/IGamePlayerJoiningEvent.cs b/src/Impostor.Api/Events/Game/IGamePlayerJoiningEvent.cs
new file mode 100644 (file)
index 0000000..dc326b0
--- /dev/null
@@ -0,0 +1,15 @@
+using Impostor.Api.Games;
+using Impostor.Api.Net;
+
+namespace Impostor.Api.Events
+{
+    /// <summary>
+    ///     Called just before a <see cref="IClientPlayer"/> joins a game.
+    /// </summary>
+    public interface IGamePlayerJoiningEvent : IGameEvent
+    {
+        IClientPlayer Player { get; }
+
+        GameJoinResult? JoinResult { get; set; }
+    }
+}
diff --git a/src/Impostor.Api/Events/MultiDisposable.cs b/src/Impostor.Api/Events/MultiDisposable.cs
new file mode 100644 (file)
index 0000000..bacaef7
--- /dev/null
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Impostor.Api.Events
+{
+    /// <summary>
+    ///     Disposes multiple <see cref="IDisposable" />.
+    /// </summary>
+    public class MultiDisposable : IDisposable
+    {
+        private readonly IEnumerable<IDisposable> _disposables;
+
+        public MultiDisposable(IEnumerable<IDisposable> disposables)
+        {
+            _disposables = disposables;
+        }
+
+        public MultiDisposable(params IDisposable[] disposables) : this(disposables.AsEnumerable())
+        {
+        }
+
+        public void Dispose()
+        {
+            foreach (var disposable in _disposables)
+            {
+                disposable?.Dispose();
+            }
+        }
+    }
+}
index ecc11f811df767a01a5a41c4c871a1d7043c38c8..8d95a1c6779f5aa3e0d1c3fc211746648d0f41dd 100644 (file)
@@ -90,5 +90,24 @@ namespace Impostor.Api.Games
         /// <param name="id">ID of the client.</param>
         /// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
         ValueTask SendToAsync(IMessageWriter writer, int id);
+
+        /// <summary>
+        ///     Creates a MessageWriter with GameData header.
+        /// </summary>
+        /// <remarks>Use with caution, recommended only for advanced developers.</remarks>
+        /// <param name="targetNetId">Net id of the InnerNetObject.</param>
+        /// <param name="callId">Rpc id of the message.</param>
+        /// <param name="targetClientId">Client id of GameDataTo's target.</param>
+        /// <param name="type">Message type of the message.</param>
+        /// <returns>A <see cref="IMessageWriter" /> that you can fill with rpc data and send using <see cref="FinishRpcAsync"/>.</returns>
+        IMessageWriter StartRpc(uint targetNetId, RpcCalls callId, int? targetClientId, MessageType type = MessageType.Reliable);
+
+        /// <summary>
+        /// Finishes rpc message and sends it to the target.
+        /// </summary>
+        /// <param name="writer">Message writer of the rpc.</param>
+        /// <param name="targetClientId">Id of the receiving client.</param>
+        /// <returns>A <see cref="ValueTask" /> representing the asynchronous operation.</returns>
+        ValueTask FinishRpcAsync(IMessageWriter writer, int? targetClientId = null);
     }
 }
diff --git a/src/Impostor.Api/IDateTimeProvider.cs b/src/Impostor.Api/IDateTimeProvider.cs
deleted file mode 100644 (file)
index 95b3dee..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-using System;
-
-namespace Impostor.Api
-{
-    public interface IDateTimeProvider
-    {
-        DateTimeOffset UtcNow { get; }
-    }
-}
diff --git a/src/Impostor.Api/Net/Custom/ICustomMessage.cs b/src/Impostor.Api/Net/Custom/ICustomMessage.cs
new file mode 100644 (file)
index 0000000..52364c8
--- /dev/null
@@ -0,0 +1,7 @@
+namespace Impostor.Api.Net.Custom
+{
+    public interface ICustomMessage
+    {
+        byte Id { get; }
+    }
+}
diff --git a/src/Impostor.Api/Net/Custom/ICustomMessageManager.cs b/src/Impostor.Api/Net/Custom/ICustomMessageManager.cs
new file mode 100644 (file)
index 0000000..81cd606
--- /dev/null
@@ -0,0 +1,18 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Impostor.Api.Net.Custom
+{
+    public interface ICustomMessageManager<T>
+        where T : ICustomMessage
+    {
+        bool TryGet(byte id, [MaybeNullWhen(false)] out T message);
+
+        /// <summary>
+        ///     Register a custom message.
+        /// </summary>
+        /// <param name="message"><typeparamref name="T"/> message.</param>
+        /// <returns>Disposable that unregisters the message.</returns>
+        IDisposable Register(T message);
+    }
+}
diff --git a/src/Impostor.Api/Net/Custom/ICustomRootMessage.cs b/src/Impostor.Api/Net/Custom/ICustomRootMessage.cs
new file mode 100644 (file)
index 0000000..352cc1b
--- /dev/null
@@ -0,0 +1,10 @@
+using System.Threading.Tasks;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Api.Net.Custom
+{
+    public interface ICustomRootMessage : ICustomMessage
+    {
+        ValueTask HandleMessageAsync(IClient client, IMessageReader reader, MessageType messageType);
+    }
+}
diff --git a/src/Impostor.Api/Net/Custom/ICustomRpc.cs b/src/Impostor.Api/Net/Custom/ICustomRpc.cs
new file mode 100644 (file)
index 0000000..262b573
--- /dev/null
@@ -0,0 +1,11 @@
+using System.Threading.Tasks;
+using Impostor.Api.Net.Inner;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Api.Net.Custom
+{
+    public interface ICustomRpc : ICustomMessage
+    {
+        ValueTask<bool> HandleRpcAsync(IInnerNetObject innerNetObject, IClientPlayer sender, IClientPlayer? target, IMessageReader reader);
+    }
+}
index fd500adcd815a7bd266c2a17325d05fa5eca7749..346e6e475386acb9d77ba37578f4d444273a545c 100644 (file)
@@ -19,6 +19,13 @@ namespace Impostor.Api.Net.Messages
 
         public MessageType SendOption { get; }
 
+        /// <summary>
+        ///     Copies the contents of this writer into a new array.
+        /// </summary>
+        /// <param name="includeHeader">Whether to include message header in the array.</param>
+        /// <returns>An array containing the data in the current writer.</returns>
+        byte[] ToByteArray(bool includeHeader);
+
         /// <summary>
         ///     Writes a boolean to the message.
         /// </summary>
diff --git a/src/Impostor.Api/Utils/IDateTimeProvider.cs b/src/Impostor.Api/Utils/IDateTimeProvider.cs
new file mode 100644 (file)
index 0000000..8212b99
--- /dev/null
@@ -0,0 +1,9 @@
+using System;
+
+namespace Impostor.Api.Utils
+{
+    public interface IDateTimeProvider
+    {
+        DateTimeOffset UtcNow { get; }
+    }
+}
diff --git a/src/Impostor.Api/Utils/IServerEnvironment.cs b/src/Impostor.Api/Utils/IServerEnvironment.cs
new file mode 100644 (file)
index 0000000..006aaeb
--- /dev/null
@@ -0,0 +1,7 @@
+namespace Impostor.Api.Utils
+{
+    public interface IServerEnvironment
+    {
+        string Version { get; }
+    }
+}
diff --git a/src/Impostor.Server/Events/Client/ClientConnectedEvent.cs b/src/Impostor.Server/Events/Client/ClientConnectedEvent.cs
new file mode 100644 (file)
index 0000000..569fccb
--- /dev/null
@@ -0,0 +1,18 @@
+using Impostor.Api.Events.Client;
+using Impostor.Api.Net;
+
+namespace Impostor.Server.Events.Client
+{
+    public class ClientConnectedEvent : IClientConnectedEvent
+    {
+        public ClientConnectedEvent(IHazelConnection connection, IClient client)
+        {
+            Connection = connection;
+            Client = client;
+        }
+
+        public IHazelConnection Connection { get; }
+
+        public IClient Client { get; }
+    }
+}
diff --git a/src/Impostor.Server/Events/Client/ClientConnectionEvent.cs b/src/Impostor.Server/Events/Client/ClientConnectionEvent.cs
new file mode 100644 (file)
index 0000000..e4bb594
--- /dev/null
@@ -0,0 +1,19 @@
+using Impostor.Api.Events.Client;
+using Impostor.Api.Net;
+using Impostor.Api.Net.Messages;
+
+namespace Impostor.Server.Events.Client
+{
+    public class ClientConnectionEvent : IClientConnectionEvent
+    {
+        public ClientConnectionEvent(IHazelConnection connection, IMessageReader handshakeData)
+        {
+            Connection = connection;
+            HandshakeData = handshakeData;
+        }
+
+        public IHazelConnection Connection { get; }
+
+        public IMessageReader HandshakeData { get; }
+    }
+}
index 4ab2d15365465958a91848b96e2eb8f6ffc7471d..2922631ee1d04873106dce30daad64984e74cc34 100644 (file)
@@ -36,7 +36,7 @@ namespace Impostor.Server.Events
             }
 
             var eventListeners = RegisteredEventListener.FromType(listener.GetType());
-            var disposes = new IDisposable[eventListeners.Count];
+            var disposes = new List<IDisposable>(eventListeners.Count);
 
             foreach (var eventListener in eventListeners)
             {
@@ -51,7 +51,7 @@ namespace Impostor.Server.Events
                     wrappedEventListener.EventType,
                     _ => new TemporaryEventRegister());
 
-                register.Add(wrappedEventListener);
+                disposes.Add(register.Add(wrappedEventListener));
             }
 
             if (eventListeners.Count > 0)
diff --git a/src/Impostor.Server/Events/Game/GamePlayerJoiningEvent.cs b/src/Impostor.Server/Events/Game/GamePlayerJoiningEvent.cs
new file mode 100644 (file)
index 0000000..f24f28b
--- /dev/null
@@ -0,0 +1,21 @@
+using Impostor.Api.Events;
+using Impostor.Api.Games;
+using Impostor.Api.Net;
+
+namespace Impostor.Server.Events
+{
+    public class GamePlayerJoiningEvent : IGamePlayerJoiningEvent
+    {
+        public GamePlayerJoiningEvent(IGame game, IClientPlayer player)
+        {
+            Game = game;
+            Player = player;
+        }
+
+        public IGame Game { get; }
+
+        public IClientPlayer Player { get; }
+
+        public GameJoinResult? JoinResult { get; set; }
+    }
+}
diff --git a/src/Impostor.Server/Events/MultiDisposable.cs b/src/Impostor.Server/Events/MultiDisposable.cs
deleted file mode 100644 (file)
index b1e2348..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Impostor.Server.Events
-{
-    /// <summary>
-    ///     Disposes multiple <see cref="IDisposable" />.
-    /// </summary>
-    internal class MultiDisposable : IDisposable
-    {
-        private readonly IEnumerable<IDisposable> _disposables;
-
-        public MultiDisposable(IEnumerable<IDisposable> disposables)
-        {
-            _disposables = disposables;
-        }
-
-        public void Dispose()
-        {
-            foreach (var disposable in _disposables)
-            {
-                disposable?.Dispose();
-            }
-        }
-    }
-}
index dcc501c237f1e5fe4b088e6c5a6a0e95e63ec73d..5199b6d76d02b2cf6babb2b4d9193f8b41b2e409 100644 (file)
@@ -4,6 +4,7 @@ using Impostor.Api;
 using Impostor.Api.Games;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Messages;
 using Impostor.Api.Net.Messages.C2S;
 using Impostor.Api.Net.Messages.S2C;
@@ -21,14 +22,16 @@ namespace Impostor.Server.Net
         private readonly AntiCheatConfig _antiCheatConfig;
         private readonly ClientManager _clientManager;
         private readonly GameManager _gameManager;
+        private readonly ICustomMessageManager<ICustomRootMessage> _customMessageManager;
 
-        public Client(ILogger<Client> logger, IOptions<AntiCheatConfig> antiCheatOptions, ClientManager clientManager, GameManager gameManager, string name, int gameVersion, IHazelConnection connection)
+        public Client(ILogger<Client> logger, IOptions<AntiCheatConfig> antiCheatOptions, ClientManager clientManager, GameManager gameManager, ICustomMessageManager<ICustomRootMessage> customMessageManager, string name, int gameVersion, IHazelConnection connection)
             : base(name, gameVersion, connection)
         {
             _logger = logger;
             _antiCheatConfig = antiCheatOptions.Value;
             _clientManager = clientManager;
             _gameManager = gameManager;
+            _customMessageManager = customMessageManager;
         }
 
         public override async ValueTask<bool> ReportCheatAsync(CheatContext context, string message)
@@ -169,10 +172,10 @@ namespace Impostor.Server.Net
 
                     var toPlayer = flag == MessageFlags.GameDataTo;
 
-                    // Handle packet.
-                    using var readerCopy = reader.Copy();
+                    var position = reader.Position;
+                    var verified = await Player!.Game.HandleGameDataAsync(reader, Player, toPlayer);
+                    reader.Seek(position);
 
-                    var verified = await Player!.Game.HandleGameDataAsync(readerCopy, Player, toPlayer);
                     if (verified)
                     {
                         // Broadcast packet to all other players.
@@ -255,6 +258,12 @@ namespace Impostor.Server.Net
                 }
 
                 default:
+                    if (_customMessageManager.TryGet(flag, out var customRootMessage))
+                    {
+                        await customRootMessage.HandleMessageAsync(this, reader, messageType);
+                        break;
+                    }
+
                     _logger.LogWarning("Server received unknown flag {0}.", flag);
                     break;
             }
diff --git a/src/Impostor.Server/Net/Custom/CustomMessageManager.cs b/src/Impostor.Server/Net/Custom/CustomMessageManager.cs
new file mode 100644 (file)
index 0000000..42b3c7b
--- /dev/null
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Concurrent;
+using System.Diagnostics.CodeAnalysis;
+using Impostor.Api;
+using Impostor.Api.Net.Custom;
+
+namespace Impostor.Server.Net.Custom
+{
+    public class CustomMessageManager<T> : ICustomMessageManager<T>
+        where T : ICustomMessage
+    {
+        private readonly ConcurrentDictionary<byte, T> _messages = new ConcurrentDictionary<byte, T>();
+
+        public bool TryGet(byte id, [MaybeNullWhen(false)] out T message)
+        {
+            return _messages.TryGetValue(id, out message);
+        }
+
+        public IDisposable Register(T message)
+        {
+            if (!_messages.TryAdd(message.Id, message))
+            {
+                throw new ImpostorException($"Message with id: {message.Id} was already registered");
+            }
+
+            return new UnregisterDisposable(this, message);
+        }
+
+        private class UnregisterDisposable : IDisposable
+        {
+            private readonly CustomMessageManager<T> _manager;
+            private readonly T _message;
+
+            private bool _disposed;
+
+            public UnregisterDisposable(CustomMessageManager<T> manager, T message)
+            {
+                _manager = manager;
+                _message = message;
+            }
+
+            public void Dispose()
+            {
+                if (_disposed)
+                {
+                    throw new ObjectDisposedException("Tried to dispose already disposed object");
+                }
+
+                _manager._messages.TryRemove(_message.Id, out _);
+                _disposed = true;
+            }
+        }
+    }
+}
index 4a1510414335b1231e3fa6749414dcbf1e363829..62339c1ff216d14d742bc8df608fda2d9f27d7a0 100644 (file)
@@ -1,6 +1,7 @@
 using System.Threading.Tasks;
 using Impostor.Api.Games;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner;
 using Impostor.Api.Net.Messages;
 using Impostor.Server.Net.State;
@@ -11,8 +12,11 @@ namespace Impostor.Server.Net.Inner
     {
         private const int HostInheritId = -2;
 
-        protected InnerNetObject(Game game)
+        private readonly ICustomMessageManager<ICustomRpc> _customMessageManager;
+
+        protected InnerNetObject(ICustomMessageManager<ICustomRpc> customMessageManager, Game game)
         {
+            _customMessageManager = customMessageManager;
             Game = game;
         }
 
@@ -36,9 +40,22 @@ namespace Impostor.Server.Net.Inner
 
         public abstract ValueTask DeserializeAsync(IClientPlayer sender, IClientPlayer? target, IMessageReader reader, bool initialState);
 
-        public abstract ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader);
+        public virtual async ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
+        {
+            return await HandleCustomRpcAsync(sender, target, call, reader) ?? await UnregisteredCall(call, sender);
+        }
+
+        protected async ValueTask<bool?> HandleCustomRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
+        {
+            if (_customMessageManager.TryGet((byte)call, out var customRpc))
+            {
+                return await customRpc.HandleRpcAsync(this, sender, target, reader);
+            }
+
+            return null;
+        }
 
-        public virtual ValueTask OnSpawnAsync()
+        internal virtual ValueTask OnSpawnAsync()
         {
             return default;
         }
index 0b52905482f6b39efaca26c5e7d252693a46f679..8d92d504a31b745514a4d83aacae59f12fa5d782 100644 (file)
@@ -4,6 +4,7 @@ using System.Threading.Tasks;
 using Impostor.Api;
 using Impostor.Api.Events.Managers;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner;
 using Impostor.Api.Net.Messages;
 using Impostor.Api.Net.Messages.Rpcs;
@@ -27,7 +28,7 @@ namespace Impostor.Server.Net.Inner.Objects.Components
         private ushort _lastSequenceId;
         private bool _spawnSnapAllowed;
 
-        public InnerCustomNetworkTransform(Game game, ILogger<InnerCustomNetworkTransform> logger, InnerPlayerControl playerControl, IEventManager eventManager, ObjectPool<PlayerMovementEvent> pool) : base(game)
+        public InnerCustomNetworkTransform(ICustomMessageManager<ICustomRpc> customMessageManager, Game game, ILogger<InnerCustomNetworkTransform> logger, InnerPlayerControl playerControl, IEventManager eventManager, ObjectPool<PlayerMovementEvent> pool) : base(customMessageManager, game)
         {
             _logger = logger;
             _playerControl = playerControl;
@@ -135,7 +136,7 @@ namespace Impostor.Server.Net.Inner.Objects.Components
                 return true;
             }
 
-            return await UnregisteredCall(call, sender);
+            return await base.HandleRpcAsync(sender, target, call, reader);
         }
 
         internal async ValueTask SetPositionAsync(IClientPlayer sender, Vector2 position, Vector2 velocity)
index edd7b1de84233efdd258926dc277a8e36d41923a..053fbf384f41d428fac89ce658594df029c689cd 100644 (file)
@@ -1,9 +1,8 @@
 using System;
 using System.Threading.Tasks;
 using Impostor.Api.Events.Managers;
-using Impostor.Api.Innersloth;
-using Impostor.Api.Innersloth.Maps;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner;
 using Impostor.Api.Net.Messages;
 using Impostor.Api.Net.Messages.Rpcs;
@@ -19,7 +18,7 @@ namespace Impostor.Server.Net.Inner.Objects.Components
         private readonly InnerPlayerControl _playerControl;
         private readonly IEventManager _eventManager;
 
-        public InnerPlayerPhysics(Game game, ILogger<InnerPlayerPhysics> logger, InnerPlayerControl playerControl, IEventManager eventManager) : base(game)
+        public InnerPlayerPhysics(ICustomMessageManager<ICustomRpc> customMessageManager, Game game, ILogger<InnerPlayerPhysics> logger, InnerPlayerControl playerControl, IEventManager eventManager) : base(customMessageManager, game)
         {
             _logger = logger;
             _playerControl = playerControl;
@@ -85,7 +84,7 @@ namespace Impostor.Server.Net.Inner.Objects.Components
                     break;
 
                 default:
-                    return await UnregisteredCall(call, sender);
+                    return await base.HandleRpcAsync(sender, target, call, reader);
             }
 
             return true;
index 69348973803d8e50aa617aa8799d83f2ff80fe70..6877907116508a8ba816e9b47547bb151c8031a8 100644 (file)
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Threading.Tasks;
 using Impostor.Api;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner;
 using Impostor.Api.Net.Inner.Objects;
 using Impostor.Api.Net.Messages;
@@ -17,7 +18,7 @@ namespace Impostor.Server.Net.Inner.Objects.Components
         private readonly ILogger<InnerVoteBanSystem> _logger;
         private readonly Dictionary<int, int[]> _votes;
 
-        public InnerVoteBanSystem(Game game, ILogger<InnerVoteBanSystem> logger) : base(game)
+        public InnerVoteBanSystem(ICustomMessageManager<ICustomRpc> customMessageManager, Game game, ILogger<InnerVoteBanSystem> logger) : base(customMessageManager, game)
         {
             _logger = logger;
             _votes = new Dictionary<int, int[]>();
@@ -78,7 +79,7 @@ namespace Impostor.Server.Net.Inner.Objects.Components
                 return true;
             }
 
-            return await UnregisteredCall(call, sender);
+            return await base.HandleRpcAsync(sender, target, call, reader);
         }
     }
 }
index 0a29d63786ff3323e856c648d0d7ac456e0f115b..e7980da205be419d03828bec4e93c1c2672833fb 100644 (file)
@@ -4,6 +4,7 @@ using System.Collections.Generic;
 using System.Threading.Tasks;
 using Impostor.Api;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner;
 using Impostor.Api.Net.Inner.Objects;
 using Impostor.Api.Net.Messages;
@@ -20,7 +21,7 @@ namespace Impostor.Server.Net.Inner.Objects
         private readonly ILogger<InnerGameData> _logger;
         private readonly ConcurrentDictionary<byte, InnerPlayerInfo> _allPlayers;
 
-        public InnerGameData(Game game, ILogger<InnerGameData> logger, IServiceProvider serviceProvider) : base(game)
+        public InnerGameData(ICustomMessageManager<ICustomRpc> customMessageManager, Game game, ILogger<InnerGameData> logger, IServiceProvider serviceProvider) : base(customMessageManager, game)
         {
             _logger = logger;
             _allPlayers = new ConcurrentDictionary<byte, InnerPlayerInfo>();
@@ -113,7 +114,7 @@ namespace Impostor.Server.Net.Inner.Objects
                 }
 
                 default:
-                    return await UnregisteredCall(call, sender);
+                    return await base.HandleRpcAsync(sender, target, call, reader);
             }
 
             return true;
index c897a6860cc333a4e62fc2086084b948f00d4f2a..225b438fed18ddd01d8a598c2ede77f6e803dd95 100644 (file)
@@ -1,7 +1,7 @@
 using System;
 using System.Threading.Tasks;
 using Impostor.Api.Net;
-using Impostor.Api.Net.Inner;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner.Objects;
 using Impostor.Api.Net.Messages;
 using Impostor.Server.Net.State;
@@ -10,7 +10,7 @@ namespace Impostor.Server.Net.Inner.Objects
 {
     internal class InnerLobbyBehaviour : InnerNetObject, IInnerLobbyBehaviour
     {
-        public InnerLobbyBehaviour(Game game) : base(game)
+        public InnerLobbyBehaviour(ICustomMessageManager<ICustomRpc> customMessageManager, Game game) : base(customMessageManager, game)
         {
             Components.Add(this);
         }
@@ -24,10 +24,5 @@ namespace Impostor.Server.Net.Inner.Objects
         {
             throw new NotImplementedException();
         }
-
-        public override ValueTask<bool> HandleRpcAsync(ClientPlayer sender, ClientPlayer? target, RpcCalls call, IMessageReader reader)
-        {
-            throw new NotImplementedException();
-        }
     }
 }
index f774cd0c0e6026c147e42be4fb82e5cf7fc14d2b..104ceae8ce06c75ed1d1651ab66fc6a063e81492 100644 (file)
@@ -6,6 +6,7 @@ using Impostor.Api;
 using Impostor.Api.Events.Managers;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner;
 using Impostor.Api.Net.Messages;
 using Impostor.Api.Net.Messages.Rpcs;
@@ -24,7 +25,7 @@ namespace Impostor.Server.Net.Inner.Objects
         [AllowNull]
         private PlayerVoteArea[] _playerStates;
 
-        public InnerMeetingHud(Game game, ILogger<InnerMeetingHud> logger, IEventManager eventManager) : base(game)
+        public InnerMeetingHud(ICustomMessageManager<ICustomRpc> customMessageManager, Game game, ILogger<InnerMeetingHud> logger, IEventManager eventManager) : base(customMessageManager, game)
         {
             _logger = logger;
             _eventManager = eventManager;
@@ -120,7 +121,7 @@ namespace Impostor.Server.Net.Inner.Objects
                 }
 
                 default:
-                    return await UnregisteredCall(call, sender);
+                    return await base.HandleRpcAsync(sender, target, call, reader);
             }
 
             return true;
index 488e7259830918f3a4f9cc15700bfe77b7770677..c78757797564b3ce8aabea5f9fb630fc6d7ac9d9 100644 (file)
@@ -8,10 +8,12 @@ using Impostor.Api.Events.Managers;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Customization;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner;
 using Impostor.Api.Net.Inner.Objects;
 using Impostor.Api.Net.Messages;
 using Impostor.Api.Net.Messages.Rpcs;
+using Impostor.Api.Utils;
 using Impostor.Server.Events.Player;
 using Impostor.Server.Net.Inner.Objects.Components;
 using Impostor.Server.Net.State;
@@ -28,7 +30,7 @@ namespace Impostor.Server.Net.Inner.Objects
         private readonly IEventManager _eventManager;
         private readonly IDateTimeProvider _dateTimeProvider;
 
-        public InnerPlayerControl(Game game, ILogger<InnerPlayerControl> logger, IServiceProvider serviceProvider, IEventManager eventManager, IDateTimeProvider dateTimeProvider) : base(game)
+        public InnerPlayerControl(ICustomMessageManager<ICustomRpc> customMessageManager, Game game, ILogger<InnerPlayerControl> logger, IServiceProvider serviceProvider, IEventManager eventManager, IDateTimeProvider dateTimeProvider) : base(customMessageManager, game)
         {
             _logger = logger;
             _eventManager = eventManager;
@@ -296,7 +298,7 @@ namespace Impostor.Server.Net.Inner.Objects
                 }
 
                 default:
-                    return await UnregisteredCall(call, sender);
+                    return await base.HandleRpcAsync(sender, target, call, reader);
             }
 
             return true;
index 763782a32b985ce164fb0a8dd97a8c24d0b61443..1a4ac1cb2b0e1876262167ec1eb52ff6394a9ca3 100644 (file)
@@ -1,10 +1,10 @@
 using System;
 using System.Collections.Generic;
-using Impostor.Api;
 using Impostor.Api.Games;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Customization;
 using Impostor.Api.Net.Messages;
+using Impostor.Api.Utils;
 
 namespace Impostor.Server.Net.Inner.Objects
 {
index 3ed285c106723d76ae4b59f1ae8dbdd82c643b61..6ef1fa6a118ff83b9da51d458d1ca2d00c31256b 100644 (file)
@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Numerics;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Maps;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner.Objects.ShipStatus;
 using Impostor.Server.Net.Inner.Objects.Systems;
 using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
@@ -12,7 +13,7 @@ namespace Impostor.Server.Net.Inner.Objects.ShipStatus
 {
     internal class InnerAirshipStatus : InnerShipStatus, IInnerAirshipStatus
     {
-        public InnerAirshipStatus(Game game) : base(game)
+        public InnerAirshipStatus(ICustomMessageManager<ICustomRpc> customMessageManager, Game game) : base(customMessageManager, game)
         {
         }
 
index 6f1879de0d3fb3845a0d8929b8bc1d1581db9c7e..a75167d774baf2bc7c3b090cb9028b802b8d600f 100644 (file)
@@ -2,6 +2,7 @@ using System.Collections.Generic;
 using System.Numerics;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Maps;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner.Objects.ShipStatus;
 using Impostor.Server.Net.Inner.Objects.Systems;
 using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
@@ -11,7 +12,7 @@ namespace Impostor.Server.Net.Inner.Objects.ShipStatus
 {
     internal class InnerMiraShipStatus : InnerShipStatus, IInnerMiraShipStatus
     {
-        public InnerMiraShipStatus(Game game) : base(game)
+        public InnerMiraShipStatus(ICustomMessageManager<ICustomRpc> customMessageManager, Game game) : base(customMessageManager, game)
         {
         }
 
index 3274727ed41c52f74677d7b51e7eaa2bb195fcac..dccbeec2292245bc0e9a8673ed586a3cc31b479d 100644 (file)
@@ -2,6 +2,7 @@ using System.Collections.Generic;
 using System.Numerics;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Maps;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner.Objects.ShipStatus;
 using Impostor.Server.Net.Inner.Objects.Systems;
 using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
@@ -11,7 +12,7 @@ namespace Impostor.Server.Net.Inner.Objects.ShipStatus
 {
     internal class InnerPolusShipStatus : InnerShipStatus, IInnerPolusShipStatus
     {
-        public InnerPolusShipStatus(Game game) : base(game)
+        public InnerPolusShipStatus(ICustomMessageManager<ICustomRpc> customMessageManager, Game game) : base(customMessageManager, game)
         {
         }
 
index 3dd2d5413949a066bc0e1f89f42bfd309ded7a24..4d14c632ebb1b2ff6501bf606ab00b3ae335ccfd 100644 (file)
@@ -7,6 +7,7 @@ using Impostor.Api;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Maps;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner;
 using Impostor.Api.Net.Inner.Objects.ShipStatus;
 using Impostor.Api.Net.Messages;
@@ -21,7 +22,7 @@ namespace Impostor.Server.Net.Inner.Objects.ShipStatus
     {
         private readonly Dictionary<SystemTypes, ISystemType> _systems = new Dictionary<SystemTypes, ISystemType>();
 
-        protected InnerShipStatus(Game game) : base(game)
+        protected InnerShipStatus(ICustomMessageManager<ICustomRpc> customMessageManager, Game game) : base(customMessageManager, game)
         {
             Components.Add(this);
         }
@@ -36,7 +37,7 @@ namespace Impostor.Server.Net.Inner.Objects.ShipStatus
 
         public abstract Vector2 MeetingSpawnCenter { get; }
 
-        public override ValueTask OnSpawnAsync()
+        internal override ValueTask OnSpawnAsync()
         {
             for (var i = 0; i < Doors.Count; i++)
             {
@@ -105,7 +106,7 @@ namespace Impostor.Server.Net.Inner.Objects.ShipStatus
                 }
 
                 default:
-                    return await UnregisteredCall(call, sender);
+                    return await base.HandleRpcAsync(sender, target, call, reader);
             }
 
             return true;
index 6670aad68dcf82d73db7fc053b2f0c8840fd4d4a..09523c100210d87e90e31866dbf2b6bc03d4e1a5 100644 (file)
@@ -2,6 +2,7 @@ using System.Collections.Generic;
 using System.Numerics;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Maps;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Inner.Objects.ShipStatus;
 using Impostor.Server.Net.Inner.Objects.Systems;
 using Impostor.Server.Net.Inner.Objects.Systems.ShipStatus;
@@ -11,7 +12,7 @@ namespace Impostor.Server.Net.Inner.Objects.ShipStatus
 {
     internal class InnerSkeldShipStatus : InnerShipStatus, IInnerSkeldShipStatus
     {
-        public InnerSkeldShipStatus(Game game) : base(game)
+        public InnerSkeldShipStatus(ICustomMessageManager<ICustomRpc> customMessageManager, Game game) : base(customMessageManager, game)
         {
         }
 
index 7a10181a79672c19632f5fcfb9649ef07fa4b1ad..903c81005f4f90d3282eda159e85324e200b9845 100644 (file)
@@ -10,6 +10,7 @@ using Impostor.Api.Net.Messages;
 using Impostor.Api.Net.Messages.S2C;
 using Impostor.Hazel;
 using Impostor.Server.Config;
+using Impostor.Server.Events.Client;
 using Impostor.Server.Net.Factories;
 using Microsoft.Extensions.Logging;
 
@@ -24,13 +25,15 @@ namespace Impostor.Server.Net.Manager
         };
 
         private readonly ILogger<ClientManager> _logger;
+        private readonly IEventManager _eventManager;
         private readonly ConcurrentDictionary<int, ClientBase> _clients;
         private readonly IClientFactory _clientFactory;
         private int _idLast;
 
-        public ClientManager(ILogger<ClientManager> logger, IClientFactory clientFactory)
+        public ClientManager(ILogger<ClientManager> logger, IEventManager eventManager, IClientFactory clientFactory)
         {
             _logger = logger;
+            _eventManager = eventManager;
             _clientFactory = clientFactory;
             _clients = new ConcurrentDictionary<int, ClientBase>();
         }
@@ -85,6 +88,8 @@ namespace Impostor.Server.Net.Manager
             client.Id = id;
             _logger.LogTrace("Client connected.");
             _clients.TryAdd(id, client);
+
+            await _eventManager.CallAsync(new ClientConnectedEvent(connection, client));
         }
 
         public void Remove(IClient client)
index 6af4f55993c5c10e2e86e13034b5f4aaee01a4ea..79d9c8ff1c78e8c54add067b17998a7c1f1c17fa 100644 (file)
@@ -6,6 +6,7 @@ using Impostor.Api.Events.Managers;
 using Impostor.Api.Net.Messages.C2S;
 using Impostor.Hazel;
 using Impostor.Hazel.Udp;
+using Impostor.Server.Events.Client;
 using Impostor.Server.Net.Hazel;
 using Impostor.Server.Net.Manager;
 using Microsoft.Extensions.Logging;
@@ -15,19 +16,19 @@ namespace Impostor.Server.Net
 {
     internal class Matchmaker
     {
+        private readonly IEventManager _eventManager;
         private readonly ClientManager _clientManager;
         private readonly ObjectPool<MessageReader> _readerPool;
-        private readonly ILogger<Matchmaker> _logger;
         private readonly ILogger<HazelConnection> _connectionLogger;
         private UdpConnectionListener? _connection;
 
         public Matchmaker(
-            ILogger<Matchmaker> logger,
+            IEventManager eventManager,
             ClientManager clientManager,
             ObjectPool<MessageReader> readerPool,
             ILogger<HazelConnection> connectionLogger)
         {
-            _logger = logger;
+            _eventManager = eventManager;
             _clientManager = clientManager;
             _readerPool = readerPool;
             _connectionLogger = connectionLogger;
@@ -65,6 +66,8 @@ namespace Impostor.Server.Net
 
             var connection = new HazelConnection(e.Connection, _connectionLogger);
 
+            await _eventManager.CallAsync(new ClientConnectionEvent(connection, e.HandshakeData));
+
             // Register client
             await _clientManager.RegisterConnectionAsync(connection, name, clientVersion);
         }
index 9a09c1b770f54fb8d7aa95da7ad85f2ff68fc61f..ee1111c1389a10672b6f8cfd13f693b74af23f15 100644 (file)
@@ -18,8 +18,6 @@ namespace Impostor.Server.Net.State
 {
     internal partial class Game
     {
-        private const int FakeClientId = int.MaxValue - 1;
-
         /// <summary>
         ///     Used for global object, spawned by the host.
         /// </summary>
@@ -105,7 +103,8 @@ namespace Impostor.Server.Net.State
                         {
                             if (!await obj.HandleRpcAsync(sender, target, (RpcCalls)reader.ReadByte(), reader))
                             {
-                                return false;
+                                parent.RemoveMessage(reader);
+                                continue;
                             }
                         }
                         else
@@ -133,13 +132,6 @@ namespace Impostor.Server.Net.State
                             var innerNetObject = (InnerNetObject)ActivatorUtilities.CreateInstance(_serviceProvider, SpawnableObjects[objectId], this);
                             var ownerClientId = reader.ReadPackedInt32();
 
-                            // Prevent fake client from being broadcasted.
-                            // TODO: Remove message from stream properly.
-                            if (ownerClientId == FakeClientId)
-                            {
-                                return false;
-                            }
-
                             innerNetObject.SpawnFlags = (SpawnFlags)reader.ReadByte();
 
                             var components = innerNetObject.GetComponentsInChildren<InnerNetObject>();
index 6e1620803c90e9cf04af7f1433153a7374ce84ac..116465f4e9e4eb19ae2b91dcce918228740a4869 100644 (file)
@@ -199,6 +199,14 @@ namespace Impostor.Server.Net.State
                 return GameJoinResult.CreateSuccess(player);
             }
 
+            var @event = new GamePlayerJoiningEvent(this, player);
+            await _eventManager.CallAsync(@event);
+
+            if (@event.JoinResult != null && !@event.JoinResult.Value.IsSuccess)
+            {
+                return @event.JoinResult.Value;
+            }
+
             await HandleJoinGameNew(player, isNew);
             return GameJoinResult.CreateSuccess(player);
         }
index b5b654eaf50013f8c92df5f4179a44316d7db77d..30ebb725f5b7d5091909526395c6e8f39355383e 100644 (file)
@@ -38,11 +38,11 @@ namespace Impostor.Server.Net.State
             }
         }
 
-        internal IMessageWriter StartRpc(uint targetNetId, RpcCalls callId, int targetClientId = -1, MessageType type = MessageType.Reliable)
+        public IMessageWriter StartRpc(uint targetNetId, RpcCalls callId, int? targetClientId = null, MessageType type = MessageType.Reliable)
         {
             var writer = MessageWriter.Get(type);
 
-            if (targetClientId < 0)
+            if (targetClientId == null || targetClientId < 0)
             {
                 writer.StartMessage(MessageFlags.GameData);
                 writer.Write(Code);
@@ -51,7 +51,7 @@ namespace Impostor.Server.Net.State
             {
                 writer.StartMessage(MessageFlags.GameDataTo);
                 writer.Write(Code);
-                writer.WritePacked(targetClientId);
+                writer.WritePacked(targetClientId.Value);
             }
 
             writer.StartMessage(GameDataTag.RpcFlag);
@@ -61,7 +61,7 @@ namespace Impostor.Server.Net.State
             return writer;
         }
 
-        internal ValueTask FinishRpcAsync(IMessageWriter writer, int? targetClientId = null)
+        public ValueTask FinishRpcAsync(IMessageWriter writer, int? targetClientId = null)
         {
             writer.EndMessage();
             writer.EndMessage();
index 846c3aed0503472e16f191336ddbc977592a5c2d..46aaf2b7fb9115dd3e263869187efea4b6664c0d 100644 (file)
@@ -1,16 +1,18 @@
 using System;
 using System.IO;
 using System.Linq;
-using Impostor.Api;
 using Impostor.Api.Events.Managers;
 using Impostor.Api.Games;
 using Impostor.Api.Games.Managers;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Manager;
 using Impostor.Api.Net.Messages;
+using Impostor.Api.Utils;
 using Impostor.Hazel.Extensions;
 using Impostor.Server.Config;
 using Impostor.Server.Events;
 using Impostor.Server.Net;
+using Impostor.Server.Net.Custom;
 using Impostor.Server.Net.Factories;
 using Impostor.Server.Net.Manager;
 using Impostor.Server.Net.Messages;
@@ -123,6 +125,7 @@ namespace Impostor.Server
                         .Get<AuthServerConfig>() ?? new AuthServerConfig();
 
                     services.AddSingleton<ServerEnvironment>();
+                    services.AddSingleton<IServerEnvironment>(p => p.GetRequiredService<ServerEnvironment>());
                     services.AddSingleton<IDateTimeProvider, RealDateTimeProvider>();
 
                     services.Configure<DebugConfig>(host.Configuration.GetSection(DebugConfig.Section));
@@ -208,6 +211,8 @@ namespace Impostor.Server
 
                     services.AddEventPools();
                     services.AddHazel();
+                    services.AddSingleton<ICustomMessageManager<ICustomRootMessage>, CustomMessageManager<ICustomRootMessage>>();
+                    services.AddSingleton<ICustomMessageManager<ICustomRpc>, CustomMessageManager<ICustomRpc>>();
                     services.AddSingleton<IMessageWriterProvider, MessageWriterProvider>();
                     services.AddSingleton<IGameCodeFactory, GameCodeFactory>();
                     services.AddSingleton<IEventManager, EventManager>();
index 506e0c0d993d0f458541f102f1911ce6735b3b6f..c450338aea85e1f4ea43d2e79861ebab77fe608b 100644 (file)
@@ -1,5 +1,5 @@
 using System;
-using Impostor.Api;
+using Impostor.Api.Utils;
 
 namespace Impostor.Server
 {
index 31af22a5dbcbd726917d68fc27fc85272da30b02..0e01e0c556b011ad82e8a48ed6a5a5f41dde2085 100644 (file)
@@ -1,4 +1,5 @@
 using System.Threading.Tasks;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Messages;
 using Impostor.Server.Config;
 using Impostor.Server.Net;
@@ -16,8 +17,8 @@ namespace Impostor.Server.Recorder
         private bool _createdGame;
         private bool _recordAfter;
 
-        public ClientRecorder(ILogger<Client> logger, IOptions<AntiCheatConfig> antiCheatOptions, ClientManager clientManager, GameManager gameManager, string name, int gameVersion, HazelConnection connection, PacketRecorder recorder)
-            : base(logger, antiCheatOptions, clientManager, gameManager, name, gameVersion, connection)
+        public ClientRecorder(ILogger<Client> logger, IOptions<AntiCheatConfig> antiCheatOptions, ClientManager clientManager, ICustomMessageManager<ICustomRootMessage> customMessageManager, GameManager gameManager, string name, int gameVersion, HazelConnection connection, PacketRecorder recorder)
+            : base(logger, antiCheatOptions, clientManager, gameManager, customMessageManager, name, gameVersion, connection)
         {
             _recorder = recorder;
             _isFirst = true;
diff --git a/src/Impostor.Server/Utils/RealDateTimeProvider.cs b/src/Impostor.Server/Utils/RealDateTimeProvider.cs
new file mode 100644 (file)
index 0000000..1b7b5f3
--- /dev/null
@@ -0,0 +1,10 @@
+using System;
+using Impostor.Api.Utils;
+
+namespace Impostor.Server.Utils
+{
+    public class RealDateTimeProvider : IDateTimeProvider
+    {
+        public DateTimeOffset UtcNow => DateTimeOffset.UtcNow;
+    }
+}
index 9c9836aa1d4c77fd0425ffe0f216b4b35c1fd4f7..a3eba159707e1b6e4881f2ebd1cb1e675924777f 100644 (file)
@@ -1,7 +1,11 @@
+using Impostor.Api.Utils;
+
 namespace Impostor.Server.Utils
 {
-    public class ServerEnvironment
+    public class ServerEnvironment : IServerEnvironment
     {
+        public string Version { get; } = DotnetUtils.Version;
+
         public bool IsReplay { get; init; }
     }
 }
index 7bd4beb0134d68ecb1643cfeef766d85c825438a..4291e15747698dbdecba9e168a37b446ee57d87d 100644 (file)
@@ -1,5 +1,5 @@
 using System;
-using Impostor.Api;
+using Impostor.Api.Utils;
 
 namespace Impostor.Tools.ServerReplay
 {
index 8bfb8e016b2fee5545cc84a2521e79903038d9bb..6c8c08b33272271d5a436fc8c8c6eac8752e7e00 100644 (file)
@@ -4,19 +4,21 @@ using System.Diagnostics;
 using System.IO;
 using System.Net;
 using System.Threading.Tasks;
-using Impostor.Api;
 using Impostor.Api.Events.Managers;
 using Impostor.Api.Games;
 using Impostor.Api.Games.Managers;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Net;
+using Impostor.Api.Net.Custom;
 using Impostor.Api.Net.Messages;
 using Impostor.Api.Net.Messages.C2S;
+using Impostor.Api.Utils;
 using Impostor.Hazel;
 using Impostor.Hazel.Extensions;
 using Impostor.Server;
 using Impostor.Server.Events;
 using Impostor.Server.Net;
+using Impostor.Server.Net.Custom;
 using Impostor.Server.Net.Factories;
 using Impostor.Server.Net.Manager;
 using Impostor.Server.Net.Redirector;
@@ -114,6 +116,8 @@ namespace Impostor.Tools.ServerReplay
 
             services.AddEventPools();
             services.AddHazel();
+            services.AddSingleton<ICustomMessageManager<ICustomRootMessage>, CustomMessageManager<ICustomRootMessage>>();
+            services.AddSingleton<ICustomMessageManager<ICustomRpc>, CustomMessageManager<ICustomRpc>>();
 
             return services.BuildServiceProvider();
         }
index 5484352e8d37661278c8ed4e71ad6087f4c1b6e4..a50faddd756043e2e7cd95466600a50efc481a81 100644 (file)
@@ -19,4 +19,7 @@
   <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.SpacingRules">
     <Rule Id="SA1009" Action="None" />
   </Rules>
+  <Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.CSharp.OrderingRules">
+    <Rule Id="SA1202" Action="Info" />
+  </Rules>
 </RuleSet>