]> git.deb.at Git - rhonda/impostor.git/commitdiff
Link player classes internally
authorAeonLucid <aeonlucid@outlook.com>
Fri, 23 Oct 2020 05:19:45 +0000 (07:19 +0200)
committerAeonLucid <aeonlucid@outlook.com>
Fri, 23 Oct 2020 05:19:45 +0000 (07:19 +0200)
16 files changed:
src/Impostor.Api/Games/IGame.cs
src/Impostor.Api/Innersloth/Data/GameNet.cs
src/Impostor.Api/Innersloth/Net/InnerNetObject.cs
src/Impostor.Api/Innersloth/Net/Objects/Components/InnerCustomNetworkTransform.cs
src/Impostor.Api/Innersloth/Net/Objects/Components/InnerPlayerPhysics.cs
src/Impostor.Api/Innersloth/Net/Objects/Components/InnerVoteBanSystem.cs
src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.PlayerInfo.cs
src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.cs
src/Impostor.Api/Innersloth/Net/Objects/InnerLobbyBehaviour.cs
src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.cs
src/Impostor.Api/Innersloth/Net/Objects/InnerPlayerControl.cs
src/Impostor.Api/Innersloth/Net/Objects/InnerShipStatus.cs
src/Impostor.Api/Net/IClientPlayer.cs
src/Impostor.Server/Net/State/ClientPlayer.cs
src/Impostor.Server/Net/State/Game.Data.cs
src/Impostor.Server/Net/State/Game.cs

index 5dbec197cea60c744b63222f7060a8cd86c505f4..05fcbdf471e4bfc2ffa4e7556801127d2633cef3 100644 (file)
@@ -3,6 +3,7 @@ using System.Net;
 using System.Threading.Tasks;
 using Impostor.Api.Innersloth;
 using Impostor.Api.Innersloth.Data;
+using Impostor.Api.Innersloth.Net;
 using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
 
@@ -32,6 +33,11 @@ namespace Impostor.Api.Games
 
         int HostId { get; }
 
+        IClientPlayer GetClientPlayer(int clientId);
+
+        T FindObjectByNetId<T>(uint netId)
+            where T : InnerNetObject;
+
         /// <summary>
         ///     Send the message to all players.
         /// </summary>
index 2d3787983f8d15beeb4f5a4909235c030a79bf7c..29ec6f9f12696229b3c28364c9cb29412eae2cda 100644 (file)
@@ -1,4 +1,5 @@
-using Impostor.Api.Innersloth.Net;
+using Impostor.Api.Games;
+using Impostor.Api.Innersloth.Net;
 using Impostor.Api.Innersloth.Net.Objects;
 
 namespace Impostor.Api.Innersloth.Data
@@ -8,7 +9,14 @@ namespace Impostor.Api.Innersloth.Data
     /// </summary>
     public class GameNet
     {
-        public InnerGameData GameData { get; internal set; }
+        private readonly IGame _game;
+
+        public GameNet(IGame game)
+        {
+            _game = game;
+        }
+
+        public InnerGameData GameData { get; private set; }
 
         internal void OnSpawn(InnerNetObject netObj)
         {
@@ -16,6 +24,23 @@ namespace Impostor.Api.Innersloth.Data
             {
                 GameData = data;
             }
+            else if (netObj is InnerPlayerControl control)
+            {
+                // Hook up InnerPlayerControl <-> IClientPlayer.
+                var clientPlayer = _game.GetClientPlayer(control.OwnerId);
+                if (clientPlayer != null)
+                {
+                    clientPlayer.Character = control;
+                }
+
+                // Hook up InnerPlayerControl <-> InnerPlayerControl.PlayerInfo.
+                control.PlayerInfo = GameData.GetPlayerById(control.PlayerId);
+
+                if (control.PlayerInfo == null)
+                {
+                    GameData.AddPlayer(control);
+                }
+            }
         }
 
         internal void OnDestroy(InnerNetObject netObj)
@@ -24,6 +49,15 @@ namespace Impostor.Api.Innersloth.Data
             {
                 GameData = null;
             }
+            else if (netObj is InnerPlayerControl control)
+            {
+                // Remove InnerPlayerControl <-> IClientPlayer.
+                var clientPlayer = _game.GetClientPlayer(control.OwnerId);
+                if (clientPlayer != null)
+                {
+                    clientPlayer.Character = null;
+                }
+            }
         }
     }
 }
\ No newline at end of file
index 6e112f305dcc9d71b299d8517cdc9919aad13739..adb5a9e8c9dee59fc7b4f285676cd40bb842ee40 100644 (file)
@@ -1,4 +1,5 @@
-using Impostor.Api.Net.Messages;
+using Impostor.Api.Net;
+using Impostor.Api.Net.Messages;
 
 namespace Impostor.Api.Innersloth.Net
 {
@@ -10,10 +11,10 @@ namespace Impostor.Api.Innersloth.Net
 
         public SpawnFlags SpawnFlags { get; internal set; }
 
-        public abstract void HandleRpc(byte callId, IMessageReader reader);
+        public abstract void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader);
 
         public abstract bool Serialize(IMessageWriter writer, bool initialState);
 
-        public abstract void Deserialize(IMessageReader reader, bool initialState);
+        public abstract void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState);
     }
 }
\ No newline at end of file
index a8c4915d350b7fb5c432857f3a22ffd8d02372d7..a506d2e101c57d09eba9e1676e8c20898cb56954 100644 (file)
@@ -1,4 +1,5 @@
 using System.Numerics;
+using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
 using Microsoft.Extensions.Logging;
 
@@ -43,7 +44,7 @@ namespace Impostor.Api.Innersloth.Net.Objects.Components
             return new Vector2(XRange.Lerp(v1), YRange.Lerp(v2));
         }
 
-        public override void HandleRpc(byte callId, IMessageReader reader)
+        public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
         {
             if (callId == 0)
             {
@@ -74,7 +75,7 @@ namespace Impostor.Api.Innersloth.Net.Objects.Components
             return true;
         }
 
-        public override void Deserialize(IMessageReader reader, bool initialState)
+        public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
         {
             var sequenceId = reader.ReadUInt16();
 
index 7c74aafab0ae089dc6fa33553019a07e7583eb17..c4b83a58250f825252bf30018c1268218b5401af 100644 (file)
@@ -1,10 +1,11 @@
-using Impostor.Api.Net.Messages;
+using Impostor.Api.Net;
+using Impostor.Api.Net.Messages;
 
 namespace Impostor.Api.Innersloth.Net.Objects.Components
 {
     public class InnerPlayerPhysics : InnerNetObject
     {
-        public override void HandleRpc(byte callId, IMessageReader reader)
+        public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
         {
             throw new System.NotImplementedException();
         }
@@ -14,7 +15,7 @@ namespace Impostor.Api.Innersloth.Net.Objects.Components
             throw new System.NotImplementedException();
         }
 
-        public override void Deserialize(IMessageReader reader, bool initialState)
+        public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
         {
             throw new System.NotImplementedException();
         }
index ed5f29a02c651bfd260a553fdfcac4827c4078f6..266a3d55cf30e369ed1e43d91199376da08f8b4d 100644 (file)
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
 
 namespace Impostor.Api.Innersloth.Net.Objects.Components
@@ -13,7 +14,7 @@ namespace Impostor.Api.Innersloth.Net.Objects.Components
             _votes = new Dictionary<int, int[]>();
         }
 
-        public override void HandleRpc(byte callId, IMessageReader reader)
+        public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
         {
             throw new NotImplementedException();
         }
@@ -23,7 +24,7 @@ namespace Impostor.Api.Innersloth.Net.Objects.Components
             throw new NotImplementedException();
         }
 
-        public override void Deserialize(IMessageReader reader, bool initialState)
+        public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
         {
             var votes = _votes;
             var unknown = reader.ReadByte();
index b076d9e42572df536ef428ec0ba32d86634d47e9..df8f149b4d4fa227d807c4ff05c581bde5e1c740 100644 (file)
@@ -15,19 +15,19 @@ namespace Impostor.Api.Innersloth.Net.Objects
 
             public byte PlayerId { get; }
 
-            public string PlayerName { get; private set; }
+            public string PlayerName { get; internal set; }
 
-            public byte ColorId { get; private set; }
+            public byte ColorId { get; internal set; }
 
-            public uint HatId { get; private set; }
+            public uint HatId { get; internal set; }
 
-            public uint PetId { get; private set; }
+            public uint PetId { get; internal set; }
 
-            public uint SkinId { get; private set; }
+            public uint SkinId { get; internal set; }
 
-            public bool Disconnected { get; private set; }
+            public bool Disconnected { get; internal set; }
 
-            public bool IsImpostor { get; private set; }
+            public bool IsImpostor { get; internal set; }
 
             public bool IsDead { get; private set; }
 
index 5d07e104ee93b6ddc559fc1510365ffb986df1c7..6c2eb6a74e84452e5f678d9b800f6d4597e7b07a 100644 (file)
@@ -1,7 +1,9 @@
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using Impostor.Api.Games;
 using Impostor.Api.Innersloth.Net.Objects.Components;
+using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
 
 namespace Impostor.Api.Innersloth.Net.Objects
@@ -9,12 +11,12 @@ namespace Impostor.Api.Innersloth.Net.Objects
     public partial class InnerGameData : InnerNetObject
     {
         private readonly IGame _game;
-        private readonly List<PlayerInfo> _allPlayers;
+        private readonly ConcurrentDictionary<byte, PlayerInfo> _allPlayers;
 
         public InnerGameData(IGame game)
         {
             _game = game;
-            _allPlayers = new List<PlayerInfo>();
+            _allPlayers = new ConcurrentDictionary<byte, PlayerInfo>();
 
             Components.Add(this);
             Components.Add(new InnerVoteBanSystem());
@@ -22,22 +24,25 @@ namespace Impostor.Api.Innersloth.Net.Objects
 
         public int PlayerCount => _allPlayers.Count;
 
-        public IReadOnlyList<PlayerInfo> Players => _allPlayers;
+        public IReadOnlyDictionary<byte, PlayerInfo> Players => _allPlayers;
 
-        public PlayerInfo GetPlayerById(byte id)
+        internal void AddPlayer(InnerPlayerControl control)
         {
-            foreach (var player in _allPlayers)
+            var playerId = control.PlayerId;
+            var playerInfo = new PlayerInfo(control.PlayerId);
+
+            if (_allPlayers.TryAdd(playerId, playerInfo))
             {
-                if (player.PlayerId == id)
-                {
-                    return player;
-                }
+                control.PlayerInfo = playerInfo;
             }
+        }
 
-            return null;
+        public PlayerInfo GetPlayerById(byte id)
+        {
+            return _allPlayers.TryGetValue(id, out var player) ? player : null;
         }
 
-        public override void HandleRpc(byte callId, IMessageReader reader)
+        public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
         {
             throw new NotImplementedException();
         }
@@ -47,7 +52,7 @@ namespace Impostor.Api.Innersloth.Net.Objects
             throw new NotImplementedException();
         }
 
-        public override void Deserialize(IMessageReader reader, bool initialState)
+        public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
         {
             if (initialState)
             {
@@ -56,8 +61,13 @@ namespace Impostor.Api.Innersloth.Net.Objects
                 for (var i = 0; i < num; i++)
                 {
                     var playerInfo = new PlayerInfo(reader.ReadByte());
+
                     playerInfo.Deserialize(reader);
-                    _allPlayers.Add(playerInfo);
+
+                    if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo))
+                    {
+                        throw new ImpostorException("Failed to add player to InnerGameData.");
+                    }
                 }
             }
             else
index 7b73ed2ed7a3bdcaebf666d97f630facd92a25fd..3863f41abcebf216f38bd4ee97328c2cd37d55ac 100644 (file)
@@ -1,4 +1,5 @@
 using Impostor.Api.Games;
+using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
 
 namespace Impostor.Api.Innersloth.Net.Objects
@@ -14,7 +15,7 @@ namespace Impostor.Api.Innersloth.Net.Objects
             Components.Add(this);
         }
 
-        public override void HandleRpc(byte callId, IMessageReader reader)
+        public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
         {
             throw new System.NotImplementedException();
         }
@@ -24,7 +25,7 @@ namespace Impostor.Api.Innersloth.Net.Objects
             throw new System.NotImplementedException();
         }
 
-        public override void Deserialize(IMessageReader reader, bool initialState)
+        public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
         {
             throw new System.NotImplementedException();
         }
index 816fe6fd6645427b71eab42a15f4eef6d0f6e356..f60cd7ee45535cd4f49d9cedd2616beb7e809361 100644 (file)
@@ -1,6 +1,8 @@
 using System;
+using System.Linq;
 using Impostor.Api.Games;
 using Impostor.Api.Innersloth.Data;
+using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
 
 namespace Impostor.Api.Innersloth.Net.Objects
@@ -24,18 +26,17 @@ namespace Impostor.Api.Innersloth.Net.Objects
 
         private void PopulateButtons(byte reporter)
         {
-            _playerStates = new PlayerVoteArea[_gameNet.GameData.PlayerCount];
-
-            for (var i = 0; i < _playerStates.Length; i++)
-            {
-                var player = _gameNet.GameData.Players[i];
-                var playerVoteArea = _playerStates[i] = new PlayerVoteArea(this, player.PlayerId);
-
-                playerVoteArea.SetDead(player.PlayerId == reporter, player.Disconnected || player.IsDead);
-            }
+            _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 void HandleRpc(byte callId, IMessageReader reader)
+        public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
         {
             throw new NotImplementedException();
         }
@@ -45,7 +46,7 @@ namespace Impostor.Api.Innersloth.Net.Objects
             throw new NotImplementedException();
         }
 
-        public override void Deserialize(IMessageReader reader, bool initialState)
+        public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
         {
             if (initialState)
             {
index fd9a609f8470bf596f6af676ffeb951efbf8f709..65860f117ccf2cf02c6c6afd13288d5e2f7d6092 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using Impostor.Api.Games;
 using Impostor.Api.Innersloth.Net.Objects.Components;
+using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
 using Microsoft.Extensions.DependencyInjection;
 
@@ -25,9 +26,36 @@ namespace Impostor.Api.Innersloth.Net.Objects
 
         public byte PlayerId { get; private set; }
 
-        public override void HandleRpc(byte callId, IMessageReader reader)
+        public InnerGameData.PlayerInfo PlayerInfo { get; internal set; }
+
+        public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
         {
-            throw new NotImplementedException();
+            switch (callId)
+            {
+                case 3:
+                {
+                    var length = reader.ReadPackedInt32();
+
+                    for (var i = 0; i < length; i++)
+                    {
+                        var playerId = reader.ReadByte();
+                        var player = _game.GameNet.GameData.GetPlayerById(playerId);
+
+                        player.IsImpostor = true;
+                    }
+
+                    break;
+                }
+
+                case 6:
+                {
+                    PlayerInfo.PlayerName = reader.ReadString();
+                    break;
+                }
+
+                default:
+                    break;
+            }
         }
 
         public override bool Serialize(IMessageWriter writer, bool initialState)
@@ -35,7 +63,7 @@ namespace Impostor.Api.Innersloth.Net.Objects
             throw new NotImplementedException();
         }
 
-        public override void Deserialize(IMessageReader reader, bool initialState)
+        public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
         {
             if (initialState)
             {
index d16eaf579b86fe1e94fb8d7a1eb8f55cb44c8a13..78ba1fe6bfbb8e671e80ab9b074808351678ed6f 100644 (file)
@@ -1,7 +1,9 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using Impostor.Api.Games;
 using Impostor.Api.Innersloth.Net.Objects.Systems;
 using Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus;
+using Impostor.Api.Net;
 using Impostor.Api.Net.Messages;
 
 namespace Impostor.Api.Innersloth.Net.Objects
@@ -28,18 +30,44 @@ namespace Impostor.Api.Innersloth.Net.Objects
 
             _systems.Add(SystemTypes.Sabotage, new SabotageSystemType(new[]
             {
-                (IActivatable) _systems[SystemTypes.Comms],
-                (IActivatable) _systems[SystemTypes.Reactor],
-                (IActivatable) _systems[SystemTypes.LifeSupp],
-                (IActivatable) _systems[SystemTypes.Electrical],
+                (IActivatable)_systems[SystemTypes.Comms],
+                (IActivatable)_systems[SystemTypes.Reactor],
+                (IActivatable)_systems[SystemTypes.LifeSupp],
+                (IActivatable)_systems[SystemTypes.Electrical],
             }));
 
             Components.Add(this);
         }
 
-        public override void HandleRpc(byte callId, IMessageReader reader)
+        public override void HandleRpc(IClientPlayer sender, byte callId, IMessageReader reader)
         {
-            throw new System.NotImplementedException();
+            switch (callId)
+            {
+                case 27:
+                {
+                    // Close doors.
+                    if (!sender.Character.PlayerInfo.IsImpostor)
+                    {
+                        Console.WriteLine($"OOPS Fake Impostor: {sender.Character.PlayerInfo.PlayerName} did doors");
+                    }
+
+                    break;
+                }
+
+                case 28:
+                {
+                    var systemType = (SystemTypes)reader.ReadByte();
+                    var player = _game.FindObjectByNetId<InnerPlayerControl>(reader.ReadPackedUInt32());
+                    var amount = reader.ReadByte();
+
+                    if (systemType == SystemTypes.Sabotage && !player.PlayerInfo.IsImpostor)
+                    {
+                        Console.WriteLine($"OOPS Fake Impostor: {player.PlayerInfo.PlayerName} did {(SystemTypes) amount}");
+                    }
+
+                    break;
+                }
+            }
         }
 
         public override bool Serialize(IMessageWriter writer, bool initialState)
@@ -47,7 +75,7 @@ namespace Impostor.Api.Innersloth.Net.Objects
             throw new System.NotImplementedException();
         }
 
-        public override void Deserialize(IMessageReader reader, bool initialState)
+        public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState)
         {
             if (initialState)
             {
@@ -67,7 +95,7 @@ namespace Impostor.Api.Innersloth.Net.Objects
                 foreach (var systemType in SystemTypeHelpers.AllTypes)
                 {
                     // TODO: Not sure what is going on here, check.
-                    if ((count & 1 << (int) (systemType & (SystemTypes.ShipTasks | SystemTypes.Doors))) != 0L)
+                    if ((count & 1 << (int)(systemType & (SystemTypes.ShipTasks | SystemTypes.Doors))) != 0L)
                     {
                         if (_systems.TryGetValue(systemType, out var system))
                         {
index bb28b844efdff5435b8281d7d2e53ce5441887e8..9cd832a95f33113c8d4cb86124db96371d26a32f 100644 (file)
@@ -1,5 +1,6 @@
 using System.Threading.Tasks;
 using Impostor.Api.Games;
+using Impostor.Api.Innersloth.Net.Objects;
 
 namespace Impostor.Api.Net
 {
@@ -23,6 +24,8 @@ namespace Impostor.Api.Net
         /// </summary>
         LimboStates Limbo { get; set; }
 
+        InnerPlayerControl Character { get; set; }
+
         ValueTask KickAsync();
 
         ValueTask BanAsync();
index c0e993eafbe6ce611869084080c632ba95a81542..c03effa92b1d5947d186039594c63f6ca3d7166a 100644 (file)
@@ -1,4 +1,5 @@
 using System.Threading.Tasks;
+using Impostor.Api.Innersloth.Net.Objects;
 using Impostor.Api.Net;
 
 namespace Impostor.Server.Net.State
@@ -19,6 +20,9 @@ namespace Impostor.Server.Net.State
         /// <inheritdoc />
         public LimboStates Limbo { get; set; }
 
+        // TODO: Correct visibility to set internal only.
+        public InnerPlayerControl Character { get; set; }
+
         public bool IsHost => Game?.Host == this;
 
         public string Scene { get; internal set; }
index e59e90e65330b3dec9d97242fb3044ef4cb15950..d54f8b4528a0f0f05c6b9e3474155d334ac2d5c7 100644 (file)
@@ -123,7 +123,7 @@ namespace Impostor.Server.Net.State
                         var netId = reader.ReadPackedUInt32();
                         if (_allObjectsFast.TryGetValue(netId, out var obj))
                         {
-                            obj.Deserialize(reader, false);
+                            obj.Deserialize(sender, reader, false);
                         }
                         else
                         {
@@ -138,8 +138,14 @@ namespace Impostor.Server.Net.State
                         var netId = reader.ReadPackedUInt32();
                         if (_allObjectsFast.TryGetValue(netId, out var obj))
                         {
-                            // Console.WriteLine(reader.ReadByte());
-                            // obj.HandleRpc(reader.ReadByte(), reader);
+                            // TODO: Remove try catch.
+                            try
+                            {
+                                obj.HandleRpc(sender, reader.ReadByte(), reader);
+                            }
+                            catch (NotImplementedException)
+                            {
+                            }
                         }
                         else
                         {
@@ -209,24 +215,12 @@ namespace Impostor.Server.Net.State
                                 var readerSub = reader.ReadMessage();
                                 if (readerSub.Length > 0)
                                 {
-                                    obj.Deserialize(readerSub, true);
+                                    obj.Deserialize(sender, readerSub, true);
                                 }
 
                                 GameNet.OnSpawn(obj);
                             }
 
-                            if ((innerNetObject.SpawnFlags & SpawnFlags.IsClientCharacter) != SpawnFlags.None)
-                            {
-                                if (TryGetPlayer(ownerClientId, out var clientById))
-                                {
-                                    _logger.LogTrace("Spawn character");
-                                }
-                                else
-                                {
-                                    _logger.LogTrace("Spawn unowned character");
-                                }
-                            }
-
                             continue;
                         }
 
@@ -251,7 +245,7 @@ namespace Impostor.Server.Net.State
                             }
 
                             RemoveNetObject(obj);
-                            GameNet.OnSpawn(obj);
+                            GameNet.OnDestroy(obj);
                             _logger.LogDebug("Destroyed InnerNetObject {0} ({1}), OwnerId {2}", obj.GetType().Name, netId, obj.OwnerId);
                         }
                         else
@@ -327,5 +321,16 @@ namespace Impostor.Server.Net.State
 
             obj.NetId = uint.MaxValue;
         }
+
+        public T FindObjectByNetId<T>(uint netId)
+            where T : InnerNetObject
+        {
+            if (_allObjectsFast.TryGetValue(netId, out var obj))
+            {
+                return (T) obj;
+            }
+
+            return null;
+        }
     }
 }
\ No newline at end of file
index 0826ce872b810705eefbef0fcb7235933033003b..b228fec9dacbbdcfc3e95f58b89d33d2e1de5a55 100644 (file)
@@ -51,7 +51,7 @@ namespace Impostor.Server.Net.State
             Code = code;
             HostId = -1;
             GameState = GameStates.NotStarted;
-            GameNet = new GameNet();
+            GameNet = new GameNet(this);
             Options = options;
             _clientManager = clientManager;
             _eventManager = eventManager;
@@ -92,6 +92,11 @@ namespace Impostor.Server.Net.State
             return false;
         }
 
+        public IClientPlayer GetClientPlayer(int clientId)
+        {
+            return _players.TryGetValue(clientId, out var clientPlayer) ? clientPlayer : null;
+        }
+
         public ValueTask EndAsync()
         {
             return _gameManager.RemoveAsync(Code);