Skip to main content

API Overview

Complete reference for the CS2-SimpleAdmin API (ICS2_SimpleAdminApi).

Introduction

The CS2-SimpleAdmin API is exposed via the ICS2_SimpleAdminApi interface, accessible through CounterStrikeSharp's capability system.


Getting the API

Using Capability System

using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Capabilities;
using CS2_SimpleAdminApi;

public class YourPlugin : BasePlugin
{
private ICS2_SimpleAdminApi? _api;
private readonly PluginCapability<ICS2_SimpleAdminApi> _pluginCapability =
new("simpleadmin:api");

public override void OnAllPluginsLoaded(bool hotReload)
{
_api = _pluginCapability.Get();

if (_api == null)
{
Logger.LogError("CS2-SimpleAdmin API not found!");
Unload(false);
return;
}

// API is ready to use
RegisterFeatures();
}
}

Static Capability Reference

// Alternative approach
var capability = ICS2_SimpleAdminApi.PluginCapability;
var api = capability?.Get();

API Categories

The API is organized into logical categories:

CategoryDescriptionLearn More
CommandsRegister/unregister commands, parse targets
MenusCreate admin menus with player selection
PenaltiesIssue bans, mutes, gags, warnings
EventsSubscribe to plugin events
UtilitiesHelper functions, player info, activity messages

Quick Reference

Command Management

// Register command
_api.RegisterCommand(name, description, callback);

// Unregister command
_api.UnRegisterCommand(name);

// Parse player targets
var targets = _api.GetTarget(command);

// Log command
_api.LogCommand(caller, command);

Full Documentation →


// Register category
_api.RegisterMenuCategory(categoryId, categoryName, permission);

// Register menu
_api.RegisterMenu(categoryId, menuId, menuName, menuFactory, permission, commandName);

// Create menu with players
_api.CreateMenuWithPlayers(context, admin, filter, onSelect);

// Create menu with back button
_api.CreateMenuWithBack(context, admin);

// Add menu option
_api.AddMenuOption(menu, name, action, disabled, permission);

// Add submenu
_api.AddSubMenu(menu, name, subMenuFactory, disabled, permission);

// Open menu
_api.OpenMenu(menu, player);

// Unregister menu
_api.UnregisterMenu(categoryId, menuId);

Full Documentation →


Penalty Management

// Issue penalty to online player
_api.IssuePenalty(player, admin, penaltyType, reason, duration);

// Issue penalty by SteamID
_api.IssuePenalty(steamId, admin, penaltyType, reason, duration);

// Get player info
var playerInfo = _api.GetPlayerInfo(player);

// Get mute status
var muteStatus = _api.GetPlayerMuteStatus(player);

Penalty Types:

  • PenaltyType.Ban - Ban player
  • PenaltyType.Kick - Kick player
  • PenaltyType.Gag - Block text chat
  • PenaltyType.Mute - Block voice chat
  • PenaltyType.Silence - Block both
  • PenaltyType.Warn - Issue warning

Full Documentation →


Event System

// Plugin ready event
_api.OnSimpleAdminReady += OnReady;

// Player penaltied
_api.OnPlayerPenaltied += OnPlayerPenaltied;

// Offline penalty added
_api.OnPlayerPenaltiedAdded += OnPlayerPenaltiedAdded;

// Admin activity
_api.OnAdminShowActivity += OnAdminActivity;

// Admin silent toggle
_api.OnAdminToggleSilent += OnAdminToggleSilent;

Full Documentation →


Utility Functions

// Get player info with penalties
var info = _api.GetPlayerInfo(player);

// Get database connection string
var connectionString = _api.GetConnectionString();

// Get server address
var serverAddress = _api.GetServerAddress();

// Get server ID
var serverId = _api.GetServerId();

// Get valid players
var players = _api.GetValidPlayers();

// Check if admin is silent
bool isSilent = _api.IsAdminSilent(player);

// Get all silent admins
var silentAdmins = _api.ListSilentAdminsSlots();

// Show admin activity
_api.ShowAdminActivity(messageKey, callerName, dontPublish, args);

// Show admin activity with custom translation
_api.ShowAdminActivityTranslated(translatedMessage, callerName, dontPublish);

// Show admin activity with module localizer (recommended)
_api.ShowAdminActivityLocalized(moduleLocalizer, messageKey, callerName, dontPublish, args);

Full Documentation →


Common Patterns

Basic Module Structure

using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Capabilities;
using CS2_SimpleAdminApi;

namespace MyModule;

public class MyModule : BasePlugin
{
private ICS2_SimpleAdminApi? _api;
private readonly PluginCapability<ICS2_SimpleAdminApi> _pluginCapability =
new("simpleadmin:api");

public override string ModuleName => "My Module";
public override string ModuleVersion => "1.0.0";

public override void OnAllPluginsLoaded(bool hotReload)
{
_api = _pluginCapability.Get();
if (_api == null) return;

// Register features
RegisterCommands();

// Wait for SimpleAdmin ready
_api.OnSimpleAdminReady += RegisterMenus;
RegisterMenus(); // Fallback for hot reload
}

public override void Unload(bool hotReload)
{
if (_api == null) return;

// Cleanup
_api.UnRegisterCommand("css_mycommand");
_api.UnregisterMenu("category", "menu");
_api.OnSimpleAdminReady -= RegisterMenus;
}
}

Command with Target Selection

[CommandHelper(1, "<#userid or name>")]
[RequiresPermissions("@css/generic")]
private void OnMyCommand(CCSPlayerController? caller, CommandInfo command)
{
// Parse targets
var targets = _api!.GetTarget(command);
if (targets == null) return;

// Filter valid players
var players = targets.Players
.Where(p => p.IsValid && !p.IsBot && caller!.CanTarget(p))
.ToList();

// Process each player
foreach (var player in players)
{
DoSomethingToPlayer(caller, player);
}

// Log command
_api.LogCommand(caller, command);
}

private object CreateMyMenu(CCSPlayerController admin, MenuContext context)
{
// Context contains categoryId, menuId, menuName, permission, commandName
return _api!.CreateMenuWithPlayers(
context, // Automatic title and category
admin,
player => player.IsValid && admin.CanTarget(player),
(admin, target) =>
{
// Action when player selected
PerformAction(admin, target);
}
);
}

Nested Menu

private object CreatePlayerMenu(CCSPlayerController admin, MenuContext context)
{
var menu = _api!.CreateMenuWithBack(context, admin);

var players = _api.GetValidPlayers()
.Where(p => admin.CanTarget(p));

foreach (var player in players)
{
_api.AddSubMenu(menu, player.PlayerName, admin =>
{
return CreateActionMenu(admin, player);
});
}

return menu;
}

private object CreateActionMenu(CCSPlayerController admin, CCSPlayerController target)
{
var menu = _api!.CreateMenuWithBack($"Actions for {target.PlayerName}", "category", admin);

_api.AddMenuOption(menu, "Action 1", _ => DoAction1(admin, target));
_api.AddMenuOption(menu, "Action 2", _ => DoAction2(admin, target));

return menu;
}

Issue Penalty

private void BanPlayer(CCSPlayerController? admin, CCSPlayerController target, int duration, string reason)
{
// Issue ban
_api!.IssuePenalty(
target,
admin,
PenaltyType.Ban,
reason,
duration // minutes, 0 = permanent
);

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

Event Subscription

public override void OnAllPluginsLoaded(bool hotReload)
{
_api = _pluginCapability.Get();
if (_api == null) return;

// Subscribe to events
_api.OnPlayerPenaltied += OnPlayerPenaltied;
}

private void OnPlayerPenaltied(
PlayerInfo player,
PlayerInfo? admin,
PenaltyType type,
string reason,
int duration,
int? penaltyId,
int? serverId)
{
Logger.LogInformation($"{player.PlayerName} received {type}: {reason} ({duration} min)");

// React to penalty
if (type == PenaltyType.Ban)
{
// Handle ban
}
}

public override void Unload(bool hotReload)
{
if (_api == null) return;
_api.OnPlayerPenaltied -= OnPlayerPenaltied;
}

Best Practices

1. Always Check for Null

if (_api == null)
{
Logger.LogError("API not available!");
return;
}

2. Use OnSimpleAdminReady Event

_api.OnSimpleAdminReady += () =>
{
// Register menus only when SimpleAdmin is ready
RegisterMenus();
};

// Also call directly for hot reload case
RegisterMenus();

3. Clean Up on Unload

public override void Unload(bool hotReload)
{
if (_api == null) return;

// Unregister all commands
_api.UnRegisterCommand("css_mycommand");

// Unregister all menus
_api.UnregisterMenu("category", "menu");

// Unsubscribe all events
_api.OnSimpleAdminReady -= OnReady;
}

4. Validate Player State

if (!player.IsValid || !player.PawnIsAlive)
{
return;
}

if (!caller.CanTarget(player))
{
return; // Immunity check
}

5. Use Per-Player Translations

// Each player sees message in their configured language
_api.ShowAdminActivityLocalized(
Localizer, // Your module's localizer
"translation_key",
caller?.PlayerName,
false,
args
);

6. Log All Admin Actions

_api.LogCommand(caller, command);
// or
_api.LogCommand(caller, $"css_mycommand {player.PlayerName}");

API Versioning

The API uses semantic versioning:

  • Major - Breaking changes
  • Minor - New features, backwards compatible
  • Patch - Bug fixes

Current Version: Check GitHub Releases


Thread Safety

The API is designed for single-threaded use within the CounterStrikeSharp game thread.

Do NOT:

  • Call API methods from background threads
  • Use async/await with API calls without proper synchronization

Do:

  • Call API methods from event handlers
  • Call API methods from commands
  • Call API methods from timers

Error Handling

The API uses exceptions for critical errors:

try
{
_api.RegisterCommand("css_cmd", "Desc", callback);
}
catch (ArgumentException ex)
{
Logger.LogError($"Failed to register command: {ex.Message}");
}

Common exceptions:

  • ArgumentException - Invalid arguments
  • InvalidOperationException - Invalid state
  • KeyNotFoundException - Player not found

Performance Considerations

Efficient Player Filtering

// ✅ Good - single LINQ query
var players = _api.GetValidPlayers()
.Where(p => p.IsValid && admin.CanTarget(p))
.ToList();

// ❌ Bad - multiple iterations
var players = _api.GetValidPlayers();
players = players.Where(p => p.IsValid).ToList();
players = players.Where(p => admin.CanTarget(p)).ToList();

Cache Expensive Operations

// Cache menu creation if used multiple times
private object? _cachedMenu;

private object GetMenu(CCSPlayerController player)
{
if (_cachedMenu == null)
{
_cachedMenu = CreateMenu(player);
}
return _cachedMenu;
}

Debugging

Enable Detailed Logging

Logger.LogInformation("Debug: API loaded");
Logger.LogWarning("Warning: Player not found");
Logger.LogError("Error: Failed to execute command");

Check API Availability

public override void OnAllPluginsLoaded(bool hotReload)
{
_api = _pluginCapability.Get();

if (_api == null)
{
Logger.LogError("❌ CS2-SimpleAdmin API not found!");
Logger.LogError("Make sure CS2-SimpleAdmin is installed and loaded.");
return;
}

Logger.LogInformation("✅ CS2-SimpleAdmin API loaded successfully");
}

Next Steps


Resources