From 96cb8bb9f00c291e1477f2bc751be8d2ccfe3a02 Mon Sep 17 00:00:00 2001 From: skuzzis Date: Thu, 2 Oct 2025 17:18:25 +0300 Subject: [PATCH 1/4] fix(managed): Logger --- managed/src/SwiftlyS2.Core/Misc/SwiftlyLogger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/managed/src/SwiftlyS2.Core/Misc/SwiftlyLogger.cs b/managed/src/SwiftlyS2.Core/Misc/SwiftlyLogger.cs index 71dedf2ca..d3e4ae7c8 100644 --- a/managed/src/SwiftlyS2.Core/Misc/SwiftlyLogger.cs +++ b/managed/src/SwiftlyS2.Core/Misc/SwiftlyLogger.cs @@ -52,7 +52,7 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except var id = $"[{eventId.ToString()}]"; var color = GetLogLevelColor(logLevel); - AnsiConsole.MarkupLineInterpolated($"[lightsteelblue1 bold]{_contextName}[/] [lightsteelblue]|[/] [grey42]{timestamp}[/] [lightsteelblue]|[/] [{color}]{level}[/] [lightsteelblue]|[/] [lightsteelblue]{_categoryName}{id}[/][default]"); + AnsiConsole.MarkupLineInterpolated($"[lightsteelblue1 bold]{_contextName}[/] [lightsteelblue]|[/] [grey42]{timestamp}[/] [lightsteelblue]|[/] [{color}]{level}[/] [lightsteelblue]|[/] [lightsteelblue]{_categoryName}{id}[/]"); string? message = formatter != null ? formatter(state, exception) : state?.ToString(); if (!string.IsNullOrEmpty(message)) From 7dcc62c23c90cdeb7e877933b38887a1dbc78acf Mon Sep 17 00:00:00 2001 From: samyyc Date: Fri, 3 Oct 2025 00:27:34 +0800 Subject: [PATCH 2/4] fix(managed): Fix netmessage callback --- .../SwiftlyS2.CS2.PluginTemplate.0.0.6.nupkg | Bin 0 -> 52648 bytes .../NetMessages/NetMessageHookCallback.cs | 21 +++--- managed/test/README.md | 36 ++++++++++ managed/test/examples/Commands.example.cs | 24 +++++++ managed/test/examples/Events.example.cs | 34 +++++++++ managed/test/examples/GameEvents.example.cs | 43 +++++++++++ .../HookAndCallNativeFunctions.example.cs | 68 ++++++++++++++++++ managed/test/examples/NetMessage.example.cs | 55 ++++++++++++++ managed/test/examples/README.md | 3 + managed/test/examples/SoundEvent.example.cs | 41 +++++++++++ managed/test/manifest.json | 9 +++ managed/test/src/test.cs | 24 +++++++ managed/test/test.csproj | 38 ++++++++++ 13 files changed, 386 insertions(+), 10 deletions(-) create mode 100644 managed/SwiftlyS2.PluginTemplate/nupkgs/SwiftlyS2.CS2.PluginTemplate.0.0.6.nupkg create mode 100644 managed/test/README.md create mode 100644 managed/test/examples/Commands.example.cs create mode 100644 managed/test/examples/Events.example.cs create mode 100644 managed/test/examples/GameEvents.example.cs create mode 100644 managed/test/examples/HookAndCallNativeFunctions.example.cs create mode 100644 managed/test/examples/NetMessage.example.cs create mode 100644 managed/test/examples/README.md create mode 100644 managed/test/examples/SoundEvent.example.cs create mode 100644 managed/test/manifest.json create mode 100644 managed/test/src/test.cs create mode 100644 managed/test/test.csproj diff --git a/managed/SwiftlyS2.PluginTemplate/nupkgs/SwiftlyS2.CS2.PluginTemplate.0.0.6.nupkg b/managed/SwiftlyS2.PluginTemplate/nupkgs/SwiftlyS2.CS2.PluginTemplate.0.0.6.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..dd076d37aea99cd2153982259d4a45590d6dae0c GIT binary patch literal 52648 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 L0`eaC>(l=MmjmEG literal 0 HcmV?d00001 diff --git a/managed/src/SwiftlyS2.Core/Modules/NetMessages/NetMessageHookCallback.cs b/managed/src/SwiftlyS2.Core/Modules/NetMessages/NetMessageHookCallback.cs index 9fd9c326a..2e4ec2e43 100644 --- a/managed/src/SwiftlyS2.Core/Modules/NetMessages/NetMessageHookCallback.cs +++ b/managed/src/SwiftlyS2.Core/Modules/NetMessages/NetMessageHookCallback.cs @@ -7,15 +7,16 @@ using SwiftlyS2.Shared.ProtobufDefinitions; using SwiftlyS2.Shared.Profiler; using System.Diagnostics.CodeAnalysis; +using SwiftlyS2.Shared.Misc; namespace SwiftlyS2.Core.NetMessages; [UnmanagedFunctionPointer(CallingConvention.Cdecl)] -internal delegate bool NetMessageClientHookCallbackDelegate(int playerId, int msgId, nint pMessage); +internal delegate HookResult NetMessageClientHookCallbackDelegate(int playerId, int msgId, nint pMessage); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] -internal delegate bool NetMessageServerHookCallbackDelegate(nint pPlayerMask, int msgId, nint pMessage); +internal delegate HookResult NetMessageServerHookCallbackDelegate(nint pPlayerMask, int msgId, nint pMessage); internal abstract class NetMessageHookCallback : IDisposable { @@ -53,16 +54,16 @@ public NetMessageClientHookCallback(INetMessageService.ClientNetMessageHandler { try { - if (msgId != T.MessageId) return true; + if (msgId != T.MessageId) return HookResult.Continue; var category = "NetMessageClientHookCallback::" + typeof(T).Name; Profiler.StartRecording(category); var msg = T.Wrap(pMessage, false); - _callback(msg, playerId); + var result = _callback(msg, playerId); Profiler.StopRecording(category); - return true; + return result; } catch (Exception e) { _logger.LogError(e, "Error in net message client hook callback for {MessageType}", typeof(T).Name); - return false; + return HookResult.Continue; } }; _unmanagedCallbackPtr = Marshal.GetFunctionPointerForDelegate(_unmanagedCallback); @@ -93,19 +94,19 @@ public NetMessageServerHookCallback(INetMessageService.ServerNetMessageHandler { try { - if (msgId != T.MessageId) return true; + if (msgId != T.MessageId) return HookResult.Continue; var category = "NetMessageServerHookCallback::" + typeof(T).Name; Profiler.StartRecording(category); var msg = T.Wrap(pMessage, false); var mask = pPlayerMask.Read(); msg.Recipients.RecipientsMask = mask; - _callback(msg); + var result = _callback(msg); pPlayerMask.Write(msg.Recipients.ToMask()); Profiler.StopRecording(category); - return true; + return result; } catch (Exception e) { _logger.LogError(e, "Error in net message server hook callback for {MessageType}", typeof(T).Name); - return false; + return HookResult.Continue; } }; _unmanagedCallbackPtr = Marshal.GetFunctionPointerForDelegate(_unmanagedCallback); diff --git a/managed/test/README.md b/managed/test/README.md new file mode 100644 index 000000000..17fa75fde --- /dev/null +++ b/managed/test/README.md @@ -0,0 +1,36 @@ +
+ +

My Plugin

+

Description

+
+ +

+ Build Status + Downloads + Stars + License +

+ +## Getting Started (delete me) + +1. **Edit `manifest.json`** + - Set your plugin's `Id`, `Name`, `Version`, `Author`, `Description`, and `EntrypointDLL` (should match your main class DLL). +2. **Edit `test.csproj`** + - Set the `` property to match your plugin's main class name. + - Add any additional dependencies as needed. +3. **Implement your plugin logic** in C#. + - Place your main plugin class in the root of the project. + - Use the SwiftlyS2 managed API to interact with the game and core. +4. **Add resources** + - Place any required files in the `gamedata`, `templates`, or `translations` folders as needed. + +## Building + +- Open the project in your preferred .NET IDE (e.g., Visual Studio, Rider, VS Code). +- Build the project. The output DLL and resources will be placed in the `build/` directory. +- The publish process will also create a zip file for easy distribution. + +## Publishing + +- Use the `dotnet publish -c Release` command to build and package your plugin. +- Distribute the generated zip file or the contents of the `build/publish` directory. \ No newline at end of file diff --git a/managed/test/examples/Commands.example.cs b/managed/test/examples/Commands.example.cs new file mode 100644 index 000000000..f1e385852 --- /dev/null +++ b/managed/test/examples/Commands.example.cs @@ -0,0 +1,24 @@ +using SwiftlyS2.Shared.Commands; + +namespace test; + +/// +/// This is an example that shows how to use commands. +/// +public partial class MyPlugin +{ + public void InitializeCommands() + { + // Register a command. + Core.Command.RegisterCommand("test2", (context) => { + Console.WriteLine("Test command"); + }); + } + + [Command("test")] // this will be `sw_test` in the console. + // [Command("test", registerRaw: true)] // this will be `test` in the console, without the sw_ prefix. + public void TestCommand(ICommandContext context) + { + context.Reply("Hello World"); + } +} \ No newline at end of file diff --git a/managed/test/examples/Events.example.cs b/managed/test/examples/Events.example.cs new file mode 100644 index 000000000..61d196e0e --- /dev/null +++ b/managed/test/examples/Events.example.cs @@ -0,0 +1,34 @@ +using SwiftlyS2.Shared.Misc; + +namespace test; + +/// +/// This is an example that shows how to use events. +/// +public partial class MyPlugin +{ + public void InitializeEvents() + { + // Register an event on tick. + Core.Event.OnTick += () => { + Console.WriteLine("Tick"); + }; + + Core.Event.OnEntityCreated += (@event) => { + Console.WriteLine("Entity created"); + Console.WriteLine(@event.Entity.DesignerName); + }; + + Core.Event.OnClientConnected += (@event) => { + Console.WriteLine("Client connected"); + // prevent a join. + @event.Result = HookResult.Stop; + }; + + Core.Event.OnPrecacheResource += (@event) => { + // Add your resource here. + @event.AddItem("characters/test.vmdl"); + }; + + } +} \ No newline at end of file diff --git a/managed/test/examples/GameEvents.example.cs b/managed/test/examples/GameEvents.example.cs new file mode 100644 index 000000000..00d4f2bcc --- /dev/null +++ b/managed/test/examples/GameEvents.example.cs @@ -0,0 +1,43 @@ +using SwiftlyS2.Shared.GameEventDefinitions; +using SwiftlyS2.Shared.Misc; +using SwiftlyS2.Shared.GameEvents; + +namespace test; + + +/// This is an example that shows various gameevent API. +public partial class MyPlugin +{ + + public void InitializeGameEvents() + { + /// Hook a game event. + /// The method must take a single parameter that is the game event type, and return a HookResult. + + Core.GameEvent.HookPre((@event) => { + Console.WriteLine($"Player {@event.UserIdController.PlayerName} jumped"); + return HookResult.Continue; + }); + + /// Fire a game event to all players. + /// You can configure the event inside the action. + /// The event will be destroyed immediately after being fired. + /// + /// To fire to a specific client, also check Core.GameEvent.FireToPlayer + Core.GameEvent.Fire(@event => { + @event.LocToken = "Hello World"; + }); + } + + [GameEventHandler(HookMode.Pre)] + public HookResult TestServerNetMessageHandler(EventPlayerJump @event) + { + /// You can also hook the event by using the attribute. + /// The attribute only works on main class that inherits BasePlugin. + + @event.DontBroadcast = true; + + return HookResult.Continue; + } + +} diff --git a/managed/test/examples/HookAndCallNativeFunctions.example.cs b/managed/test/examples/HookAndCallNativeFunctions.example.cs new file mode 100644 index 000000000..e88fecd2a --- /dev/null +++ b/managed/test/examples/HookAndCallNativeFunctions.example.cs @@ -0,0 +1,68 @@ +using Microsoft.Extensions.Logging; +using SwiftlyS2.Shared.Memory; +using SwiftlyS2.Shared.Misc; + +namespace test; + +/// +/// This is an example that shows how to hook and call native functions. +/// +public partial class MyPlugin +{ + + // Your delegate type of the function. + delegate int TestFunctionDelegate(int a, int b); + public void InitializeUnmanagedFunctions() + { + // Get the address of the function. + nint? address = Core.GameData.GetSignature("YourFunctionSignature"); + + // Or you can use the signature to get the address. + address = Core.Memory.GetAddressBySignature(Library.Server, "48 89 5C XXX"); + if (address is null) + { + Core.Logger.LogError("Failed to get the address of the function."); + return; + } + + // Get the function. + var function = Core.Memory.GetUnmanagedFunctionByAddress(address!.Value); + + // Call the function. + function.Call(1, 2); + + // Call the original function if hooked, this can bypass all the hooks that created by SwiftlyS2. + function.CallOriginal(1, 2); + + var guid = function.AddHook(next => { + return (a, b) => + { + Console.WriteLine("Hooked!"); + + Console.WriteLine("Pre hook"); + + // here is the code for pre hook. + + // you can modify the param in this way. + var modifiedA = a + 1; + + // Call the original function. + // If you want to stop the call, you can return 0 and don't call next(). + var result = next()(modifiedA, b); + + // here is the code for post hook. + Console.WriteLine("Post hook"); + + // you can modify the result in this way. + var modifiedResult = result + 1; + + return modifiedResult; + }; + }); + + // Remove the hook. + function.RemoveHook(guid); + + + } +} \ No newline at end of file diff --git a/managed/test/examples/NetMessage.example.cs b/managed/test/examples/NetMessage.example.cs new file mode 100644 index 000000000..1bff3966e --- /dev/null +++ b/managed/test/examples/NetMessage.example.cs @@ -0,0 +1,55 @@ +using SwiftlyS2.Shared.Misc; +using SwiftlyS2.Shared.NetMessages; +using SwiftlyS2.Shared.ProtobufDefinitions; + +namespace test; + + +/// This is an example that shows various net message API. +public partial class MyPlugin { + + public void InitializeNetMessage() { + + /* + This is an example that shows how to send a net message. + The msg will be destroyed immediately after being sent. + */ + Core.NetMessage.Send(msg => { + // Setting fields of the net message. + msg.Amplitude = 10; + msg.Duration = 10; + + // Control the recipients of the net message. + msg.Recipients.AddAllPlayers(); + }); + + + /* + You can also create a persistent net message and send it. + As long as the message is not recycled by GC, you can send it as many times as you want. + */ + using var message = Core.NetMessage.Create(); + message.Amplitude = 10; + message.Duration = 10; + message.Recipients.AddAllPlayers(); + message.SendToAllPlayers(); + } + + /// The ServerNetMessageHandler attribute is used to mark a method as a server-side net message handler. + /// the attribute only works on main class that inherits BasePlugin. + /// + /// The method must take a single parameter that is the net message type, and return a HookResult. + /// + [ServerNetMessageHandler] + public HookResult TestServerNetMessageHandler(CMsgSosStartSoundEvent msg) { + + // You can also set fields of the net message. + msg.SoundeventHash = 0; + + // You can also control the recipients of the net message. + msg.Recipients.RemoveAllPlayers(); + + return HookResult.Continue; + } + +} diff --git a/managed/test/examples/README.md b/managed/test/examples/README.md new file mode 100644 index 000000000..f54a08205 --- /dev/null +++ b/managed/test/examples/README.md @@ -0,0 +1,3 @@ +# This folder includes a few examples that shows some basic ability of swiftlys2. + +# You can delete this folder safety after reading. \ No newline at end of file diff --git a/managed/test/examples/SoundEvent.example.cs b/managed/test/examples/SoundEvent.example.cs new file mode 100644 index 000000000..63987868e --- /dev/null +++ b/managed/test/examples/SoundEvent.example.cs @@ -0,0 +1,41 @@ +using SwiftlyS2.Shared.Sounds; + +namespace test; + +/// +/// This is an example that shows how to use sound event. +/// +public partial class MyPlugin { + + public void InitializeSoundEvent() { + + // Create a soundevent. + using var soundEvent = new SoundEvent() { + // Set the soundevent name. + Name = "Weapon_AK47.Single", + + // Set the source entity, + // can be get by entity.Index, + // or set to -1 for emitting at recipient location (by default) + SourceEntityIndex = -1, + + // Control the volume. + Volume = 0.5f, + + // Control the pitch. + Pitch = 2f + + + }; + + // More param can be set. + soundEvent.SetFloat3("public.position", 1.0f, 1.0f, 1.0f); + + // Don't forget to add recipients. + soundEvent.Recipients.AddAllPlayers(); + + // Emit the sound event. + soundEvent.Emit(); + + } +} \ No newline at end of file diff --git a/managed/test/manifest.json b/managed/test/manifest.json new file mode 100644 index 000000000..f42651d97 --- /dev/null +++ b/managed/test/manifest.json @@ -0,0 +1,9 @@ +{ + "Id": "myplugin", + "Name": "My Plugin", + "Version": "1.0.0", + "Author": "Anonymous", + "Description": "Description", + "Website": "https://swiftlys2.net", + "EntrypointDLL": "MyPlugin.dll" +} \ No newline at end of file diff --git a/managed/test/src/test.cs b/managed/test/src/test.cs new file mode 100644 index 000000000..90711ecfc --- /dev/null +++ b/managed/test/src/test.cs @@ -0,0 +1,24 @@ +using Microsoft.Extensions.DependencyInjection; +using SwiftlyS2.Shared.Plugins; +using SwiftlyS2.Shared; + +namespace test; + +public partial class MyPlugin : BasePlugin { + public MyPlugin(ISwiftlyCore core) : base(core) + { + } + + public override void ConfigureSharedServices(IServiceCollection sharedServices) { + } + + public override void UseSharedServices(IServiceProvider sharedProvider) { + } + + public override void Load(bool hotReload) { + + } + + public override void Unload() { + } +} \ No newline at end of file diff --git a/managed/test/test.csproj b/managed/test/test.csproj new file mode 100644 index 000000000..18ba9a140 --- /dev/null +++ b/managed/test/test.csproj @@ -0,0 +1,38 @@ + + + + net8.0 + enable + enable + true + true + true + MyPlugin + $(MSBuildThisFileDirectory)build/ + $(OutputPath)publish/test + + + + + + + + + + + + + + PreserveNewest + + + + + + + + + + + + \ No newline at end of file From 84fee1904d408cdd987798319c39ca95c1beb6fc Mon Sep 17 00:00:00 2001 From: samyyc Date: Fri, 3 Oct 2025 00:29:05 +0800 Subject: [PATCH 3/4] chore(managed): Clean up --- managed/test/README.md | 36 ---------- managed/test/examples/Commands.example.cs | 24 ------- managed/test/examples/Events.example.cs | 34 ---------- managed/test/examples/GameEvents.example.cs | 43 ------------ .../HookAndCallNativeFunctions.example.cs | 68 ------------------- managed/test/examples/NetMessage.example.cs | 55 --------------- managed/test/examples/README.md | 3 - managed/test/examples/SoundEvent.example.cs | 41 ----------- managed/test/manifest.json | 9 --- managed/test/src/test.cs | 24 ------- managed/test/test.csproj | 38 ----------- 11 files changed, 375 deletions(-) delete mode 100644 managed/test/README.md delete mode 100644 managed/test/examples/Commands.example.cs delete mode 100644 managed/test/examples/Events.example.cs delete mode 100644 managed/test/examples/GameEvents.example.cs delete mode 100644 managed/test/examples/HookAndCallNativeFunctions.example.cs delete mode 100644 managed/test/examples/NetMessage.example.cs delete mode 100644 managed/test/examples/README.md delete mode 100644 managed/test/examples/SoundEvent.example.cs delete mode 100644 managed/test/manifest.json delete mode 100644 managed/test/src/test.cs delete mode 100644 managed/test/test.csproj diff --git a/managed/test/README.md b/managed/test/README.md deleted file mode 100644 index 17fa75fde..000000000 --- a/managed/test/README.md +++ /dev/null @@ -1,36 +0,0 @@ -
- -

My Plugin

-

Description

-
- -

- Build Status - Downloads - Stars - License -

- -## Getting Started (delete me) - -1. **Edit `manifest.json`** - - Set your plugin's `Id`, `Name`, `Version`, `Author`, `Description`, and `EntrypointDLL` (should match your main class DLL). -2. **Edit `test.csproj`** - - Set the `` property to match your plugin's main class name. - - Add any additional dependencies as needed. -3. **Implement your plugin logic** in C#. - - Place your main plugin class in the root of the project. - - Use the SwiftlyS2 managed API to interact with the game and core. -4. **Add resources** - - Place any required files in the `gamedata`, `templates`, or `translations` folders as needed. - -## Building - -- Open the project in your preferred .NET IDE (e.g., Visual Studio, Rider, VS Code). -- Build the project. The output DLL and resources will be placed in the `build/` directory. -- The publish process will also create a zip file for easy distribution. - -## Publishing - -- Use the `dotnet publish -c Release` command to build and package your plugin. -- Distribute the generated zip file or the contents of the `build/publish` directory. \ No newline at end of file diff --git a/managed/test/examples/Commands.example.cs b/managed/test/examples/Commands.example.cs deleted file mode 100644 index f1e385852..000000000 --- a/managed/test/examples/Commands.example.cs +++ /dev/null @@ -1,24 +0,0 @@ -using SwiftlyS2.Shared.Commands; - -namespace test; - -/// -/// This is an example that shows how to use commands. -/// -public partial class MyPlugin -{ - public void InitializeCommands() - { - // Register a command. - Core.Command.RegisterCommand("test2", (context) => { - Console.WriteLine("Test command"); - }); - } - - [Command("test")] // this will be `sw_test` in the console. - // [Command("test", registerRaw: true)] // this will be `test` in the console, without the sw_ prefix. - public void TestCommand(ICommandContext context) - { - context.Reply("Hello World"); - } -} \ No newline at end of file diff --git a/managed/test/examples/Events.example.cs b/managed/test/examples/Events.example.cs deleted file mode 100644 index 61d196e0e..000000000 --- a/managed/test/examples/Events.example.cs +++ /dev/null @@ -1,34 +0,0 @@ -using SwiftlyS2.Shared.Misc; - -namespace test; - -/// -/// This is an example that shows how to use events. -/// -public partial class MyPlugin -{ - public void InitializeEvents() - { - // Register an event on tick. - Core.Event.OnTick += () => { - Console.WriteLine("Tick"); - }; - - Core.Event.OnEntityCreated += (@event) => { - Console.WriteLine("Entity created"); - Console.WriteLine(@event.Entity.DesignerName); - }; - - Core.Event.OnClientConnected += (@event) => { - Console.WriteLine("Client connected"); - // prevent a join. - @event.Result = HookResult.Stop; - }; - - Core.Event.OnPrecacheResource += (@event) => { - // Add your resource here. - @event.AddItem("characters/test.vmdl"); - }; - - } -} \ No newline at end of file diff --git a/managed/test/examples/GameEvents.example.cs b/managed/test/examples/GameEvents.example.cs deleted file mode 100644 index 00d4f2bcc..000000000 --- a/managed/test/examples/GameEvents.example.cs +++ /dev/null @@ -1,43 +0,0 @@ -using SwiftlyS2.Shared.GameEventDefinitions; -using SwiftlyS2.Shared.Misc; -using SwiftlyS2.Shared.GameEvents; - -namespace test; - - -/// This is an example that shows various gameevent API. -public partial class MyPlugin -{ - - public void InitializeGameEvents() - { - /// Hook a game event. - /// The method must take a single parameter that is the game event type, and return a HookResult. - - Core.GameEvent.HookPre((@event) => { - Console.WriteLine($"Player {@event.UserIdController.PlayerName} jumped"); - return HookResult.Continue; - }); - - /// Fire a game event to all players. - /// You can configure the event inside the action. - /// The event will be destroyed immediately after being fired. - /// - /// To fire to a specific client, also check Core.GameEvent.FireToPlayer - Core.GameEvent.Fire(@event => { - @event.LocToken = "Hello World"; - }); - } - - [GameEventHandler(HookMode.Pre)] - public HookResult TestServerNetMessageHandler(EventPlayerJump @event) - { - /// You can also hook the event by using the attribute. - /// The attribute only works on main class that inherits BasePlugin. - - @event.DontBroadcast = true; - - return HookResult.Continue; - } - -} diff --git a/managed/test/examples/HookAndCallNativeFunctions.example.cs b/managed/test/examples/HookAndCallNativeFunctions.example.cs deleted file mode 100644 index e88fecd2a..000000000 --- a/managed/test/examples/HookAndCallNativeFunctions.example.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Microsoft.Extensions.Logging; -using SwiftlyS2.Shared.Memory; -using SwiftlyS2.Shared.Misc; - -namespace test; - -/// -/// This is an example that shows how to hook and call native functions. -/// -public partial class MyPlugin -{ - - // Your delegate type of the function. - delegate int TestFunctionDelegate(int a, int b); - public void InitializeUnmanagedFunctions() - { - // Get the address of the function. - nint? address = Core.GameData.GetSignature("YourFunctionSignature"); - - // Or you can use the signature to get the address. - address = Core.Memory.GetAddressBySignature(Library.Server, "48 89 5C XXX"); - if (address is null) - { - Core.Logger.LogError("Failed to get the address of the function."); - return; - } - - // Get the function. - var function = Core.Memory.GetUnmanagedFunctionByAddress(address!.Value); - - // Call the function. - function.Call(1, 2); - - // Call the original function if hooked, this can bypass all the hooks that created by SwiftlyS2. - function.CallOriginal(1, 2); - - var guid = function.AddHook(next => { - return (a, b) => - { - Console.WriteLine("Hooked!"); - - Console.WriteLine("Pre hook"); - - // here is the code for pre hook. - - // you can modify the param in this way. - var modifiedA = a + 1; - - // Call the original function. - // If you want to stop the call, you can return 0 and don't call next(). - var result = next()(modifiedA, b); - - // here is the code for post hook. - Console.WriteLine("Post hook"); - - // you can modify the result in this way. - var modifiedResult = result + 1; - - return modifiedResult; - }; - }); - - // Remove the hook. - function.RemoveHook(guid); - - - } -} \ No newline at end of file diff --git a/managed/test/examples/NetMessage.example.cs b/managed/test/examples/NetMessage.example.cs deleted file mode 100644 index 1bff3966e..000000000 --- a/managed/test/examples/NetMessage.example.cs +++ /dev/null @@ -1,55 +0,0 @@ -using SwiftlyS2.Shared.Misc; -using SwiftlyS2.Shared.NetMessages; -using SwiftlyS2.Shared.ProtobufDefinitions; - -namespace test; - - -/// This is an example that shows various net message API. -public partial class MyPlugin { - - public void InitializeNetMessage() { - - /* - This is an example that shows how to send a net message. - The msg will be destroyed immediately after being sent. - */ - Core.NetMessage.Send(msg => { - // Setting fields of the net message. - msg.Amplitude = 10; - msg.Duration = 10; - - // Control the recipients of the net message. - msg.Recipients.AddAllPlayers(); - }); - - - /* - You can also create a persistent net message and send it. - As long as the message is not recycled by GC, you can send it as many times as you want. - */ - using var message = Core.NetMessage.Create(); - message.Amplitude = 10; - message.Duration = 10; - message.Recipients.AddAllPlayers(); - message.SendToAllPlayers(); - } - - /// The ServerNetMessageHandler attribute is used to mark a method as a server-side net message handler. - /// the attribute only works on main class that inherits BasePlugin. - /// - /// The method must take a single parameter that is the net message type, and return a HookResult. - /// - [ServerNetMessageHandler] - public HookResult TestServerNetMessageHandler(CMsgSosStartSoundEvent msg) { - - // You can also set fields of the net message. - msg.SoundeventHash = 0; - - // You can also control the recipients of the net message. - msg.Recipients.RemoveAllPlayers(); - - return HookResult.Continue; - } - -} diff --git a/managed/test/examples/README.md b/managed/test/examples/README.md deleted file mode 100644 index f54a08205..000000000 --- a/managed/test/examples/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# This folder includes a few examples that shows some basic ability of swiftlys2. - -# You can delete this folder safety after reading. \ No newline at end of file diff --git a/managed/test/examples/SoundEvent.example.cs b/managed/test/examples/SoundEvent.example.cs deleted file mode 100644 index 63987868e..000000000 --- a/managed/test/examples/SoundEvent.example.cs +++ /dev/null @@ -1,41 +0,0 @@ -using SwiftlyS2.Shared.Sounds; - -namespace test; - -/// -/// This is an example that shows how to use sound event. -/// -public partial class MyPlugin { - - public void InitializeSoundEvent() { - - // Create a soundevent. - using var soundEvent = new SoundEvent() { - // Set the soundevent name. - Name = "Weapon_AK47.Single", - - // Set the source entity, - // can be get by entity.Index, - // or set to -1 for emitting at recipient location (by default) - SourceEntityIndex = -1, - - // Control the volume. - Volume = 0.5f, - - // Control the pitch. - Pitch = 2f - - - }; - - // More param can be set. - soundEvent.SetFloat3("public.position", 1.0f, 1.0f, 1.0f); - - // Don't forget to add recipients. - soundEvent.Recipients.AddAllPlayers(); - - // Emit the sound event. - soundEvent.Emit(); - - } -} \ No newline at end of file diff --git a/managed/test/manifest.json b/managed/test/manifest.json deleted file mode 100644 index f42651d97..000000000 --- a/managed/test/manifest.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "Id": "myplugin", - "Name": "My Plugin", - "Version": "1.0.0", - "Author": "Anonymous", - "Description": "Description", - "Website": "https://swiftlys2.net", - "EntrypointDLL": "MyPlugin.dll" -} \ No newline at end of file diff --git a/managed/test/src/test.cs b/managed/test/src/test.cs deleted file mode 100644 index 90711ecfc..000000000 --- a/managed/test/src/test.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using SwiftlyS2.Shared.Plugins; -using SwiftlyS2.Shared; - -namespace test; - -public partial class MyPlugin : BasePlugin { - public MyPlugin(ISwiftlyCore core) : base(core) - { - } - - public override void ConfigureSharedServices(IServiceCollection sharedServices) { - } - - public override void UseSharedServices(IServiceProvider sharedProvider) { - } - - public override void Load(bool hotReload) { - - } - - public override void Unload() { - } -} \ No newline at end of file diff --git a/managed/test/test.csproj b/managed/test/test.csproj deleted file mode 100644 index 18ba9a140..000000000 --- a/managed/test/test.csproj +++ /dev/null @@ -1,38 +0,0 @@ - - - - net8.0 - enable - enable - true - true - true - MyPlugin - $(MSBuildThisFileDirectory)build/ - $(OutputPath)publish/test - - - - - - - - - - - - - - PreserveNewest - - - - - - - - - - - - \ No newline at end of file From d8ba7e4a062da53b4c7dfa281952a94231983b99 Mon Sep 17 00:00:00 2001 From: skuzzis Date: Thu, 2 Oct 2025 19:29:10 +0300 Subject: [PATCH 4/4] fix(native): MessageHook return type --- src/scripting/network/netmessages.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scripting/network/netmessages.cpp b/src/scripting/network/netmessages.cpp index 64f5ad483..daade9e82 100644 --- a/src/scripting/network/netmessages.cpp +++ b/src/scripting/network/netmessages.cpp @@ -139,7 +139,7 @@ bool Bridge_NetMessages_HasField(void* pmsg, const char* fieldName) google::protobuf::Message* msg = (google::protobuf::Message*)pmsg; GETCHECK_FIELD(false); CHECK_FIELD_NOT_REPEATED(false); - + return msg->GetReflection()->HasField(*msg, field); } @@ -897,7 +897,7 @@ uint64_t Bridge_NetMessages_AddNetMessageServerHook(void* callback_ptr) auto netmessages = g_ifaceService.FetchInterface(NETMESSAGES_INTERFACE_VERSION); return netmessages->AddServerMessageSendCallback([callback_ptr](uint64_t* clients, int messageid, void* msg) { - return ((bool(*)(uint64_t*, int, void*))callback_ptr)(clients, messageid, msg); + return ((int(*)(uint64_t*, int, void*))callback_ptr)(clients, messageid, msg); }); } @@ -912,7 +912,7 @@ uint64_t Bridge_NetMessages_AddNetMessageClientHook(void* callback_ptr) auto netmessages = g_ifaceService.FetchInterface(NETMESSAGES_INTERFACE_VERSION); return netmessages->AddClientMessageSendCallback([callback_ptr](int playerid, int messageid, void* msg) { - return ((bool(*)(int, int, void*))callback_ptr)(playerid, messageid, msg); + return ((int(*)(int, int, void*))callback_ptr)(playerid, messageid, msg); }); }