Skip to content

Commit 0dded66

Browse files
committed
Fix closure issues in menus and update dependencies
Captured player and duration variables in menu callbacks to prevent closure-related bugs. Updated package versions in project files and bumped plugin version to 1.7.8-beta-5. Improved player validation and message localization logic.
1 parent 038641d commit 0dded66

File tree

10 files changed

+113
-88
lines changed

10 files changed

+113
-88
lines changed

CS2-SimpleAdmin/CS2-SimpleAdmin.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public partial class CS2_SimpleAdmin : BasePlugin, IPluginConfig<CS2_SimpleAdmin
2222
public override string ModuleName => "CS2-SimpleAdmin" + (Helper.IsDebugBuild ? " (DEBUG)" : " (RELEASE)");
2323
public override string ModuleDescription => "Simple admin plugin for Counter-Strike 2 :)";
2424
public override string ModuleAuthor => "daffyy & Dliix66";
25-
public override string ModuleVersion => "1.7.8-beta-4";
25+
public override string ModuleVersion => "1.7.8-beta-5";
2626

2727
public override void Load(bool hotReload)
2828
{

CS2-SimpleAdmin/CS2-SimpleAdmin.csproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,16 @@
1919
</PropertyGroup>
2020

2121
<ItemGroup>
22-
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.340">
22+
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.346">
2323
<PrivateAssets>none</PrivateAssets>
2424
<ExcludeAssets>runtime</ExcludeAssets>
2525
<IncludeAssets>compile; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2626
</PackageReference>
2727
<PackageReference Include="Dapper" Version="2.1.66" />
28-
<PackageReference Include="MySqlConnector" Version="2.4.0" />
28+
<PackageReference Include="MySqlConnector" Version="2.5.0-beta.1" />
2929
<PackageReference Include="System.Data.SQLite.Core" Version="1.0.119" />
30-
<PackageReference Include="System.Linq.Async" Version="6.0.3" />
31-
<PackageReference Include="ZLinq" Version="1.5.2" />
30+
<PackageReference Include="System.Linq.Async" Version="7.0.0-preview.1.g24680b5469" />
31+
<PackageReference Include="ZLinq" Version="1.5.3" />
3232
</ItemGroup>
3333

3434
<ItemGroup>

CS2-SimpleAdmin/Helper.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ public static List<CCSPlayerController> GetPlayerFromIp(string ipAddress)
6464

6565
public static List<CCSPlayerController> GetValidPlayers()
6666
{
67-
return CS2_SimpleAdmin.CachedPlayers.AsValueEnumerable().ToList();
67+
return CS2_SimpleAdmin.CachedPlayers.AsValueEnumerable().Where(p => p.Connected == PlayerConnectedState.PlayerConnected).ToList();
6868
}
6969

7070
public static List<CCSPlayerController> GetValidPlayersWithBots()
@@ -583,27 +583,32 @@ public static void ShowAdminActivityLocalized(IStringLocalizer moduleLocalizer,
583583
}
584584

585585
public static void DisplayCenterMessage(
586-
CCSPlayerController player,
587-
string messageKey,
588-
string? callerName = null,
586+
CCSPlayerController player,
587+
string messageKey,
588+
string? callerName = null,
589589
params object[] messageArgs)
590590
{
591591
if (CS2_SimpleAdmin._localizer == null) return;
592592

593+
// Determine the localized message key
593594
var localizedMessageKey = $"{messageKey}";
594595

595596
var formattedMessageArgs = messageArgs.Select(arg => arg?.ToString() ?? string.Empty).ToArray();
596597

598+
// Replace placeholder based on showActivityType
597599
for (var i = 0; i < formattedMessageArgs.Length; i++)
598600
{
599-
var arg = formattedMessageArgs[i];
601+
var arg = formattedMessageArgs[i]; // Convert argument to string if not null
602+
// Replace "CALLER" placeholder in the argument string
600603
formattedMessageArgs[i] = CS2_SimpleAdmin.Instance.Config.OtherSettings.ShowActivityType switch
601604
{
602605
1 => arg.Replace("CALLER", CS2_SimpleAdmin._localizer["sa_admin"]),
606+
2 => arg.Replace("CALLER", callerName ?? "Console"),
603607
_ => arg
604608
};
605609
}
606610

611+
// Print the localized message to the center of the screen for the player
607612
using (new WithTemporaryCulture(player.GetLanguage()))
608613
{
609614
player.PrintToCenter(CS2_SimpleAdmin._localizer[localizedMessageKey, formattedMessageArgs.Cast<object>().ToArray()]);

CS2-SimpleAdmin/Managers/PlayerManager.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,12 @@ public void CheckPlayersTimer()
364364
foreach (var player in bannedPlayers)
365365
{
366366
if (!player.UserId.HasValue) continue;
367-
await Server.NextWorldUpdateAsync(() => Helper.KickPlayer((int)player.UserId, NetworkDisconnectionReason.NETWORK_DISCONNECT_REJECT_BANNED));
367+
await Server.NextWorldUpdateAsync(() =>
368+
{
369+
if (Helper.GetPlayerFromSteamid64(player.SteamID) != null)
370+
Helper.KickPlayer((int)player.UserId,
371+
NetworkDisconnectionReason.NETWORK_DISCONNECT_REJECT_BANNED);
372+
});
368373
}
369374
}
370375

CS2-SimpleAdmin/Menus/BasicMenu.cs

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ private static MenuBuilder CreateSlapMenu(CCSPlayerController admin)
5757

5858
foreach (var player in players)
5959
{
60-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
61-
slapMenu.AddSubMenu(playerName, () => CreateSlapDamageMenu(admin, player));
60+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
61+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
62+
slapMenu.AddSubMenu(playerName, () => CreateSlapDamageMenu(admin, capturedPlayer));
6263
}
6364

6465
return slapMenu.WithBackButton();
@@ -112,12 +113,13 @@ private static MenuBuilder CreateSlayMenu(CCSPlayerController admin)
112113

113114
foreach (var player in players)
114115
{
115-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
116+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
117+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
116118
slayMenu.AddOption(playerName, _ =>
117119
{
118-
if (player.IsValid)
120+
if (capturedPlayer.IsValid)
119121
{
120-
CS2_SimpleAdmin.Slay(admin, player);
122+
CS2_SimpleAdmin.Slay(admin, capturedPlayer);
121123
}
122124
});
123125
}
@@ -139,13 +141,14 @@ private static MenuBuilder CreateKickMenu(CCSPlayerController admin)
139141

140142
foreach (var player in players)
141143
{
142-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
143-
kickMenu.AddSubMenu(playerName, () => CreateReasonMenu(admin, player, "Kick", PenaltyType.Kick,
144+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
145+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
146+
kickMenu.AddSubMenu(playerName, () => CreateReasonMenu(admin, capturedPlayer, "Kick", PenaltyType.Kick,
144147
(_, _, reason) =>
145148
{
146-
if (player.IsValid)
149+
if (capturedPlayer.IsValid)
147150
{
148-
CS2_SimpleAdmin.Instance.Kick(admin, player, reason, admin.PlayerName);
151+
CS2_SimpleAdmin.Instance.Kick(admin, capturedPlayer, reason, admin.PlayerName);
149152
}
150153
}));
151154
}
@@ -167,14 +170,15 @@ private static MenuBuilder CreateWarnMenu(CCSPlayerController admin)
167170

168171
foreach (var player in players)
169172
{
170-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
171-
warnMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Warn",
172-
(_, _, duration) => CreateReasonMenu(admin, player, "Warn", PenaltyType.Warn,
173+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
174+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
175+
warnMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, capturedPlayer, "Warn",
176+
(_, _, duration) => CreateReasonMenu(admin, capturedPlayer, "Warn", PenaltyType.Warn,
173177
(_, _, reason) =>
174178
{
175-
if (player.IsValid)
179+
if (capturedPlayer.IsValid)
176180
{
177-
CS2_SimpleAdmin.Instance.Warn(admin, player, duration, reason, admin.PlayerName);
181+
CS2_SimpleAdmin.Instance.Warn(admin, capturedPlayer, duration, reason, admin.PlayerName);
178182
}
179183
})));
180184
}
@@ -196,14 +200,15 @@ private static MenuBuilder CreateBanMenu(CCSPlayerController admin)
196200

197201
foreach (var player in players)
198202
{
199-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
200-
banMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Ban",
201-
(_, _, duration) => CreateReasonMenu(admin, player, "Ban", PenaltyType.Ban,
203+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
204+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
205+
banMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, capturedPlayer, "Ban",
206+
(_, _, duration) => CreateReasonMenu(admin, capturedPlayer, "Ban", PenaltyType.Ban,
202207
(_, _, reason) =>
203208
{
204-
if (player.IsValid)
209+
if (capturedPlayer.IsValid)
205210
{
206-
CS2_SimpleAdmin.Instance.Ban(admin, player, duration, reason, admin.PlayerName);
211+
CS2_SimpleAdmin.Instance.Ban(admin, capturedPlayer, duration, reason, admin.PlayerName);
207212
}
208213
})));
209214
}
@@ -225,14 +230,15 @@ private static MenuBuilder CreateGagMenu(CCSPlayerController admin)
225230

226231
foreach (var player in players)
227232
{
228-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
229-
gagMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Gag",
230-
(_, _, duration) => CreateReasonMenu(admin, player, "Gag", PenaltyType.Gag,
233+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
234+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
235+
gagMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, capturedPlayer, "Gag",
236+
(_, _, duration) => CreateReasonMenu(admin, capturedPlayer, "Gag", PenaltyType.Gag,
231237
(_, _, reason) =>
232238
{
233-
if (player.IsValid)
239+
if (capturedPlayer.IsValid)
234240
{
235-
CS2_SimpleAdmin.Instance.Gag(admin, player, duration, reason);
241+
CS2_SimpleAdmin.Instance.Gag(admin, capturedPlayer, duration, reason);
236242
}
237243
})));
238244
}
@@ -254,14 +260,15 @@ private static MenuBuilder CreateMuteMenu(CCSPlayerController admin)
254260

255261
foreach (var player in players)
256262
{
257-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
258-
muteMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Mute",
259-
(_, _, duration) => CreateReasonMenu(admin, player, "Mute", PenaltyType.Mute,
263+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
264+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
265+
muteMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, capturedPlayer, "Mute",
266+
(_, _, duration) => CreateReasonMenu(admin, capturedPlayer, "Mute", PenaltyType.Mute,
260267
(_, _, reason) =>
261268
{
262-
if (player.IsValid)
269+
if (capturedPlayer.IsValid)
263270
{
264-
CS2_SimpleAdmin.Instance.Mute(admin, player, duration, reason);
271+
CS2_SimpleAdmin.Instance.Mute(admin, capturedPlayer, duration, reason);
265272
}
266273
})));
267274
}
@@ -283,14 +290,15 @@ private static MenuBuilder CreateSilenceMenu(CCSPlayerController admin)
283290

284291
foreach (var player in players)
285292
{
286-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
287-
silenceMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, player, "Silence",
288-
(_, _, duration) => CreateReasonMenu(admin, player, "Silence", PenaltyType.Silence,
293+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
294+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
295+
silenceMenu.AddSubMenu(playerName, () => CreateDurationMenu(admin, capturedPlayer, "Silence",
296+
(_, _, duration) => CreateReasonMenu(admin, capturedPlayer, "Silence", PenaltyType.Silence,
289297
(_, _, reason) =>
290298
{
291-
if (player.IsValid)
299+
if (capturedPlayer.IsValid)
292300
{
293-
CS2_SimpleAdmin.Instance.Silence(admin, player, duration, reason);
301+
CS2_SimpleAdmin.Instance.Silence(admin, capturedPlayer, duration, reason);
294302
}
295303
})));
296304
}
@@ -312,8 +320,9 @@ private static MenuBuilder CreateForceTeamMenu(CCSPlayerController admin)
312320

313321
foreach (var player in players)
314322
{
315-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
316-
teamMenu.AddSubMenu(playerName, () => CreateTeamSelectionMenu(admin, player));
323+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
324+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
325+
teamMenu.AddSubMenu(playerName, () => CreateTeamSelectionMenu(admin, capturedPlayer));
317326
}
318327

319328
return teamMenu.WithBackButton();
@@ -488,8 +497,9 @@ private static MenuBuilder CreateAddAdminMenu(CCSPlayerController admin)
488497

489498
foreach (var player in players)
490499
{
491-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
492-
addAdminMenu.AddSubMenu(playerName, () => CreateAdminFlagsMenu(admin, player));
500+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
501+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
502+
addAdminMenu.AddSubMenu(playerName, () => CreateAdminFlagsMenu(admin, capturedPlayer));
493503
}
494504

495505
return addAdminMenu.WithBackButton();
@@ -539,19 +549,20 @@ private static MenuBuilder CreateRemoveAdminMenu(CCSPlayerController admin)
539549
var localizer = CS2_SimpleAdmin._localizer;
540550
var removeAdminMenu = new MenuBuilder("sa_admin_remove", admin, localizer);
541551

542-
var adminPlayers = Helper.GetValidPlayers().Where(p =>
543-
AdminManager.GetPlayerAdminData(p)?.Flags.Count > 0 &&
544-
p != admin &&
552+
var adminPlayers = Helper.GetValidPlayers().Where(p =>
553+
AdminManager.GetPlayerAdminData(p)?.Flags.Count > 0 &&
554+
p != admin &&
545555
admin.CanTarget(p));
546-
556+
547557
foreach (var player in adminPlayers)
548558
{
549-
var playerName = player.PlayerName.Length > 26 ? player.PlayerName[..26] : player.PlayerName;
559+
var capturedPlayer = player; // Capture to local variable to avoid closure issue
560+
var playerName = capturedPlayer.PlayerName.Length > 26 ? capturedPlayer.PlayerName[..26] : capturedPlayer.PlayerName;
550561
removeAdminMenu.AddOption(playerName, _ =>
551562
{
552-
if (player.IsValid)
563+
if (capturedPlayer.IsValid)
553564
{
554-
CS2_SimpleAdmin.Instance.RemoveAdmin(admin, player.SteamID.ToString());
565+
CS2_SimpleAdmin.Instance.RemoveAdmin(admin, capturedPlayer.SteamID.ToString());
555566
}
556567
});
557568
}
@@ -583,10 +594,10 @@ private static MenuBuilder CreateReloadAdminsMenu(CCSPlayerController admin)
583594
/// <param name="admin">The admin player selecting duration.</param>
584595
/// <param name="player">The target player for the penalty.</param>
585596
/// <param name="actionName">The name of the penalty action (e.g., "Kick", "Ban").</param>
586-
/// <param name="onSelectAction">Callback action executed when duration is selected.</param>
597+
/// <param name="onSelectAction">Callback function that returns the next menu when duration is selected.</param>
587598
/// <returns>A MenuBuilder instance for the duration menu.</returns>
588599
private static MenuBuilder CreateDurationMenu(CCSPlayerController admin, CCSPlayerController player, string actionName,
589-
Action<CCSPlayerController, CCSPlayerController, int> onSelectAction)
600+
Func<CCSPlayerController, CCSPlayerController, int, MenuBuilder> onSelectAction)
590601
{
591602
var localizer = CS2_SimpleAdmin._localizer;
592603

@@ -614,10 +625,8 @@ private static MenuBuilder CreateDurationMenu(CCSPlayerController admin, CCSPlay
614625

615626
foreach (var durationItem in CS2_SimpleAdmin.Instance.Config.MenuConfigs.Durations)
616627
{
617-
durationMenu.AddOption(durationItem.Name, _ =>
618-
{
619-
onSelectAction(admin, player, durationItem.Duration);
620-
});
628+
var capturedDuration = durationItem.Duration; // Capture to avoid closure issue
629+
durationMenu.AddSubMenu(durationItem.Name, () => onSelectAction(admin, player, capturedDuration));
621630
}
622631

623632
return durationMenu.WithBackButton();

0 commit comments

Comments
 (0)