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 ClearSightCamera v1.1.0
ClearSightCamera.dll
Decompiled 4 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ClearSightCamera")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Azumatt")] [assembly: AssemblyProduct("ClearSightCamera")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("4358610B-F3F4-4843-B7AF-98B7BC60DCDE")] [assembly: AssemblyFileVersion("1.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ClearSightCamera { internal static class CameraClearController { private sealed class RendererFadeData { public Renderer Renderer; public Material[] OriginalShared = Array.Empty<Material>(); public Material[] GhostMats = Array.Empty<Material>(); } private static readonly List<Renderer> _hiddenRenderers = new List<Renderer>(); private static readonly HashSet<Renderer> _hiddenRendererSet = new HashSet<Renderer>(); private static readonly Dictionary<Renderer, bool> _originalEnabled = new Dictionary<Renderer, bool>(); private static readonly Dictionary<Renderer, bool> _originalForceOff = new Dictionary<Renderer, bool>(); private static readonly Dictionary<Renderer, RendererFadeData> _fadeData = new Dictionary<Renderer, RendererFadeData>(); private static int _geometryMask; private static int GeometryMask { get { if (_geometryMask != 0) { return _geometryMask; } _geometryMask = LayerMask.GetMask(new string[4] { "Default", "static_solid", "piece", "piece_nonsolid" }); return _geometryMask; } } public static void OnAfterCameraUpdate(GameCamera cam) { if (!Object.op_Implicit((Object)(object)cam) || !Object.op_Implicit((Object)(object)cam.m_camera)) { return; } if (cam.m_freeFly) { RestoreVisuals(); return; } Player localPlayer = Player.m_localPlayer; if (!Object.op_Implicit((Object)(object)localPlayer)) { RestoreVisuals(); return; } RestoreVisuals(); if (ClearSightCameraPlugin.CullingEnabled) { ApplyCulling(cam, localPlayer); } } private static Vector3 GetCameraTargetPosition(Player player) { //IL_0013: 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) //IL_003d: 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_004c: 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) if (Object.op_Implicit((Object)(object)((Character)player).m_eye)) { return ((Character)player).m_eye.position; } if (Object.op_Implicit((Object)(object)((Character)player).m_head)) { return ((Character)player).m_head.position; } return ((Component)player).transform.position + Vector3.up * 1.6f; } private static bool TryGetCullRoot(Collider col, out Transform root) { root = null; GameObject val = (Object.op_Implicit((Object)(object)col.attachedRigidbody) ? ((Component)col.attachedRigidbody).gameObject : ((Component)col).gameObject); if (!Object.op_Implicit((Object)(object)val)) { return false; } Player localPlayer = Player.m_localPlayer; if (Object.op_Implicit((Object)(object)localPlayer) && (Object)(object)val.GetComponentInParent<Player>() == (Object)(object)localPlayer) { return false; } Piece componentInParent = val.GetComponentInParent<Piece>(); if (Object.op_Implicit((Object)(object)componentInParent)) { root = ((Component)componentInParent).transform; return true; } root = val.transform; return true; } private static void ApplyCulling(GameCamera cam, Player player) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: 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_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_0051: 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_0059: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) Camera camera = cam.m_camera; if (!Object.op_Implicit((Object)(object)camera)) { return; } Vector3 position = ((Component)camera).transform.position; Vector3 cameraTargetPosition = GetCameraTargetPosition(player); Vector3 val = cameraTargetPosition - position; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.1f) { return; } float num = Mathf.Min(magnitude, ClearSightCameraPlugin.CullMaxDistanceCfg.Value); Vector3 val2 = val / magnitude; float num2 = Mathf.Max(0.05f, ClearSightCameraPlugin.CullRadiusCfg.Value); RaycastHit[] array = Physics.SphereCastAll(position, num2, val2, num, GeometryMask, (QueryTriggerInteraction)2); if (array.Length == 0) { return; } RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val3 = array2[i]; Collider collider = ((RaycastHit)(ref val3)).collider; if (Object.op_Implicit((Object)(object)collider) && ShouldCullCollider(camera, cameraTargetPosition, collider, out Component root)) { CullUnderRoot(root); } } } private static bool IsObstructingPlayer(Camera cam, Vector3 playerEyePos, Collider col) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0026: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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) //IL_003a: 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_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_0068: 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_006d: 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_0074: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_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) Vector3 position = ((Component)cam).transform.position; Vector3 val = playerEyePos - position; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude < 0.1f) { return false; } Vector3 val2 = val / magnitude; Vector3 val3 = SafeClosestPoint(col, playerEyePos); float num = Vector3.Dot(val3 - position, val2); float num2 = magnitude; if (num <= 0f || num >= num2 + 0.05f) { return false; } Vector3 val4 = cam.WorldToViewportPoint(playerEyePos); Vector3 val5 = cam.WorldToViewportPoint(val3); if (val5.z <= 0f) { return false; } Vector2 val6 = new Vector2(val4.x, val4.y); Vector2 val7 = default(Vector2); ((Vector2)(ref val7))..ctor(val5.x, val5.y); Vector2 val8 = val6 - val7; float sqrMagnitude = ((Vector2)(ref val8)).sqrMagnitude; float value = ClearSightCameraPlugin.CullRadiusCfg.Value; return sqrMagnitude <= value * value; } private static Vector3 SafeClosestPoint(Collider col, Vector3 targetWorldPos) { //IL_0008: 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) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)col)) { return targetWorldPos; } if (!(col is BoxCollider) && !(col is SphereCollider) && !(col is CapsuleCollider)) { MeshCollider val = (MeshCollider)(object)((col is MeshCollider) ? col : null); if (val != null && val.convex) { return ((Collider)val).ClosestPoint(targetWorldPos); } Bounds bounds = col.bounds; return ((Bounds)(ref bounds)).ClosestPoint(targetWorldPos); } return col.ClosestPoint(targetWorldPos); } private static bool ShouldCullCollider(Camera cam, Vector3 playerEyePos, Collider col, out Component root) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) root = null; GameObject val = (Object.op_Implicit((Object)(object)col.attachedRigidbody) ? ((Component)col.attachedRigidbody).gameObject : ((Component)col).gameObject); if (!Object.op_Implicit((Object)(object)val)) { return false; } if (Object.op_Implicit((Object)(object)val.GetComponentInParent<Player>())) { return false; } if (Object.op_Implicit((Object)(object)val.GetComponentInParent<Character>())) { return false; } if (Object.op_Implicit((Object)(object)val.GetComponentInParent<ItemDrop>())) { return false; } if (!IsObstructingPlayer(cam, playerEyePos, col)) { return false; } Piece componentInParent = val.GetComponentInParent<Piece>(); if (Object.op_Implicit((Object)(object)componentInParent)) { root = (Component)(object)componentInParent; return true; } root = (Component)(object)val.transform; return true; } private static bool HasComponentInHierarchy<T>(GameObject go) where T : Component { if (!((Object)(object)go.GetComponentInParent<T>() != (Object)null)) { return (Object)(object)go.GetComponentInChildren<T>(true) != (Object)null; } return true; } private static bool HasHoverOrInteractInHierarchy(GameObject go) { MonoBehaviour[] componentsInParent = go.GetComponentsInParent<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInParent) { if ((val is Hoverable || val is Interactable) ? true : false) { return true; } } MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val2 in componentsInChildren) { if ((val2 is Hoverable || val2 is Interactable) ? true : false) { return true; } } return false; } private static void CullUnderRoot(Component root) { if (Object.op_Implicit((Object)(object)root)) { GameObject gameObject = root.gameObject; ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)("CULL UNDER ROOT [HoverFix] Hit " + ((Object)gameObject).name + ", " + $"occluder={(Object)(object)gameObject.GetComponentInParent<ClearSightOccluderTag>() != (Object)null}, " + $"hasHover={gameObject.GetComponentInParent<Hoverable>() != null}, " + $"hasInteract={gameObject.GetComponentInParent<Interactable>() != null}")); if (Object.op_Implicit((Object)(object)gameObject) && !Object.op_Implicit((Object)(object)gameObject.GetComponent<ClearSightOccluderTag>())) { gameObject.AddComponent<ClearSightOccluderTag>(); } if (ClearSightCameraPlugin.UseTransparency && (Object)(object)ClearSightTransparentTemplateProvider.Template != (Object)null) { FadeRenderersUnder(root, ClearSightCameraPlugin.FadeAlpha); } else { HideRenderersUnder(root); } } } private static void HideRenderersUnder(Component root) { Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (Object.op_Implicit((Object)(object)val) && !_hiddenRendererSet.Contains(val) && (val.enabled || _originalEnabled.ContainsKey(val))) { if (!_originalEnabled.ContainsKey(val)) { _originalEnabled[val] = val.enabled; _originalForceOff[val] = val.forceRenderingOff; } val.forceRenderingOff = true; _hiddenRendererSet.Add(val); _hiddenRenderers.Add(val); } } } private static void FadeRenderersUnder(Component root, float targetAlpha) { //IL_00b5: 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_00c6: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = root.GetComponentsInChildren<Renderer>(true); targetAlpha = Mathf.Clamp01(targetAlpha); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if (!Object.op_Implicit((Object)(object)val)) { continue; } if (!_fadeData.TryGetValue(val, out RendererFadeData value)) { value = new RendererFadeData { Renderer = val, OriginalShared = val.sharedMaterials, GhostMats = BuildGhostMaterials(val.sharedMaterials) }; _fadeData.Add(val, value); } if (value.GhostMats == null || value.GhostMats.Length == 0) { continue; } val.sharedMaterials = value.GhostMats; Material[] ghostMats = value.GhostMats; foreach (Material val2 in ghostMats) { if (Object.op_Implicit((Object)(object)val2) && val2.HasProperty("_Color")) { Color color = val2.color; color.a = targetAlpha; val2.color = color; } } } } private static Material[] BuildGhostMaterials(Material[] originals) { //IL_0041: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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) if (originals == null || originals.Length == 0) { return Array.Empty<Material>(); } Material template = ClearSightTransparentTemplateProvider.Template; if (!Object.op_Implicit((Object)(object)template)) { return Array.Empty<Material>(); } Material[] array = (Material[])(object)new Material[originals.Length]; for (int i = 0; i < originals.Length; i++) { Material val = originals[i]; if (Object.op_Implicit((Object)(object)val)) { Material val2 = new Material(template) { name = ((Object)val).name + " (ClearSightGhost)", mainTexture = val.mainTexture, mainTextureScale = val.mainTextureScale, mainTextureOffset = val.mainTextureOffset }; if (val.HasProperty("_Color") && val2.HasProperty("_Color")) { Color color = val.color; color.a = ClearSightCameraPlugin.FadeAlpha; val2.color = color; } else if (val2.HasProperty("_Color")) { Color color2 = val2.color; color2.a = ClearSightCameraPlugin.FadeAlpha; val2.color = color2; } array[i] = val2; } } return array; } private static void RestoreVisuals() { if (_fadeData.Count > 0) { foreach (KeyValuePair<Renderer, RendererFadeData> fadeDatum in _fadeData) { RendererFadeData value = fadeDatum.Value; if (Object.op_Implicit((Object)(object)value.Renderer) && value.OriginalShared != null && value.OriginalShared.Length != 0) { value.Renderer.sharedMaterials = value.OriginalShared; } } } if (_hiddenRenderers.Count <= 0) { return; } for (int i = 0; i < _hiddenRenderers.Count; i++) { Renderer val = _hiddenRenderers[i]; if (Object.op_Implicit((Object)(object)val)) { if (_originalEnabled.TryGetValue(val, out var value2)) { val.enabled = value2; } if (_originalForceOff.TryGetValue(val, out var value3)) { val.forceRenderingOff = value3; } else { val.forceRenderingOff = false; } } } _hiddenRenderers.Clear(); _hiddenRendererSet.Clear(); _originalEnabled.Clear(); _originalForceOff.Clear(); } } internal static class ClearSightHoverResolver { internal static bool TryResolveHoverBehindOccluder(Player player, out GameObject bestHover, out Character bestChar) { //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_003a: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Expected O, but got Unknown //IL_01b6: Unknown result type (might be due to invalid IL or missing references) bestHover = null; bestChar = null; GameCamera instance = GameCamera.instance; if (!Object.op_Implicit((Object)(object)instance) || !Object.op_Implicit((Object)(object)instance.m_camera)) { return false; } Camera camera = instance.m_camera; Vector3 position = ((Component)camera).transform.position; Vector3 forward = ((Component)camera).transform.forward; int interactMask = player.m_interactMask; RaycastHit[] array = Physics.RaycastAll(position, forward, 50f, interactMask, (QueryTriggerInteraction)2); if (array == null || array.Length == 0) { return false; } Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit val = array2[i]; Collider collider = ((RaycastHit)(ref val)).collider; if (!Object.op_Implicit((Object)(object)collider)) { continue; } GameObject val2 = (Object.op_Implicit((Object)(object)collider.attachedRigidbody) ? ((Component)collider.attachedRigidbody).gameObject : ((Component)collider).gameObject); if (!Object.op_Implicit((Object)(object)val2)) { continue; } bool flag = (Object)(object)val2.GetComponentInParent<ClearSightOccluderTag>() != (Object)null; Hoverable componentInParent = val2.GetComponentInParent<Hoverable>(); Interactable componentInParent2 = val2.GetComponentInParent<Interactable>(); Character componentInParent3 = val2.GetComponentInParent<Character>(); ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)("TryResolveHoverBehindOccluder[HoverFix] Hit " + ((Object)val2).name + ", " + $"occluder={flag}, hasHover={componentInParent != null}, hasInteract={componentInParent2 != null}")); if ((Object)(object)val2.GetComponentInParent<Player>() == (Object)(object)player || (flag && (Object)(object)componentInParent3 == (Object)null && componentInParent == null && componentInParent2 == null)) { continue; } if (Object.op_Implicit((Object)(object)componentInParent3) && (Object)(object)componentInParent3 != (Object)(object)player) { bestHover = ((Component)componentInParent3).gameObject; bestChar = componentInParent3; break; } if (componentInParent != null || componentInParent2 != null) { ? val3 = (Component)componentInParent; if ((int)val3 == 0) { val3 = (Component)componentInParent2; } Component val4 = (Component)val3; if (Object.op_Implicit((Object)(object)val4)) { bestChar = (bestHover = val4.gameObject).GetComponentInParent<Character>(); break; } } Piece componentInParent4 = val2.GetComponentInParent<Piece>(); if (Object.op_Implicit((Object)(object)componentInParent4)) { bestHover = ((Component)componentInParent4).gameObject; bestChar = ((Component)componentInParent4).GetComponentInParent<Character>(); break; } } return (Object)(object)bestHover != (Object)null; } } [HarmonyPatch(typeof(Player), "UpdateHover")] internal static class Player_UpdateHover_ClearSightPatch { private static void Postfix(Player __instance) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !ClearSightCameraPlugin.CullingEnabled || !Object.op_Implicit((Object)(object)__instance.m_hovering)) { return; } GameObject hovering = __instance.m_hovering; if (Object.op_Implicit((Object)(object)hovering.GetComponentInParent<ClearSightOccluderTag>()) && hovering.GetComponentInParent<Hoverable>() == null && hovering.GetComponentInParent<Interactable>() == null) { if (!ClearSightHoverResolver.TryResolveHoverBehindOccluder(__instance, out GameObject bestHover, out Character bestChar)) { __instance.m_hovering = null; __instance.m_hoveringCreature = null; } else { __instance.m_hovering = bestHover; __instance.m_hoveringCreature = bestChar; } } } } [HarmonyPatch(typeof(Player), "RemovePiece")] internal static class Player_RemovePiece_ClearSightPatch { private static void Prefix(Player __instance) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ClearSightCameraPlugin.CullingEnabled && Object.op_Implicit((Object)(object)__instance.m_hovering) && Object.op_Implicit((Object)(object)__instance.m_hovering.GetComponentInParent<ClearSightOccluderTag>())) { if (!ClearSightHoverResolver.TryResolveHoverBehindOccluder(__instance, out GameObject bestHover, out Character bestChar)) { __instance.m_hovering = null; __instance.m_hoveringCreature = null; } else { __instance.m_hovering = bestHover; __instance.m_hoveringCreature = bestChar; } } } } [HarmonyPatch(typeof(Player), "Interact")] internal static class Player_Interact_ClearSightPatch { private static void Prefix(Player __instance, ref GameObject go, bool hold, bool alt) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ClearSightCameraPlugin.CullingEnabled && Object.op_Implicit((Object)(object)go) && Object.op_Implicit((Object)(object)go.GetComponentInParent<ClearSightOccluderTag>()) && go.GetComponentInParent<Hoverable>() == null && go.GetComponentInParent<Interactable>() == null && ClearSightHoverResolver.TryResolveHoverBehindOccluder(__instance, out GameObject bestHover, out Character bestChar)) { ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)("Player.Interact redirect: " + ((Object)go).name + " (occluder) → " + ((Object)bestHover).name)); go = bestHover; __instance.m_hovering = bestHover; __instance.m_hoveringCreature = bestChar; } } } public sealed class ClearSightOccluderTag : MonoBehaviour { } internal static class ClearSightTransparentTemplateProvider { private static bool _initialized; private static Material _template; internal static Material Template { get { if (!_initialized) { InitializeLazy(); } return _template; } } internal static void BootstrapFromFejdStartup(FejdStartup fejd) { if (_initialized || !Object.op_Implicit((Object)(object)fejd) || !Object.op_Implicit((Object)(object)fejd.m_objectDBPrefab)) { return; } try { ZNetScene component = fejd.m_objectDBPrefab.GetComponent<ZNetScene>(); if (Object.op_Implicit((Object)(object)component) && TryInitFromArmorLeather(component)) { _initialized = true; } } catch (Exception arg) { ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)$"FejdStartup bootstrap failed: {arg}"); } } private static void InitializeLazy() { if (!_initialized) { _initialized = true; if (!((Object)(object)_template != (Object)null) && !TryInitFromAnyStandardMaterial() && !TryInitFromAnyTransparentMaterial()) { ClearSightCameraPlugin.ClearSightCameraLogger.LogWarning((object)"Could not find any suitable transparent template. Transparent culling will fall back to Hidden mode."); } } } private static bool TryInitFromArmorLeather(ZNetScene scene) { if (!Object.op_Implicit((Object)(object)scene)) { return false; } string[] array = new string[4] { "ArmorLeather", "ArmorLeatherChest", "ArmorLeatherLegs", "ArmorLeatherHelmet" }; foreach (string prefabName in array) { GameObject val = ((IEnumerable<GameObject>)scene.m_prefabs).FirstOrDefault((Func<GameObject, bool>)((GameObject x) => Object.op_Implicit((Object)(object)x) && ((Object)x).name == prefabName)); if (Object.op_Implicit((Object)(object)val) && TryBuildTemplateFromRenderers(val.GetComponentsInChildren<Renderer>(true))) { return true; } } return false; } private static bool TryInitFromAnyStandardMaterial() { try { Material[] array = Resources.FindObjectsOfTypeAll<Material>(); foreach (Material val in array) { if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val.shader == (Object)null) && ((Object)val.shader).name.Contains("Standard") && TryBuildTemplateFromMaterial(val, "Standard material '" + ((Object)val).name + "'")) { return true; } } } catch (Exception arg) { ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)$"Standard material scan failed: {arg}"); } return false; } private static bool TryInitFromAnyTransparentMaterial() { try { foreach (Material item in from m in Resources.FindObjectsOfTypeAll<Material>() orderby m.renderQueue select m) { if (Object.op_Implicit((Object)(object)item) && item.HasProperty("_Color") && item.HasProperty("_MainTex") && item.renderQueue >= 3000 && TryBuildTemplateFromMaterial(item, "transparent material '" + ((Object)item).name + "'")) { return true; } } } catch (Exception arg) { ClearSightCameraPlugin.ClearSightCameraLogger.LogDebug((object)$"Transparent material scan failed: {arg}"); } return false; } private static bool TryBuildTemplateFromRenderers(IEnumerable<Renderer> renderers) { foreach (Renderer renderer in renderers) { if (!Object.op_Implicit((Object)(object)renderer)) { continue; } Material[] sharedMaterials = renderer.sharedMaterials; if (sharedMaterials == null) { continue; } Material[] array = sharedMaterials; foreach (Material val in array) { if (Object.op_Implicit((Object)(object)val) && !((Object)(object)val.shader == (Object)null) && ((Object)val.shader).name.Contains("Standard") && TryBuildTemplateFromMaterial(val, "ArmorLeather material '" + ((Object)val).name + "'")) { return true; } } } return false; } private static bool TryBuildTemplateFromMaterial(Material source, string reason) { //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_002a: Expected O, but got Unknown if (!Object.op_Implicit((Object)(object)source) || (Object)(object)source.shader == (Object)null) { return false; } Material val = new Material(source) { name = "ClearSight_TransparentTemplate" }; if (val.HasProperty("_Mode") && val.HasProperty("_SrcBlend") && val.HasProperty("_DstBlend") && val.HasProperty("_ZWrite")) { val.SetFloat("_Mode", 2f); val.SetInt("_SrcBlend", 5); val.SetInt("_DstBlend", 10); val.SetInt("_ZWrite", 0); val.DisableKeyword("_ALPHATEST_ON"); val.EnableKeyword("_ALPHABLEND_ON"); val.DisableKeyword("_ALPHAPREMULTIPLY_ON"); } val.renderQueue = 3000; _template = val; ClearSightCameraPlugin.ClearSightCameraLogger.LogInfo((object)("Using " + reason + " (shader '" + ((Object)source.shader).name + "') as transparent template.")); return true; } } [HarmonyPatch(typeof(FejdStartup), "Awake")] internal static class FejdStartup_Awake_ClearSightBootstrap { private static void Postfix(FejdStartup __instance) { ClearSightTransparentTemplateProvider.BootstrapFromFejdStartup(__instance); } } [HarmonyPatch(typeof(Piece), "GetAllComfortPiecesInRadius")] internal static class Piece_GetAllComfortPiecesInRadius_SanitizePatch { private static void Prefix() { try { List<Piece> s_allPieces = Piece.s_allPieces; if (s_allPieces == null) { return; } for (int num = s_allPieces.Count - 1; num >= 0; num--) { if (!Object.op_Implicit((Object)(object)s_allPieces[num])) { s_allPieces.RemoveAt(num); } } } catch (Exception arg) { ClearSightCameraPlugin.ClearSightCameraLogger.LogError((object)$"Failed to sanitize Piece.m_allPieces: {arg}"); } } } [HarmonyPatch(typeof(GameCamera), "LateUpdate")] internal static class GameCamera_LateUpdate_ClearSightPatch { private static void Postfix(GameCamera __instance) { CameraClearController.OnAfterCameraUpdate(__instance); } } [HarmonyPatch(typeof(GameCamera), "CollideRay2")] internal static class GameCamera_CollideRay2_ClearSightPatch { private static bool Prefix(GameCamera __instance, Vector3 eyePos, Vector3 offsetedEyePos, ref Vector3 end) { //IL_001d: 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_0035: 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) //IL_0040: 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_0049: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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_00bb: 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_00c2: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: 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_00d7: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: 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_00eb: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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_0102: 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_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) if (!ClearSightCameraPlugin.NoClipEnabled) { return true; } int mask = LayerMask.GetMask(new string[1] { "terrain" }); float num = Vector3.Distance(eyePos, end); if (num <= 0.01f) { return false; } Vector3 val = end - offsetedEyePos; Vector3 normalized = ((Vector3)(ref val)).normalized; if (((Vector3)(ref normalized)).sqrMagnitude < 1E-06f) { return false; } float num2 = num; bool flag = false; float raycastWidth = __instance.m_raycastWidth; RaycastHit val2 = default(RaycastHit); if (Physics.SphereCast(offsetedEyePos, raycastWidth, normalized, ref val2, num, mask)) { num2 = ((RaycastHit)(ref val2)).distance; flag = true; } if (Physics.SphereCast(eyePos, raycastWidth, normalized, ref val2, num, mask)) { if (((RaycastHit)(ref val2)).distance < num2) { num2 = ((RaycastHit)(ref val2)).distance; } flag = true; } if (flag) { float num3 = Utils.LerpStep(0.5f, 2f, num2); val = end - eyePos; Vector3 val3 = eyePos + ((Vector3)(ref val)).normalized * num2; val = end - offsetedEyePos; Vector3 val4 = offsetedEyePos + ((Vector3)(ref val)).normalized * num2; end = Vector3.Lerp(val3, val4, num3); } return false; } } [HarmonyPatch(typeof(GameCamera), "Awake")] internal static class GameCamera_Awake_ClearSightPatch { private static void Postfix(GameCamera __instance) { float value = ClearSightCameraPlugin.MaxDistanceCfg.Value; if (!(value <= 0f)) { if (value > __instance.m_maxDistance) { __instance.m_maxDistance = value; } if (value > __instance.m_maxDistanceBoat) { __instance.m_maxDistanceBoat = value; } } } } [BepInPlugin("Azumatt.ClearSightCamera", "ClearSightCamera", "1.1.0")] public class ClearSightCameraPlugin : BaseUnityPlugin { public enum Toggle { On = 1, Off = 0 } public enum CullingVisualMode { Hidden, Transparent } internal const string ModName = "ClearSightCamera"; internal const string ModVersion = "1.1.0"; internal const string Author = "Azumatt"; private const string ModGUID = "Azumatt.ClearSightCamera"; private static readonly string ConfigFileName = "Azumatt.ClearSightCamera.cfg"; private static readonly string ConfigFileFullPath; internal static readonly ManualLogSource ClearSightCameraLogger; private readonly Harmony _harmony = new Harmony("Azumatt.ClearSightCamera"); private FileSystemWatcher _watcher; private readonly object _reloadLock = new object(); private DateTime _lastConfigReloadTime; private const long RELOAD_DELAY = 10000000L; internal static ClearSightCameraPlugin Instance; internal static bool CullingEnabled; internal static bool NoClipEnabled; internal static ConfigEntry<KeyboardShortcut> ToggleCullKey; internal static ConfigEntry<KeyboardShortcut> ToggleNoClipKey; internal static ConfigEntry<Toggle> CullingEnabledCfg; internal static ConfigEntry<Toggle> NoClipEnabledCfg; internal static ConfigEntry<float> MaxDistanceCfg; internal static ConfigEntry<float> GroundPaddingCfg; internal static ConfigEntry<float> CullRadiusCfg; internal static ConfigEntry<float> CullMaxDistanceCfg; internal static ConfigEntry<CullingVisualMode> CullingVisualModeCfg; internal static ConfigEntry<float> CullingFadeAlphaCfg; internal static bool UseTransparency { get { ConfigEntry<CullingVisualMode> cullingVisualModeCfg = CullingVisualModeCfg; if (cullingVisualModeCfg != null) { return cullingVisualModeCfg.Value == CullingVisualMode.Transparent; } return false; } } internal static float FadeAlpha => Mathf.Clamp01(CullingFadeAlphaCfg?.Value ?? 0.25f); public void Awake() { Instance = this; bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; CreateConfigEntries(); CullingEnabled = CullingEnabledCfg.Value.IsOn(); NoClipEnabled = NoClipEnabledCfg.Value.IsOn(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); _harmony.PatchAll(executingAssembly); SetupWatcher(); ((BaseUnityPlugin)this).Config.Save(); if (saveOnConfigSet) { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } } 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_006d: 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_0075: 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_0081: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = ToggleCullKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && ToggleCullKey.Value.IsKeyDown()) { CullingEnabled = !CullingEnabled; CullingEnabledCfg.Value = CullingEnabled.ToToggle(); ShowMessage("Camera culling: " + (CullingEnabled ? "ON" : "OFF")); } value = ToggleNoClipKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey != 0 && ToggleNoClipKey.Value.IsKeyDown()) { NoClipEnabled = !NoClipEnabled; NoClipEnabledCfg.Value = NoClipEnabled.ToToggle(); ShowMessage("Camera no-clip: " + (NoClipEnabled ? "ON" : "OFF")); } } internal static void ShowMessage(string msg) { if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { ((Character)Player.m_localPlayer).Message((MessageType)2, msg, 0, (Sprite)null); } else { ClearSightCameraLogger.LogInfo((object)msg); } } private void OnDestroy() { SaveWithRespectToConfigSet(); _watcher?.Dispose(); } private void CreateConfigEntries() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) ToggleCullKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - Hotkeys", "Toggle Culling Key", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Toggle camera occluder culling (roof/wall hiding) on/off."); ToggleNoClipKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("1 - Hotkeys", "Toggle No-Clip Key", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), "Toggle camera no-clip (ignore walls, respect ground) on/off."); CullingEnabledCfg = ((BaseUnityPlugin)this).Config.Bind<Toggle>("2 - Culling", "Culling Enabled", Toggle.On, "If true, the mod will attempt to hide occluding pieces between camera and player."); CullingVisualModeCfg = ((BaseUnityPlugin)this).Config.Bind<CullingVisualMode>("2 - Culling", "Culling Visual Mode", CullingVisualMode.Transparent, "How to visually treat occluding pieces between camera and player.\nHidden = fully disable renderers.\nTransparent = keep them visible but fade to the configured alpha."); CullingFadeAlphaCfg = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Culling", "Culling Fade Alpha", 0.25f, "Alpha value (0–1) used when Culling Visual Mode is Transparent."); CullRadiusCfg = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Culling", "Cull Sphere Radius", 1f, "Radius of the spherecast between camera and player used to find occluding pieces."); CullMaxDistanceCfg = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Culling", "Cull Max Distance", 15f, "Maximum distance from the camera along the ray to look for occluders."); NoClipEnabledCfg = ((BaseUnityPlugin)this).Config.Bind<Toggle>("3 - NoClip", "NoClip Enabled", Toggle.On, "If true, the mod will override camera collision and allow the camera to stay zoomed out, still respecting terrain."); MaxDistanceCfg = ((BaseUnityPlugin)this).Config.Bind<float>("3 - NoClip", "Forced Max Distance", 12f, "Target camera distance when no-clip is active. The vanilla max distance is around ~6 in most cases."); GroundPaddingCfg = ((BaseUnityPlugin)this).Config.Bind<float>("3 - NoClip", "Ground Padding", 0.5f, "Minimum distance above terrain to keep the camera when no-clip is active."); } private void SetupWatcher() { _watcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); _watcher.Changed += ReadConfigValues; _watcher.Created += ReadConfigValues; _watcher.Renamed += ReadConfigValues; _watcher.IncludeSubdirectories = true; _watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _watcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { DateTime now = DateTime.Now; if (now.Ticks - _lastConfigReloadTime.Ticks < 10000000) { return; } lock (_reloadLock) { if (!File.Exists(ConfigFileFullPath)) { ClearSightCameraLogger.LogWarning((object)"Config file does not exist. Skipping reload."); return; } try { ClearSightCameraLogger.LogDebug((object)"Reloading configuration..."); SaveWithRespectToConfigSet(reload: true); CullingEnabled = CullingEnabledCfg.Value.IsOn(); NoClipEnabled = NoClipEnabledCfg.Value.IsOn(); ClearSightCameraLogger.LogInfo((object)"Configuration reload complete."); } catch (Exception ex) { ClearSightCameraLogger.LogError((object)("Error reloading configuration: " + ex.Message)); } } _lastConfigReloadTime = now; } private void SaveWithRespectToConfigSet(bool reload = false) { bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet; ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; if (reload) { ((BaseUnityPlugin)this).Config.Reload(); } ((BaseUnityPlugin)this).Config.Save(); if (saveOnConfigSet) { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet; } } static ClearSightCameraPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; ClearSightCameraLogger = Logger.CreateLogSource("ClearSightCamera"); Instance = null; ToggleCullKey = null; ToggleNoClipKey = null; CullingEnabledCfg = null; NoClipEnabledCfg = null; MaxDistanceCfg = null; GroundPaddingCfg = null; CullRadiusCfg = null; CullMaxDistanceCfg = null; CullingVisualModeCfg = null; CullingFadeAlphaCfg = null; } } public static class KeyboardExtensions { public static bool IsKeyDown(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } return false; } public static bool IsKeyHeld(this KeyboardShortcut shortcut) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref shortcut)).MainKey != 0 && Input.GetKey(((KeyboardShortcut)(ref shortcut)).MainKey)) { return ((KeyboardShortcut)(ref shortcut)).Modifiers.All((Func<KeyCode, bool>)Input.GetKey); } return false; } } public static class ToggleExtensions { public static bool IsOn(this ClearSightCameraPlugin.Toggle value) { return value == ClearSightCameraPlugin.Toggle.On; } public static bool IsOff(this ClearSightCameraPlugin.Toggle value) { return value == ClearSightCameraPlugin.Toggle.Off; } public static ClearSightCameraPlugin.Toggle ToToggle(this bool value) { if (!value) { return ClearSightCameraPlugin.Toggle.Off; } return ClearSightCameraPlugin.Toggle.On; } } }