using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("DunGen")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")] [assembly: IgnoresAccessChecksTo("Unity.XR.Management")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("LGUConstellationsBridge")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("4.4.1.0")] [assembly: AssemblyInformationalVersion("4.4.1+8c5521e37f37e3d76518a16d04e5d1051842f105")] [assembly: AssemblyProduct("LGUConstellationsBridge")] [assembly: AssemblyTitle("LGUConstellationsBridge")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("4.4.1.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LGUConstellationsBridge { public static class ConstellationNotification { [CompilerGenerated] private sealed class d__21 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Canvas canvas; public string constellationName; private GameObject 5__2; private RawImage 5__3; private GameObject 5__4; private CanvasGroup 5__5; private float 5__6; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__21(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; 5__4 = null; 5__5 = null; <>1__state = -2; } private bool MoveNext() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007d: 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) //IL_00a2: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0341: Unknown result type (might be due to invalid IL or missing references) //IL_03ab: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_04cf: Unknown result type (might be due to invalid IL or missing references) //IL_051b: Unknown result type (might be due to invalid IL or missing references) //IL_05e0: Unknown result type (might be due to invalid IL or missing references) //IL_05fc: Unknown result type (might be due to invalid IL or missing references) //IL_05c9: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: { <>1__state = -1; 5__2 = new GameObject("LGU_ConstellationNotification"); 5__2.transform.SetParent(((Component)canvas).transform, false); _activeRoot = 5__2; RectTransform obj = 5__2.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; 5__2.transform.SetAsLastSibling(); GameObject val = new GameObject("Flash"); val.transform.SetParent(5__2.transform, false); 5__3 = val.AddComponent(); ((Graphic)5__3).raycastTarget = false; RectTransform component = val.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; ((Graphic)5__3).color = new Color(FlashBaseColor.r, FlashBaseColor.g, FlashBaseColor.b, 0f); 5__4 = new GameObject("Banner"); 5__4.transform.SetParent(5__2.transform, false); RectTransform obj2 = 5__4.AddComponent(); obj2.anchorMin = new Vector2(0.2f, 0.44f); obj2.anchorMax = new Vector2(0.8f, 0.56f); obj2.offsetMin = Vector2.zero; obj2.offsetMax = Vector2.zero; Image obj3 = 5__4.AddComponent(); ((Graphic)obj3).color = BannerBgColor; ((Graphic)obj3).raycastTarget = false; Outline obj4 = 5__4.AddComponent(); ((Shadow)obj4).effectColor = BorderColor; ((Shadow)obj4).effectDistance = new Vector2(1f, -1f); ((Shadow)obj4).useGraphicAlpha = false; GameObject val2 = new GameObject("Line1"); val2.transform.SetParent(5__4.transform, false); RectTransform obj5 = val2.AddComponent(); obj5.anchorMin = new Vector2(0f, 0.52f); obj5.anchorMax = new Vector2(1f, 0.92f); obj5.offsetMin = Vector2.zero; obj5.offsetMax = Vector2.zero; TextMeshProUGUI obj6 = val2.AddComponent(); ((TMP_Text)obj6).text = "CONSTELLATION UNLOCKED"; ((TMP_Text)obj6).fontSize = 16f; ((TMP_Text)obj6).alignment = (TextAlignmentOptions)514; ((Graphic)obj6).color = Line1Color; ((TMP_Text)obj6).characterSpacing = 3f; ((Graphic)obj6).raycastTarget = false; ((TMP_Text)obj6).enableWordWrapping = false; GameObject val3 = new GameObject("Line2"); val3.transform.SetParent(5__4.transform, false); RectTransform obj7 = val3.AddComponent(); obj7.anchorMin = new Vector2(0f, 0.08f); obj7.anchorMax = new Vector2(1f, 0.5f); obj7.offsetMin = Vector2.zero; obj7.offsetMax = Vector2.zero; TextMeshProUGUI obj8 = val3.AddComponent(); ((TMP_Text)obj8).text = constellationName.ToUpper(); ((TMP_Text)obj8).fontSize = 28f; ((TMP_Text)obj8).fontStyle = (FontStyles)1; ((TMP_Text)obj8).alignment = (TextAlignmentOptions)514; ((Graphic)obj8).color = Line2Color; ((Graphic)obj8).raycastTarget = false; ((TMP_Text)obj8).enableWordWrapping = false; 5__5 = 5__4.AddComponent(); 5__5.interactable = false; 5__5.blocksRaycasts = false; 5__5.alpha = 0f; 5__4.transform.localScale = new Vector3(0.8f, 0.8f, 1f); 5__6 = 0f; break; } case 1: <>1__state = -1; break; } if (5__6 < 3.4f) { if ((Object)(object)5__2 == (Object)null) { return false; } 5__6 += Time.deltaTime; if (5__6 < 0.05f) { ((Graphic)5__3).color = new Color(FlashBaseColor.r, FlashBaseColor.g, FlashBaseColor.b, 5__6 / 0.05f * 0.4f); } else if (5__6 < 0.2f) { ((Graphic)5__3).color = new Color(FlashBaseColor.r, FlashBaseColor.g, FlashBaseColor.b, 0.4f); } else if (5__6 < 0.8f) { float num = (5__6 - 0.2f) / 0.6f; ((Graphic)5__3).color = new Color(FlashBaseColor.r, FlashBaseColor.g, FlashBaseColor.b, 0.4f * (1f - num)); } else if (((Graphic)5__3).color.a > 0f) { ((Graphic)5__3).color = new Color(FlashBaseColor.r, FlashBaseColor.g, FlashBaseColor.b, 0f); } if (5__6 >= 0.1f) { if (5__5.alpha < 1f) { 5__5.alpha = 1f; } if (5__6 < 0.3f) { float num2 = (5__6 - 0.1f) / 0.20000002f; float num3 = ((num2 < 0.7f) ? Mathf.Lerp(0.8f, 1.05f, num2 / 0.7f) : Mathf.Lerp(1.05f, 1f, (num2 - 0.7f) / 0.3f)); 5__4.transform.localScale = new Vector3(num3, num3, 1f); } else if (5__4.transform.localScale.x != 1f) { 5__4.transform.localScale = Vector3.one; } if (5__6 >= 2.6f) { float num4 = (5__6 - 2.6f) / 0.8000002f; 5__5.alpha = 1f - num4; } } <>2__current = null; <>1__state = 1; return true; } if ((Object)(object)_activeRoot == (Object)(object)5__2) { _activeRoot = null; _activeCoroutine = null; } if ((Object)(object)5__2 != (Object)null) { Object.Destroy((Object)(object)5__2); } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__19 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public List names; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__19(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_0093; } <>1__state = -1; 5__2 = 0; goto IL_00a3; IL_0093: 5__2++; goto IL_00a3; IL_00a3: if (5__2 < names.Count) { Plugin.Log.LogInfo((object)("[Notification] Showing notification for: " + names[5__2])); ShowNotificationImmediate(names[5__2]); if (5__2 < names.Count - 1) { <>2__current = (object)new WaitForSeconds(4.5f); <>1__state = 1; return true; } goto IL_0093; } _sequenceCoroutine = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static int _cachedQuotaSeen = -1; private static HashSet _knownConstellations = new HashSet(StringComparer.OrdinalIgnoreCase); private static Dictionary _quotaThresholds; private static bool _rulesInitialized; private static readonly Regex SectionPattern = new Regex("^\\[Constellation:\\s*(.+?)\\]\\s*$", RegexOptions.Compiled); private static AudioClip _cachedChime; private static Coroutine _activeCoroutine; private static Coroutine _sequenceCoroutine; private static GameObject _activeRoot; private static readonly Color FlashBaseColor = new Color(0f, 40f / 51f, 0f, 0f); private static readonly Color BannerBgColor = new Color(1f / 51f, 1f / 51f, 1f / 51f, 0.9f); private static readonly Color BorderColor = new Color(0f, 40f / 51f, 0f, 1f); private static readonly Color Line1Color = new Color(0f, 40f / 51f, 0f, 1f); private static readonly Color Line2Color = new Color(0f, 1f, 0f, 1f); public static void CheckAndNotify() { if (Plugin.EnableUnlockNotification == null || !Plugin.EnableUnlockNotification.Value) { return; } try { EnsureRulesLoaded(); int num = (((Object)(object)TimeOfDay.Instance != (Object)null) ? TimeOfDay.Instance.timesFulfilledQuota : 0); HashSet hashSet = ComputeUnlockedAtQuota(num); Plugin.Log.LogInfo((object)($"[Notification] Current constellations (quota={num}): " + ((hashSet.Count > 0) ? string.Join(", ", hashSet) : "(none gated)"))); if (_cachedQuotaSeen < 0) { int num2 = Math.Max(0, num - 1); _knownConstellations = ComputeUnlockedAtQuota(num2); _cachedQuotaSeen = num2; Plugin.Log.LogInfo((object)($"[Notification] Seeded cache for quota={num2}: " + ((_knownConstellations.Count > 0) ? string.Join(", ", _knownConstellations) : "(empty)"))); } List list = new List(); foreach (string item in hashSet) { if (!_knownConstellations.Contains(item)) { list.Add(item); } } _knownConstellations = hashSet; _cachedQuotaSeen = num; if (list.Count == 0) { Plugin.Log.LogInfo((object)"[Notification] No new constellations unlocked this quota."); return; } foreach (string item2 in list) { Plugin.Log.LogInfo((object)("[Notification] Newly unlocked: " + item2)); } if (!((Object)(object)Plugin.Instance == (Object)null)) { CancelActive(); _sequenceCoroutine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(ShowNotificationsSequentially(list)); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Notification] CheckAndNotify failed: {arg}"); } } public static void ResetCache() { _knownConstellations.Clear(); _cachedQuotaSeen = -1; Plugin.Log.LogInfo((object)"[Notification] Cache reset."); } private static void EnsureRulesLoaded() { if (_rulesInitialized) { return; } _rulesInitialized = true; _quotaThresholds = new Dictionary(StringComparer.OrdinalIgnoreCase); try { string text = Path.Combine(Paths.ConfigPath, "LethalMoonUnlocks - Constellations.cfg"); if (!File.Exists(text)) { Plugin.Log.LogWarning((object)("[Notification] Config not found: " + text + " — quota-based unlock detection disabled.")); return; } string[] array = File.ReadAllLines(text); string text2 = null; bool result = false; int result2 = 0; for (int i = 0; i < array.Length; i++) { string text3 = array[i].Trim(); Match match = SectionPattern.Match(text3); if (match.Success) { FlushSection(text2, result, result2); text2 = match.Groups[1].Value.Trim(); result = false; result2 = 0; } else { if (text2 == null || text3.StartsWith("#") || string.IsNullOrEmpty(text3)) { continue; } if (text3.StartsWith("Enabled", StringComparison.OrdinalIgnoreCase)) { int num = text3.IndexOf('='); if (num >= 0) { bool.TryParse(text3.Substring(num + 1).Trim(), out result); } } else if (text3.StartsWith("RequiredQuotaCount", StringComparison.OrdinalIgnoreCase)) { int num2 = text3.IndexOf('='); if (num2 >= 0) { int.TryParse(text3.Substring(num2 + 1).Trim(), out result2); } } } } FlushSection(text2, result, result2); Plugin.Log.LogInfo((object)$"[Notification] Parsed {_quotaThresholds.Count} gated constellation(s) from config:"); foreach (KeyValuePair quotaThreshold in _quotaThresholds) { Plugin.Log.LogInfo((object)$"[Notification] {quotaThreshold.Key} -> quota {quotaThreshold.Value}"); } } catch (Exception ex) { Plugin.Log.LogError((object)("[Notification] Failed to parse unlock rules: " + ex.Message)); } } private static void FlushSection(string name, bool enabled, int quota) { if (name != null && enabled && quota > 0) { _quotaThresholds[name] = quota; } } private static HashSet ComputeUnlockedAtQuota(int quota) { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); if (_quotaThresholds == null) { return hashSet; } foreach (KeyValuePair quotaThreshold in _quotaThresholds) { if (quotaThreshold.Value <= quota) { hashSet.Add(quotaThreshold.Key); } } return hashSet; } [IteratorStateMachine(typeof(d__19))] private static IEnumerator ShowNotificationsSequentially(List names) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__19(0) { names = names }; } private static void ShowNotificationImmediate(string constellationName) { if ((Object)(object)HUDManager.Instance == (Object)null || (Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null) { Plugin.Log.LogDebug((object)"[Notification] Skipping — HUD not available"); return; } Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if ((Object)(object)canvas == (Object)null) { Plugin.Log.LogDebug((object)"[Notification] Skipping — HUD canvas not available"); return; } if (_activeCoroutine != null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(_activeCoroutine); _activeCoroutine = null; } if ((Object)(object)_activeRoot != (Object)null) { Object.Destroy((Object)(object)_activeRoot); _activeRoot = null; } AudioClip orCreateChime = GetOrCreateChime(); if ((Object)(object)orCreateChime != (Object)null && (Object)(object)HUDManager.Instance.UIAudio != (Object)null) { HUDManager.Instance.UIAudio.PlayOneShot(orCreateChime, Plugin.NotificationVolume.Value); } _activeCoroutine = ((MonoBehaviour)Plugin.Instance).StartCoroutine(RunNotification(constellationName, canvas)); } [IteratorStateMachine(typeof(d__21))] private static IEnumerator RunNotification(string constellationName, Canvas canvas) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__21(0) { constellationName = constellationName, canvas = canvas }; } private static void CancelActive() { if (!((Object)(object)Plugin.Instance == (Object)null)) { if (_sequenceCoroutine != null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(_sequenceCoroutine); _sequenceCoroutine = null; } if (_activeCoroutine != null) { ((MonoBehaviour)Plugin.Instance).StopCoroutine(_activeCoroutine); _activeCoroutine = null; } if ((Object)(object)_activeRoot != (Object)null) { Object.Destroy((Object)(object)_activeRoot); _activeRoot = null; } } } private static AudioClip GetOrCreateChime() { if ((Object)(object)_cachedChime != (Object)null) { return _cachedChime; } int num = 22050; float[] array = new float[num]; AddSineTone(array, 44100, 600f, 0f, 0.12f, 0.01f, 8f, 0.5f); AddSineTone(array, 44100, 900f, 0.08f, 0.18f, 0.01f, 6f, 0.5f); int num2 = 8820; for (int i = num2; i < num; i++) { float num3 = (float)(i - num2) / 44100f; array[i] += (Random.value * 2f - 1f) * 0.05f * Mathf.Exp((0f - num3) * 15f); } float num4 = 0f; for (int j = 0; j < num; j++) { if (Mathf.Abs(array[j]) > num4) { num4 = Mathf.Abs(array[j]); } } if (num4 > 0.9f) { float num5 = 0.9f / num4; for (int k = 0; k < num; k++) { array[k] *= num5; } } _cachedChime = AudioClip.Create("LGU_ConstellationUnlock_Chime", num, 1, 44100, false); _cachedChime.SetData(array, 0); Plugin.Log.LogInfo((object)$"[Notification] Generated procedural unlock chime ({num} samples)"); return _cachedChime; } private static void AddSineTone(float[] data, int sampleRate, float freqHz, float startSec, float durationSec, float attackSec, float decayRate, float amplitude) { int num = (int)((float)sampleRate * startSec); int num2 = (int)((float)sampleRate * durationSec); float num3 = 0f; for (int i = 0; i < num2; i++) { int num4 = num + i; if (num4 < data.Length) { float num5 = (float)i / (float)sampleRate; num3 += freqHz / (float)sampleRate; float num6 = Mathf.Sin(num3 * 2f * MathF.PI); float num7 = Mathf.Clamp01(num5 / attackSec); float num8 = Mathf.Exp((0f - num5) * decayRate); data[num4] += num6 * (num7 * num8) * amplitude; continue; } break; } } } [HarmonyPatch(typeof(Terminal), "Start")] internal static class HelpPagePatch { [CompilerGenerated] private sealed class d__8 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Terminal terminal; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__8(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; DoRewrite(terminal); return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static readonly Regex MoonsBlockPattern = new Regex(">MOONS\\r?\\n[^\\r\\n]*(\\r?\\n){1,2}", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex ConstellationsBlockPattern = new Regex(">CONSTELLATIONS\\r?\\n[^\\r\\n]*(\\r?\\n){1,2}", RegexOptions.IgnoreCase | RegexOptions.Compiled); private static readonly Regex FirstHeadingPattern = new Regex("^[ \\t]*>[A-Z][A-Z_ ]*\\r?\\n", RegexOptions.Multiline | RegexOptions.Compiled); private const string MoonsRestoredBlock = ">MOONS\nTo see the list of moons the autopilot can route to.\n\n"; private static bool _alreadyProcessed; private static ManualLogSource Log => Plugin.Log; [HarmonyPostfix] private static void Postfix(Terminal __instance) { try { if (!((Object)(object)__instance == (Object)null) && !_alreadyProcessed) { ((MonoBehaviour)__instance).StartCoroutine(DeferredRewrite(__instance)); } } catch (Exception arg) { ManualLogSource log = Log; if (log != null) { log.LogError((object)$"[Bridge.Help] Postfix exception: {arg}"); } } } [IteratorStateMachine(typeof(d__8))] private static IEnumerator DeferredRewrite(Terminal terminal) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(0) { terminal = terminal }; } private static void DoRewrite(Terminal terminal) { try { if ((Object)(object)terminal == (Object)null || (Object)(object)terminal.terminalNodes == (Object)null) { return; } if (terminal.terminalNodes.specialNodes == null || terminal.terminalNodes.specialNodes.Count <= 13) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[Bridge.Help] specialNodes shape unexpected - skipping rewrite."); } return; } TerminalNode val = terminal.terminalNodes.specialNodes[13]; if ((Object)(object)val == (Object)null) { return; } string text = val.displayText ?? string.Empty; if (string.IsNullOrEmpty(text)) { return; } bool flag = false; if (MoonsBlockPattern.IsMatch(text)) { text = MoonsBlockPattern.Replace(text, string.Empty, 1); flag = true; ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"[Bridge.Help] Stripped >MOONS block from help page."); } } else { ManualLogSource log3 = Log; if (log3 != null) { log3.LogInfo((object)"[Bridge.Help] No >MOONS block found - skipping strip."); } } Match match = ConstellationsBlockPattern.Match(text); if (match.Success) { Match match2 = FirstHeadingPattern.Match(text); if (match2.Success && match2.Index != match.Index) { string value = match.Value; string text2 = text.Remove(match.Index, match.Length); Match match3 = FirstHeadingPattern.Match(text2); int startIndex = (match3.Success ? match3.Index : 0); text = text2.Insert(startIndex, value); flag = true; ManualLogSource log4 = Log; if (log4 != null) { log4.LogInfo((object)"[Bridge.Help] Moved >CONSTELLATIONS block to top of help page."); } } else if (match2.Success) { ManualLogSource log5 = Log; if (log5 != null) { log5.LogInfo((object)"[Bridge.Help] >CONSTELLATIONS already at top - no reorder needed."); } } } else { ManualLogSource log6 = Log; if (log6 != null) { log6.LogInfo((object)"[Bridge.Help] No >CONSTELLATIONS block found - skipping reorder."); } } if (Plugin.ReaddMoonsBelowConstellations != null && Plugin.ReaddMoonsBelowConstellations.Value) { Match match4 = ConstellationsBlockPattern.Match(text); if (match4.Success && !MoonsBlockPattern.IsMatch(text)) { int startIndex2 = match4.Index + match4.Length; text = text.Insert(startIndex2, ">MOONS\nTo see the list of moons the autopilot can route to.\n\n"); flag = true; ManualLogSource log7 = Log; if (log7 != null) { log7.LogInfo((object)"[Bridge.Help] Re-added >MOONS block below >CONSTELLATIONS (config opt-in)."); } } } if (flag) { val.displayText = text; } _alreadyProcessed = true; } catch (Exception arg) { ManualLogSource log8 = Log; if (log8 != null) { log8.LogError((object)$"[Bridge.Help] DoRewrite exception: {arg}"); } } } } [HarmonyPatch] internal static class MoonSelectionClosePatch { [CompilerGenerated] private sealed class d__4 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__4(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "darmuhsTerminalStuff"); if (assembly == null) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[Bridge.MoonClose] TerminalStuff not loaded - skipping moon-close patch."); } return false; } Type type = assembly.GetType("TerminalStuff.MoonsTweaks.MoonInfo"); if (type == null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"[Bridge.MoonClose] MoonInfo type not found - skipping."); } return false; } MethodInfo method = type.GetMethod("SelectThisMoon", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)"[Bridge.MoonClose] SelectThisMoon method not found on MoonInfo - skipping."); } return false; } _moonsPlusMenuField = assembly.GetType("TerminalStuff.MoonsTweaks.MoonsPlus")?.GetField("MoonsPlusMenu", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (_moonsPlusMenuField == null) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)"[Bridge.MoonClose] MoonsPlusMenu field not found - skipping."); } return false; } Type type2 = _moonsPlusMenuField.FieldType; while (type2 != null && type2 != typeof(object)) { _exitMenuMethod = type2.GetMethod("ExitMenu", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(bool) }, null); if (_exitMenuMethod != null) { break; } type2 = type2.BaseType; } if (_exitMenuMethod == null) { ManualLogSource log5 = Log; if (log5 != null) { log5.LogWarning((object)"[Bridge.MoonClose] ExitMenu(bool) not found on MoonsPlusMenu hierarchy - skipping."); } return false; } ManualLogSource log6 = Log; if (log6 != null) { log6.LogInfo((object)"[Bridge.MoonClose] Patching MoonInfo.SelectThisMoon."); } <>2__current = method; <>1__state = 1; return true; } case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__4(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private static MethodInfo _exitMenuMethod; private static FieldInfo _moonsPlusMenuField; private static ManualLogSource Log => Plugin.Log; [IteratorStateMachine(typeof(d__4))] private static IEnumerable TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__4(-2); } [HarmonyPostfix] private static void Postfix() { try { if ((Object)(object)StartOfRound.Instance == (Object)null || !StartOfRound.Instance.travellingToNewLevel) { return; } object value = _moonsPlusMenuField.GetValue(null); if (value != null) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[Bridge.MoonClose] Moon route succeeded - closing MoonsPlus menu."); } _exitMenuMethod.Invoke(value, new object[1] { true }); } } catch (Exception arg) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogError((object)$"[Bridge.MoonClose] Postfix exception: {arg}"); } } } } [HarmonyPatch] internal static class MoonsPlusHeaderPatch { [CompilerGenerated] private sealed class d__3 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "darmuhsTerminalStuff"); if (assembly == null) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[Bridge.Header] TerminalStuff not loaded - skipping MoonsPlus header patch."); } return false; } Type type = assembly.GetType("TerminalStuff.MoonsTweaks.MoonsPlus"); if (type == null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"[Bridge.Header] MoonsPlus type not found - skipping header patch."); } return false; } MethodInfo method = type.GetMethod("SetupBetterMenu", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)"[Bridge.Header] SetupBetterMenu not found - skipping header patch."); } return false; } BuildConsNameGetter(); ManualLogSource log4 = Log; if (log4 != null) { log4.LogInfo((object)"[Bridge.Header] Patching MoonsPlus.SetupBetterMenu."); } <>2__current = method; <>1__state = 1; return true; } case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__3(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private static Func _consNameGetter; private static ManualLogSource Log => Plugin.Log; [IteratorStateMachine(typeof(d__3))] private static IEnumerable TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(-2); } private static void BuildConsNameGetter() { try { Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "LethalConstellations"); if (assembly == null) { return; } Type type = assembly.GetType("LethalConstellations.PluginCore.Collections"); if (type == null) { return; } FieldInfo currentField = type.GetField("CurrentConstellationCM", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (currentField == null) { return; } FieldInfo consNameField = currentField.FieldType.GetField("consName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(consNameField == null)) { _consNameGetter = delegate { object value = currentField.GetValue(null); return (value == null) ? string.Empty : (((string)consNameField.GetValue(value)) ?? string.Empty); }; } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[Bridge.Header] Could not build consName getter: " + ex.Message)); } } } private static PropertyInfo FindHeaderProperty(object instance) { if (instance == null) { return null; } Type type = instance.GetType(); while (type != null && type != typeof(object)) { PropertyInfo property = type.GetProperty("Header", BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(Func) && property.CanWrite) { return property; } type = type.BaseType; } return null; } [HarmonyPostfix] private static void Postfix() { try { Type type = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "darmuhsTerminalStuff")?.GetType("TerminalStuff.MoonsTweaks.MoonsPlus"); if (type == null) { return; } string[] obj = new string[3] { "AllMoons", "GoodWeatherMoons", "AffordableMoons" }; int num = 0; string[] array = obj; foreach (string text in array) { object obj2 = type.GetField(text, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); if (obj2 == null) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)("[Bridge.Header] Field " + text + " not found or null - skipping.")); } continue; } PropertyInfo propertyInfo = FindHeaderProperty(obj2); if (propertyInfo == null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[Bridge.Header] Could not find Header property on " + obj2.GetType().FullName + ".")); } continue; } Func value = delegate { string text2 = _consNameGetter?.Invoke() ?? string.Empty; return string.IsNullOrEmpty(text2) ? "===== Select a Moon =====\n\n" : ("===== " + text2.ToUpperInvariant() + " =====\n\n"); }; propertyInfo.SetValue(obj2, value); num++; ManualLogSource log3 = Log; if (log3 != null) { log3.LogDebug((object)("[Bridge.Header] Replaced header on " + text + ".")); } } if (num > 0) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogInfo((object)$"[Bridge.Header] MoonsPlus headers now show current constellation ({num} pages)."); } } else { ManualLogSource log5 = Log; if (log5 != null) { log5.LogWarning((object)"[Bridge.Header] No headers were rewritten - constellation name will not appear."); } } } catch (Exception arg) { ManualLogSource log6 = Log; if (log6 != null) { log6.LogError((object)$"[Bridge.Header] Postfix exception: {arg}"); } } } } [BepInPlugin("com.lawson.lguconstellationsbridge", "LGUConstellationsBridge", "4.5.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.lawson.lguconstellationsbridge"; public const string PluginName = "LGUConstellationsBridge"; public const string PluginVersion = "4.5.0"; internal static ManualLogSource Log; internal static ConfigEntry ReaddMoonsBelowConstellations; internal static ConfigEntry EnableUnlockNotification; internal static ConfigEntry NotificationVolume; private Harmony _harmony; public static Plugin Instance { get; private set; } private void Awake() { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"LGUConstellationsBridge v4.5.0 loading..."); ReaddMoonsBelowConstellations = ((BaseUnityPlugin)this).Config.Bind("Help", "ReaddMoonsBelowConstellations", false, "If true, the help page will show >MOONS again as a second entry directly under >CONSTELLATIONS. Default off so players are funneled through constellations."); EnableUnlockNotification = ((BaseUnityPlugin)this).Config.Bind("Notifications", "EnableUnlockNotification", true, "Show a green flash + chime when a constellation is unlocked."); NotificationVolume = ((BaseUnityPlugin)this).Config.Bind("Notifications", "NotificationVolume", 1f, new ConfigDescription("Volume multiplier for the constellation unlock chime (0.0 – 1.0).", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); _harmony = new Harmony("com.lawson.lguconstellationsbridge"); SafePatchAll(typeof(TravelToNewConstellationPatch)); SafePatchAll(typeof(ChangeLevelBlockPatch)); SafePatchAll(typeof(MoonsPlusHeaderPatch)); SafePatchAll(typeof(MoonSelectionClosePatch)); SafePatchAll(typeof(HelpPagePatch)); Log.LogInfo((object)"LGUConstellationsBridge ready."); } private void SafePatchAll(Type type) { try { _harmony.PatchAll(type); } catch (Exception ex) { Log.LogWarning((object)("PatchAll(" + type.Name + ") failed: " + ex.Message)); } } } [HarmonyPatch] internal static class TravelToNewConstellationPatch { [CompilerGenerated] private sealed class d__8 : IEnumerable, IEnumerable, IEnumerator, IEnumerator, IDisposable { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; MethodBase IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__8(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "LethalConstellations"); if (assembly == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[Bridge] LethalConstellations assembly not loaded - bridge will not patch."); } return false; } Type type = assembly.GetType("LethalConstellations.PluginCore.MenuStuff"); if (type == null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"[Bridge] Could not find LethalConstellations.PluginCore.MenuStuff."); } return false; } MethodInfo method = type.GetMethod("TravelToNewConstellation", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(int), typeof(int) }, null); if (method == null) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)"[Bridge] Could not find MenuStuff.TravelToNewConstellation(int, int)."); } return false; } _inMenuField = type.GetField("ConstellationsMenu", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.FieldType.GetField("inMenu", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _confirmationCheckField = type.GetField("ConfirmationCheck", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); Assembly assembly2 = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "darmuhsTerminalStuff"); _enterMoonsMenuMethod = (assembly2?.GetType("TerminalStuff.MoonsTweaks.MoonsPlus"))?.GetMethod("EnterMoonsMenu", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (_enterMoonsMenuMethod != null) { _moonsPlusAvailable = true; ManualLogSource log4 = Log; if (log4 != null) { log4.LogInfo((object)"[Bridge] MoonsPlus.EnterMoonsMenu found - constellation picks will route to MoonsPlus."); } } else if (assembly2 == null) { ManualLogSource log5 = Log; if (log5 != null) { log5.LogInfo((object)"[Bridge] TerminalStuff not loaded - constellation picks will land on vanilla moons."); } } else { ManualLogSource log6 = Log; if (log6 != null) { log6.LogWarning((object)"[Bridge] TerminalStuff loaded but MoonsPlus not found - falling back to vanilla moons."); } } BuildConsNameGetter(assembly); ManualLogSource log7 = Log; if (log7 != null) { log7.LogInfo((object)"[Bridge] Patching MenuStuff.TravelToNewConstellation."); } <>2__current = method; <>1__state = 1; return true; } case 1: <>1__state = -1; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new d__8(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } private static FieldInfo _confirmationCheckField; private static FieldInfo _inMenuField; private static MethodInfo _enterMoonsMenuMethod; private static bool _moonsPlusAvailable; private static Func _currentConsNameGetter; internal static bool BlockNextChangeLevel; private static ManualLogSource Log => Plugin.Log; [IteratorStateMachine(typeof(d__8))] private static IEnumerable TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(-2); } [HarmonyPrefix] private static void Prefix() { BlockNextChangeLevel = true; ManualLogSource log = Log; if (log != null) { log.LogDebug((object)"[Bridge] Block flag set - next ChangeLevelServerRpc will be skipped."); } } [HarmonyPostfix] private static void Postfix(int getPrice, int indexNum) { try { BlockNextChangeLevel = false; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)$"[Bridge] TravelToNewConstellation completed (price={getPrice}, index={indexNum})."); } ClearLcMenuState(); if (_moonsPlusAvailable && _enterMoonsMenuMethod != null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"[Bridge] Routing to MoonsPlus.EnterMoonsMenu."); } _enterMoonsMenuMethod.Invoke(null, null); } else { ManualLogSource log3 = Log; if (log3 != null) { log3.LogInfo((object)"[Bridge] No MoonsPlus available - menu will close to default ExitPage."); } } } catch (Exception arg) { BlockNextChangeLevel = false; ManualLogSource log4 = Log; if (log4 != null) { log4.LogError((object)$"[Bridge] Postfix exception: {arg}"); } } } private static void BuildConsNameGetter(Assembly lcAsm) { try { Type type = lcAsm?.GetType("LethalConstellations.PluginCore.Collections"); if (type == null) { return; } FieldInfo currentField = type.GetField("CurrentConstellationCM", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (currentField == null) { return; } FieldInfo consNameField = currentField.FieldType.GetField("consName", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(consNameField == null)) { _currentConsNameGetter = delegate { object value = currentField.GetValue(null); return (value == null) ? null : (consNameField.GetValue(value) as string); }; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[Bridge] Collections.CurrentConstellationCM.consName getter built."); } } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[Bridge] Could not build constellation name getter: " + ex.Message)); } } } private static void ClearLcMenuState() { try { object obj = (AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "LethalConstellations")?.GetType("LethalConstellations.PluginCore.MenuStuff"))?.GetField("ConstellationsMenu", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); if (obj != null && _inMenuField != null) { _inMenuField.SetValue(obj, false); } if (_confirmationCheckField != null) { _confirmationCheckField.SetValue(null, false); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[Bridge] ClearLcMenuState failed (non-fatal): " + ex.Message)); } } } } [HarmonyPatch(typeof(StartOfRound), "ChangeLevelServerRpc", new Type[] { typeof(int), typeof(int) })] internal static class ChangeLevelBlockPatch { private static ManualLogSource Log => Plugin.Log; [HarmonyPrefix] private static bool Prefix(int levelID, int newGroupCreditsAmount) { if (TravelToNewConstellationPatch.BlockNextChangeLevel) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)($"[Bridge] Blocking ChangeLevelServerRpc(levelID={levelID}, credits={newGroupCreditsAmount}) " + "during constellation pick - keeping ship in place.")); } return false; } return true; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }