Server bewerben
csb-command-access / addons / amxmodx / scripting / csb_command_access.sma
127 lines 3.4 KiB Pawn Raw Permalink History
/*
 * CSB Command Access
 * Copyright (C) 2026 counter-strike-boost.com
 *
 * Maps arbitrary console/chat commands to access flags from
 * configs/csb_cmdaccess.ini. Each mapped command is registered and, when a
 * player without the flag runs it, the plugin blocks it (PLUGIN_HANDLED) and
 * prints a denial. Lets owners restrict third-party or say-based commands
 * without recompiling them.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version. It is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See <https://www.gnu.org/licenses/> for details.
 */

#include <amxmodx>
#include <amxmisc>

#define MAX_RULES 48

new const PLUGIN[] = "CSB Command Access"
new const VERSION[] = "1.0.0"
new const AUTHOR[]  = "counter-strike-boost.com"

new g_szCmd[MAX_RULES][40]
new g_iFlags[MAX_RULES]
new g_iRuleCount = 0

new g_pEnabled

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR)

    g_pEnabled = register_cvar("csb_cmdaccess_enabled", "1")

    loadRules()
}

loadRules()
{
    new dir[128]
    get_localinfo("amxx_configsdir", dir, charsmax(dir))

    new path[160]
    formatex(path, charsmax(path), "%s/csb_cmdaccess.ini", dir)

    if (!file_exists(path))
    {
        write_file(path, "; CSB Command Access - one rule per line: <command> <flags>")
        write_file(path, "; the command is blocked for anyone missing the flags.")
        write_file(path, "; example: restrict the say-based command /rtv to reserved slots")
        write_file(path, "; say /rtv a")
    }

    new f = fopen(path, "rt")

    if (!f)
    {
        log_amx("[CSB CmdAccess] could not open %s", path)
        return
    }

    new line[96], cmd[40], flagStr[24]

    while (!feof(f) && g_iRuleCount < MAX_RULES)
    {
        fgets(f, line, charsmax(line))
        trim(line)

        if (!line[0] || line[0] == ';' || line[0] == '#')
            continue

        strtok(line, cmd, charsmax(cmd), flagStr, charsmax(flagStr), ' ')
        trim(cmd)
        trim(flagStr)

        if (!cmd[0] || !flagStr[0])
            continue

        copy(g_szCmd[g_iRuleCount], charsmax(g_szCmd[]), cmd)
        g_iFlags[g_iRuleCount] = read_flags(flagStr)

        register_clcmd(cmd, "blockCheck")
        g_iRuleCount++
    }

    fclose(f)

    log_amx("[CSB CmdAccess] loaded %d rule(s).", g_iRuleCount)
}

public blockCheck(id)
{
    if (!get_pcvar_num(g_pEnabled))
        return PLUGIN_CONTINUE

    new cmd[40]
    read_argv(0, cmd, charsmax(cmd))

    /* say-based commands arrive as "say" + argv1; rebuild the full command */
    if (equali(cmd, "say") || equali(cmd, "say_team"))
    {
        new rest[64]
        read_args(rest, charsmax(rest))
        remove_quotes(rest)
        trim(rest)
        formatex(cmd, charsmax(cmd), "%s %s", equali(cmd, "say") ? "say" : "say_team", rest)
    }

    for (new i = 0; i < g_iRuleCount; i++)
    {
        if (!equali(cmd, g_szCmd[i]))
            continue

        if (get_user_flags(id) & g_iFlags[i])
            return PLUGIN_CONTINUE

        client_print(id, print_chat, "[CSB] You do not have access to that command.")
        return PLUGIN_HANDLED
    }

    return PLUGIN_CONTINUE
}