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 ToolRefund v1.0.0
plugins/ToolRefund/ToolRefund.dll
Decompiled 8 months agousing 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) + " }"; } } }