Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CSSUniversalMenuAPI.sln
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProofOfConcepts", "tests\Pr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalMenu.Compat.MenuManagerApi", "src\UniversalMenu.Compat.MenuManagerApi\UniversalMenu.Compat.MenuManagerApi.csproj", "{44AAF649-62D6-1CD8-3F16-028F4D262BE6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalMenu.Compat.ScreenMenuAPI", "src\UniversalMenu.Compat.ScreenMenuAPI\UniversalMenu.Compat.ScreenMenuAPI.csproj", "{B5AB3AB6-5BB6-0154-27DF-61D9EE587806}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalMenu.Driver.ScreenMenuAPI", "src\UniversalMenu.Driver.ScreenMenuAPI\UniversalMenu.Driver.ScreenMenuAPI.csproj", "{E2FD83DD-D7EA-97CA-B6F4-DE2F92E5A00F}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub Actions", "GitHub Actions", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
Expand All @@ -37,6 +39,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub Actions", "GitHub Ac
.github\shared.yml = .github\shared.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalMenu.Compat.CSSharp", "src\UniversalMenu.Compat.CSSharp\UniversalMenu.Compat.CSSharp.csproj", "{EF2866D7-C411-42ED-B5E0-DCE79CCFCA09}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UniversalMenu.Compat.CSSharp.Shared", "src\UniversalMenu.Compat.CSSharp.Shared\UniversalMenu.Compat.CSSharp.Shared.csproj", "{6ADB7AC3-E7F1-4BAB-A323-633932EBB322}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -59,10 +65,22 @@ Global
{44AAF649-62D6-1CD8-3F16-028F4D262BE6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44AAF649-62D6-1CD8-3F16-028F4D262BE6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44AAF649-62D6-1CD8-3F16-028F4D262BE6}.Release|Any CPU.Build.0 = Release|Any CPU
{B5AB3AB6-5BB6-0154-27DF-61D9EE587806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B5AB3AB6-5BB6-0154-27DF-61D9EE587806}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B5AB3AB6-5BB6-0154-27DF-61D9EE587806}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B5AB3AB6-5BB6-0154-27DF-61D9EE587806}.Release|Any CPU.Build.0 = Release|Any CPU
{E2FD83DD-D7EA-97CA-B6F4-DE2F92E5A00F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2FD83DD-D7EA-97CA-B6F4-DE2F92E5A00F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2FD83DD-D7EA-97CA-B6F4-DE2F92E5A00F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2FD83DD-D7EA-97CA-B6F4-DE2F92E5A00F}.Release|Any CPU.Build.0 = Release|Any CPU
{EF2866D7-C411-42ED-B5E0-DCE79CCFCA09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EF2866D7-C411-42ED-B5E0-DCE79CCFCA09}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EF2866D7-C411-42ED-B5E0-DCE79CCFCA09}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EF2866D7-C411-42ED-B5E0-DCE79CCFCA09}.Release|Any CPU.Build.0 = Release|Any CPU
{6ADB7AC3-E7F1-4BAB-A323-633932EBB322}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6ADB7AC3-E7F1-4BAB-A323-633932EBB322}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6ADB7AC3-E7F1-4BAB-A323-633932EBB322}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6ADB7AC3-E7F1-4BAB-A323-633932EBB322}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
14 changes: 14 additions & 0 deletions package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ mkdir -p "$dst_plugins/UniversalMenu.Compat.MenuManagerApi"
src="./src/UniversalMenu.Compat.MenuManagerApi/bin/Release/net8.0/publish"
cp -r "$src/." "$dst_plugins/UniversalMenu.Compat.MenuManagerApi/"

# package UniversalMenu.Compat.CSSharp
mkdir -p "$dst_plugins/UniversalMenu.Compat.CSSharp"
src="./src/UniversalMenu.Compat.CSSharp/bin/Release/net8.0/publish"
cp -r "$src/." "$dst_plugins/UniversalMenu.Compat.CSSharp/"
# shared part: allows modified methods to load the 0Harmony.dll dependency
mkdir -p "$dst_shared/UniversalMenu.Compat.CSSharp.Shared"
src="./src/UniversalMenu.Compat.CSSharp.Shared/bin/Release/net8.0/publish"
cp -r "$src/." "$dst_shared/UniversalMenu.Compat.CSSharp.Shared/"

# package UniversalMenu.Compat.ScreenMenuAPI # this isn't implemented yet
#mkdir -p "$dst_plugins/UniversalMenu.Compat.ScreenMenuAPI"
#src="./src/UniversalMenu.Compat.ScreenMenuAPI/bin/Release/net8.0/publish"
#cp -r "$src/." "$dst_shared/UniversalMenu.Compat.ScreenMenuAPI/"

# zip CSSUniversalMenuAPI.zip
pushd "$dst"
7z a ../CSSUniversalMenuAPI.zip ./
Expand Down
154 changes: 154 additions & 0 deletions src/UniversalMenu.Compat.CSSharp.Shared/CSSharpCompatPluginShared.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using System.Linq;

using AngleSharp.Dom;
using AngleSharp.Html.Parser;

using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Modules.Menu;

using CS2ScreenMenuAPI;

using CSSUniversalMenuAPI;
using CSSUniversalMenuAPI.Extensions;

using HarmonyLib;

using IUniversalMenu = CSSUniversalMenuAPI.IMenu;

namespace UniversalMenu.Compat.CSSharp;

public static class CSSharpCompatPluginShared
{
private static Harmony? Harmony { get; set; }
private static Dictionary<nint, IUniversalMenu> ActiveMenus { get; } = new();

public static void Patch()
{
Harmony = new Harmony("com.universalmenu.compat.cssharp");

{
var original = AccessTools.Method(typeof(MenuManager), nameof(MenuManager.OpenCenterHtmlMenu));
var pre = SymbolExtensions.GetMethodInfo(() => MenuManager_OpenCenterHtmlMenu(null!, null!, null!));
Harmony.Patch(original, prefix: new HarmonyMethod(pre));
}

{
var original = AccessTools.Method(typeof(MenuManager), nameof(MenuManager.OpenChatMenu));
var pre = SymbolExtensions.GetMethodInfo(() => MenuManager_OpenChatMenu(null!, null!));
Harmony.Patch(original, prefix: new HarmonyMethod(pre));
}

{
var original = AccessTools.Method(typeof(MenuManager), nameof(MenuManager.OpenConsoleMenu));
var pre = SymbolExtensions.GetMethodInfo(() => MenuManager_OpenConsoleMenu(null!, null!));
Harmony.Patch(original, prefix: new HarmonyMethod(pre));
}

{
var original = AccessTools.Method(typeof(MenuManager), nameof(MenuManager.CloseActiveMenu));
var pre = SymbolExtensions.GetMethodInfo(() => MenuManager_CloseActiveMenu(null!));
Harmony.Patch(original, prefix: new HarmonyMethod(pre));
}
}

public static void Unpatch()
{
Harmony?.UnpatchAll();
}

public static void PlayerDisconnected(CCSPlayerController player)
{
ActiveMenus.Remove(player.Handle);
}

public static bool BaseMenu_Open(BasePlugin? plugin, CCSPlayerController player, BaseMenu menu)
{
// this API assumes there may only be 1 menu at a time, so tell the implementation
// that this menu is expected to be closed
if (ActiveMenus.TryGetValue(player.Handle, out var activeMenu))
{
ActiveMenus.Remove(player.Handle);
activeMenu.Close();
}

var api = IMenuAPI.PluginCapability.Get();

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

var newMenu = api.CreateMenu(player);
newMenu.PlayerCanClose = menu.ExitButton;

var useHtml = false;
if (newMenu is IHtmlSupportMenuExtension htmlMenu)
htmlMenu.UseHtml = useHtml = true;

if (useHtml)
newMenu.Title = menu.Title;
else
newMenu.Title = StripHtml(menu.Title);

foreach (var item in menu.MenuOptions)
{
var newItem = newMenu.CreateItem();
newItem.Enabled = !item.Disabled;

if (useHtml)
newItem.Title = item.Text;
else
newItem.Title = StripHtml(item.Text);

if (item.OnSelect is not null)
newItem.Selected += (selectedItem) =>
{
item.OnSelect(player, item);
if (menu.PostSelectAction == PostSelectAction.Close)
{
if (ActiveMenus.TryGetValue(player.Handle, out var activeMenu) && activeMenu == newMenu)
ActiveMenus.Remove(player.Handle);
newMenu.Close();
}
};
}

ActiveMenus[player.Handle] = newMenu;
newMenu.Display();
return false;
}

public static bool MenuManager_CloseActiveMenu(CCSPlayerController player)
{
Console.WriteLine($"Close active menu 1");
if (ActiveMenus.TryGetValue(player.Handle, out var activeMenu))
{
Console.WriteLine($"Close active menu 2");
ActiveMenus.Remove(player.Handle);
activeMenu.Close();
}
return true;
}

public static bool MenuManager_OpenCenterHtmlMenu(BasePlugin plugin, CCSPlayerController player, CenterHtmlMenu menu)
{
return BaseMenu_Open(plugin, player, menu);
}

public static bool MenuManager_OpenChatMenu(CCSPlayerController player, ChatMenu menu)
{
return BaseMenu_Open(null, player, menu);
}

public static bool MenuManager_OpenConsoleMenu(CCSPlayerController player, ConsoleMenu menu)
{
return BaseMenu_Open(null, player, menu);
}

private static readonly HtmlParser HtmlParser = new(new HtmlParserOptions() { IsStrictMode = false });
private static string StripHtml(string input)
{
var doc = HtmlParser.ParseFragment(input, null!);
return string.Join(string.Empty, doc.Select(x => x.Text()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<RootNamespace>UniversalMenu.Compat.CSSharp</RootNamespace>
<OutputType>Library</OutputType>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\CSSUniversalMenuAPI\CSSUniversalMenuAPI.csproj">
<Private>False</Private>
<CopyLocalSatelliteAssemblies>False</CopyLocalSatelliteAssemblies>
</ProjectReference>
<PackageReference Include="AngleSharp" Version="1.2.0" />

<PackageReference Include="CS2ScreenMenuAPI" Version="3.0.4" ExcludeAssets="runtime" />
<PackageReference Include="Lib.Harmony" Version="2.3.6" />
</ItemGroup>

</Project>
30 changes: 30 additions & 0 deletions src/UniversalMenu.Compat.CSSharp/CSSharpCompatPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes.Registration;

namespace UniversalMenu.Compat.CSSharp;

public class CSSharpCompatPlugin : BasePlugin
{
public override string ModuleName => "UniversalMenu.Compat.CSSharp";
public override string ModuleVersion => Verlite.Version.Full;

public override void Load(bool hotReload)
{
CSSharpCompatPluginShared.Patch();
}

public override void Unload(bool hotReload)
{
CSSharpCompatPluginShared.Unpatch();
}

[GameEventHandler(HookMode.Pre)]
public HookResult OnPlayerDisconnect(EventPlayerDisconnect e, GameEventInfo info)
{
if (e.Userid is null)
return HookResult.Continue;

CSSharpCompatPluginShared.PlayerDisconnected(e.Userid);
return HookResult.Continue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<RootNamespace>UniversalMenu.Compat.CSSharp</RootNamespace>
<OutputType>Library</OutputType>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\CSSUniversalMenuAPI\CSSUniversalMenuAPI.csproj">
<Private>False</Private>
<CopyLocalSatelliteAssemblies>False</CopyLocalSatelliteAssemblies>
</ProjectReference>

<ProjectReference Include="..\UniversalMenu.Compat.CSSharp.Shared\UniversalMenu.Compat.CSSharp.Shared.csproj">
<Private>False</Private>
<CopyLocalSatelliteAssemblies>False</CopyLocalSatelliteAssemblies>
<ExcludeAssets>runtime</ExcludeAssets>
</ProjectReference>

<PackageReference Include="CS2ScreenMenuAPI" Version="3.0.4" ExcludeAssets="runtime" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<RootNamespace>UniversalMenu.Compat.ScreenMenuAPI</RootNamespace>
<OutputType>Library</OutputType>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\CSSUniversalMenuAPI\CSSUniversalMenuAPI.csproj">
<Private>False</Private>
<CopyLocalSatelliteAssemblies>False</CopyLocalSatelliteAssemblies>
</ProjectReference>

<PackageReference Include="CS2ScreenMenuAPI" Version="3.0.4" ExcludeAssets="runtime" />
</ItemGroup>

</Project>