///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // D E R E L I C T // /// // (c) 2003..2024 #if TOOLS using Godot; using Godot.NativeInterop; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Loader; using System.Text.Json; //Currently doesnt _quiiiite_ work [GlobalClass, Tool] public partial class core : EditorPlugin { #if DONT_RUN public static void SetupUnloads() { GD.Print($"SetupUnloads"); //AppDomain.CurrentDomain.FirstChanceException +=CurrentDomainOnFirstChanceException; var assContext = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(System.Reflection.Assembly.GetExecutingAssembly()); assContext.Unloading += alc => { GD.Print($"Unloading (from Initialize)"); //Debug.WriteLine("Unloading (from Initialize)"); { ////complete godot async tasks, which may have been left hanging var isDone = false; while (isDone is false) { try { Dispatcher.SynchronizationContext.ExecutePendingContinuations(); isDone = true; GD.Print("Godot async tasks completed."); } catch (Exception ex) { Debug.WriteLine("Exception: " + ex); /*if (ex._IsRoutineControlFlow() is false) { __.Assert(ex); }*/ } } } //need to detach the handler, or it will keep the assembly alive. //AppDomain.CurrentDomain.FirstChanceException -= CurrentDomainOnFirstChanceException; { //unload STJ cached assemblies, //see https://github.com/dotnet/runtime/issues/65323#issuecomment-1320949911 //and https://github.com/godotengine/godot/issues/78513#issuecomment-1624682104 GD.Print($"Clearing STJ cache"); var assembly = typeof(JsonSerializerOptions).Assembly; var updateHandlerType = assembly.GetType("System.Text.Json.JsonSerializerOptionsUpdateHandler"); var clearCacheMethod = updateHandlerType?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.Public); clearCacheMethod?.Invoke(null, new object?[] { null }); GD.Print($"Cleared STJ cache"); } }; } public override void _EnterTree() { GD.Print($"_EnterTree"); var assContext = System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(System.Reflection.Assembly.GetExecutingAssembly()); assContext.Unloading += OnUnloading; try { //res.Mgr.startup(); lib.Config.startup("editor.xml"); ent.Util.RegisterData(); Util.SetupSaveState(); GD.Print($"DONE Setting up core."); } catch (Exception ex) { GD.PrintErr($"Ruh roh, ex {ex.GetType().Name} {ex.Message}"); } } [ModuleInitializer] public static void OnLoading() { GD.Print($"OnLoading"); SetupUnloads(); SetupCore(); } private void OnUnloading(AssemblyLoadContext context) { GD.Print($"OnUnloading"); Game.shutdownLogging(); } public override void _ExitTree() { GD.Print($"_ExitTree"); } public static void SetupCore() { var id = Process.GetCurrentProcess().Id; GD.Print($"Setting up core..."); // TWICE (down below) Game.setupLogging($"editor", $""); // Initialization of the plugin goes here. log.high($"Starting up core..."); var windowTitle = $"D E R E L I C T ({id})"; log.high(windowTitle); } #endif #if DONT_RUN public override void _EnterTree() { var id = Process.GetCurrentProcess().Id; GD.Print($"Setting up core..."); // TWICE (down below) Game.setupLogging($"editor", $""); // Initialization of the plugin goes here. log.high($"Starting up core..."); var windowTitle = $"D E R E L I C T ({id})"; log.high(windowTitle); try { //res.Mgr.startup(); lib.Config.startup("editor.xml"); ent.Util.RegisterData(); Util.SetupSaveState(); var curAss = Assembly.GetExecutingAssembly(); AssemblyLoadContext.GetLoadContext(curAss).Unloading += OnUnloading; GD.Print($"DONE Setting up core."); } catch (Exception ex) { GD.PrintErr($"Ruh roh, ex {ex.GetType().Name} {ex.Message}"); } } [ModuleInitializer] static public void OnLoading() { GD.Print($"On LOADing: Unpause thread"); //log.unpauseThread(); Game.setupLogging($"editor", $""); } private void OnUnloading(AssemblyLoadContext context) { GD.Print($"On UNloading: Pause thread"); //log.pauseThread(); Game.shutdownLogging(); } public override void _ExitTree() { // Clean-up of the plugin goes here. log.high($"Shutting down core . . ."); Game.shutdownLogging(); log.high($"D O N E Shutting down core."); } #endif } #endif