Decompiled source of Personal Leaderboard v0.0.3

PersonalLeaderboard.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Assets.Scripts.Utility;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using Newtonsoft.Json;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("PersonalLeaderboard")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PersonalLeaderboard")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("a052f8b9-b678-40b0-a576-d1c5418579fb")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SaveLoadWeapons
{
	[BepInPlugin("mike9k1.megabonk.personalleaderboard", "Personal Leaderboard", "0.0.3")]
	public class PersonalLeaderboard : MelonMod
	{
		public new const string PLUGIN_GUID = "mike9k1.megabonk.personalleaderboard";

		public new const string PLUGIN_NAME = "Personal Leaderboard";

		public new const string PLUGIN_VERSION = "0.0.3";

		public static string savesDirectory = "BepInEx\\plugins\\PersonalLeaderboard\\";

		private string RefreshTypeName = "PlayerInventory";

		private string RefreshMethodName = "Update";

		private string RecordTypeName = "Assets.Scripts.Saves___Serialization.Progression.MapProgress";

		private string KillsMethodName = "SetKills";

		private string CharMethodName = "OnRunFinished";

		private string LeaderboardTypeName = "LeaderboardUiNew";

		private string LeaderboardMethodName = "Refresh";

		private static bool charSet = false;

		private static bool killsSet = false;

		private static ECharacter lastPlayedCharacter;

		private static int lastNumKills;

		private static Dictionary<ECharacter, int> recordedHighScores;

		private static LeaderboardUiNew leaderboardDisplay;

		private static MyButtonTabs personalLeaderboardButton;

		private static MethodInfo jsonSerializeMethod = null;

		private static bool KillsPrefix(int kills)
		{
			lastNumKills = kills;
			charSet = true;
			if (charSet && killsSet)
			{
				SaveHighScores();
				charSet = false;
				killsSet = false;
			}
			return true;
		}

		private static bool CharPrefix(ECharacter character, bool victory, int tier)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			lastPlayedCharacter = character;
			killsSet = true;
			if (charSet && killsSet)
			{
				SaveHighScores();
				charSet = false;
				killsSet = false;
			}
			return true;
		}

		private static void SaveHighScores()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			if (!recordedHighScores.ContainsKey(lastPlayedCharacter))
			{
				recordedHighScores.Add(lastPlayedCharacter, lastNumKills);
			}
			else
			{
				if (recordedHighScores[lastPlayedCharacter] >= lastNumKills)
				{
					return;
				}
				recordedHighScores[lastPlayedCharacter] = lastNumKills;
			}
			Dictionary<ECharacter, int> val = new Dictionary<ECharacter, int>();
			foreach (KeyValuePair<ECharacter, int> recordedHighScore in recordedHighScores)
			{
				val.Add(recordedHighScore.Key, recordedHighScore.Value);
			}
			string text = "";
			Type.GetType("Il2CppSystem.Object");
			Type type = Type.GetType("Newtonsoft.Json.JsonConvert, Newtonsoft.Json");
			if (jsonSerializeMethod == null)
			{
				try
				{
					MethodInfo[] methods = type.GetMethods();
					foreach (MethodInfo methodInfo in methods)
					{
						if (methodInfo.Name == "SerializeObject")
						{
							ParameterInfo[] parameters = methodInfo.GetParameters();
							if (parameters.Length == 1 && parameters[0].ParameterType.FullName == "Il2CppSystem.Object")
							{
								jsonSerializeMethod = methodInfo;
								break;
							}
						}
					}
				}
				catch (Exception)
				{
					MelonLogger.Msg("Null ref at method parameters");
				}
			}
			if (jsonSerializeMethod != null)
			{
				MelonLogger.Msg("Built-in Newtonsoft JSON being used. Using il2cpp method call");
				text = type.GetMethod("SerializeObject", new Type[2]
				{
					typeof(Object),
					typeof(Formatting)
				}).Invoke(null, new object[2]
				{
					val,
					(object)(Formatting)1
				}).ToString();
				MelonLogger.Msg("New high score saved!");
			}
			else
			{
				MelonLogger.Msg("Full Newtonsoft JSON being used. Using windows method call");
				text = type.GetMethod("SerializeObject", new Type[2]
				{
					typeof(object),
					typeof(Formatting)
				}).Invoke(null, new object[2]
				{
					recordedHighScores,
					(object)(Formatting)1
				}).ToString();
				MelonLogger.Msg("New high score saved!");
			}
			Directory.CreateDirectory(savesDirectory);
			File.WriteAllText(savesDirectory + "highscores.json", text);
		}

		private static void LeaderboardPostfix(LeaderboardUiNew __instance)
		{
			leaderboardDisplay = __instance;
			GameObject[] array = Il2CppArrayBase<GameObject>.op_Implicit(Object.FindObjectsOfType<GameObject>(true));
			foreach (GameObject val in array)
			{
				if (((Object)val).name == "B_Effects" && val.transform.IsChildOf(((Component)__instance.leaderboardTypeButtons).transform))
				{
					MyButtonTabs component = val.GetComponent<MyButtonTabs>();
					((TMP_Text)((Component)component.text).GetComponent<TextMeshProUGUI>()).m_text = "Personal";
					((UnityEvent)((Component)component).GetComponent<Button>().onClick).AddListener(UnityAction.op_Implicit((Action)OnPersonalLeaderboardClick));
					personalLeaderboardButton = component;
					val.SetActive(true);
					break;
				}
			}
		}

		public static void OnPersonalLeaderboardClick()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			List<KeyValuePair<ECharacter, int>> list = new List<KeyValuePair<ECharacter, int>>();
			for (int i = 0; i < 10; i++)
			{
				int num = 0;
				ECharacter key = (ECharacter)0;
				foreach (KeyValuePair<ECharacter, int> recordedHighScore in recordedHighScores)
				{
					if (recordedHighScore.Value > num && !list.Contains(recordedHighScore))
					{
						num = recordedHighScore.Value;
						key = recordedHighScore.Key;
					}
				}
				if (num > 0)
				{
					KeyValuePair<ECharacter, int> item = new KeyValuePair<ECharacter, int>(key, num);
					list.Add(item);
				}
			}
			DataManager val = Object.FindFirstObjectByType<DataManager>();
			int j = 0;
			foreach (KeyValuePair<ECharacter, int> item2 in list)
			{
				new LeaderboardEntryUi();
				TextMeshProUGUI playerName = leaderboardDisplay.leaderboardEntries[j].playerName;
				ECharacter key2 = item2.Key;
				((TMP_Text)playerName).SetText(((object)(ECharacter)(ref key2)).ToString());
				TextMeshProUGUI playerName2 = leaderboardDisplay.leaderboardEntries[j].playerName;
				key2 = item2.Key;
				((TMP_Text)playerName2).m_text = ((object)(ECharacter)(ref key2)).ToString();
				((TMP_Text)leaderboardDisplay.leaderboardEntries[j].score).SetText(item2.Value.ToString());
				leaderboardDisplay.leaderboardEntries[j].characterIcon.texture = val.GetCharacterData(item2.Key).icon;
				leaderboardDisplay.leaderboardEntries[j].playerIcon.texture = val.GetCharacterData(item2.Key).icon;
				j++;
				if (j >= 10)
				{
					break;
				}
			}
			for (; j < 10; j++)
			{
				leaderboardDisplay.leaderboardEntries[j].Clear();
			}
			MyButtonTabs[] array = (MyButtonTabs[])(object)new MyButtonTabs[3];
			Array.Copy(Il2CppArrayBase<MyButtonTabs>.op_Implicit((Il2CppArrayBase<MyButtonTabs>)(object)leaderboardDisplay.leaderboardTypeButtons.buttons), array, 2);
			array[2] = personalLeaderboardButton;
			leaderboardDisplay.leaderboardTypeButtons.buttons = Il2CppReferenceArray<MyButtonTabs>.op_Implicit(array);
			leaderboardDisplay.leaderboardTypeButtons.ButtonPressed(2, false);
		}

		private static void LoadHighScores()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			recordedHighScores = new Dictionary<ECharacter, int>();
			new Dictionary<ECharacter, int>();
			if (File.Exists(savesDirectory + "highscores.json"))
			{
				string text = File.ReadAllText(savesDirectory + "highscores.json");
				Dictionary<ECharacter, int> obj = JsonConvert.DeserializeObject<Dictionary<ECharacter, int>>(text);
				if (obj.Count == 0)
				{
					recordedHighScores = JsonConvert.DeserializeObject<Dictionary<ECharacter, int>>(text);
				}
				Enumerator<ECharacter, int> enumerator = obj.GetEnumerator();
				while (enumerator.MoveNext())
				{
					KeyValuePair<ECharacter, int> current = enumerator.Current;
					recordedHighScores.Add(current.Key, current.Value);
				}
			}
		}

		private static Type FindType(string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					Type type = assembly.GetType(fullName, throwOnError: false);
					if (type != null)
					{
						return type;
					}
				}
				catch
				{
				}
			}
			return null;
		}

		private void TryPatch()
		{
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Expected O, but got Unknown
			Type type = FindType(RecordTypeName);
			if (type == null)
			{
				MelonLogger.Error("Type not found: " + RecordTypeName);
				return;
			}
			MethodInfo method = type.GetMethod(KillsMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method == null)
			{
				MelonLogger.Error("Method not found: " + type.FullName + "." + KillsMethodName + "()");
				return;
			}
			HarmonyMethod val = new HarmonyMethod(typeof(PersonalLeaderboard).GetMethod("KillsPrefix", BindingFlags.Static | BindingFlags.NonPublic));
			HarmonyInstance.Patch((MethodBase)method, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			MethodInfo method2 = type.GetMethod(CharMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method2 == null)
			{
				MelonLogger.Error("Method not found: " + type.FullName + "." + CharMethodName + "()");
				return;
			}
			HarmonyMethod val2 = new HarmonyMethod(typeof(PersonalLeaderboard).GetMethod("CharPrefix", BindingFlags.Static | BindingFlags.NonPublic));
			HarmonyInstance.Patch((MethodBase)method2, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Type type2 = FindType(LeaderboardTypeName);
			if (type2 == null)
			{
				MelonLogger.Error("Type not found: " + LeaderboardTypeName);
				return;
			}
			MethodInfo method3 = type2.GetMethod(LeaderboardMethodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method3 == null)
			{
				MelonLogger.Error("Method not found: " + type2.FullName + "." + LeaderboardMethodName + "()");
			}
			else
			{
				HarmonyMethod val3 = new HarmonyMethod(typeof(PersonalLeaderboard).GetMethod("LeaderboardPostfix", BindingFlags.Static | BindingFlags.NonPublic));
				HarmonyInstance.Patch((MethodBase)method3, (HarmonyMethod)null, val3, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				LoadHighScores();
			}
		}

		public override void OnInitializeMelon()
		{
			TryPatch();
		}
	}
}
namespace MelonLoader
{
	public class MelonMod : BasePlugin
	{
		public Harmony HarmonyInstance;

		public static MelonMod melonModRef;

		public virtual string PLUGIN_GUID => "author.game.modname";

		public virtual string PLUGIN_NAME => "Mod Name Here";

		public virtual string PLUGIN_VERSION => "0.0.1";

		public MelonMod()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			HarmonyInstance = new Harmony(PLUGIN_GUID);
			melonModRef = this;
		}

		public virtual void OnInitializeMelon()
		{
		}

		public virtual void OnLateInitializeMelon()
		{
		}

		public virtual void OnFixedUpdate()
		{
		}

		public virtual void OnUpdate()
		{
		}

		public override void Load()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			OnInitializeMelon();
			HarmonyMethod val = new HarmonyMethod(typeof(MelonMod).GetMethod("FixedUpdate"));
			HarmonyInstance.Patch((MethodBase)typeof(MyTime).GetMethod("FixedUpdate"), (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			HarmonyMethod val2 = new HarmonyMethod(typeof(MelonMod).GetMethod("Update"));
			HarmonyInstance.Patch((MethodBase)typeof(MyTime).GetMethod("Update"), (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		}

		public void Awake()
		{
			OnLateInitializeMelon();
		}

		public static void FixedUpdate()
		{
			melonModRef.OnFixedUpdate();
		}

		public static void Update()
		{
			melonModRef.OnUpdate();
		}
	}
	public class MelonLogger
	{
		private static ManualLogSource log;

		private static bool logAdded;

		public static void Msg(string message)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if (!logAdded)
			{
				log = new ManualLogSource(((AssemblyTitleAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), inherit: false)[0]).Title);
				Logger.Sources.Add((ILogSource)(object)log);
				logAdded = true;
			}
			log.LogInfo((object)message);
		}

		public static void Error(string message)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if (!logAdded)
			{
				log = new ManualLogSource(((AssemblyTitleAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), inherit: false)[0]).Title);
				Logger.Sources.Add((ILogSource)(object)log);
				logAdded = true;
			}
			log.LogError((object)message);
		}
	}
}