]> git.deb.at Git - rhonda/impostor.git/commitdiff
Meeting changes
authorjs6pak <kubastaron@hotmail.com>
Thu, 17 Jun 2021 17:13:16 +0000 (19:13 +0200)
committerminiduikboot <mini@duikbo.at>
Fri, 25 Jun 2021 16:46:28 +0000 (18:46 +0200)
src/Impostor.Api/Events/Game/Player/IPlayerVotedEvent.cs
src/Impostor.Api/Net/Messages/Rpcs/Rpc23VotingComplete.cs
src/Impostor.Api/Net/Messages/Rpcs/Rpc24CastVote.cs
src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.PlayerVoteArea.cs
src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.VoterState.cs [new file with mode: 0644]
src/Impostor.Server/Net/Inner/Objects/InnerMeetingHud.cs

index 2533266abc1689961acec70b9bd4efa7d83f9e58..1424cce9f4beda168367c99479deb965aa5529e5 100644 (file)
@@ -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,
     }
 
index bf9482738d3036b8ce840ab1187ebf6ce099eb71..6a05e41d133631a31fc9e1a87a7989dc04b98ac8 100644 (file)
@@ -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<byte> 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();
         }
index 1c51bc17e6133c8ff4e50b6233325e663cb96af2..e75ba958367842b39c36feb5438a7c7b1f91832c 100644 (file)
@@ -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();
         }
     }
 }
index 26ac98111acd26a8827e6e5878adb769c5cba2a9..9e0004a0ad170bafbc5e13b24cdd1bae55c940e5 100644 (file)
@@ -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 (file)
index 0000000..56dc958
--- /dev/null
@@ -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();
+            }
+        }
+    }
+}
index 6dcd105a9abf8f1b6b81b3e37a3bc5028b41e41a..86633e46342f27865349b19a3f83b596c1219934 100644 (file)
@@ -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<bool> HandleCastVoteAsync(ClientPlayer sender, ClientPlayer? target, byte playerId, sbyte suspectPlayerId)
+        private async ValueTask<bool> 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<byte, int> MaxPair(Dictionary<byte, int> 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, int>(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>(T[] self, Func<T, int> comparer, out bool tie)
+        private Dictionary<byte, int> CalculateVotes()
         {
-            tie = false;
-            var num = int.MinValue;
-            var result = -1;
-            for (var i = 0; i < self.Length; i++)
+            var players = new Dictionary<byte, int>();
+            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)
             {