From a5cf97e85a5c7b3a7f71181b3a9fe434b83f4042 Mon Sep 17 00:00:00 2001 From: AeonLucid Date: Fri, 23 Oct 2020 23:42:59 +0200 Subject: [PATCH] Almost all RPC calls --- .../Innersloth/Net/InnerNetObject.cs | 3 +- .../Components/InnerCustomNetworkTransform.cs | 2 +- .../Objects/Components/InnerPlayerPhysics.cs | 44 +++++- .../Objects/Components/InnerVoteBanSystem.cs | 29 +++- .../Net/Objects/InnerGameData.PlayerInfo.cs | 4 +- .../Net/Objects/InnerGameData.TaskInfo.cs | 4 +- .../Innersloth/Net/Objects/InnerGameData.cs | 140 +++++++++++++----- .../Net/Objects/InnerLobbyBehaviour.cs | 3 +- .../Innersloth/Net/Objects/InnerMeetingHud.cs | 74 ++++++++- .../Net/Objects/InnerPlayerControl.cs | 12 +- .../Innersloth/Net/Objects/InnerShipStatus.cs | 14 +- src/Impostor.Api/ProjectRules.ruleset | 2 + src/Impostor.Server/Net/State/Game.Data.cs | 23 ++- 13 files changed, 278 insertions(+), 76 deletions(-) diff --git a/src/Impostor.Api/Innersloth/Net/InnerNetObject.cs b/src/Impostor.Api/Innersloth/Net/InnerNetObject.cs index dc34587..d9912a8 100644 --- a/src/Impostor.Api/Innersloth/Net/InnerNetObject.cs +++ b/src/Impostor.Api/Innersloth/Net/InnerNetObject.cs @@ -11,8 +11,7 @@ namespace Impostor.Api.Innersloth.Net public SpawnFlags SpawnFlags { get; internal set; } - public abstract void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, - IMessageReader reader); + public abstract void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader); public abstract bool Serialize(IMessageWriter writer, bool initialState); diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerCustomNetworkTransform.cs b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerCustomNetworkTransform.cs index 8270e32..40fc96f 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerCustomNetworkTransform.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerCustomNetworkTransform.cs @@ -52,7 +52,7 @@ namespace Impostor.Api.Innersloth.Net.Objects.Components } else { - _logger.LogWarning("InnerCustomNetworkTransform: Unknown rpc call {0}", call); + _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerCustomNetworkTransform), call); } } diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerPlayerPhysics.cs b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerPlayerPhysics.cs index 7128138..a0bff8d 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerPlayerPhysics.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerPlayerPhysics.cs @@ -1,24 +1,56 @@ -using Impostor.Api.Net; +using System; +using Impostor.Api.Net; using Impostor.Api.Net.Messages; +using Microsoft.Extensions.Logging; namespace Impostor.Api.Innersloth.Net.Objects.Components { public class InnerPlayerPhysics : InnerNetObject { - public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, - IMessageReader reader) + private readonly ILogger _logger; + + public InnerPlayerPhysics(ILogger logger) { - throw new System.NotImplementedException(); + _logger = logger; + } + + public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader) + { + if (call != RpcCalls.EnterVent && call != RpcCalls.ExitVent) + { + _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerPlayerPhysics), call); + return; + } + + if (!sender.IsOwner(this)) + { + throw new ImpostorCheatException($"Client sent {call} to an unowned {nameof(InnerPlayerControl)}."); + } + + if (target != null) + { + throw new ImpostorCheatException($"Client sent {call} to a specific player instead of broadcast."); + } + + if (!sender.Character.PlayerInfo.IsImpostor) + { + throw new ImpostorCheatException($"Client sent {call} as crewmate."); + } + + var ventId = reader.ReadPackedUInt32(); + var ventEnter = call == RpcCalls.EnterVent; + + // TODO: Do stuff. } public override bool Serialize(IMessageWriter writer, bool initialState) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } public override void Deserialize(IClientPlayer sender, IMessageReader reader, bool initialState) { - throw new System.NotImplementedException(); + throw new NotImplementedException(); } } } \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerVoteBanSystem.cs b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerVoteBanSystem.cs index a9590df..1e43cd5 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerVoteBanSystem.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerVoteBanSystem.cs @@ -2,22 +2,43 @@ using System.Collections.Generic; using Impostor.Api.Net; using Impostor.Api.Net.Messages; +using Microsoft.Extensions.Logging; namespace Impostor.Api.Innersloth.Net.Objects.Components { public class InnerVoteBanSystem : InnerNetObject { + private readonly ILogger _logger; private readonly Dictionary _votes; - public InnerVoteBanSystem() + public InnerVoteBanSystem(ILogger logger) { + _logger = logger; _votes = new Dictionary(); } - public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, - IMessageReader reader) + public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader) { - throw new NotImplementedException(); + if (call != RpcCalls.AddVote) + { + _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerVoteBanSystem), call); + return; + } + + var clientId = reader.ReadInt32(); + if (clientId != sender.Client.Id) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.AddVote)} as other client."); + } + + if (target != null) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CastVote)} to wrong destinition, must be broadcast."); + } + + var targetClientId = reader.ReadInt32(); + + // TODO: Use. } public override bool Serialize(IMessageWriter writer, bool initialState) diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.PlayerInfo.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.PlayerInfo.cs index 3cc8a83..7ddd8a3 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.PlayerInfo.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.PlayerInfo.cs @@ -14,6 +14,8 @@ namespace Impostor.Api.Innersloth.Net.Objects PlayerId = playerId; } + public InnerPlayerControl Controller { get; internal set; } + public byte PlayerId { get; } public string PlayerName { get; internal set; } @@ -34,7 +36,7 @@ namespace Impostor.Api.Innersloth.Net.Objects public DeathReason LastDeathReason { get; internal set; } - public List Tasks { get; private set; } + public List Tasks { get; internal set; } public void Serialize(IMessageWriter writer) { diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.TaskInfo.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.TaskInfo.cs index d1ef9f2..cdca500 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.TaskInfo.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.TaskInfo.cs @@ -6,9 +6,9 @@ namespace Impostor.Api.Innersloth.Net.Objects { public class TaskInfo { - public uint Id { get; private set; } + public uint Id { get; internal set; } - public bool Complete { get; private set; } + public bool Complete { get; internal set; } public void Serialize(IMessageWriter writer) { diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.cs index e7fafab..2a4a3a8 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.cs @@ -5,38 +5,31 @@ using Impostor.Api.Games; using Impostor.Api.Innersloth.Net.Objects.Components; using Impostor.Api.Net; using Impostor.Api.Net.Messages; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; namespace Impostor.Api.Innersloth.Net.Objects { public partial class InnerGameData : InnerNetObject { + private readonly ILogger _logger; private readonly IGame _game; private readonly ConcurrentDictionary _allPlayers; - public InnerGameData(IGame game) + public InnerGameData(ILogger logger, IGame game, IServiceProvider serviceProvider) { + _logger = logger; _game = game; _allPlayers = new ConcurrentDictionary(); Components.Add(this); - Components.Add(new InnerVoteBanSystem()); + Components.Add(ActivatorUtilities.CreateInstance(serviceProvider)); } public int PlayerCount => _allPlayers.Count; public IReadOnlyDictionary Players => _allPlayers; - internal void AddPlayer(InnerPlayerControl control) - { - var playerId = control.PlayerId; - var playerInfo = new PlayerInfo(control.PlayerId); - - if (_allPlayers.TryAdd(playerId, playerInfo)) - { - control.PlayerInfo = playerInfo; - } - } - public PlayerInfo? GetPlayerById(byte id) { if (id == byte.MaxValue) @@ -49,7 +42,69 @@ namespace Impostor.Api.Innersloth.Net.Objects public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader) { - throw new NotImplementedException(); + switch (call) + { + case RpcCalls.SetTasks: + { + if (!sender.IsHost) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetTasks)} but was not a host."); + } + + if (target != null) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetTasks)} to a specific player instead of broadcast."); + } + + var playerId = reader.ReadByte(); + var taskTypeIds = reader.ReadBytesAndSize(); + + SetTasks(playerId, taskTypeIds); + break; + } + + case RpcCalls.UpdateGameData: + { + if (!sender.IsHost) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetTasks)} but was not a host."); + } + + if (target != null) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.SetTasks)} to a specific player instead of broadcast."); + } + + while (reader.Position < reader.Length) + { + var message = reader.ReadMessage(); + var player = GetPlayerById(message.Tag); + if (player != null) + { + player.Deserialize(message); + } + else + { + var playerInfo = new PlayerInfo(message.Tag); + + playerInfo.Deserialize(reader); + + if (!_allPlayers.TryAdd(playerInfo.PlayerId, playerInfo)) + { + throw new ImpostorException("Failed to add player to InnerGameData."); + } + } + } + + break; + } + + default: + { + _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerGameData), call); + break; + } + } } public override bool Serialize(IMessageWriter writer, bool initialState) @@ -65,7 +120,8 @@ namespace Impostor.Api.Innersloth.Net.Objects for (var i = 0; i < num; i++) { - var playerInfo = new PlayerInfo(reader.ReadByte()); + var playerId = reader.ReadByte(); + var playerInfo = new PlayerInfo(playerId); playerInfo.Deserialize(reader); @@ -77,25 +133,41 @@ namespace Impostor.Api.Innersloth.Net.Objects } else { - throw new NotImplementedException("This shouldn't happen, according to Among Us disassembly.."); - - // var num = reader.ReadByte(); - // - // for (var i = 0; i < num; i++) - // { - // var id = reader.ReadByte(); - // var player = GetPlayerById(id); - // if (player != null) - // { - // player.Deserialize(reader); - // } - // else - // { - // var playerInfo = new PlayerInfo(id); - // playerInfo.Deserialize(reader); - // _allPlayers.Add(playerInfo); - // } - // } + throw new NotImplementedException("This shouldn't happen, according to Among Us disassembly."); + } + } + + internal void AddPlayer(InnerPlayerControl control) + { + var playerId = control.PlayerId; + var playerInfo = new PlayerInfo(control.PlayerId); + + if (_allPlayers.TryAdd(playerId, playerInfo)) + { + control.PlayerInfo = playerInfo; + } + } + + private void SetTasks(byte playerId, ReadOnlyMemory taskTypeIds) + { + var player = GetPlayerById(playerId); + if (player == null) + { + _logger.LogTrace("Could not set tasks for playerId {0}.", playerId); + return; + } + + if (player.Disconnected) + { + return; + } + + player.Tasks = new List(taskTypeIds.Length); + + for (var i = 0; i < taskTypeIds.Length; i++) + { + player.Tasks.Add(new TaskInfo()); + player.Tasks[i].Id = (uint)i; } } } diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerLobbyBehaviour.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerLobbyBehaviour.cs index e0661f8..78bebd4 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/InnerLobbyBehaviour.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerLobbyBehaviour.cs @@ -15,8 +15,7 @@ namespace Impostor.Api.Innersloth.Net.Objects Components.Add(this); } - public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, - IMessageReader reader) + public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader) { throw new System.NotImplementedException(); } diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.cs index 19e636e..d742dc1 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.cs @@ -4,17 +4,20 @@ using Impostor.Api.Games; using Impostor.Api.Innersloth.Data; using Impostor.Api.Net; using Impostor.Api.Net.Messages; +using Microsoft.Extensions.Logging; namespace Impostor.Api.Innersloth.Net.Objects { public partial class InnerMeetingHud : InnerNetObject { + private readonly ILogger _logger; private readonly IGame _game; private readonly IGameNet _gameNet; private PlayerVoteArea[] _playerStates; - public InnerMeetingHud(IGame game) + public InnerMeetingHud(ILogger logger, IGame game) { + _logger = logger; _game = game; _gameNet = game.GameNet; _playerStates = null; @@ -36,10 +39,73 @@ namespace Impostor.Api.Innersloth.Net.Objects .ToArray(); } - public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, - IMessageReader reader) + public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader) { - throw new NotImplementedException(); + switch (call) + { + case RpcCalls.Close: + { + if (!sender.IsHost) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.Close)} but was not a host."); + } + + if (target != null) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.Close)} to a specific player instead of broadcast."); + } + + break; + } + + case RpcCalls.VotingComplete: + { + if (!sender.IsHost) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.VotingComplete)} but was not a host."); + } + + if (target != null) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.VotingComplete)} to a specific player instead of broadcast."); + } + + var states = reader.ReadBytesAndSize(); + var playerId = reader.ReadByte(); + var tie = reader.ReadBoolean(); + break; + } + + case RpcCalls.CastVote: + { + var srcPlayerId = reader.ReadByte(); + if (srcPlayerId != sender.Character.PlayerId) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CastVote)} to an unowned {nameof(InnerPlayerControl)}."); + } + + // Host broadcasts vote to others. + if (sender.IsHost && target != null) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CastVote)} to a specific player instead of broadcast."); + } + + // Player sends vote to host. + if (target == null || !target.IsHost) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CastVote)} to wrong destinition, must be host."); + } + + var targetPlayerId = reader.ReadByte(); + break; + } + + default: + { + _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerMeetingHud), call); + break; + } + } } public override bool Serialize(IMessageWriter writer, bool initialState) diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerPlayerControl.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerPlayerControl.cs index 998fc4f..018fbc0 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/InnerPlayerControl.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerPlayerControl.cs @@ -51,6 +51,11 @@ namespace Impostor.Api.Innersloth.Net.Objects throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CompleteTask)} to an unowned {nameof(InnerPlayerControl)}."); } + if (target != null) + { + throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.CompleteTask)} to a specific player instead of broadcast."); + } + var index = reader.ReadPackedUInt32(); break; } @@ -231,7 +236,7 @@ namespace Impostor.Api.Innersloth.Net.Objects if (!sender.Character.PlayerInfo.IsImpostor) { // TODO: Uncomment - // throw new ImpostorHackException($"Client sent {nameof(RpcCalls.MurderPlayer)} as crewmate."); + // throw new ImpostorCheatException($"Client sent {nameof(RpcCalls.MurderPlayer)} as crewmate."); } var player = reader.ReadNetObject(_game); @@ -270,7 +275,6 @@ namespace Impostor.Api.Innersloth.Net.Objects var player = _game.GameNet.GameData.GetPlayerById(playerId); // Meeting started by "player", can also be null. - Console.WriteLine("ads"); break; } @@ -346,8 +350,10 @@ namespace Impostor.Api.Innersloth.Net.Objects } default: - _logger.LogWarning("InnerPlayerControl: Unknown rpc call {0}", call); + { + _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerPlayerControl), call); break; + } } } diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerShipStatus.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerShipStatus.cs index 1992552..f3960d9 100644 --- a/src/Impostor.Api/Innersloth/Net/Objects/InnerShipStatus.cs +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerShipStatus.cs @@ -5,16 +5,19 @@ using Impostor.Api.Innersloth.Net.Objects.Systems; using Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus; using Impostor.Api.Net; using Impostor.Api.Net.Messages; +using Microsoft.Extensions.Logging; namespace Impostor.Api.Innersloth.Net.Objects { public class InnerShipStatus : InnerNetObject { + private readonly ILogger _logger; private readonly IGame _game; private readonly Dictionary _systems; - public InnerShipStatus(IGame game) + public InnerShipStatus(ILogger logger, IGame game) { + _logger = logger; _game = game; _systems = new Dictionary @@ -39,8 +42,7 @@ namespace Impostor.Api.Innersloth.Net.Objects Components.Add(this); } - public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, - IMessageReader reader) + public override void HandleRpc(IClientPlayer sender, IClientPlayer? target, RpcCalls call, IMessageReader reader) { switch (call) { @@ -67,6 +69,12 @@ namespace Impostor.Api.Innersloth.Net.Objects break; } + + default: + { + _logger.LogWarning("{0}: Unknown rpc call {1}", nameof(InnerShipStatus), call); + break; + } } } diff --git a/src/Impostor.Api/ProjectRules.ruleset b/src/Impostor.Api/ProjectRules.ruleset index a380f5c..4ba23c2 100644 --- a/src/Impostor.Api/ProjectRules.ruleset +++ b/src/Impostor.Api/ProjectRules.ruleset @@ -4,6 +4,8 @@ + + diff --git a/src/Impostor.Server/Net/State/Game.Data.cs b/src/Impostor.Server/Net/State/Game.Data.cs index d502d96..ce1e37d 100644 --- a/src/Impostor.Server/Net/State/Game.Data.cs +++ b/src/Impostor.Server/Net/State/Game.Data.cs @@ -1,15 +1,12 @@ using System; using System.Collections.Generic; -using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; -using Impostor.Api; using Impostor.Api.Innersloth.Data; using Impostor.Api.Innersloth.Net; using Impostor.Api.Innersloth.Net.Objects; using Impostor.Api.Innersloth.Net.Objects.Components; using Impostor.Api.Net.Messages; -using Impostor.Api.Net.Messages.C2S; using Impostor.Api.Net.Messages.S2C; using Impostor.Hazel; using Microsoft.Extensions.DependencyInjection; @@ -50,7 +47,7 @@ namespace Impostor.Server.Net.State private int _gamedataInitialized; private bool _gamedataFakeReceived; - internal void OnSpawn(InnerNetObject netObj) + private void OnSpawn(InnerNetObject netObj) { switch (netObj) { @@ -87,19 +84,24 @@ namespace Impostor.Server.Net.State } // Hook up InnerPlayerControl <-> InnerPlayerControl.PlayerInfo. - control.PlayerInfo = GameNet.GameData.GetPlayerById(control.PlayerId); + control.PlayerInfo = GameNet.GameData.GetPlayerById(control.PlayerId)!; if (control.PlayerInfo == null) { GameNet.GameData.AddPlayer(control); } + if (control.PlayerInfo != null) + { + control.PlayerInfo!.Controller = control; + } + break; } } } - internal void OnDestroy(InnerNetObject netObj) + private void OnDestroy(InnerNetObject netObj) { switch (netObj) { @@ -228,14 +230,7 @@ namespace Impostor.Server.Net.State var netId = reader.ReadPackedUInt32(); if (_allObjectsFast.TryGetValue(netId, out var obj)) { - // TODO: Remove try catch. - try - { - obj.HandleRpc(sender, target, (RpcCalls) reader.ReadByte(), reader); - } - catch (NotImplementedException) - { - } + obj.HandleRpc(sender, target, (RpcCalls) reader.ReadByte(), reader); } else { -- 2.39.5