Merge pull request #35 from EnhancedNetwork/dev

v1.1.4 Hotfix 3
This commit is contained in:
D1GQ authored and GitHub committed 2024-09-23 23:16:43 -05:00
commit 1c89412a5b
26 files changed
+293 -274

No files matched your search

+3 -8
View File
@@ -3,7 +3,6 @@ using BetterAmongUs.Patches;
using HarmonyLib;
using Hazel;
using InnerNet;
using Sentry.Internal.Extensions;
namespace BetterAmongUs;
@@ -623,17 +622,13 @@ class AntiCheat
if (callId is (byte)RpcCalls.SendChatNote)
{
_ = reader.ReadByte();
var type = reader.ReadByte();
if (!GameStates.IsMeeting || (ChatNoteTypes)type == ChatNoteTypes.DidVote && player.BetterData().AntiCheatInfo.ChatDidVote)
if (!GameStates.IsMeeting || !Enum.IsDefined(typeof(ChatNoteTypes), type))
{
BetterNotificationManager.NotifyCheat(player, string.Format(Translator.GetString("AntiCheat.InvalidActionRPC"), Enum.GetName((RpcCalls)callId)));
Logger.LogCheat($"{player.BetterData().RealName} {Enum.GetName((RpcCalls)callId)}: {!GameStates.IsMeeting} || {(ChatNoteTypes)type == ChatNoteTypes.DidVote} && {player.BetterData().AntiCheatInfo.ChatDidVote}");
}
if ((ChatNoteTypes)type == ChatNoteTypes.DidVote)
{
player.BetterData().AntiCheatInfo.ChatDidVote = true;
Logger.LogCheat($"{player.BetterData().RealName} {Enum.GetName((RpcCalls)callId)}: {!GameStates.IsMeeting} || {!Enum.IsDefined(typeof(ChatNoteTypes), type)}");
}
}
+4 -5
View File
@@ -1,5 +1,4 @@
using BetterAmongUs.Patches;
using System.Text.Json;
using System.Text.Json;
namespace BetterAmongUs;
@@ -198,7 +197,7 @@ class BetterDataManager
return bool.Parse(jsonData[id.ToString()]);
}
}
catch
catch
{
SaveSetting(id, Default.ToString());
}
@@ -219,7 +218,7 @@ class BetterDataManager
return float.Parse(jsonData[id.ToString()]);
}
}
catch
catch
{
SaveSetting(id, Default.ToString());
}
@@ -240,7 +239,7 @@ class BetterDataManager
return int.Parse(jsonData[id.ToString()]);
}
}
catch
catch
{
SaveSetting(id, Default.ToString());
}
+2 -2
View File
@@ -197,7 +197,7 @@ class BetterHostManager
if (player.Data.PlayerName != player.CurrentOutfit.PlayerName && !player.IsInShapeshift() || force)
{
player.RpcSetName(player.Data.PlayerName);
Logger.Log($"Reset {player.Data.PlayerName} name", "RPC");
Logger.LogPrivate($"Reset {player.Data.PlayerName} name", "RPC");
}
return;
}
@@ -305,7 +305,7 @@ class BetterHostManager
}
player.RpcSetNamePrivate(NewName, target);
Logger.Log($"Set {player.Data.PlayerName} name to {NewName.Replace("\n", "-")} for {target.Data.PlayerName}", "RPC");
Logger.LogPrivate($"Set {player.Data.PlayerName} name to {NewName.Replace("\n", "-")} for {target.Data.PlayerName}", "RPC");
}
}
}
+2 -5
View File
@@ -1,10 +1,7 @@
using System;
using System.Reflection;
using System.Text.Json;
using System.IO;
using System.Reflection;
using AmongUs.Data;
using IEnumerator = System.Collections.IEnumerator;
using UnityEngine.Networking;
using IEnumerator = System.Collections.IEnumerator;
namespace BetterAmongUs;
+4 -1
View File
@@ -1,15 +1,18 @@
using BepInEx;
namespace BetterAmongUs;
class Logger
{
public static void Log(string info, string tag = "Log")
public static void Log(string info, string tag = "Log", bool logConsole = true)
{
string mark = $"{DateTime.Now:HH:mm} [BetterLog][{tag}]";
string logFilePath = Path.Combine(BetterDataManager.filePathFolder, "better-log.txt");
string newLine = $"{mark}: {Utils.RemoveHtmlText(info)}";
File.AppendAllText(logFilePath, newLine + Environment.NewLine);
Main.Logger.LogInfo($"[{tag}] {info}");
if (logConsole) ConsoleManager.ConsoleStream.WriteLine($"{DateTime.Now:HH:mm} BetterAmongUs[{tag}]: {Utils.RemoveHtmlText(info)}");
}
public static void LogHeader(string info, string tag = "LogHeader") => Log($" >-------------- {info} --------------<", tag);
public static void LogCheat(string info, string tag = "AntiCheat") => Log(info, tag);
+2 -7
View File
@@ -22,12 +22,7 @@ static class ExtendedPlayerControl
}
}
// Get players client id
public static int GetClientId(this PlayerControl player)
{
if (player == null) return -1;
var client = player.GetClient();
return client == null ? -1 : client.Id;
}
public static int GetClientId(this PlayerControl player) => player?.GetClient()?.Id != null ? player.GetClient().Id : -1;
// Get player name with outfit color
public static string GetPlayerNameAndColor(this PlayerControl player)
{
@@ -103,7 +98,7 @@ static class ExtendedPlayerControl
{
var Ban = ban;
if (!GameStates.IsHost || PlayerControl.LocalPlayer == player || !player.DataIsCollected() && !bypassDataCheck || player.IsHost() || player.isDummy)
if (!GameStates.IsHost || player.IsLocalPlayer() || !player.DataIsCollected() && !bypassDataCheck || player.IsHost() || player.isDummy)
{
return;
}
+3 -7
View File
@@ -17,6 +17,7 @@ public static class PlayerControlDataExtension
public bool IsVerifiedBetterUser { get; set; } = false;
public bool IsBetterHost { get; set; } = false;
public bool IsTOHEHost { get; set; } = false;
public bool HasShowDcMsg { get; set; } = false;
// Track Game Info
public DisconnectReasons DisconnectReason { get; set; } = DisconnectReasons.Unknown;
@@ -27,7 +28,6 @@ public static class PlayerControlDataExtension
public class ExtendedAntiCheatInfo
{
public bool BannedByAntiCheat { get; set; } = false;
public bool ChatDidVote { get; set; } = false;
public List<string> AUMChats { get; set; } = [];
public int TimesAttemptedKilled { get; set; } = 0;
public int OpenSabotageNum { get; set; } = 0;
@@ -50,7 +50,8 @@ public static class PlayerControlDataExtension
{
_Data = BetterData._Data,
RoleInfo = new ExtendedRoleInfo(),
AntiCheatInfo = new ExtendedAntiCheatInfo()
AntiCheatInfo = new ExtendedAntiCheatInfo(),
AccountInfo = new BetterAccountInfo()
};
// Reset info when needed
@@ -76,11 +77,6 @@ public static class PlayerControlDataExtension
player.BetterData().RoleInfo.DeadDisplayRole = player.Data.RoleType;
}
if (!GameStates.IsMeeting)
{
player.BetterData().AntiCheatInfo.ChatDidVote = false;
}
if (string.IsNullOrEmpty(player.BetterData().RealName))
{
player.BetterData().RealName = player.Data.PlayerName;
@@ -1,5 +1,4 @@
using UnityEngine;
using static Il2CppSystem.Net.Http.Headers.Parser;
namespace BetterAmongUs;
@@ -1,5 +1,4 @@
using System.Dynamic;
using UnityEngine;
using UnityEngine;
namespace BetterAmongUs;
@@ -92,7 +91,7 @@ public class BetterOptionPlayerItem : BetterOptionItem
{
ThisOption.ValueText.text = Utils.PlayerFromPlayerId(CurrentIndex).GetPlayerNameAndColor();
}
else
else
{
ThisOption.ValueText.text = "<color=#ababab>Random</color>";
}
+13 -12
View File
@@ -105,8 +105,8 @@ internal static class RPC
messageWriter.WriteBytesAndSize(optionsByteArray);
AmongUsClient.Instance.FinishRpcImmediately(messageWriter);
}
}
}
public static void SendBetterCheck()
{
var flag = GameStates.IsHost && Main.BetterHost.Value;
@@ -151,7 +151,7 @@ internal static class RPC
public static void HandleCustomRPC(PlayerControl player, byte callId, MessageReader oldReader)
{
if (player == null || player.IsLocalPlayer() || player.Data == null) return;
if (player == null || player.IsLocalPlayer() || player.Data == null || Enum.IsDefined(typeof(RpcCalls), callId)) return;
if (Enum.IsDefined(typeof(CustomRPC), (int)unchecked(callId)))
{
@@ -206,21 +206,22 @@ internal static class RPC
*/
}
}
try
else if (!Enum.IsDefined(typeof(CustomRPC), (int)unchecked(callId)))
{
if (!GameStates.IsTOHEHostLobby && callId is not unchecked((byte)CustomRPC.Sicko) or unchecked((byte)CustomRPC.AUM) or (byte)CustomRPC.AUMChat)
try
{
var flag = Enum.IsDefined(typeof(CustomRPC), (int)callId) || Enum.IsDefined(typeof(RpcCalls), callId);
if (!flag && player.IsHost())
if (!GameStates.IsHost && !GameStates.IsTOHEHostLobby)
{
var BAU = "<color=#278720>♻</color><color=#0ed400><b>BetterAmongUs</b></color><color=#278720>♻</color>";
Utils.DisconnectSelf($"{BAU} does not support\n<b>Modded Lobbies</b>!");
if (player.IsHost())
{
var Icon = Translator.GetString("BAUMark");
var BAU = $"<color=#278720>{Icon}</color><color=#0ed400><b>{Translator.GetString("BAU")}</b></color><color=#278720>{Icon}</color>";
Utils.DisconnectSelf(string.Format(Translator.GetString("ModdedLobbyMsg"), BAU));
}
}
}
catch { }
}
catch { }
}
public static void HandleRPC(PlayerControl player, byte callId, MessageReader oldReader)
+2 -3
View File
@@ -1,6 +1,5 @@
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
@@ -38,11 +37,11 @@ public static class Translator
{
// Read the JSON file content
using Stream resourceStream = assembly.GetManifestResourceStream(jsonFileName);
if (resourceStream != null)
{
using StreamReader reader = new(resourceStream);
string jsonContent = reader.ReadToEnd();
// Deserialize the JSON into a dictionary
Dictionary<string, string> jsonDictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(jsonContent);
+2 -2
View File
@@ -1,7 +1,7 @@
using AmongUs.Data;
using AmongUs.GameOptions;
using BetterAmongUs.Patches;
using InnerNet;
using Sentry.Internal.Extensions;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
@@ -39,7 +39,6 @@ public static class Utils
{
pooledBubble.transform.SetParent(chat.scroller.Inner);
pooledBubble.transform.localScale = Vector3.one;
pooledBubble.Background.color = new Color(0.05f, 0.05f, 0.05f, 1f);
pooledBubble.SetCosmetics(data);
pooledBubble.gameObject.transform.Find("PoolablePlayer").gameObject.SetActive(false);
pooledBubble.ColorBlindName.gameObject.SetActive(false);
@@ -63,6 +62,7 @@ public static class Utils
chat.notificationRoutine = chat.StartCoroutine(chat.BounceDot());
}
SoundManager.Instance.PlaySound(chat.messageSound, false, 1f, null).pitch = 0.5f + (float)data.PlayerId / 15f;
ChatPatch.ChatControllerPatch.SetChatPoolTheme(pooledBubble);
}
catch (Exception ex)
{
-1
View File
@@ -1,5 +1,4 @@
using HarmonyLib;
using TMPro;
using UnityEngine;
namespace BetterAmongUs.Patches;
+172 -147
View File
@@ -1,5 +1,4 @@
using AmongUs.Data;
using AmongUs.GameOptions;
using AmongUs.GameOptions;
using Assets.CoreScripts;
using HarmonyLib;
using Hazel;
@@ -51,40 +50,34 @@ class ChatPatch
}
[HarmonyPatch(typeof(ChatController))]
class ChatControllerPatch
public class ChatControllerPatch
{
[HarmonyPatch(nameof(ChatController.Toggle))]
[HarmonyPostfix]
public static void Toggle_Postfix(/*ChatController __instance*/)
{
SetChatTheme();
}
[HarmonyPatch(nameof(ChatController.Update))]
[HarmonyPrefix]
[HarmonyPriority(Priority.First)]
public static void Update_Prefix(ChatController __instance)
{
for (int i = 0; i < __instance.scroller.Inner.gameObject.transform.childCount; i++)
if (Main.ChatDarkMode.Value)
{
GameObject chatItem = __instance.scroller.Inner.transform.GetChild(i).gameObject;
chatItem.transform.Find("ChatText (TMP)").GetComponent<TextMeshPro>().color = new Color(1f, 1f, 1f, 1f);
chatItem.transform.Find("Background").GetComponent<SpriteRenderer>().color = new Color(0.05f, 0.05f, 0.05f, 1f);
if (chatItem.transform.Find("PoolablePlayer/xMark") != null)
{
if (chatItem.transform.Find("PoolablePlayer/xMark").GetComponent<SpriteRenderer>().enabled == true)
{
chatItem.transform.Find("Background").GetComponent<SpriteRenderer>().color = new Color(0.05f, 0.05f, 0.05f, 0.5f);
}
}
// Free chat color
__instance.freeChatField.background.color = new Color32(40, 40, 40, byte.MaxValue);
__instance.freeChatField.textArea.compoText.Color(Color.white);
__instance.freeChatField.textArea.outputText.color = Color.white;
}
else
{
// Free chat color
__instance.freeChatField.background.color = new Color32(255, 255, 255, byte.MaxValue);
__instance.freeChatField.textArea.compoText.Color(Color.black);
__instance.freeChatField.textArea.outputText.color = Color.black;
}
// Free chat color
__instance.freeChatField.background.color = new Color32(40, 40, 40, byte.MaxValue);
__instance.freeChatField.textArea.compoText.Color(Color.white);
__instance.freeChatField.textArea.outputText.color = Color.white;
// Quick chat color
__instance.quickChatField.background.color = new Color32(40, 40, 40, byte.MaxValue);
__instance.quickChatField.text.color = Color.white;
__instance.quickChatButton.transform.Find("QuickChatIcon").GetComponent<SpriteRenderer>().color = new Color(0.5f, 0.5f, 0.5f, 1f);
__instance.openKeyboardButton.transform.Find("OpenKeyboardIcon").GetComponent<SpriteRenderer>().color = new Color(0.5f, 0.5f, 0.5f, 1f);
if ((Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) && Input.GetKeyDown(KeyCode.X))
{
@@ -107,137 +100,169 @@ class ChatPatch
}
}
// Add extra information to chat bubble
[HarmonyPatch(nameof(ChatController.AddChat))]
[HarmonyPrefix]
[HarmonyPriority(Priority.First)]
public static bool AddChat_Prefix(ChatController __instance, [HarmonyArgument(0)] PlayerControl sourcePlayer, [HarmonyArgument(1)] string chatText)
[HarmonyPostfix]
public static void AddChat_Postfix(ChatController __instance, [HarmonyArgument(0)] PlayerControl sourcePlayer, [HarmonyArgument(1)] string chatText)
{
bool censor = false;
if (!sourcePlayer || !PlayerControl.LocalPlayer)
ChatBubble chatBubble = SetChatPoolTheme();
StringBuilder sbTag = new StringBuilder();
StringBuilder sbInfo = new StringBuilder();
string hashPuid = Utils.GetHashPuid(sourcePlayer);
string friendCode = sourcePlayer.Data.FriendCode;
string playerName = sourcePlayer.Data.PlayerName;
string Role = $"<size=75%><color={sourcePlayer.GetTeamHexColor()}>{sourcePlayer.GetRoleName()}</color></size>+++";
if (GameStates.IsLobby && !GameStates.IsFreePlay)
{
return false;
Role = "";
if (sourcePlayer.IsDev())
sbTag.Append($"<color=#0088ff>Dev</color>+++");
if (((sourcePlayer.IsLocalPlayer() && GameStates.IsHost && Main.BetterHost.Value)
|| (!sourcePlayer.IsLocalPlayer() && sourcePlayer.BetterData().IsBetterHost && sourcePlayer.IsHost())))
sbTag.AppendFormat("<color=#0dff00>{1}{0}</color>+++", Translator.GetString("Player.BetterHost"), sourcePlayer.BetterData().IsVerifiedBetterUser || sourcePlayer.IsLocalPlayer() ? "✓ " : "");
else if ((sourcePlayer.IsLocalPlayer() || sourcePlayer.BetterData().IsBetterUser))
sbTag.AppendFormat("<color=#0dff00>{1}{0}</color>+++", Translator.GetString("Player.BetterUser"), sourcePlayer.BetterData().IsVerifiedBetterUser || sourcePlayer.IsLocalPlayer() ? "✓ " : "");
if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.SickoData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.SickoData.ContainsValue(friendCode))
sbTag.Append($"<color=#00f583>{Translator.GetString("Player.SickoUser")}</color>+++");
else if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.AUMData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.AUMData.ContainsValue(friendCode))
sbTag.Append($"<color=#4f0000>{Translator.GetString("Player.AUMUser")}</color>+++");
else if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.PlayerData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.PlayerData.ContainsValue(friendCode))
sbTag.Append($"<color=#fc0000>{Translator.GetString("Player.KnownCheater")}</color>+++");
}
NetworkedPlayerInfo data = PlayerControl.LocalPlayer.Data;
NetworkedPlayerInfo data2 = sourcePlayer.Data;
if (data2 == null || data == null || (data2.IsDead && !data.IsDead))
if (!sourcePlayer.IsImpostorTeammate())
{
return false;
}
ChatBubble pooledBubble = __instance.GetPooledBubble();
try
{
if (sourcePlayer.BetterData().IsBetterUser && GameStates.IsBetterHostLobby)
chatText = chatText.Replace("\n", "");
pooledBubble.transform.SetParent(__instance.scroller.Inner);
pooledBubble.transform.localScale = Vector3.one;
bool flag = sourcePlayer.IsLocalPlayer();
if (flag)
{
pooledBubble.SetRight();
}
else
{
pooledBubble.SetLeft();
}
bool didVote = MeetingHud.Instance && MeetingHud.Instance.DidVote(sourcePlayer.PlayerId);
pooledBubble.Background.color = new Color(0.05f, 0.05f, 0.05f, 1f);
pooledBubble.SetCosmetics(data2);
__instance.SetChatBubbleName(pooledBubble, data2, data2.IsDead, didVote, PlayerNameColor.Get(data2), null);
if (censor && DataManager.Settings.Multiplayer.CensorChat)
{
chatText = BlockedWords.CensorWords(chatText, false);
}
pooledBubble.SetText(chatText);
pooledBubble.AlignChildren();
__instance.AlignAllBubbles();
if (!__instance.IsOpenOrOpening && __instance.notificationRoutine == null)
{
__instance.notificationRoutine = __instance.StartCoroutine(__instance.BounceDot());
}
if (!flag)
{
SoundManager.Instance.PlaySound(__instance.messageSound, false, 1f, null).pitch = 0.5f + (float)sourcePlayer.PlayerId / 15f;
__instance.chatNotification.SetUp(sourcePlayer, chatText);
}
StringBuilder sbTag = new StringBuilder();
StringBuilder sbInfo = new StringBuilder();
string hashPuid = Utils.GetHashPuid(sourcePlayer);
string friendCode = sourcePlayer.Data.FriendCode;
string playerName = sourcePlayer.Data.PlayerName;
string Role = $"<size=75%><color={sourcePlayer.GetTeamHexColor()}>{sourcePlayer.GetRoleName()}</color></size>+++";
if (GameStates.IsLobby && !GameStates.IsFreePlay)
if (PlayerControl.LocalPlayer.IsAlive() && !sourcePlayer.IsLocalPlayer())
{
Role = "";
if (sourcePlayer.IsDev())
sbTag.Append($"<color=#0088ff>Dev</color>+++");
if (((sourcePlayer.IsLocalPlayer() && GameStates.IsHost && Main.BetterHost.Value)
|| (!sourcePlayer.IsLocalPlayer() && sourcePlayer.BetterData().IsBetterHost && sourcePlayer.IsHost())))
sbTag.AppendFormat("<color=#0dff00>{1}{0}</color>+++", Translator.GetString("Player.BetterHost"), sourcePlayer.BetterData().IsVerifiedBetterUser || sourcePlayer.IsLocalPlayer() ? "✓ " : "");
else if ((sourcePlayer.IsLocalPlayer() || sourcePlayer.BetterData().IsBetterUser))
sbTag.AppendFormat("<color=#0dff00>{1}{0}</color>+++", Translator.GetString("Player.BetterUser"), sourcePlayer.BetterData().IsVerifiedBetterUser || sourcePlayer.IsLocalPlayer() ? "✓ " : "");
if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.SickoData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.SickoData.ContainsValue(friendCode))
sbTag.Append($"<color=#00f583>{Translator.GetString("Player.SickoUser")}</color>+++");
else if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.AUMData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.AUMData.ContainsValue(friendCode))
sbTag.Append($"<color=#4f0000>{Translator.GetString("Player.AUMUser")}</color>+++");
else if (!string.IsNullOrEmpty(hashPuid) && AntiCheat.PlayerData.ContainsKey(hashPuid) || !string.IsNullOrEmpty(friendCode) && AntiCheat.PlayerData.ContainsValue(friendCode))
sbTag.Append($"<color=#fc0000>{Translator.GetString("Player.KnownCheater")}</color>+++");
}
if (!sourcePlayer.IsImpostorTeammate())
{
if (PlayerControl.LocalPlayer.IsAlive() && !sourcePlayer.IsLocalPlayer())
{
Role = "";
}
}
if (PlayerControl.LocalPlayer.Is(RoleTypes.GuardianAngel) && !sourcePlayer.IsAlive() || !PlayerControl.LocalPlayer.Is(RoleTypes.GuardianAngel))
{
sbTag.Append(Role);
}
sbInfo.Append("<size=75%>");
for (int i = 0; i < sbTag.ToString().Split("+++").Length; i++)
{
if (!string.IsNullOrEmpty(sbTag.ToString().Split("+++")[i]))
{
if (i < sbTag.ToString().Split("+++").Length)
{
sbInfo.Append(sbTag.ToString().Split("+++")[i]);
}
if (i != sbTag.ToString().Split("+++").Length - 2)
{
sbInfo.Append(" - ");
}
}
}
sbInfo.Append("</size>");
if (flag)
{
playerName = $"{sbInfo} " + playerName;
}
else
{
playerName += $" {sbInfo}";
}
pooledBubble.NameText.SetText(playerName);
Logger.Log($"{sourcePlayer.Data.PlayerName} -> {chatText}", "ChatLog");
}
catch
if (PlayerControl.LocalPlayer.Is(RoleTypes.GuardianAngel) && !sourcePlayer.IsAlive() || !PlayerControl.LocalPlayer.Is(RoleTypes.GuardianAngel))
{
sbTag.Append(Role);
}
return false;
sbInfo.Append("<size=75%>");
for (int i = 0; i < sbTag.ToString().Split("+++").Length; i++)
{
if (!string.IsNullOrEmpty(sbTag.ToString().Split("+++")[i]))
{
if (i < sbTag.ToString().Split("+++").Length)
{
sbInfo.Append(sbTag.ToString().Split("+++")[i]);
}
if (i != sbTag.ToString().Split("+++").Length - 2)
{
sbInfo.Append(" - ");
}
}
}
sbInfo.Append("</size>");
bool flag = sourcePlayer == PlayerControl.LocalPlayer;
if (flag)
{
playerName = $"{sbInfo} " + playerName;
}
else
{
playerName += $" {sbInfo}";
}
chatBubble.NameText.text = playerName;
chatBubble.ColorBlindName.color = Palette.PlayerColors[sourcePlayer.Data.DefaultOutfit.ColorId];
Logger.Log($"{sourcePlayer.Data.PlayerName} -> {chatText}", "ChatLog");
}
[HarmonyPatch(nameof(ChatController.AddChatNote))]
[HarmonyPostfix]
public static void AddChatNote_Postfix(ChatController __instance)
{
SetChatPoolTheme();
}
[HarmonyPatch(nameof(ChatController.AddChatWarning))]
[HarmonyPostfix]
public static void AddChatWarning_Postfix(ChatController __instance)
{
SetChatPoolTheme();
}
public static void SetChatTheme()
{
var chat = HudManager.Instance.Chat;
if (Main.ChatDarkMode.Value)
{
// Quick chat color
chat.quickChatField.background.color = new Color32(40, 40, 40, byte.MaxValue);
chat.quickChatField.text.color = Color.white;
// Icons
chat.quickChatButton.transform.Find("QuickChatIcon").GetComponent<SpriteRenderer>().color = new Color(0.5f, 0.5f, 0.5f, 1f);
chat.openKeyboardButton.transform.Find("OpenKeyboardIcon").GetComponent<SpriteRenderer>().color = new Color(0.5f, 0.5f, 0.5f, 1f);
}
else
{
// Quick chat color
chat.quickChatField.background.color = new Color32(255, 255, 255, byte.MaxValue);
chat.quickChatField.text.color = Color.black;
// Icons
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);
}
foreach (var item in HudManager.Instance.Chat.chatBubblePool.activeChildren.ToArray().Select(c => c.GetComponent<ChatBubble>()))
{
SetChatPoolTheme(item);
}
}
// Set chat theme
public static ChatBubble SetChatPoolTheme(ChatBubble? asChatBubble = null)
{
ChatBubble Get() => HudManager.Instance.Chat.chatBubblePool.activeChildren.ToArray()
.Select(c => c.GetComponent<ChatBubble>())
.Last();
ChatBubble chatBubble = asChatBubble ??= Get();
if (Main.ChatDarkMode.Value)
{
chatBubble.transform.Find("ChatText (TMP)").GetComponent<TextMeshPro>().color = new Color(1f, 1f, 1f, 1f);
chatBubble.transform.Find("Background").GetComponent<SpriteRenderer>().color = new Color(0.05f, 0.05f, 0.05f, 1f);
if (chatBubble.transform.Find("PoolablePlayer/xMark") != null)
{
if (chatBubble.transform.Find("PoolablePlayer/xMark").GetComponent<SpriteRenderer>().enabled == true)
{
chatBubble.transform.Find("Background").GetComponent<SpriteRenderer>().color = new Color(0.05f, 0.05f, 0.05f, 0.5f);
}
}
}
else
{
chatBubble.transform.Find("ChatText (TMP)").GetComponent<TextMeshPro>().color = new Color(0f, 0f, 0f, 1f);
chatBubble.transform.Find("Background").GetComponent<SpriteRenderer>().color = new Color(1f, 1f, 1f, 1f);
if (chatBubble.transform.Find("PoolablePlayer/xMark") != null)
{
if (chatBubble.transform.Find("PoolablePlayer/xMark").GetComponent<SpriteRenderer>().enabled == true)
{
chatBubble.transform.Find("Background").GetComponent<SpriteRenderer>().color = new Color(1f, 1f, 1f, 0.5f);
}
}
}
return chatBubble;
}
}
+14 -2
View File
@@ -12,6 +12,7 @@ public static class OptionsMenuBehaviourPatch
private static ClientOptionItem? BetterHost;
private static ClientOptionItem? BetterNotifications;
private static ClientOptionItem? ForceOwnLanguage;
private static ClientOptionItem? ChatDarkMode;
private static ClientOptionItem? ChatInGameplay;
private static ClientOptionItem? LobbyPlayerInfo;
private static ClientOptionItem? DisableLobbyTheme;
@@ -84,7 +85,18 @@ public static class OptionsMenuBehaviourPatch
string title = Translator.GetString("BetterOption.ForceOwnLanguage");
ForceOwnLanguage = ClientOptionItem.Create(title, Main.ForceOwnLanguage, __instance);
}
if (ChatDarkMode == null || ChatDarkMode.ToggleButton == null)
{
string title = Translator.GetString("BetterOption.ChatDarkMode");
ChatDarkMode = ClientOptionItem.Create(title, Main.ChatDarkMode, __instance, ChatDarkModeToggle);
static void ChatDarkModeToggle()
{
ChatPatch.ChatControllerPatch.SetChatTheme();
}
}
if (ChatInGameplay == null || ChatInGameplay.ToggleButton == null)
{
string title = Translator.GetString("BetterOption.ChatInGame");
@@ -143,7 +155,7 @@ public static class OptionsMenuBehaviourPatch
}
}
}
if (SwitchToVanilla == null || SwitchToVanilla.ToggleButton == null)
{
string title = Translator.GetString("BetterOption.ToVanilla");
+1 -3
View File
@@ -1,8 +1,6 @@
using BepInEx.Unity.IL2CPP.Utils;
using HarmonyLib;
using HarmonyLib;
using InnerNet;
using UnityEngine;
using static UnityEngine.GraphicsBuffer;
namespace BetterAmongUs.Patches;
+10 -11
View File
@@ -3,7 +3,6 @@ using AmongUs.GameOptions;
using HarmonyLib;
using Hazel;
using Il2CppSystem.Text;
using Steamworks;
using TMPro;
using UnityEngine;
@@ -17,7 +16,7 @@ class CommandsPatch
private static bool HasPermission => Permission != null
&& AmongUsClient.Instance?.GetHost()?.Character?.Data == Permission;
public static NetworkedPlayerInfo? Permission = null;
public static string CommandPrefix => !GameStates.IsTOHEHostLobby ? Main.CommandPrefix.Value : Main.CommandPrefix.Value == "/" ? "." : Main.CommandPrefix.Value;
// List of helper text when a command is being typed out
// First word is command, {} are arguments, first --- is command description, second --- is for help command.
@@ -116,7 +115,7 @@ class CommandsPatch
{
if (i < allCommands.Length)
{
list += $"\n{mid}<color=#e0b700><b>{Main.CommandPrefix.Value}{allCommands[i].Split(' ')[0].Split("---")[0]}</b></color> <size=65%><color=#735e00>{allCommands[i].Split("---")[1]}.</color></size>";
list += $"\n{mid}<color=#e0b700><b>{CommandPrefix}{allCommands[i].Split(' ')[0].Split("---")[0]}</b></color> <size=65%><color=#735e00>{allCommands[i].Split("---")[1]}.</color></size>";
}
}
if (Main.myAccountInfo.IsSponsor == true)
@@ -127,7 +126,7 @@ class CommandsPatch
{
if (i < allSponsorCommands.Length)
{
list += $"\n{mid}<color=#e0b700><b>{Main.CommandPrefix.Value}{allSponsorCommands[i].Split(' ')[0].Split("---")[0]}</b></color> <size=65%><color=#735e00>{allSponsorCommands[i].Split("---")[1]}.</color></size>";
list += $"\n{mid}<color=#e0b700><b>{CommandPrefix}{allSponsorCommands[i].Split(' ')[0].Split("---")[0]}</b></color> <size=65%><color=#735e00>{allSponsorCommands[i].Split("---")[1]}.</color></size>";
}
}
}
@@ -139,7 +138,7 @@ class CommandsPatch
{
if (i < allDebugCommands.Length)
{
list += $"\n{mid}<color=#e0b700><b>{Main.CommandPrefix.Value}{allDebugCommands[i].Split(' ')[0].Split("---")[0]}</b></color> <size=65%><color=#735e00>{allDebugCommands[i].Split("---")[1]}.</color></size>";
list += $"\n{mid}<color=#e0b700><b>{CommandPrefix}{allDebugCommands[i].Split(' ')[0].Split("---")[0]}</b></color> <size=65%><color=#735e00>{allDebugCommands[i].Split("---")[1]}.</color></size>";
}
}
}
@@ -253,7 +252,7 @@ class CommandsPatch
{
RPC.SyncAllNames();
hasSet = true;
}, 1f, $"Command {Main.CommandPrefix.Value}name");
}, 1f, $"Command {CommandPrefix}name");
}
else if (command.Length > 1 && !string.IsNullOrWhiteSpace(command[1]) && System.Text.RegularExpressions.Regex.IsMatch(command[1], @"^[a-zA-Z0-9]+$"))
{
@@ -282,7 +281,7 @@ class CommandsPatch
if (HandleIsHost(command) == true)
{
var player = cmdTarget;
var cmdFlag = command[0][1..].ToLower().Trim() != "kick";
var cmdFlag = command[0][1..].ToLower().Trim() != FormatCommandTranslation("Command.Helper.kick");
player.Kick(cmdFlag);
}
}
@@ -588,7 +587,7 @@ class CommandsPatch
string text = __instance.freeChatField.textArea.text;
if (string.IsNullOrEmpty(text) || text.Length <= 1 || text[0].ToString() != Main.CommandPrefix.Value || 3f - __instance.timeSinceLastMessage > 0f)
if (string.IsNullOrEmpty(text) || text.Length <= 1 || text[0].ToString() != CommandPrefix || 3f - __instance.timeSinceLastMessage > 0f)
{
if (GameStates.InGame && !GameStates.IsLobby && !GameStates.IsFreePlay && !GameStates.IsMeeting && !GameStates.IsExilling && PlayerControl.LocalPlayer.IsAlive())
return false;
@@ -671,7 +670,7 @@ class CommandsPatch
if (commandText != null && commandInfo != null)
{
// Check if the first character is the command prefix
if (text.Length > 0 && text[0].ToString() == Main.CommandPrefix.Value)
if (text.Length > 0 && text[0].ToString() == CommandPrefix)
{
// Get the typed command without the prefix
string typedCommand = text.Substring(1);
@@ -712,11 +711,11 @@ class CommandsPatch
if (Input.GetKeyDown(KeyCode.Tab) && typedParts.Length < 2)
{
__instance.freeChatField.textArea.SetText(Main.CommandPrefix.Value + commandParts[0]);
__instance.freeChatField.textArea.SetText(CommandPrefix + commandParts[0]);
}
// Display the command suggestion
commandText.GetComponent<TextMeshPro>().text = Main.CommandPrefix.Value + suggestion;
commandText.GetComponent<TextMeshPro>().text = CommandPrefix + suggestion;
commandInfo.GetComponent<TextMeshPro>().text = CommandInfo;
}
else
+1 -1
View File
@@ -150,7 +150,7 @@ class GamePlayManager
__instance.StartButton.gameObject.SetActive(true);
if (__instance.startState == GameStartManager.StartingStates.Countdown)
{
__instance.StartButton.buttonText.text = string.Format("{0}: {1}", Translator.GetString(StringNames.Cancel),(int)__instance.countDownTimer + 1);
__instance.StartButton.buttonText.text = string.Format("{0}: {1}", Translator.GetString(StringNames.Cancel), (int)__instance.countDownTimer + 1);
}
else
{
+2 -2
View File
@@ -1,5 +1,5 @@
using InnerNet;
using HarmonyLib;
using HarmonyLib;
using InnerNet;
namespace BetterAmongUs;
+6 -19
View File
@@ -81,26 +81,26 @@ class MeetingHudUpdatePatch
switch (playerData.BetterData().DisconnectReason)
{
case DisconnectReasons.ExitGame:
DisconnectText = "Left The Game";
DisconnectText = Translator.GetString("DisconnectReasonMeeting.Left");
break;
case DisconnectReasons.Banned:
if (playerData.BetterData().AntiCheatInfo.BannedByAntiCheat)
{
DisconnectText = "Banned By Anti-Cheat";
DisconnectText = Translator.GetString("DisconnectReasonMeeting.AntiCheat");
}
else
{
DisconnectText = "Banned By Host";
DisconnectText = Translator.GetString("DisconnectReasonMeeting.Banned");
}
break;
case DisconnectReasons.Kicked:
DisconnectText = "Kicked By Host";
DisconnectText = Translator.GetString("DisconnectReasonMeeting.Kicked");
break;
case DisconnectReasons.Hacking:
DisconnectText = "Banned By Server";
DisconnectText = Translator.GetString("DisconnectReasonMeeting.Cheater");
break;
default:
DisconnectText = "Disconnected";
DisconnectText = Translator.GetString("DisconnectReasonMeeting.Disconnect");
break;
}
@@ -204,19 +204,6 @@ class MeetingHudUpdatePatch
}
}
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.ClearVote))]
class MeetingHud_ClearVotePatch
{
public static void Postfix()
{
// Clear info for Anti-Cheat
foreach (var player in Main.AllPlayerControls)
{
player.BetterData().AntiCheatInfo.ChatDidVote = false;
}
}
}
[HarmonyPatch(typeof(MeetingHud), nameof(MeetingHud.OnDestroy))]
class MeetingHud_OnDestroyPatch
{
+1 -1
View File
@@ -86,7 +86,7 @@ public class PingTrackerPatch
return newPing;
}
private static string GetTimeColor(float time)
{
float minutes = (int)time / 60 + 1f;
+17 -12
View File
@@ -35,18 +35,19 @@ public static class OnPlayerJoinedPatch
{
public static void Postfix(/*AmongUsClient __instance,*/ [HarmonyArgument(0)] ClientData client)
{
var player = Utils.PlayerFromClientId(client.Id);
PlayerControlPatch.infotime = 0f;
if (player != null)
{
player.BetterData().ClearData();
}
_ = new LateTask(() =>
{
if (GameStates.IsInGame)
{
var player = Utils.PlayerFromClientId(client.Id);
if (player != null)
{
player.BetterData().ClearData();
}
// Send Better Among Us Check RPC
RPC.SendBetterCheck();
@@ -68,12 +69,15 @@ public static class OnPlayerJoinedPatch
if (!string.IsNullOrEmpty(player.Data.FriendCode) && text.Contains(player.Data.FriendCode)
|| !string.IsNullOrEmpty(Utils.GetHashPuid(player)) && text.Contains(Utils.GetHashPuid(player)))
{
player.Kick(true, $"has been banned due to being on the ban player list!");
player.Kick(true, Translator.GetString("AntiCheat.BanPlayerListMessage"), bypassDataCheck: true);
break;
}
}
}
catch { }
catch (Exception ex)
{
Logger.Error(ex);
}
}
}
@@ -100,7 +104,7 @@ public static class OnPlayerJoinedPatch
if (!string.IsNullOrEmpty(normalizedPlayerName) && isNameBanned)
{
player.Kick(false, $"has been kicked due to their name being on the ban name list!");
player.Kick(false, Translator.GetString("AntiCheat.BanNameListMessage"), bypassDataCheck: true);
}
}
catch { }
@@ -136,9 +140,10 @@ class GameDataShowNotificationPatch
{
public static void BetterShowNotification(NetworkedPlayerInfo playerData, DisconnectReasons reason = DisconnectReasons.Unknown, string forceReasonText = "")
{
if (playerData.BetterData().AntiCheatInfo.BannedByAntiCheat) return;
if (playerData.BetterData().AntiCheatInfo.BannedByAntiCheat || playerData.BetterData().HasShowDcMsg) return;
playerData.BetterData().HasShowDcMsg = true;
string playerName = playerData.BetterData().RealName;
string? playerName = playerData.BetterData().RealName;
if (forceReasonText != "")
{
@@ -167,7 +172,7 @@ class GameDataShowNotificationPatch
ReasonText = string.Format(Translator.GetString("DisconnectReason.Banned"), playerName, AmongUsClient.Instance.GetHost().Character.Data.PlayerName);
break;
case DisconnectReasons.Hacking:
ReasonText = string.Format(Translator.GetString("DisconnectReason.Disconnect"), playerName);
ReasonText = string.Format(Translator.GetString("DisconnectReason.Cheater"), playerName);
break;
case DisconnectReasons.Error:
ReasonText = string.Format(Translator.GetString("DisconnectReason.Error"), playerName);
-1
View File
@@ -1,7 +1,6 @@
using AmongUs.GameOptions;
using HarmonyLib;
using Hazel;
using static Il2CppSystem.Globalization.CultureInfo;
namespace BetterAmongUs.Patches;
+10 -16
View File
@@ -7,7 +7,6 @@ class SplashIntroPatch
{
public static bool BetterIntro = false;
public static bool IsReallyDoneLoading = false;
private static float ShowTime = 0f;
private static GameObject BetterLogo;
[HarmonyPatch(typeof(SplashManager))]
@@ -24,27 +23,20 @@ class SplashIntroPatch
[HarmonyPrefix]
public static bool Update_Prefix(SplashManager __instance)
{
ShowTime += Time.deltaTime;
if (ShowTime > 6f && BetterIntro)
if (Time.time - __instance.startTime > 2f && BetterIntro)
{
UnityEngine.Object.Destroy(__instance.logoAnimFinish.GetComponent<AudioSource>());
}
/*
if (Input.GetKeyDown(KeyCode.Mouse0) || Input.GetKeyDown(KeyCode.Mouse1))
{
if (ShowTime > 2.5f && !IsReallyDoneLoading)
if (Time.time - __instance.startTime > 2f || BetterIntro)
{
IsReallyDoneLoading = true;
__instance.startedSceneLoad = true;
__instance.sceneChanger.BeginLoadingScene();
__instance.sceneChanger.AllowFinishLoadingScene();
__instance.logoAnimFinish.gameObject.SetActive(false);
__instance.loadingObject.SetActive(true);
__instance.startedSceneLoad = true;
}
}
*/
if (__instance.doneLoadingRefdata && !__instance.startedSceneLoad && Time.time - __instance.startTime > __instance.minimumSecondsBeforeSceneChange)
{
@@ -55,22 +47,24 @@ class SplashIntroPatch
__instance.logoAnimFinish.gameObject.SetActive(true);
GameObject InnerLogo = __instance.logoAnimFinish.transform.Find("LogoRoot/ISLogo").gameObject;
BetterLogo = UnityEngine.Object.Instantiate(InnerLogo, InnerLogo.transform.parent);
GameObject.Destroy(InnerLogo);
UnityEngine.Object.Destroy(InnerLogo);
BetterLogo.name = "BetterLogo";
BetterLogo.GetComponent<SpriteRenderer>().sprite = Utils.LoadSprite("BetterAmongUs.Resources.Images.BetterAmongUs-By-The-Enhanced-Network-Logo.png", 150f);
__instance.logoAnimFinish.transform.Find("BlackOverlay").transform.SetLocalY(0f);
__instance.loadingObject.SetActive(false);
__instance.startedSceneLoad = false;
BetterIntro = true;
return false;
}
__instance.startedSceneLoad = BetterIntro;
BetterIntro = true;
__instance.startedSceneLoad = true;
if (__instance.startedSceneLoad && BetterIntro)
{
IsReallyDoneLoading = true;
__instance.sceneChanger.AllowFinishLoadingScene();
__instance.startedSceneLoad = true;
__instance.loadingObject.SetActive(true);
IsReallyDoneLoading = true;
}
}
+11
View File
@@ -15,6 +15,7 @@
"Timer": "Timer",
"SystemMessage": "System Message",
"SystemNotification": "System Notification",
"ModdedLobbyMsg": "{0} does not support\n<b>Modded Lobbies</b>",
"Player.Loading": "Loading",
"Player.NoFriendCode": "No Friend Code",
@@ -34,6 +35,13 @@
"DisconnectReason.Error": "{0} Was kicked due to an error!",
"DisconnectReason.Unknown": "{0} Left the game due to unknown reason?",
"DisconnectReasonMeeting.Left": "Left The Game",
"DisconnectReasonMeeting.Disconnect": "Disconnected",
"DisconnectReasonMeeting.Kicked": "Kicked By Host",
"DisconnectReasonMeeting.Banned": "Banned By Host",
"DisconnectReasonMeeting.AntiCheat": "Banned By Anti-Cheat",
"DisconnectReasonMeeting.Cheater": "Banned By Server",
"WelcomeMsg.WelcomeToBAU": "Welcome To {0}",
"WelcomeMsg.ThanksForDownloading": "Thanks for downloading!",
"WelcomeMsg.BAUDescription1": "<color=#0dff00>{0}</color> Is a mod for improving the vanilla Among Us experience with a built-in {1} and other futures, <color=#0dff00>{0}</color> is a client-sided mod so it can be used with other vanilla Among Us players.",
@@ -44,6 +52,7 @@
"BetterOption.BetterHost": "<color=#4f92ff>Better Host</color>",
"BetterOption.BetterNotifications": "<color=#4f92ff>Better Notifications</color>",
"BetterOption.ForceOwnLanguage": "Force System language",
"BetterOption.ChatDarkMode": "Chat Dark Mode",
"BetterOption.ChatInGame": "Chat In Gameplay",
"BetterOption.LobbyInfo": "Show Lobby Info",
"BetterOption.LobbyTheme": "Disable Lobby Theme",
@@ -92,6 +101,8 @@
"AntiCheat.UnauthorizedAction": "Has been detected doing an unauthorized action",
"AntiCheat.ByAntiCheat": "{0} by <color=#4f92ff>Anti-Cheat</color>",
"AntiCheat.KickMessage": "{0}! Reason: <color=#fc0000>{1}</color>",
"AntiCheat.BanPlayerListMessage": "has been {0} due to being on the ban player list!",
"AntiCheat.BanNameListMessage": "has been {0} due to their name being on the ban name list!",
"AntiCheat.HasBeenDetectedWithCheat": "Has been detected with a cheat",
"AntiCheat.HasBeenDetectedWithCheat2": "Has been detected with a cheat client",
"AntiCheat.InvalidAction": "Invalid Action RPC: {0}",
+9 -2
View File
@@ -25,11 +25,11 @@ public class Main : BasePlugin
{
public static readonly ReleaseTypes ReleaseBuildType = ReleaseTypes.Release;
public const string BetaNum = "0";
public const string HotfixNum = "1";
public const string HotfixNum = "3";
public const bool IsHotFix = true;
public const string PluginGuid = "com.ten.betteramongus";
public const string PluginVersion = "1.1.4";
public const string ReleaseDate = "09.20.2024"; // mm/dd/yyyy
public const string ReleaseDate = "09.23.2024"; // mm/dd/yyyy
public const string Github = "https://github.com/EnhancedNetwork/BetterAmongUs-Public";
public const string Discord = "https://discord.gg/ten";
public static BetterAccountInfo myAccountInfo = new();
@@ -153,6 +153,11 @@ public class Main : BasePlugin
{
try
{
ConsoleManager.CreateConsole();
ConsoleManager.SetConsoleTitle("Among Us - BAU Console");
ConsoleManager.ConfigPreventClose.Value = true;
ConsoleManager.ConsoleStream.WriteLine($".--------------------------------------------------------------------------------.\r\n| ____ _ _ _ _ _ |\r\n| | __ ) ___| |_| |_ ___ _ __ / \\ _ __ ___ ___ _ __ __ _ | | | |___ |\r\n| | _ \\ / _ \\ __| __/ _ \\ '__| / _ \\ | '_ ` _ \\ / _ \\| '_ \\ / _` | | | | / __||\r\n| | |_) | __/ |_| || __/ | / ___ \\| | | | | | (_) | | | | (_| | | |_| \\__ \\|\r\n| |____/ \\___|\\__|\\__\\___|_| /_/ \\_\\_| |_| |_|\\___/|_| |_|\\__, | \\___/|___/|\r\n| |___/ |\r\n'--------------------------------------------------------------------------------'");
Logger = BepInEx.Logging.Logger.CreateLogSource(PluginGuid);
BetterDataManager.SetUp();
@@ -199,6 +204,7 @@ public class Main : BasePlugin
public static ConfigEntry<bool> BetterHost { get; private set; }
public static ConfigEntry<bool> BetterNotifications { get; private set; }
public static ConfigEntry<bool> ForceOwnLanguage { get; private set; }
public static ConfigEntry<bool> ChatDarkMode { get; private set; }
public static ConfigEntry<bool> ChatInGameplay { get; private set; }
public static ConfigEntry<bool> LobbyPlayerInfo { get; private set; }
public static ConfigEntry<bool> DisableLobbyTheme { get; private set; }
@@ -211,6 +217,7 @@ public class Main : BasePlugin
BetterHost = Config.Bind("Better Options", "BetterHost", false);
BetterNotifications = Config.Bind("Better Options", "BetterNotifications", true);
ForceOwnLanguage = Config.Bind("Better Options", "ForceOwnLanguage", false);
ChatDarkMode = Config.Bind("Better Options", "ChatDarkMode", true);
ChatInGameplay = Config.Bind("Better Options", "ChatInGameplay", true);
LobbyPlayerInfo = Config.Bind("Better Options", "LobbyPlayerInfo", true);
DisableLobbyTheme = Config.Bind("Better Options", "DisableLobbyTheme", true);