Skip to content

Commit d8c5c46

Browse files
committed
Added first parse MenuManagerApi driver
1 parent b2feb2b commit d8c5c46

File tree

7 files changed

+274
-0
lines changed

7 files changed

+274
-0
lines changed

CSSUniversalMenuAPI.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1616
Directory.Build.props = Directory.Build.props
1717
Directory.Build.targets = Directory.Build.targets
1818
global.json = global.json
19+
package.sh = package.sh
1920
README.md = README.md
2021
EndProjectSection
2122
EndProject
@@ -41,6 +42,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub Actions", "GitHub Ac
4142
EndProject
4243
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalMenu.Compat.CSSharp", "src\UniversalMenu.Compat.CSSharp\UniversalMenu.Compat.CSSharp.csproj", "{EF2866D7-C411-42ED-B5E0-DCE79CCFCA09}"
4344
EndProject
45+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalMenu.Driver.MenuManagerApi", "src\UniversalMenu.Driver.MenuManagerApi\UniversalMenu.Driver.MenuManagerApi.csproj", "{FB832721-DCE2-4F62-A441-6C3E21A05317}"
46+
EndProject
4447
Global
4548
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4649
Debug|Any CPU = Debug|Any CPU
@@ -75,6 +78,10 @@ Global
7578
{EF2866D7-C411-42ED-B5E0-DCE79CCFCA09}.Debug|Any CPU.Build.0 = Debug|Any CPU
7679
{EF2866D7-C411-42ED-B5E0-DCE79CCFCA09}.Release|Any CPU.ActiveCfg = Release|Any CPU
7780
{EF2866D7-C411-42ED-B5E0-DCE79CCFCA09}.Release|Any CPU.Build.0 = Release|Any CPU
81+
{FB832721-DCE2-4F62-A441-6C3E21A05317}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
82+
{FB832721-DCE2-4F62-A441-6C3E21A05317}.Debug|Any CPU.Build.0 = Debug|Any CPU
83+
{FB832721-DCE2-4F62-A441-6C3E21A05317}.Release|Any CPU.ActiveCfg = Release|Any CPU
84+
{FB832721-DCE2-4F62-A441-6C3E21A05317}.Release|Any CPU.Build.0 = Release|Any CPU
7885
EndGlobalSection
7986
GlobalSection(SolutionProperties) = preSolution
8087
HideSolutionNode = FALSE

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,19 @@ classDiagram
113113
UniversalMenu.Compat.ScreenMenuAPI <-- PluginUsingSomeScreenMenu
114114
CSSUniversalMenuAPI <-- PluginUsingUniversalAPI
115115
```
116+
117+
<!--
118+
Potentially interested parties in working on this project:
119+
120+
exkludera Custom Menu
121+
rasco Menu library
122+
Intersting WASDMenuAPI
123+
xWidovV Admin menu
124+
Constummer Simple Guns Menu
125+
daffyy Simple Admin
126+
verneri Player votes
127+
schwarper CS2MenuManager
128+
ln(x) CS2 RTV/Extend/MapChooser
129+
T3Marius ScreenMenusAPI
130+
Mesharsky VIP manager
131+
-->

package.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,20 @@ pushd "$dst"
5050
7z a ../UniversalMenu.Driver.ScreenMenuAPI.zip ./
5151
popd
5252
rm -rf "$dst"
53+
54+
55+
# build UniversalMenu.Driver.MenuManagerApi.zip
56+
dst="./artifacts/UniversalMenu.Driver.MenuManagerApi"
57+
dst_shared="$dst/addons/counterstrikesharp/shared"
58+
dst_plugins="$dst/addons/counterstrikesharp/plugins"
59+
60+
# package UniversalMenu.Driver.MenuManagerApi
61+
mkdir -p "$dst_plugins/UniversalMenu.Driver.MenuManagerApi"
62+
src="./src/UniversalMenu.Driver.MenuManagerApi/bin/Release/net8.0/publish"
63+
cp -r "$src/." "$dst_plugins/UniversalMenu.Driver.MenuManagerApi/"
64+
65+
# zip UniversalMenu.Driver.MenuManagerApi.zip
66+
pushd "$dst"
67+
7z a ../UniversalMenu.Driver.MenuManagerApi.zip ./
68+
popd
69+
rm -rf "$dst"
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
using System;
2+
using System.Threading;
3+
using System.Collections.Generic;
4+
5+
using CounterStrikeSharp.API.Core;
6+
7+
using CSSUniversalMenuAPI;
8+
using CSSUniversalMenuAPI.Extensions;
9+
10+
using IMenuManagerApi = MenuManager.IMenuApi;
11+
using IMenuManagerMenu = CounterStrikeSharp.API.Modules.Menu.IMenu;
12+
using IMenu = CSSUniversalMenuAPI.IMenu;
13+
14+
namespace UniversalMenu.Driver.MenuManagerApi;
15+
16+
internal class PlayerMenuState
17+
{
18+
public Menu? ActiveMenu { get; set; }
19+
}
20+
21+
public sealed class MenuManagerApiDriver : IMenuAPI
22+
{
23+
internal MenuManagerApiDriverPlugin Plugin { get; }
24+
internal IMenuManagerApi? MenuManagerApi { get; set; }
25+
26+
public MenuManagerApiDriver(MenuManagerApiDriverPlugin plugin)
27+
{
28+
Plugin = plugin;
29+
}
30+
31+
private Dictionary<ulong, PlayerMenuState> MenuStates = new();
32+
internal PlayerMenuState GetMenuState(CCSPlayerController player)
33+
{
34+
if (!MenuStates.TryGetValue(player.SteamID, out var menuState))
35+
MenuStates.Add(player.SteamID, menuState = new());
36+
return menuState;
37+
}
38+
internal void PlayerDisconnected(ulong steamId)
39+
{
40+
MenuStates.Remove(steamId);
41+
}
42+
43+
IMenu IMenuAPI.CreateMenu(CCSPlayerController player, CancellationToken ct)
44+
{
45+
return new Menu()
46+
{
47+
MenuAPI = this,
48+
Player = player,
49+
Parent = null,
50+
};
51+
}
52+
53+
IMenu IMenuAPI.CreateMenu(IMenu parent, CancellationToken ct)
54+
{
55+
if (parent is not Menu parentMenu)
56+
throw new ArgumentException("Menu given belongs to another menu implementation", nameof(parent));
57+
58+
return new Menu()
59+
{
60+
MenuAPI = this,
61+
Player = parent.Player,
62+
Parent = parentMenu,
63+
};
64+
}
65+
66+
bool IMenuAPI.IsExtensionSupported(Type extension)
67+
{
68+
if (extension == typeof(INavigateBackMenuExtension))
69+
return true;
70+
return false;
71+
}
72+
73+
bool IMenuAPI.IsMenuOpen(CCSPlayerController player)
74+
{
75+
return MenuManagerApi?.HasOpenedMenu(player) ?? false;
76+
}
77+
}
78+
79+
internal class Menu : IMenu, INavigateBackMenuExtension
80+
{
81+
public required MenuManagerApiDriver MenuAPI { get; set; }
82+
83+
// IMenu
84+
public required Menu? Parent { get; init; }
85+
IMenu? IMenu.Parent => Parent;
86+
public required CCSPlayerController Player { get; init; }
87+
public bool PlayerCanClose { get; set; } = true;
88+
public bool IsActive { get; private set; }
89+
public string Title { get; set; } = string.Empty;
90+
91+
// ScreenMenuAPI
92+
internal IMenuManagerMenu? TheMenu { get; set; }
93+
private List<MenuItem> MenuItems { get; } = new();
94+
public Action<IMenu>? NavigateBack { get; set; }
95+
96+
void IMenu.Close()
97+
{
98+
if (!IsActive)
99+
return;
100+
IsActive = false;
101+
102+
var state = MenuAPI.GetMenuState(Player);
103+
if (this == state.ActiveMenu)
104+
{
105+
MenuAPI.MenuManagerApi.CloseMenu(Player);
106+
state.ActiveMenu = null;
107+
}
108+
}
109+
110+
IMenuItem IMenu.CreateItem()
111+
{
112+
var ret = new MenuItem() { Menu = this };
113+
MenuItems.Add(ret);
114+
return ret;
115+
}
116+
117+
void IMenu.Display()
118+
{
119+
if (MenuAPI.MenuManagerApi is null)
120+
throw new Exception("MenuManagerApi not found");
121+
122+
IsActive = true;
123+
if (TheMenu is not null)
124+
{
125+
TheMenu.Open(Player);
126+
return;
127+
}
128+
129+
Action<CCSPlayerController>? navBack = null;
130+
if (NavigateBack is not null)
131+
navBack = (player) => NavigateBack(this);
132+
133+
TheMenu = MenuAPI.MenuManagerApi.GetMenu(Title, back_action: navBack!);
134+
135+
foreach (var item in MenuItems)
136+
TheMenu.AddMenuOption(item.Title, (player, option) => item.RaiseSelected(), !item.Enabled);
137+
138+
TheMenu.Open(Player);
139+
}
140+
}
141+
142+
internal class MenuItem : IMenuItem
143+
{
144+
public required IMenu Menu { get; init; }
145+
public string Title { get; set; } = string.Empty;
146+
public bool Enabled { get; set; } = true;
147+
public object? Context { get; set; }
148+
149+
public event ItemSelectedAction? Selected;
150+
internal void RaiseSelected()
151+
{
152+
Selected?.Invoke(this);
153+
}
154+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Threading;
3+
4+
using CounterStrikeSharp.API.Core;
5+
using CounterStrikeSharp.API.Core.Attributes;
6+
using CounterStrikeSharp.API.Core.Attributes.Registration;
7+
using CounterStrikeSharp.API.Core.Capabilities;
8+
9+
using IMenuManagerApi = MenuManager.IMenuApi;
10+
11+
namespace UniversalMenu.Driver.MenuManagerApi;
12+
13+
[MinimumApiVersion(314)]
14+
public class MenuManagerApiDriverPlugin : BasePlugin
15+
{
16+
public override string ModuleName => "UniversalMenu.DefaultDriver.MenuManagerApi";
17+
public override string ModuleDescription => "Implement CSSUniversalMenuAPI via MenuManagerApi";
18+
public override string ModuleVersion => Verlite.Version.Full;
19+
20+
internal CancellationTokenSource Cts { get; set; } = null!;
21+
private MenuManagerApiDriver? DriverInstance { get; set; }
22+
private static readonly PluginCapability<IMenuManagerApi> MenuCapability = new("menu:nfcore");
23+
24+
public override void Load(bool hotReload)
25+
{
26+
Cts = new CancellationTokenSource();
27+
DriverInstance = new MenuManagerApiDriver(this);
28+
CSSUniversalMenuAPI.UniversalMenu.RegisterDriver("MenuManagerApi", DriverInstance);
29+
}
30+
31+
public override void Unload(bool hotReload)
32+
{
33+
Cts.Cancel();
34+
CSSUniversalMenuAPI.UniversalMenu.UnregisterDriver("MenuManagerApi");
35+
}
36+
37+
public override void OnAllPluginsLoaded(bool hotReload)
38+
{
39+
DriverInstance!.MenuManagerApi = MenuCapability.Get();
40+
}
41+
42+
[GameEventHandler(HookMode.Pre)]
43+
public HookResult OnPlayerDisconnect(EventPlayerDisconnect e, GameEventInfo info)
44+
{
45+
if (e.Userid is null)
46+
return HookResult.Continue;
47+
48+
DriverInstance?.PlayerDisconnected(e.Userid.SteamID);
49+
return HookResult.Continue;
50+
}
51+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<RootNamespace>UniversalMenu.Driver.MenuManagerApi</RootNamespace>
5+
</PropertyGroup>
6+
7+
<ItemGroup>
8+
<ProjectReference Include="..\CSSUniversalMenuAPI\CSSUniversalMenuAPI.csproj">
9+
<Private>False</Private>
10+
<CopyLocalSatelliteAssemblies>False</CopyLocalSatelliteAssemblies>
11+
</ProjectReference>
12+
13+
<Reference Include="MenuManagerApi">
14+
<Private>false</Private>
15+
<HintPath>..\..\thirdparty\MenuManagerApi\MenuManagerApi.dll</HintPath>
16+
</Reference>
17+
</ItemGroup>
18+
19+
</Project>

src/UniversalMenu.Driver.ScreenMenuAPI/ScreenMenuAPIDriverPlugin.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ public override void Unload(bool hotReload)
3434
CSSUniversalMenuAPI.UniversalMenu.UnregisterDriver("ScreenMenuAPI");
3535
}
3636

37+
[GameEventHandler(HookMode.Pre)]
38+
public HookResult OnPlayerDisconnected(EventPlayerDisconnect e, GameEventInfo info)
39+
{
40+
if (e.Userid is null)
41+
return HookResult.Continue;
42+
43+
DriverInstance?.PlayerDisconnected(e.Userid.SteamID);
44+
return HookResult.Continue;
45+
}
46+
3747
[ConsoleCommand("css_0"), ConsoleCommand("css_1"), ConsoleCommand("css_2"), ConsoleCommand("css_3"), ConsoleCommand("css_4")]
3848
[ConsoleCommand("css_5"), ConsoleCommand("css_6"), ConsoleCommand("css_7"), ConsoleCommand("css_8"), ConsoleCommand("css_9")]
3949
[ConsoleCommand("css_screenmenu_bound_buttons")]

0 commit comments

Comments
 (0)