using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using BepInEx; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Mono.Cecil; using VRPatcher.Properties; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [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 VRPatcher { public static class VRDependenciesPatcher { private static readonly ManualLogSource Logger = Logger.CreateLogSource("VRDependenciesPatcher"); internal static string VRPatcherPath => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); internal static string ManagedPath => Paths.ManagedPath; internal static string PluginsPath => Path.Combine(ManagedPath, "../Plugins/x86_64"); internal static string SubsystemsPath => Path.Combine(ManagedPath, "../UnitySubsystems"); internal static string OpenXRSubsystemsPath => Path.Combine(SubsystemsPath, "UnityOpenXR"); [Obsolete("Should not be used!", true)] public static IEnumerable TargetDLLs { get; } = new string[0]; [Obsolete("Should not be used!", true)] public static void Initialize() { if (!Directory.Exists(SubsystemsPath)) { Directory.CreateDirectory(SubsystemsPath); } if (!Directory.Exists(OpenXRSubsystemsPath)) { Directory.CreateDirectory(OpenXRSubsystemsPath); } Logger.LogInfo((object)"Copying subsystems..."); Logger.LogInfo((object)("ManagedPath=" + ManagedPath)); Logger.LogInfo((object)("PluginsPath=" + PluginsPath)); Logger.LogInfo((object)("SubsystemsPath=" + SubsystemsPath)); Logger.LogInfo((object)("OpenXRSubsystemsPath=" + OpenXRSubsystemsPath)); string text = Path.Combine(OpenXRSubsystemsPath, "UnitySubsystemsManifest.json"); byte[] unitySubsystemsManifest = Resources.UnitySubsystemsManifest; if (!CopyFile(text, unitySubsystemsManifest, replaceIfDifferent: true)) { Logger.LogInfo((object)("UnitySubsystemsManifest.json -> " + text + ": already present.")); } else { Logger.LogInfo((object)$"UnitySubsystemsManifest.json -> {text}: copied ({unitySubsystemsManifest.Length} bytes)."); } Logger.LogInfo((object)"Copying libraries..."); string text2 = Path.Combine(PluginsPath, "UnityOpenXR.dll"); byte[] unityOpenXR = Resources.UnityOpenXR; if (!CopyFile(text2, unityOpenXR, replaceIfDifferent: false)) { Logger.LogInfo((object)("UnityOpenXR.dll -> " + text2 + ": already present.")); } else { Logger.LogInfo((object)$"UnityOpenXR.dll -> {text2}: copied ({unityOpenXR.Length} bytes)."); } string text3 = Path.Combine(PluginsPath, "openxr_loader.dll"); byte[] openxr_loader = Resources.openxr_loader; if (!CopyFile(text3, openxr_loader, replaceIfDifferent: false)) { Logger.LogInfo((object)("openxr_loader.dll -> " + text3 + ": already present.")); } else { Logger.LogInfo((object)$"openxr_loader.dll -> {text3}: copied ({openxr_loader.Length} bytes)."); } Logger.LogInfo((object)$"Copy complete. UnityOpenXR.dll present: {File.Exists(text2)}, openxr_loader.dll present: {File.Exists(text3)}, manifest present: {File.Exists(text)}"); } private static bool CopyFile(string destination, byte[] data, bool replaceIfDifferent) { if (File.Exists(destination)) { if (!replaceIfDifferent) { return false; } SHA256 sHA = SHA256.Create(); byte[] array = sHA.ComputeHash(data); byte[] array2 = sHA.ComputeHash(File.ReadAllBytes(destination)); if (((ReadOnlySpan)array).SequenceEqual((ReadOnlySpan)array2)) { return false; } } File.WriteAllBytes(destination, data); return true; } private static bool CopyFiles(string destinationPath, string[] fileNames, string embedFolder, bool replaceIfDifferent = false) { DirectoryInfo directoryInfo = new DirectoryInfo(destinationPath); FileInfo[] files = directoryInfo.GetFiles(); bool result = false; Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetName().Name; foreach (string fileName in fileNames) { if (!Array.Exists(files, (FileInfo file) => fileName == file.Name)) { result = true; using Stream stream = executingAssembly.GetManifestResourceStream(name + "." + embedFolder + fileName); using FileStream destination = new FileStream(Path.Combine(directoryInfo.FullName, fileName), FileMode.Create, FileAccess.ReadWrite, FileShare.Delete); Logger.LogInfo((object)("Copying " + fileName)); stream.CopyTo(destination); } else { if (!replaceIfDifferent) { continue; } string text; using (Stream stream2 = executingAssembly.GetManifestResourceStream(name + "." + embedFolder + fileName)) { using StreamReader streamReader = new StreamReader(stream2); text = streamReader.ReadToEnd(); } FileInfo fileInfo = files.First((FileInfo file) => file.Name == fileName); string text2 = File.ReadAllText(fileInfo.FullName); if (text != text2) { result = true; Logger.LogInfo((object)("Overwriting " + fileName)); File.WriteAllText(fileInfo.FullName, text); } } } return result; } [Obsolete("Should not be used!", true)] public static void Patch(AssemblyDefinition ad) { } } } namespace VRPatcher.Properties { internal static class Resources { internal static byte[] openxr_loader => Load("VRPatcher.Plugins.openxr_loader.dll"); internal static byte[] UnityOpenXR => Load("VRPatcher.Plugins.UnityOpenXR.dll"); internal static byte[] UnitySubsystemsManifest => Load("VRPatcher.Dependencies.UnitySubsystemsManifest.json"); private static byte[] Load(string name) { using Stream stream = typeof(Resources).Assembly.GetManifestResourceStream(name); if (stream == null) { throw new FileNotFoundException("Embedded resource not found: " + name); } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } } }