Decompiled source of ToolRefund v1.0.0

plugins/ToolRefund/ToolRefund.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using GlobalSettings;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Esper89")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b6f402d359f2eeb99b4de87a8fa69982eaf803ea")]
[assembly: AssemblyProduct("Esper89.ToolRefund")]
[assembly: AssemblyTitle("Tool Refund")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/Esper89/Silksong-ToolRefund")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace ToolRefund
{
	[BepInPlugin("Esper89.ToolRefund", "Tool Refund", "1.0.0")]
	internal sealed class Mod : BaseUnityPlugin
	{
		private sealed class ConfigEntries
		{
			private ConfigEntry<bool> _enabled = file.Bind<bool>("General", "Enabled", true, "Enable tool refund on death");

			internal bool Enabled => _enabled.Value;

			public ConfigEntries(ConfigFile file)
			{
			}
		}

		[HarmonyPatch(typeof(GameManager), "SaveGame", new Type[]
		{
			typeof(int),
			typeof(Action<bool>),
			typeof(bool),
			typeof(AutoSaveName)
		})]
		private static class OnSave
		{
			private static void Postfix()
			{
				Instance.CaptureRestoreState();
			}
		}

		[HarmonyPatch(typeof(GameManager), "LoadGame")]
		private static class OnLoad
		{
			private static void Postfix()
			{
				Instance.CaptureRestoreState();
			}
		}

		[HarmonyPatch(typeof(HeroController), "Die")]
		private static class OnDeath
		{
			private static void Prefix()
			{
				Instance.playerDying = true;
				Instance.RestoreRosariesEarly();
			}
		}

		[HarmonyPatch(typeof(HeroController), "Respawn")]
		private static class OnRespawn
		{
			private static void Postfix()
			{
				Instance.RestoreTools();
				Instance.playerDying = false;
			}
		}

		[HarmonyPatch(typeof(ToolItemManager), "TryReplenishTools")]
		private static class OnToolReplenish
		{
			private static void Prefix(ReplenishMethod method, ref ToolResourcesTotal __state)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Invalid comparison between Unknown and I4
				if ((int)method == 1)
				{
					__state = new ToolResourcesTotal();
					__state.Capture();
				}
			}

			private static void Postfix(ReplenishMethod method, ToolResourcesTotal __state)
			{
				//IL_0000: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Expected I4, but got Unknown
				switch ((int)method)
				{
				case 0:
				case 2:
					Instance.CaptureRestoreState();
					break;
				case 1:
				{
					ToolResourcesTotal toolResourcesTotal = new ToolResourcesTotal();
					toolResourcesTotal.Capture();
					__state.Subtract(toolResourcesTotal);
					Instance.CaptureResourcesSpent(__state);
					break;
				}
				}
			}
		}

		private static Mod? _instance;

		private ConfigEntries? _config;

		private bool playerDying;

		private ToolRestoreState restoreState = new ToolRestoreState();

		private ToolResourcesTotal resourcesTotal = new ToolResourcesTotal();

		public const string Id = "Esper89.ToolRefund";

		private static Mod Instance
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)_instance))
				{
					throw new NullReferenceException("Mod accessed before Awake");
				}
				return _instance;
			}
		}

		private ConfigEntries Config => _config;

		public static string Name => "Tool Refund";

		public static string Version => "1.0.0";

		private void Awake()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			_instance = this;
			_config = new ConfigEntries(((BaseUnityPlugin)this).Config);
			new Harmony("Esper89.ToolRefund").PatchAll();
		}

		private void LogDebug(object msg)
		{
			((BaseUnityPlugin)this).Logger.LogDebug(msg);
		}

		private void LogInfo(object msg)
		{
			((BaseUnityPlugin)this).Logger.LogInfo(msg);
		}

		private void LogMessage(object msg)
		{
			((BaseUnityPlugin)this).Logger.LogMessage(msg);
		}

		private void LogWarning(object msg)
		{
			((BaseUnityPlugin)this).Logger.LogWarning(msg);
		}

		private void LogError(object msg)
		{
			((BaseUnityPlugin)this).Logger.LogError(msg);
		}

		private void LogFatal(object msg)
		{
			((BaseUnityPlugin)this).Logger.LogFatal(msg);
		}

		private void CaptureRestoreState()
		{
			if (!playerDying)
			{
				restoreState.Capture();
				LogDebug($"captured restore state: {restoreState}");
				resourcesTotal.Clear();
			}
		}

		private void CaptureResourcesSpent(ToolResourcesTotal spent)
		{
			resourcesTotal.Add(spent);
			LogDebug($"captured resources spent: {spent}");
		}

		private void RestoreRosariesEarly()
		{
			if (Config.Enabled)
			{
				resourcesTotal.RestoreRosaries();
				LogDebug($"restored tool rosaries: {resourcesTotal.Rosaries}");
				resourcesTotal.ClearRosaries();
			}
		}

		private void RestoreTools()
		{
			if (Config.Enabled)
			{
				restoreState.Restore();
				LogDebug($"restored tool state: {restoreState}");
				resourcesTotal.Restore();
				LogDebug($"restored tool resources: {resourcesTotal}");
				resourcesTotal.Clear();
			}
		}
	}
	internal class ToolRestoreState
	{
		private Dictionary<ToolItem, int> toolAmounts = new Dictionary<ToolItem, int>();

		public void Capture()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			Clear();
			if (!PlayerData.HasInstance)
			{
				return;
			}
			PlayerData instance = PlayerData.instance;
			foreach (ToolItem allTool in ToolItemManager.GetAllTools())
			{
				if (!((Object)(object)allTool == (Object)null))
				{
					int amountLeft = instance.GetToolData(allTool.name).AmountLeft;
					if (amountLeft != 0)
					{
						toolAmounts[allTool] = amountLeft;
					}
				}
			}
		}

		public void Restore()
		{
			//IL_004e: 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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			if (!PlayerData.HasInstance)
			{
				return;
			}
			PlayerData instance = PlayerData.instance;
			foreach (var (val2, value) in toolAmounts)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					int toolStorageAmount = ToolItemManager.GetToolStorageAmount(val2);
					Data toolData = instance.GetToolData(val2.name);
					int amountLeft = toolData.AmountLeft;
					int num2 = Math.Clamp(value, amountLeft, toolStorageAmount);
					if (num2 != amountLeft)
					{
						toolData.AmountLeft = num2;
						instance.SetToolData(val2.name, toolData);
					}
				}
			}
			ToolItemManager.ReportAllBoundAttackToolsUpdated();
			ToolItemManager.SendEquippedChangedEvent(true);
		}

		public void Clear()
		{
			toolAmounts.Clear();
		}

		public override string ToString()
		{
			IEnumerable<string> values = toolAmounts.Select<KeyValuePair<ToolItem, int>, string>((KeyValuePair<ToolItem, int> kvp) => kvp.Key.name + ": " + kvp.Value);
			return "{ " + string.Join(", ", values) + " }";
		}
	}
	internal class ToolResourcesTotal
	{
		private int rosaries;

		private int shellShards;

		private Dictionary<ToolItemStatesLiquid, int> liquidRefills = new Dictionary<ToolItemStatesLiquid, int>();

		public int Rosaries => rosaries;

		public void Capture()
		{
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			Clear();
			if (!PlayerData.HasInstance)
			{
				return;
			}
			PlayerData instance = PlayerData.instance;
			List<CurrencyQueue> currencyQueue = CurrencyManager.currencyQueue;
			rosaries = instance.geo + currencyQueue[0].amount;
			shellShards = instance.ShellShards + currencyQueue[1].amount;
			foreach (ToolItem allTool in ToolItemManager.GetAllTools())
			{
				ToolItemStatesLiquid val = (ToolItemStatesLiquid)(object)((allTool is ToolItemStatesLiquid) ? allTool : null);
				if (val != null)
				{
					int refillsLeft = val.LiquidSavedData.RefillsLeft;
					liquidRefills[val] = refillsLeft;
				}
			}
		}

		public void Subtract(ToolResourcesTotal later)
		{
			rosaries -= later.rosaries;
			shellShards -= later.shellShards;
			foreach (KeyValuePair<ToolItemStatesLiquid, int> liquidRefill in later.liquidRefills)
			{
				liquidRefill.Deconstruct(out var key, out var value);
				ToolItemStatesLiquid val = key;
				int num = value;
				if (!liquidRefills.ContainsKey(val))
				{
					liquidRefills[val] = 0;
				}
				Dictionary<ToolItemStatesLiquid, int> dictionary = liquidRefills;
				key = val;
				dictionary[key] -= num;
			}
		}

		public void Add(ToolResourcesTotal other)
		{
			rosaries += other.rosaries;
			shellShards += other.shellShards;
			foreach (KeyValuePair<ToolItemStatesLiquid, int> liquidRefill in other.liquidRefills)
			{
				liquidRefill.Deconstruct(out var key, out var value);
				ToolItemStatesLiquid val = key;
				int num = value;
				if (!liquidRefills.ContainsKey(val))
				{
					liquidRefills[val] = 0;
				}
				Dictionary<ToolItemStatesLiquid, int> dictionary = liquidRefills;
				key = val;
				dictionary[key] += num;
			}
		}

		public void RestoreRosaries()
		{
			if (PlayerData.HasInstance)
			{
				PlayerData instance = PlayerData.instance;
				if (rosaries > 0)
				{
					int value = instance.geo + rosaries;
					int currencyCap = Gameplay.GetCurrencyCap((CurrencyType)0);
					instance.geo = Math.Clamp(value, 0, currencyCap);
				}
			}
		}

		public void ClearRosaries()
		{
			rosaries = 0;
		}

		public void Restore()
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			if (!PlayerData.HasInstance)
			{
				return;
			}
			PlayerData instance = PlayerData.instance;
			if (rosaries > 0)
			{
				int value = instance.geo + rosaries;
				int currencyCap = Gameplay.GetCurrencyCap((CurrencyType)0);
				instance.geo = Math.Clamp(value, 0, currencyCap);
			}
			if (shellShards > 0)
			{
				int value2 = instance.ShellShards + shellShards;
				int currencyCap2 = Gameplay.GetCurrencyCap((CurrencyType)1);
				instance.ShellShards = Math.Clamp(value2, 0, currencyCap2);
			}
			foreach (var (val2, num2) in liquidRefills)
			{
				if (num2 > 0)
				{
					Data liquidSavedData = val2.LiquidSavedData;
					liquidSavedData.RefillsLeft = Math.Clamp(liquidSavedData.RefillsLeft + num2, 0, val2.RefillsMax);
					val2.LiquidSavedData = liquidSavedData;
				}
			}
		}

		public void Clear()
		{
			rosaries = 0;
			shellShards = 0;
			liquidRefills.Clear();
		}

		public override string ToString()
		{
			IEnumerable<string> enumerable = liquidRefills.Select<KeyValuePair<ToolItemStatesLiquid, int>, string>((KeyValuePair<ToolItemStatesLiquid, int> kvp) => ((ToolItem)kvp.Key).name + ": " + kvp.Value);
			if (shellShards > 0)
			{
				enumerable = enumerable.Prepend($"Shell Shards: {shellShards}");
			}
			if (rosaries > 0)
			{
				enumerable = enumerable.Prepend($"Rosaries: {rosaries}");
			}
			return "{ " + string.Join(", ", enumerable) + " }";
		}
	}
}