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) + " }";
}
}
}