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 resourcesDictionary = GetResourcesDictionary(); if (resourcesDictionary != null && !((Object)(object)resource == (Object)null)) { resourcesDictionary[resource.ID] = amount; if (invokeUpdate) { InvokeResourceUpdate(); } } } private static Dictionary GetResourcesDictionary() { if (PlayerData.Instance == null || ResourcesField == null) { return null; } return ResourcesField.GetValue(PlayerData.Instance) as Dictionary; } 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 list = new List(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(); 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) { } } }