using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using JetBrains.Annotations; using LCVR; using LCVR.Assets; using LCVR.Input; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using PEAKLib.UI; using PEAKLib.UI.Elements; using PeakVR; using Photon.Pun; using Photon.Realtime; using Steamworks; using TMPro; using UnityEngine; using UnityEngine.Animations.Rigging; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Experimental.Rendering; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.XR; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; using UnityEngine.SpatialTracking; using UnityEngine.UI; using UnityEngine.XR; using UnityEngine.XR.Interaction.Toolkit.Inputs.Composites; using UnityEngine.XR.Interaction.Toolkit.Inputs.Interactions; using UnityEngine.XR.Interaction.Toolkit.UI; using UnityEngine.XR.Management; using UnityEngine.XR.OpenXR; using UnityEngine.XR.OpenXR.Features; using UnityEngine.XR.OpenXR.Features.Interactions; using Zorro.ControllerSupport; using Zorro.Core; using Zorro.UI.Modal; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.andrey04o.PeakVR")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+b4b3ff0a536f5a5f73d9d77c1cb2bc48e7ee6ea6")] [assembly: AssemblyProduct("com.andrey04o.PeakVR")] [assembly: AssemblyTitle("PeakVR")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.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] [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] [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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace LCVR { public class Config { public string AssemblyPath { get; } public ConfigFile File { get; } public ConfigEntry OpenXRRuntime { get; } public ConfigEntry EnableVerboseLogging { get; } public ConfigEntry SmoothTurn { get; } public ConfigEntry SnapTurnAngle { get; } public ConfigEntry SmoothTurnSpeed { get; } public ConfigEntry MovementTunneling { get; } public ConfigEntry TunnelingStrength { get; } public ConfigEntry HideControllers { get; } public ConfigEntry InteractionLine { get; } public ConfigEntry HudLine { get; } public ConfigEntry AimAtObjectCenter { get; } public ConfigEntry ArmSpanScale { get; } public ConfigEntry VirtualArmSpan { get; } public ConfigEntry OpenXRRuntimeFile { get; } public Config(string assemblyPath, ConfigFile file) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Expected O, but got Unknown //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Expected O, but got Unknown //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Expected O, but got Unknown //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Expected O, but got Unknown AssemblyPath = assemblyPath; File = file; OpenXRRuntime = file.Bind("VR", "OpenXR Runtime", "System Default", new ConfigDescription("The OpenXR runtime (headset software) that VR launches with. Restart the game to apply.", (AcceptableValueBase)(object)new AcceptableValueList(OpenXR.GetRuntimeChoices().ToArray()), Array.Empty())); EnableVerboseLogging = file.Bind("VR", "Verbose Logging", false, "Enables verbose debug logging during OpenXR initialization."); SmoothTurn = file.Bind("Comfort", "Smooth Turn", false, "Turn smoothly with the right stick instead of snapping by a fixed angle."); SnapTurnAngle = file.Bind("Comfort", "Snap Turn Angle", 45f, new ConfigDescription("Degrees rotated per snap turn.", (AcceptableValueBase)(object)new AcceptableValueRange(15f, 90f), Array.Empty())); SmoothTurnSpeed = file.Bind("Comfort", "Smooth Turn Speed", 120f, new ConfigDescription("Smooth turn speed in degrees per second.", (AcceptableValueBase)(object)new AcceptableValueRange(45f, 240f), Array.Empty())); MovementTunneling = file.Bind("Comfort", "Movement Tunneling", true, "Close a tunnel around your view while moving or falling to reduce motion sickness."); TunnelingStrength = file.Bind("Comfort", "Tunneling Strength", 0.7f, new ConfigDescription("How far the tunnel closes in (smaller circle). 0 disables it.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); HideControllers = file.Bind("VR", "Hide Controllers", true, "Hide the VR controller models and show only your character's hands. Interaction/aim lasers then originate from your hand instead of the controller."); InteractionLine = file.Bind("Lasers", "Interaction Line", LineVisibility.OnInteract, "When to show the right-hand interaction line: Always, only when something is interactable (OnInteract), or never (Hidden)."); HudLine = file.Bind("Lasers", "HUD Pointer Line", LineVisibility.OnInteract, "When to show the left-controller HUD selection line: Always, only when pointing at a HUD item (OnInteract), or Hidden."); AimAtObjectCenter = file.Bind("Lasers", "Aim At Object Center", true, "When an interactable is available, snap the interaction line's end to the object's center instead of pointing straight ahead."); ArmSpanScale = file.Bind("VR", "Arm Span Scale", 1.089f, new ConfigDescription("Multiplier from your real arm reach to the character's arm reach. Calibrate it in-game with the T-pose window instead of editing by hand.", (AcceptableValueBase)(object)new AcceptableValueRange(0.6f, 1.8f), Array.Empty())); VirtualArmSpan = file.Bind("Internal", "VirtualArmSpan", 1.851f, new ConfigDescription("FOR INTERNAL USE ONLY, DO NOT EDIT — cached character wingspan for calibration.", (AcceptableValueBase)null, new object[1] { "Hidden" })); OpenXRRuntimeFile = file.Bind("Internal", "OpenXRRuntimeFile", "", new ConfigDescription("FOR INTERNAL USE ONLY, DO NOT EDIT", (AcceptableValueBase)null, new object[1] { "Hidden" })); OpenXRRuntimeFile.Value = OpenXR.ResolveRuntimePath(OpenXRRuntime.Value); OpenXRRuntime.SettingChanged += delegate { OpenXRRuntimeFile.Value = OpenXR.ResolveRuntimePath(OpenXRRuntime.Value); }; } } public static class Logger { private static ManualLogSource logSource; public static void SetSource(ManualLogSource Logger) { logSource = Logger; } public static void Log(object message) { logSource.LogInfo(message); } public static void LogInfo(object message) { logSource.LogInfo(message); } public static void LogWarning(object message) { logSource.LogWarning(message); } public static void LogError(object message) { logSource.LogError(message); } public static void LogDebug(object message) { logSource.LogDebug(message); } } internal static class Native { private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); public static readonly IntPtr HKEY_LOCAL_MACHINE = new IntPtr(2147483650L); [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount); [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern int GetWindowTextLength(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); [DllImport("user32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId); [DllImport("user32.dll")] private static extern bool BringWindowToTop(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] private static extern void AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); [DllImport("kernel32.dll")] private static extern uint GetCurrentProcessId(); [DllImport("kernel32.dll")] private static extern uint GetCurrentThreadId(); [DllImport("Advapi32.dll", CharSet = CharSet.Ansi, EntryPoint = "RegOpenKeyExA")] public static extern int RegOpenKeyEx(IntPtr hKey, [In] string lpSubKey, int ulOptions, int samDesired, out IntPtr phkResult); [DllImport("advapi32.dll", CharSet = CharSet.Ansi)] public static extern int RegQueryValueEx(IntPtr hKey, string lpValueName, int lpReserved, out uint lpType, StringBuilder lpData, ref uint lpcbData); [DllImport("advapi32.dll", CharSet = CharSet.Ansi)] public static extern int RegQueryInfoKey(IntPtr hKey, StringBuilder lpClass, IntPtr lpcbClass, IntPtr lpReserved, out uint lpcSubKeys, out uint lpcbMaxSubKeyLen, out uint lpcbMaxClassLen, out uint lpcValues, out uint lpcbMaxValueNameLen, out uint lpcbMaxValueLen, IntPtr lpSecurityDescriptor, IntPtr lpftLastWriteTime); [DllImport("advapi32.dll", CharSet = CharSet.Ansi, EntryPoint = "RegEnumValueA")] public static extern int RegEnumValue(IntPtr hKey, uint dwIndex, StringBuilder lpValueName, ref uint lpcchValueName, IntPtr lpReserved, IntPtr lpType, IntPtr lpData, IntPtr lpcbData); [DllImport("advapi32.dll")] public static extern int RegCloseKey(IntPtr hKey); [DllImport("Shlwapi.dll", CharSet = CharSet.Ansi)] public static extern int ShellMessageBox(IntPtr hAppInst, IntPtr hWnd, string lpcText, string lpcTitle, uint fuStyle); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetCurrentProcess(); [DllImport("advapi32.dll", SetLastError = true)] private static extern bool OpenProcessToken(IntPtr hProcess, uint dwAccess, out IntPtr hToken); [DllImport("advapi32.dll", SetLastError = true)] private static extern bool GetTokenInformation(IntPtr hToken, uint tokenInformationClass, IntPtr lpData, uint tokenInformationLength, out uint returnLength); [DllImport("kernel32.dll", SetLastError = true)] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] [SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool CloseHandle(IntPtr handle); public static bool RegOpenSubKey(ref IntPtr hKey, string lpSubKey, int samDesired) { if (RegOpenKeyEx(hKey, lpSubKey, 0, samDesired, out var phkResult) != 0) { return false; } RegCloseKey(hKey); hKey = phkResult; return true; } private static string GetWindowText(IntPtr hWnd) { int windowTextLength = GetWindowTextLength(hWnd); if (windowTextLength > 0) { StringBuilder stringBuilder = new StringBuilder(windowTextLength + 1); GetWindowText(hWnd, stringBuilder, stringBuilder.Capacity); return stringBuilder.ToString(); } return string.Empty; } private static IEnumerable FindWindows(EnumWindowsProc filter) { IntPtr zero = IntPtr.Zero; List windows = new List(); EnumWindows(delegate(IntPtr wnd, IntPtr param) { if (filter(wnd, param)) { windows.Add(wnd); } return true; }, IntPtr.Zero); return windows; } public static void BringGameWindowToFront() { uint currentPid = GetCurrentProcessId(); IntPtr[] array = FindWindows(delegate(IntPtr hWnd2, IntPtr lParam) { GetWindowThreadProcessId(hWnd2, out var processId2); return processId2 == currentPid && GetWindowText(hWnd2) == "Lethal Company"; }).ToArray(); if (array.Length > 1) { Logger.LogWarning("Multiple game windows called 'Lethal Company' detected. Selecting only the first one."); } IntPtr hWnd = array[0]; uint processId; uint windowThreadProcessId = GetWindowThreadProcessId(GetForegroundWindow(), out processId); uint currentThreadId = GetCurrentThreadId(); AttachThreadInput(windowThreadProcessId, currentThreadId, fAttach: true); BringWindowToTop(hWnd); AttachThreadInput(windowThreadProcessId, currentThreadId, fAttach: false); } public static bool IsElevated() { IntPtr hToken = IntPtr.Zero; IntPtr intPtr = IntPtr.Zero; try { if (!OpenProcessToken(GetCurrentProcess(), 8u, out hToken)) { return false; } intPtr = Marshal.AllocHGlobal(4); if (!GetTokenInformation(hToken, 20u, intPtr, 4u, out var _)) { return false; } return Marshal.ReadIntPtr(intPtr).ToInt32() != 0; } finally { if (hToken != IntPtr.Zero) { CloseHandle(hToken); } if (intPtr != IntPtr.Zero) { Marshal.FreeHGlobal(intPtr); } } } } internal static class OpenXR { public class Runtimes(Runtime[] runtimes) : IReadOnlyCollection, IEnumerable, IEnumerable { public Runtime? Default => ((IEnumerable)runtimes).Select((Func)((Runtime rt) => rt)).FirstOrDefault((Runtime? rt) => rt.Value.Default); public int Count => runtimes.Length; public bool TryGetRuntime(string name, out Runtime runtime) { runtime = default(Runtime); try { runtime = runtimes.First((Runtime rt) => rt.Name == name); return true; } catch { return false; } } public bool TryGetRuntimeByPath(string path, out Runtime runtime) { runtime = default(Runtime); try { runtime = runtimes.First((Runtime rt) => rt.Path == path); return true; } catch { return false; } } public IEnumerator GetEnumerator() { return ((IEnumerable)runtimes).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } public struct Runtime : IEquatable { public string Name { get; set; } public string Path { get; set; } public bool Default { get; set; } public static bool ReadFromJson(string path, out Runtime runtime) { runtime = default(Runtime); try { JToken val = JsonConvert.DeserializeObject(File.ReadAllText(path))[(object)"runtime"]; object name; if (val == null) { name = null; } else { JToken obj = val[(object)"name"]; name = ((obj != null) ? obj.ToObject() : null); } runtime.Name = (string)name; runtime.Path = path; string defaultRuntimePath = GetDefaultRuntimePath(); if (defaultRuntimePath != null) { runtime.Default = string.Equals(path, defaultRuntimePath, StringComparison.CurrentCultureIgnoreCase); } return true; } catch { return false; } } public bool Equals(Runtime other) { return Path == other.Path; } public override bool Equals(object obj) { if (obj is Runtime other) { return Equals(other); } return false; } public override int GetHashCode() { return HashCode.Combine(Path); } } public static class Loader { private static XRGeneralSettings xrGeneralSettings; private static XRManagerSettings xrManagerSettings; private static OpenXRLoader xrLoader; private static readonly ManualLogSource Logger; private static int recoveryTick; static Loader() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown Logger = new ManualLogSource("OpenXR Loader"); Logger.Sources.Add((ILogSource)(object)Logger); } public static bool IsRunning() { List list = new List(); SubsystemManager.GetInstances(list); return list.Any((XRDisplaySubsystem d) => d != null && ((IntegratedSubsystem)d).running); } public static void EnsureRunning() { if ((Object)(object)xrManagerSettings == (Object)null) { return; } List list = new List(); SubsystemManager.GetInstances(list); if (list.Any((XRDisplaySubsystem d) => d != null && ((IntegratedSubsystem)d).running)) { recoveryTick = 0; } else if (recoveryTick++ % 30 == 0) { if (list.Count == 0) { Logger.LogWarning((object)"OpenXR shut down — re-initializing loader"); xrManagerSettings.InitializeLoaderSync(); } Logger.LogWarning((object)"Restarting XR subsystems"); xrManagerSettings.StartSubsystems(); } } public static bool InitializeXR() { InitializeScripts(); List list = new List(); SubsystemManager.GetAllSubsystemDescriptors(list); if (!list.Any((ISubsystemDescriptor subsystem) => subsystem.id == "OpenXR Input") || !list.Any((ISubsystemDescriptor subsystem) => subsystem.id == "OpenXR Display")) { Logger.LogError((object)"No Unity OpenXR subsystem found, this installation of PeakVR was not installed correctly."); if (list.Count == 0) { return false; } Logger.LogDebug((object)"Subsystems installed:"); foreach (ISubsystemDescriptor item in list) { Logger.LogDebug((object)("- " + item.id)); } return false; } if (Native.IsElevated()) { Logger.LogWarning((object)"Application is elevated! Unable to override the XR runtime! Only the system default OpenXR runtime will be available."); return InitializeXR(null); } Runtimes runtimes = GetRuntimes(); if (runtimes.Count == 0) { Logger.LogWarning((object)"Failed to query runtimes, or no runtimes were found. Falling back to old behavior."); return InitializeXR(string.IsNullOrEmpty(Plugin.Config.OpenXRRuntimeFile.Value) ? ((Runtime?)null) : new Runtime?(new Runtime { Name = "LCVR OpenXR Override", Path = Plugin.Config.OpenXRRuntimeFile.Value })); } if (!string.IsNullOrEmpty(Plugin.Config.OpenXRRuntimeFile.Value)) { if (InitializeXR(runtimes.TryGetRuntimeByPath(Plugin.Config.OpenXRRuntimeFile.Value, out var runtime) ? runtime : new Runtime { Name = "LCVR OpenXR Override", Path = Plugin.Config.OpenXRRuntimeFile.Value })) { return true; } Logger.LogWarning((object)"Loading OpenXR using override failed, falling back to automatic enumeration..."); } Runtime? runtime2 = runtimes.Default; if (runtime2.HasValue) { Runtime valueOrDefault = runtime2.GetValueOrDefault(); if (valueOrDefault.Path != Plugin.Config.OpenXRRuntimeFile.Value && InitializeXR(valueOrDefault)) { return true; } } foreach (Runtime item2 in runtimes.Where((Runtime rt) => rt.Path != Plugin.Config.OpenXRRuntimeFile.Value && !rt.Default)) { if (InitializeXR(item2)) { return true; } } Logger.LogError((object)"All available runtimes were attempted but none worked. Aborting..."); return false; } private static bool InitializeXR(Runtime? runtime) { if (runtime.HasValue) { Runtime valueOrDefault = runtime.GetValueOrDefault(); Logger.LogInfo((object)("Attempting to initialize OpenXR on " + valueOrDefault.Name)); Environment.SetEnvironmentVariable("XR_RUNTIME_JSON", valueOrDefault.Path); } else { Logger.LogInfo((object)"Attempting to initialize OpenXR using default runtime"); Environment.SetEnvironmentVariable("XR_RUNTIME_JSON", null); } xrGeneralSettings.InitXRSDK(); xrGeneralSettings.Start(); List list = new List(); SubsystemManager.GetInstances(list); if (Plugin.Config.EnableVerboseLogging.Value) { Logger.LogWarning((object)"OpenXR Diagnostics Report:"); string[] array = GenerateReport().Split("\n"); foreach (string text in array) { Logger.LogWarning((object)text); } Logger.LogWarning((object)""); Logger.LogWarning((object)"To prevent diagnostics report from being printed, disable the 'EnableVerboseLogging' option in the settings."); } return list.Count > 0; } private static void InitializeScripts() { if (xrGeneralSettings == null) { xrGeneralSettings = ScriptableObject.CreateInstance(); } if (xrManagerSettings == null) { xrManagerSettings = ScriptableObject.CreateInstance(); } if (xrLoader == null) { xrLoader = ScriptableObject.CreateInstance(); } xrGeneralSettings.Manager = xrManagerSettings; ((List)xrManagerSettings.activeLoaders).Clear(); ((List)xrManagerSettings.activeLoaders).Add((XRLoader)(object)xrLoader); OpenXRSettings.Instance.renderMode = (RenderMode)0; OpenXRSettings.Instance.depthSubmissionMode = (DepthSubmissionMode)0; if (OpenXRSettings.Instance.features.Length == 0) { ValveIndexControllerProfile val = ScriptableObject.CreateInstance(); HPReverbG2ControllerProfile val2 = ScriptableObject.CreateInstance(); HTCViveControllerProfile val3 = ScriptableObject.CreateInstance(); MicrosoftMotionControllerProfile val4 = ScriptableObject.CreateInstance(); KHRSimpleControllerProfile val5 = ScriptableObject.CreateInstance(); MetaQuestTouchProControllerProfile val6 = ScriptableObject.CreateInstance(); OculusTouchControllerProfile val7 = ScriptableObject.CreateInstance(); XRSessionMonitor xRSessionMonitor = ScriptableObject.CreateInstance(); ((OpenXRFeature)val).enabled = true; ((OpenXRFeature)val2).enabled = true; ((OpenXRFeature)val3).enabled = true; ((OpenXRFeature)val4).enabled = true; ((OpenXRFeature)val5).enabled = true; ((OpenXRFeature)val6).enabled = true; ((OpenXRFeature)val7).enabled = true; ((OpenXRFeature)xRSessionMonitor).enabled = true; OpenXRSettings.Instance.features = (OpenXRFeature[])(object)new OpenXRFeature[8] { (OpenXRFeature)val, (OpenXRFeature)val2, (OpenXRFeature)val3, (OpenXRFeature)val4, (OpenXRFeature)val5, (OpenXRFeature)val6, (OpenXRFeature)val7, xRSessionMonitor }; } } } private static List> runtimeCache; [DllImport("UnityOpenXR", EntryPoint = "DiagnosticReport_GenerateReport")] private static extern IntPtr Internal_GenerateReport(); [DllImport("UnityOpenXR", EntryPoint = "DiagnosticReport_ReleaseReport")] private static extern void Internal_ReleaseReport(IntPtr report); [DllImport("UnityOpenXR", EntryPoint = "NativeConfig_GetRuntimeName")] private static extern bool Internal_GetRuntimeName(out IntPtr runtimeNamePtr); [DllImport("UnityOpenXR", EntryPoint = "NativeConfig_GetRuntimeVersion")] private static extern bool Internal_GetRuntimeVersion(out ushort major, out ushort minor, out ushort patch); private static string GenerateReport() { IntPtr intPtr = Internal_GenerateReport(); if (intPtr == IntPtr.Zero) { return ""; } string result = Marshal.PtrToStringAnsi(intPtr); Internal_ReleaseReport(intPtr); return result; } public static Runtimes GetRuntimes() { HashSet hashSet = new HashSet(); foreach (Runtime item2 in LocateCommonRuntimes()) { hashSet.Add(item2); } string defaultRuntimePath = GetDefaultRuntimePath(); if (Native.RegOpenKeyEx(Native.HKEY_LOCAL_MACHINE, "SOFTWARE\\Khronos\\OpenXR\\1", 0, 131097, out var phkResult) != 0) { return new Runtimes(hashSet.ToArray()); } List list = new List(); if (!Native.RegOpenSubKey(ref phkResult, "AvailableRuntimes", 131097) || !EnumRuntimeFiles(phkResult, list)) { if (string.IsNullOrEmpty(defaultRuntimePath)) { return new Runtimes(hashSet.ToArray()); } try { JToken val = JsonConvert.DeserializeObject(File.ReadAllText(defaultRuntimePath))[(object)"runtime"]; Runtime item = default(Runtime); object name; if (val == null) { name = null; } else { JToken obj = val[(object)"name"]; name = ((obj != null) ? obj.ToObject() : null); } item.Name = (string)name; item.Path = defaultRuntimePath; item.Default = true; hashSet.Add(item); } catch { } return new Runtimes(hashSet.ToArray()); } if (!list.Contains(defaultRuntimePath)) { list.Add(defaultRuntimePath); } foreach (string item3 in list) { try { JToken val2 = JsonConvert.DeserializeObject(File.ReadAllText(item3))[(object)"runtime"]; Runtime item = default(Runtime); object name2; if (val2 == null) { name2 = null; } else { JToken obj3 = val2[(object)"name"]; name2 = ((obj3 != null) ? obj3.ToObject() : null); } item.Name = (string)name2; item.Path = item3; item.Default = item3 == defaultRuntimePath; hashSet.Add(item); } catch (Exception ex) { Logger.LogWarning("Failed to parse " + item3 + ": " + ex.Message + ". Runtime will not be used."); } } return new Runtimes(hashSet.ToArray()); } [CanBeNull] private static string GetDefaultRuntimePath() { if (Native.RegOpenKeyEx(Native.HKEY_LOCAL_MACHINE, "SOFTWARE\\Khronos\\OpenXR\\1", 0, 131097, out var phkResult) != 0) { return null; } string result = null; uint lpcbData = 0u; uint lpType; bool flag = Native.RegQueryValueEx(phkResult, "ActiveRuntime", 0, out lpType, null, ref lpcbData) != 0; bool flag2 = flag; if (!flag2) { bool flag3 = lpType - 1 <= 1; flag2 = !flag3; } if (flag2) { return null; } StringBuilder stringBuilder = new StringBuilder((int)lpcbData); if (Native.RegQueryValueEx(phkResult, "ActiveRuntime", 0, out lpType, stringBuilder, ref lpcbData) == 0) { result = stringBuilder.ToString(); } return result; } private static bool EnumRuntimeFiles(IntPtr hKey, List files) { if (Native.RegQueryInfoKey(hKey, null, IntPtr.Zero, IntPtr.Zero, out var _, out var _, out var _, out var lpcValues, out var lpcbMaxValueNameLen, out var _, IntPtr.Zero, IntPtr.Zero) != 0) { return false; } for (uint num = 0u; num < lpcValues; num++) { StringBuilder stringBuilder = new StringBuilder((int)(lpcbMaxValueNameLen + 1)); uint lpcchValueName = lpcbMaxValueNameLen + 1; if (Native.RegEnumValue(hKey, num, stringBuilder, ref lpcchValueName, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero) == 0) { files.Add(stringBuilder.ToString()); } } return true; } private static IEnumerable LocateCommonRuntimes() { string path = default(string); if (SteamAPI.Init() && SteamApps.GetAppInstallDir(new AppId_t(250820u), ref path, 240u) != 0 && Runtime.ReadFromJson(Path.Combine(path, "steamxr_win64.json"), out var runtime)) { yield return runtime; } path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Virtual Desktop Streamer\\OpenXR\\virtualdesktop-openxr.json"); if (File.Exists(path) && Runtime.ReadFromJson(path, out runtime)) { yield return runtime; } path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Oculus\\Support\\oculus-runtime\\oculus_openxr_64.json"); if (File.Exists(path) && Runtime.ReadFromJson(path, out runtime)) { yield return runtime; } } public static bool GetActiveRuntimeName(out string name) { name = null; if (!Internal_GetRuntimeName(out var runtimeNamePtr)) { return false; } if (runtimeNamePtr == IntPtr.Zero) { return false; } name = Marshal.PtrToStringAnsi(runtimeNamePtr); return true; } public static bool GetActiveRuntimeVersion(out ushort major, out ushort minor, out ushort patch) { return Internal_GetRuntimeVersion(out major, out minor, out patch); } private static List> RuntimeList() { if (runtimeCache != null) { return runtimeCache; } runtimeCache = new List>(); try { foreach (Runtime runtime in GetRuntimes()) { runtimeCache.Add(new KeyValuePair(runtime.Name ?? "Unknown", runtime.Path ?? "")); } } catch (Exception ex) { Logger.LogWarning("Failed to enumerate OpenXR runtimes: " + ex.Message); } return runtimeCache; } public static List GetRuntimeChoices() { List list = new List { "System Default" }; foreach (KeyValuePair item in RuntimeList()) { list.Add(item.Key); } return list; } public static string ResolveRuntimePath(string name) { if (string.IsNullOrEmpty(name) || name == "System Default") { return ""; } foreach (KeyValuePair item in RuntimeList()) { if (item.Key == name) { return item.Value; } } return ""; } } internal static class GameObjectExtensions { public static GameObject Find(this GameObject @object, string name) { Transform obj = @object.transform.Find(name); if (obj == null) { return null; } return ((Component)obj).gameObject; } } internal static class Utils { public static byte[] ComputeHash(byte[] input) { using SHA256 sHA = SHA256.Create(); return sHA.ComputeHash(input); } public static string[] ParseConfig(string content) { string[] source = content.Split("\n", StringSplitOptions.RemoveEmptyEntries); return (from line in source where !line.TrimStart().StartsWith("#") let commentIndex = line.IndexOf('#') select (commentIndex < 0) ? line.Trim() : line.Substring(0, commentIndex).Trim() into parsedLine where !string.IsNullOrEmpty(parsedLine) select parsedLine).ToArray(); } public static string FormatPascalAndAcronym(string input) { StringBuilder stringBuilder = new StringBuilder(input[0].ToString()); if (stringBuilder.Length <= 0) { return stringBuilder.ToString(); } for (int i = 1; i < input.Length; i++) { char c = input[i - 1]; char c2 = ((i + 1 < input.Length) ? input[i + 1] : '\0'); bool flag = char.IsLower(c2); bool flag2 = char.IsUpper(c2); bool flag3 = char.IsUpper(input[i]); bool flag4 = char.IsLower(c); bool flag5 = char.IsUpper(c); if (!string.IsNullOrWhiteSpace(c.ToString()) && ((flag5 && flag3 && flag) || (flag4 && flag3 && flag) || (flag4 && flag3 && flag2))) { stringBuilder.Append(' '); } stringBuilder.Append(input[i]); } return stringBuilder.ToString(); } public static void EnableQualitySetting(this HDAdditionalCameraData camera, FrameSettingsField setting) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected I4, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) ((BitArray128)(ref camera.renderingPathCustomFrameSettingsOverrideMask.mask))[(uint)(int)setting] = false; ((FrameSettings)(ref camera.renderingPathCustomFrameSettings)).SetEnabled(setting, true); } public static void DisableQualitySetting(this HDAdditionalCameraData camera, FrameSettingsField setting) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected I4, but got Unknown //IL_0018: Unknown result type (might be due to invalid IL or missing references) ((BitArray128)(ref camera.renderingPathCustomFrameSettingsOverrideMask.mask))[(uint)(int)setting] = true; ((FrameSettings)(ref camera.renderingPathCustomFrameSettings)).SetEnabled(setting, false); } public static void AttachHeadTrackedPoseDriver(this GameObject @object) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) TrackedPoseDriver val = @object.AddComponent(); val.positionAction = Actions.Instance.HeadPosition; val.rotationAction = Actions.Instance.HeadRotation; val.trackingStateInput = new InputActionProperty(Actions.Instance.HeadTrackingState); } public static Transform[] GetChildren(this Transform transform) { List list = new List(); for (int i = 0; i < transform.childCount; i++) { list.Add(transform.GetChild(i)); } return list.ToArray(); } public static IEnumerator NopRoutine() { yield break; } public static IEnumerator FixYuckyScrollThing(Animator animator) { ScrollRect[] rects = ((Component)animator).GetComponentsInChildren(); AnimatorStateInfo currentAnimatorStateInfo = animator.GetCurrentAnimatorStateInfo(0); float maxTime = ((AnimatorStateInfo)(ref currentAnimatorStateInfo)).length; float time = 0f; while (time < maxTime) { time += Time.deltaTime; CollectionExtensions.Do((IEnumerable)rects, (Action)delegate(ScrollRect rect) { rect.verticalNormalizedPosition = 1f; }); yield return null; } } } } namespace LCVR.Assets { public static class AssetManager { private static AssetBundle assetsBundle; private static AssetBundle scenesBundle; public static GameObject Interactable; public static GameObject Keyboard; public static GameObject VolumeManager; public static GameObject SpectatorLight; public static GameObject SpectatorGhost; public static GameObject SteeringWheelPoints; public static GameObject PopupText; public static GameObject SpectatingMenu; public static GameObject Reticle; public static GameObject InitMenuEnvironment; public static GameObject MainMenuEnvironment; public static GameObject PauseMenuEnvironment; public static GameObject SettingsPanel; public static Material SplashMaterial; public static Material DefaultRayMat; public static Shader TMPAlwaysOnTop; public static Shader VignettePostProcess; public static InputActionAsset VRActions; public static InputActionAsset DefaultXRActions; public static InputActionAsset NullActions; public static Sprite GithubImage; public static Sprite KofiImage; public static Sprite DiscordImage; public static Sprite WarningImage; public static Sprite SprintImage; public static AudioClip DoorLocked; internal static bool LoadAssets() { assetsBundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Plugin.Config.AssemblyPath), "lethalcompanyvr")); scenesBundle = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Plugin.Config.AssemblyPath), "lethalcompanyvr-levels")); if ((Object)(object)assetsBundle == (Object)null || (Object)(object)scenesBundle == (Object)null) { Logger.LogError("Failed to load asset bundle!"); return false; } DefaultXRActions = assetsBundle.LoadAsset("DefaultXRActions"); return true; } } } namespace LCVR.Input { public class Actions { public static Actions Instance { get; private set; } = new Actions(); public InputAction HeadPosition { get; private set; } public InputAction HeadRotation { get; private set; } public InputAction HeadTrackingState { get; private set; } public InputAction LeftHandPosition { get; private set; } public InputAction LeftHandRotation { get; private set; } public InputAction LeftHandTrackingState { get; private set; } public InputAction RightHandPosition { get; private set; } public InputAction RightHandRotation { get; private set; } public InputAction RightHandTrackingState { get; private set; } private Actions() { HeadPosition = AssetManager.DefaultXRActions.FindAction("Head/Position", false); HeadRotation = AssetManager.DefaultXRActions.FindAction("Head/Rotation", false); HeadTrackingState = AssetManager.DefaultXRActions.FindAction("Head/Tracking State", false); LeftHandPosition = AssetManager.DefaultXRActions.FindAction("Left/Position", false); LeftHandRotation = AssetManager.DefaultXRActions.FindAction("Left/Rotation", false); LeftHandTrackingState = AssetManager.DefaultXRActions.FindAction("Left/Tracking State", false); RightHandPosition = AssetManager.DefaultXRActions.FindAction("Right/Position", false); RightHandRotation = AssetManager.DefaultXRActions.FindAction("Right/Rotation", false); RightHandTrackingState = AssetManager.DefaultXRActions.FindAction("Right/Tracking State", false); } } } namespace PeakVR { [HarmonyPatch(typeof(MainMenu), "Start")] internal static class AboutButtonPatch { [CompilerGenerated] private static class <>O { public static UnityAction <0>__Open; } private const string ButtonName = "PeakVR AboutButton"; private const float Margin = 40f; private const float SizeScale = 0.65f; [HarmonyPostfix] private static void Postfix(MainMenu __instance) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_0118: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Expected O, but got Unknown //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: 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) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) Button val = (((Object)(object)__instance.aggrocrabButton != (Object)null) ? __instance.aggrocrabButton : __instance.landfallButton); MainMenuPageSelector val2 = Object.FindObjectOfType(); Transform val3 = (((Object)(object)val2 != (Object)null && (Object)(object)val2.mainPage != (Object)null) ? ((Component)val2.mainPage).transform : (((Object)(object)val != (Object)null) ? ((Component)val).transform.parent : null)); if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.Find("PeakVR AboutButton") != (Object)null)) { GameObject val4 = new GameObject("PeakVR AboutButton", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(Button) }); val4.transform.SetParent(val3, false); Image component = val4.GetComponent(); ((Graphic)component).color = Color.white; if ((Object)(object)PeakAssets.AboutButton != (Object)null) { component.sprite = PeakAssets.AboutButton; component.preserveAspect = true; } Button component2 = val4.GetComponent