#if STANDALONE using HarmonyLib; using System; using System.IO; using System.Reflection; using UnityEngine; using UnityExplorer.Core.Config; using UnityExplorer.Loader.STANDALONE; using UnityEngine.EventSystems; using UnityExplorer.Core.Input; using UnityExplorer.Core; #if CPP using UnhollowerRuntimeLib; #endif namespace UnityExplorer { public class ExplorerStandalone : IExplorerLoader { /// /// Call this to initialize UnityExplorer without adding a log listener. /// /// The new (or active, if one exists) instance of ExplorerStandalone. public static ExplorerStandalone CreateInstance() => CreateInstance(null); /// /// Call this to initialize UnityExplorer and add a listener for UnityExplorer's log messages. /// /// Your log listener to handle UnityExplorer logs. /// The new (or active, if one exists) instance of ExplorerStandalone. public static ExplorerStandalone CreateInstance(Action logListener) { if (Instance != null) return Instance; OnLog += logListener; var instance = new ExplorerStandalone(); instance.Init(); return instance; } public static ExplorerStandalone Instance { get; private set; } /// /// Invoked whenever Explorer logs something. Subscribe to this to handle logging. /// public static event Action OnLog; public Harmony HarmonyInstance => s_harmony; public static readonly Harmony s_harmony = new Harmony(ExplorerCore.GUID); public ConfigHandler ConfigHandler => _configHandler; private StandaloneConfigHandler _configHandler; public string ExplorerFolder { get { if (s_explorerFolder == null) { s_explorerFolder = Path.Combine( Path.GetDirectoryName( Uri.UnescapeDataString(new Uri(Assembly.GetExecutingAssembly().CodeBase) .AbsolutePath)), "UnityExplorer"); if (!Directory.Exists(s_explorerFolder)) Directory.CreateDirectory(s_explorerFolder); } return s_explorerFolder; } } private static string s_explorerFolder; public string ConfigFolder => ExplorerFolder; Action IExplorerLoader.OnLogMessage => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Log); }; Action IExplorerLoader.OnLogWarning => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Warning); }; Action IExplorerLoader.OnLogError => (object log) => { OnLog?.Invoke(log?.ToString() ?? "", LogType.Error); }; private void Init() { Instance = this; _configHandler = new StandaloneConfigHandler(); #if CPP ClassInjector.RegisterTypeInIl2Cpp(); #endif var obj = new GameObject("ExplorerBehaviour"); obj.AddComponent(); GameObject.DontDestroyOnLoad(obj); obj.hideFlags = HideFlags.HideAndDontSave; ExplorerCore.Init(this); } public class ExplorerBehaviour : MonoBehaviour { #if CPP public ExplorerBehaviour(IntPtr ptr) : base(ptr) { } #endif internal void Update() { ExplorerCore.Update(); } } public void SetupPatches() { try { this.HarmonyInstance.PatchAll(); } catch (Exception ex) { ExplorerCore.Log($"Exception setting up Harmony patches:\r\n{ex.ReflectionExToString()}"); } } [HarmonyPatch(typeof(EventSystem), "current", MethodType.Setter)] public class PATCH_EventSystem_current { [HarmonyPrefix] public static void Prefix_EventSystem_set_current(ref EventSystem value) { CursorUnlocker.Prefix_EventSystem_set_current(ref value); } } [HarmonyPatch(typeof(Cursor), "lockState", MethodType.Setter)] public class PATCH_Cursor_lockState { [HarmonyPrefix] public static void Prefix_set_lockState(ref CursorLockMode value) { CursorUnlocker.Prefix_set_lockState(ref value); } } [HarmonyPatch(typeof(Cursor), "visible", MethodType.Setter)] public class PATCH_Cursor_visible { [HarmonyPrefix] public static void Prefix_set_visible(ref bool value) { CursorUnlocker.Prefix_set_visible(ref value); } } } } #endif