diff --git a/.gitignore b/.gitignore index c24589a..608c619 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,7 @@ ModelManifest.xml .vs .vscode + +# JetBrains Rider +*.sln.iml +.idea diff --git a/CSharpManager/CSharpManager.csproj b/CSharpManager/CSharpManager.csproj index 9ec4149..20ff991 100644 --- a/CSharpManager/CSharpManager.csproj +++ b/CSharpManager/CSharpManager.csproj @@ -1,24 +1,25 @@  - - Exe - net472 - enable - True - latest - 0.0.6.0 - + + Exe + net472 + enable + latest + true + True + 0.0.6.0 + - - - + + + - - - + + + - - - + + + diff --git a/CSharpManager/CSharpModManager.cs b/CSharpManager/CSharpModManager.cs index c9c28ff..56ea48f 100644 --- a/CSharpManager/CSharpModManager.cs +++ b/CSharpManager/CSharpModManager.cs @@ -1,175 +1,181 @@ -using System; -using System.Collections.Generic; -using System.IO; using System.Reflection; -using System.Threading; -using System.Threading.Tasks; using CSharpModBase; using CSharpModBase.Input; using Mono.Cecil; +using static CSharpModBase.Common; -namespace CSharpManager +namespace CSharpManager; + +public class CSharpModManager { - public class CSharpModManager - { - static string? LoadingModName { get; set; } + private Thread? _loopThread; + private static string? LoadingModName { get; set; } - public List LoadedMods { get; } = new(); - public InputManager InputManager { get; } = new(); - public bool Develop { get; set; } - private Thread? loopThread; + public List LoadedMods { get; } = []; + public InputManager InputManager { get; } = new(); + public bool Develop { get; set; } - static CSharpModManager() - { - AppDomain currentDomain = AppDomain.CurrentDomain; - currentDomain.AssemblyResolve += AssemblyResolve; - currentDomain.UnhandledException += OnUnhandledException; + static CSharpModManager() + { + var currentDomain = AppDomain.CurrentDomain; + currentDomain.AssemblyResolve += AssemblyResolve; + currentDomain.UnhandledException += OnUnhandledException; - TaskScheduler.UnobservedTaskException += OnUnobservedTaskException; - } + TaskScheduler.UnobservedTaskException += OnUnobservedTaskException; + } - private static Assembly? TryLoadDll(string path) + public CSharpModManager() + { + Utils.InitInputManager(InputManager); + // load config from ini + Ini iniFile = new(Path.Combine(LoaderDir, "b1cs.ini")); + Develop = iniFile.GetValue("Develop", "Settings", "1").Trim() == "1"; + Log.Debug($"Develop: {Develop}"); + } + + private static Assembly? TryLoadDll(string path) + { + if (File.Exists(path)) { - if (File.Exists(path)) - { - return Assembly.LoadFrom(path); - } - return null; + return Assembly.LoadFrom(path); } - private static Assembly? AssemblyResolve(object sender, ResolveEventArgs args) + return null; + } + + private static Assembly? AssemblyResolve(object sender, ResolveEventArgs args) + { + try { - try + if (LoadingModName == null) { - if (LoadingModName == null) - { - return null; - } - string dllName = $"{new AssemblyName(args.Name).Name}.dll"; - return TryLoadDll(Path.Combine(Common.ModDir, LoadingModName, dllName)) ?? - TryLoadDll(Path.Combine(Common.ModDir, "Common", dllName)) ?? - TryLoadDll(Path.Combine(Common.LoaderDir, dllName)); + return null; } - catch (Exception e) - { - Log.Error($"Load assembly {args.Name} failed:"); - Log.Error(e); - } - return Assembly.Load(args.Name); - } - private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) - { - Log.Error($"UnhandledException:"); - Log.Error((Exception)e.ExceptionObject); + var dllName = $"{new AssemblyName(args.Name).Name}.dll"; + return TryLoadDll(Path.Combine(ModDir, LoadingModName, dllName)) ?? + TryLoadDll(Path.Combine(ModDir, "CommonDirs", dllName)) ?? + TryLoadDll(Path.Combine(LoaderDir, dllName)); } - - private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) + catch (Exception e) { - Log.Error($"UnobservedTaskException:"); - Log.Error(e.Exception); + Log.Error($"Load assembly {args.Name} failed:"); + Log.Error(e); } - public CSharpModManager() + return Assembly.Load(args.Name); + } + + private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) + { + Log.Error("UnhandledException:"); + Log.Error((Exception)e.ExceptionObject); + } + + private static void OnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e) + { + Log.Error("UnobservedTaskException:"); + Log.Error(e.Exception); + } + + public void LoadMods() + { + LoadedMods.Clear(); + if (!Directory.Exists(ModDir)) { - Utils.InitInputManager(InputManager); - // load config from ini - Ini iniFile = new(Path.Combine(Common.LoaderDir, "b1cs.ini")); - Develop = iniFile.GetValue("Develop", "Settings", "1").Trim() == "1"; - Log.Debug($"Develop: {Develop}"); + Log.Error($"Mod dir {ModDir} not exists"); + return; } - public void LoadMods() + string[] dirs = Directory.GetDirectories(ModDir); + var ICSharpModType = typeof(ICSharpMod); + foreach (var dir in dirs) { - LoadedMods.Clear(); - if (!Directory.Exists(Common.ModDir)) + LoadingModName = Path.GetFileName(dir); + var dllPath = Path.Combine(dir, $"{LoadingModName}.dll"); + if (!File.Exists(dllPath)) { - Log.Error($"Mod dir {Common.ModDir} not exists"); - return; + continue; } - string[] dirs = Directory.GetDirectories(Common.ModDir); - Type ICSharpModType = typeof(ICSharpMod); - foreach (var dir in dirs) + + try { - LoadingModName = Path.GetFileName(dir); - string dllPath = Path.Combine(dir, $"{LoadingModName}.dll"); - if (!File.Exists(dllPath)) continue; - try + Log.Debug($"======== Loading {dllPath} ========"); + Assembly assembly; + if (Develop) { - Log.Debug($"======== Loading {dllPath} ========"); - Assembly assembly; - if (Develop) - { - using var assemblyDef = AssemblyDefinition.ReadAssembly(dllPath); - assemblyDef.Name.Name += DateTime.Now.ToString("_yyyyMMdd_HHmmssffff"); - using MemoryStream stream = new(); - assemblyDef.Write(stream); - assembly = Assembly.Load(stream.GetBuffer()); - } - else - { - assembly = Assembly.LoadFrom(dllPath); - } - foreach (Type type in assembly.GetTypes()) + using var assemblyDef = AssemblyDefinition.ReadAssembly(dllPath); + assemblyDef.Name.Name += DateTime.Now.ToString("_yyyyMMdd_HHmmssffff"); + using MemoryStream stream = new(); + assemblyDef.Write(stream); + assembly = Assembly.Load(stream.GetBuffer()); + } + else + { + assembly = Assembly.LoadFrom(dllPath); + } + + foreach (var type in assembly.GetTypes()) + { + if (ICSharpModType.IsAssignableFrom(type)) { - if (ICSharpModType.IsAssignableFrom(type)) + Log.Debug($"Found ICSharpMod: {type}"); + + if (Activator.CreateInstance(type) is ICSharpMod mod) { - Log.Debug($"Found ICSharpMod: {type}"); - - if (Activator.CreateInstance(type) is ICSharpMod mod) - { - mod.Init(); - LoadedMods.Add(mod); - Log.Debug($"Loaded mod {mod.Name} {mod.Version}"); - } + mod.Init(); + LoadedMods.Add(mod); + Log.Debug($"Loaded mod {mod.Name} {mod.Version}"); } } - LoadingModName = null; - } - catch (Exception e) - { - Log.Error($"Load {dllPath} failed:"); - Log.Error(e); } + + LoadingModName = null; + } + catch (Exception e) + { + Log.Error($"Load {dllPath} failed:"); + Log.Error(e); } } + } - public void ReloadMods() + public void ReloadMods() + { + Log.Debug("ReloadMods"); + InputManager.Clear(); + foreach (var mod in LoadedMods) { - Log.Debug("ReloadMods"); - InputManager.Clear(); - foreach (var mod in LoadedMods) + try { - try - { - mod.DeInit(); - } - catch (Exception e) - { - Log.Error($"DeInit {mod.Name} failed:"); - Log.Error(e); - } + mod.DeInit(); + } + catch (Exception e) + { + Log.Error($"DeInit {mod.Name} failed:"); + Log.Error(e); } - LoadMods(); } - public void StartLoop() + LoadMods(); + } + + public void StartLoop() + { + InputManager.RegisterBuiltinKeyBind(ModifierKeys.Control, Key.F5, ReloadMods); + _loopThread = new Thread(Loop) { - InputManager.RegisterBuiltinKeyBind(ModifierKeys.Control, Key.F5, ReloadMods); - loopThread = new Thread(Loop) - { - // IsBackground = true, - }; - loopThread.Start(); - } + // IsBackground = true, + }; + _loopThread.Start(); + } - private void Loop() + private void Loop() + { + while (true) { - while (true) - { - InputManager.Update(); - Thread.Sleep(10); // 10ms - } + InputManager.Update(); + Thread.Sleep(10); // 10ms } } -} +} \ No newline at end of file diff --git a/CSharpManager/Ini.cs b/CSharpManager/Ini.cs index e19d41c..d342f20 100644 --- a/CSharpManager/Ini.cs +++ b/CSharpManager/Ini.cs @@ -1,96 +1,92 @@ -// https://gist.github.com/Larry57/5725301 - -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Text; +namespace CSharpManager; + public class Ini { - Dictionary> ini = new Dictionary>(StringComparer.InvariantCultureIgnoreCase); - string file; + private readonly string _file; + private readonly Dictionary> _ini = new(StringComparer.InvariantCultureIgnoreCase); /// - /// Initialize an INI file - /// Load it if it exists + /// Initialize an INI file + /// Load it if it exists /// /// Full path where the INI file has to be read from or written to public Ini(string file) { - this.file = file; + _file = file; if (!File.Exists(file)) + { return; + } Load(); } /// - /// Load the INI file content + /// Load the INI file content /// public void Load() { - var txt = File.ReadAllText(file); + var txt = File.ReadAllText(_file); - Dictionary currentSection = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + Dictionary currentSection = new(StringComparer.InvariantCultureIgnoreCase); - ini[""] = currentSection; + _ini[""] = currentSection; foreach (var l in txt.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries) - .Select((t, i) => new - { - idx = i, - text = t.Trim() - })) - // .Where(t => !string.IsNullOrWhiteSpace(t) && !t.StartsWith(";"))) + .Select((t, i) => new + { + idx = i, + text = t.Trim() + })) + // .Where(t => !string.IsNullOrWhiteSpace(t) && !t.StartsWith(";"))) { var line = l.text; if (line.StartsWith(";") || string.IsNullOrWhiteSpace(line)) { - currentSection.Add(";" + l.idx.ToString(), line); + currentSection.Add(";" + l.idx, line); continue; } if (line.StartsWith("[") && line.EndsWith("]")) { currentSection = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - ini[line.Substring(1, line.Length - 2)] = currentSection; + _ini[line.Substring(1, line.Length - 2)] = currentSection; continue; } - var idx = line.IndexOf("="); + var idx = line.IndexOf("=", StringComparison.Ordinal); if (idx == -1) + { currentSection[line] = ""; + } else + { currentSection[line.Substring(0, idx)] = line.Substring(idx + 1); + } } } /// - /// Get a parameter value at the root level + /// Get a parameter value at the root level /// /// parameter key /// - public string GetValue(string key) - { - return GetValue(key, "", ""); - } + public string GetValue(string key) => GetValue(key, "", ""); /// - /// Get a parameter value in the section + /// Get a parameter value in the section /// /// parameter key /// section /// - public string GetValue(string key, string section) - { - return GetValue(key, section, ""); - } + public string GetValue(string key, string section) => GetValue(key, section, ""); /// - /// Returns a parameter value in the section, with a default value if not found + /// Returns a parameter value in the section, with a default value if not found /// /// parameter key /// section @@ -98,22 +94,26 @@ public string GetValue(string key, string section) /// public string GetValue(string key, string section, string @default) { - if (!ini.ContainsKey(section)) + if (!_ini.TryGetValue(section, out var value)) + { return @default; + } - if (!ini[section].ContainsKey(key)) + if (!value.ContainsKey(key)) + { return @default; + } - return ini[section][key]; + return _ini[section][key]; } /// - /// Save the INI file + /// Save the INI file /// public void Save() { var sb = new StringBuilder(); - foreach (var section in ini) + foreach (var section in _ini) { if (section.Key != "") { @@ -135,27 +135,31 @@ public void Save() } } - if (!endWithCRLF(sb)) + if (!EndWithCrlf(sb)) + { sb.AppendLine(); + } } - File.WriteAllText(file, sb.ToString()); + File.WriteAllText(_file, sb.ToString()); } - bool endWithCRLF(StringBuilder sb) + private static bool EndWithCrlf(StringBuilder sb) { if (sb.Length < 4) + { return sb[sb.Length - 2] == '\r' && sb[sb.Length - 1] == '\n'; - else - return sb[sb.Length - 4] == '\r' && - sb[sb.Length - 3] == '\n' && - sb[sb.Length - 2] == '\r' && - sb[sb.Length - 1] == '\n'; + } + + return sb[sb.Length - 4] == '\r' && + sb[sb.Length - 3] == '\n' && + sb[sb.Length - 2] == '\r' && + sb[sb.Length - 1] == '\n'; } /// - /// Write a parameter value at the root level + /// Write a parameter value at the root level /// /// parameter key /// parameter value @@ -165,7 +169,7 @@ public void WriteValue(string key, string value) } /// - /// Write a parameter value in a section + /// Write a parameter value in a section /// /// parameter key /// section @@ -173,36 +177,40 @@ public void WriteValue(string key, string value) public void WriteValue(string key, string section, string value) { Dictionary currentSection; - if (!ini.ContainsKey(section)) + if (!_ini.ContainsKey(section)) { currentSection = new Dictionary(); - ini.Add(section, currentSection); + _ini.Add(section, currentSection); } else - currentSection = ini[section]; + { + currentSection = _ini[section]; + } currentSection[key] = value; } /// - /// Get all the keys names in a section + /// Get all the keys names in a section /// /// section /// public string[] GetKeys(string section) { - if (!ini.ContainsKey(section)) - return new string[0]; + if (!_ini.TryGetValue(section, out var value)) + { + return []; + } - return ini[section].Keys.ToArray(); + return value.Keys.ToArray(); } /// - /// Get all the section names of the INI file + /// Get all the section names of the INI file /// /// public string[] GetSections() { - return ini.Keys.Where(t => t != "").ToArray(); + return _ini.Keys.Where(t => t != "").ToArray(); } -} +} \ No newline at end of file diff --git a/CSharpManager/InputManager.cs b/CSharpManager/InputManager.cs index 70e97d6..d8846e4 100644 --- a/CSharpManager/InputManager.cs +++ b/CSharpManager/InputManager.cs @@ -1,177 +1,180 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; -using System.Threading; using CSharpModBase; using CSharpModBase.Input; -namespace CSharpManager +namespace CSharpManager; + +public class InputManager : IInputManager { - public class InputManager : IInputManager + // public static GamePadButtonEventHandler? GamePadButtonDown { get; set; } + + private IntPtr HWnd; + public List BuiltinHotKeyItems { get; } = []; + public List HotKeyItems { get; } = []; + public bool EnableGamePad { get; set; } = true; + public static GamePadButton CurrentGamePadButton { get; set; } + + public HotKeyItem RegisterKeyBind(Key key, Action action) { - public List BuiltinHotKeyItems { get; } = new(); - public List HotKeyItems { get; } = new(); - public bool EnableGamePad { get; set; } = true; - public static GamePadButton CurrentGamePadButton { get; set; } - // public static GamePadButtonEventHandler? GamePadButtonDown { get; set; } + var item = new HotKeyItem(ModifierKeys.None, key, action); + RegisterKeyBind(item); + return item; + } - private IntPtr HWnd; + public HotKeyItem RegisterKeyBind(ModifierKeys modifiers, Key key, Action action) + { + var item = new HotKeyItem(modifiers, key, action); + RegisterKeyBind(item); + return item; + } - public InputManager() + public HotKeyItem RegisterGamePadBind(GamePadButton button, Action action) + { + var item = new HotKeyItem(ModifierKeys.None, Key.None, action) { - } + GamePadButton = button + }; + RegisterKeyBind(item); + return item; + } - private void FindMainWindow() + private void FindMainWindow() + { + var currentProcessId = GetCurrentProcessId(); + StringBuilder stringBuilder = new(64); + EnumWindows((hWnd, lParam) => { - uint currentProcessId = GetCurrentProcessId(); - StringBuilder stringBuilder = new(64); - EnumWindows(new EnumWindowsProc((hWnd, lParam) => + GetWindowThreadProcessId(hWnd, out var processId); + if (processId == GetCurrentProcessId() && + GetClassName(hWnd, stringBuilder, stringBuilder.Capacity) > 0 && + stringBuilder.ToString() == "UnrealWindow") { - GetWindowThreadProcessId(hWnd, out uint processId); - if (processId == GetCurrentProcessId() && - GetClassName(hWnd, stringBuilder, stringBuilder.Capacity) > 0 && - stringBuilder.ToString() == "UnrealWindow") - { - HWnd = hWnd; - return false; - } - return true; // 继续枚举 - }), IntPtr.Zero); - } + HWnd = hWnd; + return false; + } + + return true; // 继续枚举 + }, IntPtr.Zero); + } - private void HandleKeys(List items) + private void HandleKeys(List items) + { + var now = DateTime.Now.Ticks / 10000; + var modifiers = KeyUtils.Modifiers; + foreach (var item in items) { - var now = DateTime.Now.Ticks / 10000; - var modifiers = KeyUtils.Modifiers; - foreach (var item in items) + if ((item.Modifiers == modifiers && KeyUtils.IsKeyDown(item.Key)) || + (CurrentGamePadButton != GamePadButton.None && item.GamePadButton != GamePadButton.None && CurrentGamePadButton.HasFlag(item.GamePadButton))) { - if (item.Modifiers == modifiers && KeyUtils.IsKeyDown(item.Key) || - CurrentGamePadButton != GamePadButton.None && item.GamePadButton != GamePadButton.None && CurrentGamePadButton.HasFlag(item.GamePadButton)) + if (item.IsPressed && (item.RepeatMs == 0 || (item.LastTriggerMs > 0 && now - item.LastTriggerMs < item.RepeatMs))) { - if (item.IsPressed && (item.RepeatMs == 0 || item.LastTriggerMs > 0 && now - item.LastTriggerMs < item.RepeatMs)) - { - continue; - } - item.IsPressed = true; - if (item.RunOnGameThread) - { - Utils.TryRunOnGameThread(item.Action); - } - else - { - Utils.TryRun(item.Action); - } + continue; } - else if (item.IsPressed) + + item.IsPressed = true; + if (item.RunOnGameThread) { - item.IsPressed = false; + Utils.TryRunOnGameThread(item.Action); + } + else + { + Utils.TryRun(item.Action); } } - } - - public void Update() - { - if (!IsProgramFocused()) return; - if (EnableGamePad) - { - GamePadUtils.GetGamePadButtons(out var buttons); - // if (buttons != GamePadButton.None) - // { - // GamePadButtonDown?.Invoke(new GamePadButtonEvent { Button = buttons }); - // } - CurrentGamePadButton = buttons; - } - HandleKeys(BuiltinHotKeyItems); - lock (HotKeyItems) + else if (item.IsPressed) { - HandleKeys(HotKeyItems); + item.IsPressed = false; } } + } - public void Clear() + public void Update() + { + if (!IsProgramFocused()) { - lock (HotKeyItems) - { - HotKeyItems.Clear(); - } + return; } - public bool IsProgramFocused() + if (EnableGamePad) { - if (HWnd == IntPtr.Zero) - { - Thread.Sleep(1000); - FindMainWindow(); - } - var hwnd = GetForegroundWindow(); - if (hwnd == IntPtr.Zero) return false; - return hwnd == HWnd; + GamePadUtils.GetGamePadButtons(out var buttons); + // if (buttons != GamePadButton.None) + // { + // GamePadButtonDown?.Invoke(new GamePadButtonEvent { Button = buttons }); + // } + CurrentGamePadButton = buttons; } - [DllImport("user32.dll")] - private extern static IntPtr GetForegroundWindow(); - - [DllImport("user32.dll", SetLastError = true)] - static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); - - [DllImport("kernel32.dll")] - static extern uint GetCurrentProcessId(); - - private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); - - // 导入Win32 API函数 - [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] - private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); - - [DllImport("user32.dll", CharSet = CharSet.Unicode)] - public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); - - public HotKeyItem RegisterBuiltinKeyBind(Key key, Action action) + HandleKeys(BuiltinHotKeyItems); + lock (HotKeyItems) { - var item = new HotKeyItem(ModifierKeys.None, key, action); - BuiltinHotKeyItems.Add(item); - return item; + HandleKeys(HotKeyItems); } + } - public HotKeyItem RegisterBuiltinKeyBind(ModifierKeys modifiers, Key key, Action action) + public void Clear() + { + lock (HotKeyItems) { - var item = new HotKeyItem(modifiers, key, action); - BuiltinHotKeyItems.Add(item); - return item; + HotKeyItems.Clear(); } + } - public void RegisterKeyBind(HotKeyItem item) + public bool IsProgramFocused() + { + if (HWnd == IntPtr.Zero) { - lock (HotKeyItems) - { - HotKeyItems.Add(item); - } + Thread.Sleep(1000); + FindMainWindow(); } - public HotKeyItem RegisterKeyBind(Key key, Action action) + var hwnd = GetForegroundWindow(); + if (hwnd == IntPtr.Zero) { - var item = new HotKeyItem(ModifierKeys.None, key, action); - RegisterKeyBind(item); - return item; + return false; } - public HotKeyItem RegisterKeyBind(ModifierKeys modifiers, Key key, Action action) - { - var item = new HotKeyItem(modifiers, key, action); - RegisterKeyBind(item); - return item; - } + return hwnd == HWnd; + } + + [DllImport("user32.dll")] + private static extern IntPtr GetForegroundWindow(); + + [DllImport("user32.dll", SetLastError = true)] + private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); + + [DllImport("kernel32.dll")] + private static extern uint GetCurrentProcessId(); - public HotKeyItem RegisterGamePadBind(GamePadButton button, Action action) + // 导入Win32 API函数 + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] + private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); + + [DllImport("user32.dll", CharSet = CharSet.Unicode)] + public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); + + public HotKeyItem RegisterBuiltinKeyBind(Key key, Action action) + { + var item = new HotKeyItem(ModifierKeys.None, key, action); + BuiltinHotKeyItems.Add(item); + return item; + } + + public HotKeyItem RegisterBuiltinKeyBind(ModifierKeys modifiers, Key key, Action action) + { + var item = new HotKeyItem(modifiers, key, action); + BuiltinHotKeyItems.Add(item); + return item; + } + + public void RegisterKeyBind(HotKeyItem item) + { + lock (HotKeyItems) { - var item = new HotKeyItem(ModifierKeys.None, Key.None, action) - { - GamePadButton = button - }; - RegisterKeyBind(item); - return item; + HotKeyItems.Add(item); } } -} + + private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); +} \ No newline at end of file diff --git a/CSharpManager/Program.cs b/CSharpManager/Program.cs index 963df59..ac08eb6 100644 --- a/CSharpManager/Program.cs +++ b/CSharpManager/Program.cs @@ -1,13 +1,11 @@ - -namespace CSharpManager +namespace CSharpManager; + +internal class Program { - internal class Program + public static void Main(string[] args) { - public static void Main(string[] args) - { - CSharpModManager manager = new(); - manager.LoadMods(); - manager.StartLoop(); - } + CSharpModManager manager = new(); + manager.LoadMods(); + manager.StartLoop(); } -} +} \ No newline at end of file diff --git a/CSharpManager/README.md b/CSharpManager/README.md index 6440321..759de20 100644 --- a/CSharpManager/README.md +++ b/CSharpManager/README.md @@ -1,4 +1,5 @@ # CSharpManager + C# mod的管理器,CSharpLoader会加载CSharpManager,通过CSharpManager加载其他C# mod ## 编译 diff --git a/CSharpManager/b1cs.ini b/CSharpManager/b1cs.ini index 04de55c..5adfe08 100644 --- a/CSharpManager/b1cs.ini +++ b/CSharpManager/b1cs.ini @@ -1,4 +1,4 @@ [Settings] -Develop=1 -Console=1 -EnableJit=1 \ No newline at end of file +Develop = 1 +Console = 1 +EnableJit = 1 \ No newline at end of file diff --git a/CSharpModBase/CSharpModBase.cs b/CSharpModBase/CSharpModBase.cs index 5f5b904..0dce7c7 100644 --- a/CSharpModBase/CSharpModBase.cs +++ b/CSharpModBase/CSharpModBase.cs @@ -1,33 +1,24 @@ -namespace CSharpModBase -{ - public static class Common - { - public const string LoaderDir = "CSharpLoader"; - public const string ModDir = "CSharpLoader\\Mods"; - public const string DataDir = "CSharpLoader\\Data"; - } +namespace CSharpModBase; +public interface ICSharpMod +{ + /// + /// mod name + /// + string Name { get; } - public interface ICSharpMod - { - /// - /// mod name - /// - string Name { get; } + /// + /// mod version + /// + string Version { get; } - /// - /// mod version - /// - string Version { get; } + /// + /// when mod loaded, will call OnInit + /// + void Init(); - /// - /// when mod loaded, will call OnInit - /// - void Init(); - /// - /// when manamger reload mods, will call OnDeInit, - /// - /// - void DeInit(); - } -} + /// + /// when manager reload mods, will call OnDeInit, + /// + void DeInit(); +} \ No newline at end of file diff --git a/CSharpModBase/CSharpModBase.csproj b/CSharpModBase/CSharpModBase.csproj index 68192f0..2e319a4 100644 --- a/CSharpModBase/CSharpModBase.csproj +++ b/CSharpModBase/CSharpModBase.csproj @@ -1,27 +1,28 @@  - - net472 - enable - latest - True - 0.0.6.0 - + + net472 + enable + latest + true + True + 0.0.6.0 + - - - + + + - - - - + + + + - - - ..\GameDll\UnrealEngine.Runtime.dll - False - - + + + ..\GameDll\UnrealEngine.Runtime.dll + False + + diff --git a/CSharpModBase/Common.cs b/CSharpModBase/Common.cs new file mode 100644 index 0000000..b1be0f3 --- /dev/null +++ b/CSharpModBase/Common.cs @@ -0,0 +1,8 @@ +namespace CSharpModBase; + +public static class Common +{ + public const string LoaderDir = "CSharpLoader"; + public const string ModDir = @"CSharpLoader\Mods"; + public const string DataDir = @"CSharpLoader\Data"; +} \ No newline at end of file diff --git a/CSharpModBase/Input/GamePad.cs b/CSharpModBase/Input/GamePad.cs index b225fc3..340a992 100644 --- a/CSharpModBase/Input/GamePad.cs +++ b/CSharpModBase/Input/GamePad.cs @@ -1,60 +1,36 @@ -using System; using SharpDX.XInput; -namespace CSharpModBase.Input -{ - [Flags] - public enum GamePadButton - { - None = GamepadButtonFlags.None, - DPadUp = GamepadButtonFlags.DPadUp, - DPadDown = GamepadButtonFlags.DPadDown, - DPadLeft = GamepadButtonFlags.DPadLeft, - DPadRight = GamepadButtonFlags.DPadRight, - Start = GamepadButtonFlags.Start, - Back = GamepadButtonFlags.Back, - LeftThumb = GamepadButtonFlags.LeftThumb, - RightThumb = GamepadButtonFlags.RightThumb, - LeftShoulder = GamepadButtonFlags.LeftShoulder, - RightShoulder = GamepadButtonFlags.RightShoulder, - A = GamepadButtonFlags.A, - B = GamepadButtonFlags.B, - X = GamepadButtonFlags.X, - Y = GamepadButtonFlags.Y, - LeftTrigger = 0x10000, - RightTrigger = 0x20000, - DPadRightUp = DPadRight | DPadUp, - DPadLeftDown = DPadLeft | DPadDown, - DPadRightDown = DPadRight | DPadDown, - DPadLeftUp = DPadLeft | DPadUp, - } - - - public static class GamePadUtils - { - private static readonly Controller controller = new Controller(UserIndex.One); - - public static bool GetGamePadButtons(out GamePadButton flags) - { - flags = GamePadButton.None; - if (controller.GetState(out State state)) - { - Gamepad gamepad = state.Gamepad; - flags = (GamePadButton)gamepad.Buttons; - if (gamepad.LeftTrigger > 100) flags |= GamePadButton.LeftTrigger; - if (gamepad.RightTrigger > 100) flags |= GamePadButton.RightTrigger; - return true; - } - return false; - } - } - - - public class GamePadButtonEvent : EventArgs - { - public GamePadButton Button { get; set; } - } +namespace CSharpModBase.Input; +[Flags] +public enum GamePadButton +{ + None = GamepadButtonFlags.None, + DPadUp = GamepadButtonFlags.DPadUp, + DPadDown = GamepadButtonFlags.DPadDown, + DPadLeft = GamepadButtonFlags.DPadLeft, + DPadRight = GamepadButtonFlags.DPadRight, + Start = GamepadButtonFlags.Start, + Back = GamepadButtonFlags.Back, + LeftThumb = GamepadButtonFlags.LeftThumb, + RightThumb = GamepadButtonFlags.RightThumb, + LeftShoulder = GamepadButtonFlags.LeftShoulder, + RightShoulder = GamepadButtonFlags.RightShoulder, + A = GamepadButtonFlags.A, + B = GamepadButtonFlags.B, + X = GamepadButtonFlags.X, + Y = GamepadButtonFlags.Y, + LeftTrigger = 0x10000, + RightTrigger = 0x20000, + DPadRightUp = DPadRight | DPadUp, + DPadLeftDown = DPadLeft | DPadDown, + DPadRightDown = DPadRight | DPadDown, + DPadLeftUp = DPadLeft | DPadUp +} - public delegate void GamePadButtonEventHandler(GamePadButtonEvent e); +public sealed class GamePadButtonEvent : EventArgs +{ + public GamePadButton Button { get; set; } } + +public delegate void GamePadButtonEventHandler(GamePadButtonEvent e); \ No newline at end of file diff --git a/CSharpModBase/Input/GamePadUtils.cs b/CSharpModBase/Input/GamePadUtils.cs new file mode 100644 index 0000000..3fe6eed --- /dev/null +++ b/CSharpModBase/Input/GamePadUtils.cs @@ -0,0 +1,31 @@ +using SharpDX.XInput; + +namespace CSharpModBase.Input; + +public static class GamePadUtils +{ + private static readonly Controller Controller = new(UserIndex.One); + + public static bool GetGamePadButtons(out GamePadButton flags) + { + flags = GamePadButton.None; + if (Controller.GetState(out var state)) + { + var gamepad = state.Gamepad; + flags = (GamePadButton)gamepad.Buttons; + if (gamepad.LeftTrigger > 100) + { + flags |= GamePadButton.LeftTrigger; + } + + if (gamepad.RightTrigger > 100) + { + flags |= GamePadButton.RightTrigger; + } + + return true; + } + + return false; + } +} \ No newline at end of file diff --git a/CSharpModBase/Input/HotKeyData.cs b/CSharpModBase/Input/HotKeyData.cs new file mode 100644 index 0000000..8883578 --- /dev/null +++ b/CSharpModBase/Input/HotKeyData.cs @@ -0,0 +1,60 @@ +namespace CSharpModBase.Input; + +public class HotKeyData +{ + public ModifierKeys Modifiers { get; set; } + public Key Key { get; set; } + public GamePadButton GamePadButton { get; set; } + + public bool IsValid => Key != Key.None || GamePadButton != GamePadButton.None; + public string KeyString => KeyUtils.KeyToString(Modifiers, Key); + + public uint Code + { + get + { + if (GamePadButton != GamePadButton.None) + { + return 0xF0000000 | (uint)GamePadButton; + } + + return GetCode(Modifiers, Key); + } + } + + public HotKeyData(ModifierKeys modifiers, Key key) + { + Modifiers = modifiers; + Key = key; + } + + public HotKeyData() : this(ModifierKeys.None, Key.None) + { + } + + public static uint GetCode(ModifierKeys modifiers, Key key) => ((uint)modifiers << 16) | (uint)key; + + public void SetFromCode(uint code) + { + if (code >> 24 == 0xF0) + { + GamePadButton = (GamePadButton)(code & 0xFFFF); + Modifiers = ModifierKeys.None; + Key = Key.None; + } + else + { + GamePadButton = GamePadButton.None; + Modifiers = (ModifierKeys)(code >> 16); + Key = (Key)(code & 0xFF); + } + } + + public void SetKey(ModifierKeys modifiers, Key key) + { + Modifiers = modifiers; + Key = key; + } + + public override string ToString() => KeyString; +} \ No newline at end of file diff --git a/CSharpModBase/Input/HotKeyItem.cs b/CSharpModBase/Input/HotKeyItem.cs index 852e36b..8690ec6 100644 --- a/CSharpModBase/Input/HotKeyItem.cs +++ b/CSharpModBase/Input/HotKeyItem.cs @@ -1,112 +1,44 @@ -using System; +namespace CSharpModBase.Input; -namespace CSharpModBase.Input +public class HotKeyItem : HotKeyData { - public class HotKeyData - { - public HotKeyData(ModifierKeys modifiers, Key key) - { - Modifiers = modifiers; - Key = key; - } - - public HotKeyData() : this(ModifierKeys.None, Key.None) {} - - public ModifierKeys Modifiers { get; set; } - public Key Key { get; set; } - public GamePadButton GamePadButton { get; set; } + public string Label { get; set; } + public Action Action { get; set; } - public bool IsValid => Key != Key.None || GamePadButton != GamePadButton.None; - public string KeyString => KeyUtils.KeyToString(Modifiers, Key); + /// + /// 0为不支持连按,大于0为连按触发毫秒间隔 + /// + public int RepeatMs { get; set; } - public static uint GetCode(ModifierKeys modifiers, Key key) - { - return ((uint)modifiers << 16) | (uint)key; - } + /// + /// 上一次触发的时间,毫秒 + /// + public long LastTriggerMs { get; set; } - public uint Code - { - get - { - if (GamePadButton != GamePadButton.None) - { - return 0xF0000000 | (uint)GamePadButton; - } - else - { - return GetCode(Modifiers, Key); - } - } - } + /// + /// 正在被按下 + /// + public bool IsPressed { get; set; } - public void SetFromCode(uint code) - { - if ((code >> 24) == 0xF0) - { - GamePadButton = (GamePadButton)(code & 0xFFFF); - Modifiers = ModifierKeys.None; - Key = Key.None; - } - else - { - GamePadButton = GamePadButton.None; - Modifiers = (ModifierKeys)(code >> 16); - Key = (Key)(code & 0xFF); - } - } + public bool RunOnGameThread { get; set; } = true; - public void SetKey(ModifierKeys modifiers, Key key) - { - Modifiers = modifiers; - Key = key; - } - - public override string ToString() - { - return KeyString; - } + public HotKeyItem(ModifierKeys modifiers, Key key, Action action) : this("", modifiers, key, action) + { } - - public class HotKeyItem : HotKeyData + public HotKeyItem(string label, ModifierKeys modifiers, Key key, Action action) : base(modifiers, key) { - public string Label { get; set; } - public Action Action { get; set; } - /// - /// 0为不支持连按,大于0为连按触发毫秒间隔 - /// - public int RepeatMs { get; set; } - /// - /// 上一次触发的时间,毫秒 - /// - public long LastTriggerMs { get; set; } - /// - /// 正在被按下 - /// - public bool IsPressed { get; set; } - public bool RunOnGameThread { get; set; } = true; - - public HotKeyItem WithKey(ModifierKeys Modifiers, Key Key) - { - return new(Label, Modifiers, Key, Action); - } - - public HotKeyItem(ModifierKeys modifiers, Key key, Action action) : this("", modifiers, key, action) - { - } + Label = label; + Action = action; + } - public HotKeyItem(string label, ModifierKeys modifiers, Key key, Action action) : base(modifiers, key) - { - Label = label; - Action = action; - } + public HotKeyItem() : this("", ModifierKeys.None, Key.None, EmptyAction) + { + } - public HotKeyItem() : this("", ModifierKeys.None, Key.None, EmptyAction) - { - } + public HotKeyItem WithKey(ModifierKeys modifiers, Key key) => new(Label, modifiers, key, Action); - private static void EmptyAction() - { - } + private static void EmptyAction() + { } -} +} \ No newline at end of file diff --git a/CSharpModBase/Input/IInputManager.cs b/CSharpModBase/Input/IInputManager.cs index 2412625..d7ac1ad 100644 --- a/CSharpModBase/Input/IInputManager.cs +++ b/CSharpModBase/Input/IInputManager.cs @@ -1,12 +1,9 @@ -using System; +namespace CSharpModBase.Input; -namespace CSharpModBase.Input +public interface IInputManager { - public interface IInputManager - { - HotKeyItem RegisterKeyBind(Key key, Action action); + HotKeyItem RegisterKeyBind(Key key, Action action); - HotKeyItem RegisterKeyBind(ModifierKeys modifiers, Key key, Action action); - HotKeyItem RegisterGamePadBind(GamePadButton button, Action action); - } -} + HotKeyItem RegisterKeyBind(ModifierKeys modifiers, Key key, Action action); + HotKeyItem RegisterGamePadBind(GamePadButton button, Action action); +} \ No newline at end of file diff --git a/CSharpModBase/Input/Key.cs b/CSharpModBase/Input/Key.cs index 9ae37b4..571f2a9 100644 --- a/CSharpModBase/Input/Key.cs +++ b/CSharpModBase/Input/Key.cs @@ -1,146 +1,145 @@ -namespace CSharpModBase.Input +namespace CSharpModBase.Input; + +public enum Key { - public enum Key - { - None = 0x00, - LBUTTON = 0x01, - RBUTTON = 0x02, - CANCEL = 0x03, - MBUTTON = 0x04, - XBUTTON1 = 0x05, - XBUTTON2 = 0x06, - BACK = 0x08, - TAB = 0x09, - CLEAR = 0x0C, - RETURN = 0x0D, - ENTER = RETURN, - SHIFT = 0x10, - CONTROL = 0x11, - MENU = 0x12, - PAUSE = 0x13, - CAPITAL = 0x14, - KANA = 0x15, - HANGEUL = 0x15, - HANGUL = 0x15, - ESCAPE = 0x1B, - CONVERT = 0x1C, - NONCONVERT = 0x1D, - ACCEPT = 0x1E, - MODECHANGE = 0x1F, - SPACE = 0x20, - PRIOR = 0x21, - NEXT = 0x22, - END = 0x23, - HOME = 0x24, - LEFT = 0x25, - UP = 0x26, - RIGHT = 0x27, - DOWN = 0x28, - SELECT = 0x29, - PRINT = 0x2A, - EXECUTE = 0x2B, - SNAPSHOT = 0x2C, - INSERT = 0x2D, - DELETE = 0x2E, - HELP = 0x2F, - D0 = 0x30, - D1 = 0x31, - D2 = 0x32, - D3 = 0x33, - D4 = 0x34, - D5 = 0x35, - D6 = 0x36, - D7 = 0x37, - D8 = 0x38, - D9 = 0x39, - A = 0x41, - B = 0x42, - C = 0x43, - D = 0x44, - E = 0x45, - F = 0x46, - G = 0x47, - H = 0x48, - I = 0x49, - J = 0x4A, - K = 0x4B, - L = 0x4C, - M = 0x4D, - N = 0x4E, - O = 0x4F, - P = 0x50, - Q = 0x51, - R = 0x52, - S = 0x53, - T = 0x54, - U = 0x55, - V = 0x56, - W = 0x57, - X = 0x58, - Y = 0x59, - Z = 0x5A, - LWIN = 0x5B, - RWIN = 0x5C, - APPS = 0x5D, - SLEEP = 0x5F, - NUMPAD0 = 0x60, - NUMPAD1 = 0x61, - NUMPAD2 = 0x62, - NUMPAD3 = 0x63, - NUMPAD4 = 0x64, - NUMPAD5 = 0x65, - NUMPAD6 = 0x66, - NUMPAD7 = 0x67, - NUMPAD8 = 0x68, - NUMPAD9 = 0x69, - MULTIPLY = 0x6A, - ADD = 0x6B, - SEPARATOR = 0x6C, - SUBTRACT = 0x6D, - DECIMAL = 0x6E, - DIVIDE = 0x6F, - F1 = 0x70, - F2 = 0x71, - F3 = 0x72, - F4 = 0x73, - F5 = 0x74, - F6 = 0x75, - F7 = 0x76, - F8 = 0x77, - F9 = 0x78, - F10 = 0x79, - F11 = 0x7A, - F12 = 0x7B, - F13 = 0x7C, - F14 = 0x7D, - F15 = 0x7E, - F16 = 0x7F, - F17 = 0x80, - F18 = 0x81, - F19 = 0x82, - F20 = 0x83, - F21 = 0x84, - F22 = 0x85, - F23 = 0x86, - F24 = 0x87, - NUMLOCK = 0x90, - SCROLL = 0x91, - LSHIFT = 0xA0, - RSHIFT = 0xA1, - LCONTROL = 0xA2, - RCONTROL = 0xA3, - LMENU = 0xA4, - RMENU = 0xA5, - OEM_1 = 0xBA, // ';' - OEM_PLUS = 0xBB, // '+' - OEM_COMMA = 0xBC, // ',' - OEM_MINUS = 0xBD, // '-' - OEM_PERIOD = 0xBE, // '.' - OEM_2 = 0xBF, // '/' - OEM_3 = 0xC0, // '`' - OEM_4 = 0xDB, // '[' - OEM_5 = 0xDC, // '\\' - OEM_6 = 0xDD, // ']' - OEM_7 = 0xDE, // '\'' - } -} + None = 0x00, + LBUTTON = 0x01, + RBUTTON = 0x02, + CANCEL = 0x03, + MBUTTON = 0x04, + XBUTTON1 = 0x05, + XBUTTON2 = 0x06, + BACK = 0x08, + TAB = 0x09, + CLEAR = 0x0C, + RETURN = 0x0D, + ENTER = RETURN, + SHIFT = 0x10, + CONTROL = 0x11, + MENU = 0x12, + PAUSE = 0x13, + CAPITAL = 0x14, + KANA = 0x15, + HANGEUL = 0x15, + HANGUL = 0x15, + ESCAPE = 0x1B, + CONVERT = 0x1C, + NONCONVERT = 0x1D, + ACCEPT = 0x1E, + MODECHANGE = 0x1F, + SPACE = 0x20, + PRIOR = 0x21, + NEXT = 0x22, + END = 0x23, + HOME = 0x24, + LEFT = 0x25, + UP = 0x26, + RIGHT = 0x27, + DOWN = 0x28, + SELECT = 0x29, + PRINT = 0x2A, + EXECUTE = 0x2B, + SNAPSHOT = 0x2C, + INSERT = 0x2D, + DELETE = 0x2E, + HELP = 0x2F, + D0 = 0x30, + D1 = 0x31, + D2 = 0x32, + D3 = 0x33, + D4 = 0x34, + D5 = 0x35, + D6 = 0x36, + D7 = 0x37, + D8 = 0x38, + D9 = 0x39, + A = 0x41, + B = 0x42, + C = 0x43, + D = 0x44, + E = 0x45, + F = 0x46, + G = 0x47, + H = 0x48, + I = 0x49, + J = 0x4A, + K = 0x4B, + L = 0x4C, + M = 0x4D, + N = 0x4E, + O = 0x4F, + P = 0x50, + Q = 0x51, + R = 0x52, + S = 0x53, + T = 0x54, + U = 0x55, + V = 0x56, + W = 0x57, + X = 0x58, + Y = 0x59, + Z = 0x5A, + LWIN = 0x5B, + RWIN = 0x5C, + APPS = 0x5D, + SLEEP = 0x5F, + NUMPAD0 = 0x60, + NUMPAD1 = 0x61, + NUMPAD2 = 0x62, + NUMPAD3 = 0x63, + NUMPAD4 = 0x64, + NUMPAD5 = 0x65, + NUMPAD6 = 0x66, + NUMPAD7 = 0x67, + NUMPAD8 = 0x68, + NUMPAD9 = 0x69, + MULTIPLY = 0x6A, + ADD = 0x6B, + SEPARATOR = 0x6C, + SUBTRACT = 0x6D, + DECIMAL = 0x6E, + DIVIDE = 0x6F, + F1 = 0x70, + F2 = 0x71, + F3 = 0x72, + F4 = 0x73, + F5 = 0x74, + F6 = 0x75, + F7 = 0x76, + F8 = 0x77, + F9 = 0x78, + F10 = 0x79, + F11 = 0x7A, + F12 = 0x7B, + F13 = 0x7C, + F14 = 0x7D, + F15 = 0x7E, + F16 = 0x7F, + F17 = 0x80, + F18 = 0x81, + F19 = 0x82, + F20 = 0x83, + F21 = 0x84, + F22 = 0x85, + F23 = 0x86, + F24 = 0x87, + NUMLOCK = 0x90, + SCROLL = 0x91, + LSHIFT = 0xA0, + RSHIFT = 0xA1, + LCONTROL = 0xA2, + RCONTROL = 0xA3, + LMENU = 0xA4, + RMENU = 0xA5, + OEM_1 = 0xBA, // ';' + OEM_PLUS = 0xBB, // '+' + OEM_COMMA = 0xBC, // ',' + OEM_MINUS = 0xBD, // '-' + OEM_PERIOD = 0xBE, // '.' + OEM_2 = 0xBF, // '/' + OEM_3 = 0xC0, // '`' + OEM_4 = 0xDB, // '[' + OEM_5 = 0xDC, // '\\' + OEM_6 = 0xDD, // ']' + OEM_7 = 0xDE, // '\'' +} \ No newline at end of file diff --git a/CSharpModBase/Input/KeyUtils.cs b/CSharpModBase/Input/KeyUtils.cs index 1f2618b..3bdcf36 100644 --- a/CSharpModBase/Input/KeyUtils.cs +++ b/CSharpModBase/Input/KeyUtils.cs @@ -1,89 +1,103 @@ -using System.Collections.Generic; using System.Runtime.InteropServices; -namespace CSharpModBase.Input +namespace CSharpModBase.Input; + +public static class KeyUtils { - public static class KeyUtils + public static ModifierKeys Modifiers { - /// - /// Keys转字符串,支持组合键 - /// - /// - /// - public static string KeyToString(ModifierKeys modifiers, Key key, List buf) + get { - if (modifiers.HasFlag(ModifierKeys.Control)) buf.Add("Ctrl"); - if (modifiers.HasFlag(ModifierKeys.Shift)) buf.Add("Shift"); - if (modifiers.HasFlag(ModifierKeys.Alt)) buf.Add("Alt"); - string? keyCodeStr = null; - char oemKeyChar = OemKeyChar(key); - if (oemKeyChar != default) { - keyCodeStr = oemKeyChar.ToString(); - } else { - keyCodeStr = key switch - { - Key.None => "", - _ => key.ToString(), - }; + var modifiers = ModifierKeys.None; + if (GetKeyState((uint)Key.MENU) < 0) + { + modifiers |= ModifierKeys.Alt; } - if (keyCodeStr != null) + + if (GetKeyState((uint)Key.CONTROL) < 0) { - buf.Add(keyCodeStr); + modifiers |= ModifierKeys.Control; } - return string.Join("+", buf); + + if (GetKeyState((uint)Key.SHIFT) < 0) + { + modifiers |= ModifierKeys.Shift; + } + + return modifiers; } + } - public static string KeyToString(ModifierKeys modifiers, Key key) + /// + /// Keys转字符串,支持组合键 + /// + /// + /// + /// + /// + public static string KeyToString(ModifierKeys modifiers, Key key, List buf) + { + if (modifiers.HasFlag(ModifierKeys.Control)) { - return KeyToString(modifiers, key, new()); + buf.Add("Ctrl"); } - public static char OemKeyChar(Key key) + if (modifiers.HasFlag(ModifierKeys.Shift)) { - return key switch - { - Key.OEM_PLUS => '+', - Key.OEM_COMMA => ',', - Key.OEM_MINUS => '-', - Key.OEM_PERIOD => '.', - Key.OEM_1 => ';', - Key.OEM_2 => '/', - Key.OEM_3 => '`', - Key.OEM_4 => '[', - Key.OEM_5 => '\\', - Key.OEM_6 => ']', - Key.OEM_7 => '\'', - _ => default, - }; + buf.Add("Shift"); } - [DllImport("user32.dll")] - private static extern short GetKeyState(uint vk); - - public static bool IsKeyDown(Key key) + if (modifiers.HasFlag(ModifierKeys.Alt)) { - return GetKeyState((uint)key) < 0; + buf.Add("Alt"); } - public static ModifierKeys Modifiers + string? keyCodeStr; + var oemKeyChar = OemKeyChar(key); + if (oemKeyChar != default) + { + keyCodeStr = oemKeyChar.ToString(); + } + else { - get + keyCodeStr = key switch { - ModifierKeys modifiers = ModifierKeys.None; - if (GetKeyState((uint)Key.MENU) < 0) - { - modifiers |= ModifierKeys.Alt; - } - if (GetKeyState((uint)Key.CONTROL) < 0) - { - modifiers |= ModifierKeys.Control; - } - if (GetKeyState((uint)Key.SHIFT) < 0) - { - modifiers |= ModifierKeys.Shift; - } - return modifiers; - } + Key.None => "", + _ => key.ToString() + }; } + + if (keyCodeStr != null) + { + buf.Add(keyCodeStr); + } + + return string.Join("+", buf); } -} + + public static string KeyToString(ModifierKeys modifiers, Key key) => KeyToString(modifiers, key, new List()); + + public static char OemKeyChar(Key key) + { + return key switch + { + Key.OEM_PLUS => '+', + Key.OEM_COMMA => ',', + Key.OEM_MINUS => '-', + Key.OEM_PERIOD => '.', + Key.OEM_1 => ';', + Key.OEM_2 => '/', + Key.OEM_3 => '`', + Key.OEM_4 => '[', + Key.OEM_5 => '\\', + Key.OEM_6 => ']', + Key.OEM_7 => '\'', + _ => default + }; + } + + [DllImport("user32.dll")] + private static extern short GetKeyState(uint vk); + + public static bool IsKeyDown(Key key) => GetKeyState((uint)key) < 0; +} \ No newline at end of file diff --git a/CSharpModBase/Input/ModifierKeys.cs b/CSharpModBase/Input/ModifierKeys.cs index 7876a83..adbdde7 100644 --- a/CSharpModBase/Input/ModifierKeys.cs +++ b/CSharpModBase/Input/ModifierKeys.cs @@ -1,14 +1,11 @@ -using System; +namespace CSharpModBase.Input; -namespace CSharpModBase.Input +[Flags] +public enum ModifierKeys { - [Flags] - public enum ModifierKeys - { - None = 0, - Alt = 1, - Control = 2, - Shift = 4, - Windows = 8 - } -} + None = 0, + Alt = 1, + Control = 2, + Shift = 4, + Windows = 8 +} \ No newline at end of file diff --git a/CSharpModBase/Log.cs b/CSharpModBase/Log.cs index f6a0eb8..29ff3dc 100644 --- a/CSharpModBase/Log.cs +++ b/CSharpModBase/Log.cs @@ -1,78 +1,68 @@ -using System; -using System.IO; +namespace CSharpModBase; -namespace CSharpModBase +public static class Log { - public static class Log - { - private static string DateTimeString => DateTime.Now.ToString("MM-dd HH:mm:ss"); // .fff - // private static readonly StreamWriter LogFile = File.CreateText("CSharpLog.txt"); + private static string DateTimeString => DateTime.Now.ToString("MM-dd HH:mm:ss"); // .fff + // private static readonly StreamWriter LogFile = File.CreateText("CSharpLog.txt"); - public static void Info(string message) - { - string text = $"{DateTimeString} [I] {message}"; - Console.WriteLine(text); - // LogFile.WriteLine(text); - } + public static void Info(string message) + { + var text = $"{DateTimeString} [I] {message}"; + Console.WriteLine(text); + // LogFile.WriteLine(text); + } - public static void Debug(string message) - { - using (var color = new ChangeConsoleColor(ConsoleColor.Gray)) - { - string text = $"{DateTimeString} [D] {message}"; - Console.WriteLine(text); - // LogFile.WriteLine(text); - } - } + public static void Debug(string message) + { + using var color = new ChangeConsoleColor(ConsoleColor.Gray); + var text = $"{DateTimeString} [D] {message}"; + Console.WriteLine(text); + // LogFile.WriteLine(text); + } - public static void Warn(string message) - { - using (var color = new ChangeConsoleColor(ConsoleColor.Yellow)) - { - string text = $"{DateTimeString} [W] {message}"; - Console.WriteLine(text); - // LogFile.WriteLine(text); - } - } + public static void Warn(string message) + { + using var color = new ChangeConsoleColor(ConsoleColor.Yellow); + var text = $"{DateTimeString} [W] {message}"; + Console.WriteLine(text); + // LogFile.WriteLine(text); + } - public static void WarnIf(bool condition, string message) + public static void WarnIf(bool condition, string message) + { + if (condition) { - if (condition) { - Warn(message); - } + Warn(message); } + } - public static void Error(string message) - { - using (var color = new ChangeConsoleColor(ConsoleColor.Red)) - { - string text = $"{DateTimeString} [E] {message}"; - Console.Error.WriteLine(text); - // LogFile.WriteLine(text); - } - } + public static void Error(string message) + { + using var color = new ChangeConsoleColor(ConsoleColor.Red); + var text = $"{DateTimeString} [E] {message}"; + Console.Error.WriteLine(text); + // LogFile.WriteLine(text); + } - public static void Error(Exception e) - { - Error(e.Message); - Error(e.StackTrace); - } + public static void Error(Exception e) + { + Error(e.Message); + Error(e.StackTrace); } +} +public readonly struct ChangeConsoleColor : IDisposable +{ + private readonly ConsoleColor _currentForeground; - public readonly struct ChangeConsoleColor : IDisposable + public ChangeConsoleColor(ConsoleColor color) { - readonly ConsoleColor currentForeground; - - public ChangeConsoleColor(ConsoleColor color) - { - currentForeground = Console.ForegroundColor; - Console.ForegroundColor = color; - } + _currentForeground = Console.ForegroundColor; + Console.ForegroundColor = color; + } - public void Dispose() - { - Console.ForegroundColor = currentForeground; - } + public void Dispose() + { + Console.ForegroundColor = _currentForeground; } -} +} \ No newline at end of file diff --git a/CSharpModBase/Utils.cs b/CSharpModBase/Utils.cs index 5901f8b..47d2d4d 100644 --- a/CSharpModBase/Utils.cs +++ b/CSharpModBase/Utils.cs @@ -1,58 +1,47 @@ -using System; using CSharpModBase.Input; using UnrealEngine.Runtime; -namespace CSharpModBase +namespace CSharpModBase; + +public static class Utils { - public static class Utils + private static IInputManager? _inputManager; + + public static void InitInputManager(IInputManager inputManager) { - private static IInputManager? InputManager; + _inputManager = inputManager; + } - public static void InitInputManager(IInputManager inputManager) - { - InputManager = inputManager; - } + public static HotKeyItem RegisterKeyBind(Key key, Action action) => _inputManager!.RegisterKeyBind(key, action); - public static HotKeyItem RegisterKeyBind(Key key, Action action) - { - return InputManager!.RegisterKeyBind(key, action); - } + public static HotKeyItem RegisterKeyBind(ModifierKeys modifiers, Key key, Action action) => _inputManager!.RegisterKeyBind(modifiers, key, action); - public static HotKeyItem RegisterKeyBind(ModifierKeys modifiers, Key key, Action action) + public static HotKeyItem RegisterGamePadBind(GamePadButton button, Action action) => _inputManager!.RegisterGamePadBind(button, action); + + public static void TryRun(Action action) + { + try { - return InputManager!.RegisterKeyBind(modifiers, key, action); + action(); } - - public static HotKeyItem RegisterGamePadBind(GamePadButton button, Action action) + catch (Exception e) { - return InputManager!.RegisterGamePadBind(button, action); + Log.Error(e); } + } - public static void TryRun(Action aciton) + public static void TryRunOnGameThread(Action action) + { + FThreading.RunOnGameThread(() => { try { - aciton(); + action(); } catch (Exception e) { Log.Error(e); - }; - } - - public static void TryRunOnGameThread(Action aciton) - { - FThreading.RunOnGameThread(() => - { - try - { - aciton(); - } - catch (Exception e) - { - Log.Error(e); - } - }); - } + } + }); } -} +} \ No newline at end of file diff --git a/README.en.md b/README.en.md index e0f9fe8..01b5005 100644 --- a/README.en.md +++ b/README.en.md @@ -59,7 +59,7 @@ In version 0.0.7 of the C# loader, to enable C# patch/hook features, the game's Suggest install [.net 8 sdk](https://dotnet.microsoft.com/) to develop with latest syntax. You can use vscode, visual studio or rider to write code. -See CSharpModExample. +For mod template, follow [B1.Mod.Template](https://github.com/BlackMythWukongMods/B1.Mod.Template)'s Readme to install and use it ### Mod entrance diff --git a/README.md b/README.md index 56ead34..c20bfda 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ version.dll是常用的插件名字,如果你使用了其他有名称冲突的 建议安装.net 8 sdk,方便使用最新的语法。 开发工具可以使用vscode, visual studio 或者 rider。 -示例工程可以参考CSharpModExample +Mod 模板可以参考[模板仓库](https://github.com/BlackMythWukongMods/B1.Mod.Template)的 Readme 进行安装使用 ### mod入口