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 Extract Crystals In Levels v1.0.0
ExtractCrystalsInLevels.dll
Decompiled 9 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ExtractCrystalsInLevels")] [assembly: AssemblyDescription("Mod for Extracting Power Crystals In Levels! Developed by Jettcodey.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Jettcodey")] [assembly: AssemblyProduct("ExtractCrystalsInLevels")] [assembly: AssemblyCopyright("Copyright © Jettcodey 2025")] [assembly: ComVisible(false)] [assembly: Guid("b52829e7-88b6-4158-ba1b-23566c7cf06b")] [assembly: AssemblyFileVersion("1.0.0")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [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 ExtractCrystalsInLevels { [BepInPlugin("Jettcodey.ExtractCrystalsInLevels", "ExtractCrystalsInLevels", "1.0.0")] public class Plugin : BaseUnityPlugin { private ConfigEntry<bool> enableKeyPressMethod; private ConfigEntry<KeyCode> collectKey; private ConfigEntry<bool> enableExtractionMethod; private ConfigEntry<bool> enableMod; private static Dictionary<string, string> powerCrystalNameMap = new Dictionary<string, string> { { "Energy Crystal", "Item Power Crystal" }, { "Power Crystal", "Item Power Crystal" }, { "Crystal", "Item Power Crystal" } }; internal static Plugin Instance { get; private set; } = null; internal static ManualLogSource? Logger { get; private set; } private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; private Harmony? _harmony { get; set; } private void Awake() { //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); enableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Enable/disable the mod"); enableKeyPressMethod = ((BaseUnityPlugin)this).Config.Bind<bool>("Methods", "EnableKeyPressMethod", false, "Enable key press method (grab and press key to collect)"); collectKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Methods", "CollectKey", (KeyCode)117, "Key to collect power crystals (key press method)"); enableExtractionMethod = ((BaseUnityPlugin)this).Config.Bind<bool>("Methods", "EnableExtractionMethod", true, "Enable extraction method (bring to extraction point)"); if (!enableMod.Value) { Logger.LogInfo((object)"ExtractCrystalsInLevels mod is disabled in config"); return; } PowerCrystalPatches.InitializeConfig(enableMod.Value, enableKeyPressMethod.Value, collectKey.Value, enableExtractionMethod.Value); _harmony = new Harmony("Jettcodey.ExtractCrystalsInLevels"); _harmony.PatchAll(); Logger.LogInfo((object)"Plugin ExtractCrystalsInLevels v1.0.0 loaded successfully."); } public static string GetPowerCrystalKey(string displayName) { if (powerCrystalNameMap.ContainsKey(displayName)) { return powerCrystalNameMap[displayName]; } if (displayName.ToLower().Contains("crystal")) { return "Item Power Crystal"; } return displayName; } private void Update() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!enableMod.Value || !enableKeyPressMethod.Value || !Input.GetKeyDown(collectKey.Value)) { return; } PlayerController val = PlayerController.instance; if ((Object)(object)val == (Object)null) { val = Object.FindObjectOfType<PlayerController>(); } if ((Object)(object)val == (Object)null || (Object)(object)val.playerAvatarScript == (Object)null) { return; } PhysGrabber component = ((Component)val.playerAvatarScript).GetComponent<PhysGrabber>(); if ((Object)(object)component == (Object)null || !component.grabbed) { return; } PhysGrabObject grabbedPhysGrabObject = component.grabbedPhysGrabObject; if ((Object)(object)grabbedPhysGrabObject == (Object)null) { return; } ItemAttributes component2 = ((Component)grabbedPhysGrabObject).GetComponent<ItemAttributes>(); if (!((Object)(object)component2 == (Object)null)) { Logger.LogDebug((object)("Holding: " + component2.itemName)); string powerCrystalKey = GetPowerCrystalKey(component2.itemName); if (powerCrystalKey != component2.itemName || component2.itemName.IndexOf("Crystal", StringComparison.OrdinalIgnoreCase) >= 0) { Logger.LogDebug((object)"Crystal Detected! Attempting collection..."); PowerCrystalPatches.KeyPressMethod_CollectPowerCrystal(grabbedPhysGrabObject, component2, val.playerAvatarScript); } else { Logger.LogWarning((object)("Item '" + component2.itemName + "' was not recognized as a Power Crystal.")); } } } } [HarmonyPatch] public static class PowerCrystalPatches { private static bool modEnabled = true; private static bool keyPressMethodEnabled = false; private static KeyCode collectKey = (KeyCode)117; private static bool extractionMethodEnabled = true; private const int MAX_CRYSTALS_PER_RUN = 10; public static void InitializeConfig(bool modEnabledValue, bool keyPressMethodEnabledValue, KeyCode collectKeyValue, bool extractionMethodEnabledValue) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) modEnabled = modEnabledValue; keyPressMethodEnabled = keyPressMethodEnabledValue; collectKey = collectKeyValue; extractionMethodEnabled = extractionMethodEnabledValue; Plugin.Logger.LogDebug((object)("CrystalAutoApply config loaded - " + $"Mod: {modEnabled}, " + $"KeyPressMethod: {keyPressMethodEnabled}, " + $"CollectKey: {collectKey}, " + $"ExtractionMethod: {extractionMethodEnabled}")); } private static int GetCurrentRunCrystalCount() { try { if ((Object)(object)StatsManager.instance != (Object)null) { string[] array = new string[4] { "Item Power Crystal", "Power Crystal", "Energy Crystal", "Crystal" }; string[] array2 = array; foreach (string key in array2) { if (StatsManager.instance.itemsPurchased.ContainsKey(key)) { return StatsManager.instance.itemsPurchased[key]; } } if (StatsManager.instance.runStats.ContainsKey("chargingStationCharge")) { return StatsManager.instance.runStats["chargingStationCharge"]; } } return 0; } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error getting current crystal count: {arg}"); return 0; } } private static bool CanCollectMoreCrystals() { int currentRunCrystalCount = GetCurrentRunCrystalCount(); bool flag = currentRunCrystalCount < 10; if (!flag) { Debug.Log((object)$"Cannot collect more crystals: {currentRunCrystalCount}/{10} limit reached"); } return flag; } private static void ShowLimitNotification(PlayerAvatar playerAvatar) { //IL_0095: Unknown result type (might be due to invalid IL or missing references) try { string text = $"Charging Station Full! ({10}/{10})"; Type type = Type.GetType("ItemInfoExtraUI, Assembly-CSharp"); if (!(type != null)) { return; } PropertyInfo property = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public); if (!(property != null)) { return; } object value = property.GetValue(null); if (value != null) { MethodInfo method = type.GetMethod("ItemInfoText", new Type[2] { typeof(string), typeof(Color) }); if (method != null) { method.Invoke(value, new object[2] { text, Color.yellow }); } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error showing limit notification: {arg}"); } } [HarmonyPatch(typeof(PhysGrabObject), "Update")] [HarmonyPostfix] private static void PhysGrabObject_Update_Postfix(PhysGrabObject __instance) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (!modEnabled || !keyPressMethodEnabled) { return; } try { if ((Object)(object)__instance == (Object)null || !__instance.grabbedLocal || !Input.GetKeyDown(collectKey)) { return; } if (!CanCollectMoreCrystals()) { try { PlayerAvatar val = ((__instance.playerGrabbing.Count > 0) ? __instance.playerGrabbing[0].playerAvatar : null); if ((Object)(object)val != (Object)null && (Object)(object)val.photonView != (Object)null && val.photonView.IsMine) { ShowLimitNotification(val); } return; } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error showing limit notification: {arg}"); return; } } ItemAttributes component = ((Component)__instance).GetComponent<ItemAttributes>(); if ((Object)(object)component == (Object)null || (Object)(object)component.item == (Object)null) { return; } FieldInfo field = ((object)component.item).GetType().GetField("itemType"); if (field != null) { object value = field.GetValue(component.item); if (value.ToString() == "power_crystal" && __instance.playerGrabbing.Count > 0) { PlayerAvatar playerAvatar = __instance.playerGrabbing[0].playerAvatar; if ((Object)(object)playerAvatar != (Object)null) { KeyPressMethod_CollectPowerCrystal(__instance, component, playerAvatar); } } } else if (component.itemName != null && component.itemName.ToLower().Contains("crystal") && __instance.playerGrabbing.Count > 0) { PlayerAvatar playerAvatar2 = __instance.playerGrabbing[0].playerAvatar; if ((Object)(object)playerAvatar2 != (Object)null) { KeyPressMethod_CollectPowerCrystal(__instance, component, playerAvatar2); } } } catch (Exception arg2) { Plugin.Logger.LogError((object)$"Error in PhysGrabObject Patch: {arg2}"); } } public static void KeyPressMethod_CollectPowerCrystal(PhysGrabObject powerCrystal, ItemAttributes itemAttributes, PlayerAvatar playerAvatar) { try { if (!CanCollectMoreCrystals()) { Plugin.Logger.LogInfo((object)"Crystal limit reached, skipping collection"); if ((Object)(object)playerAvatar.photonView != (Object)null && playerAvatar.photonView.IsMine) { ShowLimitNotification(playerAvatar); } } else { if (!GameManager.Multiplayer()) { return; } string itemName = itemAttributes.itemName; string text = Plugin.GetPowerCrystalKey(itemName); if ((Object)(object)itemAttributes.item != (Object)null) { FieldInfo field = typeof(ItemAttributes).GetField("itemAssetName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { string text2 = field.GetValue(itemAttributes) as string; if (!string.IsNullOrEmpty(text2) && text2.Contains("PowerCrystal")) { text = "Item Power Crystal"; } } } Plugin.Logger.LogInfo((object)("Key Press method: Display Name='" + itemName + "', Dictionary Key='" + text + "'")); KeyPressMethod_UpdatePowerCrystalStats(text, itemName, playerAvatar); KeyPressMethod_RemovePowerCrystal(powerCrystal, playerAvatar); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error collecting Power Crystal (key press method): {arg}"); } } private static void KeyPressMethod_UpdatePowerCrystalStats(string itemKey, string displayName, PlayerAvatar playerAvatar) { try { if (GameManager.Multiplayer() && !PhotonNetwork.IsMasterClient) { return; } Plugin.Logger.LogDebug((object)("Key Press method: Updating Power Crystal stats: " + displayName)); if (!((Object)(object)StatsManager.instance != (Object)null)) { return; } if (!StatsManager.instance.itemsPurchased.ContainsKey(itemKey)) { string text = null; foreach (string key in StatsManager.instance.itemsPurchased.Keys) { if (key.Contains("Power Crystal") || key.Contains("PowerCrystal")) { text = key; break; } } if (text != null) { itemKey = text; Plugin.Logger.LogDebug((object)("Found alternative key: " + itemKey)); } else { StatsManager.instance.itemsPurchased[itemKey] = 0; StatsManager.instance.itemsPurchasedTotal[itemKey] = 0; Plugin.Logger.LogDebug((object)("Added new key to dictionary: " + itemKey)); } } int num = (StatsManager.instance.itemsPurchased.ContainsKey(itemKey) ? StatsManager.instance.itemsPurchased[itemKey] : 0); int num2 = (StatsManager.instance.itemsPurchasedTotal.ContainsKey(itemKey) ? StatsManager.instance.itemsPurchasedTotal[itemKey] : 0); if (num >= 10) { Plugin.Logger.LogInfo((object)$"Already at crystal limit: {num}/{10}"); return; } StatsManager.instance.itemsPurchased[itemKey] = num + 1; StatsManager.instance.itemsPurchasedTotal[itemKey] = num2 + 1; Plugin.Logger.LogInfo((object)$"Updated stats for '{itemKey}': Purchased={StatsManager.instance.itemsPurchased[itemKey]}, Total={StatsManager.instance.itemsPurchasedTotal[itemKey]}"); KeyPressMethod_UpdateChargingStationStats(itemKey, num + 1); if (GameManager.Multiplayer() && (Object)(object)PunManager.instance != (Object)null) { PunManager.instance.UpdateStat("itemsPurchased", itemKey, StatsManager.instance.itemsPurchased[itemKey]); PunManager.instance.UpdateStat("itemsPurchasedTotal", itemKey, StatsManager.instance.itemsPurchasedTotal[itemKey]); KeyPressMethod_UpdateChargingStationMultiplayer(num + 1); } KeyPressMethod_UpdateChargingStationVisuals(num + 1); if ((Object)(object)playerAvatar.photonView != (Object)null && playerAvatar.photonView.IsMine) { ShowCollectionNotification(playerAvatar, displayName, fromExtraction: false, num + 1); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error updating Power Crystal stats (key press method): {arg}"); } } private static void KeyPressMethod_UpdateChargingStationStats(string itemKey, int newCrystalCount) { try { newCrystalCount = Mathf.Min(newCrystalCount, 10); if (StatsManager.instance.runStats.ContainsKey("chargingStationCharge")) { StatsManager.instance.runStats["chargingStationCharge"] = newCrystalCount; } else { StatsManager.instance.runStats.Add("chargingStationCharge", newCrystalCount); } int num = 100; int num2 = 10; int num3 = Mathf.Min(newCrystalCount * num2, num); int num4 = num; if (StatsManager.instance.runStats.ContainsKey("chargingStationChargeTotal")) { num4 = StatsManager.instance.runStats["chargingStationChargeTotal"]; } else { StatsManager.instance.runStats.Add("chargingStationChargeTotal", num3); } if (num4 < num3) { StatsManager.instance.runStats["chargingStationChargeTotal"] = num3; } Plugin.Logger.LogInfo((object)string.Format("Updated charging station: Crystals={0}/{1}, Capacity={2}", newCrystalCount, 10, StatsManager.instance.runStats["chargingStationChargeTotal"])); if (StatsManager.instance.itemDictionary.ContainsKey(itemKey)) { Item val = StatsManager.instance.itemDictionary[itemKey]; if ((Object)(object)val != (Object)null) { StatsManager.instance.SetItemPurchase(val, newCrystalCount); } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error updating charging station stats (key press method): {arg}"); } } private static void KeyPressMethod_UpdateChargingStationMultiplayer(int newCrystalCount) { try { newCrystalCount = Mathf.Min(newCrystalCount, 10); ChargingStation instance = ChargingStation.instance; if (!((Object)(object)instance != (Object)null) || !PhotonNetwork.IsMasterClient) { return; } int num = 40; float num2 = Mathf.Clamp01((float)newCrystalCount / 10f); int num3 = Mathf.RoundToInt(num2 * (float)num); PhotonView component = ((Component)instance).GetComponent<PhotonView>(); if ((Object)(object)component != (Object)null) { MethodInfo method = typeof(ChargingStation).GetMethod("ChargingStationSegmentChangedRPC", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { method.Invoke(instance, new object[1] { (byte)num3 }); } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error updating charging station multiplayer: {arg}"); } } private static void KeyPressMethod_UpdateChargingStationVisuals(int newCrystalCount) { try { newCrystalCount = Mathf.Min(newCrystalCount, 10); ChargingStation instance = ChargingStation.instance; if ((Object)(object)instance != (Object)null) { FieldInfo field = typeof(ChargingStation).GetField("chargeInt", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(instance, newCrystalCount); } FieldInfo field2 = typeof(ChargingStation).GetField("chargeTotal", BindingFlags.Instance | BindingFlags.NonPublic); if (field2 != null) { int num = Mathf.Min(newCrystalCount * 10, 100); field2.SetValue(instance, num); } FieldInfo field3 = typeof(ChargingStation).GetField("chargeFloat", BindingFlags.Instance | BindingFlags.NonPublic); if (field3 != null) { field3.SetValue(instance, (float)newCrystalCount / 10f); } FieldInfo field4 = typeof(ChargingStation).GetField("chargeSegmentCurrent", BindingFlags.Instance | BindingFlags.NonPublic); if (field4 != null) { field4.SetValue(instance, Mathf.RoundToInt((float)newCrystalCount / 10f * 40f)); } FieldInfo field5 = typeof(ChargingStation).GetField("chargeScaleTarget", BindingFlags.Instance | BindingFlags.NonPublic); if (field5 != null) { field5.SetValue(instance, (float)newCrystalCount / 10f); } Plugin.Logger.LogInfo((object)$"Updated charging station visuals: {newCrystalCount}/{10} crystals"); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error updating charging station visuals: {arg}"); } } [HarmonyPatch(typeof(ChargingStation), "Start")] [HarmonyPostfix] private static void ChargingStation_Start_Postfix(ChargingStation __instance) { try { Plugin.Logger.LogDebug((object)"Charging Station initialized"); if ((Object)(object)StatsManager.instance != (Object)null && StatsManager.instance.itemsPurchased.ContainsKey("Item Power Crystal")) { int newCrystalCount = Mathf.Min(StatsManager.instance.itemsPurchased["Item Power Crystal"], 10); KeyPressMethod_UpdateChargingStationVisuals(newCrystalCount); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error in ChargingStation Start patch: {arg}"); } } private static void KeyPressMethod_RemovePowerCrystal(PhysGrabObject powerCrystal, PlayerAvatar playerAvatar) { try { PhysGrabber component = ((Component)playerAvatar).GetComponent<PhysGrabber>(); if ((Object)(object)component != (Object)null && (Object)(object)component.grabbedPhysGrabObject == (Object)(object)powerCrystal) { MethodInfo method = typeof(PhysGrabber).GetMethod("ReleaseObject", BindingFlags.Instance | BindingFlags.Public); if (method != null) { method.Invoke(component, new object[2] { powerCrystal.photonView.ViewID, 1f }); } else { component.grabbed = false; component.grabbedPhysGrabObject = null; } } if (powerCrystal.playerGrabbing.Contains(component)) { powerCrystal.playerGrabbing.Remove(component); } if (GameManager.Multiplayer()) { if (PhotonNetwork.IsMasterClient) { powerCrystal.DestroyPhysGrabObject(); } } else { powerCrystal.DestroyPhysGrabObject(); } Plugin.Logger.LogDebug((object)"Power Crystal removed from scene (key press method)"); } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error removing Power Crystal (key press method): {arg}"); } } [HarmonyPatch(typeof(RoundDirector), "Update")] [HarmonyPrefix] private static bool RoundDirector_Update_Prefix(RoundDirector __instance) { try { __instance.currentHaul = 0; __instance.currentHaulMax = 0; if (__instance.dollarHaulList == null) { return true; } if (__instance.dollarHaulList.Count <= 0) { return true; } List<GameObject> list = new List<GameObject>(); List<GameObject> list2 = new List<GameObject>(); for (int i = 0; i < __instance.dollarHaulList.Count; i++) { GameObject val = __instance.dollarHaulList[i]; if ((Object)(object)val == (Object)null) { list.Add(val); continue; } ValuableObject component = val.GetComponent<ValuableObject>(); if ((Object)(object)component == (Object)null) { list.Add(val); } else { list2.Add(val); } } foreach (GameObject item in list2) { if (!((Object)(object)item == (Object)null)) { ValuableObject component2 = item.GetComponent<ValuableObject>(); if (!((Object)(object)component2 == (Object)null)) { __instance.currentHaul += (int)component2.dollarValueCurrent; __instance.currentHaulMax += (int)component2.dollarValueOriginal; } } } foreach (GameObject item2 in list) { __instance.dollarHaulList.Remove(item2); } return false; } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error in while trying to fix/patch RoundDirector.Update: {arg}"); return true; } } [HarmonyPatch(typeof(ExtractionPoint), "DestroyTheFirstPhysObjectsInHaulList")] [HarmonyPrefix] private static bool ExtractionPoint_DestroyTheFirstPhysObjectsInHaulList_Prefix(ExtractionPoint __instance) { if (!modEnabled || !extractionMethodEnabled) { return true; } try { ProcessPowerCrystalsInExtractionArea(__instance); return true; } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error in Power Crystal extraction (first): {arg}"); return true; } } [HarmonyPatch(typeof(ExtractionPoint), "DestroyAllPhysObjectsInHaulList")] [HarmonyPrefix] private static bool ExtractionPoint_DestroyAllPhysObjectsInHaulList_Prefix(ExtractionPoint __instance) { if (!modEnabled || !extractionMethodEnabled) { return true; } try { ProcessPowerCrystalsInExtractionArea(__instance); return true; } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error in Power Crystal bulk extraction: {arg}"); return true; } } private static void ProcessPowerCrystalsInExtractionArea(ExtractionPoint extractionPoint) { //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) try { if (!CanCollectMoreCrystals()) { Plugin.Logger.LogInfo((object)"Crystal limit reached, skipping extraction processing"); return; } ItemAttributes[] array = Object.FindObjectsOfType<ItemAttributes>(); ItemAttributes[] array2 = array; foreach (ItemAttributes val in array2) { if (!CanCollectMoreCrystals()) { Plugin.Logger.LogInfo((object)"Crystal limit reached during extraction processing"); break; } if ((Object)(object)val == (Object)null || (Object)(object)val.item == (Object)null) { continue; } FieldInfo field = ((object)val.item).GetType().GetField("itemType"); if (field == null) { continue; } object value = field.GetValue(val.item); if (value.ToString() != "power_crystal") { continue; } RoomVolumeCheck component = ((Component)val).GetComponent<RoomVolumeCheck>(); if ((Object)(object)component == (Object)null) { continue; } bool flag = false; foreach (RoomVolume currentRoom in component.CurrentRooms) { if (!((Object)(object)currentRoom != (Object)null) || !currentRoom.Extraction) { continue; } Collider component2 = ((Component)currentRoom).GetComponent<Collider>(); if ((Object)(object)component2 != (Object)null) { Bounds bounds = component2.bounds; if (((Bounds)(ref bounds)).Contains(((Component)val).transform.position)) { flag = true; break; } } } if (flag) { HandlePowerCrystalExtraction(((Component)val).gameObject, val, extractionPoint); } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error processing power crystals in extraction area: {arg}"); } } private static void HandlePowerCrystalExtraction(GameObject powerCrystalObject, ItemAttributes itemAttributes, ExtractionPoint extractionPoint) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)powerCrystalObject == (Object)null || (Object)(object)itemAttributes == (Object)null) { return; } if (!CanCollectMoreCrystals()) { Plugin.Logger.LogInfo((object)"Crystal limit reached, skipping extraction"); return; } PlayerAvatar val = FindClosestPlayer(((Component)extractionPoint).transform.position); if (!((Object)(object)val == (Object)null)) { string itemName = itemAttributes.itemName; string powerCrystalKey = Plugin.GetPowerCrystalKey(itemName); Plugin.Logger.LogError((object)("Extraction method: Processing Power Crystal: " + itemName)); UpdatePowerCrystalStats(powerCrystalKey, itemName, val); if ((Object)(object)RoundDirector.instance != (Object)null && RoundDirector.instance.dollarHaulList != null) { RoundDirector.instance.dollarHaulList.Remove(powerCrystalObject); } PhysGrabObject component = powerCrystalObject.GetComponent<PhysGrabObject>(); if ((Object)(object)component != (Object)null) { component.DestroyPhysGrabObject(); } else { Object.Destroy((Object)(object)powerCrystalObject); } Plugin.Logger.LogInfo((object)("Power Crystal extracted: " + itemName)); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error handling power crystal extraction: {arg}"); } } private static void UpdatePowerCrystalStats(string itemKey, string displayName, PlayerAvatar playerAvatar) { try { if (GameManager.Multiplayer() && !PhotonNetwork.IsMasterClient) { return; } Plugin.Logger.LogInfo((object)("Updating Power Crystal stats: " + displayName)); if (!((Object)(object)StatsManager.instance != (Object)null)) { return; } if (!StatsManager.instance.itemsPurchased.ContainsKey(itemKey)) { StatsManager.instance.itemsPurchased[itemKey] = 0; StatsManager.instance.itemsPurchasedTotal[itemKey] = 0; } int num = StatsManager.instance.itemsPurchased[itemKey]; int num2 = StatsManager.instance.itemsPurchasedTotal[itemKey]; if (num >= 10) { Plugin.Logger.LogInfo((object)$"Already at crystal limit: {num}/{10}"); return; } StatsManager.instance.itemsPurchased[itemKey] = num + 1; StatsManager.instance.itemsPurchasedTotal[itemKey] = num2 + 1; Plugin.Logger.LogInfo((object)$"Updated stats for '{itemKey}': Purchased={StatsManager.instance.itemsPurchased[itemKey]}/{10}, Total={StatsManager.instance.itemsPurchasedTotal[itemKey]}"); UpdateChargingStationStats(itemKey, num + 1); if (GameManager.Multiplayer() && (Object)(object)PunManager.instance != (Object)null) { PunManager.instance.UpdateStat("itemsPurchased", itemKey, StatsManager.instance.itemsPurchased[itemKey]); PunManager.instance.UpdateStat("itemsPurchasedTotal", itemKey, StatsManager.instance.itemsPurchasedTotal[itemKey]); } UpdateChargingStationVisuals(num + 1); if ((Object)(object)playerAvatar.photonView != (Object)null && playerAvatar.photonView.IsMine) { ShowCollectionNotification(playerAvatar, displayName, fromExtraction: true, num + 1); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error updating Power Crystal stats (extraction method): {arg}"); } } private static void UpdateChargingStationStats(string itemKey, int newCrystalCount) { try { newCrystalCount = Mathf.Min(newCrystalCount, 10); if (StatsManager.instance.runStats.ContainsKey("chargingStationCharge")) { StatsManager.instance.runStats["chargingStationCharge"] = newCrystalCount; } else { StatsManager.instance.runStats.Add("chargingStationCharge", newCrystalCount); } int num = 100; int num2 = 10; int num3 = Mathf.Min(newCrystalCount * num2, num); int num4 = num; if (StatsManager.instance.runStats.ContainsKey("chargingStationChargeTotal")) { num4 = StatsManager.instance.runStats["chargingStationChargeTotal"]; } else { StatsManager.instance.runStats.Add("chargingStationChargeTotal", num3); } if (num4 < num3) { StatsManager.instance.runStats["chargingStationChargeTotal"] = num3; } Plugin.Logger.LogInfo((object)string.Format("Updated charging station: Crystals={0}/{1}, Capacity={2}", newCrystalCount, 10, StatsManager.instance.runStats["chargingStationChargeTotal"])); if (StatsManager.instance.itemDictionary.ContainsKey(itemKey)) { Item val = StatsManager.instance.itemDictionary[itemKey]; if ((Object)(object)val != (Object)null) { StatsManager.instance.SetItemPurchase(val, newCrystalCount); } } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error updating charging station stats (extraction method): {arg}"); } } private static void UpdateChargingStationVisuals(int newCrystalCount) { try { newCrystalCount = Mathf.Min(newCrystalCount, 10); ChargingStation instance = ChargingStation.instance; if ((Object)(object)instance != (Object)null) { FieldInfo field = typeof(ChargingStation).GetField("chargeInt", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(instance, newCrystalCount); } Plugin.Logger.LogInfo((object)$"Updated charging station visuals: {newCrystalCount}/{10} crystals"); } } catch (Exception arg) { Plugin.Logger.LogError((object)$"Error updating charging station visuals (extraction method): {arg}"); } } private static PlayerAvatar FindClosestPlayer(Vector3 position) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) try { PlayerAvatar result = null; float num = float.MaxValue; if (GameManager.Multiplayer()) { foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if (!((Object)(object)player == (Object)null) && !player.isDisabled) { float num2 = Vector3.Distance(((Component)player).transform.position, position); if (num2 < num) { num = num2; result = player; } } } } else { PlayerController instance = PlayerController.instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.playerAvatarScript != (Object)null) { result = instance.playerAvatarScript; } } return result; } catch (Exception) { return null; } } private static void ShowCollectionNotification(PlayerAvatar playerAvatar, string crystalName, bool fromExtraction, int newCount) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) try { string text = (fromExtraction ? "Extracted" : "Collected"); string text2 = $"{crystalName} {text}! ({newCount}/{10} to Charging Station)"; Type type = Type.GetType("ItemInfoExtraUI, Assembly-CSharp"); if (type != null) { PropertyInfo property = type.GetProperty("instance", BindingFlags.Static | BindingFlags.Public); if (property != null) { object value = property.GetValue(null); if (value != null) { MethodInfo method = type.GetMethod("ItemInfoText", new Type[2] { typeof(string), typeof(Color) }); if (method != null) { Color val = ((newCount < 10) ? Color.green : Color.yellow); method.Invoke(value, new object[2] { text2, val }); return; } } } } Plugin.Logger.LogInfo((object)text2); } catch (Exception arg) { Debug.LogError((object)$"Error showing notification: {arg}"); } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Jettcodey.ExtractCrystalsInLevels"; public const string PLUGIN_NAME = "ExtractCrystalsInLevels"; public const string PLUGIN_VERSION = "1.0.0"; } }