AdminStealth 0.3.14: a team pick closes the team screen for hidden admins

Telling only their client they joined spectators left the screen open, so the
admin had to unhide to get out. Move them to spectators and back to no team,
as css_hide does, with sv_disable_teamselect_menu on around it.
This commit is contained in:
Astra 2026-10-03 00:20:33 +01:00
parent 0446fe49e8
commit 7eba09905a
2 changed files with 36 additions and 12 deletions

View file

@ -23,7 +23,7 @@ namespace AdminStealth;
public class AdminStealth : BasePlugin public class AdminStealth : BasePlugin
{ {
public override string ModuleName => "AdminStealth"; public override string ModuleName => "AdminStealth";
public override string ModuleVersion => "0.3.13"; public override string ModuleVersion => "0.3.14";
public override string ModuleAuthor => "astra"; public override string ModuleAuthor => "astra";
public override string ModuleDescription => "Makes CS2-SimpleAdmin's css_hide look like leaving, and keeps it"; public override string ModuleDescription => "Makes CS2-SimpleAdmin's css_hide look like leaving, and keeps it";
@ -80,6 +80,7 @@ public class AdminStealth : BasePlugin
_hideTyped.Clear(); _hideTyped.Clear();
_restoreScheduled.Clear(); _restoreScheduled.Clear();
_restoring.Clear(); _restoring.Clear();
_closingTeamScreen.Clear();
}); });
} }
@ -136,20 +137,42 @@ public class AdminStealth : BasePlugin
player!.PrintToChat($" You're hidden, so you can't join a team. Type {ChatAlias()} to show yourself."); player!.PrintToChat($" You're hidden, so you can't join a team. Type {ChatAlias()} to show yourself.");
// M opens the team screen on the client, where the server can't block it, and a player with CloseTeamScreen(player);
// no team (as hidden admins are) can't close it without picking. Answer the pick by telling return HookResult.Stop;
// only their client they joined spectators, with the team screen disabled around it, so }
// nobody else ever sees them on a team.
// M opens the team screen on the client, where the server can't block it, and a player with no
// team (as hidden admins are) can't close it without picking. Telling only their client they
// joined spectators doesn't close it (tried live), so do what css_hide does: really move them
// to spectators and back to no team, with the team screen disabled around it. Their team
// events aren't broadcast while hidden (OnPlayerTeam), and our SimpleAdmin fork doesn't unhide
// for spectators.
private readonly HashSet<int> _closingTeamScreen = [];
private void CloseTeamScreen(CCSPlayerController player)
{
var slot = player.Slot; var slot = player.Slot;
if (!_closingTeamScreen.Add(slot))
return;
Server.ExecuteCommand("sv_disable_teamselect_menu 1"); Server.ExecuteCommand("sv_disable_teamselect_menu 1");
AddTimer(0.3f, () => Server.NextFrame(() =>
{ {
var p = Utilities.GetPlayerFromSlot(slot); var p = Utilities.GetPlayerFromSlot(slot);
if (p is { IsValid: true } && IsHidden(p)) if (p is { IsValid: true } && IsHidden(p) && p.TeamNum == (byte)CsTeam.None)
SendTeamEvent(p, (int)CsTeam.Spectator, p.TeamNum); p.ChangeTeam(CsTeam.Spectator);
});
AddTimer(0.15f, () =>
{
var p = Utilities.GetPlayerFromSlot(slot);
if (p is { IsValid: true } && IsHidden(p) && p.TeamNum == (byte)CsTeam.Spectator)
p.ChangeTeam(CsTeam.None);
}, TimerFlags.STOP_ON_MAPCHANGE);
AddTimer(0.5f, () =>
{
_closingTeamScreen.Remove(slot);
Server.ExecuteCommand("sv_disable_teamselect_menu 0");
}, TimerFlags.STOP_ON_MAPCHANGE); }, TimerFlags.STOP_ON_MAPCHANGE);
AddTimer(0.6f, () => Server.ExecuteCommand("sv_disable_teamselect_menu 0"), TimerFlags.STOP_ON_MAPCHANGE);
return HookResult.Stop;
} }
private HookResult OnTeamMenu(CCSPlayerController? player, CommandInfo command) private HookResult OnTeamMenu(CCSPlayerController? player, CommandInfo command)

View file

@ -20,8 +20,9 @@ admin off the scoreboard. This plugin makes it look like they left the server:
the team select screen doesn't open, until the restore hides them again. the team select screen doesn't open, until the restore hides them again.
- The team select screen: the server's "team" menu message (`CS_UM_VGUIMenu`) is never sent to - The team select screen: the server's "team" menu message (`CS_UM_VGUIMenu`) is never sent to
a hidden admin. M opens it on the client regardless, and a player with no team can't close it a hidden admin. M opens it on the client regardless, and a player with no team can't close it
without picking, so a pick is answered by telling only that client it joined spectators without picking, so a pick moves them to spectators and straight back to no team, as `css_hide`
(with `sv_disable_teamselect_menu` on around it); nobody else sees a team change. does (with `sv_disable_teamselect_menu` on around it), which closes it. The team events aren't
broadcast; for about 0.15 s they're on the spectator list of anyone looking at the scoreboard.
- Restoring runs `css_hide` at most once: it toggles, so a second run could unhide them. - Restoring runs `css_hide` at most once: it toggles, so a second run could unhide them.
Needs our SimpleAdmin fork (1.8.2b-zio2 or later), where moving to spectators doesn't unhide a Needs our SimpleAdmin fork (1.8.2b-zio2 or later), where moving to spectators doesn't unhide a