From: js6pak Date: Thu, 17 Jun 2021 17:13:16 +0000 (+0200) Subject: Meeting changes X-Git-Tag: v1.5.0~7^2~5 X-Git-Url: https://git.deb.at/?a=commitdiff_plain;h=d894e9adc3c2f42a961ba972fd93a1775f850c74;p=rhonda%2Fimpostor.git Meeting changes --- diff --git a/src/Impostor.Api/Events/Game/Player/IPlayerVotedEvent.cs b/src/Impostor.Api/Events/Game/Player/IPlayerVotedEvent.cs index 2533266..1424cce 100644 --- a/src/Impostor.Api/Events/Game/Player/IPlayerVotedEvent.cs +++ b/src/Impostor.Api/Events/Game/Player/IPlayerVotedEvent.cs @@ -2,10 +2,12 @@ using Impostor.Api.Net.Inner.Objects; namespace Impostor.Api.Events.Player { - public enum VoteType : sbyte + public enum VoteType : byte { - ForceSkip = -2, - Skip = -1, + HasNotVoted = 255, + Missed = 254, + Skipped = 253, + Dead = 252, Player = 0, } diff --git a/src/Impostor.Api/Net/Messages/Rpcs/Rpc23VotingComplete.cs b/src/Impostor.Api/Net/Messages/Rpcs/Rpc23VotingComplete.cs index bf94827..6a05e41 100644 --- a/src/Impostor.Api/Net/Messages/Rpcs/Rpc23VotingComplete.cs +++ b/src/Impostor.Api/Net/Messages/Rpcs/Rpc23VotingComplete.cs @@ -1,5 +1,3 @@ -using System; - namespace Impostor.Api.Net.Messages.Rpcs { public static class Rpc23VotingComplete @@ -11,9 +9,15 @@ namespace Impostor.Api.Net.Messages.Rpcs writer.Write(tie); } - public static void Deserialize(IMessageReader reader, out ReadOnlyMemory states, out byte playerId, out bool tie) + public static void Deserialize(IMessageReader reader, out IMessageReader[] states, out byte playerId, out bool tie) { - states = reader.ReadBytesAndSize(); + var length = reader.ReadPackedInt32(); + states = new IMessageReader[length]; + for (var i = 0; i < length; i++) + { + states[i] = reader.ReadMessage(); + } + playerId = reader.ReadByte(); tie = reader.ReadBoolean(); } diff --git a/src/Impostor.Api/Net/Messages/Rpcs/Rpc24CastVote.cs b/src/Impostor.Api/Net/Messages/Rpcs/Rpc24CastVote.cs index 1c51bc1..e75ba95 100644 --- a/src/Impostor.Api/Net/Messages/Rpcs/Rpc24CastVote.cs +++ b/src/Impostor.Api/Net/Messages/Rpcs/Rpc24CastVote.cs @@ -8,10 +8,10 @@ namespace Impostor.Api.Net.Messages.Rpcs writer.Write(suspectPlayerId); } - public static void Deserialize(IMessageReader reader, out byte playerId, out sbyte suspectPlayerId) + public static void Deserialize(IMessageReader reader, out byte playerId, out byte suspectPlayerId) { playerId = reader.ReadByte(); - suspectPlayerId = reader.ReadSByte(); + suspectPlayerId = reader.ReadByte(); } } } diff --git a/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.PlayerVoteArea.cs b/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.PlayerVoteArea.cs index 26ac981..9e0004a 100644 --- a/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.PlayerVoteArea.cs +++ b/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.PlayerVoteArea.cs @@ -9,12 +9,7 @@ namespace Impostor.Server.Net.Inner.Objects { public class PlayerVoteArea : IInnerMeetingHud.IPlayerVoteArea { - private const byte VoteMask = 15; - private const byte ReportedBit = 32; - private const byte VotedBit = 64; - private const byte DeadBit = 128; - - private sbyte _votedForId; + private byte _votedForId; public PlayerVoteArea(InnerMeetingHud parent, InnerPlayerInfo targetPlayer, bool isDead) { @@ -34,7 +29,7 @@ namespace Impostor.Server.Net.Inner.Objects public bool DidReport { get; private set; } - public sbyte VotedForId + public byte VotedForId { get => _votedForId; @@ -42,26 +37,26 @@ namespace Impostor.Server.Net.Inner.Objects { _votedForId = value; - if (DidVote) - { - switch ((VoteType)value) - { - case TVoteType.ForceSkip: - case TVoteType.Skip: - VoteType = (VoteType)value; - break; - - default: - VoteType = TVoteType.Player; - VotedFor = Parent.Game.GameNet.GameData!.GetPlayerById((byte)value)?.Controller; - break; - } - } - else + switch ((VoteType)value) { - VoteType = null; - VotedFor = null; + case TVoteType.Dead: + IsDead = true; + VoteType = TVoteType.Dead; + break; + + case TVoteType.HasNotVoted: + case TVoteType.Missed: + case TVoteType.Skipped: + VoteType = (VoteType)value; + break; + + default: + VoteType = TVoteType.Player; + VotedFor = Parent.Game.GameNet.GameData!.GetPlayerById(value)?.Controller; + break; } + + DidVote = VoteType != TVoteType.HasNotVoted; } } @@ -73,38 +68,19 @@ namespace Impostor.Server.Net.Inner.Objects internal void Deserialize(IMessageReader reader, bool updateVote) { - var state = reader.ReadByte(); - DeserializeState(state, out var votedForId, out var isDead, out var didVote, out var didReport); - - IsDead = isDead; - DidReport = didReport; + var votedForId = reader.ReadByte(); if (updateVote) { - DidVote = didVote; VotedForId = votedForId; } - } - internal void SetVotedFor(sbyte votedFor) - { - DidVote = true; - VotedForId = votedFor; + DidReport = reader.ReadBoolean(); } - private static void DeserializeState(byte state, out sbyte votedForId, out bool isDead, out bool didVote, out bool didReport) + internal void SetVotedFor(byte votedFor) { - votedForId = (sbyte)((state & VoteMask) - 1); - - // Among Us's meeting system is really scuffed, we need this to ensure that ForceSkip state is correct (this will break any 14+ players game) - if (votedForId == ((sbyte)TVoteType.ForceSkip + 1 & 14)) - { - votedForId = (sbyte)TVoteType.ForceSkip; - } - - isDead = (state & DeadBit) > 0; - didVote = (state & VotedBit) > 0; - didReport = (state & ReportedBit) > 0; + VotedForId = votedFor; } } } diff --git a/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.VoterState.cs b/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.VoterState.cs new file mode 100644 index 0000000..56dc958 --- /dev/null +++ b/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.VoterState.cs @@ -0,0 +1,32 @@ +using Impostor.Api.Net.Messages; + +namespace Impostor.Server.Net.Inner.Objects +{ + internal partial class InnerMeetingHud + { + public class VoterState + { + public VoterState(byte voterId, byte votedForId) + { + VoterId = voterId; + VotedForId = votedForId; + } + + public byte VoterId { get; } + + public byte VotedForId { get; } + + public static VoterState Deserialize(IMessageReader reader) + { + return new VoterState(reader.Tag, reader.ReadByte()); + } + + public void Serialize(IMessageWriter writer) + { + writer.StartMessage(this.VoterId); + writer.Write(this.VotedForId); + writer.EndMessage(); + } + } + } +} diff --git a/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.cs b/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.cs index 6dcd105..86633e4 100644 --- a/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.cs +++ b/src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; @@ -42,7 +43,8 @@ namespace Impostor.Server.Net.Inner.Objects { try { - await Task.Delay(TimeSpan.FromSeconds(Game.Options.DiscussionTime + Game.Options.VotingTime), _timerToken.Token); + const float AnimationTime = 0.25f + 0.5f + 0.4f + 3f + 0.75f + 5f; + await Task.Delay(TimeSpan.FromSeconds(AnimationTime + Game.Options.DiscussionTime + Game.Options.VotingTime), _timerToken.Token); } catch (TaskCanceledException) { @@ -70,37 +72,31 @@ namespace Impostor.Server.Net.Inner.Objects if (initialState) { PopulateButtons(); + } - foreach (var playerState in _playerStates) - { - playerState.Deserialize(reader, false); + var length = reader.ReadPackedUInt32(); - if (playerState.DidReport) - { - Reporter = playerState.TargetPlayer; - } - } - } - else + for (var i = 0; i < length; i++) { - var num = reader.ReadPackedUInt32(); + var inner = reader.ReadMessage(); + var playerVoteArea = _playerStates.SingleOrDefault(x => x.TargetPlayer.PlayerId == inner.Tag); - for (var i = 0; i < _playerStates.Length; i++) + if (playerVoteArea != null) { - if ((num & 1 << i) != 0) - { - var playerVoteArea = _playerStates[i]; + var clientPlayer = Game.Players.SingleOrDefault(x => x.Character?.PlayerId == playerVoteArea.TargetPlayer.PlayerId); + var updateVote = !playerVoteArea.DidVote && (clientPlayer?.IsHost ?? false) && playerVoteArea.VoteType != VoteType.Missed; - var clientPlayer = Game.Players.SingleOrDefault(x => x.Character?.PlayerId == playerVoteArea.TargetPlayer.PlayerId); - var isHost = (clientPlayer?.IsHost ?? false) && playerVoteArea.VoteType != VoteType.ForceSkip; + playerVoteArea.Deserialize(inner, updateVote); - playerVoteArea.Deserialize(reader, isHost); + if (updateVote) + { + await HandleVoteAsync(playerVoteArea); + await CheckForEndVotingAsync(); + } - if (isHost) - { - await HandleVoteAsync(playerVoteArea); - await CheckForEndVotingAsync(); - } + if (initialState && playerVoteArea.DidReport) + { + Reporter = playerVoteArea.TargetPlayer; } } } @@ -177,7 +173,7 @@ namespace Impostor.Server.Net.Inner.Objects } } - private async ValueTask HandleCastVoteAsync(ClientPlayer sender, ClientPlayer? target, byte playerId, sbyte suspectPlayerId) + private async ValueTask HandleCastVoteAsync(ClientPlayer sender, ClientPlayer? target, byte playerId, byte suspectPlayerId) { if (sender.IsHost) { @@ -221,46 +217,45 @@ namespace Impostor.Server.Net.Inner.Objects } } - private byte[] CalculateVotes() + private KeyValuePair MaxPair(Dictionary self, out bool tie) { - byte[] array = new byte[_playerStates.Max(x => x.TargetPlayer.PlayerId) + 2]; - foreach (var playerVoteArea in _playerStates) + tie = true; + var result = new KeyValuePair(byte.MaxValue, int.MinValue); + foreach (var keyValuePair in self) { - if (playerVoteArea.DidVote) + if (keyValuePair.Value > result.Value) { - var index = playerVoteArea.VotedForId + 1; - if (index >= 0 && index < array.Length) - { - array[index] += 1; - } + result = keyValuePair; + tie = false; + } + else if (keyValuePair.Value == result.Value) + { + tie = true; } } - return array; + return result; } - private int IndexOfMax(T[] self, Func comparer, out bool tie) + private Dictionary CalculateVotes() { - tie = false; - var num = int.MinValue; - var result = -1; - for (var i = 0; i < self.Length; i++) + var players = new Dictionary(); + foreach (var playerVoteArea in _playerStates) { - var num2 = comparer.Invoke(self[i]); - if (num2 > num) - { - result = i; - num = num2; - tie = false; - } - else if (num2 == num) + if (!playerVoteArea.IsDead && playerVoteArea.DidVote && playerVoteArea.VoteType != VoteType.Missed) { - tie = true; - result = -1; + if (players.TryGetValue(playerVoteArea.VotedForId, out var current)) + { + players[playerVoteArea.VotedForId] = current + 1; + } + else + { + players[playerVoteArea.VotedForId] = 1; + } } } - return result; + return players; } private async ValueTask HandleVotingCompleteAsync() @@ -271,14 +266,14 @@ namespace Impostor.Server.Net.Inner.Objects { if (!playerVoteArea.DidVote) { - playerVoteArea.SetVotedFor((sbyte)VoteType.ForceSkip); + playerVoteArea.SetVotedFor((byte)VoteType.Missed); await HandleVoteAsync(playerVoteArea); } } - byte[] self = this.CalculateVotes(); - var maxIdx = IndexOfMax(self, p => p, out var tie) - 1; - var exiled = Game.GameNet.GameData!.GetPlayerById((byte)maxIdx)?.Controller; + var self = this.CalculateVotes(); + var max = MaxPair(self, out var tie); + var exiled = tie ? null : Game.GameNet.GameData!.GetPlayerById(max.Key)?.Controller; if (exiled != null) {