using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; using HarmonyLib; namespace CLre.Fixes { [Bugfix(name = "InitLogSooner", description = "Start the logger slightly sooner than Cardlife does", component = BugfixType.Initialiser, id = 0)] public static class InitLogSooner { public static int millisecondsTimeout = 5000; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Init() { try { CustomLoggerThread_CreateGameObject_Patch.allowed = true; CustomLoggerThread.CreateGameObject(); CustomLoggerThread_CreateGameObject_Patch.allowed = false; API.Utility.Logging.Log("Completed early log init"); //System.IO.File.WriteAllText("InitLogSooner.log", $"Done at " + System.DateTime.Now.ToString()); } catch (Exception e) { API.App.Client.LogInitComplete += (_, __) => { API.Utility.Logging.Log($"Failed to initialise log sooner, reason:\n" + e); }; System.IO.File.WriteAllText("InitLogSooner.log", e.ToString()); } } [Bugfix(name = "InitLogSooner", target = typeof(CustomLoggerThread), component = BugfixType.HarmonyPatch, id = 0)] [HarmonyPatch(typeof(CustomLoggerThread), "CreateGameObject")] class CustomLoggerThread_CreateGameObject_Patch { internal static bool allowed = false; public static bool Prefix() { return allowed; } } [Bugfix(name = "InitLogSooner", component = BugfixType.HarmonyPatch, id = 0)] [HarmonyPatch(typeof(CustomLoggerThread), "StartQueue")] class CustomLoggerThread_StartQueue_Patch { internal static volatile bool IsLogStarted = false; private delegate void Flusher(); public static bool Prefix() { // setup thru reflection FieldInfo quitThreadField = AccessTools.Field(typeof(CustomLoggerThread), "_quitThread"); MethodInfo flushLoggerMethod = AccessTools.Method(typeof(CustomLoggerThread), "FlushLogger"); Flusher flushLogger = API.Utility.Reflection.BuildDelegate(flushLoggerMethod, null); //Flusher flushLogger = (Flusher) Delegate.CreateDelegate(typeof(Action), null, flushLoggerMethod); MethodInfo forceFlushMethod = AccessTools.Method("CustomLogger:ForceFlush"); Flusher forceFlush = API.Utility.Reflection.BuildDelegate(forceFlushMethod, null); //Flusher forceFlush = (Flusher) Delegate.CreateDelegate(typeof(Action), null, forceFlushMethod); Thread.MemoryBarrier(); IsLogStarted = true; while (!(bool) quitThreadField.GetValue(null)) { flushLogger(); forceFlush(); Thread.Sleep(millisecondsTimeout); } IsLogStarted = false; return false; } } } }