Skip to content

Commit 68bf505

Browse files
committed
Add a static class to resolve when multiple drivers are configured
This allows server operators to specify which driver should be in use by plugins. They are then able to use a wrapper. This enables the use case of a player configuring their menu, allowing the effective driver to be selected on a player by player basis.
1 parent d3d4f8c commit 68bf505

File tree

6 files changed

+91
-23
lines changed

6 files changed

+91
-23
lines changed

src/CSSUniversalMenuAPI/IMenuAPI.cs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using System.Threading;
33

44
using CounterStrikeSharp.API.Core;
5-
using CounterStrikeSharp.API.Core.Capabilities;
65

76
namespace CSSUniversalMenuAPI;
87

@@ -38,9 +37,4 @@ public interface IMenuAPI
3837
/// <param name="player">The player of which to query.</param>
3938
/// <returns>Whether the player has an active menu on their screen.</returns>
4039
bool IsMenuOpen(CCSPlayerController player);
41-
42-
/// <summary>
43-
/// Standard helper to get get or provide this implementation
44-
/// </summary>
45-
static readonly PluginCapability<IMenuAPI> PluginCapability = new("universalmenuapi");
4640
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Reflection;
5+
using System.Text.Json;
6+
using System.Threading;
7+
8+
using CounterStrikeSharp.API.Core;
9+
10+
namespace CSSUniversalMenuAPI;
11+
12+
/// <summary>
13+
/// Because menus may want access to other drivers, and PluginCapability&lt;&gt; is not expressive enough,
14+
/// this helper class is included with the interface to aid in constructing and
15+
/// </summary>
16+
public static class UniversalMenu
17+
{
18+
private static string? DefaultDriverDesired { get; }
19+
private static string? DefaultDriverName { get; set; }
20+
public static IMenuAPI? DefaultDriver { get; private set; }
21+
22+
private static Dictionary<string, IMenuAPI> RegisteredDrivers { get; } = new();
23+
public static IReadOnlyDictionary<string, IMenuAPI> Drivers => RegisteredDrivers;
24+
public static event EventHandler? DriversChanged;
25+
26+
static UniversalMenu()
27+
{
28+
var configDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Environment.CurrentDirectory;
29+
var configPath = Path.Join(configDir, "config.json");
30+
31+
if (!File.Exists(configPath))
32+
{
33+
Console.WriteLine("UniversalMenu: No default driver configured, will use first registered driver");
34+
return;
35+
}
36+
37+
var contents = File.ReadAllText(configPath);
38+
var doc = JsonDocument.Parse(contents);
39+
DefaultDriverDesired = doc.RootElement.GetProperty("driver").GetString();
40+
41+
Console.WriteLine($"UniversalMenu: Desired default driver: {DefaultDriverDesired}");
42+
}
43+
44+
public static void RegisterDriver(string name, IMenuAPI driver)
45+
{
46+
if (!RegisteredDrivers.TryAdd(name, driver))
47+
throw new InvalidOperationException($"RegisterDriver(): Conflicting named drivers configured: {name}");
48+
49+
if (DefaultDriverDesired is null || name == DefaultDriverDesired)
50+
{
51+
if (DefaultDriver is not null)
52+
throw new InvalidOperationException($"RegisterDriver(): Conflicting default drivers configured: {name} and {DefaultDriverName}");
53+
DefaultDriver = driver;
54+
DefaultDriverName = name;
55+
}
56+
DriversChanged?.Invoke(null, EventArgs.Empty);
57+
}
58+
59+
public static void UnregisterDriver(string name)
60+
{
61+
if (RegisteredDrivers.Remove(name, out var driver) && driver == DefaultDriver)
62+
{
63+
DefaultDriver = null;
64+
DefaultDriverName = null;
65+
}
66+
DriversChanged?.Invoke(null, EventArgs.Empty);
67+
}
68+
69+
public static IMenu CreateMenu(CCSPlayerController player, CancellationToken ct = default)
70+
{
71+
if (DefaultDriver is null)
72+
throw new InvalidOperationException("No default driver has been registered. Do you have a driver installed and/or configured?");
73+
return DefaultDriver.CreateMenu(player, ct);
74+
}
75+
76+
public static IMenu CreateMenu(IMenu parent, CancellationToken ct = default)
77+
{
78+
if (DefaultDriver is null)
79+
throw new InvalidOperationException("No default driver has been registered. Do you have a driver installed and/or configured?");
80+
return DefaultDriver.CreateMenu(parent, ct);
81+
}
82+
}

src/UniversalMenu.Compat.CSSharp/CSSharpCompatPlugin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public static bool BaseMenu_Open(BasePlugin? plugin, CCSPlayerController player,
8080
activeMenu.Close();
8181
}
8282

83-
var api = IMenuAPI.PluginCapability.Get();
83+
var api = CSSUniversalMenuAPI.UniversalMenu.DefaultDriver;
8484

8585
if (api is null) // fall back to builtin menu
8686
return true;

src/UniversalMenu.Compat.MenuManagerApi/MenuManagerCompat.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ public override void Load(bool hotReload)
3030
if (Instance is not null)
3131
return Instance;
3232

33-
var universalAPI = IMenuAPI.PluginCapability.Get()
34-
?? throw new Exception("Unable to find CSSUniversalAPI supporting menu or adapter");
35-
Instance = new MenuManagerTranslator(this, universalAPI);
33+
Instance = new MenuManagerTranslator(this);
3634

3735
return Instance;
3836
});

src/UniversalMenu.Compat.MenuManagerApi/MenuManagerTranslator.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
using CounterStrikeSharp.API.Core;
1010
using CounterStrikeSharp.API.Modules.Menu;
1111

12-
using CSSUniversalMenuAPI;
1312
using CSSUniversalMenuAPI.Extensions;
1413

1514
using ICssMenu = CounterStrikeSharp.API.Modules.Menu.IMenu;
@@ -22,11 +21,9 @@ namespace UniversalMenu.Compat.MenuManagerApi;
2221
public sealed class MenuManagerTranslator : IMenuManagerAPI
2322
{
2423
public MenuManagerCompat Plugin { get; }
25-
public IMenuAPI UniversalAPI { get; }
26-
public MenuManagerTranslator(MenuManagerCompat plugin, IMenuAPI universalAPI)
24+
public MenuManagerTranslator(MenuManagerCompat plugin)
2725
{
2826
Plugin = plugin;
29-
UniversalAPI = universalAPI;
3027
}
3128

3229
internal class PlayerState
@@ -69,7 +66,7 @@ MenuManagerMenuType IMenuManagerAPI.GetMenuType(CCSPlayerController player)
6966

7067
bool IMenuManagerAPI.HasOpenedMenu(CCSPlayerController player)
7168
{
72-
return UniversalAPI.IsMenuOpen(player);
69+
return CSSUniversalMenuAPI.UniversalMenu.DefaultDriver?.IsMenuOpen(player) ?? false;
7370
}
7471

7572
ICssMenu IMenuManagerAPI.NewMenu(string title, Action<CCSPlayerController> back_action)
@@ -87,7 +84,6 @@ internal sealed class MenuInstanceTranslator : ICssMenu
8784
{
8885
public string Title { get; set; }
8986
public MenuManagerTranslator Translator { get; }
90-
public IMenuAPI UniversalAPI => Translator.UniversalAPI;
9187
public bool ExitButton { get; set; }
9288

9389
public List<ChatMenuOption> MenuOptions { get; } = new();
@@ -130,7 +126,7 @@ public void Open(CCSPlayerController player)
130126
return;
131127
}
132128

133-
menu = PlayerMenus[player.SteamID] = UniversalAPI.CreateMenu(player);
129+
menu = PlayerMenus[player.SteamID] = CSSUniversalMenuAPI.UniversalMenu.CreateMenu(player);
134130
menu.Title = Title;
135131
menu.PlayerCanClose = true;// ExitButton;
136132

src/UniversalMenu.Driver.ScreenMenuAPI/ScreenMenuAPIDriverPlugin.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace UniversalMenu.ScreenMenuAPIAdapter;
1313
[MinimumApiVersion(314)]
1414
public class ScreenMenuAPIDriverPlugin : BasePlugin
1515
{
16-
public override string ModuleName => "UniversalMenu.Driver.ScreenMenuAPI";
16+
public override string ModuleName => "UniversalMenu.DefaultDriver.ScreenMenuAPI";
1717
public override string ModuleDescription => "Implement CSSUniversalMenuAPI via ScreenMenuAPI";
1818
public override string ModuleVersion => Verlite.Version.Full;
1919

@@ -24,16 +24,14 @@ public override void Load(bool hotReload)
2424
{
2525
Cts = new CancellationTokenSource();
2626

27-
Capabilities.RegisterPluginCapability(IMenuAPI.PluginCapability, () =>
28-
{
29-
DriverInstance ??= new ScreenMenuApiDriver(this);
30-
return DriverInstance;
31-
});
27+
DriverInstance = new ScreenMenuApiDriver(this);
28+
CSSUniversalMenuAPI.UniversalMenu.RegisterDriver("ScreenMenuAPI", DriverInstance);
3229
}
3330

3431
public override void Unload(bool hotReload)
3532
{
3633
Cts.Cancel();
34+
CSSUniversalMenuAPI.UniversalMenu.UnregisterDriver("ScreenMenuAPI");
3735
}
3836

3937
[ConsoleCommand("css_0"), ConsoleCommand("css_1"), ConsoleCommand("css_2"), ConsoleCommand("css_3"), ConsoleCommand("css_4")]

0 commit comments

Comments
 (0)