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 RustyHeathensCraftTracker v0.1.4
plugins/RustyHeathensCraftTracker/RustyHeathensCraftTracker.dll
Decompiled 5 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; 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("RustyHeathensCraftTracker")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.4.0")] [assembly: AssemblyInformationalVersion("0.1.4")] [assembly: AssemblyProduct("RustyHeathensCraftTracker")] [assembly: AssemblyTitle("RustyHeathensCraftTracker")] [assembly: AssemblyVersion("0.1.4.0")] [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 RustyHeathens.CraftTracker { [BepInPlugin("com.rustyheathens.crafttracker", "Rusty Heathens Craft Tracker", "0.1.4")] public sealed class Plugin : BaseUnityPlugin { private sealed class Row { public string Name; public int Have; public int Need; } internal sealed class CraftState { public Recipe Recipe; public Player Player; public int Before; } public const string Id = "com.rustyheathens.crafttracker"; internal static Plugin Instance; private Harmony harmony; private ConfigEntry<float> top; private ConfigEntry<float> right; private ConfigEntry<float> scale; private Recipe tracked; private Player owner; private readonly List<Row> rows = new List<Row>(); private float nextRefresh; private string notice; private float noticeUntil; private GUIStyle title; private GUIStyle line; private GUIStyle hint; private static readonly FieldInfo Available = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); private static readonly FieldInfo CraftRecipe = AccessTools.Field(typeof(InventoryGui), "m_craftRecipe"); private static readonly FieldInfo UpgradeItem = AccessTools.Field(typeof(InventoryGui), "m_craftUpgradeItem"); private static readonly FieldInfo UpgraderResource = AccessTools.Field(typeof(Requirement), "m_upgraderResource"); private static readonly FieldInfo OnlyOne = AccessTools.Field(typeof(Recipe), "m_requireOnlyOneIngredient"); private bool EitherIngredient { get { if (Object.op_Implicit((Object)(object)tracked) && OnlyOne != null) { return (bool)OnlyOne.GetValue(tracked); } return false; } } private void Awake() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown //IL_0179: Expected O, but got Unknown Instance = this; top = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "TopMargin", 270f, "Pixels below the top edge at 1080p; positions the checklist below the minimap."); if (Mathf.Approximately(top.Value, 210f)) { top.Value = 270f; } right = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "RightMargin", 24f, "Distance from the right edge at 1080p."); scale = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Scale", 1f, new ConfigDescription("Tracker size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.65f, 1.8f), Array.Empty<object>())); harmony = new Harmony("com.rustyheathens.crafttracker"); MethodInfo methodInfo = AccessTools.Method(typeof(InventoryGui), "DoCrafting", new Type[1] { typeof(Player) }, (Type[])null); if (Available == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Recipe selection unavailable: this game version has an unsupported recipe-list API."); } if (methodInfo == null || CraftRecipe == null || UpgradeItem == null) { ((BaseUnityPlugin)this).Logger.LogError((object)"Craft tracking unavailable: this game version has an unsupported crafting API."); } else { harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Plugin), "BeforeCraft", (Type[])null), new HarmonyMethod(typeof(Plugin), "AfterCraft", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Craft Tracker loaded. Middle-click a recipe in a crafting table to track it."); } private void OnDestroy() { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } } private void Update() { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer != (Object)(object)owner) { owner = localPlayer; tracked = null; rows.Clear(); } if (Object.op_Implicit((Object)(object)localPlayer) && !((Character)localPlayer).IsDead()) { if (InventoryGui.IsVisible() && Input.GetMouseButtonDown(2)) { TrackHoveredRecipe(); } if (Object.op_Implicit((Object)(object)tracked) && Time.unscaledTime >= nextRefresh) { nextRefresh = Time.unscaledTime + 0.2f; Refresh(localPlayer); } } } private static object Member(object obj, string name) { if (obj == null) { return null; } Type type = obj.GetType(); object obj2 = AccessTools.Property(type, name)?.GetValue(obj, null); if (obj2 == null) { FieldInfo fieldInfo = AccessTools.Field(type, name); if ((object)fieldInfo == null) { return null; } obj2 = fieldInfo.GetValue(obj); } return obj2; } private static bool UnderPointer(RectTransform rect) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)rect) || !((Component)rect).gameObject.activeInHierarchy) { return false; } Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>(); Camera val = ((Object.op_Implicit((Object)(object)componentInParent) && (int)componentInParent.renderMode != 0) ? componentInParent.worldCamera : null); if (!RectTransformUtility.RectangleContainsScreenPoint(rect, Vector2.op_Implicit(Input.mousePosition), val)) { return false; } Transform parent = ((Transform)rect).parent; while ((Object)(object)parent != (Object)null) { Component[] components = ((Component)parent).GetComponents<Component>(); foreach (Component val2 in components) { if (Object.op_Implicit((Object)(object)val2) && (((object)val2).GetType().Name == "RectMask2D" || ((object)val2).GetType().Name == "Mask") && !RectTransformUtility.RectangleContainsScreenPoint((RectTransform)(object)((parent is RectTransform) ? parent : null), Vector2.op_Implicit(Input.mousePosition), val)) { return false; } } parent = parent.parent; } return true; } private void TrackHoveredRecipe() { InventoryGui instance = InventoryGui.instance; if (!Object.op_Implicit((Object)(object)instance) || !(Available?.GetValue(instance) is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { object obj = Member(item, "InterfaceElement"); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (!Object.op_Implicit((Object)(object)val) || !UnderPointer((RectTransform)/*isinst with value type is only supported in some contexts*/)) { continue; } object obj2 = Member(item, "Recipe"); Recipe val2 = (Recipe)((obj2 is Recipe) ? obj2 : null); object obj3 = Member(item, "ItemData"); ItemData val3 = (ItemData)((obj3 is ItemData) ? obj3 : null); if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val2.m_item)) { if (val3 != null) { notice = "Choose a recipe in the Craft tab to track materials."; noticeUntil = Time.unscaledTime + 4f; } else if ((Object)(object)tracked == (Object)(object)val2) { tracked = null; rows.Clear(); } else { tracked = val2; Refresh(owner); } } break; } } private static string Local(string token) { if (Localization.instance == null) { return token; } return Localization.instance.Localize(token); } private static string Name(Recipe recipe) { return Local(recipe.m_item.m_itemData.m_shared.m_name); } private void Refresh(Player player) { rows.Clear(); Requirement[] resources = tracked.m_resources; foreach (Requirement val in resources) { if (val == null || !Object.op_Implicit((Object)(object)val.m_resItem) || (UpgraderResource != null && (bool)UpgraderResource.GetValue(val))) { continue; } int amount = val.GetAmount(1); if (amount > 0) { string token = val.m_resItem.m_itemData.m_shared.m_name; Row row = rows.FirstOrDefault((Row r) => r.Name == token); if (row != null) { row.Need += amount; continue; } rows.Add(new Row { Name = token, Need = amount, Have = ((Humanoid)player).GetInventory().CountItems(token, -1, true) }); } } } private void Styles() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown if (title == null) { title = new GUIStyle(GUI.skin.label) { fontSize = 20, fontStyle = (FontStyle)1, wordWrap = true, richText = false }; title.normal.textColor = new Color(0.25f, 0.7f, 1f); line = new GUIStyle(GUI.skin.label) { fontSize = 17, wordWrap = true, richText = false }; hint = new GUIStyle(GUI.skin.label) { fontSize = 13, wordWrap = true, richText = false }; } } private void OnGUI() { //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)owner) || ((Character)owner).IsDead() || (!Object.op_Implicit((Object)(object)tracked) && Time.unscaledTime >= noticeUntil)) { return; } Styles(); Matrix4x4 matrix = GUI.matrix; int depth = GUI.depth; float num = Mathf.Clamp((float)Screen.height / 1080f * scale.Value, 0.5f, 2.5f); GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(num, num, 1f)); GUI.depth = -100; try { float num2 = (float)Screen.width / num; float num3 = (float)Screen.height / num; if (Time.unscaledTime < noticeUntil) { GUI.Box(new Rect(Mathf.Max(10f, (num2 - 520f) / 2f), num3 * 0.2f, 520f, 55f), notice); } if (!Object.op_Implicit((Object)(object)tracked)) { return; } float num4 = Mathf.Min(num3 - 20f, (float)(150 + rows.Count * 48)); GUILayout.BeginArea(new Rect(Mathf.Max(10f, num2 - 230f - right.Value), Mathf.Clamp(top.Value, 10f, Mathf.Max(10f, num3 - num4 - 10f)), 230f, num4)); GUILayout.Label("CRAFT: " + Name(tracked), title, Array.Empty<GUILayoutOption>()); bool flag = (EitherIngredient ? rows.Any((Row r) => r.Have >= r.Need) : rows.All((Row r) => r.Have >= r.Need)); GUILayout.Label(EitherIngredient ? "Use ONE of these ingredients:" : "Materials in your inventory:", hint, Array.Empty<GUILayoutOption>()); foreach (Row row in rows) { line.normal.textColor = ((row.Have >= row.Need) ? new Color(0.35f, 1f, 0.4f) : new Color(1f, 0.3f, 0.3f)); GUILayout.Label(Local(row.Name) + " " + row.Have + "/" + row.Need, line, Array.Empty<GUILayoutOption>()); } GUILayout.Label(flag ? "Materials ready — craft at the required station." : "Collect the missing materials.", hint, Array.Empty<GUILayoutOption>()); if (InventoryGui.IsVisible() && GUILayout.Button("Clear tracker", Array.Empty<GUILayoutOption>())) { tracked = null; rows.Clear(); } GUILayout.EndArea(); } finally { GUI.matrix = matrix; GUI.depth = depth; } } private static int OutputCount(Player player, Recipe recipe) { return ((Humanoid)player).GetInventory().CountItems(recipe.m_item.m_itemData.m_shared.m_name, -1, true); } private static void BeforeCraft(InventoryGui __instance, Player player, out CraftState __state) { __state = null; Plugin instance = Instance; if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.tracked) && !((Object)(object)player != (Object)(object)Player.m_localPlayer) && UpgradeItem.GetValue(__instance) == null) { object? value = CraftRecipe.GetValue(__instance); Recipe val = (Recipe)((value is Recipe) ? value : null); if (!((Object)(object)val != (Object)(object)instance.tracked)) { __state = new CraftState { Recipe = val, Player = player, Before = OutputCount(player, val) }; } } } private static void AfterCraft(CraftState __state) { if (__state != null && Object.op_Implicit((Object)(object)Instance) && !((Object)(object)Instance.tracked != (Object)(object)__state.Recipe) && OutputCount(__state.Player, __state.Recipe) > __state.Before) { Instance.tracked = null; Instance.rows.Clear(); } } } }