Promuj serwer
csb-multimod-manager / addons / amxmodx / scripting / csb_multimod_manager.sma
158 lines 3.9 KiB Pawn Raw Permalink History
/*
 * CSB Multimod Manager
 * Copyright (C) 2026 counter-strike-boost.com
 *
 * Rotates one server through several mods by map prefix. At map start it reads a
 * mapping file, and for every block whose prefix matches the current map name it
 * execs that block's server .cfg and amx_unpauses its plugins; non-matching
 * blocks are amx_paused. This keeps kz_, deathrun_, surf_, zm_, jail_ maps on
 * the right plugin set without swapping configs by hand.
 *
 * Inspired by Multi-Mod Manager by Emp`. Independent GPL re-implementation.
 *
 * 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>

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

new g_pEnabled
new g_szMap[40]

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

    g_pEnabled = register_cvar("csb_mm_enabled", "1")
    register_concmd("csb_mm_reload", "cmdReload", ADMIN_CFG, "- re-apply the multimod config for the current map")
}

public plugin_cfg()
{
    if (get_pcvar_num(g_pEnabled))
    {
        get_mapname(g_szMap, charsmax(g_szMap))
        applyConfig()
    }
}

public cmdReload(id, level, cid)
{
    get_mapname(g_szMap, charsmax(g_szMap))
    applyConfig()
    console_print(id, "[CSB MM] Multimod config re-applied for %s.", g_szMap)
    return PLUGIN_HANDLED
}

applyConfig()
{
    new path[128]
    copy(path, charsmax(path), "addons/amxmodx/configs/csb_multimod.ini")

    if (!file_exists(path))
    {
        log_amx("[CSB MM] Config %s not found; nothing to do.", path)
        return
    }

    new fp = fopen(path, "rt")

    if (!fp)
        return

    new line[256], matched = 0

    while (!feof(fp))
    {
        fgets(fp, line, charsmax(line))
        trim(line)

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

        new prefix[32], cfgfile[64], plugins[160], pos = 0

        pos = argParse(line, pos, prefix, charsmax(prefix))
        pos = argParse(line, pos, cfgfile, charsmax(cfgfile))
        argParse(line, pos, plugins, charsmax(plugins))

        if (!prefix[0])
            continue

        if (containi(g_szMap, prefix) == 0)
        {
            matched++

            if (cfgfile[0] && !equal(cfgfile, "-"))
                server_cmd("exec addons/amxmodx/configs/%s", cfgfile)

            togglePlugins(plugins, true)
        }
        else
        {
            togglePlugins(plugins, false)
        }
    }

    fclose(fp)
    server_exec()

    if (matched)
        log_amx("[CSB MM] Applied %d matching mod block(s) for map %s.", matched, g_szMap)
}

togglePlugins(const list[], bool:enable)
{
    new item[32], len = strlen(list), k = 0

    for (new i = 0; i <= len; i++)
    {
        if (i == len || list[i] == ';')
        {
            item[k] = 0
            trim(item)

            if (item[0])
            {
                if (enable)
                    server_cmd("amx_unpause ^"%s^"", item)
                else
                    server_cmd("amx_pause ^"%s^"", item)
            }

            k = 0
        }
        else if (k < charsmax(item))
        {
            item[k++] = list[i]
        }
    }
}

argParse(const src[], start, dest[], maxlen)
{
    new len = strlen(src), i = start

    while (i < len && (src[i] == ' ' || src[i] == '^t'))
        i++

    new k = 0

    while (i < len && src[i] != ' ' && src[i] != '^t')
    {
        if (k < maxlen)
            dest[k++] = src[i]
        i++
    }

    dest[k] = 0
    return i
}