From 3bdc76dd88b7ec20b0d440afb513ea0043de2bbc Mon Sep 17 00:00:00 2001 From: Gurge44 Date: Sun, 28 Jun 2026 20:38:33 +0200 Subject: [PATCH] fix discord rp & character allowance patch --- CHANGELOG.md | 6 ++-- Main.cs | 3 +- Patches/ChatControlPatch.cs | 3 ++ Patches/ControlPatch.cs | 10 +++++++ Patches/DleksPatch.cs | 30 +++++++++++--------- Patches/GameOptionsMenuPatch.cs | 8 +++--- Patches/GameStartManagerPatch.cs | 48 ++++++++++++++++++++++++++------ Patches/TextBoxPatch.cs | 31 +++++++++++++++++++-- 8 files changed, 106 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e976cd9b..95e336acf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ > While at the time of releasing this, the mod should more-less work on InnerSloth's regions, **I still recommend playing on modded regions** (MEU/MAS/MNA/Niko-EU/Niko-AS/Niko-NA). ## Bug Fixes -- **Fixed most of the memory leaks introduced by the latest Among Us update** +- **Fixed crashes caused by the settings UI** - by Zypherus +- **Fixed the memory leaks introduced by the settings UI in the latest Among Us update** - CTA data is now synced with non-host modded clients - Fixed Generator not seeing its charge - Fixed forged roles having incorrect colors @@ -15,7 +16,7 @@ - + Mostly internal code-wise fixes ## Changes -- **The HTML log file now contains all data from the other log file (LogOutput.log)** +- **The HTML log file now contains all data from the other log file (LogOutput.log)** (that means you'll only need the HTML log to make bug reports from now on, and only the HTML log will be dumped!) - More compatibility with [BAU](https://github.com/D1GQ/BetterAmongUs) - by Limeau - Ghost roles use manual cooldown tracking instead of the protect button cooldown (fixes inconsistencies) - Renaming commands now check the DenyName list @@ -31,6 +32,7 @@ ## Additions - New setting under `Apply DenyName List`: `Ban instead of kick on trigger` +- More ability button icons - by Newholiday ### New game mode: Doom Tag - by HayashiUme - In the Doom Tag gamemode, every player is assigned a target, shown by an arrow. diff --git a/Main.cs b/Main.cs index a992bf705..db822e1a0 100644 --- a/Main.cs +++ b/Main.cs @@ -948,8 +948,7 @@ public class Main : BasePlugin if (!OperatingSystem.IsAndroid()) { // there are some issues with TextBoxPatch and DiscordRPC on Android - if (Translator.GetUserTrueLang() is not (SupportedLangs.SChinese or SupportedLangs.TChinese or SupportedLangs.Korean)) - Harmony.PatchAll(typeof(TextBoxPatch)); + Harmony.PatchAll(typeof(TextBoxPatch)); Harmony.PatchAll(typeof(DiscordRPC)); } diff --git a/Patches/ChatControlPatch.cs b/Patches/ChatControlPatch.cs index b461b359a..937b097ea 100644 --- a/Patches/ChatControlPatch.cs +++ b/Patches/ChatControlPatch.cs @@ -68,7 +68,10 @@ internal static class ChatControllerUpdatePatch ClipboardHelper.PutClipboardString(__instance.freeChatField.textArea.text); if ((Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) && Input.GetKeyDown(KeyCode.V)) + { + TextBoxPatch.Pasting = true; __instance.freeChatField.textArea.SetText(__instance.freeChatField.textArea.text + GUIUtility.systemCopyBuffer.Trim()); + } if ((Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) && Input.GetKeyDown(KeyCode.X)) { diff --git a/Patches/ControlPatch.cs b/Patches/ControlPatch.cs index f6ffe5536..85db7f4a1 100644 --- a/Patches/ControlPatch.cs +++ b/Patches/ControlPatch.cs @@ -230,6 +230,12 @@ internal static class ControllerManagerUpdatePatch { yield return new WaitForSecondsRealtime(0.1f); + if (GameSettingMenu.Instance) + { + GameSettingMenu.Instance.Close(); + yield return new WaitForSecondsRealtime(0.5f); + } + string format = GetString("ResettingOptions"); HudManager hudManager = HudManager.Instance; hudManager.ShowPopUp(string.Format(format, 0, OptionItem.AllOptions.Count)); @@ -254,6 +260,10 @@ internal static class ControllerManagerUpdatePatch OptionSaver.Save(); IsResetting = false; + + GameOptionsMenuPatch.ReCreateAllSettings(); + GameOptionsMenuPatch.RefreshSettingValues(); + GameOptionsMenuPatch.RefreshTabButtons(); } } } diff --git a/Patches/DleksPatch.cs b/Patches/DleksPatch.cs index be4efa1a8..40c804b5f 100644 --- a/Patches/DleksPatch.cs +++ b/Patches/DleksPatch.cs @@ -15,25 +15,29 @@ internal static class AllMapIconsPatch [HarmonyPrefix] public static void GameStartManagerStart_Prefix(GameStartManager __instance) { - if (__instance.AllMapIcons.TrueForAll((Predicate)(x => x.Name != MapNames.Dleks))) + try { - __instance.AllMapIcons.Insert((int)MapNames.Dleks, new MapIconByName + if (__instance.AllMapIcons.TrueForAll((Predicate)(x => x.Name != MapNames.Dleks))) { - Name = MapNames.Dleks, - MapIcon = Utils.LoadSprite("EHR.Resources.Images.DleksBanner-Wordart.png", 160f) - }); - } - if (SubmergedCompatibility.Loaded) - { - if (__instance.AllMapIcons.TrueForAll((Predicate)(x => x.Name != (MapNames)6))) - { - __instance.AllMapIcons.Insert((int)(MapNames)6, new MapIconByName + __instance.AllMapIcons.Insert((int)MapNames.Dleks, new MapIconByName { - Name = (MapNames)6, - MapIcon = Utils.LoadSprite("EHR.Resources.Images.Submerged-Wordart.png", 380f) + Name = MapNames.Dleks, + MapIcon = Utils.LoadSprite("EHR.Resources.Images.DleksBanner-Wordart.png", 160f) }); } + if (SubmergedCompatibility.Loaded) + { + if (__instance.AllMapIcons.TrueForAll((Predicate)(x => x.Name != (MapNames)6))) + { + __instance.AllMapIcons.Insert((int)(MapNames)6, new MapIconByName + { + Name = (MapNames)6, + MapIcon = Utils.LoadSprite("EHR.Resources.Images.Submerged-Wordart.png", 380f) + }); + } + } } + catch { } } [HarmonyPatch(nameof(GameStartManager.Start))] [HarmonyPostfix] diff --git a/Patches/GameOptionsMenuPatch.cs b/Patches/GameOptionsMenuPatch.cs index 7700db838..91a3c3929 100644 --- a/Patches/GameOptionsMenuPatch.cs +++ b/Patches/GameOptionsMenuPatch.cs @@ -502,10 +502,10 @@ public static class GameOptionsMenuPatch string selection = stringOptionItem.Selections[stringOptionItem.Rule.GetValueByIndex(stringOption.Value)]; if (!stringOptionItem.noTranslation) selection = Translator.GetString(selection); stringOption.ValueText.SetText(selection); - if (!StringOptionPatch.NameCache.ContainsKey(stringOption)) + if (!StringOptionPatch.NameCache.TryGetValue(stringOption, out string name)) stringOption.Initialize(); else - stringOption.TitleText.SetText(StringOptionPatch.NameCache[stringOption]); + stringOption.TitleText.SetText(name); break; case FloatOptionItem or IntegerOptionItem when optionBehaviour is NumberOption numberOption: numberOption.Value = optionItem.GetFloat(); @@ -970,10 +970,10 @@ public static class StringOptionPatch OptionItem item = OptionItem.AllOptions[index]; item.SetValue(__instance.GetInt(), doSave: true, doSync: false); NotificationPopperPatch.AddSettingsChangeMessage(item); - if (!NameCache.ContainsKey(__instance)) + if (!NameCache.TryGetValue(__instance, out string name)) __instance.Initialize(); else - __instance.TitleText.SetText(NameCache[__instance]); + __instance.TitleText.SetText(name); return false; } diff --git a/Patches/GameStartManagerPatch.cs b/Patches/GameStartManagerPatch.cs index b79b0b534..640544f0a 100644 --- a/Patches/GameStartManagerPatch.cs +++ b/Patches/GameStartManagerPatch.cs @@ -45,6 +45,8 @@ public static class GameStartManagerPatch { try { + try { GameStartManagerUpdatePatch.DiscordManagerBridge.Init(); } catch (Exception e) { Utils.ThrowException(e); } + if (!__instance) return; UpdateSpriteStartButton = true; @@ -128,12 +130,40 @@ public static class GameStartManagerPatch private static int MinPlayer; private static SpriteRenderer LobbyTimerBg; public static bool Warned; - - private static readonly Type DiscordManagerType = AccessTools.TypeByName("DiscordManager"); - private static readonly PropertyInfo InstanceExistsProperty = DiscordManagerType?.GetProperty("InstanceExists"); - private static readonly PropertyInfo InstanceProperty = DiscordManagerType?.GetProperty("Instance"); - private static readonly MethodInfo SetInLobbyHostMethod = DiscordManagerType?.GetMethod("SetInLobbyHost"); - private static readonly MethodInfo SetInLobbyClientMethod = DiscordManagerType?.GetMethod("SetInLobbyClient"); + + public static class DiscordManagerBridge + { + private static bool Initialized; + public static bool Enabled; + + public static Func InstanceExistsGetter; + public static Func InstanceGetter; + public static MethodInfo SetInLobbyHost; + public static MethodInfo SetInLobbyClient; + + public static void Init() + { + if (Initialized) return; + Initialized = true; + + var discordType = AppDomain.CurrentDomain.GetAssemblies().Select(a => + { + try { return a.GetType("DiscordManager"); } + catch { return null; } + }).FirstOrDefault(t => t != null); + + if (discordType == null) return; + + var instanceProp = discordType.BaseType!.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); + InstanceGetter = (Func)Delegate.CreateDelegate(typeof(Func), instanceProp!.GetGetMethod()!); + var existsProp = discordType.BaseType.GetProperty("InstanceExists", BindingFlags.Public | BindingFlags.Static); + InstanceExistsGetter = (Func)Delegate.CreateDelegate(typeof(Func), existsProp!.GetGetMethod()!); + SetInLobbyHost = discordType.GetMethod("SetInLobbyHost", BindingFlags.Public | BindingFlags.Instance); + SetInLobbyClient = discordType.GetMethod("SetInLobbyClient", BindingFlags.Public | BindingFlags.Instance); + + Enabled = true; + } + } public static bool Prefix(GameStartManager __instance) { @@ -290,10 +320,10 @@ public static class GameStartManagerPatch ActionMapGlyphDisplay startButtonGlyph = instance.StartButtonGlyph; startButtonGlyph?.SetColor(instance.LastPlayerCount >= instance.MinPlayers ? Palette.EnabledColor : Palette.DisabledClear); - if (DiscordManagerType != null && ((bool?)InstanceExistsProperty?.GetValue(null) ?? false)) + if (DiscordManagerBridge.Enabled && DiscordManagerBridge.InstanceExistsGetter()) { - MethodInfo method = AmongUsClient.Instance.AmHost && AmongUsClient.Instance.NetworkMode == NetworkModes.OnlineGame ? SetInLobbyHostMethod : SetInLobbyClientMethod; - method?.Invoke(InstanceProperty?.GetValue(null), [instance.LastPlayerCount, GameManager.Instance.LogicOptions.MaxPlayers, AmongUsClient.Instance.GameId]); + var method = AmongUsClient.Instance.AmHost && AmongUsClient.Instance.NetworkMode == NetworkModes.OnlineGame ? DiscordManagerBridge.SetInLobbyHost : DiscordManagerBridge.SetInLobbyClient; + method.Invoke(DiscordManagerBridge.InstanceGetter(), [instance.LastPlayerCount, GameManager.Instance.LogicOptions.MaxPlayers, AmongUsClient.Instance.GameId]); } } diff --git a/Patches/TextBoxPatch.cs b/Patches/TextBoxPatch.cs index 108529c43..d3bfea257 100644 --- a/Patches/TextBoxPatch.cs +++ b/Patches/TextBoxPatch.cs @@ -16,20 +16,45 @@ public static class TextBoxPatch private static TextMeshPro AdditionalInfoText; public static bool IsInvalidCommand; + private static int CurrentCharPos; + public static bool Pasting; + // from https://github.com/scp222thj/MalumMenu/blob/main/src/Patches/TextBoxTMPPatches.cs + // Well I guess cheat menus sometimes have useful code too.... [HarmonyPatch(typeof(TextBoxTMP), nameof(TextBoxTMP.IsCharAllowed))] [HarmonyPrefix] - public static bool AllowAllCharacters(TextBoxTMP __instance, [HarmonyArgument(0)] char i, ref bool __result) + public static bool AllowAllCharacters(TextBoxTMP __instance, ref bool __result) { - if (!__instance.IpMode && i is '\'' or '"' or '’' or '`' or '-' or '–' or '—' or '‐' or '.' or ',' or ':' or ';' or '!' or '?' or '(' or ')' or '[' or ']' or '{' or '}' or '<' or '>' or '+' or '=' or '~' or '^' or '*' or '%' or '&' or '|' or '$' or '€' or '£' or '¥' or '₽' or >= '\u0100' and <= '\u024F' or >= '\u0370' and <= '\u03FF') + string compositionString = Input.compositionString; + if (compositionString.Length > 0) { __result = true; return false; } - return true; + var input = Pasting ? GUIUtility.systemCopyBuffer.Trim() : Input.inputString; + Pasting = false; + + if (input.Length == 0) + { + __result = true; + return false; + } + + string currentText = __instance.text ?? string.Empty; + int caretPos = Mathf.Clamp(__instance.caretPos, 0, currentText.Length); + string text = currentText.Insert(caretPos, input); + CurrentCharPos = Mathf.Clamp(CurrentCharPos, 0, text.Length - 1); + char currentChar = text[CurrentCharPos]; + + if (CurrentCharPos >= text.Length - 1) CurrentCharPos = 0; + else CurrentCharPos++; + + __result = currentChar is not ('\b' or '\r' or '['); + return false; } + [HarmonyPatch(typeof(TextBoxTMP), nameof(TextBoxTMP.SetText))] [HarmonyPostfix] public static void ShowCommandHelp(TextBoxTMP __instance)