using 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";
}
}