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 SeeThrough v1.0.0
SeeThrough.dll
Decompiled 5 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.PostProcessing; using UnityEngine.Rendering; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("0.0.0.0")] [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; } } } namespace SeeThrough { internal static class AntiAliasingSwap { private static readonly FieldRef<CameraEffects, PostProcessingBehaviour> PostProcessing = AccessTools.FieldRefAccess<CameraEffects, PostProcessingBehaviour>("m_postProcessing"); private static PostProcessingProfile _profile; private static bool _logged; public static bool Swapped => (Object)(object)_profile != (Object)null; public static void Update(bool want) { //IL_006e: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Invalid comparison between Unknown and I4 //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) CameraEffects instance = CameraEffects.instance; PostProcessingProfile val = (((Object)(object)instance == (Object)null) ? null : PostProcessing.Invoke(instance)?.profile); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)_profile != (Object)null && (Object)(object)_profile != (Object)(object)val) { Restore(); } if (want == Swapped) { return; } if (!want) { Restore(); return; } AntialiasingModel antialiasing = val.antialiasing; Settings settings = antialiasing.settings; if ((int)settings.method == 1) { settings.method = (Method)0; antialiasing.settings = settings; _profile = val; if (!_logged) { _logged = true; Plugin.Log.LogInfo((object)"Antialiasing: TAA -> FXAA while the Dither style is used (TAA smears the dither)."); } } } public static void Restore() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0031: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_profile == (Object)null)) { AntialiasingModel antialiasing = _profile.antialiasing; Settings settings = antialiasing.settings; if ((int)settings.method == 0) { settings.method = (Method)1; antialiasing.settings = settings; } _profile = null; } } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] internal static class RayTestPointPatch { private static readonly MethodInfo SphereCast = AccessTools.Method(typeof(Physics), "SphereCast", new Type[6] { typeof(Vector3), typeof(float), typeof(Vector3), typeof(RaycastHit).MakeByRefType(), typeof(float), typeof(int) }, (Type[])null); private static readonly MethodInfo Raycast = AccessTools.Method(typeof(Physics), "Raycast", new Type[5] { typeof(Vector3), typeof(Vector3), typeof(RaycastHit).MakeByRefType(), typeof(float), typeof(int) }, (Type[])null); private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Call && instruction.operand is MethodInfo methodInfo) { if (methodInfo == SphereCast) { instruction.operand = AccessTools.Method(typeof(CameraCasts), "SphereCast", (Type[])null, (Type[])null); replaced++; } else if (methodInfo == Raycast) { instruction.operand = AccessTools.Method(typeof(CameraCasts), "Raycast", (Type[])null, (Type[])null); replaced++; } } yield return instruction; } if (replaced != 4) { Plugin.Log.LogWarning((object)($"GameCamera.RayTestPoint: replaced {replaced} of 4 camera casts (game update?); " + "the camera may still pull in for fading objects.")); } } } internal static class CameraCasts { private static readonly RaycastHit[] Hits = (RaycastHit[])(object)new RaycastHit[64]; public static bool SphereCast(Vector3 origin, float radius, Vector3 direction, out RaycastHit hit, float maxDistance, int layerMask) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Fader instance = Fader.Instance; if (instance == null || !instance.CameraPassesThrough) { return Physics.SphereCast(origin, radius, direction, ref hit, maxDistance, layerMask); } int n = Physics.SphereCastNonAlloc(origin, radius, direction, Hits, maxDistance, layerMask); return Nearest(instance, n, out hit); } public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hit, float maxDistance, int layerMask) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) Fader instance = Fader.Instance; if (instance == null || !instance.CameraPassesThrough) { return Physics.Raycast(origin, direction, ref hit, maxDistance, layerMask); } int n = Physics.RaycastNonAlloc(origin, direction, Hits, maxDistance, layerMask); return Nearest(instance, n, out hit); } private static bool Nearest(Fader fader, int n, out RaycastHit hit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0034: 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_0063: Unknown result type (might be due to invalid IL or missing references) hit = default(RaycastHit); float num = float.MaxValue; bool result = false; for (int i = 0; i < n; i++) { RaycastHit val = Hits[i]; if ((!(((RaycastHit)(ref val)).distance <= 0f) || !(((RaycastHit)(ref val)).point == Vector3.zero)) && !(((RaycastHit)(ref val)).distance >= num) && !fader.PassesThrough(((RaycastHit)(ref val)).collider)) { num = ((RaycastHit)(ref val)).distance; hit = val; result = true; } } return result; } } internal sealed class ConfigurationManagerAttributes { public string Category; public string DispName; public int? Order; } internal static class Diagnostics { public static bool LogPostEffects() { try { CameraEffects instance = CameraEffects.instance; if ((Object)(object)instance == (Object)null) { return false; } Traverse obj = Traverse.Create((object)instance); Traverse obj2 = obj.Field("m_postProcessing").Field("profile"); Traverse val = obj2.Field("antialiasing"); Traverse val2 = obj2.Field("motionBlur"); Traverse val3 = obj.Field("m_amplifyOcclusion"); object value = val3.GetValue(); Behaviour val4 = (Behaviour)((value is Behaviour) ? value : null); object value2 = obj.Field("m_dof").GetValue(); Behaviour val5 = (Behaviour)((value2 is Behaviour) ? value2 : null); Plugin.Log.LogInfo((object)(string.Format("Camera effects: antialiasing {0} ({1}", On(val.Property("enabled", (object[])null)), val.Property("settings", (object[])null).Field("method").GetValue()) + (AntiAliasingSwap.Swapped ? ", switched from Taa by SeeThrough" : "") + "), motion blur " + On(val2.Property("enabled", (object[])null)) + ", depth of field " + (((Object)(object)val5 != (Object)null && val5.enabled) ? "on" : "off") + ", SSAO " + (((Object)(object)val4 != (Object)null && val4.enabled) ? "on" : "off") + " " + string.Format("(downsample {0}, blur {1}, ", val3.Field("Downsample").GetValue(), val3.Field("BlurEnabled").GetValue()) + string.Format("temporal filter {0} blending {1})", val3.Field("FilterEnabled").GetValue(), val3.Field("FilterBlending").GetValue()))); } catch (Exception ex) { Plugin.Log.LogInfo((object)("Camera effects: could not read (" + ex.Message + ")")); } return true; } private static string On(Traverse enabled) { object value = enabled.GetValue(); if (!(value is bool)) { return "?"; } if (!(bool)value) { return "off"; } return "on"; } } internal sealed class Fader { internal sealed class Root { public GameObject Go; public Kinds Kind; public MeshRenderer[] Renderers; public bool[] Vegetation; public bool Interactable; } internal sealed class Faded { public Root Root; public Renderer Renderer; public FadeMode Style; public Material[] Original; public Material[] Copies; public Color[] BaseColors; public ShadowCastingMode OriginalShadows; public bool Hidden; public bool ForcedOff; public bool SetShadowsOnly; public bool HadBlock; public bool TouchedBlock; public float Alpha = 1f; public float Target = 1f; public float AppliedAlpha = -1f; public float LineTarget = 1f; public float LineWanted = float.NegativeInfinity; public float NearTarget = 1f; public float NearWanted = float.NegativeInfinity; } private const int MaxFaded = 128; private const float Settled = 0.004f; private const float HiddenBelow = 0.02f; private const float HideBelowNear = 0.5f; private readonly Dictionary<int, Root> _colliderRoots = new Dictionary<int, Root>(); private readonly Dictionary<int, Root> _roots = new Dictionary<int, Root>(); private readonly Dictionary<int, Faded> _faded = new Dictionary<int, Faded>(); private readonly List<int> _remove = new List<int>(); private readonly RaycastHit[] _hits = (RaycastHit[])(object)new RaycastHit[64]; private readonly Collider[] _overlaps = (Collider[])(object)new Collider[256]; private readonly HashSet<int> _seenRoots = new HashSet<int>(); private readonly Materials _materials = new Materials(); private float _nextScan; private int _mask; private bool _effectsLogged; internal static Fader Instance; private readonly HashSet<int> _visiblyFaded = new HashSet<int>(); private float _hoverDepth; private const float GoneWithin = 0.2f; private const float FloorReach = 0.45f; private const int MaxBisected = 6; private readonly Collider[] _nearOverlaps = (Collider[])(object)new Collider[64]; private readonly Collider[] _probe = (Collider[])(object)new Collider[32]; private readonly Dictionary<Root, float> _near = new Dictionary<Root, float>(); private readonly List<KeyValuePair<float, Collider>> _nearCandidates = new List<KeyValuePair<float, Collider>>(); private static readonly Comparison<KeyValuePair<float, Collider>> ByDistance = (KeyValuePair<float, Collider> x, KeyValuePair<float, Collider> y) => x.Key.CompareTo(y.Key); public bool CameraPassesThrough { get; private set; } public bool HoverFilterActive { get; private set; } public Fader() { Instance = this; } public bool PassesThrough(Collider c) { Root root = RootOf(c); if (root != null) { return (root.Kind & Plugin.FadeKinds.Value) != 0; } return false; } public bool HiddenFromHover(RaycastHit hit) { if (((RaycastHit)(ref hit)).distance >= _hoverDepth || (Object)(object)((RaycastHit)(ref hit)).collider == (Object)null) { return false; } Root root = RootOf(((RaycastHit)(ref hit)).collider); if (root != null && (Object)(object)root.Go != (Object)null) { return _visiblyFaded.Contains(((Object)root.Go).GetInstanceID()); } return false; } public void Update() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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) //IL_0126: Unknown result type (might be due to invalid IL or missing references) CameraPassesThrough = false; HoverFilterActive = false; Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || (Object)(object)GameCamera.instance == (Object)null) { if (_faded.Count > 0 || _roots.Count > 0) { RestoreAll(); ClearCaches(); } return; } if (!Plugin.Enabled.Value) { if (_faded.Count > 0) { RestoreAll(); } return; } CameraPassesThrough = Plugin.CameraPassThrough.Value && Plugin.FadeKinds.Value != Kinds.None && Active(localPlayer); Transform transform = ((Component)GameCamera.instance).transform; _hoverDepth = Vector3.Dot(ChestOf(localPlayer) - transform.position, transform.forward); HoverFilterActive = _visiblyFaded.Count > 0; if (!_effectsLogged) { _effectsLogged = Diagnostics.LogPostEffects(); } bool flag = Time.time >= _nextScan; if (flag) { _nextScan = Time.time + Plugin.ScanInterval.Value; } Scan(localPlayer, ((Component)GameCamera.instance).transform.position, flag); } public void LateUpdate() { _visiblyFaded.Clear(); if (_faded.Count > 0) { Animate(Time.deltaTime); } } private void MarkVisiblyFaded(Faded f) { if ((f.Hidden || f.Alpha < 0.95f) && f.Root != null && (Object)(object)f.Root.Go != (Object)null) { _visiblyFaded.Add(((Object)f.Root.Go).GetInstanceID()); } } private static Vector3 ChestOf(Player player) { //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_0016: Unknown result type (might be due to invalid IL or missing references) return Vector3.Lerp(((Component)player).transform.position, ((Character)player).GetHeadPoint(), 0.65f); } private bool Active(Player player) { if (((Character)player).IsDead() || GameCamera.InFreeFly() || Plugin.BuildCameraActive()) { return false; } if (!Plugin.WhileBuilding.Value && ((Character)player).InPlaceMode()) { return false; } return true; } private void Scan(Player player, Vector3 cam, bool full) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) if (!full && !Plugin.HideWhenInside.Value) { return; } float time = Time.time; if (!Active(player)) { return; } if (_mask == 0) { _mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "viewblock" }); } Vector3 val = ChestOf(player); Vector3 val2 = val - cam; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < Mathf.Max(0.01f, Plugin.MinCameraDistance.Value) || magnitude > Plugin.MaxCameraDistance.Value) { return; } Vector3 val3 = val2 / magnitude; float num = magnitude - Plugin.PlayerClearance.Value; if (num <= 0.05f) { return; } Vector3 end = cam + val3 * num; Kinds value = Plugin.FadeKinds.Value; if (value == Kinds.None) { return; } if (full) { ScanLine(cam, val3, num, end, value, time, magnitude, crosshair: false); } if (full && Plugin.ClearCrosshair.Value) { Vector3 forward = ((Component)GameCamera.instance).transform.forward; float num2 = Vector3.Dot(val - cam, forward); float num3 = num2 - Plugin.PlayerClearance.Value; if (num3 > 0.3f && Vector3.Angle(forward, val3) > 1f) { ScanLine(cam, forward, num3, cam + forward * num3, value, time, num2, crosshair: true); } } if (Plugin.HideWhenInside.Value) { ScanNear(cam, val3, num, value, time, magnitude); } } private void ScanLine(Vector3 cam, Vector3 dir, float len, Vector3 end, Kinds kinds, float now, float dist, bool crosshair) { //IL_0042: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) float value = Plugin.ViewRadius.Value; if (_colliderRoots.Count > 8192 || _roots.Count > 4096) { ClearCaches(); } _seenRoots.Clear(); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(dir.x, 0f, dir.z); float magnitude = ((Vector3)(ref val)).magnitude; bool flag = magnitude <= 0.5f; Vector3 flatDir = (flag ? Vector3.zero : (val / magnitude)); float charAhead = dist * magnitude; int num = Physics.SphereCastNonAlloc(cam, value, dir, _hits, len, _mask, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { Root root = RootOf(((RaycastHit)(ref _hits[i])).collider); if (root != null && (root.Kind & kinds) != Kinds.None && _seenRoots.Add(((Object)root.Go).GetInstanceID()) && (!crosshair || !root.Interactable)) { if ((root.Kind & (Kinds.Trees | Kinds.Bushes)) == 0) { Want(root, cam, end, value, now); } else { WantPlant(root, cam, end, value, now, flag, flatDir, charAhead, dir, dist); } } } float value2 = Plugin.CanopyReach.Value; if (!(value2 > 0f) || (kinds & (Kinds.Trees | Kinds.Bushes)) == 0) { return; } int num2 = Physics.OverlapCapsuleNonAlloc(cam, end, Mathf.Max(value2, value), _overlaps, _mask, (QueryTriggerInteraction)1); for (int j = 0; j < num2; j++) { Root root2 = RootOf(_overlaps[j]); if (root2 != null && (root2.Kind & kinds & (Kinds.Trees | Kinds.Bushes)) != Kinds.None && _seenRoots.Add(((Object)root2.Go).GetInstanceID()) && (!crosshair || !root2.Interactable)) { WantPlant(root2, cam, end, value, now, flag, flatDir, charAhead, dir, dist); } } } private void WantPlant(Root root, Vector3 cam, Vector3 end, float radius, float now, bool steep, Vector3 flatDir, float charAhead, Vector3 dir, float dist) { //IL_0021: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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_0007: 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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (steep) { Want(root, cam, end, radius, now, dir, dist); } else if (!(Vector3.Dot(root.Go.transform.position - cam, flatDir) > charAhead)) { Want(root, cam, end, radius, now); } } private void ScanNear(Vector3 cam, Vector3 dir, float len, Kinds kinds, float now, float dist) { //IL_0021: 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_0067: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0089: 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_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) float value = Plugin.HideDistance.Value; _near.Clear(); _nearCandidates.Clear(); int num = Physics.OverlapSphereNonAlloc(cam, value, _nearOverlaps, _mask, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { Collider val = _nearOverlaps[i]; Root root = RootOf(val); if (root != null && (root.Kind & kinds) != Kinds.None) { Bounds bounds = val.bounds; if (!(Vector3.Dot(((Bounds)(ref bounds)).ClosestPoint(cam) - cam, dir) > dist)) { _nearCandidates.Add(new KeyValuePair<float, Collider>(((Bounds)(ref bounds)).SqrDistance(cam), val)); } } } _nearCandidates.Sort(ByDistance); int num2 = 0; foreach (KeyValuePair<float, Collider> nearCandidate in _nearCandidates) { Collider value2 = nearCandidate.Value; Vector3 val2; float num3; if (HasClosestPoint(value2)) { val2 = value2.ClosestPoint(cam); num3 = Vector3.Distance(val2, cam); } else { if (num2 >= 6) { continue; } num2++; Bounds bounds2 = value2.bounds; val2 = ((Bounds)(ref bounds2)).ClosestPoint(cam); num3 = SurfaceDistance(value2, cam, value); } Vector3 val3 = cam - val2; float num4 = ((val3.y > 0.7f * ((Vector3)(ref val3)).magnitude) ? Mathf.Min(0.45f, value) : value); float num5 = Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(0.2f, num4, num3)); if (!(num5 >= 0.999f)) { Root key = RootOf(value2); if (!_near.TryGetValue(key, out var value3) || num5 < value3) { _near[key] = num5; } } } bool queriesHitBackfaces = Physics.queriesHitBackfaces; Physics.queriesHitBackfaces = true; int num6; try { num6 = Physics.RaycastNonAlloc(cam, dir, _hits, len, _mask, (QueryTriggerInteraction)1); } finally { Physics.queriesHitBackfaces = queriesHitBackfaces; } for (int j = 0; j < num6; j++) { RaycastHit val4 = _hits[j]; if (Vector3.Dot(((RaycastHit)(ref val4)).normal, dir) <= 0f) { continue; } bool flag = true; for (int k = 0; k < num6 && flag; k++) { if (k != j && (Object)(object)((RaycastHit)(ref _hits[k])).collider == (Object)(object)((RaycastHit)(ref val4)).collider && ((RaycastHit)(ref _hits[k])).distance < ((RaycastHit)(ref val4)).distance) { flag = false; } } if (flag) { Root root2 = RootOf(((RaycastHit)(ref val4)).collider); if (root2 != null && (root2.Kind & kinds) != Kinds.None) { _near[root2] = 0f; } } } foreach (KeyValuePair<Root, float> item in _near) { WantNear(item.Key, cam, value, item.Value, now); } } private static bool HasClosestPoint(Collider c) { if (!(c is BoxCollider) && !(c is SphereCollider) && !(c is CapsuleCollider)) { MeshCollider val = (MeshCollider)(object)((c is MeshCollider) ? c : null); if (val != null) { return val.convex; } return false; } return true; } private float SurfaceDistance(Collider c, Vector3 cam, float reach) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) int layer = 1 << ((Component)c).gameObject.layer; if (Touches(c, cam, 0.02f, layer)) { return 0f; } float num = 0.02f; float num2 = reach; for (int i = 0; i < 6; i++) { float num3 = (num + num2) * 0.5f; if (Touches(c, cam, num3, layer)) { num2 = num3; } else { num = num3; } } return num2; } private bool Touches(Collider c, Vector3 cam, float radius, int layer) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) int num = Physics.OverlapSphereNonAlloc(cam, radius, _probe, layer, (QueryTriggerInteraction)1); for (int i = 0; i < num; i++) { if ((Object)(object)_probe[i] == (Object)(object)c) { return true; } } return false; } private void WantNear(Root root, Vector3 cam, float reach, float alpha, float now) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0083: Invalid comparison between Unknown and I4 MeshRenderer[] renderers = root.Renderers; for (int i = 0; i < renderers.Length; i++) { MeshRenderer val = renderers[i]; if ((Object)(object)val == (Object)null) { continue; } Bounds bounds = ((Renderer)val).bounds; if (((Bounds)(ref bounds)).SqrDistance(cam) > reach * reach) { continue; } int instanceID = ((Object)val).GetInstanceID(); if (!_faded.TryGetValue(instanceID, out var value)) { if (alpha >= 0.999f || !((Renderer)val).enabled || !((Component)val).gameObject.activeInHierarchy || !((Renderer)val).isVisible || (int)((Renderer)val).shadowCastingMode == 3 || ((Renderer)val).forceRenderingOff || (alpha >= 0.5f && StyleFor(((Renderer)val).sharedMaterials) == FadeMode.Hide)) { continue; } if (_faded.Count >= 128) { break; } value = Begin(root, (Renderer)(object)val, root.Vegetation[i], alpha); if (value == null) { continue; } _faded[instanceID] = value; } value.NearTarget = alpha; value.NearWanted = now; } } private void Want(Root root, Vector3 a, Vector3 b, float radius, float now) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) Want(root, a, b, radius, now, Vector3.zero, float.PositiveInfinity); } private void Want(Root root, Vector3 a, Vector3 b, float radius, float now, Vector3 aheadDir, float aheadDist) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0063: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Invalid comparison between Unknown and I4 //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) float len = Vector3.Distance(a, b); MeshRenderer[] renderers = root.Renderers; for (int i = 0; i < renderers.Length; i++) { MeshRenderer val = renderers[i]; if ((Object)(object)val == (Object)null) { continue; } Bounds bounds = ((Renderer)val).bounds; if (Vector3.Dot(((Bounds)(ref bounds)).center - a, aheadDir) > aheadDist) { continue; } int instanceID = ((Object)val).GetInstanceID(); float t; float t2; if (_faded.TryGetValue(instanceID, out var value)) { if (SegmentHitsBounds(a, b, ((Renderer)val).bounds, radius, out t, out t2)) { float num = TargetAlpha(t, t2, len); value.LineTarget = ((value.LineWanted == now) ? Mathf.Min(value.LineTarget, num) : num); value.LineWanted = now; } } else if (((Renderer)val).enabled && ((Component)val).gameObject.activeInHierarchy && ((Renderer)val).isVisible && (int)((Renderer)val).shadowCastingMode != 3 && !((Renderer)val).forceRenderingOff && SegmentHitsBounds(a, b, ((Renderer)val).bounds, radius, out t, out t2)) { if (_faded.Count >= 128) { break; } float num2 = TargetAlpha(t, t2, len); value = Begin(root, (Renderer)(object)val, root.Vegetation[i], num2); if (value != null) { value.LineTarget = num2; value.LineWanted = now; _faded[instanceID] = value; } } } } private static float TargetAlpha(float t0, float t1, float len) { float num = t0 * len; float num2 = (1f - t1) * len + Plugin.PlayerClearance.Value; float num3 = Mathf.Min(num, num2); float value = Plugin.NearDistance.Value; float num4 = Mathf.Max(Plugin.FarDistance.Value, value + 0.01f); return Mathf.Lerp(Plugin.NearOpacity.Value, Plugin.Opacity.Value, Mathf.SmoothStep(0f, 1f, Mathf.InverseLerp(value, num4, num3))); } private static bool SegmentHitsBounds(Vector3 a, Vector3 b, Bounds bounds, float radius, out float t0, out float t1) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) ((Bounds)(ref bounds)).Expand(radius * 2f); Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; Vector3 val = b - a; t0 = 0f; t1 = 1f; for (int i = 0; i < 3; i++) { float num = ((Vector3)(ref a))[i]; float num2 = ((Vector3)(ref val))[i]; if (Mathf.Abs(num2) < 1E-06f) { if (num < ((Vector3)(ref min))[i] || num > ((Vector3)(ref max))[i]) { return false; } continue; } float num3 = 1f / num2; float num4 = (((Vector3)(ref min))[i] - num) * num3; float num5 = (((Vector3)(ref max))[i] - num) * num3; if (num4 > num5) { float num6 = num4; num4 = num5; num5 = num6; } if (num4 > t0) { t0 = num4; } if (num5 < t1) { t1 = num5; } if (t0 > t1) { return false; } } return true; } private Root RootOf(Collider c) { if ((Object)(object)c == (Object)null) { return null; } int instanceID = ((Object)c).GetInstanceID(); if (_colliderRoots.TryGetValue(instanceID, out var value) && (value == null || (Object)(object)value.Go != (Object)null)) { return value; } Root value2 = null; GameObject val = FindRootObject(c); if ((Object)(object)val != (Object)null) { int instanceID2 = ((Object)val).GetInstanceID(); if (!_roots.TryGetValue(instanceID2, out value2) || (Object)(object)value2.Go == (Object)null) { value2 = Classify(val); _roots[instanceID2] = value2; } } _colliderRoots[instanceID] = value2; return value2; } private static GameObject FindRootObject(Collider c) { if ((Object)(object)((Component)c).GetComponentInParent<Character>() != (Object)null || (Object)(object)((Component)c).GetComponentInParent<ItemDrop>() != (Object)null || (Object)(object)((Component)c).GetComponentInParent<Ship>() != (Object)null) { return null; } ZNetView componentInParent = ((Component)c).GetComponentInParent<ZNetView>(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)((Component)componentInParent).GetComponent<LocationProxy>() == (Object)null && (Object)(object)((Component)componentInParent).GetComponent<Location>() == (Object)null && ((Component)componentInParent).GetComponentsInChildren<MeshRenderer>(true).Length <= 48) { return ((Component)componentInParent).gameObject; } LODGroup componentInParent2 = ((Component)c).GetComponentInParent<LODGroup>(); if ((Object)(object)componentInParent2 != (Object)null && ((Component)componentInParent2).GetComponentsInChildren<MeshRenderer>(true).Length <= 48) { return ((Component)componentInParent2).gameObject; } Transform val = ((Component)c).transform; int num = 0; while ((Object)(object)val != (Object)null && num < 4) { int num2 = ((Component)val).GetComponentsInChildren<MeshRenderer>(true).Length; if (num2 > 48) { return null; } if (num2 > 0) { return ((Component)val).gameObject; } num++; val = val.parent; } return null; } private static Root Classify(GameObject go) { MeshRenderer[] componentsInChildren = go.GetComponentsInChildren<MeshRenderer>(true); bool[] array = new bool[componentsInChildren.Length]; bool flag = false; bool flag2 = false; for (int i = 0; i < componentsInChildren.Length; i++) { Material[] sharedMaterials = ((Renderer)componentsInChildren[i]).sharedMaterials; foreach (Material val in sharedMaterials) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.shader == (Object)null)) { string name = ((Object)val.shader).name; if (name.Contains("Vegetation") || name.Contains("Grass")) { array[i] = true; flag = true; } else if (name.Contains("Rock")) { flag2 = true; } } } } Kinds kinds = ((!((Object)(object)go.GetComponent<Piece>() != (Object)null) && !((Object)(object)go.GetComponent<WearNTear>() != (Object)null)) ? (((Object)(object)go.GetComponent<TreeBase>() != (Object)null || (Object)(object)go.GetComponent<TreeLog>() != (Object)null) ? Kinds.Trees : (((Object)(object)go.GetComponent<MineRock>() != (Object)null || (Object)(object)go.GetComponent<MineRock5>() != (Object)null) ? Kinds.Rocks : (flag ? Kinds.Bushes : ((!flag2) ? Kinds.Other : Kinds.Rocks)))) : Kinds.Pieces); if (kinds == Kinds.Trees) { for (int k = 0; k < array.Length; k++) { array[k] = true; } } return new Root { Go = go, Kind = kinds, Renderers = componentsInChildren, Vegetation = array, Interactable = (go.GetComponentInChildren<Interactable>(true) != null) }; } private static float SwapAlpha(Faded f) { if (f.Style != FadeMode.Transparent) { return 1f; } return Mathf.Max(f.Target, Plugin.SwapOpacity.Value); } private FadeMode StyleFor(Material[] materials) { FadeMode fadeMode = Plugin.Style.Value; if (fadeMode == FadeMode.Dither && !_materials.CanDither(materials)) { fadeMode = FadeMode.Transparent; } if (fadeMode == FadeMode.Transparent && !_materials.HasAlphaTemplate()) { fadeMode = FadeMode.Hide; } return fadeMode; } private Faded Begin(Root root, Renderer r, bool vegetation, float target) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) Material[] sharedMaterials = r.sharedMaterials; FadeMode fadeMode = StyleFor(sharedMaterials); Faded faded = new Faded { Root = root, Renderer = r, Style = fadeMode, Target = target, OriginalShadows = r.shadowCastingMode }; switch (fadeMode) { case FadeMode.Hide: SetHidden(faded, hide: true); return faded; case FadeMode.Dither: faded.Original = sharedMaterials; faded.Copies = _materials.DitherClones(sharedMaterials); faded.HadBlock = r.HasPropertyBlock(); faded.Alpha = 1f; r.sharedMaterials = faded.Copies; Materials.ApplyDither(faded, 1f); return faded; default: faded.Original = sharedMaterials; faded.Copies = _materials.AlphaCopies(sharedMaterials, vegetation, out faded.BaseColors); faded.Alpha = SwapAlpha(faded); r.sharedMaterials = faded.Copies; Materials.ApplyAlpha(faded); return faded; } } private void Animate(float dt) { float time = Time.time; float value = Plugin.FadeTime.Value; float num = ((value <= 0.001f) ? 1f : (1f - Mathf.Exp(-4.6f * dt / value))); float num2 = ((value <= 0.001f) ? 1f : (1f - Mathf.Exp(-4.6f * dt / (value * 0.25f)))); float num3 = Plugin.ScanInterval.Value * 2.5f; bool value2 = Plugin.Enabled.Value; _remove.Clear(); foreach (KeyValuePair<int, Faded> item in _faded) { Faded value3 = item.Value; if ((Object)(object)value3.Renderer == (Object)null) { _materials.Release(value3); _remove.Add(item.Key); continue; } bool flag = value2 && time - value3.LineWanted <= num3; bool flag2 = value2 && time - value3.NearWanted <= 0.15f; float num4 = (flag ? value3.LineTarget : 1f); float num5 = (flag2 ? value3.NearTarget : 1f); bool flag3 = flag || flag2; if (flag3) { value3.Target = Mathf.Min(num4, num5); } if (value3.Style == FadeMode.Hide) { if (!flag && (!flag2 || !(value3.NearTarget < 0.5f))) { End(value3); _remove.Add(item.Key); } else { MarkVisiblyFaded(value3); } continue; } float num6 = SwapAlpha(value3); float num7 = (flag3 ? value3.Target : num6); bool flag4 = flag2 && num5 < num4; value3.Alpha = Mathf.Lerp(value3.Alpha, num7, flag4 ? num2 : num); if (Mathf.Abs(value3.Alpha - num7) < 0.004f) { value3.Alpha = num7; } if (!flag3 && value3.Alpha >= num6 - 0.004f) { End(value3); _remove.Add(item.Key); continue; } SetHidden(value3, value3.Alpha <= 0.02f); MarkVisiblyFaded(value3); if (value3.Style == FadeMode.Dither) { if (!value3.ForcedOff) { Materials.ApplyDither(value3, value3.SetShadowsOnly ? 1f : value3.Alpha); } } else if (!Mathf.Approximately(value3.Alpha, value3.AppliedAlpha) || value3.TouchedBlock) { Materials.ApplyAlpha(value3); } } foreach (int item2 in _remove) { _faded.Remove(item2); } } private static void SetHidden(Faded f, bool hide) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Invalid comparison between Unknown and I4 //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (hide == f.Hidden) { return; } f.Hidden = hide; Renderer renderer = f.Renderer; if ((Object)(object)renderer == (Object)null) { return; } if (hide) { if (Plugin.FadeShadows.Value) { renderer.forceRenderingOff = true; f.ForcedOff = true; } else { renderer.shadowCastingMode = (ShadowCastingMode)3; f.SetShadowsOnly = true; } return; } if (f.ForcedOff) { renderer.forceRenderingOff = false; f.ForcedOff = false; } if (f.SetShadowsOnly) { if ((int)renderer.shadowCastingMode == 3) { renderer.shadowCastingMode = f.OriginalShadows; } f.SetShadowsOnly = false; } } private void End(Faded f) { Renderer renderer = f.Renderer; SetHidden(f, hide: false); if (f.Style == FadeMode.Hide) { return; } bool flag = false; if ((Object)(object)renderer != (Object)null) { Material[] sharedMaterials = renderer.sharedMaterials; flag = sharedMaterials.Length == f.Copies.Length; if (flag) { bool flag2 = false; for (int i = 0; i < sharedMaterials.Length; i++) { Material val = sharedMaterials[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)f.Copies[i] == (Object)null)) { if ((Object)(object)val == (Object)(object)f.Copies[i] || ((Object)val).name.StartsWith(((Object)f.Copies[i]).name, StringComparison.Ordinal)) { sharedMaterials[i] = f.Original[i]; flag2 = true; } else { flag = false; } } } if (flag2) { renderer.sharedMaterials = sharedMaterials; } } Materials.ClearBlock(f); } if ((Object)(object)renderer == (Object)null || flag) { _materials.Release(f); } } public void RestoreAll() { foreach (Faded value in _faded.Values) { if ((Object)(object)value.Renderer == (Object)null) { _materials.Release(value); } else { End(value); } } _faded.Clear(); _visiblyFaded.Clear(); } private void ClearCaches() { _colliderRoots.Clear(); _roots.Clear(); if (_faded.Count == 0) { _materials.ClearClones(); } } } [HarmonyPatch(typeof(Player), "FindHoverObject")] internal static class HoverPatch { private static readonly MethodInfo RaycastNonAlloc = AccessTools.Method(typeof(Physics), "RaycastNonAlloc", new Type[5] { typeof(Vector3), typeof(Vector3), typeof(RaycastHit[]), typeof(float), typeof(int) }, (Type[])null); private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { int replaced = 0; foreach (CodeInstruction instruction in instructions) { if (instruction.opcode == OpCodes.Call && instruction.operand is MethodInfo methodInfo && methodInfo == RaycastNonAlloc) { instruction.operand = AccessTools.Method(typeof(HoverPatch), "HoverRaycast", (Type[])null, (Type[])null); replaced++; } yield return instruction; } if (replaced != 1) { Plugin.Log.LogWarning((object)($"Player.FindHoverObject: replaced {replaced} of 1 hover raycasts (game update?); " + "faded objects may block interaction.")); } } public static int HoverRaycast(Vector3 origin, Vector3 direction, RaycastHit[] results, float maxDistance, int layerMask) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) int num = Physics.RaycastNonAlloc(origin, direction, results, maxDistance, layerMask); Fader instance = Fader.Instance; if (instance == null || !instance.HoverFilterActive) { return num; } int result = 0; for (int i = 0; i < num; i++) { if (!instance.HiddenFromHover(results[i])) { results[result++] = results[i]; } } return result; } } internal static class MaterialManRefresh { private static bool _looked; private static FieldInfo _blocks; private static FieldInfo _renderers; private static MethodInfo _queue; public static void Request(GameObject root, Renderer renderer) { try { MaterialMan instance = MaterialMan.instance; if ((Object)(object)instance == (Object)null || (Object)(object)renderer == (Object)null || !Resolve() || !(_blocks.GetValue(instance) is IDictionary dictionary)) { return; } object obj = (((Object)(object)root != (Object)null) ? dictionary[((Object)root).GetInstanceID()] : null); if (!Holds(obj, renderer)) { obj = null; foreach (object value in dictionary.Values) { if (Holds(value, renderer)) { obj = value; break; } } } if (obj != null) { _queue.Invoke(instance, new object[1] { obj }); } } catch (Exception ex) { Plugin.Log.LogDebug((object)("MaterialMan refresh skipped: " + ex.Message)); } } private static bool Holds(object container, Renderer renderer) { if (container != null && _renderers.GetValue(container) is List<Renderer> list) { return list.Contains(renderer); } return false; } private static bool Resolve() { if (_looked) { return _queue != null; } _looked = true; Type type = AccessTools.Inner(typeof(MaterialMan), "PropertyContainer"); _blocks = AccessTools.Field(typeof(MaterialMan), "m_blocks"); _renderers = ((type == null) ? null : AccessTools.Field(type, "m_assignedRenderers")); _queue = AccessTools.Method(typeof(MaterialMan), "QueuePropertyUpdate", (Type[])null, (Type[])null); if (_blocks == null || _renderers == null || _queue == null) { Plugin.Log.LogInfo((object)"MaterialMan internals not found; faded objects' property blocks keep a solid fade value until the game rewrites them."); _queue = null; } return _queue != null; } } internal sealed class Materials { private const string CrossFade = "LOD_FADE_CROSSFADE"; private static readonly int LodFadeId = Shader.PropertyToID("unity_LODFade"); private static readonly int ColorId = Shader.PropertyToID("_Color"); private static readonly MaterialPropertyBlock Block = new MaterialPropertyBlock(); private static readonly string[] ClearTextures = new string[8] { "_EmissionMap", "_DetailAlbedoMap", "_DetailNormalMap", "_DetailMask", "_MetallicGlossMap", "_SpecGlossMap", "_OcclusionMap", "_ParallaxMap" }; private readonly Dictionary<Material, Material> _ditherClones = new Dictionary<Material, Material>(); private readonly Dictionary<Shader, bool> _ditherShaders = new Dictionary<Shader, bool>(); private Material _standardTemplate; private Material _twoSidedTemplate; private float _nextTemplateSearch; private bool _templateLogged; private bool _noTemplateWarned; public bool CanDither(Material[] mats) { bool result = false; foreach (Material val in mats) { if (!((Object)(object)val == (Object)null)) { if ((Object)(object)val.shader == (Object)null || !ShaderCanDither(val.shader)) { return false; } result = true; } } return result; } private bool ShaderCanDither(Shader shader) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) if (_ditherShaders.TryGetValue(shader, out var value)) { return value; } LocalKeywordSpace keywordSpace = shader.keywordSpace; value = Array.IndexOf(((LocalKeywordSpace)(ref keywordSpace)).keywordNames, "LOD_FADE_CROSSFADE") >= 0; _ditherShaders[shader] = value; if (!value) { Plugin.Log.LogInfo((object)("Shader '" + ((Object)shader).name + "' has no LOD_FADE_CROSSFADE dither; objects using it fade with Transparent copies instead.")); } return value; } public Material[] DitherClones(Material[] original) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_006e: 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) Material[] array = (Material[])(object)new Material[original.Length]; for (int i = 0; i < original.Length; i++) { Material val = original[i]; if (!((Object)(object)val == (Object)null)) { if (!_ditherClones.TryGetValue(val, out var value) || (Object)(object)value == (Object)null) { value = new Material(val) { name = ((Object)val).name + " (SeeThrough)", hideFlags = (HideFlags)52 }; value.enableInstancing = false; Material obj = value; LocalKeyword val2 = new LocalKeyword(val.shader, "LOD_FADE_CROSSFADE"); obj.EnableKeyword(ref val2); _ditherClones[val] = value; } array[i] = value; } } return array; } public static void ApplyDither(Fader.Faded f, float alpha) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) Renderer renderer = f.Renderer; float num = Mathf.Clamp(alpha, 0.004f, 1f); renderer.GetPropertyBlock(Block); if (!f.HadBlock && !Block.isEmpty && !Block.HasVector(LodFadeId)) { f.HadBlock = true; } Block.SetVector(LodFadeId, new Vector4(num, num, 0f, 0f)); renderer.SetPropertyBlock(Block); f.AppliedAlpha = f.Alpha; } public void ClearClones() { foreach (Material value in _ditherClones.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } _ditherClones.Clear(); _ditherShaders.Clear(); } public Material[] AlphaCopies(Material[] original, bool vegetation, out Color[] baseColors) { Material[] array = (Material[])(object)new Material[original.Length]; baseColors = (Color[])(object)new Color[original.Length]; for (int i = 0; i < original.Length; i++) { if ((Object)(object)original[i] != (Object)null) { array[i] = AlphaCopy(original[i], vegetation, out baseColors[i]); } } return array; } private Material AlphaCopy(Material src, bool vegetation, out Color baseColor) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) Material val = new Material(vegetation ? (_twoSidedTemplate ?? _standardTemplate) : (_standardTemplate ?? _twoSidedTemplate)) { name = ((Object)src).name + " (SeeThrough)", hideFlags = (HideFlags)52 }; if (val.renderQueue < 2501) { val.renderQueue = 3000; } string[] clearTextures = ClearTextures; foreach (string text in clearTextures) { if (val.HasProperty(text)) { val.SetTexture(text, (Texture)null); } } if (val.HasProperty("_EmissionColor")) { val.SetColor("_EmissionColor", Color.black); } if (val.HasProperty("_Metallic")) { val.SetFloat("_Metallic", 0f); } if (val.HasProperty("_Glossiness")) { val.SetFloat("_Glossiness", 0f); } if (src.HasProperty("_MainTex")) { val.mainTexture = src.mainTexture; val.mainTextureScale = src.mainTextureScale; val.mainTextureOffset = src.mainTextureOffset; } else { val.mainTexture = null; } if (val.HasProperty("_BumpMap")) { val.SetTexture("_BumpMap", src.HasProperty("_BumpMap") ? src.GetTexture("_BumpMap") : null); } if (val.HasProperty("_BumpScale")) { val.SetFloat("_BumpScale", src.HasProperty("_BumpScale") ? src.GetFloat("_BumpScale") : 1f); } baseColor = (src.HasProperty("_Color") ? src.color : Color.white); baseColor.a = 1f; val.color = baseColor; return val; } public static void ApplyAlpha(Fader.Faded f) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < f.Copies.Length; i++) { Material val = f.Copies[i]; if (!((Object)(object)val == (Object)null)) { Color val2 = f.BaseColors[i]; val2.a = f.Alpha; val.SetColor(ColorId, val2); } } f.AppliedAlpha = f.Alpha; FixBlockAlpha(f); } private static void FixBlockAlpha(Fader.Faded f) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) Renderer renderer = f.Renderer; if ((Object)(object)renderer == (Object)null || !renderer.HasPropertyBlock()) { return; } renderer.GetPropertyBlock(Block); if (Block.HasColor(ColorId)) { Color color = Block.GetColor(ColorId); if (!Mathf.Approximately(color.a, f.Alpha)) { color.a = f.Alpha; Block.SetColor(ColorId, color); renderer.SetPropertyBlock(Block); f.TouchedBlock = true; } } } public static void ClearBlock(Fader.Faded f) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) Renderer renderer = f.Renderer; if (f.Style == FadeMode.Dither) { if (!f.HadBlock) { renderer.SetPropertyBlock((MaterialPropertyBlock)null); return; } renderer.GetPropertyBlock(Block); Block.SetVector(LodFadeId, new Vector4(1f, 1f, 0f, 0f)); renderer.SetPropertyBlock(Block); MaterialManRefresh.Request(f.Root?.Go, renderer); } else if (f.TouchedBlock && renderer.HasPropertyBlock()) { renderer.GetPropertyBlock(Block); if (Block.HasColor(ColorId)) { Color color = Block.GetColor(ColorId); color.a = 1f; Block.SetColor(ColorId, color); renderer.SetPropertyBlock(Block); } } } public void Release(Fader.Faded f) { if (f.Style != FadeMode.Transparent || f.Copies == null) { return; } Material[] copies = f.Copies; foreach (Material val in copies) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } f.Copies = null; } public bool HasAlphaTemplate() { //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Expected O, but got Unknown if ((Object)(object)_standardTemplate != (Object)null || (Object)(object)_twoSidedTemplate != (Object)null) { return true; } if (Time.time < _nextTemplateSearch) { return false; } _nextTemplateSearch = Time.time + 10f; int num = int.MinValue; int num2 = int.MinValue; Material[] array = Resources.FindObjectsOfTypeAll<Material>(); foreach (Material val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val.shader == (Object)null) { continue; } string name = ((Object)val.shader).name; if (!name.StartsWith("Standard") || name.Contains("Specular") || !val.IsKeywordEnabled("_ALPHABLEND_ON") || !val.HasProperty("_MainTex") || !val.HasProperty("_Color") || !val.HasProperty("_SrcBlend") || val.GetFloat("_SrcBlend") != 5f || val.GetFloat("_DstBlend") != 10f) { continue; } int num3 = 0; string[] shaderKeywords = val.shaderKeywords; foreach (string text in shaderKeywords) { switch (text) { case "_NORMALMAP": num3++; continue; case "_EMISSION": num3--; continue; case "_ALPHABLEND_ON": continue; } if (!text.StartsWith("_ADD") && !text.StartsWith("_VALUENOISE")) { num3 -= 10; } } if (name.Contains("TwoSided")) { if (num3 > num2) { num2 = num3; _twoSidedTemplate = val; } } else if (num3 > num) { num = num3; _standardTemplate = val; } } if ((Object)(object)_standardTemplate == (Object)null && (Object)(object)_twoSidedTemplate == (Object)null) { Shader val2 = Shader.Find("Standard"); if ((Object)(object)val2 != (Object)null) { Material val3 = new Material(val2) { name = "SeeThrough Standard Fade", hideFlags = (HideFlags)52 }; val3.SetFloat("_Mode", 2f); val3.SetFloat("_SrcBlend", 5f); val3.SetFloat("_DstBlend", 10f); val3.SetFloat("_ZWrite", 0f); val3.DisableKeyword("_ALPHATEST_ON"); val3.EnableKeyword("_ALPHABLEND_ON"); val3.DisableKeyword("_ALPHAPREMULTIPLY_ON"); val3.renderQueue = 3000; _standardTemplate = val3; Plugin.Log.LogWarning((object)"No game material uses the Standard shader in Fade mode; built one from Shader.Find(\"Standard\"). If faded objects look solid, set [Fade] Style = Hide."); } } if ((Object)(object)_standardTemplate == (Object)null && (Object)(object)_twoSidedTemplate == (Object)null) { if (!_noTemplateWarned) { Plugin.Log.LogWarning((object)"No see-through material found in the game; Transparent fading uses Hide for now."); } _noTemplateWarned = true; return false; } if (!_templateLogged) { _templateLogged = true; Plugin.Log.LogInfo((object)("See-through templates: " + Describe(_standardTemplate) + "; two-sided: " + Describe(_twoSidedTemplate))); } return true; } private static string Describe(Material m) { if (!((Object)(object)m == (Object)null)) { return string.Format("'{0}' ({1}, queue {2}, keywords {3})", ((Object)m).name, ((Object)m.shader).name, m.renderQueue, string.Join(" ", m.shaderKeywords)); } return "none"; } } public enum FadeMode { Dither, Transparent, Hide } [Flags] public enum Kinds { None = 0, Trees = 1, Bushes = 2, Rocks = 4, Pieces = 8, Other = 0x10 } [BepInPlugin("vh.seethrough", "SeeThrough", "1.0.0")] public class Plugin : BaseUnityPlugin { public const string Guid = "vh.seethrough"; public const string Name = "SeeThrough"; public const string Version = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<KeyboardShortcut> ToggleKey; internal static ConfigEntry<FadeMode> Style; internal static ConfigEntry<float> Opacity; internal static ConfigEntry<float> NearOpacity; internal static ConfigEntry<float> SwapOpacity; internal static ConfigEntry<float> NearDistance; internal static ConfigEntry<float> FarDistance; internal static ConfigEntry<float> FadeTime; internal static ConfigEntry<Kinds> FadeKinds; internal static ConfigEntry<bool> CameraPassThrough; internal static ConfigEntry<bool> DitherWithoutTaa; internal static ConfigEntry<bool> HideWhenInside; internal static ConfigEntry<bool> FadeShadows; internal static ConfigEntry<float> HideDistance; internal static ConfigEntry<float> ViewRadius; internal static ConfigEntry<bool> ClearCrosshair; internal static ConfigEntry<float> CanopyReach; internal static ConfigEntry<float> PlayerClearance; internal static ConfigEntry<float> ScanInterval; internal static ConfigEntry<bool> WhileBuilding; internal static ConfigEntry<float> MinCameraDistance; internal static ConfigEntry<float> MaxCameraDistance; private Fader _fader; private Harmony _harmony; private const string CatGeneral = "1. General"; private const string CatLook = "2. Fading"; private const string CatCamera = "3. Camera"; private const string CatDetection = "4. Detection"; private static Func<bool> _rbcActive; private static bool _rbcLooked; private static ConfigDescription Describe(string category, string name, int order, string text, AcceptableValueBase range = null) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown return new ConfigDescription(text, range, new object[1] { new ConfigurationManagerAttributes { Category = category, DispName = name, Order = order } }); } private static AcceptableValueRange<float> Range(float min, float max) { return new AcceptableValueRange<float>(min, max); } private void Awake() { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0574: Unknown result type (might be due to invalid IL or missing references) //IL_057e: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, Describe("1. General", "Enabled", 2, "Fade trees, bushes, rocks and building pieces that stand between the camera and your character. Purely visual and only on your screen.")); ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", KeyboardShortcut.Empty, Describe("1. General", "Toggle key", 1, "Key that turns Enabled on and off while playing. Empty: no key.")); Style = ((BaseUnityPlugin)this).Config.Bind<FadeMode>("Fade", "Style", FadeMode.Dither, Describe("2. Fading", "Style", 10, "Dither: blockers keep their own look (colour, moss, wind) and are drawn with a fine screen-door pattern that thins out as they fade, the way Valheim fades trees in. Objects whose shader can't dither use Transparent. Transparent: blockers get alpha-blended copies (colour slightly off, no wind). Hide: blockers are not drawn at all while they block the view.")); FadeKinds = ((BaseUnityPlugin)this).Config.Bind<Kinds>("Fade", "Kinds", Kinds.Trees | Kinds.Bushes | Kinds.Rocks | Kinds.Pieces, Describe("2. Fading", "Objects that fade", 9, "Which objects fade. Trees: trees and logs. Bushes: bushes, berry bushes and other plants. Rocks: rocks and ore deposits. Pieces: anything built (walls, roofs, beams, furniture). Other: everything else with a collider, such as the static walls and rocks of dungeons and villages.")); Opacity = ((BaseUnityPlugin)this).Config.Bind<float>("Fade", "Opacity", 0.4f, Describe("2. Fading", "Opacity (far)", 8, "How solid a faded object stays when it is 'Far distance' or more from both the camera and your character: 0 = invisible, 1 = not faded.", (AcceptableValueBase)(object)Range(0f, 1f))); NearOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Fade", "NearOpacity", 0.1f, Describe("2. Fading", "Opacity (near)", 7, "How solid a faded object stays when it is 'Near distance' or less from the camera or from your character; objects in between get a value between this and 'Opacity (far)'. Set both the same for the same fade everywhere.", (AcceptableValueBase)(object)Range(0f, 1f))); NearDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Fade", "NearDistance", 1f, Describe("2. Fading", "Near distance", 6, "Metres from the camera or your character at which an object gets 'Opacity (near)'.", (AcceptableValueBase)(object)Range(0f, 10f))); FarDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Fade", "FarDistance", 4f, Describe("2. Fading", "Far distance", 5, "Metres from both the camera and your character at which an object gets 'Opacity (far)'.", (AcceptableValueBase)(object)Range(0.5f, 20f))); FadeTime = ((BaseUnityPlugin)this).Config.Bind<float>("Fade", "FadeTime", 0.4f, Describe("2. Fading", "Fade time", 4, "Seconds an object takes to (almost completely) fade out or back in. The fade eases out, so it starts quickly and settles softly; longer is smoother.", (AcceptableValueBase)(object)Range(0f, 2f))); FadeShadows = ((BaseUnityPlugin)this).Config.Bind<bool>("Fade", "FadeShadows", true, Describe("2. Fading", "Fade shadows", 3, "Shadows go with the object: a dithered object's shadow thins with it, and an object faded to nothing (or hidden in Hide style, or because the camera is right at it) casts no shadow. Off: hidden objects keep their full shadow.")); DitherWithoutTaa = ((BaseUnityPlugin)this).Config.Bind<bool>("Fade", "DitherWithoutTaa", true, Describe("2. Fading", "FXAA instead of TAA", 2, "Valheim's antialiasing is temporal (TAA), which smears the Dither pattern into a blocky blur, worst while the camera moves. On: while Style is Dither, Valheim's antialiasing uses FXAA instead (edges still smoothed, nothing smeared). The game's Antialiasing setting still turns it on or off. Off: keep TAA.")); SwapOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Fade", "SwapOpacity", 0.6f, Describe("2. Fading", "Swap opacity (Transparent)", 1, "Transparent style only. The see-through copy can't reproduce Valheim's moss, snow and colour tint, so shown nearly solid it flashes a different (often orange or yellow) colour. An object therefore switches to its copy already this see-through and fades on from there, and back at this value. Lower: less colour difference, bigger jump at the switch. 1: fade from fully solid.", (AcceptableValueBase)(object)Range(0f, 1f))); CameraPassThrough = ((BaseUnityPlugin)this).Config.Bind<bool>("Fade", "CameraPassThrough", true, Describe("3. Camera", "Camera keeps its distance", 5, "The camera no longer moves in towards you when one of the objects that fade is behind you; it keeps its distance and the object fades instead. Terrain and objects that don't fade still push the camera in as in vanilla. Off: vanilla camera collision.")); HideWhenInside = ((BaseUnityPlugin)this).Config.Bind<bool>("Fade", "HideWhenInside", true, Describe("3. Camera", "Fade objects at the camera", 4, "As the camera comes within 'Close-up distance' of a trunk, rock, wall or other object that fades, the object fades out smoothly and is completely gone before the camera is inside it, so you never see its dark inside. Off: objects only fade while they block the view.")); HideDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Fade", "HideDistance", 1.2f, Describe("3. Camera", "Close-up distance", 3, "Metres from the camera to an object's surface where the close-up fade starts. The object is fully gone at 0.2 m. Larger: a longer, softer fade.", (AcceptableValueBase)(object)Range(0.4f, 4f))); MinCameraDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Detection", "MinCameraDistance", 1f, Describe("3. Camera", "Min camera distance", 2, "Nothing fades when the camera is closer than this to your character (first-person views).", (AcceptableValueBase)(object)Range(0f, 5f))); MaxCameraDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Detection", "MaxCameraDistance", 20f, Describe("3. Camera", "Max camera distance", 1, "Nothing fades when the camera is farther than this from your character (free-fly, build and flight cameras).", (AcceptableValueBase)(object)Range(5f, 100f))); ClearCrosshair = ((BaseUnityPlugin)this).Config.Bind<bool>("Detection", "ClearCrosshair", true, Describe("4. Detection", "Keep the crosshair clear", 6, "Also fade what stands between the camera and the crosshair, up to your character's distance, so you can see what you aim at around your character. What you aim at beyond your character never fades. Off: only the line from the camera to your character is kept clear.")); ViewRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Detection", "ViewRadius", 0.4f, Describe("4. Detection", "View radius", 5, "Radius in metres of the clear line from the camera to your character. Bigger fades more objects around the line.", (AcceptableValueBase)(object)Range(0.05f, 2f))); CanopyReach = ((BaseUnityPlugin)this).Config.Bind<float>("Detection", "CanopyReach", 5f, Describe("4. Detection", "Tree top reach", 4, "Tree tops and bushes often have no collider, so trees and bushes whose trunk or stem is this many metres from the line are also checked, and fade if their leaves cross it. 0: only objects whose collider is on the line.", (AcceptableValueBase)(object)Range(0f, 12f))); PlayerClearance = ((BaseUnityPlugin)this).Config.Bind<float>("Detection", "PlayerClearance", 0.5f, Describe("4. Detection", "Character clearance", 3, "The line stops this many metres short of your character, so the floor you stand on and the wall you lean against don't fade.", (AcceptableValueBase)(object)Range(0f, 3f))); ScanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Detection", "ScanInterval", 0.1f, Describe("4. Detection", "Scan interval", 2, "Seconds between checks for blockers. Fading itself is animated every frame.", (AcceptableValueBase)(object)Range(0.02f, 1f))); WhileBuilding = ((BaseUnityPlugin)this).Config.Bind<bool>("Detection", "WhileBuilding", false, Describe("4. Detection", "Fade while building", 1, "Also fade while a hammer, hoe or cultivator is out (placement mode). Off: building pieces stay solid while you build. Runic Build Camera's free camera never fades anything.")); _fader = new Fader(); _harmony = new Harmony("vh.seethrough"); _harmony.PatchAll(); Style.SettingChanged += delegate { _fader.RestoreAll(); }; FadeShadows.SettingChanged += delegate { _fader.RestoreAll(); }; Enabled.SettingChanged += delegate { if (!Enabled.Value) { _fader.RestoreAll(); } }; } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) try { KeyboardShortcut value = ToggleKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey != 0) { value = ToggleKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Enabled.Value = !Enabled.Value; if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)1, "SeeThrough " + (Enabled.Value ? "on" : "off"), 0, (Sprite)null, false); } } } _fader.Update(); AntiAliasingSwap.Update(Enabled.Value && Style.Value == FadeMode.Dither && DitherWithoutTaa.Value); } catch (Exception ex) { Log.LogError((object)ex); _fader.RestoreAll(); } } private void LateUpdate() { try { _fader.LateUpdate(); } catch (Exception ex) { Log.LogError((object)ex); _fader.RestoreAll(); } } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _fader?.RestoreAll(); AntiAliasingSwap.Restore(); } internal static bool BuildCameraActive() { if (!_rbcLooked) { _rbcLooked = true; try { Type type = AccessTools.TypeByName("RunicBuildCamera.Integration.BuildCameraRuntime"); MethodInfo methodInfo = ((type == null) ? null : AccessTools.PropertyGetter(type, "IsActive")); if (methodInfo != null && methodInfo.IsStatic && methodInfo.ReturnType == typeof(bool)) { _rbcActive = (Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), methodInfo); } } catch (Exception ex) { Log.LogWarning((object)("Runic Build Camera check unavailable: " + ex.Message)); } } if (_rbcActive == null) { return false; } try { return _rbcActive(); } catch { _rbcActive = null; return false; } } } }