Files
CS2-SimpleAdmin/CS2-SimpleAdmin-docs/docs/developer/api/utilities.md
Dawid Bepierszcz b0d8696756 Add CS2-SimpleAdmin documentation site
Introduces a new documentation site for CS2-SimpleAdmin using Docusaurus, including developer API references, tutorials, user guides, and module documentation. Removes the CleanModule example and updates FunCommands and ExampleModule. Also updates main plugin and API files to support new documentation and module structure.
2025-10-20 01:27:01 +02:00

12 KiB

sidebar_position
sidebar_position
6

Utilities API

Helper functions and utility methods for module development.

Player Management

GetValidPlayers

Get a list of all valid, connected players.

List<CCSPlayerController> GetValidPlayers()

Returns: List of valid player controllers

Example:

var players = _api!.GetValidPlayers();

foreach (var player in players)
{
    Console.WriteLine($"Player: {player.PlayerName}");
}

// Filter for specific criteria
var alivePlayers = _api.GetValidPlayers()
    .Where(p => p.PawnIsAlive)
    .ToList();

var ctPlayers = _api.GetValidPlayers()
    .Where(p => p.Team == CsTeam.CounterTerrorist)
    .ToList();

Note: This method filters out invalid and bot players automatically.


Admin Status

IsAdminSilent

Check if an admin is in silent mode.

bool IsAdminSilent(CCSPlayerController player)

Parameters:

  • player - Player to check

Returns: true if player is in silent mode, false otherwise

Example:

private void PerformAdminAction(CCSPlayerController admin, CCSPlayerController target)
{
    // Do the action
    DoAction(target);

    // Only show activity if not silent
    if (!_api!.IsAdminSilent(admin))
    {
        Server.PrintToChatAll($"{admin.PlayerName} performed action on {target.PlayerName}");
    }
}

ListSilentAdminsSlots

Get a list of player slots for all admins currently in silent mode.

HashSet<int> ListSilentAdminsSlots()

Returns: HashSet of player slots

Example:

var silentAdmins = _api!.ListSilentAdminsSlots();

Console.WriteLine($"Silent admins: {silentAdmins.Count}");

foreach (var slot in silentAdmins)
{
    var player = Utilities.GetPlayerFromSlot(slot);
    if (player != null)
    {
        Console.WriteLine($"- {player.PlayerName} (slot {slot})");
    }
}

Activity Messages

ShowAdminActivity

Show an admin activity message to all players.

void ShowAdminActivity(
    string messageKey,
    string? callerName = null,
    bool dontPublish = false,
    params object[] messageArgs
)

Parameters:

  • messageKey - Translation key from SimpleAdmin's lang files
  • callerName - Admin name (null for console)
  • dontPublish - If true, don't trigger OnAdminShowActivity event
  • messageArgs - Arguments for message formatting

Example:

// Using SimpleAdmin's built-in translations
_api!.ShowAdminActivity(
    "sa_admin_player_kick_message",  // Translation key
    admin?.PlayerName,
    false,
    player.PlayerName,
    reason
);

Limitations:

  • Only works with SimpleAdmin's own translation keys
  • For module-specific messages, use ShowAdminActivityLocalized

ShowAdminActivityTranslated

Show a pre-translated admin activity message.

void ShowAdminActivityTranslated(
    string translatedMessage,
    string? callerName = null,
    bool dontPublish = false
)

Parameters:

  • translatedMessage - Already translated message
  • callerName - Admin name
  • dontPublish - If true, don't trigger event

Example:

// Use when you've already translated the message
var message = Localizer?["my_action_message", player.PlayerName] ?? $"Action on {player.PlayerName}";

_api!.ShowAdminActivityTranslated(
    message,
    admin?.PlayerName,
    false
);

Use Case:

  • When you need custom message formatting
  • When translation is already done

Show admin activity with per-player language support using module's localizer.

void ShowAdminActivityLocalized(
    object moduleLocalizer,
    string messageKey,
    string? callerName = null,
    bool dontPublish = false,
    params object[] messageArgs
)

Parameters:

  • moduleLocalizer - Your module's IStringLocalizer instance
  • messageKey - Translation key from your module's lang files
  • callerName - Admin name
  • dontPublish - If true, don't trigger event
  • messageArgs - Message arguments

Example:

// Each player sees message in their configured language!
if (Localizer != null)
{
    _api!.ShowAdminActivityLocalized(
        Localizer,  // Your module's localizer
        "fun_admin_god_message",  // From your lang/en.json
        admin?.PlayerName,
        false,
        player.PlayerName
    );
}

lang/en.json:

{
  "fun_admin_god_message": "{lightred}{0}{default} changed god mode for {lightred}{1}{default}!"
}

Why This is Best:

  • Each player sees message in their own language
  • Uses your module's translations
  • Supports color codes
  • Per-player localization

Complete Examples

Action with Activity Message

private void ToggleGodMode(CCSPlayerController? admin, CCSPlayerController target)
{
    // Perform action
    if (GodPlayers.Contains(target.Slot))
    {
        GodPlayers.Remove(target.Slot);
    }
    else
    {
        GodPlayers.Add(target.Slot);
    }

    // Show activity (respecting silent mode)
    if (admin == null || !_api!.IsAdminSilent(admin))
    {
        if (Localizer != null)
        {
            _api!.ShowAdminActivityLocalized(
                Localizer,
                "fun_admin_god_message",
                admin?.PlayerName,
                false,
                target.PlayerName
            );
        }
    }

    // Log action
    _api!.LogCommand(admin, $"css_god {target.PlayerName}");
}

Broadcast to Non-Silent Admins

private void NotifyAdmins(string message)
{
    var silentAdmins = _api!.ListSilentAdminsSlots();

    var players = _api.GetValidPlayers();

    foreach (var player in players)
    {
        // Check if player is admin
        if (!AdminManager.PlayerHasPermissions(player, "@css/generic"))
            continue;

        // Skip if admin is in silent mode
        if (silentAdmins.Contains(player.Slot))
            continue;

        player.PrintToChat(message);
    }
}

Filter Players by Criteria

private List<CCSPlayerController> GetTargetablePlayers(CCSPlayerController admin)
{
    return _api!.GetValidPlayers()
        .Where(p =>
            p.IsValid &&
            !p.IsBot &&
            p.PawnIsAlive &&
            admin.CanTarget(p))
        .ToList();
}

private List<CCSPlayerController> GetAliveEnemies(CCSPlayerController player)
{
    return _api!.GetValidPlayers()
        .Where(p =>
            p.Team != player.Team &&
            p.PawnIsAlive)
        .ToList();
}

private List<CCSPlayerController> GetAdmins()
{
    return _api!.GetValidPlayers()
        .Where(p => AdminManager.PlayerHasPermissions(p, "@css/generic"))
        .ToList();
}

Best Practices

1. Use ShowAdminActivityLocalized

// ✅ Good - Per-player language
_api.ShowAdminActivityLocalized(
    Localizer,
    "my_message_key",
    admin?.PlayerName,
    false,
    args
);

// ❌ Bad - Single language for all
Server.PrintToChatAll($"{admin?.PlayerName} did something");

2. Respect Silent Mode

// ✅ Good - Check silent mode
if (admin == null || !_api.IsAdminSilent(admin))
{
    ShowActivity();
}

// ❌ Bad - Always show activity
ShowActivity();  // Ignores silent mode!

3. Validate Players from GetValidPlayers

var players = _api.GetValidPlayers();

foreach (var player in players)
{
    // Still good to check, especially for async operations
    if (!player.IsValid) continue;

    DoSomething(player);
}

4. Cache Silent Admin List if Checking Multiple Times

// ✅ Good - Cache for multiple checks
var silentAdmins = _api.ListSilentAdminsSlots();

foreach (var admin in admins)
{
    if (silentAdmins.Contains(admin.Slot)) continue;
    NotifyAdmin(admin);
}

// ❌ Bad - Query for each admin
foreach (var admin in admins)
{
    if (_api.IsAdminSilent(admin)) continue;  // ← Repeated calls
    NotifyAdmin(admin);
}

Common Patterns

Silent Mode Wrapper

private void ShowActivityIfNotSilent(
    CCSPlayerController? admin,
    string messageKey,
    params object[] args)
{
    if (admin != null && _api!.IsAdminSilent(admin))
        return;

    if (Localizer != null)
    {
        _api!.ShowAdminActivityLocalized(
            Localizer,
            messageKey,
            admin?.PlayerName,
            false,
            args
        );
    }
}

// Usage
ShowActivityIfNotSilent(admin, "my_action", player.PlayerName);

Get Online Admins

private List<CCSPlayerController> GetOnlineAdmins(string permission = "@css/generic")
{
    return _api!.GetValidPlayers()
        .Where(p => AdminManager.PlayerHasPermissions(p, permission))
        .ToList();
}

// Usage
var admins = GetOnlineAdmins("@css/root");
foreach (var admin in admins)
{
    admin.PrintToChat("Important admin message");
}

Notify All Players Except Silent Admins

private void BroadcastMessage(string message, bool excludeSilentAdmins = true)
{
    var silentAdmins = excludeSilentAdmins
        ? _api!.ListSilentAdminsSlots()
        : new HashSet<int>();

    foreach (var player in _api.GetValidPlayers())
    {
        if (silentAdmins.Contains(player.Slot))
            continue;

        player.PrintToChat(message);
    }
}

Activity Message Formatting

Color Codes in Messages

All activity messages support color codes:

{
  "my_message": "{lightred}Admin{default} banned {lightred}{0}{default} for {yellow}{1}{default}"
}

Available Colors:

  • {default} - Default color
  • {white} - White
  • {darkred} - Dark red
  • {green} - Green
  • {lightyellow} - Light yellow
  • {lightblue} - Light blue
  • {olive} - Olive
  • {lime} - Lime
  • {red} - Red
  • {purple} - Purple
  • {grey} - Grey
  • {yellow} - Yellow
  • {gold} - Gold
  • {silver} - Silver
  • {blue} - Blue
  • {darkblue} - Dark blue
  • {bluegrey} - Blue grey
  • {magenta} - Magenta
  • {lightred} - Light red
  • {orange} - Orange

Message Arguments

// lang/en.json
{
  "ban_message": "{lightred}{0}{default} banned {lightred}{1}{default} for {yellow}{2}{default} minutes: {red}{3}"
}

// Code
_api.ShowAdminActivityLocalized(
    Localizer,
    "ban_message",
    admin?.PlayerName,
    false,
    admin?.PlayerName,  // {0}
    target.PlayerName,   // {1}
    duration,            // {2}
    reason               // {3}
);

Performance Tips

Minimize GetValidPlayers Calls

// ✅ Good - Call once, filter multiple times
var allPlayers = _api.GetValidPlayers();
var alivePlayers = allPlayers.Where(p => p.PawnIsAlive).ToList();
var deadPlayers = allPlayers.Where(p => !p.PawnIsAlive).ToList();

// ❌ Bad - Multiple calls
var alivePlayers = _api.GetValidPlayers().Where(p => p.PawnIsAlive).ToList();
var deadPlayers = _api.GetValidPlayers().Where(p => !p.PawnIsAlive).ToList();

Efficient Filtering

// ✅ Good - Single LINQ query
var targets = _api.GetValidPlayers()
    .Where(p => p.Team == CsTeam.Terrorist &&
                p.PawnIsAlive &&
                admin.CanTarget(p))
    .ToList();

// ❌ Bad - Multiple iterations
var players = _api.GetValidPlayers();
players = players.Where(p => p.Team == CsTeam.Terrorist).ToList();
players = players.Where(p => p.PawnIsAlive).ToList();
players = players.Where(p => admin.CanTarget(p)).ToList();

Troubleshooting

Activity Messages Not Showing

Check:

  1. Is Localizer not null?
  2. Does translation key exist in lang files?
  3. Is message correctly formatted?
  4. Check dontPublish parameter

Silent Mode Not Working

Check:

  1. Is player actually in silent mode? (css_hide command)
  2. Are you checking before showing activity?
  3. Check slot vs player controller mismatch