AutoExecConfig() или стена быдлокода от Refresh

Сообщения
271
Реакции
84
Здравствуйте!

Было довольно познавательно провести время в спорах с одним из ключевых специалистов этого ресурса, в результате которого я узнал много нового о себе и своей божественно-гениальной натуре, а также обнаружил очевидный "косяк" в работе функции AutoExecConfig(), которая используется в десятках увиденных мной плагинов.

Опуская все регалии, заслуги и опыт моего оппонента, оставляя только суть "вопроса", можно подытожить следующее:
  1. Функция AutoExecConfig() всегда корректно читает данные из конфигурационного файла.
  2. Поскольку делает она это асинхронным запросом результат ее работы доступен лишь в следующем кадре.
Код:
#include <amxmodx>
#include <amxmisc>

new pCvar1, pCvar2, Cvar1, Cvar2[32]

public plugin_init() {
    register_plugin("test cvars", "1.0", "mx?!")
}

public plugin_cfg() {
    //new szConfigsDir[64]
    log_to_file("acs_debug.txt", "fresh start? %s", get_cvar_pointer("_pointer") ? "no" : "yes")

    //get_configsdir(szConfigsDir, 63)
    //server_cmd("exec %s/testcvars.cfg", szConfigsDir)
    //server_exec()

    create_cvar("_pointer", "0")

    pCvar1 = create_cvar("test_cvar1", "0")
    pCvar2 = create_cvar("test_cvar2", "value")

    bind_pcvar_num(pCvar1, Cvar1)
    bind_pcvar_string(pCvar2, Cvar2, charsmax(Cvar2))

    hook_cvar_change(pCvar1, "hook_cvar1")
    hook_cvar_change(pCvar2, "hook_cvar2")

    log_to_file("acs_debug.txt", "time before AutoExecConfig(): %f", get_gametime())
    AutoExecConfig(.name = "testcvars")

    log_to_file("acs_debug.txt", "check(1): cvar1 = %d, cvar2 = %s", Cvar1, Cvar2)
    RequestFrame("check_cvar")
    //set_task(0.01, "check_cvar", 0);
    log_to_file("acs_debug.txt", "here we should initialize db connection %f", get_gametime())
}

public hook_cvar1(pCvar, const szOldVal[], const szNewVal[]) {
    log_to_file("acs_debug.txt", "cvar1 old val %s, new val %s, time %f", szOldVal, szNewVal, get_gametime())
}

public hook_cvar2(pCvar, const szOldVal[], const szNewVal[]) {
    log_to_file("acs_debug.txt", "cvar2 old val %s, new val %s, time %f", szOldVal, szNewVal, get_gametime())
}

public check_cvar() {
    log_to_file("acs_debug.txt", "check(2): cvar1 = %d, cvar2 = %s", Cvar1, Cvar2)
}
Результат работы:

Код:
L 01/28/2024 - 15:34:19: fresh start? yes
L 01/28/2024 - 15:34:19: time before AutoExecConfig(): 1.000000
L 01/28/2024 - 15:34:19: check(1): cvar1 = 0, cvar2 = value
L 01/28/2024 - 15:34:19: here we should initialize db connection 1.000000
L 01/28/2024 - 15:34:20: cvar1 old val 0, new val 333, time 1.000000
L 01/28/2024 - 15:34:20: cvar2 old val value, new val value_new3, time 1.000000
L 01/28/2024 - 15:34:20: check(2): cvar1 = 333, cvar2 = value_new3
L 01/28/2024 - 15:36:03: fresh start? no
L 01/28/2024 - 15:36:03: time before AutoExecConfig(): 1.000000
L 01/28/2024 - 15:36:03: check(1): cvar1 = 333, cvar2 = value_new3
L 01/28/2024 - 15:36:03: here we should initialize db connection 1.000000
L 01/28/2024 - 15:36:03: cvar1 old val 333, new val 444, time 1.000000
L 01/28/2024 - 15:36:03: cvar2 old val value_new3, new val value_new4, time 1.000000
L 01/28/2024 - 15:36:03: check(2): cvar1 = 444, cvar2 = value_new4

У меня возник вопрос, почему??? за 5 лет программирования, нельзя было добавить в эту функцию callback оформленный через RequestFrame() и не лепить костыли, которые все копируют и потом быдлокодерам, вроде меня, предъявляют как божественную истину: "так все делают", "не будь вторым Карауловым", "я 5 лет программирую, так надо", "нужно переделать автоконфиг на конфиг написаннный вручную, и вызывать через через server_cmd("exec", путь); server_exec(), эта комбинация сразу же запускает конфиг в текущем кадре"...

Разработчики AMXX, очевидным образом, пытались упростить и унифицировать процесс разработки плагинов, однако даже самые опытные программисты используют таймер от 3 до 7 секунд или форвард OnConfigsExecuted(), который вызывается далеко не сразу, а за время потраченное на инициализацию таким образом плагина, на сервер зайдут все пользователи, в обход возможно установленных ограничений.

Второй вопрос, вытекает из первого. Для того чтобы использовать актуальные значения кваров через AutoExecConfig() в форварде plugin_precache(), очевидно, необходимо просто поменять порядок вызова форвардов, поставив на первое место plugin_cfg(). Почему за 5 лет программирования нельзя было организовать это второе незначительное изменение, ведь с Оксихромом там трется и другой опытный программист, Сергей.
 
Сообщения
1,672
Реакции
1,497
Помог
24 раз(а)
Сообщения
271
Реакции
84
fl0wer, можешь показать пример плагина, который сломается?
 
Сообщения
1,672
Реакции
1,497
Помог
24 раз(а)
Сообщения
271
Реакции
84
fl0wer, это теория, есть ли конкретный плагин, который пострадает. Обычно люди которые инициализируют в init() не используют cfg().
 
Сообщения
3,393
Реакции
1,487
Помог
125 раз(а)
Refresh, это не теория а обратная совместимость называется.
 
Сообщения
1,672
Реакции
1,497
Помог
24 раз(а)
Поскольку делает она это асинхронным запросом
AutoExecConfig не делает это асинхроно, асинхороно это когда с коллбэком.
Тут же просто через натив добавляются все кфг со всех плагинов в хранилище, а после plugin_cfg вызывается создание всех добавленных конфигов.
С одной стороны прикольно, что собрали все конфиги и после plugin_cfg создали, но какой смысла тогда от таких конфигов, которые даже в прекеше не могу использовать, ведь cfg как раз таки и говорит о том, как программа должна работать, а не присобачиваться где-то потом.

 
Сообщения
1,184
Реакции
2,156
Помог
57 раз(а)
Под "асинхронно" понимается не мгновенный результат.
 
Сообщения
1,672
Реакции
1,497
Помог
24 раз(а)
Nordic Warrior, тогда создать еще 1 форвард, перед precache().
Такой форвард есть, называется plugin_natives, он вызывается раньше precache.

Только вот загвоздка в том, что это никак не поменяет ситуацию, так как конфиги сначала собираются, а потом создаются после plugin_cfg.
 
Сообщения
271
Реакции
84
fl0wer, в любом случае надо что-то двигать, либо precache переместить после cfg(), либо cfg() перед precache(). Это будет не сильно сложная задача исправить совместимость плагина с новой версией amxx.
 
Сообщения
1,672
Реакции
1,497
Помог
24 раз(а)
Refresh, исходники у amxmodx открыты, как говорится велком. Перемещать ничего не надо, нужно хранилище убрать и создавать по факту вызова натива, тогда никакая совместимость не сломается.
 

AUF

Сообщения
73
Реакции
9
тоже волнует этот вопрос) bot писал про актуальные значения кваров OnConfigsExecuted()
но допустим есть квар bind_pcvar_string(create_cvar("snd_path", "events/task_complete.wav"), SND_PATH, charsmax(SND_PATH))
и что бы этот квар нормально читался нужно грузить его первым в plugin_precache и далее вызывать кфг из plugin_precache
server_cmd("exec addons/amxmodx/configs/Конфиг.cfg")
server_exec()
и далее
precache_sound или precache_generic для загрузки игроку.
можно ли как то вызвать нормально конфиг и прочитать из него квар нормально в таком случаи?? просто если конфиг не вызвать в plugin_precache а позже то и в plugin_precache не попадет сам звук который надо загрузить игроку исходя из квара.
также и AutoExecConfig конфиг создает с кварами но прочитать то что в кваре в plugin_precache не получается. бред да и только)
спасает только это
server_cmd("exec addons/amxmodx/configs/Конфиг.cfg")
server_exec()
вызвал когда нужно и в любой момент да хоть 100 раз) а кто то это называет быдлокодом) тут я бы поспорил теже 100 раз!)
 
Сообщения
327
Реакции
289
Помог
9 раз(а)
но допустим есть квар bind_pcvar_string(create_cvar("snd_path", "events/task_complete.wav"), SND_PATH, charsmax(SND_PATH))
Ну, это же вы его сделали кваром. Он у вас меняется в течение карты? Есть необходимость его изменения через консоль в процессе игры?

и что бы этот квар нормально читался нужно грузить его первым в plugin_precache и далее вызывать кфг из plugin_precache
И чтобы ЭТО нормально читалось, нужно внести его в *.ini и оттуда читать. Для чтения настроек из файла давно придумали парсеры.
 
Сообщения
271
Реакции
84
Финт с RequestFrame() не работает, если в каком-то плагине написанном небыдлокодером внутри plugin_init() или plugin_cfg() используется :
Код:
server_cmd("exec %s")
server_exec()
Замкнутый круг :rofl:
 
Последнее редактирование:

Пользователи, просматривающие эту тему

Сейчас на форуме нет ни одного пользователя.
Сверху Снизу