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 LootPulse v1.0.7
plugins/HiarlyScripter-LootPulse/LootPulse.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Threading; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; 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("LootPulse")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+775dd9c5dfdb8222af9eee00db9dd7384abd60f0")] [assembly: AssemblyProduct("LootPulse")] [assembly: AssemblyTitle("LootPulse")] [assembly: AssemblyVersion("1.0.0.0")] namespace LootPulse; [BepInPlugin("com.hiarlyscripter.repo.lootpulse", "LootPulse", "1.0.6")] public sealed class LootPulsePlugin : BaseUnityPlugin { internal static ConfigEntry<KeyCode> ScanKey; internal static ConfigEntry<float> ScanRange; internal static ConfigEntry<float> CooldownSeconds; internal static ConfigEntry<bool> EnableVisualBrackets; internal static ConfigEntry<bool> EnableMapIcons; internal static ConfigEntry<bool> RequireLevelOrRun; internal static ConfigEntry<bool> VerboseLogging; private float _lastScanTime = -999f; private int _lastTickFrame = -1; private bool _harmonyLoopLogged; private bool _pluginLoopLogged; private static string _patchedMethodName; private static bool _discoverApiChecked; private static MethodInfo _discoverWithState; private static MethodInfo _discoverNoParam; private static object _discoverStateValue; internal static LootPulsePlugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; ScanKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Scanner", "ScanKey", (KeyCode)102, "Key that triggers the valuable scanner."); ScanRange = ((BaseUnityPlugin)this).Config.Bind<float>("Scanner", "ScanRange", 30f, new ConfigDescription("Detection radius in meters.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>())); CooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Scanner", "CooldownSeconds", 4f, new ConfigDescription("Minimum seconds between consecutive scans.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); EnableVisualBrackets = ((BaseUnityPlugin)this).Config.Bind<bool>("Scanner", "EnableVisualBrackets", true, "Display visual discovery brackets on valuables found."); EnableMapIcons = ((BaseUnityPlugin)this).Config.Bind<bool>("Scanner", "EnableMapIcons", true, "Add valuable icon to the map when scanning."); RequireLevelOrRun = ((BaseUnityPlugin)this).Config.Bind<bool>("Scanner", "RequireLevelOrRun", true, "Only scan during active runs (generated level). Disable only for testing outside a level."); VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Scanner", "VerboseLogging", false, "Log details for each individually processed item."); Log.LogInfo((object)$"v1.0.6 loaded. Press {ScanKey.Value} to scan valuables."); Log.LogInfo((object)($"Config | key={ScanKey.Value} | range={ScanRange.Value} | cooldown={CooldownSeconds.Value} | " + $"visualBrackets={EnableVisualBrackets.Value} | mapIcons={EnableMapIcons.Value} | " + $"requireLevelOrRun={RequireLevelOrRun.Value} | verbose={VerboseLogging.Value}")); Assembly executingAssembly = Assembly.GetExecutingAssembly(); Log.LogInfo((object)"Build marker: v1.0.6-release"); Log.LogInfo((object)("Assembly location: " + executingAssembly.Location)); try { Log.LogInfo((object)$"Assembly file time UTC: {File.GetLastWriteTimeUtc(executingAssembly.Location):yyyy-MM-dd HH:mm:ss}"); } catch { } InstallHarmonyPatch(new Harmony("com.hiarlyscripter.repo.lootpulse")); } private void Update() { if (!_pluginLoopLogged) { _pluginLoopLogged = true; Log.LogInfo((object)"Update loop active. (plugin MonoBehaviour)"); } Tick("Plugin.Update"); } internal void TickFromGameLoop(string source) { if (!_harmonyLoopLogged) { _harmonyLoopLogged = true; Log.LogInfo((object)("Harmony game loop active: " + source)); } Tick(source); } private void Tick(string source) { //IL_001c: 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_0036: Invalid comparison between Unknown and I4 //IL_0053: Unknown result type (might be due to invalid IL or missing references) int frameCount = Time.frameCount; if (frameCount == _lastTickFrame) { return; } _lastTickFrame = frameCount; bool keyDown = Input.GetKeyDown(ScanKey.Value); if (!keyDown && (int)ScanKey.Value != 102) { keyDown = Input.GetKeyDown((KeyCode)102); } if (!keyDown) { return; } Log.LogInfo((object)$"Scan key detected: {ScanKey.Value} | source={source}"); float time = Time.time; float num = time - _lastScanTime; if (num < CooldownSeconds.Value) { Log.LogInfo((object)$"Scan blocked: cooldown active ({CooldownSeconds.Value - num:F1}s remaining)"); return; } if (RequireLevelOrRun.Value) { bool flag = false; try { flag = SemiFunc.RunIsLevel(); } catch (Exception ex) { Log.LogWarning((object)("RunIsLevel check failed (" + ex.Message + "). Proceeding without validation.")); flag = true; } if (!flag) { Log.LogInfo((object)"Scan blocked: not in active level/run (RequireLevelOrRun=true)"); return; } } _lastScanTime = time; RunScan(); } private static void InstallHarmonyPatch(Harmony harmony) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown (string, string)[] obj = new(string, string)[3] { ("GameDirector", "Update"), ("PlayerAvatar", "Update"), ("PlayerController", "Update") }; HarmonyMethod val = new HarmonyMethod(typeof(LootPulsePlugin).GetMethod("HarmonyTickPostfix", BindingFlags.Static | BindingFlags.NonPublic)); (string, string)[] array = obj; for (int i = 0; i < array.Length; i++) { var (text, text2) = array[i]; try { Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int j = 0; j < assemblies.Length; j++) { type = assemblies[j].GetType(text); if (type != null) { break; } } if (type == null) { Log.LogWarning((object)("Harmony fallback: type not found — " + text)); continue; } MethodInfo method = type.GetMethod(text2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method == null) { Log.LogWarning((object)("Harmony fallback: method not found — " + text + "." + text2)); continue; } harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); _patchedMethodName = text + "." + text2; Log.LogInfo((object)("Harmony tick patch installed: " + _patchedMethodName)); string watchedMethod = _patchedMethodName; ThreadPool.QueueUserWorkItem(delegate { Thread.Sleep(60000); if ((Object)(object)Instance != (Object)null && !Instance._harmonyLoopLogged) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("WARNING: Harmony patch installed but no game loop tick observed yet. Patched method: " + watchedMethod)); } } }); return; } catch (Exception ex) { Log.LogWarning((object)("Harmony patch failed for " + text + "." + text2 + ": " + ex.Message)); } } Log.LogError((object)"ERROR: no valid game loop method found. LootPulse cannot scan."); } private static void HarmonyTickPostfix() { Instance?.TickFromGameLoop(_patchedMethodName); } private void RunScan() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) Vector3 zero = Vector3.zero; try { PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val == (Object)null) { Log.LogInfo((object)"Scan blocked: local player not found"); return; } if ((Object)(object)val.playerTransform == (Object)null) { Log.LogInfo((object)"Scan blocked: local player not found (transform null)"); return; } zero = val.playerTransform.position; } catch (Exception ex) { Log.LogWarning((object)("Scan blocked: local player not found (" + ex.Message + ")")); return; } List<PhysGrabObject> list = null; bool flag = false; try { list = SemiFunc.PhysGrabObjectAllValuablesWithinRange(ScanRange.Value, zero, false, default(LayerMask)); flag = true; } catch (Exception ex2) { Log.LogWarning((object)("PhysGrabObjectAllValuablesWithinRange failed (" + ex2.Message + "). Using fallback.")); try { list = FindValuablesFallback(zero, ScanRange.Value); } catch (Exception ex3) { Log.LogWarning((object)("Scan blocked: scan API unavailable (" + ex3.Message + ")")); return; } } if (list == null) { Log.LogWarning((object)"Scan blocked: scan API unavailable (null result)"); return; } int count = list.Count; int num = 0; int num2 = 0; int num3 = 0; Log.LogInfo((object)($"Scan executed | origin={zero:F1} | range={ScanRange.Value}m | " + string.Format("api={0} | found={1}", flag ? "SemiFunc" : "FindObjectsOfType", count))); foreach (PhysGrabObject item in list) { if ((Object)(object)item == (Object)null) { continue; } try { ValuableObject component = ((Component)item).GetComponent<ValuableObject>(); if ((Object)(object)component == (Object)null) { if (VerboseLogging.Value) { Log.LogDebug((object)("No ValuableObject on: " + ((Object)item).name)); } continue; } if (VerboseLogging.Value) { Log.LogDebug((object)("Processing: " + ((Object)item).name)); } if (EnableVisualBrackets.Value && TryApplyBrackets(component)) { num++; } if (EnableMapIcons.Value && TryAddToMap(component)) { num2++; } } catch (Exception ex4) { num3++; Log.LogWarning((object)("Error processing " + ((item != null) ? ((Object)item).name : null) + ": " + ex4.Message)); } } Log.LogInfo((object)$"Result | brackets={num}/{count} | map={num2}/{count} | errors={num3}"); } private static bool TryApplyBrackets(ValuableObject vo) { try { ResolveDiscoverApi(); if (_discoverWithState != null) { _discoverWithState.Invoke(vo, new object[1] { _discoverStateValue }); return true; } if (_discoverNoParam != null) { _discoverNoParam.Invoke(vo, null); return true; } return false; } catch (Exception ex) { if (VerboseLogging.Value) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)("Discover exception: " + ex.Message)); } } return false; } } private static void ResolveDiscoverApi() { if (_discoverApiChecked) { return; } _discoverApiChecked = true; Type typeFromHandle = typeof(ValuableObject); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public; Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { type = assemblies[i].GetType("ValuableDiscoverGraphic"); if (type != null) { break; } } if (type != null) { Type nestedType = type.GetNestedType("State", BindingFlags.Public); if (nestedType != null && nestedType.IsEnum) { MethodInfo method = typeFromHandle.GetMethod("Discover", bindingAttr, null, new Type[1] { nestedType }, null); if (method != null) { _discoverWithState = method; _discoverStateValue = Enum.Parse(nestedType, "Discover"); ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"Discover API resolved: ValuableObject.Discover(ValuableDiscoverGraphic.State)"); } return; } } } MethodInfo method2 = typeFromHandle.GetMethod("Discover", bindingAttr, null, Type.EmptyTypes, null); if (method2 != null) { _discoverNoParam = method2; ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"Discover API resolved: ValuableObject.Discover() [no-param fallback]"); } } else { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)"Discover API not found in any form. Visual brackets disabled."); } } } private static bool TryAddToMap(ValuableObject vo) { try { Map instance = Map.Instance; if ((Object)(object)instance == (Object)null) { if (VerboseLogging.Value) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)"Map.Instance is null."); } } return false; } instance.AddValuable(vo); return true; } catch (Exception ex) { if (VerboseLogging.Value) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogDebug((object)("Map.AddValuable failed: " + ex.Message)); } } return false; } } private static List<PhysGrabObject> FindValuablesFallback(Vector3 origin, float range) { //IL_002a: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) List<PhysGrabObject> list = new List<PhysGrabObject>(); float num = range * range; ValuableObject[] array = Object.FindObjectsOfType<ValuableObject>(); foreach (ValuableObject val in array) { if ((Object)(object)val == (Object)null) { continue; } Vector3 val2 = ((Component)val).transform.position - origin; if (!(((Vector3)(ref val2)).sqrMagnitude > num)) { PhysGrabObject component = ((Component)val).GetComponent<PhysGrabObject>(); if ((Object)(object)component != (Object)null) { list.Add(component); } } } ManualLogSource log = Log; if (log != null) { log.LogInfo((object)$"Fallback: {list.Count} valuables found via FindObjectsOfType."); } return list; } }