Decompiled source of HistoryFix v1.0.0

HistoryFix.dll

Decompiled 2 months 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.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.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[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 Local.Fix.History
{
	[BepInPlugin("local.fix.history", "HistoryFix", "1.0.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 versionNumber = "1.0.0";

		private static ConfigEntry<uint> historyLimit;

		private static ConfigEntry<bool> backupProfile;

		private static readonly List<Guid> deleted = new List<Guid>();

		public 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_004b: 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)
			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));
				for (int num = list.Count; num >= historyLimit.Value; num--)
				{
					HistoryFileInfo val = list[num - 1];
					((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 <= 1073741823 && value2 != 0)
			{
				value = (int)(historyLimit.Value + 35);
			}
			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> FixEclipseTracking(IEnumerable<CodeInstruction> codeInstructions)
		{
			MethodInfo getType = typeof(object).GetMethod("GetType");
			foreach (CodeInstruction instruction in codeInstructions)
			{
				yield return instruction;
				if (CodeInstructionExtensions.Calls(instruction, getType))
				{
					yield return Transpilers.EmitDelegate<Func<Type, Type>>((Func<Type, Type>)((Type type) => (!(type == typeof(EclipseRun))) ? type : typeof(Run)));
				}
			}
		}

		[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_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: 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 equipment in inventoryEquipment.equipments)
			{
				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);
				}))
				{
					ItemIcon component = Object.Instantiate<GameObject>(__instance.itemIconPrefab, ((Component)__instance).transform).GetComponent<ItemIcon>();
					__instance.itemIcons.Add(component);
					__instance.LayoutIndividualIcon(ref val, __instance.itemIcons.Count - 1);
					component.image.texture = equipment.pickupIconTexture;
					((Behaviour)component.stackText).enabled = false;
					TooltipProvider tooltipProvider = component.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;
					}
				}
			}
			__instance.OnIconCountChanged();
		}

		[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;
				IFileSystem storage = MorgueManager.storage;
				UPath val = MorgueManager.historyDirectory / UPath.op_Implicit(runGuid.ToString());
				storage.DeleteFile(UPath.op_Implicit(((object)(UPath)(ref val)).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 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)(ref enumerator)).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;
		}
	}
}