From 517dea855c79cf014d7268a274a211d9cbc6733d Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Sat, 19 Oct 2024 19:28:33 +0900 Subject: [PATCH 01/12] add .idea to ignore folder --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) 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 From 16ecd97e38acc33dd9d548c9f8a9ca587ec12e0d Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Sat, 19 Oct 2024 19:29:02 +0900 Subject: [PATCH 02/12] remove CSharpExample because mod template moved to https://github.com/BlackMythWukongMods/B1.Mod.Template --- CSharpLoader.sln | 14 ------ CSharpModExample/CSharpExample.csproj | 64 ------------------------ CSharpModExample/MyUtils.cs | 72 --------------------------- CSharpModExample/Program.cs | 55 -------------------- CSharpModExample/README.md | 3 -- CSharpModExample/build.sh | 2 - CSharpModExample/obfuscar.xml | 8 --- 7 files changed, 218 deletions(-) delete mode 100644 CSharpModExample/CSharpExample.csproj delete mode 100644 CSharpModExample/MyUtils.cs delete mode 100644 CSharpModExample/Program.cs delete mode 100644 CSharpModExample/README.md delete mode 100644 CSharpModExample/build.sh delete mode 100644 CSharpModExample/obfuscar.xml diff --git a/CSharpLoader.sln b/CSharpLoader.sln index 9e18968..e881b59 100644 --- a/CSharpLoader.sln +++ b/CSharpLoader.sln @@ -9,8 +9,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpManager", "CSharpMana EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpModBase", "CSharpModBase\CSharpModBase.csproj", "{82BC94A3-CB1D-4A7C-9C0A-1860D8C57942}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpExample", "CSharpModExample\CSharpExample.csproj", "{541076F4-03E4-4C7E-B511-E5D548DD6707}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,18 +55,6 @@ Global {82BC94A3-CB1D-4A7C-9C0A-1860D8C57942}.Release|x64.Build.0 = Release|Any CPU {82BC94A3-CB1D-4A7C-9C0A-1860D8C57942}.Release|x86.ActiveCfg = Release|Any CPU {82BC94A3-CB1D-4A7C-9C0A-1860D8C57942}.Release|x86.Build.0 = Release|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|Any CPU.Build.0 = Debug|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|x64.ActiveCfg = Debug|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|x64.Build.0 = Debug|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|x86.ActiveCfg = Debug|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|x86.Build.0 = Debug|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|Any CPU.ActiveCfg = Release|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|Any CPU.Build.0 = Release|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|x64.ActiveCfg = Release|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|x64.Build.0 = Release|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|x86.ActiveCfg = Release|Any CPU - {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CSharpModExample/CSharpExample.csproj b/CSharpModExample/CSharpExample.csproj deleted file mode 100644 index e52ac7e..0000000 --- a/CSharpModExample/CSharpExample.csproj +++ /dev/null @@ -1,64 +0,0 @@ - - - - net472 - enable - True - latest - 0.0.1.0 - - - - - - - - - - - - - - ..\GameDll\BtlSvr.Main.dll - False - - - ..\GameDll\b1.Native.dll - False - - - ..\GameDll\b1.NativePlugins.dll - False - - - ..\GameDll\GSE.Core.dll - False - - - ..\GameDll\GSE.ProtobufDB.dll - False - - - ..\GameDll\Google.Protobuf.dll - False - - - ..\GameDll\Protobuf.RunTime.dll - False - - - ..\GameDll\UnrealEngine.Runtime.dll - False - - - ..\GameDll\UnrealEngine.dll - False - - - - diff --git a/CSharpModExample/MyUtils.cs b/CSharpModExample/MyUtils.cs deleted file mode 100644 index 7dc7e41..0000000 --- a/CSharpModExample/MyUtils.cs +++ /dev/null @@ -1,72 +0,0 @@ - -using b1; -using UnrealEngine.Engine; -using UnrealEngine.Runtime; - -namespace CSharpExample -{ - public static class MyUtils - { - private static UWorld? world; - - public static UWorld? GetWorld() - { - if (world == null) - { - UObjectRef uobjectRef = GCHelper.FindRef(FGlobals.GWorld); - world = uobjectRef?.Managed as UWorld; - } - return world; - } - - public static APawn GetControlledPawn() - { - return UGSE_EngineFuncLib.GetFirstLocalPlayerController(GetWorld()).GetControlledPawn(); - } - - public static BGUPlayerCharacterCS GetBGUPlayerCharacterCS() - { - return (GetControlledPawn() as BGUPlayerCharacterCS)!; - } - - public static BGP_PlayerControllerB1 GetPlayerController() - { - return (BGP_PlayerControllerB1)UGSE_EngineFuncLib.GetFirstLocalPlayerController(GetWorld()); - } - - public static BUS_GSEventCollection GetBUS_GSEventCollection() - { - return BUS_EventCollectionCS.Get(GetControlledPawn()); - } - - public static T LoadAsset(string asset) where T : UObject - { - return b1.BGW.BGW_PreloadAssetMgr.Get(GetWorld()).TryGetCachedResourceObj(asset, b1.BGW.ELoadResourceType.SyncLoadAndCache, b1.BGW.EAssetPriority.Default, null, -1, -1); - } - - public static UClass LoadClass(string asset) - { - return LoadAsset(asset); - } - - public static AActor? SpawnActor(string classAsset) - { - var controlledPawn = GetControlledPawn(); - FVector actorLocation = controlledPawn.GetActorLocation(); - FVector b = controlledPawn.GetActorForwardVector() * 1000.0f; - FVector start = actorLocation + b; - FRotator frotator = UMathLibrary.FindLookAtRotation(start, actorLocation); - UClass uClass = LoadClass($"PrefabricatorAsset'{classAsset}'"); - if (uClass == null) - { - return null; - } - return BGUFunctionLibraryCS.BGUSpawnActor(controlledPawn.World, uClass, start, frotator); - } - - public static AActor GetActorOfClass(string classAsset) - { - return UGameplayStatics.GetActorOfClass(GetWorld(), LoadAsset(classAsset)); - } - } -} diff --git a/CSharpModExample/Program.cs b/CSharpModExample/Program.cs deleted file mode 100644 index 90770ce..0000000 --- a/CSharpModExample/Program.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using b1; -using BtlShare; -using CSharpModBase; -using CSharpModBase.Input; -// using HarmonyLib; - -namespace CSharpExample -{ - public class MyMod : ICSharpMod - { - public string Name => "ModExample"; - public string Version => "0.0.1"; - // private readonly Harmony harmony; - - public MyMod() - { - // harmony = new Harmony(Name); - // Harmony.DEBUG = true; - } - - public void Init() - { - Console.WriteLine($"{Name} Init"); - Utils.RegisterKeyBind(Key.ENTER, () => Console.WriteLine("Enter pressed")); - Utils.RegisterKeyBind(ModifierKeys.Control, Key.ENTER, FindPlayer); - - // hook - // harmony.PatchAll(); - } - - public void DeInit() - { - Console.WriteLine($"{Name} DeInit"); - // harmony.UnpatchAll(); - } - - private void FindPlayer() - { - Console.WriteLine("Ctrl+Enter pressed"); - var player = MyUtils.GetControlledPawn(); - if (player == null) - { - Console.WriteLine("Player not found"); - } - else - { - Console.WriteLine($"Player found: {player}"); - float hp = BGUFunctionLibraryCS.GetAttrValue(player, EBGUAttrFloat.Hp); - float hpMax = BGUFunctionLibraryCS.GetAttrValue(player, EBGUAttrFloat.HpMax); - Console.WriteLine($"HP: {hp}/{hpMax}"); - } - } - } -} diff --git a/CSharpModExample/README.md b/CSharpModExample/README.md deleted file mode 100644 index 1882d07..0000000 --- a/CSharpModExample/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# 编译 - -dotnet build diff --git a/CSharpModExample/build.sh b/CSharpModExample/build.sh deleted file mode 100644 index 2728920..0000000 --- a/CSharpModExample/build.sh +++ /dev/null @@ -1,2 +0,0 @@ -dotnet build -cp bin/Debug/net472/CSharpExample.dll C:/Users/An/Soft/Steam/steamapps/common/BlackMythWukong/b1/Binaries/Win64/CSharpLoader/Mods \ No newline at end of file diff --git a/CSharpModExample/obfuscar.xml b/CSharpModExample/obfuscar.xml deleted file mode 100644 index 89a70df..0000000 --- a/CSharpModExample/obfuscar.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - From 192cfa61a878bb04d3942b313cf8bc8cf2ec57f3 Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Sat, 19 Oct 2024 19:41:48 +0900 Subject: [PATCH 03/12] enable implicit using, move utils to its own folder, extract some classes out from one file, some format changes and syntax sugars --- CSharpModBase/CSharpModBase.cs | 54 +++-- CSharpModBase/CSharpModBase.csproj | 41 ++-- CSharpModBase/Input/GamePad.cs | 86 +++----- CSharpModBase/Input/HotKeyData.cs | 62 ++++++ CSharpModBase/Input/HotKeyItem.cs | 128 +++--------- CSharpModBase/Input/IInputManager.cs | 15 +- CSharpModBase/Input/Key.cs | 289 +++++++++++++-------------- CSharpModBase/Input/KeyUtils.cs | 89 --------- CSharpModBase/Input/ModifierKeys.cs | 21 +- CSharpModBase/Log.cs | 114 +++++------ CSharpModBase/Utils.cs | 58 ------ CSharpModBase/Utils/GamePadUtils.cs | 32 +++ CSharpModBase/Utils/InputUtils.cs | 47 +++++ CSharpModBase/Utils/KeyUtils.cs | 104 ++++++++++ 14 files changed, 564 insertions(+), 576 deletions(-) create mode 100644 CSharpModBase/Input/HotKeyData.cs delete mode 100644 CSharpModBase/Input/KeyUtils.cs delete mode 100644 CSharpModBase/Utils.cs create mode 100644 CSharpModBase/Utils/GamePadUtils.cs create mode 100644 CSharpModBase/Utils/InputUtils.cs create mode 100644 CSharpModBase/Utils/KeyUtils.cs diff --git a/CSharpModBase/CSharpModBase.cs b/CSharpModBase/CSharpModBase.cs index 5f5b904..47ddfc9 100644 --- a/CSharpModBase/CSharpModBase.cs +++ b/CSharpModBase/CSharpModBase.cs @@ -1,33 +1,31 @@ -namespace CSharpModBase +namespace CSharpModBase; + +public static class Common { - public static class Common - { - public const string LoaderDir = "CSharpLoader"; - public const string ModDir = "CSharpLoader\\Mods"; - public const string DataDir = "CSharpLoader\\Data"; - } + public const string LoaderDir = "CSharpLoader"; + public const string ModDir = @"CSharpLoader\Mods"; + public const string DataDir = @"CSharpLoader\Data"; +} +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/Input/GamePad.cs b/CSharpModBase/Input/GamePad.cs index b97af16..519e8cd 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.DPadDown, - 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.DPadDown, + 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 GamePadButtonEventArgs : EventArgs +{ + public GamePadButton Button { get; set; } } + +public delegate void GamePadButtonEventHandler(GamePadButtonEventArgs e); \ No newline at end of file diff --git a/CSharpModBase/Input/HotKeyData.cs b/CSharpModBase/Input/HotKeyData.cs new file mode 100644 index 0000000..9cdb04c --- /dev/null +++ b/CSharpModBase/Input/HotKeyData.cs @@ -0,0 +1,62 @@ +using CSharpModBase.Utils; + +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 deleted file mode 100644 index 1f2618b..0000000 --- a/CSharpModBase/Input/KeyUtils.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System.Collections.Generic; -using System.Runtime.InteropServices; - -namespace CSharpModBase.Input -{ - public static class KeyUtils - { - /// - /// Keys转字符串,支持组合键 - /// - /// - /// - public static string KeyToString(ModifierKeys modifiers, Key key, List buf) - { - 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(), - }; - } - if (keyCodeStr != null) - { - buf.Add(keyCodeStr); - } - return string.Join("+", buf); - } - - public static string KeyToString(ModifierKeys modifiers, Key key) - { - return KeyToString(modifiers, key, new()); - } - - 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) - { - return GetKeyState((uint)key) < 0; - } - - public static ModifierKeys Modifiers - { - get - { - 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; - } - } - } -} 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 deleted file mode 100644 index 5901f8b..0000000 --- a/CSharpModBase/Utils.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using CSharpModBase.Input; -using UnrealEngine.Runtime; - -namespace CSharpModBase -{ - public static class Utils - { - private static IInputManager? InputManager; - - public static void InitInputManager(IInputManager inputManager) - { - InputManager = inputManager; - } - - public static HotKeyItem RegisterKeyBind(Key key, Action action) - { - return InputManager!.RegisterKeyBind(key, action); - } - - public static HotKeyItem RegisterKeyBind(ModifierKeys modifiers, Key key, Action action) - { - return InputManager!.RegisterKeyBind(modifiers, key, action); - } - - public static HotKeyItem RegisterGamePadBind(GamePadButton button, Action action) - { - return InputManager!.RegisterGamePadBind(button, action); - } - - public static void TryRun(Action aciton) - { - try - { - aciton(); - } - catch (Exception e) - { - Log.Error(e); - }; - } - - public static void TryRunOnGameThread(Action aciton) - { - FThreading.RunOnGameThread(() => - { - try - { - aciton(); - } - catch (Exception e) - { - Log.Error(e); - } - }); - } - } -} diff --git a/CSharpModBase/Utils/GamePadUtils.cs b/CSharpModBase/Utils/GamePadUtils.cs new file mode 100644 index 0000000..4dc389d --- /dev/null +++ b/CSharpModBase/Utils/GamePadUtils.cs @@ -0,0 +1,32 @@ +using CSharpModBase.Input; +using SharpDX.XInput; + +namespace CSharpModBase.Utils; + +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/Utils/InputUtils.cs b/CSharpModBase/Utils/InputUtils.cs new file mode 100644 index 0000000..b6253f4 --- /dev/null +++ b/CSharpModBase/Utils/InputUtils.cs @@ -0,0 +1,47 @@ +using CSharpModBase.Input; +using UnrealEngine.Runtime; + +namespace CSharpModBase.Utils; + +public static class InputUtils +{ + private static IInputManager? _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(ModifierKeys modifiers, Key key, Action action) => _inputManager!.RegisterKeyBind(modifiers, key, action); + + public static HotKeyItem RegisterGamePadBind(GamePadButton button, Action action) => _inputManager!.RegisterGamePadBind(button, action); + + public static void TryRun(Action action) + { + try + { + action(); + } + catch (Exception e) + { + Log.Error(e); + } + } + + public static void TryRunOnGameThread(Action action) + { + FThreading.RunOnGameThread(() => + { + try + { + action(); + } + catch (Exception e) + { + Log.Error(e); + } + }); + } +} \ No newline at end of file diff --git a/CSharpModBase/Utils/KeyUtils.cs b/CSharpModBase/Utils/KeyUtils.cs new file mode 100644 index 0000000..bcee644 --- /dev/null +++ b/CSharpModBase/Utils/KeyUtils.cs @@ -0,0 +1,104 @@ +using System.Runtime.InteropServices; +using CSharpModBase.Input; + +namespace CSharpModBase.Utils; + +public static class KeyUtils +{ + public static ModifierKeys Modifiers + { + get + { + var 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; + } + } + + /// + /// Keys转字符串,支持组合键 + /// + /// + /// + /// + /// + public static string KeyToString(ModifierKeys modifiers, Key key, List buf) + { + 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; + var oemKeyChar = OemKeyChar(key); + if (oemKeyChar != default) + { + keyCodeStr = oemKeyChar.ToString(); + } + else + { + keyCodeStr = key switch + { + 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 From 733e4e96bdc6a3b66a78819e69070be727ca2343 Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Sat, 19 Oct 2024 19:48:46 +0900 Subject: [PATCH 04/12] enable implicit usings, use syntax sugar, code cleanup --- CSharpManager/CSharpManager.csproj | 35 ++-- CSharpManager/CSharpModManager.cs | 262 ++++++++++++++-------------- CSharpManager/Ini.cs | 128 +++++++------- CSharpManager/InputManager.cs | 264 +++++++++++++++-------------- CSharpManager/Program.cs | 18 +- CSharpManager/README.md | 1 + CSharpManager/b1cs.ini | 6 +- 7 files changed, 366 insertions(+), 348 deletions(-) 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..b5eb3fa 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 CSharpModBase.Utils; using Mono.Cecil; -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() + { + InputUtils.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}"); + } + + 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(Common.ModDir, LoadingModName, dllName)) ?? + TryLoadDll(Path.Combine(Common.ModDir, "Common", dllName)) ?? + TryLoadDll(Path.Combine(Common.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(Common.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 {Common.ModDir} not exists"); + return; } - public void LoadMods() + string[] dirs = Directory.GetDirectories(Common.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..2abb831 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; + this._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..dcae22e 100644 --- a/CSharpManager/InputManager.cs +++ b/CSharpManager/InputManager.cs @@ -1,177 +1,181 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; -using System.Threading; using CSharpModBase; using CSharpModBase.Input; +using CSharpModBase.Utils; -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; + InputUtils.TryRunOnGameThread(item.Action); + } + else + { + InputUtils.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 From a050f11f7404b706765f77830d46368dd2845f85 Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Sat, 19 Oct 2024 23:18:53 +0900 Subject: [PATCH 05/12] move common dirs into another file --- CSharpModBase/CSharpModBase.cs | 7 ------- CSharpModBase/CommonDirs.cs | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-) create mode 100644 CSharpModBase/CommonDirs.cs diff --git a/CSharpModBase/CSharpModBase.cs b/CSharpModBase/CSharpModBase.cs index 47ddfc9..0dce7c7 100644 --- a/CSharpModBase/CSharpModBase.cs +++ b/CSharpModBase/CSharpModBase.cs @@ -1,12 +1,5 @@ namespace CSharpModBase; -public static class Common -{ - public const string LoaderDir = "CSharpLoader"; - public const string ModDir = @"CSharpLoader\Mods"; - public const string DataDir = @"CSharpLoader\Data"; -} - public interface ICSharpMod { /// diff --git a/CSharpModBase/CommonDirs.cs b/CSharpModBase/CommonDirs.cs new file mode 100644 index 0000000..0beda20 --- /dev/null +++ b/CSharpModBase/CommonDirs.cs @@ -0,0 +1,8 @@ +namespace CSharpModBase; + +public static class CommonDirs +{ + public const string LoaderDir = "CSharpLoader"; + public const string ModDir = @"CSharpLoader\Mods"; + public const string DataDir = @"CSharpLoader\Data"; +} \ No newline at end of file From f4a84d3f5081383e5b7a72b46416283e3dbc9839 Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Mon, 21 Oct 2024 19:38:24 +0900 Subject: [PATCH 06/12] fix rename common to common dirs causes error --- CSharpManager/CSharpModManager.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/CSharpManager/CSharpModManager.cs b/CSharpManager/CSharpModManager.cs index b5eb3fa..1b8fd03 100644 --- a/CSharpManager/CSharpModManager.cs +++ b/CSharpManager/CSharpModManager.cs @@ -3,6 +3,7 @@ using CSharpModBase.Input; using CSharpModBase.Utils; using Mono.Cecil; +using static CSharpModBase.CommonDirs; namespace CSharpManager; @@ -28,7 +29,7 @@ public CSharpModManager() { InputUtils.InitInputManager(InputManager); // load config from ini - Ini iniFile = new(Path.Combine(Common.LoaderDir, "b1cs.ini")); + Ini iniFile = new(Path.Combine(LoaderDir, "b1cs.ini")); Develop = iniFile.GetValue("Develop", "Settings", "1").Trim() == "1"; Log.Debug($"Develop: {Develop}"); } @@ -53,9 +54,9 @@ public CSharpModManager() } var 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 TryLoadDll(Path.Combine(ModDir, LoadingModName, dllName)) ?? + TryLoadDll(Path.Combine(ModDir, "CommonDirs", dllName)) ?? + TryLoadDll(Path.Combine(LoaderDir, dllName)); } catch (Exception e) { @@ -81,13 +82,13 @@ private static void OnUnobservedTaskException(object sender, UnobservedTaskExcep public void LoadMods() { LoadedMods.Clear(); - if (!Directory.Exists(Common.ModDir)) + if (!Directory.Exists(ModDir)) { - Log.Error($"Mod dir {Common.ModDir} not exists"); + Log.Error($"Mod dir {ModDir} not exists"); return; } - string[] dirs = Directory.GetDirectories(Common.ModDir); + string[] dirs = Directory.GetDirectories(ModDir); var ICSharpModType = typeof(ICSharpMod); foreach (var dir in dirs) { From ae82090ae9dbe8e6620be4d8d26874ed517f1d66 Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Mon, 21 Oct 2024 21:45:42 +0900 Subject: [PATCH 07/12] revert some breaking changes in CsharpModBase --- CSharpModBase/{CommonDirs.cs => Common.cs} | 2 +- CSharpModBase/Input/GamePad.cs | 4 ++-- CSharpModBase/{Utils => Input}/GamePadUtils.cs | 3 +-- CSharpModBase/Input/HotKeyData.cs | 2 -- CSharpModBase/{Utils => Input}/KeyUtils.cs | 3 +-- CSharpModBase/{Utils/InputUtils.cs => Utils.cs} | 4 ++-- 6 files changed, 7 insertions(+), 11 deletions(-) rename CSharpModBase/{CommonDirs.cs => Common.cs} (86%) rename CSharpModBase/{Utils => Input}/GamePadUtils.cs (92%) rename CSharpModBase/{Utils => Input}/KeyUtils.cs (97%) rename CSharpModBase/{Utils/InputUtils.cs => Utils.cs} (94%) diff --git a/CSharpModBase/CommonDirs.cs b/CSharpModBase/Common.cs similarity index 86% rename from CSharpModBase/CommonDirs.cs rename to CSharpModBase/Common.cs index 0beda20..b1be0f3 100644 --- a/CSharpModBase/CommonDirs.cs +++ b/CSharpModBase/Common.cs @@ -1,6 +1,6 @@ namespace CSharpModBase; -public static class CommonDirs +public static class Common { public const string LoaderDir = "CSharpLoader"; public const string ModDir = @"CSharpLoader\Mods"; diff --git a/CSharpModBase/Input/GamePad.cs b/CSharpModBase/Input/GamePad.cs index 519e8cd..dd1195f 100644 --- a/CSharpModBase/Input/GamePad.cs +++ b/CSharpModBase/Input/GamePad.cs @@ -28,9 +28,9 @@ public enum GamePadButton DPadLeftUp = DPadLeft | DPadUp } -public sealed class GamePadButtonEventArgs : EventArgs +public sealed class GamePadButtonEvent : EventArgs { public GamePadButton Button { get; set; } } -public delegate void GamePadButtonEventHandler(GamePadButtonEventArgs e); \ No newline at end of file +public delegate void GamePadButtonEventHandler(GamePadButtonEvent e); \ No newline at end of file diff --git a/CSharpModBase/Utils/GamePadUtils.cs b/CSharpModBase/Input/GamePadUtils.cs similarity index 92% rename from CSharpModBase/Utils/GamePadUtils.cs rename to CSharpModBase/Input/GamePadUtils.cs index 4dc389d..3fe6eed 100644 --- a/CSharpModBase/Utils/GamePadUtils.cs +++ b/CSharpModBase/Input/GamePadUtils.cs @@ -1,7 +1,6 @@ -using CSharpModBase.Input; using SharpDX.XInput; -namespace CSharpModBase.Utils; +namespace CSharpModBase.Input; public static class GamePadUtils { diff --git a/CSharpModBase/Input/HotKeyData.cs b/CSharpModBase/Input/HotKeyData.cs index 9cdb04c..8883578 100644 --- a/CSharpModBase/Input/HotKeyData.cs +++ b/CSharpModBase/Input/HotKeyData.cs @@ -1,5 +1,3 @@ -using CSharpModBase.Utils; - namespace CSharpModBase.Input; public class HotKeyData diff --git a/CSharpModBase/Utils/KeyUtils.cs b/CSharpModBase/Input/KeyUtils.cs similarity index 97% rename from CSharpModBase/Utils/KeyUtils.cs rename to CSharpModBase/Input/KeyUtils.cs index bcee644..3bdcf36 100644 --- a/CSharpModBase/Utils/KeyUtils.cs +++ b/CSharpModBase/Input/KeyUtils.cs @@ -1,7 +1,6 @@ using System.Runtime.InteropServices; -using CSharpModBase.Input; -namespace CSharpModBase.Utils; +namespace CSharpModBase.Input; public static class KeyUtils { diff --git a/CSharpModBase/Utils/InputUtils.cs b/CSharpModBase/Utils.cs similarity index 94% rename from CSharpModBase/Utils/InputUtils.cs rename to CSharpModBase/Utils.cs index b6253f4..47d2d4d 100644 --- a/CSharpModBase/Utils/InputUtils.cs +++ b/CSharpModBase/Utils.cs @@ -1,9 +1,9 @@ using CSharpModBase.Input; using UnrealEngine.Runtime; -namespace CSharpModBase.Utils; +namespace CSharpModBase; -public static class InputUtils +public static class Utils { private static IInputManager? _inputManager; From 9161461b1c29cda7095178644b4902649a192306 Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Mon, 21 Oct 2024 21:48:24 +0900 Subject: [PATCH 08/12] revert some breaking changes in CSharpManager --- CSharpManager/CSharpModManager.cs | 5 ++--- CSharpManager/Ini.cs | 2 +- CSharpManager/InputManager.cs | 5 ++--- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/CSharpManager/CSharpModManager.cs b/CSharpManager/CSharpModManager.cs index 1b8fd03..56ea48f 100644 --- a/CSharpManager/CSharpModManager.cs +++ b/CSharpManager/CSharpModManager.cs @@ -1,9 +1,8 @@ using System.Reflection; using CSharpModBase; using CSharpModBase.Input; -using CSharpModBase.Utils; using Mono.Cecil; -using static CSharpModBase.CommonDirs; +using static CSharpModBase.Common; namespace CSharpManager; @@ -27,7 +26,7 @@ static CSharpModManager() public CSharpModManager() { - InputUtils.InitInputManager(InputManager); + Utils.InitInputManager(InputManager); // load config from ini Ini iniFile = new(Path.Combine(LoaderDir, "b1cs.ini")); Develop = iniFile.GetValue("Develop", "Settings", "1").Trim() == "1"; diff --git a/CSharpManager/Ini.cs b/CSharpManager/Ini.cs index 2abb831..d342f20 100644 --- a/CSharpManager/Ini.cs +++ b/CSharpManager/Ini.cs @@ -14,7 +14,7 @@ public class Ini /// 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)) { diff --git a/CSharpManager/InputManager.cs b/CSharpManager/InputManager.cs index dcae22e..d8846e4 100644 --- a/CSharpManager/InputManager.cs +++ b/CSharpManager/InputManager.cs @@ -2,7 +2,6 @@ using System.Text; using CSharpModBase; using CSharpModBase.Input; -using CSharpModBase.Utils; namespace CSharpManager; @@ -76,11 +75,11 @@ private void HandleKeys(List items) item.IsPressed = true; if (item.RunOnGameThread) { - InputUtils.TryRunOnGameThread(item.Action); + Utils.TryRunOnGameThread(item.Action); } else { - InputUtils.TryRun(item.Action); + Utils.TryRun(item.Action); } } else if (item.IsPressed) From ec23f75719fd2a9e021c9801840738115abf82cc Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Mon, 21 Oct 2024 21:52:35 +0900 Subject: [PATCH 09/12] update README.md --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 56ead34..b160641 100644 --- a/README.md +++ b/README.md @@ -51,8 +51,6 @@ version.dll是常用的插件名字,如果你使用了其他有名称冲突的 - C# mod管理器,加载和管理C# mod - CSharpModBase - 提供给mod使用的接口 -- CSharpModExample - - mod示例 - GameDll - 游戏内的C# dll,写mod代码需要引用这些dll @@ -60,7 +58,7 @@ version.dll是常用的插件名字,如果你使用了其他有名称冲突的 建议安装.net 8 sdk,方便使用最新的语法。 开发工具可以使用vscode, visual studio 或者 rider。 -示例工程可以参考CSharpModExample +Mod 模板可以参考[模板仓库](https://github.com/BlackMythWukongMods/B1.Mod.Template)的 Readme 进行安装使用 ### mod入口 From a5cd8108254f4fe2767bbcff6f7c68f8d678cda5 Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Mon, 21 Oct 2024 21:54:47 +0900 Subject: [PATCH 10/12] Revert "remove CSharpExample because mod template moved to https://github.com/BlackMythWukongMods/B1.Mod.Template" This reverts commit 16ecd97e38acc33dd9d548c9f8a9ca587ec12e0d. --- CSharpLoader.sln | 14 ++++++ CSharpModExample/CSharpExample.csproj | 64 ++++++++++++++++++++++++ CSharpModExample/MyUtils.cs | 72 +++++++++++++++++++++++++++ CSharpModExample/Program.cs | 55 ++++++++++++++++++++ CSharpModExample/README.md | 3 ++ CSharpModExample/build.sh | 2 + CSharpModExample/obfuscar.xml | 8 +++ 7 files changed, 218 insertions(+) create mode 100644 CSharpModExample/CSharpExample.csproj create mode 100644 CSharpModExample/MyUtils.cs create mode 100644 CSharpModExample/Program.cs create mode 100644 CSharpModExample/README.md create mode 100644 CSharpModExample/build.sh create mode 100644 CSharpModExample/obfuscar.xml diff --git a/CSharpLoader.sln b/CSharpLoader.sln index e881b59..9e18968 100644 --- a/CSharpLoader.sln +++ b/CSharpLoader.sln @@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpManager", "CSharpMana EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpModBase", "CSharpModBase\CSharpModBase.csproj", "{82BC94A3-CB1D-4A7C-9C0A-1860D8C57942}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CSharpExample", "CSharpModExample\CSharpExample.csproj", "{541076F4-03E4-4C7E-B511-E5D548DD6707}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -55,6 +57,18 @@ Global {82BC94A3-CB1D-4A7C-9C0A-1860D8C57942}.Release|x64.Build.0 = Release|Any CPU {82BC94A3-CB1D-4A7C-9C0A-1860D8C57942}.Release|x86.ActiveCfg = Release|Any CPU {82BC94A3-CB1D-4A7C-9C0A-1860D8C57942}.Release|x86.Build.0 = Release|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|Any CPU.Build.0 = Debug|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|x64.ActiveCfg = Debug|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|x64.Build.0 = Debug|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|x86.ActiveCfg = Debug|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Debug|x86.Build.0 = Debug|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|Any CPU.ActiveCfg = Release|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|Any CPU.Build.0 = Release|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|x64.ActiveCfg = Release|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|x64.Build.0 = Release|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|x86.ActiveCfg = Release|Any CPU + {541076F4-03E4-4C7E-B511-E5D548DD6707}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/CSharpModExample/CSharpExample.csproj b/CSharpModExample/CSharpExample.csproj new file mode 100644 index 0000000..e52ac7e --- /dev/null +++ b/CSharpModExample/CSharpExample.csproj @@ -0,0 +1,64 @@ + + + + net472 + enable + True + latest + 0.0.1.0 + + + + + + + + + + + + + + ..\GameDll\BtlSvr.Main.dll + False + + + ..\GameDll\b1.Native.dll + False + + + ..\GameDll\b1.NativePlugins.dll + False + + + ..\GameDll\GSE.Core.dll + False + + + ..\GameDll\GSE.ProtobufDB.dll + False + + + ..\GameDll\Google.Protobuf.dll + False + + + ..\GameDll\Protobuf.RunTime.dll + False + + + ..\GameDll\UnrealEngine.Runtime.dll + False + + + ..\GameDll\UnrealEngine.dll + False + + + + diff --git a/CSharpModExample/MyUtils.cs b/CSharpModExample/MyUtils.cs new file mode 100644 index 0000000..7dc7e41 --- /dev/null +++ b/CSharpModExample/MyUtils.cs @@ -0,0 +1,72 @@ + +using b1; +using UnrealEngine.Engine; +using UnrealEngine.Runtime; + +namespace CSharpExample +{ + public static class MyUtils + { + private static UWorld? world; + + public static UWorld? GetWorld() + { + if (world == null) + { + UObjectRef uobjectRef = GCHelper.FindRef(FGlobals.GWorld); + world = uobjectRef?.Managed as UWorld; + } + return world; + } + + public static APawn GetControlledPawn() + { + return UGSE_EngineFuncLib.GetFirstLocalPlayerController(GetWorld()).GetControlledPawn(); + } + + public static BGUPlayerCharacterCS GetBGUPlayerCharacterCS() + { + return (GetControlledPawn() as BGUPlayerCharacterCS)!; + } + + public static BGP_PlayerControllerB1 GetPlayerController() + { + return (BGP_PlayerControllerB1)UGSE_EngineFuncLib.GetFirstLocalPlayerController(GetWorld()); + } + + public static BUS_GSEventCollection GetBUS_GSEventCollection() + { + return BUS_EventCollectionCS.Get(GetControlledPawn()); + } + + public static T LoadAsset(string asset) where T : UObject + { + return b1.BGW.BGW_PreloadAssetMgr.Get(GetWorld()).TryGetCachedResourceObj(asset, b1.BGW.ELoadResourceType.SyncLoadAndCache, b1.BGW.EAssetPriority.Default, null, -1, -1); + } + + public static UClass LoadClass(string asset) + { + return LoadAsset(asset); + } + + public static AActor? SpawnActor(string classAsset) + { + var controlledPawn = GetControlledPawn(); + FVector actorLocation = controlledPawn.GetActorLocation(); + FVector b = controlledPawn.GetActorForwardVector() * 1000.0f; + FVector start = actorLocation + b; + FRotator frotator = UMathLibrary.FindLookAtRotation(start, actorLocation); + UClass uClass = LoadClass($"PrefabricatorAsset'{classAsset}'"); + if (uClass == null) + { + return null; + } + return BGUFunctionLibraryCS.BGUSpawnActor(controlledPawn.World, uClass, start, frotator); + } + + public static AActor GetActorOfClass(string classAsset) + { + return UGameplayStatics.GetActorOfClass(GetWorld(), LoadAsset(classAsset)); + } + } +} diff --git a/CSharpModExample/Program.cs b/CSharpModExample/Program.cs new file mode 100644 index 0000000..90770ce --- /dev/null +++ b/CSharpModExample/Program.cs @@ -0,0 +1,55 @@ +using System; +using b1; +using BtlShare; +using CSharpModBase; +using CSharpModBase.Input; +// using HarmonyLib; + +namespace CSharpExample +{ + public class MyMod : ICSharpMod + { + public string Name => "ModExample"; + public string Version => "0.0.1"; + // private readonly Harmony harmony; + + public MyMod() + { + // harmony = new Harmony(Name); + // Harmony.DEBUG = true; + } + + public void Init() + { + Console.WriteLine($"{Name} Init"); + Utils.RegisterKeyBind(Key.ENTER, () => Console.WriteLine("Enter pressed")); + Utils.RegisterKeyBind(ModifierKeys.Control, Key.ENTER, FindPlayer); + + // hook + // harmony.PatchAll(); + } + + public void DeInit() + { + Console.WriteLine($"{Name} DeInit"); + // harmony.UnpatchAll(); + } + + private void FindPlayer() + { + Console.WriteLine("Ctrl+Enter pressed"); + var player = MyUtils.GetControlledPawn(); + if (player == null) + { + Console.WriteLine("Player not found"); + } + else + { + Console.WriteLine($"Player found: {player}"); + float hp = BGUFunctionLibraryCS.GetAttrValue(player, EBGUAttrFloat.Hp); + float hpMax = BGUFunctionLibraryCS.GetAttrValue(player, EBGUAttrFloat.HpMax); + Console.WriteLine($"HP: {hp}/{hpMax}"); + } + } + } +} diff --git a/CSharpModExample/README.md b/CSharpModExample/README.md new file mode 100644 index 0000000..1882d07 --- /dev/null +++ b/CSharpModExample/README.md @@ -0,0 +1,3 @@ +# 编译 + +dotnet build diff --git a/CSharpModExample/build.sh b/CSharpModExample/build.sh new file mode 100644 index 0000000..2728920 --- /dev/null +++ b/CSharpModExample/build.sh @@ -0,0 +1,2 @@ +dotnet build +cp bin/Debug/net472/CSharpExample.dll C:/Users/An/Soft/Steam/steamapps/common/BlackMythWukong/b1/Binaries/Win64/CSharpLoader/Mods \ No newline at end of file diff --git a/CSharpModExample/obfuscar.xml b/CSharpModExample/obfuscar.xml new file mode 100644 index 0000000..89a70df --- /dev/null +++ b/CSharpModExample/obfuscar.xml @@ -0,0 +1,8 @@ + + + + + + + + From 3c1fd41c0f9bc654c3f359d9fc7b37ee72c8c06a Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Mon, 21 Oct 2024 21:55:00 +0900 Subject: [PATCH 11/12] update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index b160641..c20bfda 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ version.dll是常用的插件名字,如果你使用了其他有名称冲突的 - C# mod管理器,加载和管理C# mod - CSharpModBase - 提供给mod使用的接口 +- CSharpModExample + - mod示例 - GameDll - 游戏内的C# dll,写mod代码需要引用这些dll From 3bd43acb1dc4f33f0afab08f4b18a62745517872 Mon Sep 17 00:00:00 2001 From: lxymahatma Date: Mon, 21 Oct 2024 21:59:36 +0900 Subject: [PATCH 12/12] Update README.en.md --- README.en.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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