Skip to content

Commit 38af2a4

Browse files
authored
Merge pull request #16 from schwarper/MenuTypeScreenMenu
feat(menu): add MenuType support to ScreenMenu fix(menu): resolve issue where ScreenMenu would remain player frozen when closed
2 parents 741319e + f93d2b6 commit 38af2a4

6 files changed

Lines changed: 135 additions & 45 deletions

File tree

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ jobs:
6565
mkdir -p release
6666
cd BuildOutput
6767
# Create zip, excluding .nupkg and .xml files
68-
zip -r ../CS2MenuManager-v${{ env.BUILD_NUMBER }}-${{ env.GITHUB_SHA_SHORT }}.zip * --exclude '*.nupkg' '*.xml'
68+
zip -r ../CS2MenuManager-v${{ env.BUILD_NUMBER }}.zip * --exclude '*.nupkg' '*.xml'
6969
7070
- name: Create GitHub Release
7171
id: create_release

API/Class/BaseMenu.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ public virtual void Display() { }
210210
/// </summary>
211211
/// <param name="player">The player who pressed the key.</param>
212212
/// <param name="key">The key that was pressed.</param>
213-
public void OnKeyPress(CCSPlayerController player, int key)
213+
public virtual void OnKeyPress(CCSPlayerController player, int key)
214214
{
215215
if (player.Handle != Player.Handle)
216216
return;
@@ -233,7 +233,7 @@ public void OnKeyPress(CCSPlayerController player, int key)
233233
}
234234
}
235235

236-
private void HandleMenuItemSelection(int key)
236+
internal void HandleMenuItemSelection(int key)
237237
{
238238
int menuItemIndex = CurrentOffset + key - 1;
239239
if (menuItemIndex < 0 || menuItemIndex >= Menu.ItemOptions.Count) return;
@@ -247,10 +247,8 @@ private void HandleMenuItemSelection(int key)
247247

248248
internal void RegisterOnKeyPress()
249249
{
250-
if (Menu is WasdMenu or ScreenMenu)
251-
{
250+
if (Menu is WasdMenu || (Menu is ScreenMenu screenMenu && screenMenu.MenuType == MenuType.Scrollable))
252251
return;
253-
}
254252

255253
for (int i = 0; i <= 9; i++)
256254
{
@@ -271,15 +269,21 @@ void _func(CCSPlayerController? player, CommandInfo info)
271269

272270
internal void DeregisterOnKeyPress()
273271
{
274-
if (Menu is WasdMenu or ScreenMenu)
272+
if (Menu is WasdMenu || (Menu is ScreenMenu screenMenu && screenMenu.MenuType == MenuType.Scrollable))
275273
return;
276274

277275
foreach (KeyValuePair<string, CommandCallback> kvp in _keyCommands)
278-
Menu.Plugin.RemoveCommand(kvp.Key, kvp.Value);
276+
{
277+
if (_keyCommands.ContainsKey(kvp.Key))
278+
{
279+
Menu.Plugin.RemoveCommand(kvp.Key, kvp.Value);
280+
}
281+
}
279282

280283
_keyCommands.Clear();
281284
}
282285

286+
283287
internal void RegisterPlayerDisconnectEvent()
284288
{
285289
Menu.Plugin.RegisterEventHandler<EventPlayerDisconnect>(OnPlayerDisconnect);

API/Class/Config.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ public class Cfg
6565
Font = "Arial Bold",
6666
Size = 32,
6767
FreezePlayer = false,
68-
ShowResolutionsOption = true
68+
ShowResolutionsOption = true,
69+
MenuType = "Both"
6970
};
7071
public Dictionary<string, Resolution> Resolutions { get; set; } = [];
7172
public Dictionary<string, Dictionary<string, string>> Lang { get; set; } = [];
@@ -137,6 +138,7 @@ public class ScreenMenu
137138
public int Size { get; set; }
138139
public bool FreezePlayer { get; set; }
139140
public bool ShowResolutionsOption { get; set; }
141+
public string MenuType { get; set; } = string.Empty;
140142
}
141143

142144
public static Cfg Config { get; set; } = new();

API/Enum/MenuType.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
namespace CS2MenuManager.API.Enum;
2+
3+
/// <summary>
4+
/// Defines the types of menus.
5+
/// </summary>
6+
public enum MenuType
7+
{
8+
/// <summary>
9+
/// A scrollable menu type.
10+
/// </summary>
11+
Scrollable,
12+
13+
/// <summary>
14+
/// A menu type controlled by key presses.
15+
/// </summary>
16+
KeyPress,
17+
18+
/// <summary>
19+
/// A menu type that supports both scrolling and key presses.
20+
/// </summary>
21+
Both
22+
}

API/Menu/ScreenMenu.cs

Lines changed: 97 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ public class ScreenMenu(string title, BasePlugin plugin) : BaseMenu(title, plugi
7575
/// </summary>
7676
public string SelectKey { get; set; } = Config.Buttons.Select;
7777

78+
/// <summary>
79+
/// Defines the types of menus.
80+
/// </summary>
81+
public MenuType MenuType { get; set; } = Config.ScreenMenu.MenuType switch
82+
{
83+
string text when text.Length > 0 && char.ToLower(text[0]) == 's' => MenuType.Scrollable,
84+
string text when text.Length > 0 && char.ToLower(text[0]) == 'k' => MenuType.KeyPress,
85+
_ => MenuType.Both
86+
};
87+
7888
/// <summary>
7989
/// Displays the menu to the specified player for a specified duration.
8090
/// </summary>
@@ -126,17 +136,20 @@ public ScreenMenuInstance(CCSPlayerController player, IMenu menu) : base(player,
126136
if (Menu is not ScreenMenu screenMenu)
127137
return;
128138

139+
if (screenMenu.MenuType != MenuType.KeyPress)
140+
{
141+
Buttons = new Dictionary<string, Action>()
142+
{
143+
{ screenMenu.ScrollUpKey, ScrollUp },
144+
{ screenMenu.ScrollDownKey, ScrollDown },
145+
{ screenMenu.SelectKey, Choose },
146+
};
147+
}
148+
129149
Menu.Plugin.RegisterListener<OnTick>(OnTick);
130150
Menu.Plugin.RegisterListener<CheckTransmit>(OnCheckTransmit);
131151
Menu.Plugin.RegisterListener<OnEntityDeleted>(OnEntityDeleted);
132152
if (screenMenu.FreezePlayer) Player.Freeze();
133-
134-
Buttons = new Dictionary<string, Action>()
135-
{
136-
{ screenMenu.ScrollUpKey, ScrollUp },
137-
{ screenMenu.ScrollDownKey, ScrollDown },
138-
{ screenMenu.SelectKey, Choose },
139-
};
140153
}
141154

142155
/// <summary>
@@ -172,14 +185,24 @@ public override void Display()
172185
builder.AppendLine(" ");
173186

174187
(string text, int _) = visibleOptions[i];
175-
string displayLine = (i == CurrentChoiceIndex) ? $"> {text}" : $" {text}";
188+
189+
string displayLine = screenMenu.MenuType switch
190+
{
191+
MenuType.KeyPress => text,
192+
MenuType.Scrollable or MenuType.Both => (i == CurrentChoiceIndex) ? $"> {text}" : $" {text}",
193+
_ => string.Empty
194+
};
195+
176196
builder.AppendLine(displayLine);
177197
}
178198

179-
builder.AppendLine(" ");
180-
builder.AppendLine(Player.Localizer("ScrollKey", screenMenu.ScrollUpKey, screenMenu.ScrollDownKey));
181-
builder.AppendLine(Player.Localizer("SelectKey", screenMenu.SelectKey));
182-
builder.AppendLine(" ");
199+
if (screenMenu.MenuType != MenuType.KeyPress)
200+
{
201+
builder.AppendLine(" ");
202+
builder.AppendLine(Player.Localizer("ScrollKey", screenMenu.ScrollUpKey, screenMenu.ScrollDownKey));
203+
builder.AppendLine(Player.Localizer("SelectKey", screenMenu.SelectKey));
204+
builder.AppendLine(" ");
205+
}
183206

184207
if (WorldText == null || !WorldText.IsValid)
185208
WorldText = CreateWorldText(builder.ToString(), screenMenu.Size, screenMenu.TextColor, screenMenu.Font, screenMenu.Background, screenMenu.BackgroundHeight, screenMenu.BackgroundWidth);
@@ -201,29 +224,32 @@ public override void Close()
201224
Menu.Plugin.RemoveListener<OnEntityDeleted>(OnEntityDeleted);
202225

203226
if (WorldText != null && WorldText.IsValid) WorldText.Remove();
204-
if (((ScreenMenu)Menu).FreezePlayer) Player.Freeze();
227+
if (((ScreenMenu)Menu).FreezePlayer) Player.Unfreeze();
205228

206229
if (!string.IsNullOrEmpty(Config.Sound.Exit))
207230
Player.ExecuteClientCommand($"play {Config.Sound.Exit}");
208231
}
209232

210233
private void OnTick()
211234
{
212-
PlayerButtons button = Player.Buttons;
213-
214-
foreach (KeyValuePair<string, Action> kvp in Buttons)
235+
if (((ScreenMenu)Menu).MenuType != MenuType.KeyPress)
215236
{
216-
if (ButtonMapping.TryGetValue(kvp.Key, out PlayerButtons buttonMappingButton))
237+
PlayerButtons button = Player.Buttons;
238+
239+
foreach (KeyValuePair<string, Action> kvp in Buttons)
217240
{
218-
if ((button & buttonMappingButton) == 0 && (OldButton & buttonMappingButton) != 0)
241+
if (ButtonMapping.TryGetValue(kvp.Key, out PlayerButtons buttonMappingButton))
219242
{
220-
kvp.Value.Invoke();
221-
break;
243+
if ((button & buttonMappingButton) == 0 && (OldButton & buttonMappingButton) != 0)
244+
{
245+
kvp.Value.Invoke();
246+
break;
247+
}
222248
}
223249
}
224-
}
225250

226-
OldButton = button;
251+
OldButton = button;
252+
}
227253

228254
if (WorldText != null)
229255
{
@@ -266,6 +292,35 @@ private void ScrollUp()
266292
Player.ExecuteClientCommand($"play {Config.Sound.ScrollUp}");
267293
}
268294

295+
/// <summary>
296+
/// Handles key press events for the menu.
297+
/// </summary>
298+
/// <param name="player">The player who pressed the key.</param>
299+
/// <param name="key">The key that was pressed.</param>
300+
public override void OnKeyPress(CCSPlayerController player, int key)
301+
{
302+
switch (key)
303+
{
304+
case 7 when ((ScreenMenu)Menu).ShowResolutionsOption:
305+
Close();
306+
ResolutionMenu(Player, Menu.Plugin, Menu).Display(Player, 0);
307+
break;
308+
case 8 when HasPrevButton:
309+
if (Page > 0) PrevPage();
310+
else PrevSubMenu();
311+
break;
312+
case 9 when HasNextButton:
313+
NextPage();
314+
break;
315+
case 0 when HasExitButton:
316+
Close();
317+
break;
318+
default:
319+
HandleMenuItemSelection(key);
320+
break;
321+
}
322+
}
323+
269324
private void Choose()
270325
{
271326
List<(string Text, int GlobalIndex)> visibleOptions = GetVisibleOptions();
@@ -283,22 +338,27 @@ private void Choose()
283338
case -3: Close(); return;
284339
case -4: Close(); ResolutionMenu(Player, Menu.Plugin, Menu).Display(Player, 0); return;
285340
default:
286-
ItemOption option = Menu.ItemOptions[globalIndex];
341+
HandleOption(globalIndex);
342+
break;
343+
}
344+
}
287345

288-
if (option.DisableOption != DisableOption.None)
289-
{
290-
Player.PrintToChat(Player.Localizer("WarnDisabledItem").ReplaceColorTags());
291-
return;
292-
}
346+
private void HandleOption(int globalIndex)
347+
{
348+
ItemOption option = Menu.ItemOptions[globalIndex];
293349

294-
option.OnSelect?.Invoke(Player, option);
350+
if (option.DisableOption != DisableOption.None)
351+
{
352+
Player.PrintToChat(Player.Localizer("WarnDisabledItem").ReplaceColorTags());
353+
return;
354+
}
295355

296-
if (!string.IsNullOrEmpty(Config.Sound.Select))
297-
Player.ExecuteClientCommand($"play {Config.Sound.Select}");
356+
option.OnSelect?.Invoke(Player, option);
298357

299-
Close();
300-
break;
301-
}
358+
if (!string.IsNullOrEmpty(Config.Sound.Select))
359+
Player.ExecuteClientCommand($"play {Config.Sound.Select}");
360+
361+
Close();
302362
}
303363

304364
private List<(string Text, int GlobalIndex)> GetVisibleOptions()
@@ -324,7 +384,7 @@ private void Choose()
324384
visible.Add((text, i));
325385
}
326386

327-
if (((ScreenMenu)Menu).ShowResolutionsOption) visible.Add(($"!{displayNumber++}. {Player.Localizer("SelectResolution")}\n", -4));
387+
if (((ScreenMenu)Menu).ShowResolutionsOption) visible.Add(($"{displayNumber++}. {Player.Localizer("SelectResolution")}\n", -4));
328388
if (HasPrevButton) visible.Add(($"8. {Player.Localizer("Prev")}", -2));
329389
if (HasNextButton) visible.Add(($"9. {Player.Localizer("Next")}", -1));
330390
if (HasExitButton) visible.Add(($"0. {Player.Localizer("Exit")}", -3));
@@ -351,11 +411,12 @@ private void OnEntityDeleted(CEntityInstance entity)
351411
Close();
352412
}
353413

354-
private static ScreenMenu ResolutionMenu(CCSPlayerController player, BasePlugin plugin, IMenu prevMenu)
414+
private ScreenMenu ResolutionMenu(CCSPlayerController player, BasePlugin plugin, IMenu prevMenu)
355415
{
356416
ScreenMenu menu = new(player.Localizer("SelectResolution"), plugin)
357417
{
358418
ShowResolutionsOption = false,
419+
MenuType = ((ScreenMenu)Menu).MenuType
359420
};
360421

361422
foreach (KeyValuePair<string, Resolution> resolution in Config.Resolutions)

config.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ Font = "Arial Bold"
5353
Size = 32
5454
FreezePlayer = false
5555
ShowResolutionsOption = true
56+
MenuType = "Both" // Supported Scrollable, KeyPress, Both
5657

5758
[Resolutions]
5859
"1920x1080" = { PositionX = -9.0, PositionY = 0.0 }

0 commit comments

Comments
 (0)