From aa35550940569a385430b5bbfa4bd7404aac88f4 Mon Sep 17 00:00:00 2001 From: Cold-Mint Date: Sun, 21 Jul 2024 23:18:44 +0800 Subject: [PATCH] =?UTF-8?q?Supports=20loading=20necessary=20dll=20files.?= =?UTF-8?q?=20=E6=94=AF=E6=8C=81=E5=8A=A0=E8=BD=BD=E5=BF=85=E8=A6=81?= =?UTF-8?q?=E7=9A=84dll=E6=96=87=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locals/Log.csv | 12 +- scripts/Config.cs | 19 +++- scripts/debug/LogCat.cs | 7 +- scripts/loader/uiLoader/SplashScreenLoader.cs | 2 + scripts/mod/ModLoader.cs | 105 ++++++++++++++++++ scripts/utils/ResUtils.cs | 26 +++++ 6 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 scripts/mod/ModLoader.cs diff --git a/locals/Log.csv b/locals/Log.csv index d6d8e73..f09a131 100644 --- a/locals/Log.csv +++ b/locals/Log.csv @@ -86,4 +86,14 @@ log_weapon_not_in_pickup_range,武器不在拾取范围内。,The weapon is not log_weapon_picked_up,武器被拾取。,Weapon picked up.,武器が拾い取られました。 log_weapon_pickup_failed,武器拾取失败。,Weapon pickup failed.,武器の拾い取りに失敗しました。 log_enter_the_picking_range_body,进入拾取范围。,Enter the picking range.,拾い取り範囲に入ります。 -log_search_for_weapon_timeout,搜索武器超时。,Search for weapon timeout.,武器の検索がタイムアウトしました。 \ No newline at end of file +log_search_for_weapon_timeout,搜索武器超时。,Search for weapon timeout.,武器の検索がタイムアウトしました。 +log_initialize_the_context,初始化上下文环境。,Initialize the context environment.,コンテキスト環境を初期化します。 +log_initialize_the_context_failed,初始化上下文环境失败。,Initialize the context environment failed.,コンテキスト環境の初期化に失敗しました。 +log_get_dll_folder_failed,获取DLL文件夹失败。,Failed to get the DLL folder.,DLLフォルダの取得に失敗しました。 +log_dll_not_exist,位于{0}的Dll文件不存在。,The Dll file located at {0} does not exist.,{0}にあるDLLファイルが存在しません。 +log_load_dll,开始加载位于{0}的DLL文件。,Start loading the DLL file located at {0}.,{0}にあるDLLファイルのロードを開始します。 +log_load_dll_argument_exception,{0}不是绝对路径。,{0} is not an absolute path.,{0}は絶対パスではありません。 +log_load_dll_argument_null_exception,{0}参数为空。,The {0} parameter is empty.,{0}パラメータが空です。 +log_load_dll_file_load_exception,加载DLL文件{0}失败。,Failed to load the DLL file {0}.,DLLファイル{0}のロードに失敗しました。 +log_load_dll_bad_image_format_exception,{0}不是有效的程序集。,{0} is not a valid assembly.,{0}は有効なアセンブリではありません。 +log_load_dll_success,成功加载位于{0}的dll文件。,Successfully loaded the dll file located at {0}.,{0}にあるDLLファイルを正常にロードしました。 \ No newline at end of file diff --git a/scripts/Config.cs b/scripts/Config.cs index 1278cff..7cf9ba5 100644 --- a/scripts/Config.cs +++ b/scripts/Config.cs @@ -52,7 +52,7 @@ public static class Config /// App配置文件路径 /// public const string AppConfigPath = "res://AppConfig.yaml"; - + /// /// The percentage of speed reduced after a thrown item hits an enemy /// 抛出的物品击中敌人后减少的速度百分比 @@ -89,6 +89,12 @@ public static class Config /// 公司/创作者名字 /// public const string CompanyName = "ColdMint"; + + /// + /// Solution Name + /// 解决方案名称 + /// + public static string SolutionName = "ColdMint.Traveler"; /// /// How many item slots are there on the shortcut bar @@ -187,7 +193,11 @@ public static class Config //The host operating system is a web browser //宿主操作系统是网页浏览器 - Web + Web, + + //Running on editor + //在编辑器内运行 + Editor } /// @@ -197,6 +207,11 @@ public static class Config /// public static OsEnum GetOs() { + if (OS.HasFeature("editor")) + { + return OsEnum.Editor; + } + if (OS.HasFeature("windows")) { return OsEnum.Windows; diff --git a/scripts/debug/LogCat.cs b/scripts/debug/LogCat.cs index 9c0789c..91324b7 100644 --- a/scripts/debug/LogCat.cs +++ b/scripts/debug/LogCat.cs @@ -64,6 +64,11 @@ public static class LogCat /// 日志收集器 /// public const string LogCollector = "LogCollector"; + /// + /// Mod Loader + /// 模组加载器 + /// + public const string ModLoader = "ModLoader"; } @@ -192,7 +197,7 @@ public static class LogCat break; } - StringBuilder.Append(DateTime.Now.ToString(" yyyy-M-d HH:mm:ss ")); + StringBuilder.Append(DateTime.Now.ToString(" (K)yyyy-MM-d hh:mm:ss.fff ")); StringBuilder.Append(label); StringBuilder.Append(" :"); var key = $"log_{message}"; diff --git a/scripts/loader/uiLoader/SplashScreenLoader.cs b/scripts/loader/uiLoader/SplashScreenLoader.cs index b80687a..a47c30a 100644 --- a/scripts/loader/uiLoader/SplashScreenLoader.cs +++ b/scripts/loader/uiLoader/SplashScreenLoader.cs @@ -10,6 +10,7 @@ using ColdMint.scripts.inventory; using ColdMint.scripts.loot; using ColdMint.scripts.map; using ColdMint.scripts.map.roomInjectionProcessor; +using ColdMint.scripts.mod; using Godot; namespace ColdMint.scripts.loader.uiLoader; @@ -81,6 +82,7 @@ public partial class SplashScreenLoader : UiLoaderTemplate //Disable all logs in the release version. //在发行版禁用所有日志。 LogCat.MinLogLevel = Config.IsDebug() ? LogCat.InfoLogLevel : LogCat.DisableAllLogLevel; + ModLoader.Init(); ContributorDataManager.RegisterAllContributorData(); DeathInfoGenerator.RegisterDeathInfoHandler(new SelfDeathInfoHandler()); MapGenerator.RegisterRoomInjectionProcessor(new ChanceRoomInjectionProcessor()); diff --git a/scripts/mod/ModLoader.cs b/scripts/mod/ModLoader.cs new file mode 100644 index 0000000..2a4b41e --- /dev/null +++ b/scripts/mod/ModLoader.cs @@ -0,0 +1,105 @@ +using System; +using System.IO; +using System.Runtime.Loader; +using ColdMint.scripts.debug; +using ColdMint.scripts.utils; + +namespace ColdMint.scripts.mod; + +/// +/// Mod Loader +/// 模组加载器 +/// +public class ModLoader +{ + /// + /// AssemblyLoadContext + /// 装配加载上下文 + /// + private static AssemblyLoadContext? _assemblyLoadContext; + + private static string[] _requiredDllList = new[] { Config.SolutionName }; + + public static void Init() + { + //Initialize the context. + //初始化上下文环境。 + LogCat.Log("initialize_the_context", LogCat.LogLabel.ModLoader); + _assemblyLoadContext = AssemblyLoadContext.GetLoadContext(typeof(Godot.Bridge.ScriptManagerBridge).Assembly); + if (_assemblyLoadContext == null) + { + LogCat.LogError("initialize_the_context_failed", LogCat.LogLabel.ModLoader); + return; + } + + var dllFolder = ResUtils.GetSelfDllFolder(); + if (dllFolder == null) + { + LogCat.LogError("get_dll_folder_failed", LogCat.LogLabel.ModLoader); + return; + } + + foreach (var requiredDll in _requiredDllList) + { + var dllPath = Path.Join(dllFolder, requiredDll + ".dll"); + //Load the necessary dll files. + //加载必须的dll文件。 + if (!File.Exists(dllPath)) + { + //When the dll that must be loaded does not exist, an error is reported immediately. + //当必须加载的dll不存在时,立即报错。 + LogCat.LogErrorWithFormat("dll_not_exist", LogCat.LogLabel.ModLoader, true, dllPath); + throw new NullReferenceException("dll not exist:" + dllPath); + } + + //Load the dll. + //加载dll。 + LogCat.LogWithFormat("load_dll", LogCat.LogLabel.ModLoader, true, dllPath); + try + { + _assemblyLoadContext.LoadFromAssemblyPath(dllPath); + } + catch (ArgumentNullException argumentNullException) + { + //The assemblyPath parameter is null. + //assemblyPath参数为空。 + LogCat.LogErrorWithFormat("load_dll_argument_null_exception", LogCat.LogLabel.ModLoader, true, dllPath); + LogCat.WhenCaughtException(argumentNullException, LogCat.LogLabel.ModLoader); + return; + } + catch (ArgumentException argumentException) + { + //Not an absolute path. + //不是绝对路径 + LogCat.LogErrorWithFormat("load_dll_argument_exception", LogCat.LogLabel.ModLoader, true, dllPath); + LogCat.WhenCaughtException(argumentException, LogCat.LogLabel.ModLoader); + return; + } + catch (FileLoadException fileLoadException) + { + //A file that was found could not be loaded. + //无法加载找到的文件。 + LogCat.LogErrorWithFormat("load_dll_file_load_exception", LogCat.LogLabel.ModLoader, true, dllPath); + LogCat.WhenCaughtException(fileLoadException, LogCat.LogLabel.ModLoader); + return; + } + catch (BadImageFormatException badImageFormatException) + { + //assemblyPath is not a valid assembly. + //assemblyPath不是有效的程序集。 + LogCat.LogErrorWithFormat("load_dll_bad_image_format_exception", LogCat.LogLabel.ModLoader, true, + dllPath); + LogCat.WhenCaughtException(badImageFormatException, LogCat.LogLabel.ModLoader); + return; + } + + //Loading the dll succeeded. + //加载dll成功。 + LogCat.LogWithFormat("load_dll_success", LogCat.LogLabel.ModLoader, true, dllPath); + } + } + + public static void LoadMod() + { + } +} \ No newline at end of file diff --git a/scripts/utils/ResUtils.cs b/scripts/utils/ResUtils.cs index e142f61..423b514 100644 --- a/scripts/utils/ResUtils.cs +++ b/scripts/utils/ResUtils.cs @@ -1,4 +1,5 @@ using System; +using System.IO; namespace ColdMint.scripts.utils; @@ -14,6 +15,31 @@ public static class ResUtils /// private const string Suffix = ".remap"; + /// + /// Gets the location of its own dll + /// 获取自身dll的存放位置 + /// + /// + public static string? GetSelfDllFolder() + { + var currentDirectory = Environment.CurrentDirectory; + if (Config.GetOs() == Config.OsEnum.Editor) + { + return Path.Join(currentDirectory, ".godot", "mono", "temp", "bin", "Debug"); + } + + if (Config.GetOs() == Config.OsEnum.Windows) + { + return Path.Join(currentDirectory, "data_" + Config.SolutionName + "_windows_x86_64"); + } + + if (Config.GetOs() == Config.OsEnum.Linux) + { + return Path.Join(currentDirectory, "data_" + Config.SolutionName + "_linuxbsd_x86_64"); + } + return null; + } + /// /// The game returns the res directory with a.remap suffix at runtime, causing an error while loading the resource /// 游戏在运行时返回res目录后带有.remap后缀,导致加载资源时出错