Decompiled source of AutoUpCraft v1.0.0

BepInEx/plugins/AutoUpCraft.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Sparroh")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("AutoUpCraft")]
[assembly: AssemblyTitle("AutoUpCraft")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 AutoUpCraft
{
	internal static class AutoUpcraftService
	{
		private static bool _converting;

		private static bool _loggedMissingWindow;

		private static bool _loggedMissingCosts;

		private static bool _costsReady;

		private static ResourceCost[] _toRare;

		private static ResourceCost[] _toEpic;

		private static ResourceCost[] _toExotic;

		private static readonly FieldInfo UpcraftToRareCostField = AccessTools.Field(typeof(CraftingWindow), "upcraftToRareCost");

		private static readonly FieldInfo UpcraftToEpicCostField = AccessTools.Field(typeof(CraftingWindow), "upcraftToEpicCost");

		private static readonly FieldInfo UpcraftToExoticCostField = AccessTools.Field(typeof(CraftingWindow), "upcraftToExoticCost");

		private static readonly FieldInfo ResourcesField = AccessTools.Field(typeof(PlayerData), "resources");

		private static readonly MethodInfo InvokeResourceUpdateMethod = AccessTools.Method(typeof(PlayerData), "InvokeResourceUpdate", (Type[])null, (Type[])null);

		public static bool IsConverting => _converting;

		public static bool WouldOvercap(PlayerResource resource, int amountBeforeAdd, int amountAdded)
		{
			if ((Object)(object)resource == (Object)null || amountAdded <= 0)
			{
				return false;
			}
			return amountBeforeAdd + amountAdded > resource.Max;
		}

		public static void TryAutoUpcraftFromOverflow(PlayerResource overflowedScrap)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Invalid comparison between Unknown and I4
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			if (_converting || (Object)(object)overflowedScrap == (Object)null || PlayerData.Instance == null || (Object)(object)Global.Instance == (Object)null || !TryGetScrapRarity(overflowedScrap, out var rarity))
			{
				return;
			}
			if ((int)rarity >= 3)
			{
				ClampResource(overflowedScrap);
				return;
			}
			if (!EnsureCostsCached())
			{
				ClampResource(overflowedScrap);
				return;
			}
			if (!TryGetNextTierRecipe(rarity, out var toRarity, out var cost))
			{
				ClampResource(overflowedScrap);
				return;
			}
			_converting = true;
			try
			{
				ConvertWhileCapped(rarity, toRarity, cost);
			}
			catch (Exception arg)
			{
				SparrohPlugin.Log.LogError((object)$"Auto upcraft failed: {arg}");
			}
			finally
			{
				ClampResource(overflowedScrap);
				_converting = false;
			}
		}

		private static bool TryGetNextTierRecipe(Rarity fromRarity, out Rarity toRarity, out ResourceCost[] cost)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			switch ((int)fromRarity)
			{
			case 0:
				toRarity = (Rarity)1;
				cost = _toRare;
				if (cost != null)
				{
					return cost.Length != 0;
				}
				return false;
			case 1:
				toRarity = (Rarity)2;
				cost = _toEpic;
				if (cost != null)
				{
					return cost.Length != 0;
				}
				return false;
			case 2:
				toRarity = (Rarity)3;
				cost = _toExotic;
				if (cost != null)
				{
					return cost.Length != 0;
				}
				return false;
			default:
				toRarity = (Rarity)(-1);
				cost = null;
				return false;
			}
		}

		public static void RestoreUnclampedTotal(PlayerResource resource, int amountBeforeAdd, int amountAdded)
		{
			if ((Object)(object)resource == (Object)null || amountAdded <= 0 || PlayerData.Instance == null)
			{
				return;
			}
			int num = amountBeforeAdd + amountAdded;
			if (num > resource.Max)
			{
				int resource2 = PlayerData.Instance.GetResource(resource);
				if (resource2 < num)
				{
					SetResourceRaw(resource, num);
					SparrohPlugin.Log.LogDebug((object)($"Restored overflow for {resource.ID}: clamped {resource2} → unclamped {num} " + $"(before {amountBeforeAdd} + {amountAdded})"));
				}
			}
		}

		private static bool ConvertWhileCapped(Rarity fromRarity, Rarity toRarity, ResourceCost[] cost)
		{
			//IL_0009: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			if (cost == null || cost.Length == 0)
			{
				return false;
			}
			PlayerResource scrap = GetScrap(fromRarity);
			PlayerResource scrap2 = GetScrap(toRarity);
			if ((Object)(object)scrap == (Object)null || (Object)(object)scrap2 == (Object)null)
			{
				return false;
			}
			PlayerData instance = PlayerData.Instance;
			bool result = false;
			int num = 0;
			while (num++ < 10000)
			{
				int resource = instance.GetResource(scrap);
				if (resource < scrap.Max || instance.GetResource(scrap2) >= scrap2.Max || !instance.CanAffordCost(cost) || !instance.TryRemoveResources(cost))
				{
					break;
				}
				instance.AddResource(scrap2, 1, false);
				result = true;
				SparrohPlugin.Log.LogDebug((object)($"Upcrafted {fromRarity} scrap → 1 {toRarity} scrap " + $"(was {resource}/{scrap.Max})"));
			}
			return result;
		}

		private static void ClampResource(PlayerResource scrap)
		{
			if (!((Object)(object)scrap == (Object)null) && PlayerData.Instance != null)
			{
				int resource = PlayerData.Instance.GetResource(scrap);
				if (resource > scrap.Max)
				{
					SetResourceRaw(scrap, scrap.Max);
					SparrohPlugin.Log.LogDebug((object)$"Clamped {scrap.ID} from {resource} to {scrap.Max}");
				}
			}
		}

		private static void SetResourceRaw(PlayerResource resource, int amount, bool invokeUpdate = true)
		{
			Dictionary<string, int> resourcesDictionary = GetResourcesDictionary();
			if (resourcesDictionary != null && !((Object)(object)resource == (Object)null))
			{
				resourcesDictionary[resource.ID] = amount;
				if (invokeUpdate)
				{
					InvokeResourceUpdate();
				}
			}
		}

		private static Dictionary<string, int> GetResourcesDictionary()
		{
			if (PlayerData.Instance == null || ResourcesField == null)
			{
				return null;
			}
			return ResourcesField.GetValue(PlayerData.Instance) as Dictionary<string, int>;
		}

		private static void InvokeResourceUpdate()
		{
			try
			{
				InvokeResourceUpdateMethod?.Invoke(null, null);
			}
			catch (Exception ex)
			{
				SparrohPlugin.Log.LogDebug((object)("InvokeResourceUpdate failed: " + ex.Message));
			}
		}

		private static PlayerResource GetScrap(Rarity rarity)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Expected I4, but got Unknown
			RarityData[] rarities = Global.Instance.Rarities;
			int num = (int)rarity;
			if (rarities == null || num < 0 || num >= rarities.Length)
			{
				return null;
			}
			return rarities[num].scrapResource;
		}

		private static bool TryGetScrapRarity(PlayerResource resource, out Rarity rarity)
		{
			rarity = (Rarity)(-1);
			if ((Object)(object)resource == (Object)null || Global.Instance?.Rarities == null)
			{
				return false;
			}
			RarityData[] rarities = Global.Instance.Rarities;
			int num = Math.Min(rarities.Length, 4);
			for (int i = 0; i < num; i++)
			{
				if ((Object)(object)rarities[i].scrapResource == (Object)(object)resource)
				{
					rarity = (Rarity)(sbyte)i;
					return true;
				}
			}
			return false;
		}

		private static bool EnsureCostsCached()
		{
			if (_costsReady)
			{
				return true;
			}
			CraftingWindow val = FindCraftingWindow();
			if ((Object)(object)val == (Object)null)
			{
				if (!_loggedMissingWindow)
				{
					_loggedMissingWindow = true;
					SparrohPlugin.Log.LogWarning((object)"CraftingWindow not found yet; auto-upcraft will retry when scrap overcaps.");
				}
				return false;
			}
			_toRare = UpcraftToRareCostField?.GetValue(val) as ResourceCost[];
			_toEpic = UpcraftToEpicCostField?.GetValue(val) as ResourceCost[];
			_toExotic = UpcraftToExoticCostField?.GetValue(val) as ResourceCost[];
			if (!IsValidCost(_toRare) || !IsValidCost(_toEpic) || !IsValidCost(_toExotic))
			{
				if (!_loggedMissingCosts)
				{
					_loggedMissingCosts = true;
					SparrohPlugin.Log.LogError((object)"Failed to read vanilla upcraft costs from CraftingWindow. Auto-upcraft disabled until costs are available.");
				}
				return false;
			}
			_costsReady = true;
			_loggedMissingWindow = false;
			_loggedMissingCosts = false;
			SparrohPlugin.Log.LogInfo((object)("Cached vanilla upcraft costs (Rare: " + FormatCost(_toRare) + ", Epic: " + FormatCost(_toEpic) + ", Exotic: " + FormatCost(_toExotic) + ")"));
			return true;
		}

		private static bool IsValidCost(ResourceCost[] cost)
		{
			if (cost == null || cost.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < cost.Length; i++)
			{
				if ((Object)(object)cost[i].resource == (Object)null || cost[i].count < 1)
				{
					return false;
				}
			}
			return true;
		}

		private static string FormatCost(ResourceCost[] cost)
		{
			List<string> list = new List<string>(cost.Length);
			for (int i = 0; i < cost.Length; i++)
			{
				string arg = (((Object)(object)cost[i].resource != (Object)null) ? cost[i].resource.ID : "?");
				list.Add($"{cost[i].count}x {arg}");
			}
			return string.Join(" + ", list);
		}

		private static CraftingWindow FindCraftingWindow()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			CraftingWindow[] array = Resources.FindObjectsOfTypeAll<CraftingWindow>();
			if (array == null || array.Length == 0)
			{
				return null;
			}
			foreach (CraftingWindow val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					Scene scene = ((Component)val).gameObject.scene;
					if (((Scene)(ref scene)).IsValid())
					{
						return val;
					}
				}
			}
			return array[0];
		}

		public static bool IsUpgradeScrap(PlayerResource resource)
		{
			Rarity rarity;
			return TryGetScrapRarity(resource, out rarity);
		}
	}
	[BepInPlugin("sparroh.autoupcraft", "AutoUpCraft", "1.0.0")]
	[MycoMod(/*Could not decode attribute arguments.*/)]
	public class SparrohPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "sparroh.autoupcraft";

		public const string PluginName = "AutoUpCraft";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			_harmony = new Harmony("sparroh.autoupcraft");
			_harmony.PatchAll();
			Log.LogInfo((object)"AutoUpCraft v1.0.0 loaded");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "AutoUpCraft";

		public const string PLUGIN_NAME = "AutoUpCraft";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace AutoUpCraft.Patches
{
	[HarmonyPatch(typeof(PlayerData), "AddResource")]
	internal static class PlayerDataAddResourcePatch
	{
		[HarmonyPrefix]
		private static void Prefix(PlayerResource resource, int amount, ref int __state)
		{
			__state = -1;
			if (amount > 0 && !((Object)(object)resource == (Object)null) && !AutoUpcraftService.IsConverting && AutoUpcraftService.IsUpgradeScrap(resource) && PlayerData.Instance != null)
			{
				__state = PlayerData.Instance.GetResource(resource);
			}
		}

		[HarmonyPostfix]
		private static void Postfix(PlayerResource resource, int amount, int __state)
		{
			if (amount > 0 && !((Object)(object)resource == (Object)null) && !AutoUpcraftService.IsConverting && AutoUpcraftService.IsUpgradeScrap(resource) && __state >= 0 && AutoUpcraftService.WouldOvercap(resource, __state, amount))
			{
				AutoUpcraftService.RestoreUnclampedTotal(resource, __state, amount);
				AutoUpcraftService.TryAutoUpcraftFromOverflow(resource);
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}