Strafen-API

Complete reference for issuing and managing player penalties.

Strafe Types

public enum PenaltyType
{
    Ban,      // Ban player from server
    Kick,     // Kick player from server
    Gag,      // Block text chat
    Mute,     // Block voice chat
    Silence,  // Block both text and voice
    Warn      // Issue warning
}

---

Issue Strafen

IssuePenalty (Online Spieler)

Issue a penalty to a currently connected player.

void IssuePenalty(
    CCSPlayerController player,
    CCSPlayerController? admin,
    PenaltyType penaltyType,
    string reason,
    int duration = -1
)

Parameters:

Beispiel:

// Ban player for 1 day
_api!.IssuePenalty(
    player,
    admin,
    PenaltyType.Ban,
    "Cheating",
    1440  // 24 hours in minutes
);

// Permanent ban
_api.IssuePenalty(
    player,
    admin,
    PenaltyType.Ban,
    "Severe rule violation",
    0
);

// Kick player
_api.IssuePenalty(
    player,
    admin,
    PenaltyType.Kick,
    "AFK"
);

// Gag for 30 minutes
_api.IssuePenalty(
    player,
    admin,
    PenaltyType.Gag,
    "Chat spam",
    30
);

---

IssuePenalty (Offline Spieler)

Issue a penalty to a player by SteamID (even if offline).

void IssuePenalty(
    SteamID steamid,
    CCSPlayerController? admin,
    PenaltyType penaltyType,
    string reason,
    int duration = -1
)

Parameters:

Beispiel:

// Ban offline player
var steamId = new SteamID(76561198012345678);

_api!.IssuePenalty(
    steamId,
    admin,
    PenaltyType.Ban,
    "Ban evasion",
    10080  // 7 days
);

// Mute offline player
_api.IssuePenalty(
    steamId,
    admin,
    PenaltyType.Mute,
    "Voice abuse",
    1440
);

Supported SteamID Formats:

// SteamID64
new SteamID(76561198012345678)

// Also works with SteamID string parsing
SteamID.FromString("STEAM_1:0:12345678")
SteamID.FromString("[U:1:12345678]")

---

Get Spieler Information

GetPlayerInfo

Get detailed player information including penalty counts.

PlayerInfo GetPlayerInfo(CCSPlayerController player)

Returns: PlayerInfo object containing:

Beispiel:

var playerInfo = _api!.GetPlayerInfo(player);

Console.WriteLine($"Player: {playerInfo.PlayerName}");
Console.WriteLine($"SteamID: {playerInfo.SteamId}");
Console.WriteLine($"Warnings: {playerInfo.Warnings}");
Console.WriteLine($"Total Bans: {playerInfo.Bans}");

// Check if player has penalties
if (playerInfo.Warnings >= 3)
{
    _api.IssuePenalty(player, null, PenaltyType.Ban, "Too many warnings", 1440);
}

Throws:

---

GetPlayerMuteStatus

Get current mute/gag/silence status for a player.

Dictionary<PenaltyType, List<(DateTime EndDateTime, int Duration, bool Passed)>> GetPlayerMuteStatus(
    CCSPlayerController player
)

Returns: Dictionary mapping penalty types to lists of active penalties

Beispiel:

var muteStatus = _api!.GetPlayerMuteStatus(player);

// Check if player is gagged
if (muteStatus.ContainsKey(PenaltyType.Gag))
{
    var gagPenalties = muteStatus[PenaltyType.Gag];

    foreach (var (endTime, duration, passed) in gagPenalties)
    {
        if (!passed)
        {
            var remaining = endTime - DateTime.UtcNow;
            Console.WriteLine($"Gagged for {remaining.TotalMinutes:F0} more minutes");
        }
    }
}

// Check if player is muted
if (muteStatus.ContainsKey(PenaltyType.Mute))
{
    Console.WriteLine("Player is currently muted");
}

// Check if player is silenced
if (muteStatus.ContainsKey(PenaltyType.Silence))
{
    Console.WriteLine("Player is silenced (gag + mute)");
}

---

Server Information

GetConnectionString

Get the database connection string.

string GetConnectionString()

Beispiel:

var connectionString = _api!.GetConnectionString();
// Use for custom database operations

---

GetServerAddress

Get the server's IP address and port.

string GetServerAddress()

Beispiel:

var serverAddress = _api!.GetServerAddress();
Console.WriteLine($"Server: {serverAddress}");
// Example output: "192.168.1.100:27015"

---

GetServerId

Get the server's unique ID in the database.

int? GetServerId()

Returns:

Beispiel:

var serverId = _api!.GetServerId();

if (serverId.HasValue)
{
    Console.WriteLine($"Server ID: {serverId.Value}");
}
else
{
    Console.WriteLine("Single-server mode");
}

---

Vollständige Beispiele

Ban with Validation

private void BanPlayer(CCSPlayerController? admin, CCSPlayerController target, int duration, string reason)
{
    // Validate player
    if (!target.IsValid)
    {
        admin?.PrintToChat("Invalid player!");
        return;
    }

    // Check immunity
    if (admin != null && !admin.CanTarget(target))
    {
        admin.PrintToChat($"You cannot ban {target.PlayerName} (higher immunity)!");
        return;
    }

    // Get player info to check history
    var playerInfo = _api!.GetPlayerInfo(target);

    Logger.LogInformation(
        $"{admin?.PlayerName ?? "Console"} banning {playerInfo.PlayerName} " +
        $"(SteamID: {playerInfo.SteamId}, Previous bans: {playerInfo.Bans})"
    );

    // Issue ban
    _api.IssuePenalty(target, admin, PenaltyType.Ban, reason, duration);

    // Show activity
    if (admin == null || !_api.IsAdminSilent(admin))
    {
        var durationText = duration == 0 ? "permanently" : $"for {duration} minutes";
        Server.PrintToChatAll($"{admin?.PlayerName ?? "Console"} banned {target.PlayerName} {durationText}: {reason}");
    }
}

---

Progressive Punishment System

private void HandlePlayerOffense(CCSPlayerController? admin, CCSPlayerController target, string reason)
{
    var playerInfo = _api!.GetPlayerInfo(target);

    // Progressive punishment based on warning count
    if (playerInfo.Warnings == 0)
    {
        // First offense - warning
        _api.IssuePenalty(target, admin, PenaltyType.Warn, reason);
        target.PrintToChat("This is your first warning!");
    }
    else if (playerInfo.Warnings == 1)
    {
        // Second offense - gag for 30 minutes
        _api.IssuePenalty(target, admin, PenaltyType.Gag, $"Second offense: {reason}", 30);
        target.PrintToChat("Second warning! You are gagged for 30 minutes.");
    }
    else if (playerInfo.Warnings == 2)
    {
        // Third offense - 1 day ban
        _api.IssuePenalty(target, admin, PenaltyType.Ban, $"Third offense: {reason}", 1440);
        target.PrintToChat("Third offense! You are banned for 1 day.");
    }
    else
    {
        // More than 3 warnings - permanent ban
        _api.IssuePenalty(target, admin, PenaltyType.Ban, $"Multiple offenses: {reason}", 0);
    }
}

---

Check Active Strafen Before Action

private void AllowPlayerToChat(CCSPlayerController player)
{
    var muteStatus = _api!.GetPlayerMuteStatus(player);

    // Check if player is gagged
    if (muteStatus.ContainsKey(PenaltyType.Gag))
    {
        player.PrintToChat("You are currently gagged and cannot use chat!");
        return;
    }

    // Check if player is silenced (includes gag)
    if (muteStatus.ContainsKey(PenaltyType.Silence))
    {
        player.PrintToChat("You are silenced and cannot communicate!");
        return;
    }

    // Player can chat
    ProcessChatMessage(player);
}

---

Offline Spieler Ban

private void BanOfflinePlayer(CCSPlayerController? admin, string steamIdString, int duration, string reason)
{
    // Parse SteamID
    if (!ulong.TryParse(steamIdString, out ulong steamId64))
    {
        admin?.PrintToChat("Invalid SteamID format!");
        return;
    }

    var steamId = new SteamID(steamId64);

    // Issue offline ban
    _api!.IssuePenalty(steamId, admin, PenaltyType.Ban, reason, duration);

    Logger.LogInformation(
        $"{admin?.PlayerName ?? "Console"} banned offline player " +
        $"(SteamID: {steamId64}) for {duration} minutes: {reason}"
    );

    admin?.PrintToChat($"Offline ban issued to SteamID {steamId64}");
}

---

Multi-Account-Erkennung

[GameEventHandler]
public HookResult OnPlayerConnect(EventPlayerConnectFull @event, GameEventInfo info)
{
    var player = @event.Userid;
    if (player == null || !player.IsValid) return HookResult.Continue;

    var playerInfo = _api!.GetPlayerInfo(player);

    // Check if player has multiple accounts
    if (playerInfo.Bans > 0)
    {
        // Notify admins
        var admins = Utilities.GetPlayers()
            .Where(p => AdminManager.PlayerHasPermissions(p, "@css/ban"));

        foreach (var admin in admins)
        {
            admin.PrintToChat(
                $"⚠ {player.PlayerName} has {playerInfo.Bans} previous ban(s)!"
            );
        }
    }

    return HookResult.Continue;
}

---

Bewährte Vorgehensweisen

1. Always Validate Spieler

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

// Check immunity
if (admin != null && !admin.CanTarget(target))
{
    admin.PrintToChat("Cannot target this player!");
    return;
}

2. Provide Clear Reasons

// ✅ Good - Specific reason
_api.IssuePenalty(player, admin, PenaltyType.Ban, "Aimbot detected in Round 12", 10080);

// ❌ Bad - Vague reason
_api.IssuePenalty(player, admin, PenaltyType.Ban, "cheating", 10080);

3. Log Strafe Actions

_api.IssuePenalty(player, admin, PenaltyType.Ban, reason, duration);

Logger.LogInformation(
    $"Penalty issued: {admin?.PlayerName ?? "Console"} -> {player.PlayerName} " +
    $"| Type: {PenaltyType.Ban} | Duration: {duration}m | Reason: {reason}"
);

4. Handle Kick Separately

// Kick doesn't need duration
_api.IssuePenalty(player, admin, PenaltyType.Kick, reason);

// NOT:
_api.IssuePenalty(player, admin, PenaltyType.Kick, reason, 0);

5. Check Active Strafen

// Before issuing new penalty, check existing ones
var muteStatus = _api.GetPlayerMuteStatus(player);

if (muteStatus.ContainsKey(PenaltyType.Gag))
{
    admin?.PrintToChat($"{player.PlayerName} is already gagged!");
    return;
}

---

Häufige Muster

Duration Helpers

public static class PenaltyDurations
{
    public const int OneHour = 60;
    public const int OneDay = 1440;
    public const int OneWeek = 10080;
    public const int TwoWeeks = 20160;
    public const int OneMonth = 43200;
    public const int Permanent = 0;
}

// Usage
_api.IssuePenalty(player, admin, PenaltyType.Ban, reason, PenaltyDurations.OneWeek);

Strafe History Display

private void ShowPlayerHistory(CCSPlayerController admin, CCSPlayerController target)
{
    var info = _api!.GetPlayerInfo(target);

    admin.PrintToChat($"=== {info.PlayerName} History ===");
    admin.PrintToChat($"Warnings: {info.Warnings}");
    admin.PrintToChat($"Bans: {info.Bans}");
    admin.PrintToChat($"Mutes: {info.Mutes}");
    admin.PrintToChat($"Gags: {info.Gags}");

    var muteStatus = _api.GetPlayerMuteStatus(target);

    if (muteStatus.ContainsKey(PenaltyType.Gag))
        admin.PrintToChat("Currently: GAGGED");
    if (muteStatus.ContainsKey(PenaltyType.Mute))
        admin.PrintToChat("Currently: MUTED");
    if (muteStatus.ContainsKey(PenaltyType.Silence))
        admin.PrintToChat("Currently: SILENCED");
}

---

Fehlerbehandlung

Handle Invalid Spieler

try
{
    var playerInfo = _api!.GetPlayerInfo(player);
    // Use playerInfo...
}
catch (KeyNotFoundException)
{
    Logger.LogError($"Player info not found for {player?.PlayerName}");
    return;
}

Validate SteamID

private bool TryParseSteamId(string input, out SteamID steamId)
{
    steamId = default;

    if (ulong.TryParse(input, out ulong steamId64))
    {
        steamId = new SteamID(steamId64);
        return true;
    }

    return false;
}

---