1+ using System ;
2+ using System . Collections . Generic ;
3+ using System . Linq ;
4+
5+ using AngleSharp . Dom ;
6+ using AngleSharp . Html . Parser ;
7+
18using CounterStrikeSharp . API . Core ;
29using CounterStrikeSharp . API . Core . Attributes . Registration ;
10+ using CounterStrikeSharp . API . Modules . Menu ;
11+
12+ using CSSUniversalMenuAPI ;
13+ using CSSUniversalMenuAPI . Extensions ;
14+
15+ using HarmonyLib ;
16+
17+ using IUniversalMenu = CSSUniversalMenuAPI . IMenu ;
318
419namespace UniversalMenu . Compat . CSSharp ;
520
@@ -10,21 +25,135 @@ public class CSSharpCompatPlugin : BasePlugin
1025
1126 public override void Load ( bool hotReload )
1227 {
13- CSSharpCompatPluginShared . Patch ( ) ;
28+ Harmony = new Harmony ( "com.universalmenu.compat.cssharp" ) ;
29+
30+ {
31+ var original = AccessTools . Method ( typeof ( MenuManager ) , nameof ( MenuManager . OpenCenterHtmlMenu ) ) ;
32+ var pre = SymbolExtensions . GetMethodInfo ( ( ) => MenuManager_OpenCenterHtmlMenu ( null ! , null ! , null ! ) ) ;
33+ Harmony . Patch ( original , prefix : new HarmonyMethod ( pre ) ) ;
34+ }
35+
36+ {
37+ var original = AccessTools . Method ( typeof ( MenuManager ) , nameof ( MenuManager . OpenChatMenu ) ) ;
38+ var pre = SymbolExtensions . GetMethodInfo ( ( ) => MenuManager_OpenChatMenu ( null ! , null ! ) ) ;
39+ Harmony . Patch ( original , prefix : new HarmonyMethod ( pre ) ) ;
40+ }
41+
42+ {
43+ var original = AccessTools . Method ( typeof ( MenuManager ) , nameof ( MenuManager . OpenConsoleMenu ) ) ;
44+ var pre = SymbolExtensions . GetMethodInfo ( ( ) => MenuManager_OpenConsoleMenu ( null ! , null ! ) ) ;
45+ Harmony . Patch ( original , prefix : new HarmonyMethod ( pre ) ) ;
46+ }
47+
48+ {
49+ var original = AccessTools . Method ( typeof ( MenuManager ) , nameof ( MenuManager . CloseActiveMenu ) ) ;
50+ var pre = SymbolExtensions . GetMethodInfo ( ( ) => MenuManager_CloseActiveMenu ( null ! ) ) ;
51+ Harmony . Patch ( original , prefix : new HarmonyMethod ( pre ) ) ;
52+ }
1453 }
1554
1655 public override void Unload ( bool hotReload )
1756 {
18- CSSharpCompatPluginShared . Unpatch ( ) ;
57+ Harmony ? . UnpatchAll ( ) ;
1958 }
2059
60+ private static Harmony ? Harmony { get ; set ; }
61+ private static Dictionary < nint , IUniversalMenu > ActiveMenus { get ; } = new ( ) ;
62+
2163 [ GameEventHandler ( HookMode . Pre ) ]
2264 public HookResult OnPlayerDisconnect ( EventPlayerDisconnect e , GameEventInfo info )
2365 {
2466 if ( e . Userid is null )
2567 return HookResult . Continue ;
2668
27- CSSharpCompatPluginShared . PlayerDisconnected ( e . Userid ) ;
69+ ActiveMenus . Remove ( e . Userid . Handle ) ;
2870 return HookResult . Continue ;
2971 }
72+
73+ public static bool BaseMenu_Open ( BasePlugin ? plugin , CCSPlayerController player , BaseMenu menu )
74+ {
75+ // this API assumes there may only be 1 menu at a time, so tell the implementation
76+ // that this menu is expected to be closed
77+ if ( ActiveMenus . TryGetValue ( player . Handle , out var activeMenu ) )
78+ {
79+ ActiveMenus . Remove ( player . Handle ) ;
80+ activeMenu . Close ( ) ;
81+ }
82+
83+ var api = IMenuAPI . PluginCapability . Get ( ) ;
84+
85+ if ( api is null ) // fall back to builtin menu
86+ return true ;
87+
88+ var newMenu = api . CreateMenu ( player ) ;
89+ newMenu . PlayerCanClose = menu . ExitButton ;
90+
91+ var useHtml = false ;
92+ if ( newMenu is IHtmlSupportMenuExtension htmlMenu )
93+ htmlMenu . UseHtml = useHtml = true ;
94+
95+ if ( useHtml )
96+ newMenu . Title = menu . Title ;
97+ else
98+ newMenu . Title = StripHtml ( menu . Title ) ;
99+
100+ foreach ( var item in menu . MenuOptions )
101+ {
102+ var newItem = newMenu . CreateItem ( ) ;
103+ newItem . Enabled = ! item . Disabled ;
104+
105+ if ( useHtml )
106+ newItem . Title = item . Text ;
107+ else
108+ newItem . Title = StripHtml ( item . Text ) ;
109+
110+ if ( item . OnSelect is not null )
111+ newItem . Selected += ( selectedItem ) =>
112+ {
113+ item . OnSelect ( player , item ) ;
114+ if ( menu . PostSelectAction == PostSelectAction . Close )
115+ {
116+ if ( ActiveMenus . TryGetValue ( player . Handle , out var activeMenu ) && activeMenu == newMenu )
117+ ActiveMenus . Remove ( player . Handle ) ;
118+ newMenu . Close ( ) ;
119+ }
120+ } ;
121+ }
122+
123+ ActiveMenus [ player . Handle ] = newMenu ;
124+ newMenu . Display ( ) ;
125+ return false ;
126+ }
127+
128+ public static bool MenuManager_CloseActiveMenu ( CCSPlayerController player )
129+ {
130+ if ( ActiveMenus . TryGetValue ( player . Handle , out var activeMenu ) )
131+ {
132+ ActiveMenus . Remove ( player . Handle ) ;
133+ activeMenu . Close ( ) ;
134+ }
135+ return true ;
136+ }
137+
138+ public static bool MenuManager_OpenCenterHtmlMenu ( BasePlugin plugin , CCSPlayerController player , CenterHtmlMenu menu )
139+ {
140+ return BaseMenu_Open ( plugin , player , menu ) ;
141+ }
142+
143+ public static bool MenuManager_OpenChatMenu ( CCSPlayerController player , ChatMenu menu )
144+ {
145+ return BaseMenu_Open ( null , player , menu ) ;
146+ }
147+
148+ public static bool MenuManager_OpenConsoleMenu ( CCSPlayerController player , ConsoleMenu menu )
149+ {
150+ return BaseMenu_Open ( null , player , menu ) ;
151+ }
152+
153+ private static readonly HtmlParser HtmlParser = new ( new HtmlParserOptions ( ) { IsStrictMode = false } ) ;
154+ private static string StripHtml ( string input )
155+ {
156+ var doc = HtmlParser . ParseFragment ( input , null ! ) ;
157+ return string . Join ( string . Empty , doc . Select ( x => x . Text ( ) ) ) ;
158+ }
30159}
0 commit comments