Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of HistoryFix v1.2.0
HistoryFix.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using HG; using HarmonyLib; using Microsoft.CodeAnalysis; using RoR2; using RoR2.Achievements; using RoR2.Stats; using RoR2.UI; using RoR2.UI.LogBook; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.UI; using Zio; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.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 Local.Fix.History { [BepInPlugin("local.fix.history", "HistoryFix", "1.2.0")] public class Plugin : BaseUnityPlugin { private class InventoryEquipment : MonoBehaviour { internal readonly List<EquipmentDef> equipments = new List<EquipmentDef>(); } private class Report : MonoBehaviour { internal RunReport entry; } public const string identifier = "local.fix.history"; public const string version = "1.2.0"; private static ConfigEntry<uint> historyLimit; private static ConfigEntry<bool> backupProfile; private static readonly List<Guid> deleted = new List<Guid>(); protected void Awake() { historyLimit = ((BaseUnityPlugin)this).Config.Bind<uint>("General", "History Limit", 60u, "Maximum number of run reports. Set to zero for unlimited entries."); backupProfile = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Profile Backup", false, "Enable monthly backup of player information on Steam platform."); Harmony.CreateAndPatchAll(typeof(Plugin), (string)null); } [HarmonyPatch(typeof(MorgueManager), "EnforceHistoryLimit")] [HarmonyPrefix] private static bool FixHistoryLimit() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if (historyLimit.Value != 0) { List<HistoryFileInfo> list = CollectionPool<HistoryFileInfo, List<HistoryFileInfo>>.RentCollection(); MorgueManager.GetHistoryFiles(list); list.Sort((HistoryFileInfo a, HistoryFileInfo b) => b.lastModified.CompareTo(a.lastModified)); int num = list.Count; while (num >= historyLimit.Value) { HistoryFileInfo val = list[--num]; ((HistoryFileInfo)(ref val)).Delete(); } CollectionPool<HistoryFileInfo, List<HistoryFileInfo>>.ReturnCollection(list); } return false; } [HarmonyPatch(typeof(Console), "SaveArchiveConVars")] [HarmonyPrefix] private static void PreserveHistory() { int value = int.MaxValue; uint value2 = historyLimit.Value; if (value2 <= int.MaxValue && value2 != 0) { value = (int)(historyLimit.Value - 1); } MorgueManager.morgueHistoryLimit.value = value; } [HarmonyPatch(typeof(StatManager), "OnServerGameOver")] [HarmonyPatch(typeof(CompleteThreeStagesAchievement), "Check")] [HarmonyPatch(typeof(CompleteThreeStagesWithoutHealingServerAchievement), "Check")] [HarmonyPatch(typeof(LoopOnceAchievement), "Check")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> FixTypeForEclipse(IEnumerable<CodeInstruction> IL) { MethodInfo method = typeof(object).GetMethod("GetType"); foreach (CodeInstruction instruction in IL) { yield return instruction; if (CodeInstructionExtensions.Calls(instruction, method)) { yield return Transpilers.EmitDelegate<Func<Type, Type>>((Func<Type, Type>)((Type type) => (!(type == typeof(EclipseRun))) ? type : typeof(Run))); } } } [HarmonyPatch(typeof(ItemIcon), "Awake")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> FixForUserProfile(IEnumerable<CodeInstruction> IL, ILGenerator generator) { Label label = generator.DefineLabel(); MethodInfo method = typeof(HUD).GetProperty("localUserViewer").GetMethod; FieldInfo field = typeof(ItemIcon).GetField("userProfile", AccessTools.all); foreach (CodeInstruction instruction in IL) { if (CodeInstructionExtensions.Calls(instruction, method)) { yield return new CodeInstruction(OpCodes.Dup, (object)null); yield return new CodeInstruction(OpCodes.Brfalse, (object)label); } else if (CodeInstructionExtensions.StoresField(instruction, field)) { instruction.labels.Add(label); } yield return instruction; } } [HarmonyPatch(typeof(SaveSystemSteam), "WriteToDisk")] [HarmonyPostfix] private static void SaveProfile(FileOutput fileOutput) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) UPath path = fileOutput.fileReference.path; if (!backupProfile.Value) { return; } string text = DateTime.Now.ToString("yyyy-MM"); path = UPathExtensions.GetDirectory(path) / UPath.op_Implicit("History") / UPath.op_Implicit(text) / UPath.op_Implicit(UPathExtensions.GetName(path)); IFileSystem fileSystem = fileOutput.fileReference.fileSystem; byte[] contents = fileOutput.contents; if (fileSystem.FileExists(path)) { return; } using Stream stream = fileSystem.OpenFile(path, FileMode.Create, FileAccess.Write, FileShare.None); stream.Write(contents, 0, contents.Length); } [HarmonyPatch(typeof(GameEndReportPanelController), "SetPlayerInfo")] [HarmonyPrefix] private static void GetEquipment(GameEndReportPanelController __instance, PlayerInfo playerInfo) { ItemInventoryDisplay itemInventoryDisplay = __instance.itemInventoryDisplay; if (!Object.op_Implicit((Object)(object)itemInventoryDisplay)) { return; } InventoryEquipment inventoryEquipment = ((Component)itemInventoryDisplay).gameObject.GetComponent<InventoryEquipment>(); if (Object.op_Implicit((Object)(object)inventoryEquipment)) { inventoryEquipment.equipments.Clear(); } else { inventoryEquipment = ((Component)itemInventoryDisplay).gameObject.AddComponent<InventoryEquipment>(); } EquipmentIndex[] equipment = playerInfo.equipment; for (int i = 0; i < equipment.Length; i++) { EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(equipment[i]); if ((Object)(object)equipmentDef != (Object)null) { inventoryEquipment.equipments.Add(equipmentDef); } } } [HarmonyPatch(typeof(ItemInventoryDisplay), "UpdateDisplay")] [HarmonyPostfix] private static void AddEquipment(ItemInventoryDisplay __instance) { //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) InventoryEquipment inventoryEquipment = default(InventoryEquipment); if (!Object.op_Implicit((Object)(object)__instance) || !((Component)__instance).TryGetComponent<InventoryEquipment>(ref inventoryEquipment)) { return; } LayoutValues val = default(LayoutValues); __instance.CalculateLayoutValues(ref val, __instance.itemIcons.Count + inventoryEquipment.equipments.Count); foreach (EquipmentDef equipment2 in inventoryEquipment.equipments) { EquipmentDef equipment = equipment2; ItemIcon icon; if (!__instance.itemIcons.Any(delegate(ItemIcon item) { Texture pickupIconTexture = equipment.pickupIconTexture; RawImage image = item.image; return (Object)(object)pickupIconTexture == (Object)(object)((image != null) ? image.texture : null); })) { icon = Object.Instantiate<GameObject>(__instance.itemIconPrefab, ((Component)__instance).transform).GetComponent<ItemIcon>(); __instance.itemIcons.Add(icon); __instance.LayoutIndividualIcon(ref val, __instance.itemIcons.Count - 1); icon.image.texture = equipment.pickupIconTexture; ((Behaviour)icon.stackText).enabled = false; update(dlc); update(dlc4); TooltipProvider tooltipProvider = icon.tooltipProvider; tooltipProvider.titleToken = equipment.nameToken; tooltipProvider.bodyToken = equipment.pickupToken; tooltipProvider.titleColor = Color32.op_Implicit(ColorCatalog.GetColor(equipment.colorIndex)); ItemIcon val2 = __instance.itemIcons.First(); if (val2.tooltipProvider?.bodyToken == ItemCatalog.GetItemDef(val2.itemIndex)?.descriptionToken) { tooltipProvider.bodyToken = equipment.descriptionToken; } } [MethodImpl(MethodImplOptions.NoInlining)] void dlc() { ((Behaviour)icon.durationImage).enabled = false; } [MethodImpl(MethodImplOptions.NoInlining)] void dlc4() { icon.asyncRawImage.SetAssetOrDirectReference(equipment.pickupIconSpriteReference, equipment.pickupIconSprite); ((Behaviour)icon.rentalImage).enabled = false; ((Behaviour)icon.disabledImage).enabled = false; } } __instance.OnIconCountChanged(); static void update(Action patch) { try { patch(); } catch (Exception ex) when (((ex is MissingFieldException || ex is TypeLoadException) ? 1 : 0) != 0) { Debug.LogException(ex); } } } [HarmonyPatch(typeof(CategoryDef), "InitializeMorgue")] [HarmonyPostfix] private static void LoadReport(GameObject gameObject, Entry entry) { Button component = gameObject.GetComponent<Button>(); if (!((Object)(object)component != (Object)null)) { return; } object obj = entry?.extraData; RunReport val = (RunReport)((obj is RunReport) ? obj : null); if (val != null) { ((Component)component).gameObject.AddComponent<Report>().entry = val; if (deleted.Contains(val.runGuid)) { RemoveButton(component); } } } [HarmonyPatch(typeof(MPButton), "OnPointerClick")] [HarmonyPostfix] private static void OnClick(Button __instance, PointerEventData eventData) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Invalid comparison between Unknown and I4 //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown Report component = default(Report); if ((int)eventData.button == 1 && ((Component)__instance).TryGetComponent<Report>(ref component)) { SimpleDialogBox obj = SimpleDialogBox.Create((MPEventSystem)null); obj.headerToken = new TokenParamsPair("Delete History Entry", Array.Empty<object>()); obj.descriptionToken = new TokenParamsPair("Are you sure you want to permanently delete the selected run report?", Array.Empty<object>()); obj.AddActionButton(new UnityAction(deleteEntry), "DIALOG_OPTION_YES", true, Array.Empty<object>()); obj.AddCancelButton("CANCEL", Array.Empty<object>()); } void deleteEntry() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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) Guid runGuid = component.entry.runGuid; MorgueManager.storage.DeleteFile(UPath.op_Implicit(((object)(MorgueManager.historyDirectory / UPath.op_Implicit(runGuid.ToString()))/*cast due to .constrained prefix*/).ToString() + ".xml")); deleted.Add(runGuid); RemoveButton(__instance); } } private static void RemoveButton(Button button) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) ((Behaviour)button).enabled = false; CollectionExtensions.Do<Image>((IEnumerable<Image>)((Component)button).GetComponentsInChildren<Image>(), (Action<Image>)delegate(Image image) { ((Behaviour)image).enabled = false; }); Color grey = Color.grey; Color filter = ((Color)(ref grey)).AlphaMultiplied(0.5f); CollectionExtensions.Do<HGTextMeshProUGUI>((IEnumerable<HGTextMeshProUGUI>)((Component)button).GetComponentsInChildren<HGTextMeshProUGUI>(), (Action<HGTextMeshProUGUI>)delegate(HGTextMeshProUGUI text) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //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) ((Graphic)text).color = ((Graphic)text).color * filter; }); CollectionExtensions.Do<RawImage>((IEnumerable<RawImage>)((Component)button).GetComponentsInChildren<RawImage>(), (Action<RawImage>)delegate(RawImage icon) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //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) ((Graphic)icon).color = ((Graphic)icon).color * filter; }); } [HarmonyPatch(typeof(HGButton), "OnPointerEnter")] [HarmonyPostfix] private static void UpdateTooltip(HGButton __instance) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) LanguageTextMeshController hoverLanguageTextMeshController = __instance.hoverLanguageTextMeshController; Report report = default(Report); if (!((Object)(object)hoverLanguageTextMeshController == (Object)null) && ((Component)__instance).TryGetComponent<Report>(ref report)) { RunReport entry = report.entry; PlayerInfo val = entry.FindFirstPlayerInfo(); StatSheet statSheet = val.statSheet; DifficultyDef difficultyDef = DifficultyCatalog.GetDifficultyDef(entry.ruleBook.FindDifficulty()); hoverLanguageTextMeshController.token = RemoveSymbols(hoverLanguageTextMeshController.token, Language.GetString("VOIDSURVIVOR_BODY_NAME")) + "\n<style=cSub>" + Language.GetString("LOBBY_CONTROL_PANEL_NAME") + ": " + Language.GetString((entry.playerInfoCount > 1) ? "TITLE_MULTIPLAYER" : "TITLE_SINGLEPLAYER") + "\n" + Language.GetString("RULE_HEADER_DIFFICULTY") + ": " + Language.GetString(difficultyDef.nameToken) + "\n" + Language.GetString("RULE_HEADER_ARTIFACTS") + ": " + GetArtifact(entry.ruleBook) + "\n" + Language.GetString("STATNAME_TOTALTIMEALIVE") + ": " + statSheet.GetStatDisplayValue(StatDef.totalTimeAlive) + "\n" + Language.GetString("STATNAME_TOTALITEMSCOLLECTED").Split().First() + $": {GetItemCount(val)}\n" + Language.GetString("STATNAME_TOTALSTAGESCOMPLETED") + $": {statSheet.GetStatValueULong(StatDef.totalStagesCompleted)}\n" + "</style>\n<style=cStack><i>Right-click to delete...</i></style>"; } } private static string RemoveSymbols(string source, string substring) { char[] value = substring.Where((char character) => char.IsLetter(character) || char.IsSeparator(character)).ToArray(); return source.Replace(substring, new string(value)); } private unsafe static string GetArtifact(RuleBook ruleBook) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) string text = null; ChoicesEnumerable choices = ruleBook.choices; Enumerator enumerator = ((ChoicesEnumerable)(ref choices)).GetEnumerator(); try { while (((Enumerator)(ref enumerator)).MoveNext()) { RuleChoiceDef current = ((Enumerator)(ref enumerator)).Current; if ((int)current.artifactIndex != -1 && current.localIndex == ruleBook.GetRuleChoiceIndex(current.ruleDef)) { if (text != null) { text = current.localName; break; } text = ArtifactCatalog.GetArtifactDef(current.artifactIndex)?.nameToken; if (text != null) { text = Language.GetString(text).Trim().Split() .Last(); } } } } finally { ((IDisposable)(*(Enumerator*)(&enumerator))/*cast due to .constrained prefix*/).Dispose(); } return text ?? Language.GetString("OPTION_OFF"); } private static int GetItemCount(PlayerInfo player) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 int num = 0; for (int i = 0; i < player.itemStacks.Length; i++) { ItemDef itemDef = ItemCatalog.GetItemDef((ItemIndex)i); if (Object.op_Implicit((Object)(object)itemDef) && !itemDef.hidden && (int)itemDef.tier != 5) { num += player.itemStacks[i]; } } return num; } } }