using System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; 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 Pigeon; using Pigeon.Math; using Pigeon.Movement; using Sparroh.UI; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("RedactedNotification")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("RedactedNotification")] [assembly: AssemblyTitle("RedactedNotification")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } public static class HudRepositionClient { private const string ApiTypeName = "HudRepositionAPI"; private static Type _apiType; private static MethodInfo _register; private static MethodInfo _unregister; private static bool _available; public static bool IsAvailable { get { EnsureResolved(); return _available; } } public static void Register(string id, string displayName, RectTransform rect, ConfigEntry anchorX, ConfigEntry anchorY) { if (!_available) { EnsureResolved(force: true); } if (!_available || (Object)(object)rect == (Object)null || anchorX == null || anchorY == null) { return; } try { _register.Invoke(null, new object[5] { id, displayName, rect, anchorX, anchorY }); } catch (Exception ex) { Debug.LogWarning((object)("[HudRepositionClient] Register failed: " + (ex.InnerException?.Message ?? ex.Message))); } } public static void Unregister(string id) { if (!_available) { EnsureResolved(force: true); } if (!_available || string.IsNullOrEmpty(id)) { return; } try { _unregister.Invoke(null, new object[1] { id }); } catch (Exception) { } } private static void EnsureResolved(bool force = false) { if (_available && !force) { return; } _apiType = null; _register = null; _unregister = null; _available = false; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType("HudRepositionAPI", throwOnError: false); if (type != null) { _apiType = type; break; } } catch { } } if (_apiType == null) { return; } MethodInfo[] methods = _apiType.GetMethods(BindingFlags.Static | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (methodInfo.Name == "Register" && parameters.Length == 5 && parameters[0].ParameterType == typeof(string) && parameters[1].ParameterType == typeof(string) && typeof(RectTransform).IsAssignableFrom(parameters[2].ParameterType)) { _register = methodInfo; } else if (methodInfo.Name == "Unregister" && parameters.Length == 1 && parameters[0].ParameterType == typeof(string)) { _unregister = methodInfo; } } _available = _register != null && _unregister != null; } } [HarmonyPatch] public static class RedactedPatches { [HarmonyPatch(typeof(MissionSelectButton), "Setup", new Type[] { typeof(MissionData), typeof(MissionSelectWindow), typeof(bool), typeof(bool), typeof(bool) })] [HarmonyPostfix] private static void MissionSelectButton_Setup_Postfix(MissionSelectButton __instance) { try { if (SparrohPlugin.Scanner != null && !((Object)(object)__instance == (Object)null)) { ref MissionData mission = ref __instance.Mission; SparrohPlugin.Scanner.ObserveMission(ref mission); } } catch { } } [HarmonyPatch(typeof(MissionSelectWindow), "Setup")] [HarmonyPostfix] private static void MissionSelectWindow_Setup_Postfix() { try { SparrohPlugin.Scanner?.ForceRescan(); } catch { } } } [BepInPlugin("sparroh.redactednotification", "RedactedNotification", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [MycoMod(/*Could not decode attribute arguments.*/)] public class SparrohPlugin : BaseUnityPlugin { public const string PluginGUID = "sparroh.redactednotification"; public const string PluginName = "RedactedNotification"; public const string PluginVersion = "1.0.1"; internal static ManualLogSource Logger; private Harmony _harmony; private RedactedHUD _hud; internal static RedactedBoardScanner Scanner { get; private set; } private void Awake() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; try { _harmony = new Harmony("sparroh.redactednotification"); } catch (Exception ex) { Logger.LogError((object)("Failed to create Harmony instance: " + ex.Message)); return; } ConfigFile configFile = ((BaseUnityPlugin)this).Config; try { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, "sparroh.redactednotification.cfg"); fileSystemWatcher.Changed += delegate { try { configFile.Reload(); } catch { } }; fileSystemWatcher.EnableRaisingEvents = true; } catch (Exception ex2) { Logger.LogWarning((object)("Failed to set up config watcher: " + ex2.Message)); } try { Scanner = new RedactedBoardScanner(); _hud = new RedactedHUD(configFile, Scanner); } catch (Exception ex3) { Logger.LogError((object)("Failed to initialize RedactedNotification: " + ex3.Message)); } try { _harmony.PatchAll(); } catch (Exception ex4) { Logger.LogError((object)("Failed to apply Harmony patches: " + ex4.Message)); } Logger.LogInfo((object)"RedactedNotification v1.0.1 loaded."); } private void Update() { try { Scanner?.Update(); } catch (Exception ex) { Logger.LogError((object)("Error in RedactedBoardScanner.Update(): " + ex.Message)); } try { _hud?.UpdateHudVisibility(); } catch (Exception ex2) { Logger.LogError((object)("Error in RedactedHUD.UpdateHudVisibility(): " + ex2.Message)); } try { _hud?.Update(); } catch (Exception ex3) { Logger.LogError((object)("Error in RedactedHUD.Update(): " + ex3.Message)); } } private void OnDestroy() { try { _hud?.OnDestroy(); } catch (Exception ex) { Logger.LogError((object)("Error in RedactedHUD.OnDestroy(): " + ex.Message)); } try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex2) { Logger.LogError((object)("Error unpatching Harmony: " + ex2.Message)); } } } public sealed class RedactedBoardScanner { private int _cachedSeed = int.MinValue; private bool _hasRedactedOnBoard; private int _redactedIndex = -1; private MissionModifier _redactedModifier; private bool _resolveAttempted; private int _matchCount; public bool HasRedactedOnBoard => _hasRedactedOnBoard; public int MatchCount => _matchCount; public MissionModifier RedactedModifier => _redactedModifier; public int RedactedIndex => _redactedIndex; public int LastScannedSeed => _cachedSeed; public bool IsResolved { get { if (_redactedIndex >= 0) { return (Object)(object)_redactedModifier != (Object)null; } return false; } } public void Update() { try { if (!((Object)(object)Global.Instance == (Object)null) && (IsResolved || TryResolveRedacted())) { int missionSelectSeed = Global.MissionSelectSeed; if (missionSelectSeed != _cachedSeed) { _cachedSeed = missionSelectSeed; RescanBoard(missionSelectSeed); } } } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("RedactedBoardScanner.Update failed: " + ex.Message)); } } public void ForceRescan() { if (!((Object)(object)Global.Instance == (Object)null) && (IsResolved || TryResolveRedacted())) { _cachedSeed = Global.MissionSelectSeed; RescanBoard(_cachedSeed); } } public void ObserveMission(ref MissionData mission) { if ((IsResolved || TryResolveRedacted()) && MissionHasRedacted(ref mission) && !_hasRedactedOnBoard) { _hasRedactedOnBoard = true; SparrohPlugin.Logger.LogInfo((object)"ERROR REDACTED observed on mission select board."); } } public bool TryResolveRedacted() { if (IsResolved) { return true; } if ((Object)(object)Global.Instance == (Object)null || Global.Instance.MissionModifiers == null) { return false; } if (_resolveAttempted) { _ = _redactedIndex; _ = 0; } _resolveAttempted = true; WeightedArray missionModifiers = Global.Instance.MissionModifiers; int length = missionModifiers.Length; for (int i = 0; i < length; i++) { MissionModifier val = missionModifiers[i]; if (!((Object)(object)val == (Object)null) && IsErrorRedacted(val)) { _redactedIndex = i; _redactedModifier = val; SparrohPlugin.Logger.LogInfo((object)$"Resolved ERROR REDACTED modifier at index {i} (APIName='{val.APIName}', Name='{SafeName(val)}')."); return true; } } for (int j = 0; j < length; j++) { MissionModifier val2 = missionModifiers[j]; if (!((Object)(object)val2 == (Object)null)) { string text = val2.APIName ?? string.Empty; string text2 = SafeName(val2); string text3 = (text + " " + text2).ToLowerInvariant(); if (text3.Contains("redact") || text3.Contains("error redacted") || text3.Contains("error_redacted")) { _redactedIndex = j; _redactedModifier = val2; SparrohPlugin.Logger.LogInfo((object)$"Resolved ERROR REDACTED modifier (fallback) at index {j} (APIName='{text}')."); return true; } } } return false; } private static string SafeName(MissionModifier mod) { try { return ((mod != null) ? mod.Name : null) ?? string.Empty; } catch { return string.Empty; } } private static bool IsErrorRedacted(MissionModifier mod) { if ((Object)(object)mod == (Object)null) { return false; } string text = (mod.APIName ?? string.Empty).ToLowerInvariant(); if ((text.Contains("error_redacted") || text.Contains("error-redacted") || text == "redacted" || text.Contains("redacted")) && text.Contains("redact")) { return true; } try { string text2 = (mod.Name ?? string.Empty).ToLowerInvariant(); if (text2.Contains("error") && text2.Contains("redact")) { return true; } if (text2 == "error redacted" || text2.Contains("error redacted")) { return true; } } catch { } return false; } private void RescanBoard(int currentSeed) { _hasRedactedOnBoard = false; _matchCount = 0; if ((Object)(object)Global.Instance == (Object)null || Global.Instance.Regions == null) { return; } try { Mission mission = Global.GetMission("intro"); if ((Object)(object)mission != (Object)null && PlayerData.Instance != null && !PlayerData.Instance.HasCompletedMission(mission)) { SparrohPlugin.Logger.LogDebug((object)"Board scan skipped: intro mission not completed."); return; } } catch { } WorldRegion[] regions = Global.Instance.Regions; foreach (WorldRegion val in regions) { if (!((Object)(object)val == (Object)null) && !val.LockRegion) { ScanRegion(val, currentSeed); } } if (_hasRedactedOnBoard) { SparrohPlugin.Logger.LogInfo((object)$"ERROR REDACTED present on mission board (seed={currentSeed}, matches={_matchCount})."); } else { SparrohPlugin.Logger.LogDebug((object)$"Board scan complete (seed={currentSeed}): no ERROR REDACTED."); } } private void ScanRegion(WorldRegion region, int currentSeed) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0198: Unknown result type (might be due to invalid IL or missing references) int[] array = new int[Global.Instance.Missions.Length]; int num = FillValidMissions(region.Flags, array); Random val = default(Random); ((Random)(ref val))..ctor(MathUtil.Squirrel3Hash((region.ID + 3173412) * 71239192, currentSeed)); bool[] array2 = new bool[Global.Instance.Missions.Length]; Random val2 = default(Random); MissionData data = default(MissionData); for (int i = 0; i < 8; i++) { if (num == 0) { num = FillValidMissions(region.Flags, array); } if (num == 0) { break; } int num2 = ((Random)(ref val)).Next() + 1; ((Random)(ref val2))..ctor(MathUtil.Squirrel3Hash(num2, currentSeed)); LevelFlags val3 = region.Flags; bool flag = false; if (i >= 7 && (region.Flags & 0x8000) != 0) { SceneData[] legacyScenes = region.LegacyScenes; if (legacyScenes != null && legacyScenes.Length != 0) { flag = true; val3 = (LevelFlags)(val3 & -32769); for (int num3 = num - 1; num3 >= 0; num3--) { if ((Global.Instance.Missions[array[num3]].MissionFlags & 0x400) == 0) { array[num3] = array[num - 1]; num--; } } } } if (num == 0) { num = FillValidMissions(val3, array); } if (num == 0) { break; } int num4 = ((Random)(ref val2)).Next(num); int num5 = array[num4]; array[num4] = array[num - 1]; num--; array2[num5] = true; Mission val4 = Global.Instance.Missions[num5]; if (!((Object)(object)val4 == (Object)null)) { SceneData[] array3 = ((flag && region.LegacyScenes != null && region.LegacyScenes.Length != 0) ? region.LegacyScenes : region.Scenes); if (array3 != null && array3.Length != 0) { SceneData val5 = array3[((Random)(ref val2)).Next(array3.Length)]; ((MissionData)(ref data))..ctor(num2, val4, region, val5, Global.Instance.DefaultMissionContainer, val4.GetAdditionalData()); CheckAndCount(ref data); } } } for (int j = 0; j < Global.Instance.Missions.Length; j++) { Mission val6 = Global.Instance.Missions[j]; if (!((Object)(object)val6 == (Object)null)) { if ((val6.MissionFlags & 1) == 0 && val6.ShowHiddenMissionInSelectScreen(region)) { int missionSeed = ((Random)(ref val)).Next() + 1; AddSpecialMission(val6, missionSeed, region, currentSeed, spawnInDesignedScene: false); } else if ((val6.MissionFlags & 0x20) != 0 && !array2[j]) { array2[j] = true; int missionSeed2 = ((Random)(ref val)).Next() + 1; bool spawnInDesignedScene = (val6.MissionFlags & 0x400) != 0 && ((Random)(ref val)).NextFloat() <= 0.35f; AddSpecialMission(val6, missionSeed2, region, currentSeed, spawnInDesignedScene); } } } for (int k = 0; k < Global.Instance.Missions.Length; k++) { Mission val7 = Global.Instance.Missions[k]; if (!((Object)(object)val7 == (Object)null) && (val7.MissionFlags & 0x80) != 0) { float rareSpawnChance = val7.GetRareSpawnChance(); if (((Random)(ref val)).NextFloat() < rareSpawnChance) { int missionSeed3 = ((Random)(ref val)).Next() + 1; AddSpecialMission(val7, missionSeed3, region, currentSeed, spawnInDesignedScene: false); } } } } private void AddSpecialMission(Mission mission, int missionSeed, WorldRegion region, int currentSeed, bool spawnInDesignedScene) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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) Random val = default(Random); ((Random)(ref val))..ctor(MathUtil.Squirrel3Hash(missionSeed, currentSeed)); SceneData[] array = region.Scenes; if (spawnInDesignedScene && (region.Flags & 0x8000) != 0) { SceneData[] legacyScenes = region.LegacyScenes; if (legacyScenes != null && legacyScenes.Length != 0) { array = legacyScenes; } } if (array != null && array.Length != 0) { SceneData val2 = array[((Random)(ref val)).Next(array.Length)]; MissionData data = default(MissionData); ((MissionData)(ref data))..ctor(missionSeed, mission, region, val2, Global.Instance.DefaultMissionContainer, mission.GetAdditionalData()); CheckAndCount(ref data); } } private void CheckAndCount(ref MissionData data) { if (MissionHasRedacted(ref data)) { _hasRedactedOnBoard = true; _matchCount++; } } public bool MissionHasRedacted(ref MissionData data) { if (!IsResolved) { return false; } int modifierCount = ((MissionData)(ref data)).GetModifierCount(); if (modifierCount <= 0) { return false; } for (int i = 0; i < modifierCount; i++) { if (((MissionData)(ref data)).GetModifier(i) == _redactedIndex) { return true; } } return false; } private static int FillValidMissions(LevelFlags compatibleLevels, int[] indexBuffer, int onlyThisIndex = -1) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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) Mission[] missions = Global.Instance.Missions; int result = 0; for (int i = 0; i < missions.Length; i++) { if (onlyThisIndex >= 0) { indexBuffer[result++] = onlyThisIndex; } else if ((missions[i].MissionFlags & 0x80) == 0) { bool flag = false; if ((missions[i].MissionFlags & 0x200) != 0 && (compatibleLevels & 0x8000) != 0) { flag = true; } bool flag2 = false; if ((missions[i].MissionFlags & 0x400) != 0 && (compatibleLevels & 0x8000) == 0) { flag2 = true; } if ((flag || flag2) && missions[i].CanBeSelected() && (missions[i].CompatibleLevels & 0x40F0 & compatibleLevels) != 0 && (missions[i].MissionFlags & 2) == 0) { indexBuffer[result++] = i; } } } return result; } } public sealed class RedactedHUD { private readonly ConfigFile _configFile; private readonly RedactedBoardScanner _scanner; private ConfigEntry _enableHud; private ConfigEntry _showWhenNotDetected; private ConfigEntry _enableBlink; private ConfigEntry _blinkSpeed; private ConfigEntry _blinkMinAlpha; private ConfigEntry _anchorX; private ConfigEntry _anchorY; private ConfigEntry _alertText; private ConfigEntry _idleText; private HudHandle _hud; private Image _iconImage; private Sprite _fallbackTriangle; private bool _lastDetected; private bool _lastShowIdle; private Color _baseAlertColor = UIColors.Orchid; private Color _baseIdleColor = UIColors.TextMuted; public static RedactedHUD Instance { get; private set; } private bool IsHudAlive { get { if (HudHandle.IsValid(_hud)) { return _hud.Primary != null; } return false; } } public RedactedHUD(ConfigFile configFile, RedactedBoardScanner scanner) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) _configFile = configFile; _scanner = scanner; Instance = this; try { _enableHud = configFile.Bind("General", "EnableHUD", true, "Show the ERROR REDACTED board notification on the player HUD."); _showWhenNotDetected = configFile.Bind("General", "ShowWhenNotDetected", false, "When enabled, always show a grey idle indicator (\"no ERROR detected.\") when ERROR REDACTED is not on the board. When disabled, the HUD is hidden until the modifier appears."); _alertText = configFile.Bind("General", "AlertText", "ERROR REDACTED has appeared!", "Text shown when ERROR REDACTED is on the current mission board."); _idleText = configFile.Bind("General", "IdleText", "no ERROR detected.", "Text shown in idle mode when ERROR REDACTED is not on the board."); _enableBlink = configFile.Bind("General", "EnableBlink", true, "Pulse the alert HUD when ERROR REDACTED is on the board so it is easier to notice."); _blinkSpeed = configFile.Bind("General", "BlinkSpeed", 2f, "Blink rate in full cycles per second (soft alpha pulse). Reasonable range: 1–3."); _blinkMinAlpha = configFile.Bind("General", "BlinkMinAlpha", 0.35f, "Minimum alpha during the dim phase of the blink (0–1). Higher = subtler blink."); _anchorX = configFile.Bind("HUD Positioning", "AnchorX", 0.5f, "X anchor position for the notification (0-1)."); _anchorY = configFile.Bind("HUD Positioning", "AnchorY", 0.12f, "Y anchor position for the notification (0-1)."); _enableHud.SettingChanged += delegate { OnEnableChanged(); }; _showWhenNotDetected.SettingChanged += delegate { RefreshVisual(force: true); }; _alertText.SettingChanged += delegate { RefreshVisual(force: true); }; _idleText.SettingChanged += delegate { RefreshVisual(force: true); }; _enableBlink.SettingChanged += delegate { ApplyBlinkAlpha(1f); }; _blinkMinAlpha.SettingChanged += delegate { }; _anchorX.SettingChanged += delegate { OnAnchorChanged(); }; _anchorY.SettingChanged += delegate { OnAnchorChanged(); }; } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Failed to initialize RedactedHUD config: " + ex.Message)); } } public void Update() { try { if (_enableHud == null || !_enableHud.Value) { if (IsHudAlive && _hud.IsActive) { _hud.SetActive(false); } return; } if (_hud != null && !IsHudAlive) { ClearDestroyedHud(); } if ((Object)(object)Player.LocalPlayer == (Object)null || (Object)(object)Player.LocalPlayer.PlayerLook == (Object)null || (Object)(object)Player.LocalPlayer.PlayerLook.Reticle == (Object)null) { return; } bool flag = _scanner != null && _scanner.HasRedactedOnBoard; if (!flag && (_showWhenNotDetected == null || !_showWhenNotDetected.Value)) { if (IsHudAlive) { _hud.SetActive(false); } return; } if (!IsHudAlive) { CreateHud(); if (!IsHudAlive) { return; } } _hud.SetActive(true); RefreshVisual(force: false); UpdateBlink(flag); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error in RedactedHUD.Update(): " + ex.Message)); } } private void UpdateBlink(bool detected) { if (IsHudAlive) { if (!detected || _enableBlink == null || !_enableBlink.Value) { ApplyBlinkAlpha(1f); return; } float num = ((_blinkSpeed != null) ? Mathf.Max(0.1f, _blinkSpeed.Value) : 2f); float num2 = ((_blinkMinAlpha != null) ? Mathf.Clamp01(_blinkMinAlpha.Value) : 0.35f); float num3 = Mathf.PingPong(Time.unscaledTime * num, 1f); float alpha = Mathf.Lerp(num2, 1f, num3); ApplyBlinkAlpha(alpha); } } private void ApplyBlinkAlpha(float alpha) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) if (IsHudAlive) { alpha = Mathf.Clamp01(alpha); if (_hud.Primary != null && (Object)(object)_hud.Primary.Tmp != (Object)null) { Color color = (_lastDetected ? _baseAlertColor : _baseIdleColor); color.a = alpha; ((Graphic)_hud.Primary.Tmp).color = color; } if ((Object)(object)_iconImage != (Object)null) { Color color2 = ((Graphic)_iconImage).color; float num = (_lastDetected ? 1f : 0.85f); color2.a = num * alpha; ((Graphic)_iconImage).color = color2; } } } public void UpdateHudVisibility() { if (!IsHudAlive) { ClearDestroyedHud(); return; } if (_enableHud == null || !_enableHud.Value) { _hud.SetActive(false); return; } bool active = (_scanner != null && _scanner.HasRedactedOnBoard) || (_showWhenNotDetected != null && _showWhenNotDetected.Value); _hud.SetActive(active); } private void OnEnableChanged() { if (_enableHud != null && !_enableHud.Value && _hud != null) { DestroyHud(); } UpdateHudVisibility(); } private void OnAnchorChanged() { if (IsHudAlive) { _hud.SetAnchor(_anchorX.Value, _anchorY.Value); } } private void ClearDestroyedHud() { if (_hud == null) { return; } try { if ((Object)(object)_hud.Rect != (Object)null) { HudRepositionClient.Unregister("sparroh.redactednotification"); } } catch { } _hud = null; _iconImage = null; } private void CreateHud() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) if (IsHudAlive) { return; } ClearDestroyedHud(); _hud = HudBuilder.Create("RedactedNotificationHUD").ParentToReticle(true).Anchor(_anchorX.Value, _anchorY.Value) .Pivot(new Vector2(0.5f, 0.5f)) .Size(420f, 32f, true) .AddText("StatusText", 18f, (TextAlignmentOptions)514) .Build(); if (!IsHudAlive) { return; } try { RectTransform val = UIFactory.CreateRect("RedactedIcon", (Transform)(object)_hud.Rect); val.anchorMin = new Vector2(0f, 0.5f); val.anchorMax = new Vector2(0f, 0.5f); val.pivot = new Vector2(0f, 0.5f); val.sizeDelta = UITheme.ScaledSize(28f, 28f); val.anchoredPosition = new Vector2(UITheme.S(4f), 0f); _iconImage = ((Component)val).gameObject.AddComponent(); ((Graphic)_iconImage).raycastTarget = false; _iconImage.preserveAspect = true; if (_hud.Primary != null && (Object)(object)_hud.Primary.Rect != (Object)null) { RectTransform rect = _hud.Primary.Rect; rect.offsetMin = new Vector2(UITheme.S(34f), rect.offsetMin.y); } } catch (Exception ex) { SparrohPlugin.Logger.LogWarning((object)("Could not create redacted icon: " + ex.Message)); _iconImage = null; } HudRepositionClient.Register("sparroh.redactednotification", "ERROR REDACTED Alert", _hud.Rect, _anchorX, _anchorY); _lastDetected = false; _lastShowIdle = false; RefreshVisual(force: true); } private void DestroyHud() { HudRepositionClient.Unregister("sparroh.redactednotification"); if (_hud != null) { if (_hud.IsAlive) { _hud.Destroy(); } _hud = null; } _iconImage = null; } private void RefreshVisual(bool force) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) if (!IsHudAlive) { return; } bool flag = _scanner != null && _scanner.HasRedactedOnBoard; bool flag2 = _showWhenNotDetected != null && _showWhenNotDetected.Value; if (force || flag != _lastDetected || flag2 != _lastShowIdle) { _lastDetected = flag; _lastShowIdle = flag2; if (flag) { string text = ((_alertText != null) ? _alertText.Value : "ERROR REDACTED has appeared!"); _baseAlertColor = GetAlertColor(); _hud.Primary.Text = text; ((Graphic)_hud.Primary.Tmp).color = _baseAlertColor; ApplyIcon(alert: true); ApplyBlinkAlpha(1f); } else if (flag2) { string text2 = ((_idleText != null) ? _idleText.Value : "no ERROR detected."); _baseIdleColor = UIColors.TextMuted; _hud.Primary.Text = text2; ((Graphic)_hud.Primary.Tmp).color = _baseIdleColor; ApplyIcon(alert: false); ApplyBlinkAlpha(1f); } } } private Color GetAlertColor() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) try { if (_scanner != null && (Object)(object)_scanner.RedactedModifier != (Object)null) { return _scanner.RedactedModifier.IconColor; } } catch { } return UIColors.Orchid; } private void ApplyIcon(bool alert) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_iconImage == (Object)null) { return; } Sprite val = null; Color alertColor = default(Color); if (alert) { alertColor = GetAlertColor(); try { if (_scanner != null && (Object)(object)_scanner.RedactedModifier != (Object)null) { val = _scanner.RedactedModifier.Icon; } } catch { } } else { ((Color)(ref alertColor))..ctor(0.45f, 0.45f, 0.48f, 0.85f); try { if (_scanner != null && (Object)(object)_scanner.RedactedModifier != (Object)null) { val = _scanner.RedactedModifier.Icon; } } catch { } } if ((Object)(object)val == (Object)null) { val = GetFallbackTriangle(); } _iconImage.sprite = val; ((Graphic)_iconImage).color = alertColor; ((Behaviour)_iconImage).enabled = (Object)(object)val != (Object)null; } private Sprite GetFallbackTriangle() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_fallbackTriangle != (Object)null) { return _fallbackTriangle; } Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false); ((Texture)val).filterMode = (FilterMode)1; ((Texture)val).wrapMode = (TextureWrapMode)1; Color val2 = default(Color); ((Color)(ref val2))..ctor(0f, 0f, 0f, 0f); Color white = Color.white; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num = ((float)j + 0.5f) / 32f; float num2 = ((float)i + 0.5f) / 32f; float num3 = num2 * 0.5f; bool flag = num2 >= 0.12f && num2 <= 0.92f && Mathf.Abs(num - 0.5f) <= num3 * 0.9f; val.SetPixel(j, i, flag ? white : val2); } } val.Apply(false, true); _fallbackTriangle = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f); return _fallbackTriangle; } public void OnDestroy() { try { DestroyHud(); } catch (Exception ex) { SparrohPlugin.Logger.LogError((object)("Error in RedactedHUD.OnDestroy(): " + ex.Message)); } } } namespace RedactedNotification { public static class MyPluginInfo { public const string PLUGIN_GUID = "RedactedNotification"; public const string PLUGIN_NAME = "RedactedNotification"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }