using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CMRLib.Core; using ComputerysModdingUtilities; using FishNet; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: StraftatMod(true)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Theanine")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+035ee42632884b38ea937935eb423d7c7e886381")] [assembly: AssemblyProduct("Theanine")] [assembly: AssemblyTitle("Theanine")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Theanine { internal static class Killfeed { private const string UiRoot = "---USER INTERFACE---"; private const string LogsName = "LogsPosition"; private const string StartRoundText = "START ROUND TEXT"; private const string PlayerNameText = "PlayerNameText"; private const float HiddenY = 10000f; private const int CheckEveryFrames = 30; private static ManualLogSource _log; private static bool _enabled; private static Transform _logs; private static Transform _playerName; private static float? _logsOriginalY; private static float? _playerNameOriginalY; private static int _lastCheck = -999; public static bool Enabled { get { return _enabled; } set { if (_enabled != value) { _enabled = value; _log.LogInfo((object)("[Killfeed] hiding -> " + (value ? "on" : "off"))); Apply(); } } } public static void Install(ManualLogSource log, bool enabled) { _log = log; _enabled = enabled; CmrHost.Tick += OnTick; _log.LogInfo((object)("[Killfeed] installed, hiding " + (enabled ? "on" : "off"))); } private static void OnTick() { if (Time.frameCount - _lastCheck >= 30) { _lastCheck = Time.frameCount; Apply(); } } private static void Apply() { Resolve(); Move(_logs, _logsOriginalY, "LogsPosition"); Move(_playerName, _playerNameOriginalY, "PlayerNameText"); } private static void Resolve() { if ((Object)(object)_logs != (Object)null && (Object)(object)_playerName != (Object)null) { return; } Transform val = UiFind.Root("---USER INTERFACE---"); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)_logs == (Object)null) { _logs = UiFind.Descendant(val, "LogsPosition"); if ((Object)(object)_logs != (Object)null) { Remember(_logs, ref _logsOriginalY, "LogsPosition"); } } if (!((Object)(object)_playerName == (Object)null)) { return; } Transform val2 = UiFind.Descendant(val, "START ROUND TEXT"); if ((Object)(object)val2 != (Object)null) { _playerName = UiFind.Descendant(val2, "PlayerNameText"); if ((Object)(object)_playerName != (Object)null) { Remember(_playerName, ref _playerNameOriginalY, "PlayerNameText"); } } } private static void Remember(Transform t, ref float? slot, string name) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (!slot.HasValue) { float y = t.localPosition.y; if (y >= 9999f) { _log.LogWarning((object)($"[Killfeed] {name} found already hidden (Y={y}) - the original is unknown, " + "restoring it will be impossible until the game restarts")); return; } slot = y; _log.LogInfo((object)$"[Killfeed] {name}: remembered original Y = {y}"); } } private static void Move(Transform t, float? originalY, string name) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t == (Object)null) { return; } float num; if (_enabled) { num = 10000f; } else { if (!originalY.HasValue) { return; } num = originalY.Value; } Vector3 localPosition = t.localPosition; if (!(Mathf.Abs(localPosition.y - num) < 0.1f)) { t.localPosition = new Vector3(localPosition.x, num, localPosition.z); _log.LogInfo((object)$"[Killfeed] {name}: Y {localPosition.y} -> {num}"); } } } [HarmonyPatch] internal static class ModsPopup { private static readonly string[] Markers = new string[3] { "mods detected", "non-vanilla", "matchmaking pool" }; private static ManualLogSource _log; public static bool Enabled { get; set; } public static void Install(ManualLogSource log, bool enabled) { _log = log; Enabled = enabled; _log.LogInfo((object)("[Popup] mods warning suppression: " + (enabled ? "on" : "off"))); } [HarmonyPatch(typeof(PauseManager), "ShowInfoPopup")] [HarmonyPrefix] private static bool Prefix(string __0) { try { string text = __0 ?? ""; if (!Enabled) { _log.LogInfo((object)("[Popup] shown (suppression off): \"" + Shorten(text) + "\"")); return true; } if (!IsAboutMods(text)) { _log.LogInfo((object)("[Popup] passed through (not about mods): \"" + Shorten(text) + "\"")); return true; } _log.LogInfo((object)("[Popup] SUPPRESSED: \"" + Shorten(text) + "\"")); return false; } catch (Exception ex) { _log.LogError((object)("[Popup] prefix failed: " + ex.GetType().Name + ": " + ex.Message)); return true; } } private static bool IsAboutMods(string text) { string text2 = text.ToLowerInvariant(); string[] markers = Markers; foreach (string value in markers) { if (text2.Contains(value)) { return true; } } return false; } private static string Shorten(string s) { if (s.Length > 60) { return s.Substring(0, 57) + "..."; } return s; } } internal static class NetGraph { private const int GraphWidth = 300; private const int GraphHeight = 60; private const float FpsScaleMax = 200f; private const float PingScaleMax = 200f; private static ManualLogSource _log; private static int _mode; private static float _smoothedDelta; private static float _fps; private static long _ping; private static readonly float[] _fpsHistory = new float[300]; private static readonly float[] _pingHistory = new float[300]; private static int _cursor; private static GUIStyle _style; private static Texture2D _dot; public static int Mode { get { return _mode; } set { int num = Mathf.Clamp(value, 0, 2); if (_mode != num) { _mode = num; _log.LogInfo((object)$"[NetGraph] mode -> {_mode}"); } } } public static void Install(ManualLogSource log, int mode) { _log = log; _mode = Mathf.Clamp(mode, 0, 2); CmrHost.Tick += OnTick; CmrHost.GuiDraw += OnGui; _log.LogInfo((object)$"[NetGraph] installed, mode {_mode}"); } private static void OnTick() { if (_mode != 0) { _smoothedDelta += (Time.unscaledDeltaTime - _smoothedDelta) * 0.1f; _fps = ((_smoothedDelta > 0f) ? (1f / _smoothedDelta) : 0f); if ((Object)(object)InstanceFinder.TimeManager != (Object)null) { _ping = InstanceFinder.TimeManager.RoundTripTime; } if (_mode >= 2) { _fpsHistory[_cursor] = _fps; _pingHistory[_cursor] = _ping; _cursor = (_cursor + 1) % 300; } } } private static void OnGui() { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (_mode != 0) { EnsureStyles(); int width = Screen.width; int height = Screen.height; GUI.color = Color.white; GUI.Label(new Rect((float)(width - 310), (float)(height - 100), 300f, 80f), $"FPS: {Mathf.CeilToInt(_fps)}\nMS: {_ping}", _style); if (_mode >= 2) { DrawGraph(width - 310, height - 80); } } } private static void DrawGraph(float x, float y) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) float num = y + 60f; for (int i = 0; i < 300; i += 2) { int num2 = (_cursor + i) % 300; float num3 = Mathf.Clamp(_fpsHistory[num2] / 200f * 60f, 0f, 60f); float num4 = Mathf.Clamp(_pingHistory[num2] / 200f * 60f, 0f, 60f); GUI.color = Color.green; GUI.DrawTexture(new Rect(x + (float)i, num - num3, 1f, 2f), (Texture)(object)_dot); GUI.color = Color.yellow; GUI.DrawTexture(new Rect(x + (float)i, num - num4, 1f, 2f), (Texture)(object)_dot); } GUI.color = Color.white; } private static void EnsureStyles() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (_style == null) { GUIStyle val = new GUIStyle { alignment = (TextAnchor)8, fontSize = 14 }; val.normal.textColor = Color.white; _style = val; _dot = new Texture2D(1, 1); _dot.SetPixel(0, 0, Color.white); _dot.Apply(); ((Object)_dot).hideFlags = (HideFlags)61; } } } [BepInPlugin("cmr.theanine", "Theanine", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class TheaninePlugin : BaseUnityPlugin { public const string ModGuid = "cmr.theanine"; public const string ModName = "Theanine"; public const string ModVersion = "1.0.0"; private readonly Harmony _harmony = new Harmony("cmr.theanine"); private void Awake() { TheanineSettings.Bind(((BaseUnityPlugin)this).Config); Install("UI host", delegate { CmrHost.Install(((BaseUnityPlugin)this).Logger); }); Install("Killfeed", delegate { Killfeed.Install(((BaseUnityPlugin)this).Logger, TheanineSettings.DisableKillfeed.Value); Wire(TheanineSettings.DisableKillfeed, delegate(bool v) { Killfeed.Enabled = v; }); }); Install("Mods popup", delegate { ModsPopup.Install(((BaseUnityPlugin)this).Logger, TheanineSettings.DisableModsPopout.Value); _harmony.PatchAll(typeof(ModsPopup)); Wire(TheanineSettings.DisableModsPopout, delegate(bool v) { ModsPopup.Enabled = v; }); }); Install("NetGraph", delegate { NetGraph.Install(((BaseUnityPlugin)this).Logger, TheanineSettings.NetGraphMode.Value); Wire(TheanineSettings.NetGraphMode, delegate(int v) { NetGraph.Mode = v; }); }); Install("Mod menu (optional)", delegate { ModMenuDecoration.Apply(typeof(TheaninePlugin), "Theanine.Resources.icon.png", "Interface quality of life.", ((BaseUnityPlugin)this).Logger, Array.Empty()); }); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Theanine 1.0.0 - ready"); } private void Install(string name, Action install) { try { install(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[Features] " + name + ": installed")); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[Features] " + name + ": NOT installed - " + ex.GetType().Name + ": " + ex.Message)); } } private void Wire(ConfigEntry entry, Action apply) { entry.SettingChanged += delegate { ((BaseUnityPlugin)this).Logger.LogInfo((object)$"[Settings] {((ConfigEntryBase)entry).Definition.Section}/{((ConfigEntryBase)entry).Definition.Key} -> {entry.Value}"); apply(entry.Value); }; } } internal static class TheanineSettings { public static ConfigEntry DisableKillfeed { get; private set; } public static ConfigEntry DisableModsPopout { get; private set; } public static ConfigEntry NetGraphMode { get; private set; } public static void Bind(ConfigFile cfg) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown DisableKillfeed = cfg.Bind("UI", "DisableKillfeed", false, "Hide the killfeed."); DisableModsPopout = cfg.Bind("UI", "DisableModsPopout", false, "Hide the game's 'mods detected' warning."); NetGraphMode = cfg.Bind("UI", "NetGraph", 0, new ConfigDescription("FPS and ping overlay. 0 = off, 1 = text, 2 = text and graph.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 2), Array.Empty())); } } }