diff --git a/src/CSSUniversalMenuAPI/IMenuAPI.cs b/src/CSSUniversalMenuAPI/IMenuAPI.cs
index e230954..2a0e193 100644
--- a/src/CSSUniversalMenuAPI/IMenuAPI.cs
+++ b/src/CSSUniversalMenuAPI/IMenuAPI.cs
@@ -2,7 +2,6 @@
using System.Threading;
using CounterStrikeSharp.API.Core;
-using CounterStrikeSharp.API.Core.Capabilities;
namespace CSSUniversalMenuAPI;
@@ -38,9 +37,4 @@ public interface IMenuAPI
/// The player of which to query.
/// Whether the player has an active menu on their screen.
bool IsMenuOpen(CCSPlayerController player);
-
- ///
- /// Standard helper to get get or provide this implementation
- ///
- static readonly PluginCapability PluginCapability = new("universalmenuapi");
}
diff --git a/src/CSSUniversalMenuAPI/UniversalMenu.cs b/src/CSSUniversalMenuAPI/UniversalMenu.cs
new file mode 100644
index 0000000..830539d
--- /dev/null
+++ b/src/CSSUniversalMenuAPI/UniversalMenu.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Text.Json;
+using System.Threading;
+
+using CounterStrikeSharp.API.Core;
+
+namespace CSSUniversalMenuAPI;
+
+///
+/// Because menus may want access to other drivers, and PluginCapability<> is not expressive enough,
+/// this helper class is included with the interface to aid in constructing and
+///
+public static class UniversalMenu
+{
+ private static string? DefaultDriverDesired { get; }
+ private static string? DefaultDriverName { get; set; }
+ public static IMenuAPI? DefaultDriver { get; private set; }
+
+ private static Dictionary RegisteredDrivers { get; } = new();
+ public static IReadOnlyDictionary Drivers => RegisteredDrivers;
+ public static event EventHandler? DriversChanged;
+
+ static UniversalMenu()
+ {
+ var configDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Environment.CurrentDirectory;
+ var configPath = Path.Join(configDir, "config.json");
+
+ if (!File.Exists(configPath))
+ {
+ Console.WriteLine("UniversalMenu: No default driver configured, will use first registered driver");
+ return;
+ }
+
+ var contents = File.ReadAllText(configPath);
+ var doc = JsonDocument.Parse(contents);
+ DefaultDriverDesired = doc.RootElement.GetProperty("driver").GetString();
+
+ Console.WriteLine($"UniversalMenu: Desired default driver: {DefaultDriverDesired}");
+ }
+
+ public static void RegisterDriver(string name, IMenuAPI driver)
+ {
+ if (!RegisteredDrivers.TryAdd(name, driver))
+ throw new InvalidOperationException($"RegisterDriver(): Conflicting named drivers configured: {name}");
+
+ if (DefaultDriverDesired is null || name == DefaultDriverDesired)
+ {
+ if (DefaultDriver is not null)
+ throw new InvalidOperationException($"RegisterDriver(): Conflicting default drivers configured: {name} and {DefaultDriverName}");
+ DefaultDriver = driver;
+ DefaultDriverName = name;
+ }
+ DriversChanged?.Invoke(null, EventArgs.Empty);
+ }
+
+ public static void UnregisterDriver(string name)
+ {
+ if (RegisteredDrivers.Remove(name, out var driver) && driver == DefaultDriver)
+ {
+ DefaultDriver = null;
+ DefaultDriverName = null;
+ }
+ DriversChanged?.Invoke(null, EventArgs.Empty);
+ }
+
+ public static IMenu CreateMenu(CCSPlayerController player, CancellationToken ct = default)
+ {
+ if (DefaultDriver is null)
+ throw new InvalidOperationException("No default driver has been registered. Do you have a driver installed and/or configured?");
+ return DefaultDriver.CreateMenu(player, ct);
+ }
+
+ public static IMenu CreateMenu(IMenu parent, CancellationToken ct = default)
+ {
+ if (DefaultDriver is null)
+ throw new InvalidOperationException("No default driver has been registered. Do you have a driver installed and/or configured?");
+ return DefaultDriver.CreateMenu(parent, ct);
+ }
+}
diff --git a/src/UniversalMenu.Compat.CSSharp/CSSharpCompatPlugin.cs b/src/UniversalMenu.Compat.CSSharp/CSSharpCompatPlugin.cs
index 7995713..5cfa963 100644
--- a/src/UniversalMenu.Compat.CSSharp/CSSharpCompatPlugin.cs
+++ b/src/UniversalMenu.Compat.CSSharp/CSSharpCompatPlugin.cs
@@ -80,7 +80,7 @@ public static bool BaseMenu_Open(BasePlugin? plugin, CCSPlayerController player,
activeMenu.Close();
}
- var api = IMenuAPI.PluginCapability.Get();
+ var api = CSSUniversalMenuAPI.UniversalMenu.DefaultDriver;
if (api is null) // fall back to builtin menu
return true;
diff --git a/src/UniversalMenu.Compat.MenuManagerApi/MenuManagerCompat.cs b/src/UniversalMenu.Compat.MenuManagerApi/MenuManagerCompat.cs
index aa4a84a..8761de5 100644
--- a/src/UniversalMenu.Compat.MenuManagerApi/MenuManagerCompat.cs
+++ b/src/UniversalMenu.Compat.MenuManagerApi/MenuManagerCompat.cs
@@ -30,9 +30,7 @@ public override void Load(bool hotReload)
if (Instance is not null)
return Instance;
- var universalAPI = IMenuAPI.PluginCapability.Get()
- ?? throw new Exception("Unable to find CSSUniversalAPI supporting menu or adapter");
- Instance = new MenuManagerTranslator(this, universalAPI);
+ Instance = new MenuManagerTranslator(this);
return Instance;
});
diff --git a/src/UniversalMenu.Compat.MenuManagerApi/MenuManagerTranslator.cs b/src/UniversalMenu.Compat.MenuManagerApi/MenuManagerTranslator.cs
index 28f7a78..681ed16 100644
--- a/src/UniversalMenu.Compat.MenuManagerApi/MenuManagerTranslator.cs
+++ b/src/UniversalMenu.Compat.MenuManagerApi/MenuManagerTranslator.cs
@@ -9,7 +9,6 @@
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Menu;
-using CSSUniversalMenuAPI;
using CSSUniversalMenuAPI.Extensions;
using ICssMenu = CounterStrikeSharp.API.Modules.Menu.IMenu;
@@ -22,11 +21,9 @@ namespace UniversalMenu.Compat.MenuManagerApi;
public sealed class MenuManagerTranslator : IMenuManagerAPI
{
public MenuManagerCompat Plugin { get; }
- public IMenuAPI UniversalAPI { get; }
- public MenuManagerTranslator(MenuManagerCompat plugin, IMenuAPI universalAPI)
+ public MenuManagerTranslator(MenuManagerCompat plugin)
{
Plugin = plugin;
- UniversalAPI = universalAPI;
}
internal class PlayerState
@@ -69,7 +66,7 @@ MenuManagerMenuType IMenuManagerAPI.GetMenuType(CCSPlayerController player)
bool IMenuManagerAPI.HasOpenedMenu(CCSPlayerController player)
{
- return UniversalAPI.IsMenuOpen(player);
+ return CSSUniversalMenuAPI.UniversalMenu.DefaultDriver?.IsMenuOpen(player) ?? false;
}
ICssMenu IMenuManagerAPI.NewMenu(string title, Action back_action)
@@ -87,7 +84,6 @@ internal sealed class MenuInstanceTranslator : ICssMenu
{
public string Title { get; set; }
public MenuManagerTranslator Translator { get; }
- public IMenuAPI UniversalAPI => Translator.UniversalAPI;
public bool ExitButton { get; set; }
public List MenuOptions { get; } = new();
@@ -130,7 +126,7 @@ public void Open(CCSPlayerController player)
return;
}
- menu = PlayerMenus[player.SteamID] = UniversalAPI.CreateMenu(player);
+ menu = PlayerMenus[player.SteamID] = CSSUniversalMenuAPI.UniversalMenu.CreateMenu(player);
menu.Title = Title;
menu.PlayerCanClose = true;// ExitButton;
diff --git a/src/UniversalMenu.Driver.ScreenMenuAPI/ScreenMenuAPIDriverPlugin.cs b/src/UniversalMenu.Driver.ScreenMenuAPI/ScreenMenuAPIDriverPlugin.cs
index 3f51b4c..81378b5 100644
--- a/src/UniversalMenu.Driver.ScreenMenuAPI/ScreenMenuAPIDriverPlugin.cs
+++ b/src/UniversalMenu.Driver.ScreenMenuAPI/ScreenMenuAPIDriverPlugin.cs
@@ -13,7 +13,7 @@ namespace UniversalMenu.ScreenMenuAPIAdapter;
[MinimumApiVersion(314)]
public class ScreenMenuAPIDriverPlugin : BasePlugin
{
- public override string ModuleName => "UniversalMenu.Driver.ScreenMenuAPI";
+ public override string ModuleName => "UniversalMenu.DefaultDriver.ScreenMenuAPI";
public override string ModuleDescription => "Implement CSSUniversalMenuAPI via ScreenMenuAPI";
public override string ModuleVersion => Verlite.Version.Full;
@@ -24,16 +24,14 @@ public override void Load(bool hotReload)
{
Cts = new CancellationTokenSource();
- Capabilities.RegisterPluginCapability(IMenuAPI.PluginCapability, () =>
- {
- DriverInstance ??= new ScreenMenuApiDriver(this);
- return DriverInstance;
- });
+ DriverInstance = new ScreenMenuApiDriver(this);
+ CSSUniversalMenuAPI.UniversalMenu.RegisterDriver("ScreenMenuAPI", DriverInstance);
}
public override void Unload(bool hotReload)
{
Cts.Cancel();
+ CSSUniversalMenuAPI.UniversalMenu.UnregisterDriver("ScreenMenuAPI");
}
[ConsoleCommand("css_0"), ConsoleCommand("css_1"), ConsoleCommand("css_2"), ConsoleCommand("css_3"), ConsoleCommand("css_4")]