From: AeonLucid Date: Fri, 23 Oct 2020 03:38:32 +0000 (+0200) Subject: Implement deserialization for most GameData objects X-Git-Tag: v1.2.2~96^2~44 X-Git-Url: https://git.deb.at/?a=commitdiff_plain;h=be5a876113d8ff4af066e3874417af85ebf97b9c;p=rhonda%2Fimpostor.git Implement deserialization for most GameData objects --- diff --git a/src/Impostor.Api/Extensions/SpanReaderExtensions.cs b/src/Impostor.Api/Extensions/SpanReaderExtensions.cs index 97365ac..c103ee7 100644 --- a/src/Impostor.Api/Extensions/SpanReaderExtensions.cs +++ b/src/Impostor.Api/Extensions/SpanReaderExtensions.cs @@ -2,7 +2,7 @@ using System.Buffers.Binary; using System.Runtime.CompilerServices; -namespace Impostor.Api.Extensions +namespace Impostor.Api { /// /// Priovides a StreamReader-like api throught extensions diff --git a/src/Impostor.Api/Games/IGame.cs b/src/Impostor.Api/Games/IGame.cs index 17fa2b8..5dbec19 100644 --- a/src/Impostor.Api/Games/IGame.cs +++ b/src/Impostor.Api/Games/IGame.cs @@ -16,6 +16,8 @@ namespace Impostor.Api.Games GameStates GameState { get; } + GameNet GameNet { get; } + IEnumerable Players { get; } IPEndPoint PublicIp { get; } diff --git a/src/Impostor.Api/Innersloth/Data/GameNet.cs b/src/Impostor.Api/Innersloth/Data/GameNet.cs new file mode 100644 index 0000000..2d37879 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Data/GameNet.cs @@ -0,0 +1,29 @@ +using Impostor.Api.Innersloth.Net; +using Impostor.Api.Innersloth.Net.Objects; + +namespace Impostor.Api.Innersloth.Data +{ + /// + /// Holds all data that is serialized over the network through GameData packets. + /// + public class GameNet + { + public InnerGameData GameData { get; internal set; } + + internal void OnSpawn(InnerNetObject netObj) + { + if (netObj is InnerGameData data) + { + GameData = data; + } + } + + internal void OnDestroy(InnerNetObject netObj) + { + if (netObj is InnerGameData) + { + GameData = null; + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Data/MapId.cs b/src/Impostor.Api/Innersloth/Data/MapId.cs new file mode 100644 index 0000000..97d79d4 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Data/MapId.cs @@ -0,0 +1,10 @@ +namespace Impostor.Api.Innersloth.Data +{ + public static class MapId + { + // TODO: Not sure if correct, check + public const int Skeld = 0; + public const int MiraHQ = 1; + public const int Polus = 2; + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/GameOptionsData.cs b/src/Impostor.Api/Innersloth/GameOptionsData.cs index e420e53..41bebff 100644 --- a/src/Impostor.Api/Innersloth/GameOptionsData.cs +++ b/src/Impostor.Api/Innersloth/GameOptionsData.cs @@ -1,5 +1,4 @@ -using Impostor.Api.Extensions; -using Impostor.Api.Innersloth.Data; +using Impostor.Api.Innersloth.Data; using System; using System.IO; diff --git a/src/Impostor.Api/Innersloth/Net/GameObject.cs b/src/Impostor.Api/Innersloth/Net/GameObject.cs new file mode 100644 index 0000000..c58e4fb --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/GameObject.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; + +namespace Impostor.Api.Innersloth.Net +{ + public class GameObject + { + public GameObject() + { + Components = new List(); + } + + protected List Components { get; } + + public List GetComponentsInChildren() + { + var result = new List(); + + foreach (var component in Components) + { + if (component is T c) + { + result.Add(c); + } + } + + return result; + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/InnerNetObject.cs b/src/Impostor.Api/Innersloth/Net/InnerNetObject.cs new file mode 100644 index 0000000..6e112f3 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/InnerNetObject.cs @@ -0,0 +1,19 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net +{ + public abstract class InnerNetObject : GameObject + { + public uint NetId { get; internal set; } + + public int OwnerId { get; internal set; } + + public SpawnFlags SpawnFlags { get; internal set; } + + public abstract void HandleRpc(byte callId, IMessageReader reader); + + public abstract bool Serialize(IMessageWriter writer, bool initialState); + + public abstract void Deserialize(IMessageReader reader, bool initialState); + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerCustomNetworkTransform.cs b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerCustomNetworkTransform.cs new file mode 100644 index 0000000..a8c4915 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerCustomNetworkTransform.cs @@ -0,0 +1,112 @@ +using System.Numerics; +using Impostor.Api.Net.Messages; +using Microsoft.Extensions.Logging; + +namespace Impostor.Api.Innersloth.Net.Objects.Components +{ + public class InnerCustomNetworkTransform : InnerNetObject + { + private static readonly FloatRange XRange = new FloatRange(-40f, 40f); + private static readonly FloatRange YRange = new FloatRange(-40f, 40f); + + private readonly ILogger _logger; + + private ushort _lastSequenceId; + private Vector2 _targetSyncPosition; + private Vector2 _targetSyncVelocity; + + public InnerCustomNetworkTransform(ILogger logger) + { + _logger = logger; + } + + private static bool SidGreaterThan(ushort newSid, ushort prevSid) + { + var num = (ushort)(prevSid + (uint) short.MaxValue); + + return (int) prevSid < (int) num + ? newSid > prevSid && newSid <= num + : newSid > prevSid || newSid <= num; + } + + private static void WriteVector2(IMessageWriter writer, Vector2 vec) + { + writer.Write((ushort)(XRange.ReverseLerp(vec.X) * (double) ushort.MaxValue)); + writer.Write((ushort)(YRange.ReverseLerp(vec.Y) * (double) ushort.MaxValue)); + } + + private static Vector2 ReadVector2(IMessageReader reader) + { + var v1 = reader.ReadUInt16() / (float) ushort.MaxValue; + var v2 = reader.ReadUInt16() / (float) ushort.MaxValue; + + return new Vector2(XRange.Lerp(v1), YRange.Lerp(v2)); + } + + public override void HandleRpc(byte callId, IMessageReader reader) + { + if (callId == 0) + { + SnapTo(ReadVector2(reader), reader.ReadUInt16()); + } + else + { + _logger.LogWarning("InnerCustomNetworkTransform: Unknown rpc call {0}", callId); + } + } + + public override bool Serialize(IMessageWriter writer, bool initialState) + { + if (initialState) + { + writer.Write(_lastSequenceId); + WriteVector2(writer, _targetSyncPosition); + WriteVector2(writer, _targetSyncVelocity); + return true; + } + + // TODO: DirtyBits == 0 return false. + _lastSequenceId++; + + writer.Write(_lastSequenceId); + WriteVector2(writer, _targetSyncPosition); + WriteVector2(writer, _targetSyncVelocity); + return true; + } + + public override void Deserialize(IMessageReader reader, bool initialState) + { + var sequenceId = reader.ReadUInt16(); + + if (initialState) + { + _lastSequenceId = sequenceId; + _targetSyncPosition = ReadVector2(reader); + _targetSyncVelocity = ReadVector2(reader); + } + else + { + if (!SidGreaterThan(sequenceId, _lastSequenceId)) + { + return; + } + + _lastSequenceId = sequenceId; + _targetSyncPosition = ReadVector2(reader); + _targetSyncVelocity = ReadVector2(reader); + } + } + + private void SnapTo(Vector2 position, ushort minSid) + { + if (SidGreaterThan(minSid, _lastSequenceId)) + { + return; + } + + _lastSequenceId = minSid; + _targetSyncPosition = position; + _targetSyncVelocity = Vector2.Zero; + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerPlayerPhysics.cs b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerPlayerPhysics.cs new file mode 100644 index 0000000..7c74aaf --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerPlayerPhysics.cs @@ -0,0 +1,22 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Components +{ + public class InnerPlayerPhysics : InnerNetObject + { + public override void HandleRpc(byte callId, IMessageReader reader) + { + throw new System.NotImplementedException(); + } + + public override bool Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public override void Deserialize(IMessageReader reader, bool initialState) + { + throw new System.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 new file mode 100644 index 0000000..ed5f29a --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Components/InnerVoteBanSystem.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Components +{ + public class InnerVoteBanSystem : InnerNetObject + { + private readonly Dictionary _votes; + + public InnerVoteBanSystem() + { + _votes = new Dictionary(); + } + + public override void HandleRpc(byte callId, IMessageReader reader) + { + throw new NotImplementedException(); + } + + public override bool Serialize(IMessageWriter writer, bool initialState) + { + throw new NotImplementedException(); + } + + public override void Deserialize(IMessageReader reader, bool initialState) + { + var votes = _votes; + var unknown = reader.ReadByte(); + if (unknown != 0) + { + for (var i = 0; i < unknown; i++) + { + var v4 = reader.ReadInt32(); + if (v4 == 0) + { + break; + } + + if (!votes.TryGetValue(v4, out var v12)) + { + v12 = new int[3]; + votes[v4] = v12; + } + + for (var j = 0; j < 3; j++) + { + v12[j] = reader.ReadPackedInt32(); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.PlayerInfo.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.PlayerInfo.cs new file mode 100644 index 0000000..b076d9e --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.PlayerInfo.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects +{ + public partial class InnerGameData + { + public class PlayerInfo + { + public PlayerInfo(byte playerId) + { + PlayerId = playerId; + } + + public byte PlayerId { get; } + + public string PlayerName { get; private set; } + + public byte ColorId { get; private set; } + + public uint HatId { get; private set; } + + public uint PetId { get; private set; } + + public uint SkinId { get; private set; } + + public bool Disconnected { get; private set; } + + public bool IsImpostor { get; private set; } + + public bool IsDead { get; private set; } + + public List Tasks { get; private set; } + + public void Serialize(IMessageWriter writer) + { + throw new NotImplementedException(); + } + + public void Deserialize(IMessageReader reader) + { + PlayerName = reader.ReadString(); + ColorId = reader.ReadByte(); + HatId = reader.ReadPackedUInt32(); + PetId = reader.ReadPackedUInt32(); + SkinId = reader.ReadPackedUInt32(); + var flag = reader.ReadByte(); + Disconnected = (flag & 1) > 0; + IsImpostor = (flag & 2) > 0; + IsDead = (flag & 4) > 0; + var taskCount = reader.ReadByte(); + Tasks = new List(); + for (var i = 0; i < taskCount; i++) + { + Tasks.Add(new TaskInfo()); + Tasks[i].Deserialize(reader); + } + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.TaskInfo.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.TaskInfo.cs new file mode 100644 index 0000000..d1ef9f2 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.TaskInfo.cs @@ -0,0 +1,26 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects +{ + public partial class InnerGameData + { + public class TaskInfo + { + public uint Id { get; private set; } + + public bool Complete { get; private set; } + + public void Serialize(IMessageWriter writer) + { + writer.WritePacked(Id); + writer.Write(Complete); + } + + public void Deserialize(IMessageReader reader) + { + this.Id = reader.ReadPackedUInt32(); + this.Complete = reader.ReadBoolean(); + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.cs new file mode 100644 index 0000000..5d07e10 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerGameData.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using Impostor.Api.Games; +using Impostor.Api.Innersloth.Net.Objects.Components; +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects +{ + public partial class InnerGameData : InnerNetObject + { + private readonly IGame _game; + private readonly List _allPlayers; + + public InnerGameData(IGame game) + { + _game = game; + _allPlayers = new List(); + + Components.Add(this); + Components.Add(new InnerVoteBanSystem()); + } + + public int PlayerCount => _allPlayers.Count; + + public IReadOnlyList Players => _allPlayers; + + public PlayerInfo GetPlayerById(byte id) + { + foreach (var player in _allPlayers) + { + if (player.PlayerId == id) + { + return player; + } + } + + return null; + } + + public override void HandleRpc(byte callId, IMessageReader reader) + { + throw new NotImplementedException(); + } + + public override bool Serialize(IMessageWriter writer, bool initialState) + { + throw new NotImplementedException(); + } + + public override void Deserialize(IMessageReader reader, bool initialState) + { + if (initialState) + { + var num = reader.ReadPackedInt32(); + + for (var i = 0; i < num; i++) + { + var playerInfo = new PlayerInfo(reader.ReadByte()); + playerInfo.Deserialize(reader); + _allPlayers.Add(playerInfo); + } + } + 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); + // } + // } + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerLobbyBehaviour.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerLobbyBehaviour.cs new file mode 100644 index 0000000..7b73ed2 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerLobbyBehaviour.cs @@ -0,0 +1,32 @@ +using Impostor.Api.Games; +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects +{ + public class InnerLobbyBehaviour : InnerNetObject + { + private readonly IGame _game; + + public InnerLobbyBehaviour(IGame game) + { + _game = game; + + Components.Add(this); + } + + public override void HandleRpc(byte callId, IMessageReader reader) + { + throw new System.NotImplementedException(); + } + + public override bool Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public override void Deserialize(IMessageReader reader, bool initialState) + { + throw new System.NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.PlayerVoteArea.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.PlayerVoteArea.cs new file mode 100644 index 0000000..82f0ef6 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.PlayerVoteArea.cs @@ -0,0 +1,49 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects +{ + public partial class InnerMeetingHud + { + public class PlayerVoteArea + { + private const byte VoteMask = 15; + private const byte ReportedBit = 32; + private const byte VotedBit = 64; + private const byte DeadBit = 128; + + public PlayerVoteArea(InnerMeetingHud parent, byte targetPlayerId) + { + Parent = parent; + TargetPlayerId = targetPlayerId; + } + + public InnerMeetingHud Parent { get; } + + public byte TargetPlayerId { get; } + + public bool IsDead { get; private set; } + + public bool DidVote { get; private set; } + + public bool DidReport { get; private set; } + + public sbyte VotedFor { get; private set; } + + internal void SetDead(bool didReport, bool isDead) + { + DidReport = didReport; + IsDead = isDead; + } + + public void Deserialize(IMessageReader reader) + { + var num = reader.ReadByte(); + + VotedFor = (sbyte)((num & VoteMask) - 1); + IsDead = (num & DeadBit) > 0; + DidVote = (num & VotedBit) > 0; + DidReport = (num & ReportedBit) > 0; + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.cs new file mode 100644 index 0000000..816fe6f --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerMeetingHud.cs @@ -0,0 +1,78 @@ +using System; +using Impostor.Api.Games; +using Impostor.Api.Innersloth.Data; +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects +{ + public partial class InnerMeetingHud : InnerNetObject + { + private readonly IGame _game; + private readonly GameNet _gameNet; + private PlayerVoteArea[] _playerStates; + + public InnerMeetingHud(IGame game) + { + _game = game; + _gameNet = game.GameNet; + _playerStates = null; + + Components.Add(this); + } + + public byte ReporterId { get; private set; } + + 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); + } + } + + public override void HandleRpc(byte callId, IMessageReader reader) + { + throw new NotImplementedException(); + } + + public override bool Serialize(IMessageWriter writer, bool initialState) + { + throw new NotImplementedException(); + } + + public override void Deserialize(IMessageReader reader, bool initialState) + { + if (initialState) + { + PopulateButtons(0); + + foreach (var playerState in _playerStates) + { + playerState.Deserialize(reader); + + if (playerState.DidReport) + { + ReporterId = playerState.TargetPlayerId; + } + } + } + else + { + var num = reader.ReadPackedUInt32(); + + for (var i = 0; i < _playerStates.Length; i++) + { + if ((num & 1 << i) != 0) + { + _playerStates[i].Deserialize(reader); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerPlayerControl.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerPlayerControl.cs new file mode 100644 index 0000000..fd9a609 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerPlayerControl.cs @@ -0,0 +1,48 @@ +using System; +using Impostor.Api.Games; +using Impostor.Api.Innersloth.Net.Objects.Components; +using Impostor.Api.Net.Messages; +using Microsoft.Extensions.DependencyInjection; + +namespace Impostor.Api.Innersloth.Net.Objects +{ + public class InnerPlayerControl : InnerNetObject + { + private readonly IGame _game; + + public InnerPlayerControl(IGame game, IServiceProvider serviceProvider) + { + _game = game; + + Components.Add(this); + Components.Add(ActivatorUtilities.CreateInstance(serviceProvider)); + Components.Add(ActivatorUtilities.CreateInstance(serviceProvider)); + + PlayerId = byte.MaxValue; + } + + public bool IsNew { get; private set; } + + public byte PlayerId { get; private set; } + + public override void HandleRpc(byte callId, IMessageReader reader) + { + throw new NotImplementedException(); + } + + public override bool Serialize(IMessageWriter writer, bool initialState) + { + throw new NotImplementedException(); + } + + public override void Deserialize(IMessageReader reader, bool initialState) + { + if (initialState) + { + IsNew = reader.ReadBoolean(); + } + + PlayerId = reader.ReadByte(); + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/InnerShipStatus.cs b/src/Impostor.Api/Innersloth/Net/Objects/InnerShipStatus.cs new file mode 100644 index 0000000..d16eaf5 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/InnerShipStatus.cs @@ -0,0 +1,81 @@ +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.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects +{ + public class InnerShipStatus : InnerNetObject + { + private readonly IGame _game; + private readonly Dictionary _systems; + + public InnerShipStatus(IGame game) + { + _game = game; + + _systems = new Dictionary + { + [SystemTypes.Electrical] = new SwitchSystem(), + [SystemTypes.MedBay] = new MedScanSystem(), + [SystemTypes.Reactor] = new ReactorSystemType(), + [SystemTypes.LifeSupp] = new LifeSuppSystemType(), + [SystemTypes.Security] = new SecurityCameraSystemType(), + [SystemTypes.Comms] = new HudOverrideSystemType(), + [SystemTypes.Doors] = new DoorsSystemType(_game), + }; + + _systems.Add(SystemTypes.Sabotage, new SabotageSystemType(new[] + { + (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) + { + throw new System.NotImplementedException(); + } + + public override bool Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public override void Deserialize(IMessageReader reader, bool initialState) + { + if (initialState) + { + // TODO: (_systems[SystemTypes.Doors] as DoorsSystemType).SetDoors(); + foreach (var systemType in SystemTypeHelpers.AllTypes) + { + if (_systems.TryGetValue(systemType, out var system)) + { + system.Deserialize(reader, true); + } + } + } + else + { + var count = reader.ReadPackedUInt32(); + + 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 (_systems.TryGetValue(systemType, out var system)) + { + system.Deserialize(reader, false); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/IActivatable.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/IActivatable.cs new file mode 100644 index 0000000..eaae0a2 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/IActivatable.cs @@ -0,0 +1,7 @@ +namespace Impostor.Api.Innersloth.Net.Objects.Systems +{ + public interface IActivatable + { + bool IsActive { get; } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/ISystemType.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ISystemType.cs new file mode 100644 index 0000000..0b25e94 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ISystemType.cs @@ -0,0 +1,11 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems +{ + public interface ISystemType + { + void Serialize(IMessageWriter writer, bool initialState); + + void Deserialize(IMessageReader reader, bool initialState); + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/DoorsSystemType.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/DoorsSystemType.cs new file mode 100644 index 0000000..05a2916 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/DoorsSystemType.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using Impostor.Api.Games; +using Impostor.Api.Innersloth.Data; +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus +{ + public class DoorsSystemType : ISystemType + { + // TODO: AutoDoors + private readonly Dictionary _doors; + + public DoorsSystemType(IGame game) + { + // TODO: Check + var doorCount = game.Options.MapId switch + { + MapId.Skeld => 13, + MapId.MiraHQ => 2, + MapId.Polus => 12, + _ => throw new ArgumentOutOfRangeException() + }; + + _doors = new Dictionary(doorCount); + + for (var i = 0; i < doorCount; i++) + { + _doors.Add(i, false); + } + } + + public void Serialize(IMessageWriter writer, bool initialState) + { + throw new NotImplementedException(); + } + + public void Deserialize(IMessageReader reader, bool initialState) + { + if (initialState) + { + for (var i = 0; i < _doors.Count; i++) + { + _doors[i] = reader.ReadBoolean(); + } + } + else + { + var num = reader.ReadPackedUInt32(); + + for (var i = 0; i < _doors.Count; i++) + { + if ((num & 1 << i) != 0) + { + _doors[i] = reader.ReadBoolean(); + } + } + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/HudOverrideSystemType.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/HudOverrideSystemType.cs new file mode 100644 index 0000000..fe29bb0 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/HudOverrideSystemType.cs @@ -0,0 +1,19 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus +{ + public class HudOverrideSystemType : ISystemType, IActivatable + { + public bool IsActive { get; private set; } + + public void Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public void Deserialize(IMessageReader reader, bool initialState) + { + IsActive = reader.ReadBoolean(); + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/LifeSuppSystemType.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/LifeSuppSystemType.cs new file mode 100644 index 0000000..fd8b01a --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/LifeSuppSystemType.cs @@ -0,0 +1,44 @@ +using System.Collections.Generic; +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus +{ + public class LifeSuppSystemType : ISystemType, IActivatable + { + public LifeSuppSystemType() + { + Countdown = 10000f; + CompletedConsoles = new HashSet(); + } + + public float Countdown { get; private set; } + + public HashSet CompletedConsoles { get; } + + public bool IsActive => Countdown < 10000.0; + + public void Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public void Deserialize(IMessageReader reader, bool initialState) + { + Countdown = reader.ReadSingle(); + + if (reader.Position >= reader.Length) + { + return; + } + + CompletedConsoles.Clear(); // TODO: Thread safety + + var num = reader.ReadPackedInt32(); + + for (var i = 0; i < num; i++) + { + CompletedConsoles.Add(reader.ReadPackedInt32()); + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/MedScanSystem.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/MedScanSystem.cs new file mode 100644 index 0000000..f93fb8e --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/MedScanSystem.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus +{ + public class MedScanSystem : ISystemType + { + public MedScanSystem() + { + UsersList = new List(); + } + + public List UsersList { get; } + + public void Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public void Deserialize(IMessageReader reader, bool initialState) + { + UsersList.Clear(); + + var num = reader.ReadPackedInt32(); + + for (var i = 0; i < num; i++) + { + UsersList.Add(reader.ReadByte()); + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/ReactorSystemType.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/ReactorSystemType.cs new file mode 100644 index 0000000..d3f1973 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/ReactorSystemType.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus +{ + public class ReactorSystemType : ISystemType, IActivatable + { + public ReactorSystemType() + { + Countdown = 10000f; + UserConsolePairs = new HashSet>(); + } + + public float Countdown { get; private set; } + + public HashSet> UserConsolePairs { get; } + + public bool IsActive => Countdown < 10000.0; + + public void Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public void Deserialize(IMessageReader reader, bool initialState) + { + Countdown = reader.ReadSingle(); + UserConsolePairs.Clear(); // TODO: Thread safety + + var count = reader.ReadPackedInt32(); + + for (var i = 0; i < count; i++) + { + UserConsolePairs.Add(new Tuple(reader.ReadByte(), reader.ReadByte())); + } + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/SabotageSystemType.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/SabotageSystemType.cs new file mode 100644 index 0000000..f442b91 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/SabotageSystemType.cs @@ -0,0 +1,26 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus +{ + public class SabotageSystemType : ISystemType + { + private readonly IActivatable[] _specials; + + public SabotageSystemType(IActivatable[] specials) + { + _specials = specials; + } + + public float Timer { get; set; } + + public void Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public void Deserialize(IMessageReader reader, bool initialState) + { + Timer = reader.ReadSingle(); + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/SecurityCameraSystemType.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/SecurityCameraSystemType.cs new file mode 100644 index 0000000..4e16b31 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/SecurityCameraSystemType.cs @@ -0,0 +1,19 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus +{ + public class SecurityCameraSystemType : ISystemType + { + public byte InUse { get; internal set; } + + public void Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public void Deserialize(IMessageReader reader, bool initialState) + { + InUse = reader.ReadByte(); + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/SwitchSystem.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/SwitchSystem.cs new file mode 100644 index 0000000..6d46d01 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/ShipStatus/SwitchSystem.cs @@ -0,0 +1,27 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems.ShipStatus +{ + public class SwitchSystem : ISystemType, IActivatable + { + public byte ExpectedSwitches { get; set; } + + public byte ActualSwitches { get; set; } + + public byte Value { get; set; } = byte.MaxValue; + + public bool IsActive { get; } + + public void Serialize(IMessageWriter writer, bool initialState) + { + throw new System.NotImplementedException(); + } + + public void Deserialize(IMessageReader reader, bool initialState) + { + ExpectedSwitches = reader.ReadByte(); + ActualSwitches = reader.ReadByte(); + Value = reader.ReadByte(); + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/SystemTypeHelpers.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/SystemTypeHelpers.cs new file mode 100644 index 0000000..46e68ff --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/SystemTypeHelpers.cs @@ -0,0 +1,28 @@ +using System; +using System.Linq; + +namespace Impostor.Api.Innersloth.Net.Objects.Systems +{ + internal class SystemTypeHelpers + { + public static readonly SystemTypes[] AllTypes; + public static readonly string[] Names; + + static SystemTypeHelpers() + { + AllTypes = Enum.GetValues(typeof(SystemTypes)).Cast().ToArray(); + Names = AllTypes.Select(x => + { + return x switch + { + SystemTypes.UpperEngine => "Upper Engine", + SystemTypes.Nav => "Navigations", + SystemTypes.LifeSupp => "O2", + SystemTypes.LowerEngine => "Lower Engine", + SystemTypes.LockerRoom => "Locker Room", + _ => x.ToString() + }; + }).ToArray(); + } + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/Objects/Systems/SystemTypes.cs b/src/Impostor.Api/Innersloth/Net/Objects/Systems/SystemTypes.cs new file mode 100644 index 0000000..0ff4220 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/Objects/Systems/SystemTypes.cs @@ -0,0 +1,31 @@ +namespace Impostor.Api.Innersloth.Net.Objects.Systems +{ + public enum SystemTypes : byte + { + Hallway, + Storage, + Cafeteria, + Reactor, + UpperEngine, + Nav, + Admin, + Electrical, + LifeSupp, + Shields, + MedBay, + Security, + Weapons, + LowerEngine, + Comms, + ShipTasks, + Doors, + Sabotage, + Decontamination, + Launchpad, + LockerRoom, + Laboratory, + Balcony, + Office, + Greenhouse, + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Innersloth/Net/SpawnFlags.cs b/src/Impostor.Api/Innersloth/Net/SpawnFlags.cs new file mode 100644 index 0000000..0372196 --- /dev/null +++ b/src/Impostor.Api/Innersloth/Net/SpawnFlags.cs @@ -0,0 +1,11 @@ +using System; + +namespace Impostor.Api.Innersloth.Net +{ + [Flags] + public enum SpawnFlags : byte + { + None = 0, + IsClientCharacter = 1, + } +} \ No newline at end of file diff --git a/src/Impostor.Api/Net/Messages/C2S/Message01JoinGameC2S.cs b/src/Impostor.Api/Net/Messages/C2S/Message01JoinGameC2S.cs index c713790..f121b97 100644 --- a/src/Impostor.Api/Net/Messages/C2S/Message01JoinGameC2S.cs +++ b/src/Impostor.Api/Net/Messages/C2S/Message01JoinGameC2S.cs @@ -1,5 +1,4 @@ using System; -using Impostor.Api.Extensions; namespace Impostor.Api.Net.Messages.C2S { diff --git a/src/Impostor.Api/Net/Messages/C2S/Message10AlterGameC2S.cs b/src/Impostor.Api/Net/Messages/C2S/Message10AlterGameC2S.cs index e9ad8e8..dd143c0 100644 --- a/src/Impostor.Api/Net/Messages/C2S/Message10AlterGameC2S.cs +++ b/src/Impostor.Api/Net/Messages/C2S/Message10AlterGameC2S.cs @@ -1,5 +1,4 @@ -using Impostor.Api.Extensions; -using Impostor.Api.Innersloth.Data; +using Impostor.Api.Innersloth.Data; namespace Impostor.Api.Net.Messages.C2S { diff --git a/src/Impostor.Api/Properties/AssemblyInfo.cs b/src/Impostor.Api/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c02e44a --- /dev/null +++ b/src/Impostor.Api/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly:InternalsVisibleTo("Impostor.Server")] \ No newline at end of file diff --git a/src/Impostor.Server/GameData/GameObject.cs b/src/Impostor.Server/GameData/GameObject.cs deleted file mode 100644 index c78dee0..0000000 --- a/src/Impostor.Server/GameData/GameObject.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Collections.Generic; - -namespace Impostor.Server.GameData -{ - public class GameObject - { - public GameObject() - { - Components = new List(); - } - - protected List Components { get; } - - public List GetComponentsInChildren() - { - var result = new List(); - - foreach (var component in Components) - { - if (component.GetType().IsAssignableTo(typeof(T))) - { - result.Add((T) component); - } - } - - return result; - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/InnerNetObject.cs b/src/Impostor.Server/GameData/InnerNetObject.cs deleted file mode 100644 index d1a09e0..0000000 --- a/src/Impostor.Server/GameData/InnerNetObject.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Impostor.Api.Net.Messages; - -namespace Impostor.Server.GameData -{ - public abstract class InnerNetObject : GameObject - { - public uint NetId { get; set; } - - public int OwnerId { get; set; } - - public SpawnFlags SpawnFlags { get; internal set; } - - public abstract void HandleRpc(byte callId, IMessageReader reader); - - public abstract bool Serialize(IMessageWriter writer, bool initialState); - - public abstract void Deserialize(IMessageReader reader, bool initialState); - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/Components/InnerCustomNetworkTransform.cs b/src/Impostor.Server/GameData/Objects/Components/InnerCustomNetworkTransform.cs deleted file mode 100644 index c6804ed..0000000 --- a/src/Impostor.Server/GameData/Objects/Components/InnerCustomNetworkTransform.cs +++ /dev/null @@ -1,113 +0,0 @@ -using System.Numerics; -using Impostor.Api.Innersloth; -using Impostor.Api.Net.Messages; -using Microsoft.Extensions.Logging; - -namespace Impostor.Server.GameData.Objects.Components -{ - public class InnerCustomNetworkTransform : InnerNetObject - { - private static readonly FloatRange XRange = new FloatRange(-40f, 40f); - private static readonly FloatRange YRange = new FloatRange(-40f, 40f); - - private readonly ILogger _logger; - - private ushort _lastSequenceId; - private Vector2 _targetSyncPosition; - private Vector2 _targetSyncVelocity; - - public InnerCustomNetworkTransform(ILogger logger) - { - _logger = logger; - } - - private static bool SidGreaterThan(ushort newSid, ushort prevSid) - { - var num = (ushort)(prevSid + (uint) short.MaxValue); - - return (int) prevSid < (int) num - ? newSid > prevSid && newSid <= num - : newSid > prevSid || newSid <= num; - } - - private static void WriteVector2(IMessageWriter writer, Vector2 vec) - { - writer.Write((ushort)(XRange.ReverseLerp(vec.X) * (double) ushort.MaxValue)); - writer.Write((ushort)(YRange.ReverseLerp(vec.Y) * (double) ushort.MaxValue)); - } - - private static Vector2 ReadVector2(IMessageReader reader) - { - var v1 = reader.ReadUInt16() / (float) ushort.MaxValue; - var v2 = reader.ReadUInt16() / (float) ushort.MaxValue; - - return new Vector2(XRange.Lerp(v1), YRange.Lerp(v2)); - } - - public override void HandleRpc(byte callId, IMessageReader reader) - { - if (callId == 0) - { - SnapTo(ReadVector2(reader), reader.ReadUInt16()); - } - else - { - _logger.LogWarning("InnerCustomNetworkTransform: Unknown rpc call {0}", callId); - } - } - - public override bool Serialize(IMessageWriter writer, bool initialState) - { - if (initialState) - { - writer.Write(_lastSequenceId); - WriteVector2(writer, _targetSyncPosition); - WriteVector2(writer, _targetSyncVelocity); - return true; - } - - // TODO: DirtyBits == 0 return false. - _lastSequenceId++; - - writer.Write(_lastSequenceId); - WriteVector2(writer, _targetSyncPosition); - WriteVector2(writer, _targetSyncVelocity); - return true; - } - - public override void Deserialize(IMessageReader reader, bool initialState) - { - var sequenceId = reader.ReadUInt16(); - - if (initialState) - { - _lastSequenceId = sequenceId; - _targetSyncPosition = ReadVector2(reader); - _targetSyncVelocity = ReadVector2(reader); - } - else - { - if (!SidGreaterThan(sequenceId, _lastSequenceId)) - { - return; - } - - _lastSequenceId = sequenceId; - _targetSyncPosition = ReadVector2(reader); - _targetSyncVelocity = ReadVector2(reader); - } - } - - private void SnapTo(Vector2 position, ushort minSid) - { - if (SidGreaterThan(minSid, _lastSequenceId)) - { - return; - } - - _lastSequenceId = minSid; - _targetSyncPosition = position; - _targetSyncVelocity = Vector2.Zero; - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/Components/InnerPlayerPhysics.cs b/src/Impostor.Server/GameData/Objects/Components/InnerPlayerPhysics.cs deleted file mode 100644 index 698f97e..0000000 --- a/src/Impostor.Server/GameData/Objects/Components/InnerPlayerPhysics.cs +++ /dev/null @@ -1,22 +0,0 @@ -using Impostor.Api.Net.Messages; - -namespace Impostor.Server.GameData.Objects.Components -{ - public class InnerPlayerPhysics : InnerNetObject - { - public override void HandleRpc(byte callId, IMessageReader reader) - { - throw new System.NotImplementedException(); - } - - public override bool Serialize(IMessageWriter writer, bool initialState) - { - throw new System.NotImplementedException(); - } - - public override void Deserialize(IMessageReader reader, bool initialState) - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/Components/InnerVoteBanSystem.cs b/src/Impostor.Server/GameData/Objects/Components/InnerVoteBanSystem.cs deleted file mode 100644 index 72253ba..0000000 --- a/src/Impostor.Server/GameData/Objects/Components/InnerVoteBanSystem.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Collections.Generic; -using Impostor.Api.Net.Messages; - -namespace Impostor.Server.GameData.Objects.Components -{ - public class InnerVoteBanSystem : InnerNetObject - { - private readonly Dictionary _votes; - - public InnerVoteBanSystem() - { - _votes = new Dictionary(); - } - - public override void HandleRpc(byte callId, IMessageReader reader) - { - throw new NotImplementedException(); - } - - public override bool Serialize(IMessageWriter writer, bool initialState) - { - throw new NotImplementedException(); - } - - public override void Deserialize(IMessageReader reader, bool initialState) - { - var votes = _votes; - var unknown = reader.ReadBoolean(); - if (unknown) - { - while (true) - { - var v4 = reader.ReadInt32(); - - if (!votes.TryGetValue(v4, out var v12)) - { - v12 = new int[3]; - votes[v4] = v12; - } - - for (var i = 0; i < 3; i++) - { - v12[i] = reader.ReadPackedInt32(); - } - } - } - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/InnerGameData.PlayerInfo.cs b/src/Impostor.Server/GameData/Objects/InnerGameData.PlayerInfo.cs deleted file mode 100644 index dfcdfab..0000000 --- a/src/Impostor.Server/GameData/Objects/InnerGameData.PlayerInfo.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Collections.Generic; -using Impostor.Api.Net.Messages; - -namespace Impostor.Server.GameData.Objects -{ - public partial class InnerGameData - { - public class PlayerInfo - { - public PlayerInfo(byte playerId) - { - PlayerId = playerId; - } - - public byte PlayerId { get; } - - public string PlayerName { get; private set; } - - public byte ColorId { get; private set; } - - public uint HatId { get; private set; } - - public uint PetId { get; private set; } - - public uint SkinId { get; private set; } - - public bool Disconnected { get; private set; } - - public bool IsImpostor { get; private set; } - - public bool IsDead { get; private set; } - - public List Tasks { get; private set; } - - public void Serialize(IMessageWriter writer) - { - throw new NotImplementedException(); - } - - public void Deserialize(IMessageReader reader) - { - PlayerName = reader.ReadString(); - ColorId = reader.ReadByte(); - HatId = reader.ReadPackedUInt32(); - PetId = reader.ReadPackedUInt32(); - SkinId = reader.ReadPackedUInt32(); - var flag = reader.ReadByte(); - Disconnected = (flag & 1) > 0; - IsImpostor = (flag & 2) > 0; - IsDead = (flag & 4) > 0; - var taskCount = reader.ReadByte(); - Tasks = new List(); - for (var i = 0; i < taskCount; i++) - { - Tasks.Add(new TaskInfo()); - Tasks[i].Deserialize(reader); - } - } - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/InnerGameData.TaskInfo.cs b/src/Impostor.Server/GameData/Objects/InnerGameData.TaskInfo.cs deleted file mode 100644 index 516a7a9..0000000 --- a/src/Impostor.Server/GameData/Objects/InnerGameData.TaskInfo.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Impostor.Api.Net.Messages; - -namespace Impostor.Server.GameData.Objects -{ - public partial class InnerGameData - { - public class TaskInfo - { - public uint Id { get; private set; } - - public bool Complete { get; private set; } - - public void Serialize(IMessageWriter writer) - { - writer.WritePacked(Id); - writer.Write(Complete); - } - - public void Deserialize(IMessageReader reader) - { - this.Id = reader.ReadPackedUInt32(); - this.Complete = reader.ReadBoolean(); - } - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/InnerGameData.cs b/src/Impostor.Server/GameData/Objects/InnerGameData.cs deleted file mode 100644 index 3b27000..0000000 --- a/src/Impostor.Server/GameData/Objects/InnerGameData.cs +++ /dev/null @@ -1,83 +0,0 @@ -using System; -using System.Collections.Generic; -using Impostor.Api.Games; -using Impostor.Api.Net.Messages; -using Impostor.Server.GameData.Objects.Components; - -namespace Impostor.Server.GameData.Objects -{ - public partial class InnerGameData : InnerNetObject - { - private readonly IGame _game; - private readonly List _allPlayers; - - public InnerGameData(IGame game) - { - _game = game; - _allPlayers = new List(); - - Components.Add(this); - Components.Add(new InnerVoteBanSystem()); - } - - public PlayerInfo GetPlayerById(byte id) - { - foreach (var player in _allPlayers) - { - if (player.PlayerId == id) - { - return player; - } - } - - return null; - } - - public override void HandleRpc(byte callId, IMessageReader reader) - { - throw new NotImplementedException(); - } - - public override bool Serialize(IMessageWriter writer, bool initialState) - { - throw new NotImplementedException(); - } - - public override void Deserialize(IMessageReader reader, bool initialState) - { - if (initialState) - { - var num = reader.ReadPackedInt32(); - - for (var i = 0; i < num; i++) - { - var playerInfo = new PlayerInfo(reader.ReadByte()); - playerInfo.Deserialize(reader); - _allPlayers.Add(playerInfo); - } - } - else - { - throw new NotImplementedException("This shouldn't happen, according to Among Us assembly.."); - - // 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); - // } - // } - } - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/InnerLobbyBehaviour.cs b/src/Impostor.Server/GameData/Objects/InnerLobbyBehaviour.cs deleted file mode 100644 index c9f96c0..0000000 --- a/src/Impostor.Server/GameData/Objects/InnerLobbyBehaviour.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Impostor.Api.Games; -using Impostor.Api.Net.Messages; - -namespace Impostor.Server.GameData.Objects -{ - public class InnerLobbyBehaviour : InnerNetObject - { - private readonly IGame _game; - - public InnerLobbyBehaviour(IGame game) - { - _game = game; - - Components.Add(this); - } - - public override void HandleRpc(byte callId, IMessageReader reader) - { - throw new System.NotImplementedException(); - } - - public override bool Serialize(IMessageWriter writer, bool initialState) - { - throw new System.NotImplementedException(); - } - - public override void Deserialize(IMessageReader reader, bool initialState) - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/InnerMeetingHud.cs b/src/Impostor.Server/GameData/Objects/InnerMeetingHud.cs deleted file mode 100644 index 7088526..0000000 --- a/src/Impostor.Server/GameData/Objects/InnerMeetingHud.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Impostor.Api.Games; -using Impostor.Api.Net.Messages; - -namespace Impostor.Server.GameData.Objects -{ - public class InnerMeetingHud : InnerNetObject - { - private readonly IGame _game; - - public InnerMeetingHud(IGame game) - { - _game = game; - - Components.Add(this); - } - - public override void HandleRpc(byte callId, IMessageReader reader) - { - throw new System.NotImplementedException(); - } - - public override bool Serialize(IMessageWriter writer, bool initialState) - { - throw new System.NotImplementedException(); - } - - public override void Deserialize(IMessageReader reader, bool initialState) - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/InnerPlayerControl.cs b/src/Impostor.Server/GameData/Objects/InnerPlayerControl.cs deleted file mode 100644 index 965f8c7..0000000 --- a/src/Impostor.Server/GameData/Objects/InnerPlayerControl.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using Impostor.Api.Games; -using Impostor.Api.Net.Messages; -using Impostor.Server.GameData.Objects.Components; -using Microsoft.Extensions.DependencyInjection; - -namespace Impostor.Server.GameData.Objects -{ - public class InnerPlayerControl : InnerNetObject - { - private readonly IGame _game; - - public InnerPlayerControl(IGame game, IServiceProvider serviceProvider) - { - _game = game; - - Components.Add(this); - Components.Add(ActivatorUtilities.CreateInstance(serviceProvider)); - Components.Add(ActivatorUtilities.CreateInstance(serviceProvider)); - - PlayerId = byte.MaxValue; - } - - public bool IsNew { get; private set; } - - public byte PlayerId { get; private set; } - - public override void HandleRpc(byte callId, IMessageReader reader) - { - throw new NotImplementedException(); - } - - public override bool Serialize(IMessageWriter writer, bool initialState) - { - throw new NotImplementedException(); - } - - public override void Deserialize(IMessageReader reader, bool initialState) - { - if (initialState) - { - IsNew = reader.ReadBoolean(); - } - - PlayerId = reader.ReadByte(); - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/Objects/InnerShipStatus.cs b/src/Impostor.Server/GameData/Objects/InnerShipStatus.cs deleted file mode 100644 index 00d38c4..0000000 --- a/src/Impostor.Server/GameData/Objects/InnerShipStatus.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Impostor.Api.Games; -using Impostor.Api.Net.Messages; - -namespace Impostor.Server.GameData.Objects -{ - public class InnerShipStatus : InnerNetObject - { - private readonly IGame _game; - - public InnerShipStatus(IGame game) - { - _game = game; - - Components.Add(this); - } - - public override void HandleRpc(byte callId, IMessageReader reader) - { - throw new System.NotImplementedException(); - } - - public override bool Serialize(IMessageWriter writer, bool initialState) - { - throw new System.NotImplementedException(); - } - - public override void Deserialize(IMessageReader reader, bool initialState) - { - throw new System.NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/Impostor.Server/GameData/SpawnFlags.cs b/src/Impostor.Server/GameData/SpawnFlags.cs deleted file mode 100644 index f91b378..0000000 --- a/src/Impostor.Server/GameData/SpawnFlags.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; - -namespace Impostor.Server.GameData -{ - [Flags] - public enum SpawnFlags : byte - { - None = 0, - IsClientCharacter = 1, - } -} \ No newline at end of file diff --git a/src/Impostor.Server/Net/State/Game.Data.cs b/src/Impostor.Server/Net/State/Game.Data.cs index 4b6565a..e59e90e 100644 --- a/src/Impostor.Server/Net/State/Game.Data.cs +++ b/src/Impostor.Server/Net/State/Game.Data.cs @@ -6,12 +6,12 @@ using System.Threading.Tasks; using Impostor.Api; using Impostor.Api.Innersloth.Data; using Impostor.Api.Innersloth.GameData; +using Impostor.Api.Innersloth.Net; +using Impostor.Api.Innersloth.Net.Objects; using Impostor.Api.Net.Messages; using Impostor.Api.Net.Messages.C2S; using Impostor.Api.Net.Messages.S2C; using Impostor.Hazel; -using Impostor.Server.GameData; -using Impostor.Server.GameData.Objects; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -180,7 +180,7 @@ namespace Impostor.Server.Net.State continue; } - _logger.LogTrace( + _logger.LogDebug( "Spawning {0} components, SpawnFlags {1}", innerNetObject.GetType().Name, innerNetObject.SpawnFlags); @@ -192,7 +192,7 @@ namespace Impostor.Server.Net.State obj.NetId = reader.ReadPackedUInt32(); obj.OwnerId = ownerClientId; - _logger.LogTrace( + _logger.LogDebug( "- {0}, NetId {1}, OwnerId {2}", obj.GetType().Name, obj.NetId, @@ -211,6 +211,8 @@ namespace Impostor.Server.Net.State { obj.Deserialize(readerSub, true); } + + GameNet.OnSpawn(obj); } if ((innerNetObject.SpawnFlags & SpawnFlags.IsClientCharacter) != SpawnFlags.None) @@ -235,21 +237,30 @@ namespace Impostor.Server.Net.State case GameDataTag.DespawnFlag: { // Only the host is allowed to despawn objects. - if (!sender.IsHost) - { - _logger.LogWarning("Player {0} ({1}) tried to send DespawnFlag as non-host.", sender.Client.Name, sender.Client.Id); - return false; - } - var netId = reader.ReadPackedUInt32(); if (_allObjectsFast.TryGetValue(netId, out var obj)) { + if (sender.Client.Id != obj.OwnerId && !sender.IsHost) + { + _logger.LogWarning( + "Player {0} ({1}) tried to send DespawnFlag for {2} but was denied.", + sender.Client.Name, + sender.Client.Id, + netId); + return false; + } + RemoveNetObject(obj); - _logger.LogTrace("Destroyed InnerNetObject {0} ({1})", obj.GetType().Name, netId); + GameNet.OnSpawn(obj); + _logger.LogDebug("Destroyed InnerNetObject {0} ({1}), OwnerId {2}", obj.GetType().Name, netId, obj.OwnerId); } else { - _logger.LogWarning("Received DespawnFlag for unregistered NetId {0}.", netId); + _logger.LogWarning( + "Player {0} ({1}) sent DespawnFlag for unregistered NetId {2}.", + sender.Client.Name, + sender.Client.Id, + netId); } break; diff --git a/src/Impostor.Server/Net/State/Game.cs b/src/Impostor.Server/Net/State/Game.cs index c3283df..0826ce8 100644 --- a/src/Impostor.Server/Net/State/Game.cs +++ b/src/Impostor.Server/Net/State/Game.cs @@ -51,6 +51,7 @@ namespace Impostor.Server.Net.State Code = code; HostId = -1; GameState = GameStates.NotStarted; + GameNet = new GameNet(); Options = options; _clientManager = clientManager; _eventManager = eventManager; @@ -67,6 +68,8 @@ namespace Impostor.Server.Net.State public GameStates GameState { get; private set; } + public GameNet GameNet { get; } + public GameOptionsData Options { get; } public IDictionary Items { get; } diff --git a/src/Impostor.Tools.ServerReplay/Program.cs b/src/Impostor.Tools.ServerReplay/Program.cs index ebae6bf..c904081 100644 --- a/src/Impostor.Tools.ServerReplay/Program.cs +++ b/src/Impostor.Tools.ServerReplay/Program.cs @@ -43,7 +43,8 @@ namespace Impostor.Tools.ServerReplay private static async Task Main(string[] args) { Log.Logger = new LoggerConfiguration() - .MinimumLevel.Verbose() + // .MinimumLevel.Verbose() + .MinimumLevel.Debug() .WriteTo.Console() .CreateLogger();