Decompiled source of SmartConnect v1.0.0

SmartConnect.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Microsoft.CodeAnalysis;
using ProjectM;
using ProjectM.Shared;
using ProjectM.UI;
using Stunlock.Network;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SmartConnect")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SmartConnect")]
[assembly: AssemblyTitle("SmartConnect")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 SmartConnect
{
	[BepInPlugin("io.zfolmt.SmartConnect", "SmartConnect", "1.0.0")]
	internal class Plugin : BasePlugin
	{
		private Harmony _harmony;

		private static readonly string ConfigFile = Path.Combine(Paths.ConfigPath, "io.zfolmt.SmartConnect.cfg");

		private static ConfigEntry<bool> enable;

		private static ConfigEntry<int> timerSeconds;

		private static ConfigEntry<bool> showTimer;

		private static ConfigEntry<string> ipAddress;

		private static ConfigEntry<bool> autoJoin;

		internal static Plugin Instance { get; private set; }

		public static Harmony Harmony => Instance._harmony;

		public static ManualLogSource LogInstance => ((BasePlugin)Instance).Log;

		public static bool Enabled => enable.Value;

		public static int TimerSeconds => timerSeconds.Value;

		public static bool ShowTimer => showTimer.Value;

		public static string IPAddress => ipAddress.Value;

		public static bool AutoJoin => autoJoin.Value;

		public override void Load()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			Instance = this;
			_harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
			InitConfig();
			ManualLogSource log = ((BasePlugin)this).Log;
			bool flag = default(bool);
			BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(63, 2, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("SmartConnect");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0");
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] loaded! Note that this will do nothing on dedicated servers.");
			}
			log.LogInfo(val);
		}

		private static void InitConfig()
		{
			CreateFile(ConfigFile);
			enable = InitConfigEntry("General", "Enable", defaultValue: false, "Enable/Disable SmartConnect (auto continue).");
			timerSeconds = InitConfigEntry("General", "TimerSeconds", 5, "Timer in seconds before mod will continue, or join. Detected mouse left-clicks will deactivate the timer until next restart.");
			showTimer = InitConfigEntry("General", "ShowTimer", defaultValue: true, "Show radial timer on screen.");
			ipAddress = InitConfigEntry("General", "IPAddress", "", "Server address to join if auto join is enabled.");
			autoJoin = InitConfigEntry("General", "AutoJoin", defaultValue: false, "Enable to automatically join the entered server address instead of using 'Continue'.");
		}

		private static ConfigEntry<T> InitConfigEntry<T>(string section, string key, T defaultValue, string description)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<T> val = ((BasePlugin)Instance).Config.Bind<T>(section, key, defaultValue, description);
			string text = Path.Combine(Paths.ConfigPath, "io.zfolmt.SmartConnect.cfg");
			ConfigEntry<T> val2 = default(ConfigEntry<T>);
			if (File.Exists(text) && new ConfigFile(text, true).TryGetEntry<T>(section, key, ref val2))
			{
				val.Value = val2.Value;
			}
			return val;
		}

		public override bool Unload()
		{
			((BasePlugin)this).Config.Clear();
			_harmony.UnpatchSelf();
			return true;
		}

		private static void CreateFile(string file)
		{
			if (!File.Exists(file))
			{
				File.Create(file).Dispose();
			}
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "io.zfolmt.SmartConnect";

		public const string PLUGIN_NAME = "SmartConnect";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace SmartConnect.Patches
{
	[HarmonyPatch]
	internal static class MainMenuNewViewPatches
	{
		private static readonly bool Active = Plugin.Enabled;

		private static readonly bool AutoJoin = Plugin.AutoJoin;

		private static readonly int TimerSeconds = Plugin.TimerSeconds;

		private static readonly bool ShowTimer = Plugin.ShowTimer;

		private static readonly string IPAddress = Plugin.IPAddress;

		private static GameObject timerGameObject;

		private static Image timerObjectImage;

		private static bool consoleReady = false;

		private static bool triggered = false;

		private static DateTime timerStart = DateTime.MinValue;

		private static readonly string ResourcePath = "SmartConnect.Resources.icon.png";

		[HarmonyPostfix]
		[HarmonyPatch(typeof(MainMenuNewView), "SetConsoleReady")]
		private static void ConsoleReadyPostfix()
		{
			if (Active && !triggered)
			{
				consoleReady = true;
				timerStart = DateTime.UtcNow;
			}
		}

		[HarmonyPatch(typeof(MainMenuNewView), "Update")]
		[HarmonyPrefix]
		private static void UpdatePrefix()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Expected O, but got Unknown
			if (!Active || !consoleReady || triggered)
			{
				return;
			}
			if (ShowTimer && (Object)(object)timerGameObject == (Object)null)
			{
				MainMenuCanvasBase val = Object.FindObjectOfType<MainMenuCanvasBase>();
				if ((Object)(object)val != (Object)null)
				{
					GameObject val2 = new GameObject("RadialTimer");
					Object.DontDestroyOnLoad((Object)(object)val2);
					RectTransform val3 = val2.AddComponent<RectTransform>();
					timerGameObject = val2;
					val2.transform.SetParent((Transform)(object)val.MenuParent, false);
					using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ResourcePath);
					Texture2D val4 = LoadBackgroundTextureFromStream(stream);
					Sprite sprite = Sprite.Create(val4, new Rect(0f, 0f, (float)((Texture)val4).width, (float)((Texture)val4).height), new Vector2(0.5f, 0.5f));
					Image obj = (timerObjectImage = val2.AddComponent<Image>());
					obj.sprite = sprite;
					obj.type = (Type)3;
					obj.fillMethod = (FillMethod)4;
					obj.fillClockwise = false;
					obj.fillOrigin = 2;
					obj.fillAmount = 0f;
					((Graphic)obj).color = new Color(1f, 0.3f, 0.3f, 1f);
					val3.sizeDelta = new Vector2((float)(((Texture)val4).width / 2), (float)(((Texture)val4).height / 2));
					val3.anchoredPosition = new Vector2(0f, 0f);
					((Transform)val3).localScale = Vector3.one;
					val2.SetActive(true);
				}
			}
			else if (ShowTimer)
			{
				timerObjectImage.fillAmount = (float)(DateTime.UtcNow - timerStart).TotalSeconds / (float)TimerSeconds;
			}
			if (Input.GetMouseButtonDown(0))
			{
				Plugin.LogInstance.LogInfo((object)"Mouse left-click detected, stopping timer till next restart...");
				triggered = true;
				if (ShowTimer)
				{
					((Graphic)timerObjectImage).color = Color.clear;
				}
			}
			else
			{
				if (!(DateTime.UtcNow - timerStart > TimeSpan.FromSeconds(TimerSeconds)))
				{
					return;
				}
				if ((Object)(object)timerGameObject != (Object)null)
				{
					Object.Destroy((Object)(object)timerGameObject);
				}
				MainMenuNewView val5 = Object.FindObjectOfType<MainMenuNewView>();
				if (!((Object)(object)val5 != (Object)null))
				{
					return;
				}
				triggered = true;
				if (!string.IsNullOrEmpty(IPAddress) && AutoJoin)
				{
					string[] array = IPAddress.Split(':');
					string text = array[0];
					ushort num = ushort.Parse(array[1]);
					ConnectAddress connectAddress = ConnectAddress.CreateSteamIPv4(text, num);
					try
					{
						ServerHistoryEntry val6 = new ServerHistoryEntry
						{
							ConnectAddress = connectAddress
						};
						val5.JoinGame(val6);
						return;
					}
					catch (Exception ex)
					{
						Plugin.LogInstance.LogError((object)("Failed to join server:" + ex));
						return;
					}
				}
				val5.ContinueButton_OnClick();
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(MainMenuNewView), "OnDestroy")]
		private static void OnDestroyPrefix()
		{
			if ((Object)(object)timerGameObject != (Object)null)
			{
				Object.Destroy((Object)(object)timerGameObject);
			}
		}

		private static SaveFileData LoadSessionDataFromFiles(string saveFolderPath, string persistentDataPath, string folderGuid, string saveFileName)
		{
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Expected O, but got Unknown
			try
			{
				string text = Path.Combine(saveFolderPath, "SessionId.json");
				string text2 = Path.Combine(saveFolderPath, "StartDate.json");
				if (File.Exists(text))
				{
					string text3 = File.ReadLines(text).FirstOrDefault();
					if (!string.IsNullOrEmpty(text3))
					{
						SaveFileData.SessionIdFileName = text3;
						Console.WriteLine("SessionIdFileName set to: " + SaveFileData.SessionIdFileName);
						if (File.Exists(text2))
						{
							string text4 = File.ReadLines(text2).FirstOrDefault();
							if (!string.IsNullOrEmpty(text4))
							{
								SaveFileData.StartDateFileName = text4;
								Console.WriteLine("StartDateFileName set to: " + SaveFileData.StartDateFileName);
								return new SaveFileData
								{
									Path = persistentDataPath,
									SessionId = folderGuid,
									Name = saveFileName
								};
							}
							throw new Exception("StartDate.json is empty or could not be read.");
						}
						throw new Exception("StartDate.json not found at path: " + text2);
					}
					throw new Exception("SessionId.json is empty or could not be read.");
				}
				throw new Exception("SessionId.json not found at path: " + text);
			}
			catch (Exception ex)
			{
				Console.WriteLine("Error loading session data: " + ex.Message);
				return null;
			}
		}

		private static int GetAutoSaveNumber(string fileName)
		{
			Match match = Regex.Match(Path.GetFileName(fileName), "AutoSave_(\\d+)\\.save\\.gz");
			if (match.Success)
			{
				return int.Parse(match.Groups[1].Value);
			}
			return 0;
		}

		public static void FindGameObjects(Transform root, bool includeInactive = false)
		{
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			Stack<(Transform, int)> stack = new Stack<(Transform, int)>();
			stack.Push((root, 0));
			HashSet<Transform> hashSet = new HashSet<Transform>();
			Il2CppArrayBase<Transform> componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(includeInactive);
			List<Transform> list = new List<Transform>();
			foreach (Transform item in componentsInChildren)
			{
				list.Add(item);
			}
			List<Transform> list2 = list;
			bool flag = default(bool);
			while (stack.Count > 0)
			{
				var (val, num) = stack.Pop();
				if (!hashSet.Add(val))
				{
					continue;
				}
				List<string> values = FindGameObjectComponents(((Component)val).gameObject);
				string text = new string('|', num);
				ManualLogSource logInstance = Plugin.LogInstance;
				BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(8, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text);
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)((Component)val).gameObject).name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" | ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(string.Join(",", values));
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" | [");
					Scene scene = ((Component)val).gameObject.scene;
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Scene)(ref scene)).name);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("]");
				}
				logInstance.LogInfo(val2);
				foreach (Transform item2 in list2)
				{
					if ((Object)(object)item2.parent == (Object)(object)val)
					{
						stack.Push((item2, num + 1));
					}
				}
			}
		}

		public static List<string> FindGameObjectComponents(GameObject parentObject)
		{
			List<string> list = new List<string>();
			int componentCount = parentObject.GetComponentCount();
			for (int i = 0; i < componentCount; i++)
			{
				list.Add($"{((Object)parentObject.GetComponentAtIndex(i)).GetIl2CppType().FullName}({i})");
			}
			return list;
		}

		public static Texture2D LoadBackgroundTextureFromStream(Stream stream)
		{
			//IL_001d: 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_002e: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			byte[] array = new byte[stream.Length];
			stream.Read(array, 0, array.Length);
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			ImageConversion.LoadImage(val, Il2CppStructArray<byte>.op_Implicit(array));
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			return val;
		}
	}
}