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<ConfigEntryBase>());
});
((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<T>(ConfigEntry<T> entry, Action<T> 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<bool> DisableKillfeed { get; private set; }
public static ConfigEntry<bool> DisableModsPopout { get; private set; }
public static ConfigEntry<int> 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<bool>("UI", "DisableKillfeed", false, "Hide the killfeed.");
DisableModsPopout = cfg.Bind<bool>("UI", "DisableModsPopout", false, "Hide the game's 'mods detected' warning.");
NetGraphMode = cfg.Bind<int>("UI", "NetGraph", 0, new ConfigDescription("FPS and ping overlay. 0 = off, 1 = text, 2 = text and graph.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
}
}
}