AdminStealth 0.1.0: make CS2-SimpleAdmin's css_hide look like leaving, block status for players
This commit is contained in:
commit
61f8ea0ad1
6 changed files with 304 additions and 0 deletions
120
AdminStealth.cs
Normal file
120
AdminStealth.cs
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes.Registration;
|
||||
using CounterStrikeSharp.API.Core.Capabilities;
|
||||
using CounterStrikeSharp.API.Modules.Commands;
|
||||
using CounterStrikeSharp.API.Modules.Entities;
|
||||
using CounterStrikeSharp.API.ValveConstants.Protobuf;
|
||||
using CS2_SimpleAdminApi;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace AdminStealth;
|
||||
|
||||
// Companion to CS2-SimpleAdmin's css_hide. When an admin hides, everyone else sees them leave the
|
||||
// server, and nothing the hide does afterwards (the suicide, the team changes, their real
|
||||
// disconnect later) is announced. Also blocks the status command for players, which would
|
||||
// otherwise still list a hidden admin.
|
||||
public class AdminStealth : BasePlugin
|
||||
{
|
||||
public override string ModuleName => "AdminStealth";
|
||||
public override string ModuleVersion => "0.1.0";
|
||||
public override string ModuleAuthor => "astra";
|
||||
public override string ModuleDescription => "Makes CS2-SimpleAdmin's css_hide look like leaving the server";
|
||||
|
||||
private static readonly PluginCapability<ICS2_SimpleAdminApi> SimpleAdminCapability = new("simpleadmin:api");
|
||||
private ICS2_SimpleAdminApi? _simpleAdmin;
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
AddCommandListener("status", OnStatus);
|
||||
}
|
||||
|
||||
public override void OnAllPluginsLoaded(bool hotReload)
|
||||
{
|
||||
try
|
||||
{
|
||||
_simpleAdmin = SimpleAdminCapability.Get();
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
}
|
||||
|
||||
if (_simpleAdmin == null)
|
||||
{
|
||||
Logger.LogError("CS2-SimpleAdmin's API isn't available, so hiding won't look like leaving");
|
||||
return;
|
||||
}
|
||||
_simpleAdmin.OnAdminToggleSilent += OnAdminToggleSilent;
|
||||
}
|
||||
|
||||
public override void Unload(bool hotReload)
|
||||
{
|
||||
if (_simpleAdmin != null)
|
||||
_simpleAdmin.OnAdminToggleSilent -= OnAdminToggleSilent;
|
||||
}
|
||||
|
||||
// Players get nothing back. The server console and RCON still work.
|
||||
private HookResult OnStatus(CCSPlayerController? player, CommandInfo command)
|
||||
{
|
||||
return player == null ? HookResult.Continue : HookResult.Stop;
|
||||
}
|
||||
|
||||
private void OnAdminToggleSilent(int slot, bool hidden)
|
||||
{
|
||||
if (!hidden)
|
||||
return;
|
||||
|
||||
var admin = Utilities.GetPlayerFromSlot(slot);
|
||||
if (admin is not { IsValid: true, IsBot: false })
|
||||
return;
|
||||
|
||||
// A fake player_disconnect, sent to each client rather than fired on the server, so no
|
||||
// plugin (SimpleAdmin included) treats the admin as really gone.
|
||||
var leave = new EventPlayerDisconnect(true)
|
||||
{
|
||||
Userid = admin,
|
||||
Playerid = admin.Slot,
|
||||
Name = admin.PlayerName,
|
||||
Networkid = new SteamID(admin.SteamID).SteamId3,
|
||||
Xuid = admin.SteamID,
|
||||
Reason = (int)NetworkDisconnectionReason.NETWORK_DISCONNECT_DISCONNECT_BY_USER,
|
||||
EverFullyConnected = true,
|
||||
};
|
||||
foreach (var player in Utilities.GetPlayers())
|
||||
{
|
||||
if (player is { IsValid: true, IsBot: false, IsHLTV: false } && player.Slot != slot)
|
||||
leave.FireEventToClient(player);
|
||||
}
|
||||
leave.Free();
|
||||
}
|
||||
|
||||
[GameEventHandler(HookMode.Pre)]
|
||||
public HookResult OnPlayerTeam(EventPlayerTeam @event, GameEventInfo info)
|
||||
{
|
||||
if (IsHidden(@event.Userid))
|
||||
info.DontBroadcast = true;
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
[GameEventHandler(HookMode.Pre)]
|
||||
public HookResult OnPlayerDeath(EventPlayerDeath @event, GameEventInfo info)
|
||||
{
|
||||
if (IsHidden(@event.Userid))
|
||||
info.DontBroadcast = true;
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
// Pre runs before SimpleAdmin's own handler forgets the player was hidden.
|
||||
[GameEventHandler(HookMode.Pre)]
|
||||
public HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo info)
|
||||
{
|
||||
if (IsHidden(@event.Userid))
|
||||
info.DontBroadcast = true;
|
||||
return HookResult.Continue;
|
||||
}
|
||||
|
||||
private bool IsHidden(CCSPlayerController? player)
|
||||
{
|
||||
return player is { IsValid: true, IsBot: false } && _simpleAdmin?.IsAdminSilent(player) == true;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue