Move to coroutine over latetask

This commit is contained in:
D1GQ committed 2026-06-22 22:54:42 -05:00
1 parent c5cc628454
commit d087619855
7 files changed
+155 -226

No files matched your search

-111
View File
@@ -1,111 +0,0 @@
namespace BetterAmongUs.Modules;
/// <summary>
/// Represents a delayed task that executes after a specified time interval.
/// </summary>
internal sealed class LateTask
{
private readonly Action _action;
private float _remainingTime;
private readonly string _name;
private readonly bool _shouldLog;
private static readonly List<LateTask> Tasks = new();
/// <summary>
/// Initializes a new instance of the LateTask class.
/// </summary>
/// <param name="action">The action to execute after the delay.</param>
/// <param name="delay">The delay in seconds before executing the action.</param>
/// <param name="name">The name of the task for logging purposes.</param>
/// <param name="shouldLog">Whether to log task completion.</param>
private LateTask(Action action, float delay, string name = "Unnamed Task", bool shouldLog = true)
{
_action = action ?? throw new ArgumentNullException(nameof(action));
_remainingTime = delay;
_name = name ?? throw new ArgumentNullException(nameof(name));
_shouldLog = shouldLog;
Tasks.Add(this);
}
/// <summary>
/// Updates the task timer and executes the action if the delay has elapsed.
/// </summary>
/// <param name="deltaTime">The time in seconds since the last update.</param>
/// <returns>True if the task has completed and should be removed, false otherwise.</returns>
private bool Update(float deltaTime)
{
_remainingTime -= deltaTime;
if (_remainingTime > 0)
return false;
try
{
_action.Invoke();
if (_shouldLog)
{
Logger_.Log($"{_name} has finished", nameof(LateTask));
}
return true;
}
catch (Exception ex)
{
Logger_.Error($"Error executing task '{_name}': {ex}");
return true;
}
}
/// <summary>
/// Schedules a new delayed task.
/// </summary>
/// <param name="action">The action to execute after the delay.</param>
/// <param name="delay">The delay in seconds before executing the action.</param>
/// <param name="name">The name of the task for logging purposes.</param>
/// <param name="shouldLog">Whether to log task completion.</param>
internal static void Schedule(Action action, float delay, string name = "Unnamed Task", bool shouldLog = true)
{
_ = new LateTask(action, delay, name, shouldLog);
}
/// <summary>
/// Updates all scheduled tasks with the elapsed time.
/// </summary>
/// <param name="deltaTime">The time in seconds since the last update.</param>
internal static void UpdateAll(float deltaTime)
{
if (Tasks.Count == 0)
return;
var completedTasks = new List<LateTask>(Tasks.Count);
foreach (var task in Tasks.ToArray())
{
if (task.Update(deltaTime))
{
completedTasks.Add(task);
}
}
foreach (var task in completedTasks)
{
Tasks.Remove(task);
}
}
/// <summary>
/// Cancels and removes all scheduled tasks.
/// </summary>
public static void CancelAll()
{
Tasks.Clear();
}
/// <summary>
/// Gets the number of currently active tasks.
/// </summary>
public static int ActiveTaskCount => Tasks.Count;
}
+25 -4
View File
@@ -91,9 +91,15 @@ internal static class ClientPatch
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnGameEnd))]
[HarmonyPrefix]
private static void AmongUsClient_OnGameEnd_Prefix()
private static void AmongUsClient_OnGameEnd_Prefix(AmongUsClient __instance)
{
// Preserve all player GameObjects during scene transitions
__instance.StartCoroutine(CoMovePlayerData());
}
private static IEnumerator CoMovePlayerData()
{
foreach (var data in GameData.Instance.AllPlayers)
{
if (data == null || data.gameObject == null)
@@ -102,8 +108,12 @@ internal static class ClientPatch
UnityEngine.Object.DontDestroyOnLoad(data.gameObject);
}
// Move player GameObjects to active scene after a short delay
LateTask.Schedule(() =>
while (SceneManager.GetActiveScene().name == Constants.ONLINE_SCENE)
{
yield return null;
}
if (SceneManager.GetActiveScene().name == "EndGame")
{
foreach (var data in GameData.Instance.AllPlayers)
{
@@ -112,7 +122,18 @@ internal static class ClientPatch
SceneManager.MoveGameObjectToScene(data.gameObject, SceneManager.GetActiveScene());
}
}, 0.6f, shouldLog: false);
}
else
{
foreach (var data in GameData.Instance.AllPlayers)
{
if (data == null || data.gameObject == null)
continue;
UnityEngine.Object.Destroy(data.gameObject);
}
GameData.Instance.AllPlayers.Clear();
}
}
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.CoStartGame))]
@@ -1,10 +1,9 @@
using BetterAmongUs.Utilities;
using BetterAmongUs.Managers;
using BetterAmongUs.Managers;
using BetterAmongUs.Modules.AntiCheat;
using BetterAmongUs.Modules.Support;
using BetterAmongUs.Utilities;
using HarmonyLib;
using UnityEngine;
using BetterAmongUs.Modules;
namespace BetterAmongUs.Patches.Client.Managers;
@@ -44,7 +43,6 @@ internal static class ModManagerPatch
// Update various BAU systems each frame
BetterAntiCheat.Update();
LateTask.UpdateAll(Time.deltaTime);
BetterNotificationManager.Update();
}
}
@@ -1,11 +1,14 @@
using BetterAmongUs.Data.Config;
using BetterAmongUs.Utilities;
using BepInEx.Unity.IL2CPP.Utils;
using BetterAmongUs.Data.Config;
using BetterAmongUs.Managers;
using BetterAmongUs.Modules;
using BetterAmongUs.Modules.Support;
using BetterAmongUs.Mono.Extended;
using BetterAmongUs.Utilities;
using HarmonyLib;
using InnerNet;
using System.Collections;
using UnityEngine;
namespace BetterAmongUs.Patches.Gameplay.Anticheat;
@@ -24,57 +27,56 @@ internal class PlatformSpoofPatch
if (GameState.IsLobby)
{
try
AmongUsClient.Instance.StartCoroutine(CoPlatformSpecificDataDeserialize(__instance));
}
}
private static IEnumerator CoPlatformSpecificDataDeserialize(PlatformSpecificData __instance)
{
yield return new WaitForSeconds(3.5f);
var player = BAUPlugin.AllPlayerControls.FirstOrDefault(pc => pc.GetClient().PlatformData == __instance);
if (player != null && __instance != null)
{
// Check Xbox/Windows store players for invalid platform ID length
if (__instance.Platform is Platforms.StandaloneWin10 or Platforms.Xbox)
{
LateTask.Schedule(() =>
if (__instance.XboxPlatformId.ToString().Length is < 10 or > 16)
{
var player = BAUPlugin.AllPlayerControls.FirstOrDefault(pc => pc.GetClient().PlatformData == __instance);
// Invalid ID length, likely spoofing
player.ReportPlayer(ReportReasons.Cheating_Hacking);
BetterNotificationManager.NotifyCheat(player,
Translator.GetString("AntiCheat.Reason.PlatformSpoofer"),
Translator.GetString("AntiCheat.HasBeenDetectedWithCheat")
);
Logger_.LogCheat($"{player.ExtendedData().RealName} {Translator.GetString("AntiCheat.PlatformSpoofer")}: {__instance.XboxPlatformId}");
}
}
if (player != null && __instance != null)
{
// Check Xbox/Windows store players for invalid platform ID length
if (__instance.Platform is Platforms.StandaloneWin10 or Platforms.Xbox)
{
if (__instance.XboxPlatformId.ToString().Length is < 10 or > 16)
{
// Invalid ID length, likely spoofing
player.ReportPlayer(ReportReasons.Cheating_Hacking);
BetterNotificationManager.NotifyCheat(player,
Translator.GetString("AntiCheat.Reason.PlatformSpoofer"),
Translator.GetString("AntiCheat.HasBeenDetectedWithCheat")
);
Logger_.LogCheat($"{player.ExtendedData().RealName} {Translator.GetString("AntiCheat.PlatformSpoofer")}: {__instance.XboxPlatformId}");
}
}
// Check Playstation players for invalid platform ID length
if (__instance.Platform is Platforms.Playstation)
{
if (__instance.PsnPlatformId.ToString().Length is < 14 or > 20)
{
// Invalid ID length, likely spoofing
player.ReportPlayer(ReportReasons.Cheating_Hacking);
BetterNotificationManager.NotifyCheat(player,
Translator.GetString("AntiCheat.Reason.PlatformSpoofer"),
Translator.GetString("AntiCheat.HasBeenDetectedWithCheat")
);
Logger_.LogCheat($"{player.ExtendedData().RealName} {Translator.GetString("AntiCheat.PlatformSpoofer")}: {__instance.PsnPlatformId}");
}
}
// Check Playstation players for invalid platform ID length
if (__instance.Platform is Platforms.Playstation)
{
if (__instance.PsnPlatformId.ToString().Length is < 14 or > 20)
{
// Invalid ID length, likely spoofing
player.ReportPlayer(ReportReasons.Cheating_Hacking);
BetterNotificationManager.NotifyCheat(player,
Translator.GetString("AntiCheat.Reason.PlatformSpoofer"),
Translator.GetString("AntiCheat.HasBeenDetectedWithCheat")
);
Logger_.LogCheat($"{player.ExtendedData().RealName} {Translator.GetString("AntiCheat.PlatformSpoofer")}: {__instance.PsnPlatformId}");
}
}
// Check for unknown or undefined platforms
if (__instance.Platform is Platforms.Unknown || !Enum.IsDefined(__instance.Platform))
{
BetterNotificationManager.NotifyCheat(player,
Translator.GetString("AntiCheat.Reason.PlatformSpoofer"),
Translator.GetString("AntiCheat.HasBeenDetectedWithCheat")
);
}
}
}, 3.5f, shouldLog: false);
// Check for unknown or undefined platforms
if (__instance.Platform is Platforms.Unknown || !Enum.IsDefined(__instance.Platform))
{
BetterNotificationManager.NotifyCheat(player,
Translator.GetString("AntiCheat.Reason.PlatformSpoofer"),
Translator.GetString("AntiCheat.HasBeenDetectedWithCheat")
);
}
catch { }
}
}
}
@@ -1,8 +1,11 @@
using BetterAmongUs.Data.Config;
using BetterAmongUs.Utilities;
using BepInEx.Unity.IL2CPP.Utils;
using BetterAmongUs.Data.Config;
using BetterAmongUs.Managers;
using BetterAmongUs.Modules;
using BetterAmongUs.Utilities;
using HarmonyLib;
using System.Collections;
using UnityEngine;
namespace BetterAmongUs.Patches.Gameplay.Managers;
@@ -19,22 +22,24 @@ internal static class HudManagerPatch
[HarmonyPostfix]
private static void HudManager_Start_Postfix(HudManager __instance)
{
// Create custom BAU notification system if it doesn't exist
__instance.StartCoroutine(CoHudManagerStart());
}
private static IEnumerator CoHudManagerStart()
{
BetterNotificationManager.Init();
// Show welcome message after 1 second delay (only once per session)
LateTask.Schedule(() =>
{
if (!HasBeenWelcomed && GameState.IsInGame && GameState.IsLobby && !GameState.IsFreePlay)
{
// Show notification with welcome text
BetterNotificationManager.Notify($"<b><color=#00751f>{string.Format(Translator.GetString("WelcomeMsg.WelcomeToBAU"), Translator.GetString("BetterAmongUs"))}!</color></b>", 8f);
yield return new WaitForSeconds(1f);
// Send detailed welcome message to private chat
Utils.AddChatPrivate(WelcomeMessage, overrideName: " ");
HasBeenWelcomed = true;
}
}, 1f, shouldLog: false);
if (!HasBeenWelcomed && GameState.IsInGame && GameState.IsLobby && !GameState.IsFreePlay)
{
// Show notification with welcome text
BetterNotificationManager.Notify($"<b><color=#00751f>{string.Format(Translator.GetString("WelcomeMsg.WelcomeToBAU"), Translator.GetString("BetterAmongUs"))}!</color></b>", 8f);
// Send detailed welcome message to private chat
Utils.AddChatPrivate(WelcomeMessage, overrideName: " ");
HasBeenWelcomed = true;
}
}
[HarmonyPatch(typeof(HudManager), nameof(HudManager.Update))]
@@ -1,13 +1,15 @@
using BepInEx.Unity.IL2CPP.Utils;
using BetterAmongUs.Data;
using BetterAmongUs.Data.Config;
using BetterAmongUs.Utilities;
using BetterAmongUs.Modules;
using BetterAmongUs.Modules.Support;
using BetterAmongUs.Mono.Extended;
using BetterAmongUs.Patches.Gameplay.UI;
using BetterAmongUs.Patches.Gameplay.UI.Settings;
using BetterAmongUs.Utilities;
using HarmonyLib;
using InnerNet;
using System.Collections;
namespace BetterAmongUs.Patches.Gameplay.Player;
@@ -31,45 +33,52 @@ internal static class PlayerJoinAndLeftPatch
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnPlayerJoined))]
[HarmonyPostfix]
private static void AmongUsClient_OnPlayerJoined_Postfix(ClientData data)
private static void AmongUsClient_OnPlayerJoined_Postfix(AmongUsClient __instance, ClientData data)
{
// Schedule ban list checks 2.5 seconds after player joins
LateTask.Schedule(() =>
if (GameState.IsHost)
{
if (GameState.IsHost)
__instance.StartCoroutine(CoCheckPlayerOnJoin(data));
}
}
private static IEnumerator CoCheckPlayerOnJoin(ClientData data)
{
while (!data.InScene || data.Character == null || data.Character.Data == null || data.Character.Data.IsIncomplete)
{
yield return null;
}
if (GameState.IsInGame)
{
var player = Utils.PlayerFromClientId(data.Id);
// Check if player is in ban list by friend code or PUID
if (BetterGameSettings.UseBanPlayerList.GetBool())
{
if (GameState.IsInGame)
if (player != null)
{
var player = Utils.PlayerFromClientId(data.Id);
// Check if player is in ban list by friend code or PUID
if (BetterGameSettings.UseBanPlayerList.GetBool())
if (TextFileHandler.CompareStringMatch(BetterDataManager.Files.banPlayerListFilePath,
BAUPlugin.AllPlayerControls.Select(player => player.Data.FriendCode)
.Concat(BAUPlugin.AllPlayerControls.Select(player => player.GetHashPuid())).ToArray()))
{
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.Kick(true, Translator.GetString("AntiCheat.BanPlayerListMessage"), bypassDataCheck: true);
}
}
}
// Check if player name matches banned name patterns
if (BetterGameSettings.UseBanNameList.GetBool())
{
if (player != null)
{
if (TextFileHandler.CompareStringFilters(BetterDataManager.Files.banNameListFilePath, [player.Data.PlayerName]))
{
player?.Kick(true, Translator.GetString("AntiCheat.BanPlayerListMessage"), bypassDataCheck: true);
}
}
player.Kick(true, Translator.GetString("AntiCheat.BanPlayerListMessage"), bypassDataCheck: true);
yield break;
}
}
}
}, 2.5f, "OnPlayerJoinedPatch", false);
// Check if player name matches banned name patterns
if (BetterGameSettings.UseBanNameList.GetBool())
{
if (player != null)
{
if (TextFileHandler.CompareStringFilters(BetterDataManager.Files.banNameListFilePath, [player.Data.PlayerName]))
{
player?.Kick(true, Translator.GetString("AntiCheat.BanPlayerListMessage"), bypassDataCheck: true);
}
}
}
}
}
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnPlayerLeft))]
+17 -12
View File
@@ -1,8 +1,10 @@
using AmongUs.Data;
using BepInEx.Unity.IL2CPP.Utils;
using BetterAmongUs.Modules;
using BetterAmongUs.Patches.Gameplay.UI.Chat;
using BetterAmongUs.Utilities.Extension;
using InnerNet;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
@@ -411,21 +413,24 @@ internal static class Utils
/// <param name="showReason">Whether to show the reason in a popup.</param>
internal static void DisconnectSelf(string reason, bool showReason = true)
{
AmongUsClient.Instance.ExitGame(0);
AmongUsClient.Instance.StartCoroutine(CoDisconnectSelf(reason, showReason));
}
LateTask.Schedule(() =>
private static IEnumerator CoDisconnectSelf(string reason, bool showReason = true)
{
AmongUsClient.Instance.ExitGame(DisconnectReasons.ExitGame);
yield return new WaitForSeconds(0.2f);
SceneChanger.ChangeScene(Constants.MAIN_MENU_SCENE);
if (showReason)
{
SceneChanger.ChangeScene("MainMenu");
yield return new WaitForSeconds(0.1f);
if (showReason)
{
LateTask.Schedule(() =>
{
var lines = "<color=#ebbd34>----------------------------------------------------------------------------------------------</color>";
ShowPopUp($"{lines}\n\n\n<size=150%>{reason}</size>\n\n\n{lines}");
}, 0.1f, "DisconnectSelf 2");
}
}, 0.2f, "DisconnectSelf 1");
var lines = "<color=#ebbd34>----------------------------------------------------------------------------------------------</color>";
ShowPopUp($"{lines}\n\n\n<size=150%>{reason}</size>\n\n\n{lines}");
}
}
/// <summary>