mirror of
https://github.com/D1GQ/BetterAmongUs.git
synced 2026-10-19 15:51:52 +00:00
Merge pull request #135 from D1GQ/v3.3.4-dev
V3.3.4 - AU v19 Compatibility
This commit is contained in:
87 files changed
+1340
-920
No files matched your search
@@ -15,7 +15,7 @@ internal abstract class AutoRegisterAttribute : Attribute
|
||||
/// </summary>
|
||||
internal static void Initialize()
|
||||
{
|
||||
var types = ModInfo.Assembly.GetTypes();
|
||||
var types = BAUPlugin.ModInfo.Assembly.GetTypes();
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
@@ -63,7 +63,7 @@ internal abstract class AutoRegisterAttribute<T> : AutoRegisterAttribute where T
|
||||
/// <inheritdoc/>
|
||||
protected override void Register()
|
||||
{
|
||||
var types = ModInfo.Assembly.GetTypes();
|
||||
var types = BAUPlugin.ModInfo.Assembly.GetTypes();
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using BetterAmongUs.Modules;
|
||||
using Il2CppInterop.Runtime.Injection;
|
||||
using Il2CppInterop.Runtime.Injection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BetterAmongUs.Attributes;
|
||||
@@ -21,7 +20,7 @@ internal class RegisterInIl2Cpp(params Type[] interfaces) : Attribute
|
||||
/// </summary>
|
||||
internal static void Initialize()
|
||||
{
|
||||
var types = ModInfo.Assembly.GetTypes();
|
||||
var types = BAUPlugin.ModInfo.Assembly.GetTypes();
|
||||
foreach (var type in types)
|
||||
{
|
||||
var attr = type.GetCustomAttribute<RegisterInIl2Cpp>();
|
||||
@@ -37,7 +36,7 @@ internal class RegisterInIl2Cpp(params Type[] interfaces) : Attribute
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Failed to register {type.Name}: {ex.Message}");
|
||||
BAUPlugin.Logger.Error($"Failed to register {type.Name}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
namespace BetterAmongUs;
|
||||
|
||||
internal partial class BAUPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains constants That are used across BAU.
|
||||
/// </summary>
|
||||
internal static class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Example comment for BanPlayerList file.
|
||||
/// </summary>
|
||||
internal const string BAN_PLAYER_LIST_CONTENT = """
|
||||
// Example ban entries (friend code and/or hashed PUID)
|
||||
// Format: [FriendCode], [HashedPUID]
|
||||
// Example with both:
|
||||
// FriendCode#0000, abc123def456789
|
||||
// Example with just friend code:
|
||||
// FriendCode#0000
|
||||
// Example with just hashed PUID:
|
||||
// , hash123xyz789
|
||||
""";
|
||||
|
||||
/// <summary>
|
||||
/// Example comment for BanNameList file.
|
||||
/// </summary>
|
||||
internal const string BAN_NAME_LIST_CONTENT = """
|
||||
// Example banned player name regex patterns
|
||||
// Each pattern on a new line
|
||||
//
|
||||
// ^TNT$
|
||||
// ^hyde$
|
||||
// ^[\P{IsBasicLatin}\s]+$
|
||||
""";
|
||||
|
||||
/// <summary>
|
||||
/// Example comment for BanChatList file.
|
||||
/// </summary>
|
||||
internal const string BAN_CHAT_LIST_CONTENT = """
|
||||
// Example banned chat message regex patterns
|
||||
// Each pattern on a new line
|
||||
//
|
||||
// (?i)(?<!(?:say|said|don'?t|didn'?t|wr[io]te|\bthe\b|\bat\b).*)(?: |^)sta*r?t*(?:ing|\b)(?!.*ban)
|
||||
// (?i)^go[go]*$");
|
||||
// (?i)ni?gg?(?:a|er)
|
||||
// (?i)sns(?-i).*[A-Z]{6}
|
||||
// [A-Z]{6}.*(?i)sns
|
||||
// (?i)(?:modded|expert|no cooldown) lobby(?-i).*[A-Z]{6}
|
||||
// [A-Z]{6}.*(?i)(?:modded|expert|no cooldown) lobby
|
||||
""";
|
||||
|
||||
/// <summary>
|
||||
/// Legacy example comment for BanNameList file.
|
||||
/// </summary>
|
||||
internal const string BAN_NAME_LIST_CONTENT_LEGACY = """
|
||||
// Example banned player names
|
||||
// Each name on a new line - supports wildcards with **
|
||||
// ** at start and end: contains anywhere
|
||||
// ** at start only: ends with
|
||||
// ** at end only: starts with
|
||||
// No **: exact match (case-insensitive)
|
||||
//
|
||||
// HackerPlayer123
|
||||
// CheaterAccount
|
||||
// **Bot**
|
||||
// **Script
|
||||
// Exploit**
|
||||
// **Cheat**
|
||||
""";
|
||||
|
||||
internal const char ENCRYPTED_LOG_PREFIX = '\u2063';
|
||||
internal const char ENCRYPTED_LOG_POSTFIX = '\u2064';
|
||||
internal const int MAX_CHAT_TEXT = 120;
|
||||
internal const string BAU_CUSTOM_RPC_FLAG = "bau:rpc";
|
||||
internal const string BAU_MODDED_PROTOCOL_FLAG = "bau:flags";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
using Semver;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BetterAmongUs;
|
||||
|
||||
internal partial class BAUPlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains metadata and constants for the BetterAmongUs mod.
|
||||
/// </summary>
|
||||
internal static class ModInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The base version number of the mod in MAJOR.MINOR.PATCH format.
|
||||
/// </summary>
|
||||
internal const string VERSION_NUMBER = "1.3.4";
|
||||
|
||||
/// <summary>
|
||||
/// The beta release number. Increment this for each beta release.
|
||||
/// </summary>
|
||||
internal const string BETA_NUMBER = "0";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full version string for the current build configuration.
|
||||
/// </summary>
|
||||
#if RELEASE
|
||||
internal const string VERSION = VERSION_NUMBER;
|
||||
#elif BETA
|
||||
internal const string VERSION = $"{VERSION_NUMBER}-beta-{BETA_NUMBER}";
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full version string with a v prefix for the current build configuration.
|
||||
/// </summary>
|
||||
internal const string VERSION_STRING = "v" + VERSION;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parsed semantic version of the mod.
|
||||
/// </summary>
|
||||
internal static readonly SemVersion SemVersion = SemVersion.Parse(VERSION);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Git commit hash from assembly metadata.
|
||||
/// </summary>
|
||||
public static string CommitHash = ThisAssembly.Git.Commit;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the build date from assembly metadata.
|
||||
/// </summary>
|
||||
public static string BuildDate = ThisAssembly.Metadata.BuildDate;
|
||||
|
||||
/// <summary>
|
||||
/// The name of BAU.
|
||||
/// </summary>
|
||||
internal const string PLUGIN_NAME = "BetterAmongUs";
|
||||
|
||||
/// <summary>
|
||||
/// The GUID (Globally Unique Identifier) of BAU.
|
||||
/// </summary>
|
||||
internal const string PLUGIN_GUID = "com.d1gq.betteramongus";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of supported Among Us versions.
|
||||
/// </summary>
|
||||
internal static string[] SupportedAmongUsVersions =
|
||||
[
|
||||
"2026.9.29"
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// The GitHub repository URL for BAU.
|
||||
/// </summary>
|
||||
internal const string GITHUB = ThisAssembly.Git.RepositoryUrl;
|
||||
|
||||
/// <summary>
|
||||
/// The Discord invite URL for BAU.
|
||||
/// </summary>
|
||||
internal const string DISCORD = "https://discord.gg/vjYrXpzNAn";
|
||||
|
||||
/// <summary>
|
||||
/// Indicator rather that BAU is running on Starlight for Android.
|
||||
/// </summary>
|
||||
internal static readonly bool Starlight = OperatingSystem.IsAndroid();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves metadata from the assembly attributes.
|
||||
/// </summary>
|
||||
/// <param name="key">The metadata key to retrieve.</param>
|
||||
/// <returns>The metadata value, or an empty string if not found.</returns>
|
||||
private static string GetAssemblyMetadata(string key)
|
||||
{
|
||||
var attribute = Assembly
|
||||
.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||
.FirstOrDefault(a => a.Key == key);
|
||||
|
||||
return attribute?.Value ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The assembly associated to this mod.
|
||||
/// </summary>
|
||||
internal static Assembly Assembly
|
||||
{
|
||||
get
|
||||
{
|
||||
if (field == null)
|
||||
{
|
||||
field = Assembly.GetExecutingAssembly();
|
||||
}
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains constants for Among Us.
|
||||
/// </summary>
|
||||
internal static class AmongUs
|
||||
{
|
||||
/// <summary>
|
||||
/// The process name of the Among Us executable.
|
||||
/// </summary>
|
||||
internal const string PROCESS_NAME = "Among Us.exe";
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
-51
@@ -7,7 +7,6 @@ using BetterAmongUs.Attributes;
|
||||
using BetterAmongUs.Data;
|
||||
using BetterAmongUs.Data.Config;
|
||||
using BetterAmongUs.Data.Json;
|
||||
using BetterAmongUs.Enums;
|
||||
using BetterAmongUs.Managers;
|
||||
using BetterAmongUs.Modules;
|
||||
using BetterAmongUs.Modules.OptionItems;
|
||||
@@ -22,42 +21,10 @@ using UnityEngine.SceneManagement;
|
||||
|
||||
namespace BetterAmongUs;
|
||||
|
||||
[BepInPlugin(ModInfo.PLUGIN_GUID, ModInfo.PLUGIN_NAME, ModInfo.PLUGIN_VERSION)]
|
||||
[BepInPlugin(ModInfo.PLUGIN_GUID, ModInfo.PLUGIN_NAME, ModInfo.VERSION)]
|
||||
[BepInProcess(ModInfo.AmongUs.PROCESS_NAME)]
|
||||
internal class BAUPlugin : BasePlugin
|
||||
internal partial class BAUPlugin : BasePlugin
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the formatted version text for display.
|
||||
/// </summary>
|
||||
/// <param name="newLine">Whether to use newline separation for additional info.</param>
|
||||
/// <returns>Formatted version string.</returns>
|
||||
internal static string GetVersionText(bool newLine = false)
|
||||
{
|
||||
string text = string.Empty;
|
||||
|
||||
string newLineText = newLine ? "\n" : " ";
|
||||
|
||||
switch (ModInfo.ReleaseBuildType)
|
||||
{
|
||||
case ReleaseTypes.Release:
|
||||
text = $"v{BetterAmongUsVersion}";
|
||||
break;
|
||||
case ReleaseTypes.Beta:
|
||||
text = $"v{BetterAmongUsVersion}{newLineText}Beta {ModInfo.BETA_NUM}";
|
||||
break;
|
||||
case ReleaseTypes.Dev:
|
||||
text = $"v{BetterAmongUsVersion}{newLineText}Dev {ModInfo.CommitHash}-{ModInfo.BuildDate}";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (ModInfo.IS_HOTFIX)
|
||||
text += $"{newLineText}Hotfix {ModInfo.HOTFIX_NUM}";
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the BAUPlugin instance.
|
||||
/// </summary>
|
||||
@@ -68,11 +35,6 @@ internal class BAUPlugin : BasePlugin
|
||||
/// </summary>
|
||||
internal static Harmony Harmony { get; } = new Harmony(ModInfo.PLUGIN_GUID);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the BetterAmongUs version string.
|
||||
/// </summary>
|
||||
internal static string BetterAmongUsVersion => ModInfo.PLUGIN_VERSION;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the application version string.
|
||||
/// </summary>
|
||||
@@ -86,7 +48,7 @@ internal class BAUPlugin : BasePlugin
|
||||
/// <summary>
|
||||
/// Gets platform-specific data.
|
||||
/// </summary>
|
||||
internal static PlatformSpecificData PlatformData => Constants.GetPlatformData();
|
||||
internal static PlatformSpecificData PlatformData => global::Constants.GetPlatformData();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of all PlayerControl instances.
|
||||
@@ -108,10 +70,15 @@ internal class BAUPlugin : BasePlugin
|
||||
/// </summary>
|
||||
internal static Vent[] AllVents => UnityEngine.Object.FindObjectsOfType<Vent>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the BAU logger instance.
|
||||
/// </summary>
|
||||
internal static BAULogger Logger { get; private set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the BepInEx logger instance.
|
||||
/// </summary>
|
||||
internal static ManualLogSource? Logger;
|
||||
private static ManualLogSource? _manualLogSource;
|
||||
|
||||
public override void Load()
|
||||
{
|
||||
@@ -138,7 +105,7 @@ internal class BAUPlugin : BasePlugin
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error(ex);
|
||||
Logger.Error(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,14 +130,10 @@ internal class BAUPlugin : BasePlugin
|
||||
OutfitData.Initialize();
|
||||
SceneManager.add_sceneLoaded((Action<Scene, LoadSceneMode>)OnSceneLoaded);
|
||||
|
||||
if (File.Exists(BetterDataManager.Files.logFilePath))
|
||||
File.WriteAllText(BetterDataManager.Files.previousLogFilePath, File.ReadAllText(BetterDataManager.Files.logFilePath));
|
||||
|
||||
File.WriteAllText(BetterDataManager.Files.logFilePath, "");
|
||||
Logger_.Log("Better Among Us successfully loaded!");
|
||||
Logger.Log("Better Among Us successfully loaded!");
|
||||
|
||||
string SupportedVersions = string.Join(" ", ModInfo.SupportedAmongUsVersions);
|
||||
Logger_.Log($"BetterAmongUs {BetterAmongUsVersion}-{ModInfo.BuildDate} - [{AppVersion} --> {SupportedVersions}] {Utils.GetPlatformName(PlatformData.Platform)}");
|
||||
Logger.Log($"BetterAmongUs {ModInfo.VERSION_STRING}-{ModInfo.BuildDate} - [{AppVersion} --> {SupportedVersions}] {Utils.GetPlatformName(PlatformData.Platform)}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -202,13 +165,15 @@ internal class BAUPlugin : BasePlugin
|
||||
/// </summary>
|
||||
private static void SetupConsole()
|
||||
{
|
||||
Encryptor.Initialize();
|
||||
ConsoleManager.CreateConsole();
|
||||
ConsoleManager.ConfigPreventClose.Value = true;
|
||||
if (ConsoleManager.ConfigConsoleEnabled.Value) ConsoleManager.DetachConsole();
|
||||
ConsoleManager.ConfigConsoleEnabled.Value = false;
|
||||
ConsoleManager.SetConsoleTitle("Among Us - BAU Console");
|
||||
Logger = BepInEx.Logging.Logger.CreateLogSource(ModInfo.PLUGIN_GUID);
|
||||
var customLogListener = new CustomLogListener();
|
||||
_manualLogSource = BepInEx.Logging.Logger.CreateLogSource(ModInfo.PLUGIN_GUID);
|
||||
Logger = new BAULogger(_manualLogSource);
|
||||
var customLogListener = new CustomLogListener(Logger);
|
||||
BepInEx.Logging.Logger.Listeners.Add(customLogListener);
|
||||
ConsoleManager.SetConsoleColor(ConsoleColor.Green);
|
||||
ConsoleManager.ConsoleStream.WriteLine($".--------------------------------------------------------------------------------.\r\n| ____ _ _ _ _ _ |\r\n| | __ ) ___| |_| |_ ___ _ __ / \\ _ __ ___ ___ _ __ __ _ | | | |___ |\r\n| | _ \\ / _ \\ __| __/ _ \\ '__| / _ \\ | '_ ` _ \\ / _ \\| '_ \\ / _` | | | | / __||\r\n| | |_) | __/ |_| || __/ | / ___ \\| | | | | | (_) | | | | (_| | | |_| \\__ \\|\r\n| |____/ \\___|\\__|\\__\\___|_| /_/ \\_\\_| |_| |_|\\___/|_| |_|\\__, | \\___/|___/|\r\n| |___/ |\r\n'--------------------------------------------------------------------------------'");
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<OutputType>Library</OutputType>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<Configurations>Debug;Release;Beta</Configurations>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Apply Null Notation Restrictions -->
|
||||
@@ -79,21 +80,25 @@
|
||||
|
||||
<!-- NuGet Core Packages -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2026.8.18" />
|
||||
<PackageReference Include="AmongUs.GameLibs.Steam" Version="2026.9.29" />
|
||||
<PackageReference Include="BepInEx.IL2CPP.MSBuild" Version="2.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="BepInEx.Unity.IL2CPP" Version="6.0.0-be.735" Private="false" ExcludeAssets="runtime;native" />
|
||||
<PackageReference Include="Costura.Fody" Version="5.8.0-alpha0098">
|
||||
<IncludeAssets>runtime; compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- NuGet Info Packages -->
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Semver" Version="3.0.0" />
|
||||
<PackageReference Include="GitInfo" Version="3.3.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
<PackageReference Include="ThisAssembly.Metadata" Version="2.1.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -7,10 +7,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BetterAmongUs", "BetterAmon
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Beta|Any CPU = Beta|Any CPU
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{41193AE4-8181-49F8-9DA4-F4B7B275A0EA}.Beta|Any CPU.ActiveCfg = Beta|Any CPU
|
||||
{41193AE4-8181-49F8-9DA4-F4B7B275A0EA}.Beta|Any CPU.Build.0 = Beta|Any CPU
|
||||
{41193AE4-8181-49F8-9DA4-F4B7B275A0EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{41193AE4-8181-49F8-9DA4-F4B7B275A0EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{41193AE4-8181-49F8-9DA4-F4B7B275A0EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
||||
@@ -36,8 +36,6 @@ internal sealed class PlayerArgument(BaseCommand command, string argInfo = "{pla
|
||||
/// <summary>
|
||||
/// Tries to parse the player argument and find the corresponding PlayerControl.
|
||||
/// </summary>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
internal override bool TryParse(out PlayerControl result)
|
||||
{
|
||||
foreach (var player in BAUPlugin.AllPlayerControls)
|
||||
@@ -59,8 +57,6 @@ internal sealed class PlayerArgument(BaseCommand command, string argInfo = "{pla
|
||||
/// <summary>
|
||||
/// Checks if the given player info matches the argument value.
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
private bool IsMatchingPlayer(NetworkedPlayerInfo data)
|
||||
{
|
||||
return Arg.Equals(data.PlayerName.Replace(' ', '_'), StringComparison.OrdinalIgnoreCase)
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using BetterAmongUs.Utilities;
|
||||
|
||||
namespace BetterAmongUs.Commands.Arguments;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a player command argument.
|
||||
/// </summary>
|
||||
/// <param name="command">The command this argument belongs to.</param>
|
||||
/// <param name="argInfo">Information about the argument (default: "{player}").</param>
|
||||
internal sealed class PlayerInfoArgument(BaseCommand command, string argInfo = "{player}") : BaseArgument<NetworkedPlayerInfo>(command, argInfo)
|
||||
{
|
||||
protected override string[] GetArgSuggestions()
|
||||
{
|
||||
List<string> suggestions = [];
|
||||
var allPlayers = GameData.Instance.AllPlayers;
|
||||
int count = allPlayers.Count;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var playerData = allPlayers[i];
|
||||
if (playerData.IsLocalData())
|
||||
{
|
||||
int insertIndex = suggestions.Count;
|
||||
|
||||
if (!string.IsNullOrEmpty(playerData.PlayerName))
|
||||
suggestions.Insert(insertIndex, playerData.PlayerName.Replace(' ', '_'));
|
||||
|
||||
if (!string.IsNullOrEmpty(playerData.FriendCode))
|
||||
suggestions.Insert(insertIndex + 1, playerData.FriendCode);
|
||||
|
||||
suggestions.Insert(insertIndex + 2, $"ID{playerData.PlayerId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string.IsNullOrEmpty(playerData.PlayerName))
|
||||
suggestions.Add(playerData.PlayerName.Replace(' ', '_'));
|
||||
|
||||
if (!string.IsNullOrEmpty(playerData.FriendCode))
|
||||
suggestions.Add(playerData.FriendCode);
|
||||
|
||||
suggestions.Add($"ID{playerData.PlayerId}");
|
||||
}
|
||||
}
|
||||
|
||||
return [.. suggestions];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to parse the player argument and find the corresponding PlayerControl.
|
||||
/// </summary>
|
||||
internal override bool TryParse(out NetworkedPlayerInfo result)
|
||||
{
|
||||
foreach (var playerData in GameData.Instance.AllPlayers)
|
||||
{
|
||||
if (IsMatchingPlayer(playerData))
|
||||
{
|
||||
result = playerData;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
result = default!;
|
||||
BaseCommand.CommandErrorText("Player not found!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the given player info matches the argument value.
|
||||
/// </summary>
|
||||
private bool IsMatchingPlayer(NetworkedPlayerInfo data)
|
||||
{
|
||||
return Arg.Equals(data.PlayerName.Replace(' ', '_'), StringComparison.OrdinalIgnoreCase)
|
||||
|| Arg.Equals(data.FriendCode, StringComparison.OrdinalIgnoreCase)
|
||||
|| Arg.Equals($"ID{data.PlayerId}", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
+27
-47
@@ -22,56 +22,38 @@ internal sealed class DumpCommand : BaseCommand
|
||||
return base.CanRunCommand(out reason);
|
||||
}
|
||||
|
||||
private static string DecryptLog(string log)
|
||||
{
|
||||
string newLog = string.Empty;
|
||||
string[] logArray = log.Split([Environment.NewLine], StringSplitOptions.None);
|
||||
foreach (string text in logArray)
|
||||
{
|
||||
if (text.Contains("[PrivateLog]"))
|
||||
{
|
||||
newLog += text.Split(':')[0] + ":" + text.Split(':')[1].Replace("[PrivateLog]", "") + ": " + Encryptor.Decrypt(text.Split(':')[2][1..]) + "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog += text + "\n";
|
||||
}
|
||||
}
|
||||
return newLog;
|
||||
}
|
||||
|
||||
internal override void Run()
|
||||
{
|
||||
string logFilePath = BetterDataManager.Files.logFilePath;
|
||||
if (!File.Exists(logFilePath))
|
||||
string bepInExLog = Path.Combine(Paths.BepInExRootPath, "LogOutput.log");
|
||||
if (!File.Exists(bepInExLog))
|
||||
{
|
||||
CommandErrorText("Log file not found!");
|
||||
CommandErrorText("BepInEx log file not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ModInfo.Starlight)
|
||||
if (!BAUPlugin.ModInfo.Starlight)
|
||||
{
|
||||
string log = File.ReadAllText(logFilePath);
|
||||
string newLog = DecryptLog(log);
|
||||
|
||||
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
string logFolderPath = Path.Combine(desktopPath, "BetterLogDumps");
|
||||
string logFolderPath = Path.Combine(desktopPath, "BAULogDumps");
|
||||
|
||||
if (!Directory.Exists(logFolderPath))
|
||||
{
|
||||
Directory.CreateDirectory(logFolderPath);
|
||||
}
|
||||
string logFileName = "log-" + BAUPlugin.GetVersionText().Replace(' ', '-').ToLower() + "-" + DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss") + "-bau" + ".log";
|
||||
string logFile = Path.Combine(logFolderPath, logFileName);
|
||||
File.WriteAllText(logFile, newLog);
|
||||
|
||||
string bepInExLog = Path.Combine(Paths.BepInExRootPath, "LogOutput.log");
|
||||
if (File.Exists(bepInExLog))
|
||||
string log;
|
||||
using (FileStream fileStream = new(bepInExLog, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (StreamReader reader = new(fileStream))
|
||||
{
|
||||
string logFileBepInExeName = "log-" + BAUPlugin.GetVersionText().Replace(' ', '-').ToLower() + "-" + DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss") + "-bepinex" + ".log";
|
||||
string logFileBepInExe = Path.Combine(logFolderPath, logFileBepInExeName);
|
||||
File.Copy(bepInExLog, logFileBepInExe);
|
||||
log = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
string decryptedLog = BAULogger.DecryptLogs(log);
|
||||
|
||||
string logFileName = "log-" + BAUPlugin.ModInfo.VERSION_STRING + "-" + DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss") + "-bepinex" + ".log";
|
||||
string logFilePath_New = Path.Combine(logFolderPath, logFileName);
|
||||
File.WriteAllText(logFilePath_New, decryptedLog);
|
||||
|
||||
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo()
|
||||
{
|
||||
FileName = logFolderPath,
|
||||
@@ -84,27 +66,25 @@ internal sealed class DumpCommand : BaseCommand
|
||||
else
|
||||
{
|
||||
string dataPath = BetterDataManager.Folders.fileFolderPath;
|
||||
string logFolderPath = Path.Combine(dataPath, "BetterLogDumps");
|
||||
string logFolderPath = Path.Combine(dataPath, "BAULogDumps");
|
||||
if (!Directory.Exists(logFolderPath))
|
||||
{
|
||||
Directory.CreateDirectory(logFolderPath);
|
||||
}
|
||||
|
||||
string androidLogContent = File.ReadAllText(logFilePath);
|
||||
string androidNewLog = DecryptLog(androidLogContent);
|
||||
|
||||
string androidLogFileName = "log-" + BAUPlugin.GetVersionText().Replace(' ', '-').ToLower() + "-" + DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss") + "-bau" + ".log";
|
||||
string androidNewLogFilePath = Path.Combine(logFolderPath, androidLogFileName);
|
||||
File.WriteAllText(androidNewLogFilePath, androidNewLog);
|
||||
|
||||
string bepInExLog = Path.Combine(Paths.BepInExRootPath, "LogOutput.log");
|
||||
if (File.Exists(bepInExLog))
|
||||
string log;
|
||||
using (FileStream fileStream = new(bepInExLog, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (StreamReader reader = new(fileStream))
|
||||
{
|
||||
string logFileBepInExeName = "log-" + BAUPlugin.GetVersionText().Replace(' ', '-').ToLower() + "-" + DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss") + "-bepinex" + ".log";
|
||||
string logFileBepInExe = Path.Combine(logFolderPath, logFileBepInExeName);
|
||||
File.Copy(bepInExLog, logFileBepInExe);
|
||||
log = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
string decryptedLog = BAULogger.DecryptLogs(log);
|
||||
|
||||
string logFileName = "log-" + BAUPlugin.ModInfo.VERSION_STRING + "-" + DateTime.Now.ToString("yyyy.MM.dd-HH.mm.ss") + "-bepinex" + ".log";
|
||||
string logFilePath_New = Path.Combine(logFolderPath, logFileName);
|
||||
File.WriteAllText(logFilePath_New, decryptedLog);
|
||||
|
||||
CommandResultText($"Dump logs at <color=#b1b1b1>'{logFolderPath}'</color>");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,29 +13,33 @@ internal sealed class PlayerInfoCommand : BaseCommand
|
||||
|
||||
public PlayerInfoCommand()
|
||||
{
|
||||
_playerArgument = new PlayerArgument(this);
|
||||
_playerArgument = new PlayerInfoArgument(this);
|
||||
Arguments = [_playerArgument];
|
||||
}
|
||||
private readonly PlayerArgument _playerArgument;
|
||||
private readonly PlayerInfoArgument _playerArgument;
|
||||
|
||||
internal override void Run()
|
||||
{
|
||||
if (!_playerArgument.TryParse(out var player))
|
||||
if (!_playerArgument.TryParse(out var playerData))
|
||||
return;
|
||||
|
||||
if (player.Data == null)
|
||||
if (playerData == null)
|
||||
return;
|
||||
|
||||
StringBuilder sb = new();
|
||||
var hexColor = Utils.Color32ToHex(Palette.PlayerColors[player.CurrentOutfit.ColorId]);
|
||||
var hexColor = Utils.Color32ToHex(Palette.PlayerColors[playerData.DefaultOutfit.ColorId]);
|
||||
var format1 = "┌ •";
|
||||
var format2 = "├ •";
|
||||
var format3 = "└ •";
|
||||
sb.Append($"<size=150%><color={hexColor}><b>{player.Data.PlayerName}</color> Info:</b></size>\n");
|
||||
sb.Append($"{format1} <color=#c1c1c1>ID: {player.Data.PlayerId}</color>\n");
|
||||
sb.Append($"{format2} <color=#c1c1c1>HashPUID: {Utils.GetHashStr($"{player.Data.Puid}")}</color>\n");
|
||||
sb.Append($"{format2} <color=#c1c1c1>Platform: {Utils.GetPlatformName(player)}</color>\n");
|
||||
sb.Append($"{format3} <color=#c1c1c1>FriendCode: {player.Data.FriendCode}</color>");
|
||||
sb.Append($"<size=150%><color={hexColor}><b>{playerData.PlayerName}</color> Info:</b></size>\n");
|
||||
sb.Append($"{format1} <color=#c1c1c1>ID: {playerData.PlayerId}</color>\n");
|
||||
sb.Append($"{format2} <color=#c1c1c1>HashPUID: {Utils.GetHashStr($"{playerData.Puid}")}</color>\n");
|
||||
var client = Utils.ClientFromClientId(playerData.ClientId);
|
||||
if (client != null)
|
||||
{
|
||||
sb.Append($"{format2} <color=#c1c1c1>Platform: {Utils.GetPlatformName(client.PlatformData.Platform)}</color>\n");
|
||||
}
|
||||
sb.Append($"{format3} <color=#c1c1c1>FriendCode: {playerData.FriendCode}</color>");
|
||||
CommandResultText(sb.ToString());
|
||||
}
|
||||
}
|
||||
@@ -16,9 +16,7 @@ internal sealed class RemovePlayerCommand : BaseCommand
|
||||
_identifierArgument = new StringArgument(this, "{identifier}")
|
||||
{
|
||||
ArgSuggestions = () =>
|
||||
BetterDataManager.Files.BetterDataFile.AllCheatData
|
||||
.SelectMany(info => new[] { info.HashPuid.Replace(' ', '_'), info.FriendCode.Replace(' ', '_'), info.PlayerName.Replace(' ', '_') })
|
||||
.ToArray()
|
||||
[.. BetterDataManager.Files.BetterDataFile.AllCheatData.SelectMany(info => new[] { info.HashPuid.Replace(' ', '_'), info.FriendCode.Replace(' ', '_'), info.PlayerName.Replace(' ', '_') })]
|
||||
};
|
||||
Arguments = [_identifierArgument];
|
||||
}
|
||||
|
||||
+162
-66
@@ -1,6 +1,7 @@
|
||||
using BetterAmongUs.Data.Config;
|
||||
using BetterAmongUs.Data.Json;
|
||||
using BetterAmongUs.Utilities;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BetterAmongUs.Data;
|
||||
@@ -64,12 +65,12 @@ internal static class BetterDataManager
|
||||
/// <summary>
|
||||
/// The log file path.
|
||||
/// </summary>
|
||||
internal static readonly string logFilePath = Path.Combine(Folders.fileFolderPath, "better-log.txt");
|
||||
internal static readonly string logFilePath_Legacy = Path.Combine(Folders.fileFolderPath, "better-log.txt");
|
||||
|
||||
/// <summary>
|
||||
/// The previous log file path.
|
||||
/// </summary>
|
||||
internal static readonly string previousLogFilePath = Path.Combine(Folders.fileFolderPath, "better-previous-log.txt");
|
||||
internal static readonly string previousLogFilePath_Legacy = Path.Combine(Folders.fileFolderPath, "better-previous-log.txt");
|
||||
|
||||
/// <summary>
|
||||
/// Legacy data file path (BetterData.json).
|
||||
@@ -102,9 +103,14 @@ internal static class BetterDataManager
|
||||
internal static readonly string banNameListFilePath = Path.Combine(Folders.saveInfoFolderPath, "BanNameList.txt");
|
||||
|
||||
/// <summary>
|
||||
/// File containing banned words/patterns.
|
||||
/// Legacy file containing banned words/patterns.
|
||||
/// </summary>
|
||||
internal static readonly string banWordListFilePath = Path.Combine(Folders.saveInfoFolderPath, "BanWordList.txt");
|
||||
internal static readonly string banWordListFilePath_Legacy = Path.Combine(Folders.saveInfoFolderPath, "BanWordList.txt");
|
||||
|
||||
/// <summary>
|
||||
/// File containing banned chat messages/patterns.
|
||||
/// </summary>
|
||||
internal static readonly string banChatListFilePath = Path.Combine(Folders.saveInfoFolderPath, "BanChatList.txt");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -114,7 +120,7 @@ internal static class BetterDataManager
|
||||
[
|
||||
Files.banPlayerListFilePath,
|
||||
Files.banNameListFilePath,
|
||||
Files.banWordListFilePath
|
||||
Files.banChatListFilePath
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
@@ -123,7 +129,7 @@ internal static class BetterDataManager
|
||||
/// <returns>The game installation path string.</returns>
|
||||
internal static string GetPathToAmongUs()
|
||||
{
|
||||
if (!ModInfo.Starlight)
|
||||
if (!BAUPlugin.ModInfo.Starlight)
|
||||
{
|
||||
return Path.GetDirectoryName(Application.dataPath) ?? throw new Exception("Unable to find `Application.dataPath` path!");
|
||||
}
|
||||
@@ -148,7 +154,7 @@ internal static class BetterDataManager
|
||||
/// <returns>The persistent data path string.</returns>
|
||||
internal static string GetPathToAmongUsData()
|
||||
{
|
||||
if (!ModInfo.Starlight)
|
||||
if (!BAUPlugin.ModInfo.Starlight)
|
||||
{
|
||||
return Application.persistentDataPath;
|
||||
}
|
||||
@@ -169,63 +175,26 @@ internal static class BetterDataManager
|
||||
|
||||
foreach (var path in InitPaths)
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
var directory = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
if (File.Exists(path)) continue;
|
||||
|
||||
using var writer = File.CreateText(path);
|
||||
if (path == Files.banPlayerListFilePath)
|
||||
{
|
||||
writer.WriteLine("// Example ban entries (friend code and/or hashed PUID)");
|
||||
writer.WriteLine("// Format: [FriendCode], [HashedPUID]");
|
||||
writer.WriteLine("// Example with both:");
|
||||
writer.WriteLine("// FriendCode#0000, abc123def456789");
|
||||
writer.WriteLine("// Example with just friend code:");
|
||||
writer.WriteLine("// FriendCode#0000");
|
||||
writer.WriteLine("// Example with just hashed PUID:");
|
||||
writer.WriteLine("// , hash123xyz789");
|
||||
}
|
||||
else if (path == Files.banNameListFilePath)
|
||||
{
|
||||
writer.WriteLine("// Example banned player names");
|
||||
writer.WriteLine("// Each name on a new line - supports wildcards with **");
|
||||
writer.WriteLine("// ** at start and end: contains anywhere");
|
||||
writer.WriteLine("// ** at start only: ends with");
|
||||
writer.WriteLine("// ** at end only: starts with");
|
||||
writer.WriteLine("// No **: exact match (case-insensitive)");
|
||||
writer.WriteLine("// ");
|
||||
writer.WriteLine("// HackerPlayer123");
|
||||
writer.WriteLine("// CheaterAccount");
|
||||
writer.WriteLine("// **Bot**");
|
||||
writer.WriteLine("// **Script");
|
||||
writer.WriteLine("// Exploit**");
|
||||
writer.WriteLine("// **Cheat**");
|
||||
}
|
||||
else if (path == Files.banWordListFilePath)
|
||||
{
|
||||
writer.WriteLine("// Example banned words/patterns");
|
||||
writer.WriteLine("// Each word or pattern on a new line - supports wildcards with **");
|
||||
writer.WriteLine("// ** at start and end: contains anywhere");
|
||||
writer.WriteLine("// ** at start only: ends with");
|
||||
writer.WriteLine("// ** at end only: starts with");
|
||||
writer.WriteLine("// No **: exact match (case-insensitive)");
|
||||
writer.WriteLine("// ");
|
||||
writer.WriteLine("// hack");
|
||||
writer.WriteLine("// cheat");
|
||||
writer.WriteLine("// exploit");
|
||||
writer.WriteLine("// **bot**");
|
||||
writer.WriteLine("// **script**");
|
||||
writer.WriteLine("// modded");
|
||||
writer.WriteLine("// aimbot");
|
||||
writer.WriteLine("// wallhack");
|
||||
writer.WriteLine("// **hack**");
|
||||
writer.WriteLine("// **cheat**");
|
||||
writer.WriteLine("// speed**");
|
||||
}
|
||||
var directory = Path.GetDirectoryName(path);
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
using var writer = File.CreateText(path);
|
||||
if (path == Files.banPlayerListFilePath)
|
||||
{
|
||||
writer.WriteLine(BAUPlugin.Constants.BAN_PLAYER_LIST_CONTENT);
|
||||
}
|
||||
else if (path == Files.banNameListFilePath)
|
||||
{
|
||||
writer.WriteLine(BAUPlugin.Constants.BAN_NAME_LIST_CONTENT);
|
||||
}
|
||||
else if (path == Files.banChatListFilePath)
|
||||
{
|
||||
writer.WriteLine(BAUPlugin.Constants.BAN_CHAT_LIST_CONTENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -235,16 +204,143 @@ internal static class BetterDataManager
|
||||
/// </summary>
|
||||
private static void LoadLegacyData()
|
||||
{
|
||||
if (File.Exists(Files.logFilePath_Legacy))
|
||||
{
|
||||
File.Delete(Files.logFilePath_Legacy);
|
||||
}
|
||||
|
||||
if (File.Exists(Files.previousLogFilePath_Legacy))
|
||||
{
|
||||
File.Delete(Files.previousLogFilePath_Legacy);
|
||||
}
|
||||
|
||||
if (File.Exists(Files.settingsFilePath_Legacy))
|
||||
{
|
||||
BAUConfigs.SettingsPreset.Value = 1;
|
||||
File.Move(Files.settingsFilePath_Legacy, Files.SettingsFilePath);
|
||||
if (File.Exists(Files.SettingsFilePath))
|
||||
{
|
||||
File.Delete(Files.settingsFilePath_Legacy);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.Move(Files.settingsFilePath_Legacy, Files.SettingsFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (File.Exists(Files.dataFilePath_Legacy))
|
||||
{
|
||||
File.Move(Files.dataFilePath_Legacy, Files.dataFilePath);
|
||||
if (File.Exists(Files.dataFilePath))
|
||||
{
|
||||
File.Delete(Files.dataFilePath_Legacy);
|
||||
}
|
||||
else
|
||||
{
|
||||
File.Move(Files.dataFilePath_Legacy, Files.dataFilePath);
|
||||
}
|
||||
}
|
||||
|
||||
HandleMigrationFromWildcardToRegex();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs data migration from legacy wildcard‑based ban lists to the new regex‑based format.
|
||||
/// </summary>
|
||||
private static void HandleMigrationFromWildcardToRegex()
|
||||
{
|
||||
MigrateBanWordList();
|
||||
MigrateBanNameList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migrates the legacy wildcard‑based BanWordList to the new regex-based BanChatList.
|
||||
/// </summary>
|
||||
private static void MigrateBanWordList()
|
||||
{
|
||||
if (!File.Exists(Files.banWordListFilePath_Legacy)) return;
|
||||
|
||||
var content = File.ReadLines(Files.banWordListFilePath_Legacy)
|
||||
.Where(line =>
|
||||
!string.IsNullOrWhiteSpace(line) &&
|
||||
!line.StartsWith("//") &&
|
||||
!line.StartsWith("#")
|
||||
).ToArray();
|
||||
|
||||
if (content.Any())
|
||||
{
|
||||
using var writer = File.CreateText(Files.banChatListFilePath);
|
||||
writer.WriteLine(BAUPlugin.Constants.BAN_CHAT_LIST_CONTENT);
|
||||
writer.WriteLine();
|
||||
writer.WriteLine("// Your old wildcard based filters have been converted to regex patterns");
|
||||
writer.WriteLine("// They will behave exactly the same as before");
|
||||
writer.WriteLine("// You can keep using them without changing anything else");
|
||||
writer.WriteLine();
|
||||
foreach (var line in content)
|
||||
{
|
||||
writer.Write("(?i)(?: |^)");
|
||||
if (line.StartsWith("**")) writer.Write(".*");
|
||||
writer.Write(Regex.Escape(line.Trim('*')));
|
||||
if (line.EndsWith("**")) writer.Write(".*");
|
||||
writer.WriteLine("(?: |$)");
|
||||
}
|
||||
}
|
||||
File.Delete(Files.banWordListFilePath_Legacy);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Migrates the BanNameList from the legacy wildcard format to the current regex‑based format.
|
||||
/// </summary>
|
||||
private static void MigrateBanNameList()
|
||||
{
|
||||
if (!File.Exists(Files.banNameListFilePath)) return;
|
||||
|
||||
var lines = File.ReadLines(Files.banNameListFilePath)
|
||||
.Where(line => line != "// ")
|
||||
.ToArray();
|
||||
|
||||
// Return if file contains new example comment
|
||||
if (lines.AnyLineInContentLines(BAUPlugin.Constants.BAN_NAME_LIST_CONTENT))
|
||||
return;
|
||||
|
||||
var content = lines.Where(line =>
|
||||
!string.IsNullOrWhiteSpace(line) &&
|
||||
!line.StartsWith("//") &&
|
||||
!line.StartsWith("#")
|
||||
).ToArray();
|
||||
|
||||
if (!content.Any())
|
||||
{
|
||||
File.Delete(Files.banNameListFilePath);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!content.Any(s => Regex.IsMatch(s, @"\*\*")) &&
|
||||
!lines.AnyLineInContentLines(BAUPlugin.Constants.BAN_NAME_LIST_CONTENT_LEGACY)) return;
|
||||
|
||||
using var writer = File.CreateText(Files.banNameListFilePath);
|
||||
writer.WriteLine(BAUPlugin.Constants.BAN_NAME_LIST_CONTENT);
|
||||
writer.WriteLine();
|
||||
writer.WriteLine("// Your old wildcard based filters have been converted to regex patterns");
|
||||
writer.WriteLine("// They will behave exactly the same as before");
|
||||
writer.WriteLine("// You can keep using them without changing anything else");
|
||||
writer.WriteLine();
|
||||
foreach (var line in content)
|
||||
{
|
||||
writer.Write("(?i)");
|
||||
if (!line.StartsWith("**")) writer.Write("^");
|
||||
writer.Write(Regex.Escape(line.Trim('*')));
|
||||
if (!line.EndsWith("**")) writer.Write("$");
|
||||
writer.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether any line from the supplied array matches a line in the specified content string.
|
||||
/// </summary>
|
||||
/// <param name="lines">An array of strings to search.</param>
|
||||
/// <param name="content">A multi‑line string whose individual lines are compared against <paramref name="lines"/>.</param>
|
||||
/// <returns><c>true</c> if at least one line from <paramref name="lines"/> equals any line in <paramref name="content"/>, <c>false</c> otherwise.</returns>
|
||||
private static bool AnyLineInContentLines(this string[] lines, string content)
|
||||
{
|
||||
return content.Split(Environment.NewLine).Any(lines.Contains);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -63,11 +63,21 @@ internal static class BAUConfigs
|
||||
/// </summary>
|
||||
internal static BAUConfigEntry<bool> MinimapIcons { get; } = new("Better Options", "MinimapIcons", true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration entry for new minimap colors setting.
|
||||
/// </summary>
|
||||
internal static BAUConfigEntry<bool> BetterMinimapColors { get; } = new("Better Options", "BetterMinimapColors", true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration entry for vent color groups setting.
|
||||
/// </summary>
|
||||
internal static BAUConfigEntry<bool> VentColorGroups { get; } = new("Better Options", "VentColorGroups", true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration entry for better color blind text setting.
|
||||
/// </summary>
|
||||
internal static BAUConfigEntry<bool> BetterColorblindText { get; } = new("Better Options", "BetterColorblindText", true);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration entry for compress settings file setting.
|
||||
/// </summary>
|
||||
|
||||
@@ -80,7 +80,7 @@ internal abstract class AbstractJsonFile
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error(ex);
|
||||
BAUPlugin.Logger.Error(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ internal abstract class AbstractJsonFile
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error(ex);
|
||||
BAUPlugin.Logger.Error(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ internal sealed class BetterGameSettingsFile : AbstractJsonFile
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Failed to convert JSON element for key {kvp.Key}: {ex.Message}");
|
||||
BAUPlugin.Logger.Error($"Failed to convert JSON element for key {kvp.Key}: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ internal sealed class AppearReplayEvent : IReplayEvent<AppearReplayEvent.AppearR
|
||||
EventData = new AppearReplayData(args.Player.PlayerId, args.Animate);
|
||||
}
|
||||
|
||||
internal record AppearReplayData(int PlayerId, bool Animate) : IReplayEvent.Data;
|
||||
internal record AppearReplayData(byte PlayerId, bool Animate) : IReplayEvent.Data;
|
||||
|
||||
internal record AppearReplayArgs(PlayerControl Player, bool Animate) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -37,7 +37,7 @@ internal sealed class ChatEvent : IReplayEvent<ChatEvent.ChatReplayData, ChatEve
|
||||
EventData = new ChatReplayData(args.Player.PlayerId, args.Message);
|
||||
}
|
||||
|
||||
internal record ChatReplayData(int PlayerId, string Message) : IReplayEvent.Data;
|
||||
internal record ChatReplayData(byte PlayerId, string Message) : IReplayEvent.Data;
|
||||
|
||||
internal record ChatReplayArgs(PlayerControl Player, string Message) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -37,7 +37,7 @@ internal sealed class ChatNoteEvent : IReplayEvent<ChatNoteEvent.ChatNoteReplayD
|
||||
EventData = new ChatNoteReplayData(args.Player.PlayerId, (int)args.NoteType);
|
||||
}
|
||||
|
||||
internal record ChatNoteReplayData(int PlayerId, int NoteType) : IReplayEvent.Data;
|
||||
internal record ChatNoteReplayData(byte PlayerId, int NoteType) : IReplayEvent.Data;
|
||||
|
||||
internal record ChatNoteReplayArgs(PlayerControl Player, ChatNoteTypes NoteType) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -35,7 +35,7 @@ internal sealed class MurderReplayEvent : IReplayEvent<MurderReplayEvent.MurderR
|
||||
EventData = new MurderReplayData(murderReplayArgs.Killer.PlayerId, murderReplayArgs.Target.PlayerId);
|
||||
}
|
||||
|
||||
internal record MurderReplayData(int KillerId, int TargetId) : IReplayEvent.Data;
|
||||
internal record MurderReplayData(byte KillerId, byte TargetId) : IReplayEvent.Data;
|
||||
|
||||
internal record MurderReplayArgs(PlayerControl Killer, PlayerControl Target) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -42,7 +42,7 @@ internal sealed class ProtectReplayEvent : IReplayEvent<ProtectReplayEvent.Prote
|
||||
EventData = new ProtectReplayData(args.Player.PlayerId, args.Target.PlayerId);
|
||||
}
|
||||
|
||||
internal record ProtectReplayData(int PlayerId, int TargetId) : IReplayEvent.Data;
|
||||
internal record ProtectReplayData(byte PlayerId, byte TargetId) : IReplayEvent.Data;
|
||||
|
||||
internal record ProtectReplayArgs(PlayerControl Player, PlayerControl Target) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ internal sealed class ProtectedReplayEvent : IReplayEvent<ProtectedReplayEvent.P
|
||||
EventData = new ProtectedReplayData(args.Killer.PlayerId, args.Target.PlayerId);
|
||||
}
|
||||
|
||||
internal record ProtectedReplayData(int KillerId, int TargetId) : IReplayEvent.Data;
|
||||
internal record ProtectedReplayData(byte KillerId, byte TargetId) : IReplayEvent.Data;
|
||||
|
||||
internal record ProtectedReplayArgs(PlayerControl Killer, PlayerControl Target) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -36,7 +36,7 @@ internal sealed class SetRoleEvent : IReplayEvent<SetRoleEvent.SetRoleReplayData
|
||||
EventData = new SetRoleReplayData(args.Player.PlayerId, (int)args.RoleType);
|
||||
}
|
||||
|
||||
internal record SetRoleReplayData(int PlayerId, int RoleType) : IReplayEvent.Data;
|
||||
internal record SetRoleReplayData(byte PlayerId, int RoleType) : IReplayEvent.Data;
|
||||
|
||||
internal record SetRoleReplayArgs(PlayerControl Player, RoleTypes RoleType) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -42,7 +42,7 @@ internal sealed class ShapeshiftReplayEvent : IReplayEvent<ShapeshiftReplayEvent
|
||||
EventData = new ShapeshiftReplayData(args.Player.PlayerId, args.Target.PlayerId, args.Animate);
|
||||
}
|
||||
|
||||
internal record ShapeshiftReplayData(int PlayerId, int TargetId, bool Animate) : IReplayEvent.Data;
|
||||
internal record ShapeshiftReplayData(byte PlayerId, byte TargetId, bool Animate) : IReplayEvent.Data;
|
||||
|
||||
internal record ShapeshiftReplayArgs(PlayerControl Player, PlayerControl Target, bool Animate) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -37,7 +37,7 @@ internal sealed class UpdateSystemReplayEvent : IReplayEvent<UpdateSystemReplayE
|
||||
EventData = new UpdateSystemReplayData(checked((byte)args.System), args.Player.PlayerId, args.Amount);
|
||||
}
|
||||
|
||||
internal record UpdateSystemReplayData(byte SystemType, int PlayerId, byte Amount) : IReplayEvent.Data;
|
||||
internal record UpdateSystemReplayData(byte SystemType, byte PlayerId, byte Amount) : IReplayEvent.Data;
|
||||
|
||||
internal record UpdateSystemReplayArgs(SystemTypes System, PlayerControl Player, byte Amount) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -38,7 +38,7 @@ internal sealed class VanishReplayEvent : IReplayEvent<VanishReplayEvent.VanishR
|
||||
EventData = new VanishReplayData(args.Player.PlayerId);
|
||||
}
|
||||
|
||||
internal record VanishReplayData(int PlayerId) : IReplayEvent.Data;
|
||||
internal record VanishReplayData(byte PlayerId) : IReplayEvent.Data;
|
||||
|
||||
internal record VanishReplayArgs(PlayerControl Player) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -45,7 +45,7 @@ internal sealed class VentReplayEvent : IReplayEvent<VentReplayEvent.VentReplayD
|
||||
EventData = new VentReplayData(args.Player.PlayerId, args.Exit, args.VentId);
|
||||
}
|
||||
|
||||
internal record VentReplayData(int PlayerId, bool Exit, int VentId) : IReplayEvent.Data;
|
||||
internal record VentReplayData(byte PlayerId, bool Exit, int VentId) : IReplayEvent.Data;
|
||||
|
||||
internal record VentReplayArgs(PlayerControl Player, bool Exit, int VentId) : IReplayEvent.Args;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ internal sealed class SharedSecretExchange
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error("ECDH unavailable, using fallback handshake: " + ex.Message, logConsole: false);
|
||||
BAUPlugin.Logger.Error("ECDH unavailable, using fallback handshake: " + ex.Message, logConsole: false);
|
||||
cryptoDisabled = true;
|
||||
dh = null;
|
||||
publicKey = [];
|
||||
@@ -129,7 +129,7 @@ internal sealed class SharedSecretExchange
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error("Error generating shared secret: " + ex.Message, logConsole: false);
|
||||
BAUPlugin.Logger.Error("Error generating shared secret: " + ex.Message, logConsole: false);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace BetterAmongUs.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// Represents custom platform identifiers.
|
||||
/// </summary>
|
||||
internal enum CustomPlatforms
|
||||
{
|
||||
/// <summary>
|
||||
/// Starlight.
|
||||
/// </summary>
|
||||
Starlight = 112
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<!-- FodyWeavers.xml -->
|
||||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
|
||||
<Costura>
|
||||
<IncludeAssemblies>
|
||||
Semver
|
||||
</IncludeAssemblies>
|
||||
</Costura>
|
||||
</Weavers>
|
||||
@@ -0,0 +1,141 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
|
||||
<xs:element name="Weavers">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element name="Costura" minOccurs="0" maxOccurs="1">
|
||||
<xs:complexType>
|
||||
<xs:all>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="IncludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="ExcludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="IncludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged32Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="Unmanaged64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
<xs:element minOccurs="0" maxOccurs="1" name="PreloadOrder" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The order of preloaded assemblies, delimited with line breaks.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="CreateTemporaryAssemblies" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeDebugSymbols" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls if .pdbs for reference assemblies are also embedded.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeRuntimeReferences" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls if runtime assemblies are also embedded.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="UseRuntimeReferencePaths" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Controls whether the runtime assemblies are embedded with their full path or only with their assembly name.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="DisableCompression" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="DisableCleanup" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="LoadAtModuleInit" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IgnoreSatelliteAssemblies" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="ExcludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="ExcludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with |</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="IncludeRuntimeAssemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Unmanaged32Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 32 bit assembly names to include, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="Unmanaged64Assemblies" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A list of unmanaged 64 bit assembly names to include, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="PreloadOrder" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>The order of preloaded assemblies, delimited with |.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:all>
|
||||
<xs:attribute name="VerifyAssembly" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="GenerateXsd" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@@ -1,13 +1,13 @@
|
||||
using BepInEx.Unity.IL2CPP.Utils;
|
||||
using BetterAmongUs.Attributes;
|
||||
using BetterAmongUs.Utilities;
|
||||
using BetterAmongUs.Modules.Support;
|
||||
using BetterAmongUs.Network.Loaders;
|
||||
using BetterAmongUs.Utilities;
|
||||
using BetterAmongUs.Utilities.Extension;
|
||||
using Il2CppInterop.Runtime.Attributes;
|
||||
using System.Collections;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using BetterAmongUs.Utilities.Extension;
|
||||
|
||||
namespace BetterAmongUs.Managers;
|
||||
|
||||
@@ -93,7 +93,7 @@ internal sealed class BAUUpdateManager : MonoBehaviour
|
||||
|
||||
private void Start()
|
||||
{
|
||||
var oldDll = ModInfo.Assembly.Location + ".old";
|
||||
var oldDll = BAUPlugin.ModInfo.Assembly.Location + ".old";
|
||||
if (File.Exists(oldDll))
|
||||
{
|
||||
File.Delete(oldDll);
|
||||
|
||||
@@ -172,8 +172,8 @@ internal static class BetterNotificationManager
|
||||
Notify(text, time: 8f);
|
||||
}
|
||||
|
||||
Logger_.LogCheat($"{player.cosmetics.nameText.text} Info: {player.Data.PlayerName} - {player.Data.FriendCode} - {player.GetHashPuid()}");
|
||||
Logger_.LogCheat(Utils.RemoveHtmlText(rawText));
|
||||
BAUPlugin.Logger.LogCheat($"{player.cosmetics.nameText.text} Info: {player.Data.PlayerName} - {player.Data.FriendCode} - {player.GetHashPuid()}");
|
||||
BAUPlugin.Logger.LogCheat(Utils.RemoveHtmlText(rawText));
|
||||
|
||||
if (GameState.IsHost && kickPlayer)
|
||||
{
|
||||
|
||||
@@ -41,7 +41,7 @@ internal static class NetworkManager
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error(ex, "NetworkManager");
|
||||
BAUPlugin.Logger.Error(ex, "NetworkManager");
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -414,7 +414,7 @@ internal static class NetworkManager
|
||||
/// </summary>
|
||||
private static void HandleInvalidTag(MessageReader reader)
|
||||
{
|
||||
Logger_.Warning($"Bad tag {reader.Tag} at {reader.Offset}+{reader.Position}={reader.Length}: " + string.Join(" ", reader.Buffer.Take(128)), "NetworkManager");
|
||||
BAUPlugin.Logger.Warning($"Bad tag {reader.Tag} at {reader.Offset}+{reader.Position}={reader.Length}: " + string.Join(" ", reader.Buffer.Take(128)), "NetworkManager");
|
||||
reader.Recycle();
|
||||
}
|
||||
|
||||
@@ -477,7 +477,7 @@ internal static class NetworkManager
|
||||
|
||||
if (BetterAntiCheat.CheckCancelRPC(player, callId, reader) == false)
|
||||
{
|
||||
if (!player.IsLocalPlayer()) Logger_.LogCheat($"RPC canceled by Anti-Cheat: {Enum.GetName((RpcCalls)callId)}{Enum.GetName((CustomRPC)callId)} - {callId}");
|
||||
if (!player.IsLocalPlayer()) BAUPlugin.Logger.LogCheat($"RPC canceled by Anti-Cheat: {Enum.GetName((RpcCalls)callId)}{Enum.GetName((CustomRPC)callId)} - {callId}");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
-125
@@ -1,125 +0,0 @@
|
||||
using BetterAmongUs.Enums;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BetterAmongUs;
|
||||
|
||||
/// <summary>
|
||||
/// Contains metadata and constants for the BetterAmongUs mod.
|
||||
/// </summary>
|
||||
internal static class ModInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the release type of the current build.
|
||||
/// </summary>
|
||||
internal static readonly ReleaseTypes ReleaseBuildType = ReleaseTypes.Release;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Git commit hash from assembly metadata.
|
||||
/// </summary>
|
||||
public static string CommitHash = ThisAssembly.Git.Commit;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the build date from assembly metadata.
|
||||
/// </summary>
|
||||
public static string BuildDate = ThisAssembly.Metadata.BuildDate;
|
||||
|
||||
/// <summary>
|
||||
/// The beta number for beta releases.
|
||||
/// </summary>
|
||||
internal const string BETA_NUM = "0";
|
||||
|
||||
/// <summary>
|
||||
/// The hotfix number for hotfix releases.
|
||||
/// </summary>
|
||||
internal const string HOTFIX_NUM = "1";
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether this is a hotfix release.
|
||||
/// </summary>
|
||||
internal const bool IS_HOTFIX = true;
|
||||
|
||||
/// <summary>
|
||||
/// The name of BAU.
|
||||
/// </summary>
|
||||
internal const string PLUGIN_NAME = "BetterAmongUs";
|
||||
|
||||
/// <summary>
|
||||
/// The GUID (Globally Unique Identifier) of BAU.
|
||||
/// </summary>
|
||||
internal const string PLUGIN_GUID = "com.d1gq.betteramongus";
|
||||
|
||||
/// <summary>
|
||||
/// The version of BAU.
|
||||
/// </summary>
|
||||
internal const string PLUGIN_VERSION = "1.3.3";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of supported Among Us versions.
|
||||
/// </summary>
|
||||
internal static string[] SupportedAmongUsVersions =
|
||||
[
|
||||
"2026.8.18"
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// The GitHub repository URL for BAU.
|
||||
/// </summary>
|
||||
internal const string GITHUB = ThisAssembly.Git.RepositoryUrl;
|
||||
|
||||
/// <summary>
|
||||
/// The Discord invite URL for BAU.
|
||||
/// </summary>
|
||||
internal const string DISCORD = "https://discord.gg/vjYrXpzNAn";
|
||||
|
||||
/// <summary>
|
||||
/// Indicator rather that BAU is running on Starlight for Android.
|
||||
/// </summary>
|
||||
internal static readonly bool Starlight = OperatingSystem.IsAndroid();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves metadata from the assembly attributes.
|
||||
/// </summary>
|
||||
/// <param name="key">The metadata key to retrieve.</param>
|
||||
/// <returns>The metadata value, or an empty string if not found.</returns>
|
||||
private static string GetAssemblyMetadata(string key)
|
||||
{
|
||||
var attribute = Assembly
|
||||
.GetCustomAttributes<AssemblyMetadataAttribute>()
|
||||
.FirstOrDefault(a => a.Key == key);
|
||||
|
||||
return attribute?.Value ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The assembly associated to this mod.
|
||||
/// </summary>
|
||||
internal static Assembly Assembly
|
||||
{
|
||||
get
|
||||
{
|
||||
if (field == null)
|
||||
{
|
||||
field = Assembly.GetExecutingAssembly();
|
||||
}
|
||||
return field;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Contains constants for Among Us.
|
||||
/// </summary>
|
||||
internal static class AmongUs
|
||||
{
|
||||
/// <summary>
|
||||
/// The process name of the Among Us executable.
|
||||
/// </summary>
|
||||
internal const string PROCESS_NAME = "Among Us.exe";
|
||||
}
|
||||
|
||||
internal static class Constants
|
||||
{
|
||||
internal const int MAX_CHAT_TEXT = 120;
|
||||
internal const string BAU_CUSTOM_RPC_FLAG = "bau:rpc";
|
||||
internal const string BAU_MODDED_PROTOCOL_FLAG = "bau:flags";
|
||||
}
|
||||
}
|
||||
@@ -164,7 +164,7 @@ internal static class BetterAntiCheat
|
||||
{
|
||||
if (BetterNotificationManager.NotifyCheat(player, TranslationStrings.AntiCheat_InvalidHostRPC.Format(Enum.GetName((RpcCalls)callId))))
|
||||
{
|
||||
Logger_.LogCheat($"{player.ExtendedData().RealName} {Enum.GetName((RpcCalls)callId)}: {!player.IsHost()}");
|
||||
BAUPlugin.Logger.LogCheat($"{player.ExtendedData().RealName} {Enum.GetName((RpcCalls)callId)}: {!player.IsHost()}");
|
||||
}
|
||||
|
||||
reader.Recycle();
|
||||
@@ -183,7 +183,7 @@ internal static class BetterAntiCheat
|
||||
{
|
||||
if (BetterNotificationManager.NotifyCheat(player, TranslationStrings.AntiCheat_InvalidSetRPC.Format(Enum.GetName((RpcCalls)callId))))
|
||||
{
|
||||
Logger_.LogCheat($"{player.ExtendedData().RealName} {Enum.GetName((RpcCalls)callId)}: {GameState.IsInGamePlay}");
|
||||
BAUPlugin.Logger.LogCheat($"{player.ExtendedData().RealName} {Enum.GetName((RpcCalls)callId)}: {GameState.IsInGamePlay}");
|
||||
}
|
||||
|
||||
reader.Recycle();
|
||||
@@ -223,7 +223,7 @@ internal static class BetterAntiCheat
|
||||
{
|
||||
if (BetterNotificationManager.NotifyCheat(player, TranslationStrings.AntiCheat_InvalidLobbyRPC.Format(Enum.GetName((RpcCalls)callId))))
|
||||
{
|
||||
Logger_.LogCheat($"{player.ExtendedData().RealName} {Enum.GetName((RpcCalls)callId)}: {GameState.IsInGame} && {GameState.IsLobby}");
|
||||
BAUPlugin.Logger.LogCheat($"{player.ExtendedData().RealName} {Enum.GetName((RpcCalls)callId)}: {GameState.IsInGame} && {GameState.IsLobby}");
|
||||
}
|
||||
|
||||
reader.Recycle();
|
||||
@@ -237,7 +237,7 @@ internal static class BetterAntiCheat
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error(ex);
|
||||
BAUPlugin.Logger.Error(ex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ internal abstract class RPCHandler
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error(ex);
|
||||
BAUPlugin.Logger.Error(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -181,7 +181,7 @@ internal abstract class RPCHandler
|
||||
{
|
||||
string Name = Enum.GetName((RpcCalls)CallId) ?? Enum.GetName((CustomRPC)CallId) ?? $"Unregistered({CallId})";
|
||||
Name = $"[{Enum.GetName(catchedHandlerFlag)}] > " + Name;
|
||||
Logger_.LogCheat($"{catchedSender?.ExtendedData()?.RealName ?? player.ExtendedData()?.RealName ?? string.Empty} {Name}: {info}");
|
||||
BAUPlugin.Logger.LogCheat($"{catchedSender?.ExtendedData()?.RealName ?? player.ExtendedData()?.RealName ?? string.Empty} {Name}: {info}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -34,7 +34,7 @@ internal sealed class AUMChatHandler : RPCHandler
|
||||
betterData.AntiCheatInfo.AUMChats.Add(msgString);
|
||||
}
|
||||
|
||||
Logger_.Log($"{sender.Data.PlayerName} -> {msgString}", "AUMChatLog");
|
||||
BAUPlugin.Logger.Log($"{sender.Data.PlayerName} -> {msgString}", "AUMChatLog");
|
||||
|
||||
if (BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_Anticheat))
|
||||
return;
|
||||
|
||||
@@ -25,7 +25,7 @@ internal sealed class CheckNameHandler : RPCHandler
|
||||
if (BetterNotificationManager.NotifyCheat(sender, GetFormatSetText()))
|
||||
{
|
||||
Utils.AddChatPrivate($"{sender.GetPlayerNameAndColor()} Has tried to change their name to '{name}' but has been undone!");
|
||||
Logger_.LogCheat($"{sender.ExtendedData().RealName} Has tried to change their name to '{name}' but has been undone!");
|
||||
BAUPlugin.Logger.LogCheat($"{sender.ExtendedData().RealName} Has tried to change their name to '{name}' but has been undone!");
|
||||
LogRpcInfo($"{sender.DataIsCollected() == true} && {!GameState.IsLocalGame} && {GameState.IsVanillaServer}");
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ internal sealed class UpdateSystemHandler : RPCHandler
|
||||
{
|
||||
systemHandlers = new Dictionary<uint, Func<PlayerControl?, ISystemType, MessageReader, byte, bool>>
|
||||
{
|
||||
{ (uint)SystemTypes.Sabotage, (sender, system, reader, count) => HandleSabotageSystem(sender, system.Cast<SabotageSystemType>(), reader) },
|
||||
{ (uint)SystemTypes.Ventilation, (sender, system, reader, count) => HandleVentilationSystem(sender, system.Cast<VentilationSystem>(), count) },
|
||||
{ (uint)SystemTypes.Sabotage, (sender, system, reader, count) => HandleSabotageSystem(sender, system.Cast<SabotageSystemType>()) },
|
||||
{ (uint)SystemTypes.Ventilation, (sender, system, reader, count) => HandleVentilationSystem(sender, system.Cast<VentilationSystem>(), reader) },
|
||||
{ (uint)SystemTypes.Electrical, (sender, system, reader, count) => HandleSwitchSystem(sender, system.Cast<SwitchSystem>(), count) },
|
||||
{ (uint)SystemTypes.Comms, (sender, system, reader, count) => HandleCommsSystem(sender, system, count) },
|
||||
{ (uint)SystemTypes.MushroomMixupSabotage, (sender, system, reader, count) => HandleMushroomMixupSabotageSystem(sender, system.Cast<MushroomMixupSabotageSystem>(), count) },
|
||||
@@ -68,10 +68,8 @@ internal sealed class UpdateSystemHandler : RPCHandler
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool HandleSabotageSystem(PlayerControl? sender, SabotageSystemType sabotageSystem, MessageReader reader)
|
||||
private static bool HandleSabotageSystem(PlayerControl? sender, SabotageSystemType sabotageSystem)
|
||||
{
|
||||
byte count = reader.ReadByte();
|
||||
|
||||
if (!sender.IsImpostorTeam())
|
||||
{
|
||||
return false;
|
||||
@@ -85,8 +83,14 @@ internal sealed class UpdateSystemHandler : RPCHandler
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool HandleVentilationSystem(PlayerControl? sender, VentilationSystem ventilationSystem, byte count)
|
||||
private static bool HandleVentilationSystem(PlayerControl? sender, VentilationSystem ventilationSystem, MessageReader reader)
|
||||
{
|
||||
_ = reader.ReadUInt16();
|
||||
var operation = (VentilationSystem.Operation)reader.ReadByte();
|
||||
if (operation == VentilationSystem.Operation.BootImpostors)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -17,11 +17,12 @@ internal sealed class SendChatHandler : RPCHandler
|
||||
{
|
||||
var text = reader.ReadString();
|
||||
|
||||
if (BetterGameSettings.UseBanWordList.GetBool() && (!BetterGameSettings.UseBanWordListOnlyLobby.GetBool() || GameState.IsLobby))
|
||||
if (BetterGameSettings.UseBanChatList.GetBool() && (!BetterGameSettings.UseBanChatListOnlyLobby.GetBool() || GameState.IsLobby))
|
||||
{
|
||||
if (TextFileHandler.CompareStringFilters(BetterDataManager.Files.banWordListFilePath, text.Split(' ')))
|
||||
if (TextFileHandler.CompareStringRegexMatches(BetterDataManager.Files.banChatListFilePath, text))
|
||||
{
|
||||
sender.Kick(false, $"has been kicked due to\nchat message containing a banned word!");
|
||||
var ban = BetterGameSettings.UseBanChatListBan.GetBool();
|
||||
sender.Kick(ban, $"has been {(ban ? "banned" : "kicked")} due to\nchat message matching a banned pattern!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ internal sealed class SetNameHandler : RPCHandler
|
||||
if (BetterNotificationManager.NotifyCheat(sender, GetFormatSetText()))
|
||||
{
|
||||
Utils.AddChatPrivate($"{sender.GetPlayerNameAndColor()} Has tried to change their name to '{name}' but has been undone!");
|
||||
Logger_.LogCheat($"{sender.ExtendedData().RealName} Has tried to change their name to '{name}' but has been undone!");
|
||||
BAUPlugin.Logger.LogCheat($"{sender.ExtendedData().RealName} Has tried to change their name to '{name}' but has been undone!");
|
||||
LogRpcInfo($"Player attempted to change name multiple times: '{name}'");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
using BepInEx;
|
||||
using BepInEx.Logging;
|
||||
using BetterAmongUs.Utilities;
|
||||
|
||||
namespace BetterAmongUs.Modules;
|
||||
|
||||
/// <summary>
|
||||
/// Provides logging for BetterAmongUs with various log levels and destinations.
|
||||
/// </summary>
|
||||
internal sealed class BAULogger(ManualLogSource manualLogSource)
|
||||
{
|
||||
private readonly ManualLogSource _manualLogSource = manualLogSource;
|
||||
|
||||
/// <summary>
|
||||
/// Logs a message with specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="info">The message to log.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
/// <param name="color">The console color for the message.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
internal void Log(string info, string tag = "Log", bool logConsole = true, ConsoleColor color = ConsoleColor.White, bool hostOnly = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (hostOnly && !GameState.IsHost)
|
||||
return;
|
||||
|
||||
_manualLogSource.LogInfo($"[{tag}] {info}");
|
||||
if (logConsole)
|
||||
{
|
||||
ConsoleManager.SetConsoleColor(color);
|
||||
ConsoleManager.ConsoleStream.WriteLine($"{DateTime.Now:HH:mm} BetterAmongUs[{tag}]: {Utils.RemoveHtmlText(info)}");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a header message with visual formatting.
|
||||
/// </summary>
|
||||
/// <param name="info">The header text.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal void LogHeader(string info, string tag = "LogHeader", bool hostOnly = false, bool logConsole = true) => Log($" >-------------- {info} --------------<", tag, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs cheat detection messages with green console color.
|
||||
/// </summary>
|
||||
/// <param name="info">The cheat detection message.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal void LogCheat(string info, string tag = "AntiCheat", bool hostOnly = false, bool logConsole = true) => Log(info, tag, color: ConsoleColor.Green, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs error messages with red console color.
|
||||
/// </summary>
|
||||
/// <param name="info">The error message.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal void Error(string info, string tag = "Error", bool hostOnly = false, bool logConsole = true) => Log(info, tag, color: ConsoleColor.Red, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs exception details with red console color.
|
||||
/// </summary>
|
||||
/// <param name="ex">The exception to log.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal void Error(Exception ex, string tag = "Error", bool hostOnly = false, bool logConsole = true) => Log(ex.ToString(), tag, color: ConsoleColor.Red, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs warning messages with yellow console color.
|
||||
/// </summary>
|
||||
/// <param name="info">The warning message.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal void Warning(string info, string tag = "Warning", bool hostOnly = false, bool logConsole = true) => Log(info, tag, color: ConsoleColor.Yellow, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a test message for debugging purposes.
|
||||
/// </summary>
|
||||
internal void Test()
|
||||
{
|
||||
Log("------------------> TEST <------------------", "TEST");
|
||||
InGame("TEST");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a message in-game via the disconnect message notifier.
|
||||
/// </summary>
|
||||
/// <param name="info">The message to display in-game.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
internal void InGame(string info, bool hostOnly = false)
|
||||
{
|
||||
if (hostOnly && !GameState.IsHost)
|
||||
return;
|
||||
|
||||
if (HudManager.InstanceExists) HudManager.Instance.Notifier.AddDisconnectMessage(info);
|
||||
Log(info, "InGame", hostOnly: hostOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a private message with encryption for sensitive data.
|
||||
/// </summary>
|
||||
/// <param name="info">The sensitive message to log.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
internal void LogPrivate(string info, string tag = "Log", bool hostOnly = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (hostOnly && !GameState.IsHost)
|
||||
return;
|
||||
|
||||
string encrypted = Encryptor.Encrypt(info);
|
||||
Log(BAUPlugin.Constants.ENCRYPTED_LOG_PREFIX + encrypted + BAUPlugin.Constants.ENCRYPTED_LOG_POSTFIX, tag, false);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts all encrypted sections within a log file text.
|
||||
/// </summary>
|
||||
/// <param name="logText">The raw log file content containing encrypted sections marked with prefix and postfix characters.</param>
|
||||
/// <returns>The log text with all encrypted sections decrypted and markers removed.</returns>
|
||||
internal static string DecryptLogs(string logText)
|
||||
{
|
||||
string newLog = string.Empty;
|
||||
string[] logArray = logText.Split([Environment.NewLine], StringSplitOptions.None);
|
||||
|
||||
foreach (string text in logArray)
|
||||
{
|
||||
if (text.Contains(BAUPlugin.Constants.ENCRYPTED_LOG_PREFIX) &&
|
||||
text.Contains(BAUPlugin.Constants.ENCRYPTED_LOG_POSTFIX))
|
||||
{
|
||||
int start = text.IndexOf(BAUPlugin.Constants.ENCRYPTED_LOG_PREFIX);
|
||||
int end = text.IndexOf(BAUPlugin.Constants.ENCRYPTED_LOG_POSTFIX);
|
||||
|
||||
string before = text[..start];
|
||||
string encrypted = text.Substring(start + 1, end - start - 1);
|
||||
string after = text[(end + 1)..];
|
||||
|
||||
try
|
||||
{
|
||||
string decrypted = Encryptor.Decrypt(encrypted);
|
||||
newLog += before + decrypted + after + "\n";
|
||||
}
|
||||
catch
|
||||
{
|
||||
newLog += text + "\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newLog += text + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return newLog;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom log listener for BepInEx that forwards logs to the BetterAmongUs logging system.
|
||||
/// </summary>
|
||||
internal class CustomLogListener(BAULogger bauLogger) : ILogListener
|
||||
{
|
||||
private readonly BAULogger _bauLogger = bauLogger;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the log levels to filter.
|
||||
/// </summary>
|
||||
public LogLevel LogLevelFilter { get; set; } = LogLevel.Info | LogLevel.Warning | LogLevel.Error;
|
||||
|
||||
/// <summary>
|
||||
/// Handles log events from BepInEx.
|
||||
/// </summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="eventArgs">The log event arguments.</param>
|
||||
public void LogEvent(object sender, LogEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Source.SourceName.ToLower().Contains("unity")
|
||||
|| eventArgs.Source.SourceName.ToLower().Contains("betteramongus"))
|
||||
return;
|
||||
|
||||
if (eventArgs.Level is LogLevel.None or LogLevel.Info)
|
||||
{
|
||||
_bauLogger.Log(eventArgs.Data.ToString(), "BepInEx." + eventArgs.Source.SourceName, logConsole: false);
|
||||
}
|
||||
else if (eventArgs.Level is LogLevel.Warning)
|
||||
{
|
||||
_bauLogger.Warning(eventArgs.Data.ToString(), "BepInEx." + eventArgs.Source.SourceName, logConsole: false);
|
||||
}
|
||||
else if (eventArgs.Level is LogLevel.Error or LogLevel.Fatal)
|
||||
{
|
||||
_bauLogger.Error(eventArgs.Data.ToString(), "BepInEx." + eventArgs.Source.SourceName, logConsole: false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the log listener.
|
||||
/// </summary>
|
||||
public void Dispose() { }
|
||||
|
||||
/// <summary>
|
||||
/// Flushes the log listener.
|
||||
/// </summary>
|
||||
public void Flush() { }
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BetterAmongUs.Modules;
|
||||
|
||||
@@ -8,16 +8,82 @@ namespace BetterAmongUs.Modules;
|
||||
/// </summary>
|
||||
internal static class Encryptor
|
||||
{
|
||||
private static readonly byte[] Key = Encoding.UTF8.GetBytes("0123456789ABCDEF0123456789ABCDEF");
|
||||
private static readonly byte[] IV = Encoding.UTF8.GetBytes("ABCDEF0123456789");
|
||||
private static byte[] Key = [];
|
||||
private static byte[] IV = [];
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the encryption system by loading or generating AES keys.
|
||||
/// </summary>
|
||||
internal static void Initialize()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (PlayerPrefs.HasKey("BAUEncryptionKey") && PlayerPrefs.HasKey("BAUEncryptionIV"))
|
||||
{
|
||||
string keyString = PlayerPrefs.GetString("BAUEncryptionKey");
|
||||
string ivString = PlayerPrefs.GetString("BAUEncryptionIV");
|
||||
|
||||
if (string.IsNullOrEmpty(keyString) || string.IsNullOrEmpty(ivString))
|
||||
{
|
||||
throw new Exception("Keys are empty");
|
||||
}
|
||||
|
||||
Key = Convert.FromBase64String(keyString);
|
||||
IV = Convert.FromBase64String(ivString);
|
||||
|
||||
if (Key.Length != 32 || IV.Length != 16)
|
||||
{
|
||||
throw new Exception("Invalid key length");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GenerateAndSaveKeys();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
PlayerPrefs.DeleteKey("BAUEncryptionKey");
|
||||
PlayerPrefs.DeleteKey("BAUEncryptionIV");
|
||||
PlayerPrefs.Save();
|
||||
GenerateAndSaveKeys();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a new 256-bit AES key and 128-bit initialization vector (IV),
|
||||
/// then saves them to PlayerPrefs as Base64 strings.
|
||||
/// </summary>
|
||||
private static void GenerateAndSaveKeys()
|
||||
{
|
||||
using (Aes aes = Aes.Create())
|
||||
{
|
||||
aes.KeySize = 256;
|
||||
aes.BlockSize = 128;
|
||||
aes.GenerateKey();
|
||||
aes.GenerateIV();
|
||||
Key = aes.Key;
|
||||
IV = aes.IV;
|
||||
}
|
||||
|
||||
PlayerPrefs.SetString("BAUEncryptionKey", Convert.ToBase64String(Key));
|
||||
PlayerPrefs.SetString("BAUEncryptionIV", Convert.ToBase64String(IV));
|
||||
PlayerPrefs.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypts a plain text string using AES encryption.
|
||||
/// </summary>
|
||||
/// <param name="input">The plain text string to encrypt.</param>
|
||||
/// <returns>A base64-encoded string containing the encrypted data.</returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown if encryption is not initialized.</exception>
|
||||
internal static string Encrypt(string input)
|
||||
{
|
||||
if (Key == null || Key.Length == 0 || IV == null || IV.Length == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Encryption not initialized. Call InitializeEncryption() first.");
|
||||
}
|
||||
|
||||
using Aes aes = Aes.Create();
|
||||
aes.Key = Key;
|
||||
aes.IV = IV;
|
||||
@@ -36,8 +102,16 @@ internal static class Encryptor
|
||||
/// </summary>
|
||||
/// <param name="input">The base64-encoded encrypted string.</param>
|
||||
/// <returns>The decrypted plain text string.</returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown if encryption is not initialized.</exception>
|
||||
/// <exception cref="FormatException">Thrown if the input is not valid Base64.</exception>
|
||||
/// <exception cref="CryptographicException">Thrown if decryption fails due to invalid key or corrupted data.</exception>
|
||||
internal static string Decrypt(string input)
|
||||
{
|
||||
if (Key == null || Key.Length == 0 || IV == null || IV.Length == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Encryption not initialized. Call InitializeEncryption() first.");
|
||||
}
|
||||
|
||||
using Aes aes = Aes.Create();
|
||||
aes.Key = Key;
|
||||
aes.IV = IV;
|
||||
|
||||
@@ -1,240 +0,0 @@
|
||||
using BepInEx;
|
||||
using BepInEx.Logging;
|
||||
using BetterAmongUs.Data;
|
||||
using BetterAmongUs.Utilities;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace BetterAmongUs.Modules;
|
||||
|
||||
/// <summary>
|
||||
/// Provides logging utilities for BetterAmongUs with various log levels and destinations.
|
||||
/// </summary>
|
||||
internal static class Logger_
|
||||
{
|
||||
/// <summary>
|
||||
/// Logs a message with specified parameters.
|
||||
/// </summary>
|
||||
/// <param name="info">The message to log.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
/// <param name="color">The console color for the message.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
internal static void Log(string info, string tag = "Log", bool logConsole = true, ConsoleColor color = ConsoleColor.White, bool hostOnly = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (hostOnly && !GameState.IsHost)
|
||||
return;
|
||||
|
||||
string mark = $"{DateTime.Now:HH:mm} [BetterLog][{tag}]";
|
||||
string logFilePath = BetterDataManager.Files.logFilePath;
|
||||
string newLine = $"{mark}: {Utils.RemoveHtmlText(info)}";
|
||||
File.AppendAllText(logFilePath, newLine + Environment.NewLine);
|
||||
BAUPlugin.Logger.LogInfo($"[{tag}] {info}");
|
||||
if (logConsole)
|
||||
{
|
||||
ConsoleManager.SetConsoleColor(color);
|
||||
ConsoleManager.ConsoleStream.WriteLine($"{DateTime.Now:HH:mm} BetterAmongUs[{tag}]: {Utils.RemoveHtmlText(info)}");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs method calls with detailed information about the caller.
|
||||
/// </summary>
|
||||
/// <param name="info">Additional information about the method call.</param>
|
||||
/// <param name="runtimeType">The type containing the method (optional).</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="callerFilePath">Automatically populated: path of the file containing the caller.</param>
|
||||
/// <param name="callerLineNumber">Automatically populated: line number of the caller.</param>
|
||||
/// <param name="callerMemberName">Automatically populated: name of the calling member.</param>
|
||||
internal static void LogMethod(
|
||||
string info = "",
|
||||
Type? runtimeType = null,
|
||||
bool hostOnly = false,
|
||||
[CallerFilePath] string callerFilePath = "",
|
||||
[CallerLineNumber] int callerLineNumber = 0,
|
||||
[CallerMemberName] string callerMemberName = "")
|
||||
{
|
||||
var loggedMethodFrame = new StackFrame(1, true);
|
||||
|
||||
var loggedMethod = loggedMethodFrame.GetMethod();
|
||||
string loggedMethodName = loggedMethod.Name;
|
||||
string? loggedClassFullName = runtimeType?.FullName ?? loggedMethod.DeclaringType?.FullName;
|
||||
string? loggedClassName = runtimeType?.Name ?? loggedMethod.DeclaringType?.Name;
|
||||
|
||||
string logMessage = string.IsNullOrEmpty(info)
|
||||
? $"{loggedClassFullName}.{loggedMethodName} was called from {Path.GetFileName(callerFilePath)}({callerLineNumber}) in {callerMemberName}."
|
||||
: $"{loggedClassFullName}.{loggedMethodName} was called from {Path.GetFileName(callerFilePath)}({callerLineNumber}) in {callerMemberName}. Info: {info}.";
|
||||
|
||||
Log(logMessage, "MethodLog", hostOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs private method calls with detailed information, using encrypted storage.
|
||||
/// </summary>
|
||||
/// <param name="info">Additional information about the method call.</param>
|
||||
/// <param name="runtimeType">The type containing the method (optional).</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="callerFilePath">Automatically populated: path of the file containing the caller.</param>
|
||||
/// <param name="callerLineNumber">Automatically populated: line number of the caller.</param>
|
||||
/// <param name="callerMemberName">Automatically populated: name of the calling member.</param>
|
||||
internal static void LogMethodPrivate(
|
||||
string info = "",
|
||||
Type? runtimeType = null,
|
||||
bool hostOnly = false,
|
||||
[CallerFilePath] string callerFilePath = "",
|
||||
[CallerLineNumber] int callerLineNumber = 0,
|
||||
[CallerMemberName] string callerMemberName = "")
|
||||
{
|
||||
var loggedMethodFrame = new StackFrame(1, true);
|
||||
|
||||
var loggedMethod = loggedMethodFrame.GetMethod();
|
||||
string loggedMethodName = loggedMethod.Name;
|
||||
string? loggedClassFullName = runtimeType?.FullName ?? loggedMethod.DeclaringType?.FullName;
|
||||
string? loggedClassName = runtimeType?.Name ?? loggedMethod.DeclaringType?.Name;
|
||||
|
||||
string logMessage = string.IsNullOrEmpty(info)
|
||||
? $"{loggedClassFullName}.{loggedMethodName} was called from {Path.GetFileName(callerFilePath)}({callerLineNumber}) in {callerMemberName}."
|
||||
: $"{loggedClassFullName}.{loggedMethodName} was called from {Path.GetFileName(callerFilePath)}({callerLineNumber}) in {callerMemberName}. Info: {info}.";
|
||||
|
||||
LogPrivate(logMessage, "MethodLog", hostOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a header message with visual formatting.
|
||||
/// </summary>
|
||||
/// <param name="info">The header text.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal static void LogHeader(string info, string tag = "LogHeader", bool hostOnly = false, bool logConsole = true) => Log($" >-------------- {info} --------------<", tag, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs cheat detection messages with green console color.
|
||||
/// </summary>
|
||||
/// <param name="info">The cheat detection message.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal static void LogCheat(string info, string tag = "AntiCheat", bool hostOnly = false, bool logConsole = true) => Log(info, tag, color: ConsoleColor.Green, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs error messages with red console color.
|
||||
/// </summary>
|
||||
/// <param name="info">The error message.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal static void Error(string info, string tag = "Error", bool hostOnly = false, bool logConsole = true) => Log(info, tag, color: ConsoleColor.Red, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs exception details with red console color.
|
||||
/// </summary>
|
||||
/// <param name="ex">The exception to log.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal static void Error(Exception ex, string tag = "Error", bool hostOnly = false, bool logConsole = true) => Log(ex.ToString(), tag, color: ConsoleColor.Red, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs warning messages with yellow console color.
|
||||
/// </summary>
|
||||
/// <param name="info">The warning message.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
/// <param name="logConsole">Whether to output to console.</param>
|
||||
internal static void Warning(string info, string tag = "Warning", bool hostOnly = false, bool logConsole = true) => Log(info, tag, color: ConsoleColor.Yellow, hostOnly: hostOnly, logConsole: logConsole);
|
||||
|
||||
/// <summary>
|
||||
/// Logs a test message for debugging purposes.
|
||||
/// </summary>
|
||||
internal static void Test()
|
||||
{
|
||||
Log("------------------> TEST <------------------", "TEST");
|
||||
InGame("TEST");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a message in-game via the disconnect message notifier.
|
||||
/// </summary>
|
||||
/// <param name="info">The message to display in-game.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
internal static void InGame(string info, bool hostOnly = false)
|
||||
{
|
||||
if (hostOnly && !GameState.IsHost)
|
||||
return;
|
||||
|
||||
if (HudManager.InstanceExists) HudManager.Instance.Notifier.AddDisconnectMessage(info);
|
||||
Log(info, "InGame", hostOnly: hostOnly);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a private message with encryption for sensitive data.
|
||||
/// </summary>
|
||||
/// <param name="info">The sensitive message to log.</param>
|
||||
/// <param name="tag">The log tag/category.</param>
|
||||
/// <param name="hostOnly">Whether to log only when the client is host.</param>
|
||||
internal static void LogPrivate(string info, string tag = "Log", bool hostOnly = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (hostOnly && !GameState.IsHost)
|
||||
return;
|
||||
|
||||
string mark = $"{DateTime.Now:HH:mm} [BetterLog][PrivateLog][{tag}]";
|
||||
string logFilePath = BetterDataManager.Files.logFilePath;
|
||||
string newLine = $"{mark}: " + Encryptor.Encrypt($"{info}");
|
||||
File.AppendAllText(logFilePath, newLine + Environment.NewLine);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Custom log listener for BepInEx that forwards logs to the BetterAmongUs logging system.
|
||||
/// </summary>
|
||||
internal class CustomLogListener : ILogListener
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the log levels to filter.
|
||||
/// </summary>
|
||||
public LogLevel LogLevelFilter { get; set; } = LogLevel.Info | LogLevel.Warning | LogLevel.Error;
|
||||
|
||||
/// <summary>
|
||||
/// Handles log events from BepInEx.
|
||||
/// </summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="eventArgs">The log event arguments.</param>
|
||||
public void LogEvent(object sender, LogEventArgs eventArgs)
|
||||
{
|
||||
if (eventArgs.Source.SourceName.ToLower().Contains("unity")
|
||||
|| eventArgs.Source.SourceName.ToLower().Contains("betteramongus"))
|
||||
return;
|
||||
|
||||
if (eventArgs.Level is LogLevel.None or LogLevel.Info)
|
||||
{
|
||||
Logger_.Log(eventArgs.Data.ToString(), "BepInEx." + eventArgs.Source.SourceName, logConsole: false);
|
||||
}
|
||||
else if (eventArgs.Level is LogLevel.Warning)
|
||||
{
|
||||
Logger_.Warning(eventArgs.Data.ToString(), "BepInEx." + eventArgs.Source.SourceName, logConsole: false);
|
||||
}
|
||||
else if (eventArgs.Level is LogLevel.Error or LogLevel.Fatal)
|
||||
{
|
||||
Logger_.Error(eventArgs.Data.ToString(), "BepInEx." + eventArgs.Source.SourceName, logConsole: false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the log listener.
|
||||
/// </summary>
|
||||
public void Dispose() { }
|
||||
|
||||
/// <summary>
|
||||
/// Flushes the log listener.
|
||||
/// </summary>
|
||||
public void Flush() { }
|
||||
}
|
||||
@@ -238,7 +238,7 @@ public sealed class OptionPlayerItem : OptionItem<int>
|
||||
{
|
||||
if (Value != -1)
|
||||
{
|
||||
var player = Utils.PlayerFromPlayerId(Value);
|
||||
var player = Utils.PlayerFromPlayerId((byte)Value);
|
||||
if (player != null)
|
||||
return $"{player.GetPlayerNameAndColor()}";
|
||||
else
|
||||
|
||||
@@ -80,7 +80,7 @@ internal abstract class BAUSupportEvent(string attributeFlag)
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Invoking event '{_attributeFlag}' for {pluginInfo.GetType().Name}: {ex}");
|
||||
BAUPlugin.Logger.Error($"Invoking event '{_attributeFlag}' for {pluginInfo.GetType().Name}: {ex}");
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,25 +9,14 @@ namespace BetterAmongUs.Modules;
|
||||
internal static class TextFileHandler
|
||||
{
|
||||
/// <summary>
|
||||
/// Compares strings against filter patterns in a file using wildcard matching.
|
||||
/// Compares a string against regex patterns in a file.
|
||||
/// </summary>
|
||||
/// <param name="filePath">Path to the filter file.</param>
|
||||
/// <param name="strings">Array of strings to check against filters.</param>
|
||||
/// <returns>True if any string matches a filter pattern, false otherwise.</returns>
|
||||
internal static bool CompareStringFilters(string filePath, string[] strings)
|
||||
/// <param name="filePath">Path to the file containing regex patterns.</param>
|
||||
/// <param name="inputString">String to match against.</param>
|
||||
/// <returns>True if the string matches a regex pattern, false otherwise.</returns>
|
||||
internal static bool CompareStringRegexMatches(string filePath, string inputString)
|
||||
{
|
||||
foreach (var content in ReadContents(filePath))
|
||||
{
|
||||
foreach (var text in strings)
|
||||
{
|
||||
if (CheckFilterString(content, text))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return ReadContents(filePath).Any(content => Regex.IsMatch(inputString, content, RegexOptions.Compiled));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -43,17 +32,10 @@ internal static class TextFileHandler
|
||||
StringComparer.OrdinalIgnoreCase
|
||||
);
|
||||
|
||||
foreach (var content in ReadContents(filePath))
|
||||
{
|
||||
string normalizedContent = content.ToLower().Trim();
|
||||
|
||||
if (stringSet.Contains(normalizedContent))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
var contents = ReadContents(filePath)
|
||||
.SelectMany(line => line.Split(',', StringSplitOptions.RemoveEmptyEntries))
|
||||
.Select(s => s.ToLower().Trim());
|
||||
return contents.Any(stringSet.Contains);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -66,35 +48,16 @@ internal static class TextFileHandler
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
return File.ReadLines(filePath)
|
||||
.Where(line => !string.IsNullOrWhiteSpace(line) &&
|
||||
!line.StartsWith("//") &&
|
||||
!line.StartsWith("#"))
|
||||
.SelectMany(line => line.Split(',', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(s => s.Trim()));
|
||||
.Where(line =>
|
||||
!string.IsNullOrWhiteSpace(line) &&
|
||||
!line.StartsWith("//") &&
|
||||
!line.StartsWith("#")
|
||||
);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a text matches a filter pattern with wildcard support.
|
||||
/// </summary>
|
||||
/// <param name="filter">The filter pattern (supports ** wildcards).</param>
|
||||
/// <param name="text">The text to check.</param>
|
||||
/// <returns>True if the text matches the filter pattern, false otherwise.</returns>
|
||||
private static bool CheckFilterString(string filter, string text)
|
||||
{
|
||||
string pattern = filter switch
|
||||
{
|
||||
_ when filter.StartsWith("**") && filter.EndsWith("**") => Regex.Escape(filter.Trim('*')), // Contains anywhere
|
||||
_ when filter.StartsWith("**") => Regex.Escape(filter.TrimStart('*')) + "$", // Ends with
|
||||
_ when filter.EndsWith("**") => "^" + Regex.Escape(filter.TrimEnd('*')), // Starts with
|
||||
_ => "^" + Regex.Escape(filter) + "$" // Exact match
|
||||
};
|
||||
|
||||
return Regex.IsMatch(text, pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a YAML-like string into a dictionary of key-value pairs.
|
||||
/// </summary>
|
||||
|
||||
@@ -22,9 +22,9 @@ internal static class Translator
|
||||
/// </summary>
|
||||
internal static void Initialize()
|
||||
{
|
||||
Logger_.Log("Loading language files...", "Translator");
|
||||
BAUPlugin.Logger.Log("Loading language files...", "Translator");
|
||||
LoadLanguages();
|
||||
Logger_.Log("Language files loaded successfully", "Translator");
|
||||
BAUPlugin.Logger.Log("Language files loaded successfully", "Translator");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -34,14 +34,14 @@ internal static class Translator
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = ModInfo.Assembly;
|
||||
var assembly = BAUPlugin.ModInfo.Assembly;
|
||||
var jsonFileNames = GetJsonResourceNames(assembly);
|
||||
|
||||
TranslateMaps = [];
|
||||
|
||||
if (jsonFileNames.Length == 0)
|
||||
{
|
||||
Logger_.Error("JSON translation files do not exist.", "Translator");
|
||||
BAUPlugin.Logger.Error("JSON translation files do not exist.", "Translator");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ internal static class Translator
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Error loading languages: {ex}", "Translator");
|
||||
BAUPlugin.Logger.Error($"Error loading languages: {ex}", "Translator");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ internal static class Translator
|
||||
|
||||
if (jsonDictionary == null)
|
||||
{
|
||||
Logger_.Error($"Failed to deserialize JSON from {resourceName}", "Translator");
|
||||
BAUPlugin.Logger.Error($"Failed to deserialize JSON from {resourceName}", "Translator");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -103,12 +103,12 @@ internal static class Translator
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger_.Error($"Invalid JSON format in {resourceName}: Missing or invalid 'LanguageID' field.", "Translator");
|
||||
BAUPlugin.Logger.Error($"Invalid JSON format in {resourceName}: Missing or invalid 'LanguageID' field.", "Translator");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Error loading language file {resourceName}: {ex}", "Translator");
|
||||
BAUPlugin.Logger.Error($"Error loading language file {resourceName}: {ex}", "Translator");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ internal static class Translator
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Error retrieving string [{translationString}]: {ex}", "Translator");
|
||||
BAUPlugin.Logger.Error($"Error retrieving string [{translationString}]: {ex}", "Translator");
|
||||
return fallbackText;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ internal sealed class BetterPingTracker : MonoBehaviour
|
||||
|
||||
if (pingText == null || pingAspectPosition == null)
|
||||
{
|
||||
Logger_.Error("BetterPingTracker.SetUp() called with null parameters!");
|
||||
BAUPlugin.Logger.Error("BetterPingTracker.SetUp() called with null parameters!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -84,8 +84,8 @@ internal sealed class BetterPingTracker : MonoBehaviour
|
||||
sb.AppendFormat("{0}: <b>{1}</b>\n", TranslationStrings.Timer.LocalizedString.ToUpper(), $"<{timeColor}>{lobbyTimerDisplay}</color>");
|
||||
}
|
||||
|
||||
sb.Append($"<color=#00dbdb><size=75%>BetterAmongUs {BAUPlugin.GetVersionText(true)}</size></color>\n");
|
||||
sb.Append($"<color=#8A8A8A>{ModInfo.GITHUB}</color>\n".Size(52f));
|
||||
sb.Append($"<color=#00dbdb><size=75%>BetterAmongUs {BAUPlugin.ModInfo.VERSION_STRING}</size></color>\n");
|
||||
sb.Append($"<color=#8A8A8A>{BAUPlugin.ModInfo.GITHUB}</color>\n".Size(52f));
|
||||
|
||||
if (BAUConfigs.ShowFPS.Value)
|
||||
{
|
||||
|
||||
@@ -29,7 +29,7 @@ internal sealed class ExtendedPlayerInfo : MonoBehaviour, IMonoExtension<Network
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Log("Handshake disabled: " + ex.Message);
|
||||
BAUPlugin.Logger.Log("Handshake disabled: " + ex.Message);
|
||||
HandshakeHandler = null;
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ internal sealed class ExtendedPlayerInfo : MonoBehaviour, IMonoExtension<Network
|
||||
TranslationStrings.AntiCheat_UnauthorizedAction.LocalizedString
|
||||
);
|
||||
|
||||
Logger_.LogCheat($"{BaseMono.Object.ExtendedData().RealName} {AntiCheatInfo.RPCSentPS} Sent.");
|
||||
BAUPlugin.Logger.LogCheat($"{BaseMono.Object.ExtendedData().RealName} {AntiCheatInfo.RPCSentPS} Sent.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ internal sealed class ExtendedPlayerInfo : MonoBehaviour, IMonoExtension<Network
|
||||
{
|
||||
try
|
||||
{
|
||||
if (reader.ReadString() == ModInfo.Constants.BAU_MODDED_PROTOCOL_FLAG)
|
||||
if (reader.ReadString() == BAUPlugin.Constants.BAU_MODDED_PROTOCOL_FLAG)
|
||||
{
|
||||
int flagCount = reader.ReadPackedInt32();
|
||||
for (int i = 0; i < flagCount; i++)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using BetterAmongUs.Attributes;
|
||||
using BetterAmongUs.Data;
|
||||
using BetterAmongUs.Data.Config;
|
||||
using BetterAmongUs.Generated;
|
||||
using BetterAmongUs.Modules.Support;
|
||||
using BetterAmongUs.MonoScripts.Extended;
|
||||
@@ -91,7 +92,14 @@ internal sealed class MeetingInfoDisplay : PlayerInfoDisplay
|
||||
|
||||
if (!BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_CustomColorBlindText))
|
||||
{
|
||||
_pva.ColorBlindName.transform.localPosition = new Vector3(-0.91f, -0.19f, -0.05f);
|
||||
if (BAUConfigs.BetterColorblindText.Value)
|
||||
{
|
||||
_pva.ColorBlindName.transform.localPosition = new Vector3(-0.91f, -0.19f, -0.05f);
|
||||
}
|
||||
else
|
||||
{
|
||||
_pva.ColorBlindName.transform.localPosition = _pva.NameText.transform.localPosition - new Vector3(0f, 0.19f, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
_lastUpdateFrame = Time.frameCount;
|
||||
|
||||
@@ -217,7 +217,7 @@ internal class PlayerInfoDisplay : MonoBehaviour
|
||||
}
|
||||
else
|
||||
{
|
||||
var targetData = Utils.PlayerDataFromPlayerId(_player.shapeshiftTargetPlayerId);
|
||||
var targetData = Utils.PlayerDataFromPlayerId((byte)_player.shapeshiftTargetPlayerId);
|
||||
if (targetData == null)
|
||||
return;
|
||||
|
||||
@@ -411,12 +411,20 @@ internal class PlayerInfoDisplay : MonoBehaviour
|
||||
private void UpdateColorBlindTextPosition()
|
||||
{
|
||||
if (BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_CustomColorBlindText))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var text = _player.cosmetics.colorBlindText;
|
||||
if (!text.enabled)
|
||||
return;
|
||||
|
||||
if (!BAUConfigs.BetterColorblindText.Value)
|
||||
{
|
||||
text.transform.localPosition = new Vector3(0f, -0.2f, 0f);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_player.onLadder && !_player.MyPhysics.Animations.IsPlayingAnyLadderAnimation())
|
||||
{
|
||||
text.transform.localPosition = new Vector3(0f, -1.3f, 0.4999f);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using BetterAmongUs.Enums;
|
||||
using BetterAmongUs.Modules;
|
||||
using BetterAmongUs.Modules;
|
||||
using Semver;
|
||||
using System.Collections;
|
||||
using System.Text.Json.Serialization;
|
||||
using UnityEngine;
|
||||
@@ -12,6 +12,12 @@ namespace BetterAmongUs.Network.Configs;
|
||||
[Serializable]
|
||||
internal sealed class BAUUpdateData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the download link for the updated DLL file.
|
||||
/// </summary>
|
||||
[JsonPropertyName("valid")]
|
||||
public bool Valid { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the download link for the updated DLL file.
|
||||
/// </summary>
|
||||
@@ -24,86 +30,27 @@ internal sealed class BAUUpdateData
|
||||
[JsonPropertyName("version")]
|
||||
public string Version { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the release type as an integer value.
|
||||
/// </summary>
|
||||
[JsonPropertyName("releaseType")]
|
||||
public int ReleaseType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets whether this update is a hotfix.
|
||||
/// </summary>
|
||||
[JsonPropertyName("isHotfix")]
|
||||
public bool IsHotfix { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the hotfix number if this is a hotfix update.
|
||||
/// </summary>
|
||||
[JsonPropertyName("hotfixNumber")]
|
||||
public int HotfixNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the beta number if this is a beta release.
|
||||
/// </summary>
|
||||
[JsonPropertyName("betaNumber")]
|
||||
public int BetaNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines if this update is newer than the currently installed version.
|
||||
/// </summary>
|
||||
/// <returns>True if the update is newer, false otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// Compares version numbers, release types, and specific build numbers
|
||||
/// to determine if an update should be applied.
|
||||
/// </remarks>
|
||||
internal bool IsNewUpdate()
|
||||
{
|
||||
try
|
||||
{
|
||||
var updateVersion = new Version(Version);
|
||||
var modVersion = new Version(ModInfo.PLUGIN_VERSION);
|
||||
|
||||
// 1. Compare main version (major.minor.build)
|
||||
if (updateVersion > modVersion)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (updateVersion < modVersion)
|
||||
if (!Valid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 2. Versions are equal, compare release types
|
||||
var updateReleaseType = (ReleaseTypes)ReleaseType;
|
||||
var currentReleaseType = ModInfo.ReleaseBuildType;
|
||||
var updateVersion = SemVersion.Parse(Version);
|
||||
var modVersion = BAUPlugin.ModInfo.SemVersion;
|
||||
|
||||
// Release is always preferred over Beta
|
||||
if (updateReleaseType == ReleaseTypes.Release && currentReleaseType == ReleaseTypes.Beta)
|
||||
return true;
|
||||
|
||||
// Don't downgrade from Release to Beta
|
||||
if (updateReleaseType == ReleaseTypes.Beta && currentReleaseType == ReleaseTypes.Release)
|
||||
return false;
|
||||
|
||||
// 3. Same version and release type, compare specific numbers
|
||||
if (updateReleaseType == ReleaseTypes.Beta)
|
||||
{
|
||||
return BetaNumber > int.Parse(ModInfo.BETA_NUM);
|
||||
}
|
||||
|
||||
// Release version - check hotfixes
|
||||
if (IsHotfix && !ModInfo.IS_HOTFIX)
|
||||
return true;
|
||||
|
||||
if (IsHotfix && ModInfo.IS_HOTFIX)
|
||||
return HotfixNumber > int.Parse(ModInfo.HOTFIX_NUM);
|
||||
|
||||
// Same version, same type, no newer hotfix
|
||||
return false;
|
||||
return updateVersion.ComparePrecedenceTo(modVersion) > 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Update check failed: {ex.Message}");
|
||||
BAUPlugin.Logger.Error($"Update check failed: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -132,7 +79,7 @@ internal sealed class BAUUpdateData
|
||||
}
|
||||
|
||||
object waiting = true;
|
||||
var dllPath = ModInfo.Assembly.Location;
|
||||
var dllPath = BAUPlugin.ModInfo.Assembly.Location;
|
||||
yield return GitHubFile.CoDownloadFile(DllLink, dllPath + ".temp", path =>
|
||||
{
|
||||
File.Move(dllPath, dllPath + ".old");
|
||||
@@ -152,6 +99,6 @@ internal sealed class BAUUpdateData
|
||||
/// <returns>A formatted string containing version information.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Version}:{ReleaseType}:{BetaNumber}:{HotfixNumber}";
|
||||
return $"{SemVersion.Parse(Version)}";
|
||||
}
|
||||
}
|
||||
@@ -80,7 +80,7 @@ internal sealed class NewsData()
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Failed to manually deserialize YAML: {ex.Message}");
|
||||
BAUPlugin.Logger.Error($"Failed to manually deserialize YAML: {ex.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ internal static class GitHubFile
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger_.Error($"Error downloading file from URL '{url}': {www.error} (Response Code: {(int)www.responseCode})");
|
||||
BAUPlugin.Logger.Error($"Error downloading file from URL '{url}': {www.error} (Response Code: {(int)www.responseCode})");
|
||||
if (showProgress)
|
||||
{
|
||||
CustomLoadingBarManager.SetLoadingPercent(100f, "Download Failed!");
|
||||
@@ -77,7 +77,7 @@ internal static class GitHubFile
|
||||
byte[] bytes = www.downloadHandler.GetNativeData().ToArray();
|
||||
File.WriteAllBytes(localFilePath, bytes);
|
||||
|
||||
Logger_.Log($"Saved file: {localFilePath}");
|
||||
BAUPlugin.Logger.Log($"Saved file: {localFilePath}");
|
||||
callback?.Invoke(localFilePath);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ internal static class GitHubFile
|
||||
|
||||
if (www.result != UnityWebRequest.Result.Success)
|
||||
{
|
||||
Logger_.Error($"Error downloading {url}: {www.error}");
|
||||
BAUPlugin.Logger.Error($"Error downloading {url}: {www.error}");
|
||||
yield break;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,7 +80,7 @@ internal sealed class GithubAPI : MonoBehaviour
|
||||
yield return newsLoader.CoFetchNewsData();
|
||||
|
||||
// Disable auto updating on Starlight
|
||||
if (!ModInfo.Starlight)
|
||||
if (!BAUPlugin.ModInfo.Starlight)
|
||||
{
|
||||
var updateLoader = gameObject.AddComponent<BAUUpdateLoader>();
|
||||
yield return updateLoader.CoFetchUpdateData();
|
||||
|
||||
@@ -25,10 +25,6 @@ internal sealed class BAUUpdateLoader : MonoBehaviour
|
||||
/// Coroutine to fetch update data from the remote repository.
|
||||
/// </summary>
|
||||
/// <returns>IEnumerator for coroutine execution.</returns>
|
||||
/// <remarks>
|
||||
/// If no internet connection is detected, it retries several times before giving up.
|
||||
/// After successfully loading update data, it initializes the UpdateManager.
|
||||
/// </remarks>
|
||||
[HideFromIl2Cpp]
|
||||
internal IEnumerator CoFetchUpdateData()
|
||||
{
|
||||
@@ -47,7 +43,7 @@ internal sealed class BAUUpdateLoader : MonoBehaviour
|
||||
}
|
||||
|
||||
string callBack = "";
|
||||
yield return GitHubFile.CoFetchTextFile(GitUrlPath.RepositoryApi.Combine("update.json").ToString(), (string text) =>
|
||||
yield return GitHubFile.CoFetchTextFile(GitUrlPath.RepositoryApi.Combine("update-V2.json").ToString(), (string text) =>
|
||||
{
|
||||
callBack = text;
|
||||
});
|
||||
@@ -65,7 +61,7 @@ internal sealed class BAUUpdateLoader : MonoBehaviour
|
||||
if (response != null)
|
||||
{
|
||||
UpdateInfo = response;
|
||||
Logger_.Log($"Loaded update info");
|
||||
BAUPlugin.Logger.Log($"Loaded update info");
|
||||
}
|
||||
|
||||
BAUUpdateManager.Init();
|
||||
|
||||
@@ -53,7 +53,7 @@ internal sealed class NewsLoader : MonoBehaviour
|
||||
|
||||
if (response == null || !response.ContainsKey("News"))
|
||||
{
|
||||
Logger_.Error("manifest.json deserialization failed or no 'News' key found.");
|
||||
BAUPlugin.Logger.Error("manifest.json deserialization failed or no 'News' key found.");
|
||||
yield break;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ internal sealed class NewsLoader : MonoBehaviour
|
||||
|
||||
yield return CoLoadNewsTest();
|
||||
|
||||
Logger_.Log($"Loaded {ModNews.NewsDataToProcess.Count} news files");
|
||||
BAUPlugin.Logger.Log($"Loaded {ModNews.NewsDataToProcess.Count} news files");
|
||||
|
||||
Destroy(this);
|
||||
}
|
||||
@@ -97,7 +97,7 @@ internal sealed class NewsLoader : MonoBehaviour
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Failed to deserialize yaml for '{fileName}': {ex.Message}");
|
||||
BAUPlugin.Logger.Error($"Failed to deserialize yaml for '{fileName}': {ex.Message}");
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ internal sealed class NewsLoader : MonoBehaviour
|
||||
private IEnumerator CoLoadNewsTest()
|
||||
{
|
||||
string yamlDirectory = "BetterAmongUs.Resources.NewsTest";
|
||||
var assembly = ModInfo.Assembly;
|
||||
var assembly = BAUPlugin.ModInfo.Assembly;
|
||||
using Stream? resourceStream = assembly.GetManifestResourceStream(yamlDirectory);
|
||||
if (resourceStream != null)
|
||||
{
|
||||
@@ -124,7 +124,7 @@ internal sealed class NewsLoader : MonoBehaviour
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Failed to deserialize yaml for '{yamlDirectory}': {ex.Message}");
|
||||
BAUPlugin.Logger.Error($"Failed to deserialize yaml for '{yamlDirectory}': {ex.Message}");
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ internal static class RPC
|
||||
{
|
||||
AmongUsClient.Instance.SendRpcImmediately(PlayerControl.LocalPlayer.MyPhysics.NetId, CUSTOM_RPC_CALL, SendOption.Reliable, writer =>
|
||||
{
|
||||
writer.Write(ModInfo.Constants.BAU_CUSTOM_RPC_FLAG); // Flag to check if its a rpc packed into SetNamePlateStr
|
||||
writer.Write(BAUPlugin.Constants.BAU_CUSTOM_RPC_FLAG); // Flag to check if its a rpc packed into SetNamePlateStr
|
||||
writer.Write((byte)customRPC);
|
||||
action(writer);
|
||||
}, targetClientId);
|
||||
@@ -120,7 +120,7 @@ internal static class RPC
|
||||
{
|
||||
try
|
||||
{
|
||||
if (reader.ReadString() == ModInfo.Constants.BAU_CUSTOM_RPC_FLAG)
|
||||
if (reader.ReadString() == BAUPlugin.Constants.BAU_CUSTOM_RPC_FLAG)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ internal static class ClientPatch
|
||||
private static bool SignInStatusComponent_SetOnline_Prefix()
|
||||
{
|
||||
// Get supported Among Us versions for BAU
|
||||
var varSupportedVersions = ModInfo.SupportedAmongUsVersions;
|
||||
var varSupportedVersions = BAUPlugin.ModInfo.SupportedAmongUsVersions;
|
||||
Version currentVersion = new(BAUPlugin.AppVersion);
|
||||
Version firstSupportedVersion = new(varSupportedVersions.First());
|
||||
Version lastSupportedVersion = new(varSupportedVersions.Last());
|
||||
@@ -56,7 +56,7 @@ internal static class ClientPatch
|
||||
|
||||
// Show warning popup for newer Among Us version
|
||||
Utils.ShowPopUp($"<size=200%>-= <color=#ff2200><b>Warning</b></color> =-</size>\n\n" +
|
||||
$"<size=125%><color=#0dff00>Better Among Us {BAUPlugin.GetVersionText()}</color>\nsupports <color=#4f92ff>Among Us {verText}</color>,\n" +
|
||||
$"<size=125%><color=#0dff00>Better Among Us {BAUPlugin.ModInfo.VERSION_STRING}</color>\nsupports <color=#4f92ff>Among Us {verText}</color>,\n" +
|
||||
$"<color=#4f92ff>Among Us <b>{BAUPlugin.AppVersion}</b></color> is above the supported versions!\n" +
|
||||
$"<color=#ae1700>You may encounter minor to game breaking bugs.</color></size>");
|
||||
}
|
||||
@@ -71,7 +71,7 @@ internal static class ClientPatch
|
||||
|
||||
// Show warning popup for older Among Us version
|
||||
Utils.ShowPopUp($"<size=200%>-= <color=#ff2200><b>Warning</b></color> =-</size>\n\n" +
|
||||
$"<size=125%><color=#0dff00>Better Among Us {BAUPlugin.GetVersionText()}</color>\nsupports <color=#4f92ff>Among Us {verText}</color>,\n" +
|
||||
$"<size=125%><color=#0dff00>Better Among Us {BAUPlugin.ModInfo.VERSION_STRING}</color>\nsupports <color=#4f92ff>Among Us {verText}</color>,\n" +
|
||||
$"<color=#4f92ff>Among Us <b>{BAUPlugin.AppVersion}</b></color> is below the supported versions!\n" +
|
||||
$"<color=#ae1700>You may encounter minor to game breaking bugs.</color></size>");
|
||||
}
|
||||
@@ -86,7 +86,7 @@ internal static class ClientPatch
|
||||
// Hide custom loading bar when exiting game
|
||||
CustomLoadingBarManager.ToggleLoadingBar(false);
|
||||
|
||||
Logger_.Log($"Client has left game for: {Enum.GetName(reason)}", "AmongUsClientPatch");
|
||||
BAUPlugin.Logger.Log($"Client has left game for: {Enum.GetName(reason)}", "AmongUsClientPatch");
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnGameEnd))]
|
||||
|
||||
@@ -23,7 +23,7 @@ internal static class DiscordPatch
|
||||
if (activity == null)
|
||||
return;
|
||||
|
||||
string details = $"BAU {BAUPlugin.GetVersionText()}";
|
||||
string details = $"BAU {BAUPlugin.ModInfo.VERSION_STRING}";
|
||||
activity.Details = details;
|
||||
|
||||
// Skip lobby info processing if Discord already shows "In Menus"
|
||||
@@ -50,7 +50,7 @@ internal static class DiscordPatch
|
||||
{
|
||||
// Streamer mode hides lobby code, only show mode info
|
||||
if (GameState.IsHideNSeek)
|
||||
details = $"BAU v{ModInfo.PLUGIN_VERSION} - Hide & Seek";
|
||||
details = $"BAU v{BAUPlugin.ModInfo.VERSION_STRING} - Hide & Seek";
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -5,6 +5,7 @@ using BetterAmongUs.Generated;
|
||||
using BetterAmongUs.Managers;
|
||||
using BetterAmongUs.Modules;
|
||||
using BetterAmongUs.MonoScripts.Extended;
|
||||
using BetterAmongUs.Patches.Gameplay.Player;
|
||||
using BetterAmongUs.Patches.Gameplay.UI;
|
||||
using BetterAmongUs.Patches.Gameplay.UI.Chat;
|
||||
using BetterAmongUs.Utilities;
|
||||
@@ -55,12 +56,14 @@ internal static class OptionsMenuBehaviourPatch
|
||||
ClientOptionItem.CreateToggle(TranslationStrings.BetterOption_UnlockFPS, BAUConfigs.UnlockFPS, 1, __instance, UpdateFrameRate);
|
||||
ClientOptionItem.CreateToggle(TranslationStrings.BetterOption_ShowFPS, BAUConfigs.ShowFPS, 1, __instance);
|
||||
|
||||
ClientOptionItem.CreateToggle(TranslationStrings.BetterOption_VentColorGroups, BAUConfigs.VentColorGroups, 2, __instance, MiniMapBehaviourPatch.ClearMapIcons);
|
||||
ClientOptionItem.CreateToggle(TranslationStrings.BetterOption_MinimapIcons, BAUConfigs.MinimapIcons, 2, __instance, MiniMapBehaviourPatch.ClearMapIcons);
|
||||
ClientOptionItem.CreateToggle(TranslationStrings.BetterOption_MinimapIcons, BAUConfigs.MinimapIcons, 2, __instance, MiniMapBehaviourPatch.ForceCloseMiniMap);
|
||||
ClientOptionItem.CreateToggle(TranslationStrings.BetterOption_BetterMinimapColors, BAUConfigs.BetterMinimapColors, 2, __instance, MiniMapBehaviourPatch.ForceCloseMiniMap);
|
||||
ClientOptionItem.CreateToggle(TranslationStrings.BetterOption_VentColorGroups, BAUConfigs.VentColorGroups, 2, __instance, MiniMapBehaviourPatch.ForceCloseMiniMap);
|
||||
ClientOptionItem.CreateToggle(TranslationStrings.BetterOption_BetterColorblindText, BAUConfigs.BetterColorblindText, 2, __instance, CosmeticsLayerPatch.UpdateAllColorblindText);
|
||||
ClientOptionItem.CreateToggle(TranslationStrings.BetterOption_CompressSettingFiles, BAUConfigs.CompressSettingFiles, 2, __instance, ConvertAllSettingFiles);
|
||||
|
||||
// Button options (no toggle)
|
||||
if (!ModInfo.Starlight)
|
||||
if (!BAUPlugin.ModInfo.Starlight)
|
||||
{
|
||||
ClientOptionItem.CreateButton(TranslationStrings.BetterOption_SaveData, -1, __instance, OpenSaveData, () =>
|
||||
{
|
||||
|
||||
@@ -13,6 +13,6 @@ internal static class VersionShowerPatch
|
||||
{
|
||||
string mark = TranslationStrings.BAUMark.LocalizedString;
|
||||
string bau = TranslationStrings.BAU.LocalizedString;
|
||||
__instance.text.text = $"<color=#0dff00>{mark}{bau}{mark} {BAUPlugin.GetVersionText()}</color> <color=#ababab>~</color> {Utils.GetPlatformName(BAUPlugin.PlatformData.Platform)} v{BAUPlugin.AmongUsVersion} ({BAUPlugin.AppVersion})";
|
||||
__instance.text.text = $"<color=#0dff00>{mark}{bau}{mark} {BAUPlugin.ModInfo.VERSION_STRING}</color> <color=#ababab>~</color> {Utils.GetPlatformName(BAUPlugin.PlatformData.Platform)} v{BAUPlugin.AmongUsVersion} ({BAUPlugin.AppVersion})";
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using BetterAmongUs.Utilities;
|
||||
using BetterAmongUs.Modules;
|
||||
using BetterAmongUs.Modules;
|
||||
using BetterAmongUs.Patches.Gameplay.UI.Settings;
|
||||
using BetterAmongUs.Utilities;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace BetterAmongUs.Patches.Gameplay.Anticheat;
|
||||
@@ -20,6 +20,10 @@ internal static class CheckPlayerLevelPatch
|
||||
// Kick players below minimum level
|
||||
if (!__instance.IsLocalPlayer() && BetterGameSettings.KickLevel.GetBool() && __instance.Data.PlayerLevel < BetterGameSettings.KickLevelBelow.GetInt())
|
||||
{
|
||||
var minPlayers = BetterGameSettings.KickLevelBelowMinimumPlayers.GetInt();
|
||||
if (minPlayers > 1 && minPlayers > BAUPlugin.AllPlayerControls.Count)
|
||||
return;
|
||||
|
||||
__instance.TryKick(setReasonInfo: $" is level {__instance.Data.PlayerLevel}, level must be equal or above {BetterGameSettings.KickLevelBelow.GetInt()} to join");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using BepInEx.Unity.IL2CPP.Utils;
|
||||
using BetterAmongUs.Data.Config;
|
||||
using BetterAmongUs.Enums;
|
||||
using BetterAmongUs.Generated;
|
||||
using BetterAmongUs.Managers;
|
||||
using BetterAmongUs.Modules;
|
||||
@@ -40,6 +41,11 @@ internal static class PlatformSpoofPatch
|
||||
|
||||
if (player != null && __instance != null)
|
||||
{
|
||||
if (__instance.Platform == (Platforms)CustomPlatforms.Starlight)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Check Xbox/Windows store players for invalid platform ID length
|
||||
if (__instance.Platform is Platforms.StandaloneWin10 or Platforms.Xbox)
|
||||
{
|
||||
@@ -51,7 +57,7 @@ internal static class PlatformSpoofPatch
|
||||
TranslationStrings.AntiCheat_Reason_PlatformSpoofer.LocalizedString,
|
||||
TranslationStrings.AntiCheat_HasBeenDetectedWithCheat.LocalizedString
|
||||
);
|
||||
Logger_.LogCheat($"{player.ExtendedData().RealName} {TranslationStrings.AntiCheat_Reason_PlatformSpoofer}: {__instance.XboxPlatformId}");
|
||||
BAUPlugin.Logger.LogCheat($"{player.ExtendedData().RealName} {TranslationStrings.AntiCheat_Reason_PlatformSpoofer}: {__instance.XboxPlatformId}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,7 +72,7 @@ internal static class PlatformSpoofPatch
|
||||
TranslationStrings.AntiCheat_Reason_PlatformSpoofer.LocalizedString,
|
||||
TranslationStrings.AntiCheat_HasBeenDetectedWithCheat.LocalizedString
|
||||
);
|
||||
Logger_.LogCheat($"{player.ExtendedData().RealName} {TranslationStrings.AntiCheat_Reason_PlatformSpoofer}: {__instance.PsnPlatformId}");
|
||||
BAUPlugin.Logger.LogCheat($"{player.ExtendedData().RealName} {TranslationStrings.AntiCheat_Reason_PlatformSpoofer}: {__instance.PsnPlatformId}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ internal static class VoteBanSystemPatch
|
||||
maxVotes = votes.Length; // Total possible votes
|
||||
}
|
||||
|
||||
Logger_.InGame(
|
||||
BAUPlugin.Logger.InGame(
|
||||
$"{src.Character?.GetPlayerNameAndColor() ?? src.PlayerName} " +
|
||||
$"voted to kick {client.Character?.GetPlayerNameAndColor() ?? client.PlayerName} " +
|
||||
$"<#6F6F6F>(</color><#FFFFFF>{currentVotes}</color><#6F6F6F>/</color><#FFFFFF>{maxVotes}</color><#6F6F6F>)</color>"
|
||||
|
||||
@@ -160,6 +160,6 @@ internal static class LobbyPatch
|
||||
[HarmonyPrefix]
|
||||
private static void GameStartManager_FinallyBegin_Prefix(/*GameStartManager __instance*/)
|
||||
{
|
||||
Logger_.LogHeader($"Game Has Started - {Enum.GetName(typeof(MapNames), GameState.GetActiveMapId)}/{GameState.GetActiveMapId}", "GamePlayManager");
|
||||
BAUPlugin.Logger.LogHeader($"Game Has Started - {Enum.GetName(typeof(MapNames), GameState.GetActiveMapId)}/{GameState.GetActiveMapId}", "GamePlayManager");
|
||||
}
|
||||
}
|
||||
@@ -114,14 +114,24 @@ internal static class FindAGameManagerPatch
|
||||
Transform child = container.transform.Find("Container");
|
||||
Transform tmproObject = child.Find("TrueHostName_TMP");
|
||||
|
||||
// Use existing TMP component or create new one
|
||||
TMP_Text tmpro = tmproObject != null
|
||||
? tmproObject.GetComponent<TextMeshPro>()
|
||||
: CreateNewTextMeshPro(child);
|
||||
TMP_Text? tmpro = null;
|
||||
|
||||
tmpro.font = container.capacity.font;
|
||||
tmpro.fontSize = 3f;
|
||||
tmpro.text = FormatGameInfoText(container.gameListing);
|
||||
if (tmproObject != null)
|
||||
{
|
||||
tmpro = tmproObject.GetComponent<TextMeshPro>();
|
||||
}
|
||||
|
||||
if (tmpro == null)
|
||||
{
|
||||
tmpro = CreateNewTextMeshPro(child);
|
||||
}
|
||||
|
||||
if (tmpro != null)
|
||||
{
|
||||
tmpro.font = container.capacity?.font;
|
||||
tmpro.fontSize = 3f;
|
||||
tmpro.text = FormatGameInfoText(container.gameListing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace BetterAmongUs.Patches.Gameplay.Managers;
|
||||
[HarmonyPatch]
|
||||
internal static class HudManagerPatch
|
||||
{
|
||||
internal static string WelcomeMessage => $"<b><color=#00b530><size=125%><align=\"center\">{TranslationStrings.WelcomeMsg_WelcomeToBAU.Format(TranslationStrings.BetterAmongUs)}\n{BAUPlugin.GetVersionText()}</size>\n" +
|
||||
internal static string WelcomeMessage => $"<b><color=#00b530><size=125%><align=\"center\">{TranslationStrings.WelcomeMsg_WelcomeToBAU.Format(TranslationStrings.BetterAmongUs)}\n{BAUPlugin.ModInfo.VERSION_STRING}</size>\n" +
|
||||
$"{TranslationStrings.WelcomeMsg_ThanksForDownloading}</align></color></b>\n<size=120%> </size>\n" +
|
||||
TranslationStrings.WelcomeMsg_BAUDescription1.Format(TranslationStrings.BAU, TranslationStrings.BetterOption_AntiCheat);
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using AmongUs.GameOptions;
|
||||
using BetterAmongUs.Utilities;
|
||||
using BetterAmongUs.Utilities;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace BetterAmongUs.Patches.Gameplay.Options;
|
||||
@@ -15,7 +14,7 @@ internal static class LogicOptionsPatch
|
||||
return;
|
||||
|
||||
// Show anonymous votes when dead and not Guardian Angel
|
||||
if (!PlayerControl.LocalPlayer.IsAlive() && !PlayerControl.LocalPlayer.Is(RoleTypes.GuardianAngel))
|
||||
if (!PlayerControl.LocalPlayer.IsAlive() && !PlayerControl.LocalPlayer.IsGhostRole())
|
||||
{
|
||||
__result = false;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using BetterAmongUs.Utilities;
|
||||
using BetterAmongUs.Data.Config;
|
||||
using BetterAmongUs.Modules.Support;
|
||||
using BetterAmongUs.Utilities;
|
||||
using HarmonyLib;
|
||||
|
||||
namespace BetterAmongUs.Patches.Gameplay.Player;
|
||||
@@ -7,11 +8,27 @@ namespace BetterAmongUs.Patches.Gameplay.Player;
|
||||
[HarmonyPatch]
|
||||
internal static class CosmeticsLayerPatch
|
||||
{
|
||||
internal static void UpdateAllColorblindText()
|
||||
{
|
||||
foreach (var player in PlayerControl.AllPlayerControls)
|
||||
{
|
||||
player.cosmetics.colorBlindText.text = player.cosmetics.GetColorBlindText();
|
||||
}
|
||||
|
||||
if (MeetingHud.Instance != null)
|
||||
{
|
||||
foreach (var pva in MeetingHud.Instance.playerStates)
|
||||
{
|
||||
pva.SetColorblindText();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(CosmeticsLayer), nameof(CosmeticsLayer.GetColorBlindText))]
|
||||
[HarmonyPrefix]
|
||||
private static bool CosmeticsLayer_GetColorBlindText_Prefix(CosmeticsLayer __instance, ref string __result)
|
||||
{
|
||||
if (BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_CustomColorBlindText))
|
||||
if (!BAUConfigs.BetterColorblindText.Value || BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_CustomColorBlindText))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ internal static class PlayerControlPatch
|
||||
return;
|
||||
|
||||
// Log kill event with player names and roles
|
||||
Logger_.LogPrivate($"{__instance.Data.PlayerName} Has killed {target.Data.PlayerName} as {__instance.Data.RoleType.GetRoleName()}", "EventLog");
|
||||
BAUPlugin.Logger.LogPrivate($"{__instance.Data.PlayerName} Has killed {target.Data.PlayerName} as {__instance.Data.RoleType.GetRoleName()}", "EventLog");
|
||||
|
||||
// Track kill count in player's BetterData
|
||||
if (resultFlags.HasFlag(MurderResultFlags.Succeeded) || resultFlags.HasFlag(MurderResultFlags.DecisionByHost))
|
||||
@@ -104,7 +104,7 @@ internal static class PlayerControlPatch
|
||||
if (targetPlayer == null)
|
||||
return;
|
||||
|
||||
if (!BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_CustomColorBlindText))
|
||||
if (BAUConfigs.BetterColorblindText.Value && !BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_CustomColorBlindText))
|
||||
{
|
||||
if (targetPlayer.Data.PlayerId == __instance.Data.PlayerId)
|
||||
{
|
||||
@@ -118,9 +118,9 @@ internal static class PlayerControlPatch
|
||||
|
||||
// Log shapeshift events (both shifting and unshifting)
|
||||
if (__instance != targetPlayer)
|
||||
Logger_.LogPrivate($"{__instance.Data.PlayerName} Has Shapeshifted into {targetPlayer.Data.PlayerName}, did animate: {animate}", "EventLog");
|
||||
BAUPlugin.Logger.LogPrivate($"{__instance.Data.PlayerName} Has Shapeshifted into {targetPlayer.Data.PlayerName}, did animate: {animate}", "EventLog");
|
||||
else
|
||||
Logger_.LogPrivate($"{__instance.Data.PlayerName} Has Un-Shapeshifted, did animate: {animate}", "EventLog");
|
||||
BAUPlugin.Logger.LogPrivate($"{__instance.Data.PlayerName} Has Un-Shapeshifted, did animate: {animate}", "EventLog");
|
||||
}
|
||||
|
||||
private static IEnumerator CoSetColorEarly(PlayerControl __instance)
|
||||
@@ -135,9 +135,9 @@ internal static class PlayerControlPatch
|
||||
{
|
||||
// Log Phantom role visibility changes
|
||||
if (isActive)
|
||||
Logger_.LogPrivate($"{__instance.Data.PlayerName} Has Vanished as Phantom, did animate: {shouldAnimate}", "EventLog");
|
||||
BAUPlugin.Logger.LogPrivate($"{__instance.Data.PlayerName} Has Vanished as Phantom, did animate: {shouldAnimate}", "EventLog");
|
||||
else
|
||||
Logger_.LogPrivate($"{__instance.Data.PlayerName} Has Appeared as Phantom, did animate: {shouldAnimate}", "EventLog");
|
||||
BAUPlugin.Logger.LogPrivate($"{__instance.Data.PlayerName} Has Appeared as Phantom, did animate: {shouldAnimate}", "EventLog");
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerControl), nameof(PlayerControl.SetName))]
|
||||
@@ -163,7 +163,7 @@ internal static class PlayerControlPatch
|
||||
private static void PlayerPhysics_BootFromVent_Postfix(PlayerPhysics __instance, int ventId)
|
||||
{
|
||||
// Log vent boot events (when engineer boots someone)
|
||||
Logger_.LogPrivate($"{__instance.myPlayer.Data.PlayerName} Has been booted from vent: {ventId}, as {__instance.myPlayer.Data.RoleType.GetRoleName()}", "EventLog");
|
||||
BAUPlugin.Logger.LogPrivate($"{__instance.myPlayer.Data.PlayerName} Has been booted from vent: {ventId}, as {__instance.myPlayer.Data.RoleType.GetRoleName()}", "EventLog");
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerPhysics), nameof(PlayerPhysics.CoEnterVent))]
|
||||
@@ -171,7 +171,7 @@ internal static class PlayerControlPatch
|
||||
private static void PlayerPhysics_CoEnterVent_Postfix(PlayerPhysics __instance, int id)
|
||||
{
|
||||
// Log vent entry events
|
||||
Logger_.LogPrivate($"{__instance.myPlayer.Data.PlayerName} Has entered vent: {id}, as {__instance.myPlayer.Data.RoleType.GetRoleName()}", "EventLog");
|
||||
BAUPlugin.Logger.LogPrivate($"{__instance.myPlayer.Data.PlayerName} Has entered vent: {id}, as {__instance.myPlayer.Data.RoleType.GetRoleName()}", "EventLog");
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(PlayerPhysics), nameof(PlayerPhysics.CoExitVent))]
|
||||
@@ -179,6 +179,6 @@ internal static class PlayerControlPatch
|
||||
private static void PlayerPhysics_CoExitVent_Postfix(PlayerPhysics __instance, int id)
|
||||
{
|
||||
// Log vent exit events
|
||||
Logger_.LogPrivate($"{__instance.myPlayer.Data.PlayerName} Has exit vent: {id}, as {__instance.myPlayer.Data.RoleType.GetRoleName()}", "EventLog");
|
||||
BAUPlugin.Logger.LogPrivate($"{__instance.myPlayer.Data.PlayerName} Has exit vent: {id}, as {__instance.myPlayer.Data.RoleType.GetRoleName()}", "EventLog");
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ internal static class PlayerJoinAndLeftPatch
|
||||
host?.SetColor(host.CurrentOutfit.ColorId);
|
||||
}
|
||||
|
||||
Logger_.Log($"Successfully joined {GameCode.IntToGameName(AmongUsClient.Instance.GameId)}", "OnGameJoinedPatch");
|
||||
BAUPlugin.Logger.Log($"Successfully joined {GameCode.IntToGameName(AmongUsClient.Instance.GameId)}", "OnGameJoinedPatch");
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(AmongUsClient), nameof(AmongUsClient.OnPlayerJoined))]
|
||||
@@ -74,7 +74,8 @@ internal static class PlayerJoinAndLeftPatch
|
||||
{
|
||||
if (player != null)
|
||||
{
|
||||
if (TextFileHandler.CompareStringFilters(BetterDataManager.Files.banNameListFilePath, [player.Data.PlayerName]))
|
||||
if (TextFileHandler.CompareStringRegexMatches(BetterDataManager.Files.banNameListFilePath,
|
||||
player.Data.PlayerName))
|
||||
{
|
||||
player.Kick(true, TranslationStrings.AntiCheat_BanNameListMessage.LocalizedString, bypassDataCheck: true);
|
||||
}
|
||||
@@ -152,7 +153,7 @@ internal static class PlayerJoinAndLeftPatch
|
||||
{
|
||||
var ReasonText = $"<color=#ff0>{playerData.ExtendedData().RealName}</color> {forceReasonText}";
|
||||
|
||||
Logger_.Log(ReasonText);
|
||||
BAUPlugin.Logger.Log(ReasonText);
|
||||
|
||||
HudManager.Instance.Notifier.AddDisconnectMessage(ReasonText);
|
||||
}
|
||||
@@ -189,7 +190,7 @@ internal static class PlayerJoinAndLeftPatch
|
||||
break;
|
||||
}
|
||||
|
||||
Logger_.Log(ReasonText);
|
||||
BAUPlugin.Logger.Log(ReasonText);
|
||||
|
||||
// Add formatted disconnect message to game UI
|
||||
HudManager.Instance.Notifier.AddDisconnectMessage(ReasonText);
|
||||
|
||||
@@ -8,7 +8,6 @@ using BetterAmongUs.Structs;
|
||||
using BetterAmongUs.Utilities;
|
||||
using BetterAmongUs.Utilities.Extension;
|
||||
using HarmonyLib;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BetterAmongUs.Patches.Gameplay.UI.Chat;
|
||||
@@ -218,14 +217,7 @@ internal static class ChatPatch
|
||||
private static void ChatController_AddChat_Postfix(ChatController __instance, PlayerControl sourcePlayer, string chatText)
|
||||
{
|
||||
// Log chat publicly if player is alive, privately if dead
|
||||
if (sourcePlayer.IsAlive() || !PlayerControl.LocalPlayer.IsAlive())
|
||||
{
|
||||
Logger_.Log($"{sourcePlayer.Data.PlayerName} -> {chatText}", "ChatLog");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger_.LogPrivate($"{sourcePlayer.Data.PlayerName} -> {chatText}", "ChatLog");
|
||||
}
|
||||
BAUPlugin.Logger.LogPrivate($"{sourcePlayer.Data.PlayerName} -> {chatText}", "ChatLog");
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ChatController), nameof(ChatController.SetChatBubbleName))]
|
||||
@@ -294,9 +286,16 @@ internal static class ChatPatch
|
||||
bubble.NameText.SetText(playerName);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ChatBubble), nameof(ChatBubble.SetName))]
|
||||
[HarmonyPostfix]
|
||||
private static void ChatBubble_SetName_Postfix(ChatBubble __instance)
|
||||
{
|
||||
SetChatPoolTheme(__instance);
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(ChatController), nameof(ChatController.GetPooledBubble))]
|
||||
[HarmonyPostfix]
|
||||
private static void ChatController_GetPooledBubble_Postfix(ChatController __instance, ChatBubble __result)
|
||||
private static void ChatController_GetPooledBubble_Postfix(ChatBubble __result)
|
||||
{
|
||||
SetChatPoolTheme(__result);
|
||||
}
|
||||
@@ -323,38 +322,29 @@ internal static class ChatPatch
|
||||
chat.quickChatButton.transform.Find("QuickChatIcon").GetComponent<SpriteRenderer>().color = new Color(1f, 1f, 1f, 1f);
|
||||
chat.openKeyboardButton.transform.Find("OpenKeyboardIcon").GetComponent<SpriteRenderer>().color = new Color(1f, 1f, 1f, 1f);
|
||||
}
|
||||
|
||||
// Apply theme to all existing chat bubbles
|
||||
foreach (var item in HudManager.Instance.Chat.chatBubblePool.activeChildren.SelectIl2Cpp(c => c.GetComponent<ChatBubble>()))
|
||||
{
|
||||
SetChatPoolTheme(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply theme to individual chat bubble
|
||||
internal static ChatBubble SetChatPoolTheme(ChatBubble asChatBubble)
|
||||
{
|
||||
var chatBubble = asChatBubble;
|
||||
|
||||
var alpha = chatBubble.Background.color.a;
|
||||
if (BAUConfigs.ChatDarkMode.Value)
|
||||
{
|
||||
chatBubble.transform.Find("ChatText (TMP)").GetComponentInChildren<TextMeshPro>(true).color = Color.white;
|
||||
chatBubble.transform.Find("Background").GetComponentInChildren<SpriteRenderer>(true).color = new Color(0.15f, 0.15f, 0.15f, 1f);
|
||||
|
||||
var mark = chatBubble.transform.Find("PoolablePlayer/xMark");
|
||||
if (mark != null && mark.GetComponentInChildren<SpriteRenderer>(true).enabled)
|
||||
{
|
||||
chatBubble.transform.Find("Background").GetComponentInChildren<SpriteRenderer>(true).color = new Color(0.15f, 0.15f, 0.15f, 0.5f);
|
||||
}
|
||||
chatBubble.TextArea.color = Color.white;
|
||||
chatBubble.Background.color = new Color(0.15f, 0.15f, 0.15f, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
chatBubble.transform.Find("ChatText (TMP)").GetComponentInChildren<TextMeshPro>(true).color = Color.black;
|
||||
chatBubble.transform.Find("Background").GetComponentInChildren<SpriteRenderer>(true).color = Color.white;
|
||||
|
||||
var mark = chatBubble.transform.Find("PoolablePlayer/xMark");
|
||||
if (mark != null && mark.GetComponentInChildren<SpriteRenderer>(true).enabled)
|
||||
{
|
||||
chatBubble.transform.Find("Background").GetComponentInChildren<SpriteRenderer>(true).color = new Color(1f, 1f, 1f, 0.5f);
|
||||
}
|
||||
chatBubble.TextArea.color = new Color(0.15f, 0.15f, 0.15f);
|
||||
chatBubble.Background.color = new Color(1f, 1f, 1f, alpha);
|
||||
}
|
||||
|
||||
return chatBubble;
|
||||
@@ -369,8 +359,8 @@ internal static class ChatPatch
|
||||
__instance.textArea.AllowSymbols = true;
|
||||
__instance.textArea.AllowPaste = true;
|
||||
__instance.textArea.AllowEmail = true;
|
||||
__instance.textArea.characterLimit = ModInfo.Constants.MAX_CHAT_TEXT;
|
||||
__instance.charCountText.text = "0/" + ModInfo.Constants.MAX_CHAT_TEXT;
|
||||
__instance.textArea.characterLimit = BAUPlugin.Constants.MAX_CHAT_TEXT;
|
||||
__instance.charCountText.text = "0/" + BAUPlugin.Constants.MAX_CHAT_TEXT;
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(FreeChatInputField), nameof(FreeChatInputField.UpdateCharCount))]
|
||||
@@ -379,7 +369,7 @@ internal static class ChatPatch
|
||||
{
|
||||
// Update character counter with color coding
|
||||
int length = __instance.textArea.text.Length;
|
||||
__instance.charCountText.text = string.Format("{0}/" + ModInfo.Constants.MAX_CHAT_TEXT, length);
|
||||
__instance.charCountText.text = string.Format("{0}/" + BAUPlugin.Constants.MAX_CHAT_TEXT, length);
|
||||
__instance.charCountText.color = GetCharColor(length);
|
||||
}
|
||||
|
||||
@@ -387,7 +377,7 @@ internal static class ChatPatch
|
||||
{
|
||||
// Color gradient: green -> yellow -> red as text length increases
|
||||
Color[] colorGradient = [Color.green, Color.yellow, Color.red];
|
||||
(float min, float max) lerpRange = (0f, ModInfo.Constants.MAX_CHAT_TEXT - 1);
|
||||
(float min, float max) lerpRange = (0f, BAUPlugin.Constants.MAX_CHAT_TEXT - 1);
|
||||
return colorGradient.LerpColor(lerpRange, length);
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,8 @@ internal static class GameSummaryPatch
|
||||
// Log game end info to console
|
||||
private static void LogGameEnd()
|
||||
{
|
||||
Logger_.LogHeader($"Game Has Ended - {Enum.GetName(typeof(MapNames), GameState.GetActiveMapId)}/{GameState.GetActiveMapId}", "GamePlayManager");
|
||||
Logger_.LogHeader("Game Summary Start", "GameSummary");
|
||||
BAUPlugin.Logger.LogHeader($"Game Has Ended - {Enum.GetName(typeof(MapNames), GameState.GetActiveMapId)}/{GameState.GetActiveMapId}", "GamePlayManager");
|
||||
BAUPlugin.Logger.LogHeader("Game Summary Start", "GameSummary");
|
||||
}
|
||||
|
||||
// Creates the visual game summary on screen
|
||||
@@ -52,14 +52,14 @@ internal static class GameSummaryPatch
|
||||
|
||||
// Get win condition info
|
||||
var (winTeam, winTag, winColor) = GetWinInfo();
|
||||
Logger_.Log($"{winTeam}: {winTag}", "GameSummary");
|
||||
BAUPlugin.Logger.Log($"{winTeam}: {winTag}", "GameSummary");
|
||||
|
||||
// Build and display summary text
|
||||
var summaryHeader = BuildSummaryHeader(winTeam, winTag, winColor);
|
||||
var playerList = BuildPlayerList();
|
||||
|
||||
summaryText.text = $"{summaryHeader}\n\n<size=58%>{playerList}</size>";
|
||||
Logger_.LogHeader("Game Summary End", "GameSummary");
|
||||
BAUPlugin.Logger.LogHeader("Game Summary End", "GameSummary");
|
||||
}
|
||||
|
||||
// Creates the text object for the summary
|
||||
@@ -191,7 +191,7 @@ internal static class GameSummaryPatch
|
||||
|
||||
var playerLine = BuildPlayerLine(playerData);
|
||||
stringBuilder.AppendLine($"- {playerLine}\n");
|
||||
Logger_.Log(Utils.RemoveHtmlText(playerLine).Replace("\n", " "), "GameSummary");
|
||||
BAUPlugin.Logger.Log(Utils.RemoveHtmlText(playerLine).Replace("\n", " "), "GameSummary");
|
||||
}
|
||||
|
||||
return stringBuilder;
|
||||
|
||||
@@ -54,7 +54,7 @@ internal static class MeetingHudPatch
|
||||
MeetingHud.Instance.ProceedButton.DestroyTextTranslators();
|
||||
}
|
||||
|
||||
Logger_.LogHeader("Meeting Has Started");
|
||||
BAUPlugin.Logger.LogHeader("Meeting Has Started");
|
||||
}
|
||||
|
||||
// Updates host icon with current host info
|
||||
@@ -134,6 +134,6 @@ internal static class MeetingHudPatch
|
||||
}
|
||||
|
||||
timeOpen = 0f;
|
||||
Logger_.LogHeader("Meeting Has Ended");
|
||||
BAUPlugin.Logger.LogHeader("Meeting Has Ended");
|
||||
}
|
||||
}
|
||||
@@ -20,39 +20,68 @@ internal static class MiniMapBehaviourPatch
|
||||
[HarmonyPatch(typeof(MapBehaviour), nameof(MapBehaviour.ShowNormalMap))]
|
||||
[HarmonyPostfix]
|
||||
private static void MapBehaviour_ShowNormalMap_Postfix(MapBehaviour __instance)
|
||||
=> __instance.ColorControl.SetColor(new Color(0.05f, 0.6f, 1f, 1f)); // Blue tint for normal map
|
||||
{
|
||||
if (!BAUConfigs.BetterMinimapColors.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
__instance.ColorControl.SetColor(new Color(0.05f, 0.6f, 1f, 1f));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(MapBehaviour), nameof(MapBehaviour.ShowDetectiveMap))]
|
||||
[HarmonyPostfix]
|
||||
private static void MapBehaviour_ShowDetectiveMap_Postfix(MapBehaviour __instance)
|
||||
=> __instance.ColorControl.SetColor(new Color(0.05f, 0.6f, 1f, 1f)); // Blue tint for detective map
|
||||
{
|
||||
if (!BAUConfigs.BetterMinimapColors.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
__instance.ColorControl.SetColor(new Color(0.05f, 0.6f, 1f, 1f));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(MapBehaviour), nameof(MapBehaviour.ShowSabotageMap))]
|
||||
[HarmonyPostfix]
|
||||
private static void MapBehaviour_ShowSabotageMap_Postfix(MapBehaviour __instance)
|
||||
=> __instance.ColorControl.SetColor(new Color(1f, 0.3f, 0f, 1f)); // Orange tint for sabotage map
|
||||
{
|
||||
if (!BAUConfigs.BetterMinimapColors.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
__instance.ColorControl.SetColor(new Color(1f, 0.3f, 0f, 1f));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(MapCountOverlay), nameof(MapCountOverlay.OnEnable))]
|
||||
[HarmonyPostfix]
|
||||
private static void MapCountOverlay_OnEnable_Postfix(MapCountOverlay __instance)
|
||||
// Green background normally, gray if comms sabotaged
|
||||
=> __instance.BackgroundColor.SetColor(PlayerTask.PlayerHasTaskOfType<IHudOverrideTask>(PlayerControl.LocalPlayer) ? Palette.DisabledGrey : new Color(0.2f, 0.5f, 0f, 1f));
|
||||
{
|
||||
if (!BAUConfigs.BetterMinimapColors.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
__instance.BackgroundColor.SetColor(PlayerTask.PlayerHasTaskOfType<IHudOverrideTask>(PlayerControl.LocalPlayer) ? Palette.DisabledGrey : new Color(0.2f, 0.5f, 0f, 1f));
|
||||
}
|
||||
|
||||
[HarmonyPatch(typeof(MapCountOverlay), nameof(MapCountOverlay.Update))]
|
||||
[HarmonyPrefix]
|
||||
private static void MapCountOverlay_Update_Prefix(MapCountOverlay __instance)
|
||||
{
|
||||
// Handle comms sabotage effect on map
|
||||
if (!BAUConfigs.BetterMinimapColors.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (PlayerTask.PlayerHasTaskOfType<IHudOverrideTask>(PlayerControl.LocalPlayer))
|
||||
{
|
||||
// Comms sabotaged - disable map
|
||||
__instance.isSab = true;
|
||||
__instance.BackgroundColor.SetColor(Palette.DisabledGrey);
|
||||
__instance.SabotageText.gameObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Comms working - normal map
|
||||
__instance.isSab = false;
|
||||
__instance.BackgroundColor.SetColor(new Color(0.2f, 0.5f, 0f, 1f));
|
||||
__instance.SabotageText.gameObject.SetActive(false);
|
||||
@@ -62,14 +91,21 @@ internal static class MiniMapBehaviourPatch
|
||||
[HarmonyPatch(typeof(MapConsole), nameof(MapConsole.Use))]
|
||||
[HarmonyPostfix]
|
||||
private static void MapConsole_ShowCountOverlay_Postfix()
|
||||
=> MapBehaviour.Instance.ColorControl.SetColor(new Color(0.2f, 0.5f, 0f, 1f)); // Green tint for admin map
|
||||
{
|
||||
if (!BAUConfigs.BetterMinimapColors.Value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
MapBehaviour.Instance.ColorControl.SetColor(new Color(0.2f, 0.5f, 0f, 1f));
|
||||
}
|
||||
|
||||
private static Transform? _icons; // Container for all custom map icons
|
||||
|
||||
/// <summary>
|
||||
/// Clears all map icons to be regenerated
|
||||
/// </summary>
|
||||
internal static void ClearMapIcons()
|
||||
internal static void ForceCloseMiniMap()
|
||||
{
|
||||
if (_icons != null)
|
||||
{
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using BetterAmongUs.Modules.Support;
|
||||
using BetterAmongUs.Utilities.Extension;
|
||||
using HarmonyLib;
|
||||
using Il2CppInterop.Runtime.InteropTypes.Arrays;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using BetterAmongUs.Utilities.Extension;
|
||||
|
||||
namespace BetterAmongUs.Patches.Gameplay.UI;
|
||||
|
||||
@@ -14,6 +14,9 @@ internal static class ServerDropdownPatch
|
||||
[HarmonyPrefix]
|
||||
private static void FindAGameManager_Start_Prefix(FindAGameManager __instance)
|
||||
{
|
||||
if (BAUPlugin.ModInfo.Starlight)
|
||||
return;
|
||||
|
||||
if (BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_ServerDropDown))
|
||||
return;
|
||||
|
||||
@@ -33,7 +36,11 @@ internal static class ServerDropdownPatch
|
||||
[HarmonyPrefix]
|
||||
private static bool ServerDropdown_FillServerOptions_Prefix(ServerDropdown __instance)
|
||||
{
|
||||
if (BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_ServerDropDown)) return true;
|
||||
if (BAUPlugin.ModInfo.Starlight)
|
||||
return true;
|
||||
|
||||
if (BAUModdedSupportFlags.HasFlag(BAUModdedSupportFlags.Disable_ServerDropDown))
|
||||
return true;
|
||||
|
||||
__instance.background.size = new Vector2(5, 1);
|
||||
|
||||
|
||||
@@ -16,19 +16,19 @@ internal sealed class BetterGameSettings
|
||||
internal static OptionCheckboxItem? InvalidFriendCode;
|
||||
internal static OptionCheckboxItem? UseBanPlayerList;
|
||||
internal static OptionCheckboxItem? UseBanNameList;
|
||||
internal static OptionCheckboxItem? UseBanWordList;
|
||||
internal static OptionCheckboxItem? UseBanWordListOnlyLobby;
|
||||
internal static OptionCheckboxItem? UseBanChatList;
|
||||
internal static OptionCheckboxItem? UseBanChatListOnlyLobby;
|
||||
internal static OptionCheckboxItem? UseBanChatListBan;
|
||||
internal static OptionCheckboxItem? DetectedLevel;
|
||||
internal static OptionIntItem? DetectedLevelAbove;
|
||||
internal static OptionCheckboxItem? KickLevel;
|
||||
internal static OptionIntItem? KickLevelBelow;
|
||||
internal static OptionIntItem? KickLevelBelowMinimumPlayers;
|
||||
internal static OptionCheckboxItem? DetectCheatClients;
|
||||
internal static OptionCheckboxItem? DetectInvalidRpcs;
|
||||
internal static OptionCheckboxItem? RpcRateLimiting;
|
||||
internal static OptionIntItem? RpcRateLimit;
|
||||
|
||||
internal static OptionStringItem? RoleRandomizer;
|
||||
|
||||
internal static OptionCheckboxItem? CancelInvalidSabotage;
|
||||
internal static OptionCheckboxItem? CensorDetectionReason;
|
||||
}
|
||||
@@ -75,8 +75,9 @@ internal static class GameSettingsPatch
|
||||
BetterGameSettings.CancelInvalidSabotage = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_CancelInvalidSabotage, true);
|
||||
BetterGameSettings.UseBanPlayerList = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_UseBanPlayerList, true);
|
||||
BetterGameSettings.UseBanNameList = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_UseBanNameList, true);
|
||||
BetterGameSettings.UseBanWordList = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_UseBanWordList, true);
|
||||
BetterGameSettings.UseBanWordListOnlyLobby = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_UseBanWordListOnlyLobby, true, BetterGameSettings.UseBanWordList);
|
||||
BetterGameSettings.UseBanChatList = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_UseBanChatList, true);
|
||||
BetterGameSettings.UseBanChatListOnlyLobby = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_UseBanChatListOnlyLobby, true, BetterGameSettings.UseBanChatList);
|
||||
BetterGameSettings.UseBanChatListBan = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_UseBanChatListBan, false, BetterGameSettings.UseBanChatList);
|
||||
}
|
||||
|
||||
// General detection settings
|
||||
@@ -86,19 +87,13 @@ internal static class GameSettingsPatch
|
||||
BetterGameSettings.DetectedLevelAbove = OptionIntItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_DetectedLevelAbove, (100, 10000, 5), 500, ("Lv ", ""), BetterGameSettings.DetectedLevel);
|
||||
BetterGameSettings.KickLevel = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_KickLevel, false);
|
||||
BetterGameSettings.KickLevelBelow = OptionIntItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_KickLevelBelow, (0, 10000, 1), 0, ("Lv ", ""), BetterGameSettings.KickLevel);
|
||||
BetterGameSettings.KickLevelBelowMinimumPlayers = OptionIntItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_KickLevelBelowMinimumPlayers, (1, 15, 1), 9, parent: BetterGameSettings.KickLevelBelow);
|
||||
BetterGameSettings.DetectCheatClients = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_DetectCheatClients, true);
|
||||
BetterGameSettings.DetectInvalidRpcs = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_DetectInvalidRpcs, true);
|
||||
BetterGameSettings.RpcRateLimiting = OptionCheckboxItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_RpcRateLimiting, true);
|
||||
BetterGameSettings.RpcRateLimit = OptionIntItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_RateLimit, (25, 1000, 1), 50, ("", " PS"), BetterGameSettings.RpcRateLimiting);
|
||||
}
|
||||
|
||||
// Role algorithm settings
|
||||
if (IsPreload || GameState.IsHost)
|
||||
{
|
||||
OptionHeaderItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_MainHeader_RoleAlgorithm);
|
||||
BetterGameSettings.RoleRandomizer = OptionStringItem.Create(BetterSettingsTab, TranslationStrings.BetterSetting_Setting_RoleRandomizer, [new("System.Random"), new("UnityEngine.Random")], 0);
|
||||
}
|
||||
|
||||
BetterSettingsTab.UpdateVisuals();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using AmongUs.GameOptions;
|
||||
using BetterAmongUs.Modules;
|
||||
using BetterAmongUs.Utilities;
|
||||
using BetterAmongUs.Modules;
|
||||
using HarmonyLib;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -21,7 +20,7 @@ internal class ZoomPatch
|
||||
// - Not Guardian Angel AND
|
||||
// - Either not in gameplay OR player is dead
|
||||
bool canZoom = GameState.IsCanMove &&
|
||||
!PlayerControl.LocalPlayer.Is(RoleTypes.GuardianAngel) &&
|
||||
!PlayerControl.LocalPlayer.IsGhostRole() &&
|
||||
(!GameState.IsInGamePlay || !PlayerControl.LocalPlayer.IsAlive());
|
||||
|
||||
// Should we reset zoom (when player was zooming but no longer can)
|
||||
|
||||
@@ -10,21 +10,32 @@ namespace BetterAmongUs.Patches.Unity;
|
||||
[HarmonyPatch]
|
||||
internal static class UnityWebRequestPatch
|
||||
{
|
||||
// Build mod version header string
|
||||
/// <summary>
|
||||
/// Builds a mod version header string for network transmission.
|
||||
/// Format: "major;minor;patch;metadata1/metadata2/metadata3"
|
||||
/// </summary>
|
||||
public static string GetHeader()
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
var version = BAUPlugin.ModInfo.SemVersion;
|
||||
|
||||
// Format: "Version;BuildType;IsHotfix/HotfixNum/BetaNum"
|
||||
stringBuilder.Append(ModInfo.PLUGIN_VERSION);
|
||||
stringBuilder.Append(version.Major);
|
||||
stringBuilder.Append(';');
|
||||
stringBuilder.Append(Enum.GetName(ModInfo.ReleaseBuildType));
|
||||
stringBuilder.Append(version.Minor);
|
||||
stringBuilder.Append(';');
|
||||
stringBuilder.Append(ModInfo.IS_HOTFIX);
|
||||
stringBuilder.Append('/');
|
||||
stringBuilder.Append(ModInfo.HOTFIX_NUM);
|
||||
stringBuilder.Append('/');
|
||||
stringBuilder.Append(ModInfo.BETA_NUM);
|
||||
stringBuilder.Append(version.Patch);
|
||||
stringBuilder.Append(';');
|
||||
|
||||
var buildMetadata = version.Metadata;
|
||||
if (buildMetadata.Length > 0)
|
||||
{
|
||||
for (int i = 0; i < buildMetadata.Length; i++)
|
||||
{
|
||||
stringBuilder.Append(buildMetadata[i]);
|
||||
if (i < buildMetadata.Length - 1)
|
||||
stringBuilder.Append('/');
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
@@ -68,7 +79,7 @@ internal static class UnityWebRequestPatch
|
||||
|
||||
if (responseHeader != null)
|
||||
{
|
||||
Logger_.Log("Connected to a supported Better Among Us matchmaking server");
|
||||
BAUPlugin.Logger.Log("Connected to a supported Better Among Us matchmaking server");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
"BetterOption.ShowFPS": "ShowFPS",
|
||||
"BetterOption.VentColorGroups": "Vent Color Groups",
|
||||
"BetterOption.MinimapIcons": "Minimap Icons",
|
||||
"BetterOption.BetterMinimapColors": "Better Minimap Colors",
|
||||
"BetterOption.BetterColorblindText": "Better Colorblind Text",
|
||||
"BetterOption.CompressSettingFiles": "Compress Setting Files",
|
||||
|
||||
"BetterOption.SaveData": "Open Save Data",
|
||||
@@ -73,9 +75,7 @@
|
||||
"BetterSetting.SetTo": "Set To:",
|
||||
"BetterSetting.MainHeader.System": "<color=#07B400>System Settings</color>",
|
||||
"BetterSetting.MainHeader.AntiCheat": "<color=#4f92ff>Anti-Cheat Settings</color>",
|
||||
"BetterSetting.MainHeader.RoleAlgorithm": "<color=#4f92ff>Role Algorithm Settings</color>",
|
||||
"BetterSetting.MainHeader.Gameplay": "<color=#d7d700>Gameplay Settings</color>",
|
||||
"BetterSetting.MainHeader.HideNSeek": "<color=#d7d700>Hide & Seek Settings</color>",
|
||||
"BetterSetting.TextHeader.HostOnly": "<color=#4f92ff>Host Only</color>",
|
||||
"BetterSetting.TextHeader.Detections": "<color=#4f92ff>Detections</color>",
|
||||
|
||||
@@ -88,20 +88,19 @@
|
||||
"BetterSetting.Setting.CancelInvalidSabotage": "Cancel invalid sabotages",
|
||||
"BetterSetting.Setting.UseBanPlayerList": "Use ban player list",
|
||||
"BetterSetting.Setting.UseBanNameList": "Use ban name list",
|
||||
"BetterSetting.Setting.UseBanWordList": "Use ban word list",
|
||||
"BetterSetting.Setting.UseBanWordListOnlyLobby": "Only in lobby",
|
||||
"BetterSetting.Setting.ShowRoleForClients": "Show role in name for clients",
|
||||
"BetterSetting.Setting.UseBanChatList": "Use ban chat list",
|
||||
"BetterSetting.Setting.UseBanChatListOnlyLobby": "Only in lobby",
|
||||
"BetterSetting.Setting.UseBanChatListBan": "Ban",
|
||||
"BetterSetting.Setting.CensorDetectionReason": "Censor detection reason",
|
||||
"BetterSetting.Setting.DetectedLevel": "Detected player levels",
|
||||
"BetterSetting.Setting.DetectedLevelAbove": "Detected player level above",
|
||||
"BetterSetting.Setting.KickLevel": "Kick player levels",
|
||||
"BetterSetting.Setting.KickLevelBelow": "Kick player level below",
|
||||
"BetterSetting.Setting.KickLevelBelowMinimumPlayers": "Only when player count at least",
|
||||
"BetterSetting.Setting.DetectCheatClients": "Detect cheat clients",
|
||||
"BetterSetting.Setting.DetectInvalidRpcs": "Detect invalid Rpcs",
|
||||
"BetterSetting.Setting.RpcRateLimiting": "Rpc Rate Limiting",
|
||||
"BetterSetting.Setting.RateLimit": "Rate Limit",
|
||||
"BetterSetting.Setting.RoleRandomizer": "Randomizer",
|
||||
"BetterSetting.Setting.DesyncRoles": "Desync roles to other clients",
|
||||
"BetterSetting.Setting.DisableSabotagesForDead": "Disable sabotages for dead",
|
||||
"BetterSetting.Setting.DisableSabotages": "Disable sabotages",
|
||||
"BetterSetting.Setting.RemovePetOnDeath": "Remove pet on death",
|
||||
|
||||
@@ -468,7 +468,7 @@ internal static class PlayerControlUtils
|
||||
if (data == null)
|
||||
return false;
|
||||
|
||||
return data.RoleType == RoleTypes.GuardianAngel;
|
||||
return data.RoleType is RoleTypes.GuardianAngel or RoleTypes.SpiritGuide;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -80,7 +80,7 @@ internal static class RoleUtils
|
||||
return color;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
return "#ffffff";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -114,7 +114,7 @@ internal static class RoleUtils
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (PlayerControl.LocalPlayer.Is(RoleTypes.GuardianAngel))
|
||||
if (PlayerControl.LocalPlayer.IsGhostRole())
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
@@ -146,6 +146,7 @@ internal static class RoleUtils
|
||||
{
|
||||
{ RoleTypes.CrewmateGhost, Colors.CrewmateBlue.ColorToHex() },
|
||||
{ RoleTypes.GuardianAngel, "#8cffff" },
|
||||
{ RoleTypes.SpiritGuide, "#ff0066" },
|
||||
{ RoleTypes.Crewmate, Colors.CrewmateBlue.ColorToHex() },
|
||||
{ RoleTypes.Scientist, "#00d9d9" },
|
||||
{ RoleTypes.Engineer, "#8f8f8f" },
|
||||
|
||||
+14
-12
@@ -1,4 +1,5 @@
|
||||
using BepInEx.Unity.IL2CPP.Utils;
|
||||
using BetterAmongUs.Enums;
|
||||
using BetterAmongUs.Generated;
|
||||
using BetterAmongUs.Modules;
|
||||
using BetterAmongUs.Patches.Gameplay.UI.Chat;
|
||||
@@ -77,7 +78,7 @@ internal static class Utils
|
||||
/// </summary>
|
||||
/// <param name="clientId">The client ID to look up.</param>
|
||||
/// <returns>The ClientData if found, null otherwise.</returns>
|
||||
internal static ClientData? ClientFromClientId(int clientId) =>
|
||||
internal static ClientData? ClientFromClientId(ClientId clientId) =>
|
||||
AmongUsClient.Instance.allClients.FirstOrDefaultIl2Cpp(cd => cd.Id == clientId);
|
||||
|
||||
/// <summary>
|
||||
@@ -85,7 +86,7 @@ internal static class Utils
|
||||
/// </summary>
|
||||
/// <param name="playerId">The player ID to look up.</param>
|
||||
/// <returns>The NetworkedPlayerInfo if found, null otherwise.</returns>
|
||||
internal static NetworkedPlayerInfo? PlayerDataFromPlayerId(int playerId) =>
|
||||
internal static NetworkedPlayerInfo? PlayerDataFromPlayerId(PlayerId playerId) =>
|
||||
GameData.Instance.AllPlayers.FirstOrDefaultIl2Cpp(data => data.PlayerId == playerId);
|
||||
|
||||
/// <summary>
|
||||
@@ -93,7 +94,7 @@ internal static class Utils
|
||||
/// </summary>
|
||||
/// <param name="clientId">The client ID to look up.</param>
|
||||
/// <returns>The NetworkedPlayerInfo if found, null otherwise.</returns>
|
||||
internal static NetworkedPlayerInfo? PlayerDataFromClientId(int clientId) =>
|
||||
internal static NetworkedPlayerInfo? PlayerDataFromClientId(ClientId clientId) =>
|
||||
GameData.Instance.AllPlayers.FirstOrDefaultIl2Cpp(data => data.ClientId == clientId);
|
||||
|
||||
/// <summary>
|
||||
@@ -109,7 +110,7 @@ internal static class Utils
|
||||
/// </summary>
|
||||
/// <param name="playerId">The player ID to look up.</param>
|
||||
/// <returns>The PlayerControl if found, null otherwise.</returns>
|
||||
internal static PlayerControl? PlayerFromPlayerId(int playerId) =>
|
||||
internal static PlayerControl? PlayerFromPlayerId(PlayerId playerId) =>
|
||||
BAUPlugin.AllPlayerControls.FirstOrDefault(player => player.PlayerId == playerId);
|
||||
|
||||
/// <summary>
|
||||
@@ -117,7 +118,7 @@ internal static class Utils
|
||||
/// </summary>
|
||||
/// <param name="clientId">The client ID to look up.</param>
|
||||
/// <returns>The PlayerControl if found, null otherwise.</returns>
|
||||
internal static PlayerControl? PlayerFromClientId(int clientId) =>
|
||||
internal static PlayerControl? PlayerFromClientId(ClientId clientId) =>
|
||||
BAUPlugin.AllPlayerControls.FirstOrDefault(player => player.GetClientId() == clientId);
|
||||
|
||||
/// <summary>
|
||||
@@ -125,7 +126,7 @@ internal static class Utils
|
||||
/// </summary>
|
||||
/// <param name="netId">The network ID to look up.</param>
|
||||
/// <returns>The PlayerControl if found, null otherwise.</returns>
|
||||
internal static PlayerControl? PlayerFromNetId(uint netId) =>
|
||||
internal static PlayerControl? PlayerFromNetId(NetId netId) =>
|
||||
BAUPlugin.AllPlayerControls.FirstOrDefault(player => player.NetId == netId);
|
||||
|
||||
// Chat functionality
|
||||
@@ -430,7 +431,7 @@ internal static class Utils
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error(ex);
|
||||
BAUPlugin.Logger.Error(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -444,7 +445,7 @@ internal static class Utils
|
||||
{
|
||||
try
|
||||
{
|
||||
var stream = ModInfo.Assembly.GetManifestResourceStream(path);
|
||||
var stream = BAUPlugin.ModInfo.Assembly.GetManifestResourceStream(path);
|
||||
if (stream == null)
|
||||
return null;
|
||||
|
||||
@@ -460,7 +461,7 @@ internal static class Utils
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error(ex);
|
||||
BAUPlugin.Logger.Error(ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -474,13 +475,13 @@ internal static class Utils
|
||||
{
|
||||
if (!File.Exists(filePath))
|
||||
{
|
||||
Logger_.Error($"File not found: {filePath}");
|
||||
BAUPlugin.Logger.Error($"File not found: {filePath}");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Path.GetExtension(filePath).ToLower() != ".wav")
|
||||
{
|
||||
Logger_.Error("Only .wav files are supported.");
|
||||
BAUPlugin.Logger.Error("Only .wav files are supported.");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -496,7 +497,7 @@ internal static class Utils
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger_.Error($"Failed to load WAV: {ex}");
|
||||
BAUPlugin.Logger.Error($"Failed to load WAV: {ex}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -602,6 +603,7 @@ internal static class Utils
|
||||
Platforms.Switch => ("Switch", "Console"),
|
||||
Platforms.Android => ("Android", "Mobile"),
|
||||
Platforms.IPhone => ("IPhone", "Mobile"),
|
||||
(Platforms)CustomPlatforms.Starlight => ("Starlight", "Mobile"),
|
||||
Platforms.Unknown => ("None", ""),
|
||||
_ => (string.Empty, string.Empty)
|
||||
};
|
||||
|
||||
@@ -323,6 +323,16 @@ public static class TranslationStrings
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterOption_MinimapIcons = new("BetterOption.MinimapIcons");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Better Minimap Colors
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterOption_BetterMinimapColors = new("BetterOption.BetterMinimapColors");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Better Colorblind Text
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterOption_BetterColorblindText = new("BetterOption.BetterColorblindText");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Compress Setting Files
|
||||
/// </summary>
|
||||
@@ -363,21 +373,11 @@ public static class TranslationStrings
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_MainHeader_AntiCheat = new("BetterSetting.MainHeader.AntiCheat");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: <color=#4f92ff>Role Algorithm Settings</color>
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_MainHeader_RoleAlgorithm = new("BetterSetting.MainHeader.RoleAlgorithm");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: <color=#d7d700>Gameplay Settings</color>
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_MainHeader_Gameplay = new("BetterSetting.MainHeader.Gameplay");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: <color=#d7d700>Hide & Seek Settings</color>
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_MainHeader_HideNSeek = new("BetterSetting.MainHeader.HideNSeek");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: <color=#4f92ff>Host Only</color>
|
||||
/// </summary>
|
||||
@@ -434,19 +434,19 @@ public static class TranslationStrings
|
||||
public static readonly TranslationString BetterSetting_Setting_UseBanNameList = new("BetterSetting.Setting.UseBanNameList");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Use ban word list
|
||||
/// Base Translation: Use ban chat list
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_Setting_UseBanWordList = new("BetterSetting.Setting.UseBanWordList");
|
||||
public static readonly TranslationString BetterSetting_Setting_UseBanChatList = new("BetterSetting.Setting.UseBanChatList");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Only in lobby
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_Setting_UseBanWordListOnlyLobby = new("BetterSetting.Setting.UseBanWordListOnlyLobby");
|
||||
public static readonly TranslationString BetterSetting_Setting_UseBanChatListOnlyLobby = new("BetterSetting.Setting.UseBanChatListOnlyLobby");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Show role in name for clients
|
||||
/// Base Translation: Ban
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_Setting_ShowRoleForClients = new("BetterSetting.Setting.ShowRoleForClients");
|
||||
public static readonly TranslationString BetterSetting_Setting_UseBanChatListBan = new("BetterSetting.Setting.UseBanChatListBan");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Censor detection reason
|
||||
@@ -473,6 +473,11 @@ public static class TranslationStrings
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_Setting_KickLevelBelow = new("BetterSetting.Setting.KickLevelBelow");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Only when player count at least
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_Setting_KickLevelBelowMinimumPlayers = new("BetterSetting.Setting.KickLevelBelowMinimumPlayers");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Detect cheat clients
|
||||
/// </summary>
|
||||
@@ -493,16 +498,6 @@ public static class TranslationStrings
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_Setting_RateLimit = new("BetterSetting.Setting.RateLimit");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Randomizer
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_Setting_RoleRandomizer = new("BetterSetting.Setting.RoleRandomizer");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Desync roles to other clients
|
||||
/// </summary>
|
||||
public static readonly TranslationString BetterSetting_Setting_DesyncRoles = new("BetterSetting.Setting.DesyncRoles");
|
||||
|
||||
/// <summary>
|
||||
/// Base Translation: Disable sabotages for dead
|
||||
/// </summary>
|
||||
|
||||
Reference in new issue
Block a user