diff --git a/src/Patches/Gameplay/Anticheat/VoteBanSystemPatch.cs b/src/Patches/Gameplay/Anticheat/VoteBanSystemPatch.cs index 30f7e6e..c078ec1 100644 --- a/src/Patches/Gameplay/Anticheat/VoteBanSystemPatch.cs +++ b/src/Patches/Gameplay/Anticheat/VoteBanSystemPatch.cs @@ -2,6 +2,7 @@ using BetterAmongUs.Managers; using BetterAmongUs.Modules; using BetterAmongUs.Modules.Support; +using BetterAmongUs.Structs; using HarmonyLib; namespace BetterAmongUs.Patches.Gameplay.Anticheat; @@ -9,7 +10,7 @@ namespace BetterAmongUs.Patches.Gameplay.Anticheat; [HarmonyPatch] internal static class VoteBanSystemPatch { - private static readonly List<(int ClientId, (ushort HashPuid, string FriendCode) Voter)> _voteData = []; + private static readonly List<(int ClientId, TempClientData Voter)> _voteData = []; [HarmonyPatch(typeof(VoteBanSystem), nameof(VoteBanSystem.Awake))] [HarmonyPrefix] @@ -21,7 +22,7 @@ internal static class VoteBanSystemPatch [HarmonyPatch(typeof(VoteBanSystem), nameof(VoteBanSystem.AddVote))] [HarmonyPrefix] - private static bool VoteBanSystem_AddVote_Prefix(VoteBanSystem __instance, int srcClient, int clientId, ref bool __state) + private static bool VoteBanSystem_AddVote_Prefix(int srcClient, int clientId, ref bool __state) { __state = false; @@ -38,8 +39,10 @@ internal static class VoteBanSystemPatch var client = Utils.ClientFromClientId(srcClient); if (client == null) return false; + var tempClient = new TempClientData(client); + // Allow host to vote without restrictions - if (client.Id == AmongUsClient.Instance.GetHost().Id) + if (tempClient.Id == AmongUsClient.Instance.GetHost().Id) { return true; } @@ -61,25 +64,22 @@ internal static class VoteBanSystemPatch } // If client has no ID, allow vote but log it - if (string.IsNullOrEmpty(client.ProductUserId) && string.IsNullOrEmpty(client.FriendCode)) + if (string.IsNullOrEmpty(tempClient.Puid) && string.IsNullOrEmpty(tempClient.FriendCode)) { __state = true; return true; } - // Generate hash for client's ProductUserId - var clientHash = Utils.GetHashUInt16(client.ProductUserId); - // Check if this client has already voted for the same target - foreach (var (targetClientId, (existingHash, existingFriendCode)) in _voteData) + foreach (var (targetClientId, existingVoter) in _voteData) { if (targetClientId != clientId) continue; // Detect duplicate votes by comparing hash or friend code - bool isDuplicateVote = existingHash == clientHash || - !string.IsNullOrEmpty(client.FriendCode) && - existingFriendCode == client.FriendCode; + bool isDuplicateVote = existingVoter.HashPuid == tempClient.HashPuid || + !string.IsNullOrEmpty(tempClient.FriendCode) && + existingVoter.FriendCode == tempClient.FriendCode; if (isDuplicateVote) { @@ -89,7 +89,7 @@ internal static class VoteBanSystemPatch } // Record the vote - _voteData.Add((clientId, (clientHash, client.FriendCode))); + _voteData.Add((clientId, tempClient)); __state = true; return true; } @@ -111,11 +111,9 @@ internal static class VoteBanSystemPatch private static void LogVote(VoteBanSystem voteBanSystem, int srcClient, int clientId) { - // Get source and target client info var src = Utils.ClientFromClientId(srcClient); var client = Utils.ClientFromClientId(clientId); - // Calculate current votes and required votes int currentVotes = 0; int maxVotes = 0; @@ -125,7 +123,6 @@ internal static class VoteBanSystemPatch maxVotes = votes.Length; // Total possible votes } - // Log vote with colored player names and vote count Logger_.InGame( $"{src.Character?.GetPlayerNameAndColor() ?? src.PlayerName} " + $"voted to kick {client.Character?.GetPlayerNameAndColor() ?? client.PlayerName} " + diff --git a/src/Structs/TempClientData.cs b/src/Structs/TempClientData.cs new file mode 100644 index 0000000..61724d9 --- /dev/null +++ b/src/Structs/TempClientData.cs @@ -0,0 +1,36 @@ +using BetterAmongUs.Helpers; +using InnerNet; + +namespace BetterAmongUs.Structs; + +/// +/// Represents temporary client data for caching or snapshot purposes. +/// +/// The client data to copy values from. +internal readonly struct TempClientData(ClientData clientData) +{ + /// + /// Gets the unique identifier of the client. + /// + internal readonly int Id = clientData.Id; + + /// + /// Gets the product user ID (PUID) of the client. + /// + internal readonly string Puid = clientData.ProductUserId; + + /// + /// Gets the hashed product user ID. + /// + internal readonly string HashPuid = Utils.GetHashStr(clientData.ProductUserId); + + /// + /// Gets the friend code of the client. + /// + internal readonly string FriendCode = clientData.FriendCode; + + /// + /// Gets the player name of the client. + /// + internal readonly string PlayerName = clientData.PlayerName; +} \ No newline at end of file