Attempt to fix "banned by Innersloth Anti-Cheat" issues

This commit is contained in:
At0mBomba committed 2026-07-19 14:32:03 +03:00
1 parent b723860ab8
commit f3e73e0cdc
9 files changed
+156 -37

No files matched your search

+36
View File
@@ -0,0 +1,36 @@
using System.Collections;
using BepInEx.Unity.IL2CPP.Utils;
using BetterAmongUs.Patches.Gameplay.UI.Settings;
using UnityEngine;
namespace BetterAmongUs.Managers;
/// <summary>
/// Manages the cooldown period between player kick actions.
/// This cooldown is necessary to avoid bans by Innersloth anti-cheat.
/// </summary>
internal static class KickCooldownManager
{
private static float CooldownSeconds => BetterGameSettings.KickCooldown.GetFloat();
private static float _lastTriggerTime;
internal static bool IsReady() => Time.time - _lastTriggerTime > CooldownSeconds;
internal static void Trigger() => _lastTriggerTime = Time.time;
private static float TimeToNextAvailableTrigger() => CooldownSeconds - (Time.time - _lastTriggerTime);
internal static void ScheduleAction(Action action)
{
AmongUsClient.Instance.StartCoroutine(RunScheduledAction(action));
}
private static IEnumerator RunScheduledAction(Action action)
{
while (!IsReady())
{
yield return new WaitForSeconds(TimeToNextAvailableTrigger());
}
Trigger();
action();
}
}
+5 -5
View File
@@ -51,31 +51,31 @@ internal static class BetterAntiCheat
{
string reason = TranslationStrings.AntiCheat_Reason_SickoMenuUser.LocalizedString;
string kickMessage = TranslationStrings.AntiCheat_KickMessage.Format(TranslationStrings.AntiCheat_ByAntiCheat, reason);
player.Kick(true, kickMessage, true);
player.TryKick(true, kickMessage, true);
}
else if (BetterDataManager.Files.BetterDataFile.AUMData.Any(info => info.CheckPlayerData(player.Data)))
{
string reason = TranslationStrings.AntiCheat_Reason_AUMUser.LocalizedString;
string kickMessage = TranslationStrings.AntiCheat_KickMessage.Format(TranslationStrings.AntiCheat_ByAntiCheat, reason);
player.Kick(true, kickMessage, true);
player.TryKick(true, kickMessage, true);
}
else if (BetterDataManager.Files.BetterDataFile.KNData.Any(info => info.CheckPlayerData(player.Data)))
{
string reason = TranslationStrings.AntiCheat_Reason_KNUser.LocalizedString;
string kickMessage = TranslationStrings.AntiCheat_KickMessage.Format(TranslationStrings.AntiCheat_ByAntiCheat, reason);
player.Kick(true, kickMessage, true);
player.TryKick(true, kickMessage, true);
}
else if (BetterDataManager.Files.BetterDataFile.MMCData.Any(info => info.CheckPlayerData(player.Data)))
{
string reason = TranslationStrings.AntiCheat_Reason_MMCUser.LocalizedString;
string kickMessage = TranslationStrings.AntiCheat_KickMessage.Format(TranslationStrings.AntiCheat_ByAntiCheat, reason);
player.Kick(true, kickMessage, true);
player.TryKick(true, kickMessage, true);
}
else if (BetterDataManager.Files.BetterDataFile.CheatData.Any(info => info.CheckPlayerData(player.Data)))
{
string reason = TranslationStrings.AntiCheat_Reason_KnownCheater.LocalizedString;
string kickMessage = TranslationStrings.AntiCheat_KickMessage.Format(TranslationStrings.AntiCheat_ByAntiCheat, reason);
player.Kick(true, kickMessage, true);
player.TryKick(true, kickMessage, true);
}
}
}
+1 -1
View File
@@ -277,7 +277,7 @@ internal class PlayerInfoDisplay : MonoBehaviour
if (GameState.IsHost && BetterGameSettings.InvalidFriendCode.GetBool())
{
string kickMessage = TranslationStrings.AntiCheat_KickMessage.Format(TranslationStrings.AntiCheat_ByAntiCheat, TranslationStrings.AntiCheat_Reason_InvalidFriendCode);
_player.Kick(true, kickMessage, true);
_player.TryKick(true, kickMessage, true);
}
}
@@ -1,6 +1,6 @@
using BetterAmongUs.Modules;
using BetterAmongUs.Utilities;
using BetterAmongUs.Modules;
using BetterAmongUs.Patches.Gameplay.UI.Settings;
using BetterAmongUs.Utilities;
using HarmonyLib;
namespace BetterAmongUs.Patches.Gameplay.Anticheat;
@@ -20,7 +20,7 @@ internal static class CheckPlayerLevelPatch
// Kick players below minimum level
if (!__instance.IsLocalPlayer() && BetterGameSettings.KickLevel.GetBool() && __instance.Data.PlayerLevel < BetterGameSettings.KickLevelBelow.GetInt())
{
__instance.Kick(setReasonInfo: $" is level {__instance.Data.PlayerLevel}, level must be equal or above {BetterGameSettings.KickLevelBelow.GetInt()} to join");
__instance.TryKick(setReasonInfo: $" is level {__instance.Data.PlayerLevel}, level must be equal or above {BetterGameSettings.KickLevelBelow.GetInt()} to join");
}
}
}
@@ -1,7 +1,9 @@
using System.Collections;
using BepInEx.Unity.IL2CPP.Utils;
using BetterAmongUs.Data;
using BetterAmongUs.Data.Config;
using BetterAmongUs.Generated;
using BetterAmongUs.Managers;
using BetterAmongUs.Modules;
using BetterAmongUs.Modules.Support;
using BetterAmongUs.MonoScripts.Extended;
@@ -10,7 +12,6 @@ using BetterAmongUs.Patches.Gameplay.UI.Settings;
using BetterAmongUs.Utilities;
using HarmonyLib;
using InnerNet;
using System.Collections;
namespace BetterAmongUs.Patches.Gameplay.Player;
@@ -38,6 +39,7 @@ internal static class PlayerJoinAndLeftPatch
{
if (GameState.IsHost)
{
KickCooldownManager.Trigger();
__instance.StartCoroutine(CoCheckPlayerOnJoin(data));
}
}
@@ -59,8 +61,7 @@ internal static class PlayerJoinAndLeftPatch
if (player != null)
{
if (TextFileHandler.CompareStringMatch(BetterDataManager.Files.banPlayerListFilePath,
BAUPlugin.AllPlayerControls.Select(player => player.Data.FriendCode)
.Concat(BAUPlugin.AllPlayerControls.Select(player => player.GetHashPuid())).ToArray()))
[player.Data.FriendCode, player.GetHashPuid()]))
{
player.Kick(true, TranslationStrings.AntiCheat_BanPlayerListMessage.LocalizedString, bypassDataCheck: true);
yield break;
@@ -75,7 +76,7 @@ internal static class PlayerJoinAndLeftPatch
{
if (TextFileHandler.CompareStringFilters(BetterDataManager.Files.banNameListFilePath, [player.Data.PlayerName]))
{
player?.Kick(true, TranslationStrings.AntiCheat_BanPlayerListMessage.LocalizedString, bypassDataCheck: true);
player.Kick(true, TranslationStrings.AntiCheat_BanNameListMessage.LocalizedString, bypassDataCheck: true);
}
}
}
@@ -86,6 +87,8 @@ internal static class PlayerJoinAndLeftPatch
[HarmonyPostfix]
private static void AmongUsClient_OnPlayerLeft_Postfix(ClientData data, DisconnectReasons reason)
{
KickCooldownManager.Trigger();
// Reclaim favorite color when player leaves in lobby
if (GameState.IsLobby)
{
@@ -11,6 +11,7 @@ namespace BetterAmongUs.Patches.Gameplay.UI.Settings;
// Custom game settings definitions
internal sealed class BetterGameSettings
{
internal static OptionFloatItem? KickCooldown;
internal static OptionStringItem? WhenCheating;
internal static OptionCheckboxItem? InvalidFriendCode;
internal static OptionCheckboxItem? UseBanPlayerList;
@@ -67,6 +68,7 @@ internal static class GameSettingsPatch
if (IsPreload || GameState.IsHost)
{
OptionTitleItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_TextHeader_HostOnly);
BetterGameSettings.KickCooldown = OptionFloatItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_KickCooldown, (0f, 3f, 0.1f), 2f, ("", "s"));
BetterGameSettings.WhenCheating = OptionStringItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_WhenCheating,
[TranslationStrings.BetterSetting_Setting_WhenCheating_Notify, TranslationStrings.BetterSetting_Setting_WhenCheating_Kick, TranslationStrings.BetterSetting_Setting_WhenCheating_Ban], 2);
BetterGameSettings.InvalidFriendCode = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_InvalidFriendCode, true);
+1
View File
@@ -79,6 +79,7 @@
"BetterSetting.TextHeader.HostOnly": "<color=#4f92ff>Host Only</color>",
"BetterSetting.TextHeader.Detections": "<color=#4f92ff>Detections</color>",
"BetterSetting.Setting.KickCooldown": "Kick cooldown",
"BetterSetting.Setting.WhenCheating": "When a player is caught cheating",
"BetterSetting.Setting.WhenCheating.Notify": "Notify",
"BetterSetting.Setting.WhenCheating.Kick": "Kick",
+96 -24
View File
@@ -1,6 +1,7 @@
using AmongUs.GameOptions;
using BetterAmongUs.Data;
using BetterAmongUs.Generated;
using BetterAmongUs.Managers;
using BetterAmongUs.Modules;
using BetterAmongUs.MonoScripts.Extended;
using BetterAmongUs.Patches.Gameplay.Player;
@@ -127,42 +128,113 @@ internal static class PlayerControlUtils
return true;
}
/// <summary>
/// Kicks a player from the game as soon as it is safe to do so.
/// </summary>
/// <param name="player">The player to kick.</param>
/// <param name="ban">Whether to ban the player.</param>
/// <param name="setReasonInfo">Custom reason message for the kick.</param>
/// <param name="antiCheatBan">Whether this is an anti-cheat related kick.</param>
/// <param name="bypassDataCheck">Whether to bypass the data collection check.</param>
/// <param name="forceBan">Whether to force a ban regardless of settings.</param>
internal static void Kick(this PlayerControl player, bool ban = false, string setReasonInfo = "", bool antiCheatBan = false, bool bypassDataCheck = false, bool forceBan = false)
{
if (!player.CanKick(ban, antiCheatBan, bypassDataCheck, forceBan, out var shouldBan)) return;
KickCooldownManager.ScheduleAction(() => { player.PerformKick(shouldBan, setReasonInfo, antiCheatBan); });
}
/// <summary>
/// Kicks a player from the game immediately if it is safe to do so, otherwise does nothing.
/// This should be used instead of <see cref="Kick"/> in places where this method is repeatedly called, like Update methods for example.
/// </summary>
/// <param name="player">The player to kick.</param>
/// <param name="ban">Whether to ban the player.</param>
/// <param name="setReasonInfo">Custom reason message for the kick.</param>
/// <param name="antiCheatBan">Whether this is an anti-cheat related kick.</param>
/// <param name="bypassDataCheck">Whether to bypass the data collection check.</param>
/// <param name="forceBan">Whether to force a ban regardless of settings.</param>
internal static void TryKick(this PlayerControl player, bool ban = false, string setReasonInfo = "", bool antiCheatBan = false, bool bypassDataCheck = false, bool forceBan = false)
{
if (!KickCooldownManager.IsReady()) return;
if (!player.CanKick(ban, antiCheatBan, bypassDataCheck, forceBan, out var shouldBan)) return;
KickCooldownManager.Trigger();
player.PerformKick(shouldBan, setReasonInfo, antiCheatBan);
}
/// <summary>
/// Kicks a player from the game immediately, regardless of cooldown.
/// Only use this if the target player is extremely dangerous and must be removed immediately.
/// </summary>
/// <param name="player">The player to kick.</param>
/// <param name="ban">Whether to ban the player.</param>
/// <param name="setReasonInfo">Custom reason message for the kick.</param>
/// <param name="antiCheatBan">Whether this is an anti-cheat related kick.</param>
/// <param name="bypassDataCheck">Whether to bypass the data collection check.</param>
/// <param name="forceBan">Whether to force a ban regardless of settings.</param>
internal static void KickImmediate(this PlayerControl player, bool ban = false, string setReasonInfo = "", bool antiCheatBan = false, bool bypassDataCheck = false, bool forceBan = false)
{
if (!player.CanKick(ban, antiCheatBan, bypassDataCheck, forceBan, out var shouldBan)) return;
player.PerformKick(shouldBan, setReasonInfo, antiCheatBan);
}
/// <summary>
/// Determines whether the specified player can be kicked from the game and sets the outcome.
/// </summary>
/// <param name="player">The player to evaluate.</param>
/// <param name="ban">Whether to ban the player.</param>
/// <param name="antiCheatBan">Whether this is an anti-cheat related kick.</param>
/// <param name="bypassDataCheck">Whether to bypass the data collection check.</param>
/// <param name="forceBan">Whether to force a ban regardless of settings.</param>
/// <param name="shouldBan">
/// When the method returns, this value indicates whether the player should be banned
/// based on the provided flags and internal checks.
/// </param>
/// <returns><c>true</c> if the player can be kicked/banned, <c>false</c> otherwise.</returns>
private static bool CanKick(this PlayerControl player, bool ban, bool antiCheatBan, bool bypassDataCheck,
bool forceBan, out bool shouldBan)
{
shouldBan = ban || forceBan;
if (!GameState.IsHost || player.IsLocalPlayer() || (!player.DataIsCollected() && !bypassDataCheck) || player.IsHost() || player.isDummy)
return false;
if (forceBan || !antiCheatBan) return true;
return HandleAntiCheatBanCheck(shouldBan, out shouldBan);
}
/// <summary>
/// Determines whether a player should be banned when an anti‑cheat check is performed.
/// </summary>
/// <param name="ban">Whether the player has already been flagged for banning before this method is called.</param>
/// <param name="shouldBan">The output value that indicates whether the player should ultimately be banned.</param>
/// <returns>
/// <c>true</c> if the player can be kicked or banned.<br/>
/// <c>false</c> if <see cref="BetterGameSettings.WhenCheating"/> is set to <c>0</c> (Notify).
/// </returns>
private static bool HandleAntiCheatBanCheck(bool ban, out bool shouldBan)
{
shouldBan = ban && BetterGameSettings.WhenCheating.GetStringIndex() == 2;
return BetterGameSettings.WhenCheating.GetStringIndex() != 0;
}
/// <summary>
/// Kicks a player from the game with optional ban and anti-cheat features.
/// </summary>
/// <param name="player">The player to kick.</param>
/// <param name="ban">Whether to ban the player.</param>
/// <param name="setReasonInfo">Custom reason message for the kick.</param>
/// <param name="AntiCheatBan">Whether this is an anti-cheat related kick.</param>
/// <param name="bypassDataCheck">Whether to bypass the data collection check.</param>
/// <param name="forceBan">Whether to force a ban regardless of settings.</param>
internal static void Kick(this PlayerControl player, bool ban = false, string setReasonInfo = "", bool AntiCheatBan = false, bool bypassDataCheck = false, bool forceBan = false)
/// <param name="antiCheatBan">Whether this is an anti-cheat related kick.</param>
private static void PerformKick(this PlayerControl player, bool ban = false, string setReasonInfo = "", bool antiCheatBan = false)
{
var Ban = ban || forceBan;
if (!GameState.IsHost || player.IsLocalPlayer() || (!player.DataIsCollected() && !bypassDataCheck) || player.IsHost() || player.isDummy)
{
return;
}
if (AntiCheatBan)
{
if (BetterGameSettings.WhenCheating.GetStringIndex() == 0 && !forceBan)
{
return;
}
Ban = (Ban && BetterGameSettings.WhenCheating.GetStringIndex() == 2) || forceBan;
}
if (setReasonInfo != "")
{
PlayerJoinAndLeftPatch.BetterShowNotification(player.Data, forceReasonText: string.Format(setReasonInfo, Ban ? TranslationStrings.AntiCheat_Ban.LocalizedString.ToLower() : TranslationStrings.AntiCheat_Kick.LocalizedString.ToLower()));
PlayerJoinAndLeftPatch.BetterShowNotification(player.Data, forceReasonText: string.Format(setReasonInfo, ban ? TranslationStrings.AntiCheat_Ban.LocalizedString.ToLower() : TranslationStrings.AntiCheat_Kick.LocalizedString.ToLower()));
}
AmongUsClient.Instance.KickPlayer(player.GetClientId(), Ban);
AmongUsClient.Instance.KickPlayer(player.GetClientId(), ban);
player.ExtendedData().AntiCheatInfo.BannedByAntiCheat = AntiCheatBan;
player.ExtendedData().AntiCheatInfo.BannedByAntiCheat = antiCheatBan;
}
/// <summary>
@@ -388,6 +388,11 @@ public static class TranslationStrings
/// </summary>
public static readonly TranslationString BetterSetting_TextHeader_Detections = new("BetterSetting.TextHeader.Detections");
/// <summary>
/// Base Translation: Kick cooldown
/// </summary>
public static readonly TranslationString BetterSetting_Setting_KickCooldown = new("BetterSetting.Setting.KickCooldown");
/// <summary>
/// Base Translation: When a player is caught cheating
/// </summary>