Skip to content

Commit c3811d2

Browse files
committed
feat(managed): Manual plugin load
1 parent 2033f22 commit c3811d2

File tree

6 files changed

+96
-1
lines changed

6 files changed

+96
-1
lines changed

managed/src/SwiftlyS2.Core/Modules/Plugins/PluginManager.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,15 @@ static async Task WaitForFileAccess( CancellationToken token, string filePath, i
158158
internal void Initialize()
159159
{
160160
LoadExports();
161-
LoadPlugins();
161+
if (!NativeCore.PluginManualLoadState()) LoadPlugins();
162+
else
163+
{
164+
var plugins = NativeCore.PluginLoadOrder().Split('\x01');
165+
foreach (var plugin in plugins)
166+
{
167+
_ = LoadPluginById(plugin, silent: false);
168+
}
169+
}
162170
}
163171

164172
public IReadOnlyList<PluginContext> GetPlugins() => plugins.AsReadOnly();
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#pragma warning disable CS0649
2+
#pragma warning disable CS0169
3+
4+
using System.Buffers;
5+
using System.Text;
6+
using System.Threading;
7+
using SwiftlyS2.Shared.Natives;
8+
9+
namespace SwiftlyS2.Core.Natives;
10+
11+
internal static class NativeCore {
12+
private static int _MainThreadID;
13+
14+
private unsafe static delegate* unmanaged<byte> _PluginManualLoadState;
15+
16+
public unsafe static bool PluginManualLoadState() {
17+
var ret = _PluginManualLoadState();
18+
return ret == 1;
19+
}
20+
21+
private unsafe static delegate* unmanaged<byte*, int> _PluginLoadOrder;
22+
23+
public unsafe static string PluginLoadOrder() {
24+
var ret = _PluginLoadOrder(null);
25+
var pool = ArrayPool<byte>.Shared;
26+
var retBuffer = pool.Rent(ret + 1);
27+
fixed (byte* retBufferPtr = retBuffer) {
28+
ret = _PluginLoadOrder(retBufferPtr);
29+
var retString = Encoding.UTF8.GetString(retBufferPtr, ret);
30+
pool.Return(retBuffer);
31+
return retString;
32+
}
33+
}
34+
}

natives/core.native

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class Core
2+
3+
bool PluginManualLoadState = void
4+
string PluginLoadOrder = void

plugin_files/configs/core.example.jsonc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
"ConsoleFilter": true,
1111
"FollowCS2ServerGuidelines": true,
1212
"Language": "en",
13+
"ManualLoadPlugins": false,
14+
"PluginLoadOrder": [],
1315
"Menu": {
1416
"AvailableInputModes": [
1517
"button",

src/scripting/core/core.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/************************************************************************************************
2+
* SwiftlyS2 is a scripting framework for Source2-based games.
3+
* Copyright (C) 2025 Swiftly Solution SRL via Sava Andrei-Sebastian and it's contributors (samyycX)
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
************************************************************************************************/
18+
19+
#include <scripting/scripting.h>
20+
#include <api/interfaces/manager.h>
21+
22+
uint8_t Bridge_Core_PluginManualLoadState()
23+
{
24+
static auto config = g_ifaceService.FetchInterface<IConfiguration>(CONFIGURATION_INTERFACE_VERSION);
25+
if (bool* b = std::get_if<bool>(&config->GetValue("core.ManualLoadPlugins")))
26+
{
27+
return *b ? 1 : 0;
28+
}
29+
return 0;
30+
}
31+
32+
int Bridge_Core_PluginLoadOrder(char* out)
33+
{
34+
static auto config = g_ifaceService.FetchInterface<IConfiguration>(CONFIGURATION_INTERFACE_VERSION);
35+
if (std::string* vec = std::get_if<std::string>(&config->GetValue("core.PluginLoadOrder")))
36+
{
37+
if (out != nullptr) strcpy(out, vec->c_str());
38+
return static_cast<int>(vec->size());
39+
}
40+
return 0;
41+
}
42+
43+
DEFINE_NATIVE("Core.PluginManualLoadState", Bridge_Core_PluginManualLoadState);
44+
DEFINE_NATIVE("Core.PluginLoadOrder", Bridge_Core_PluginLoadOrder);

src/server/configuration/configuration.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,9 @@ bool Configuration::Load()
488488
RegisterConfiguration(wasEdited, config_json, "core", "core", "Menu.Buttons.ScrollBack", "f");
489489
RegisterConfiguration(wasEdited, config_json, "core", "core", "Menu.Buttons.Exit", "tab");
490490

491+
RegisterConfiguration(wasEdited, config_json, "core", "core", "ManualLoadPlugins", false);
492+
RegisterConfigurationVector<std::string>(wasEdited, config_json, "core", "core", "PluginLoadOrder", {}, true, "\x01");
493+
491494
RegisterConfigurationVector<std::string>(wasEdited, config_json, "core", "core", "Menu.AvailableInputModes", { "button", "wasd" }, true, " ");
492495
RegisterConfiguration(wasEdited, config_json, "core", "core", "Menu.InputMode", "button");
493496

0 commit comments

Comments
 (0)