#include <amxmodx>
#include <amxmisc>
public plugin_init() {
register_plugin("File List Creator", "0.1.2", "VinSKy ");
register_cvar("pc_ini_file", "file_list_creator.ini");
set_task(5.0, "generate_file_lists"); // Автоматический запуск через 5 секунд после загрузки плагина
}
public generate_file_lists() {
new ini_path[128];
get_localinfo("amxx_configsdir", ini_path, sizeof(ini_path));
new pc_ini[64];
get_pcvar_string(get_cvar_pointer("pc_ini_file"), pc_ini, sizeof(pc_ini));
format(ini_path, sizeof(ini_path), "%s/%s", ini_path, pc_ini);
new file_ini = fopen(ini_path, "r");
if (!file_ini) {
// Создать дефолтный INI файл
file_ini = fopen(ini_path, "w");
if (file_ini) {
fputs(file_ini, "// Конфигурация File List Creator^n");
fputs(file_ini, "// Формат: ^"расширение^" ^"директория^" ^"включить точку^" ^"файлы конфигов^" ^n");
fputs(file_ini, "// ^"расширение^" - без точки (например amxx, bsp)^n");
fputs(file_ini, "// ^"директория^" - абсолютный путь к папке, которую сканировать (можно относительный путь от корня сервера)^n");
fputs(file_ini, "// ^"включать_точку^" - 1 = добавлять точку перед расширением (.amxx), 0 = не добавлять (amxx)^n");
fputs(file_ini, "// ^"файлы_конфигов^" - абсолютные пути к файлам, куда писать список; несколько через |. Файл будет создан если его нет.^n");
fputs(file_ini, "// Примеры:^n");
fputs(file_ini, "// ^"amxx^" ^"/addons/amxmodx/plugins^" ^"1^" ^"/addons/amxmodx/configs/plugins.ini^"^n");
fputs(file_ini, "// ^"bsp^" ^"/maps^" ^"0^" ^"/mapcycle.txt|/addons/amxmodx/configs/maps.ini^"^n");
fputs(file_ini, "^n");
fputs(file_ini, "// ^"amxx^" ^"/addons/amxmodx/plugins^" ^"1^" ^"/addons/amxmodx/configs/plugins.ini^"^n");
fputs(file_ini, "// ^"bsp^" ^"/maps^" ^"0^" ^"/mapcycle.txt|/addons/amxmodx/configs/maps.ini^"^n");
fclose(file_ini);
log_amx("Created default INI file: %s", ini_path);
}
// Теперь открыть для чтения
file_ini = fopen(ini_path, "r");
if (!file_ini) {
log_amx("Failed to create or open INI file: %s", ini_path);
return;
}
}
new line[256];
while (!feof(file_ini)) {
fgets(file_ini, line, sizeof(line) - 1);
trim(line);
if (!strlen(line) || line[0] == ';') continue;
// Парсинг: поддержка формата в кавычках: "ext" "dir" "include_dot" "cfg1|cfg2"
new extension[32], dir[128], include_dot_str[8], configs_str[256];
if (line[0] == '"') {
// Используем поэтапное извлечение между кавычками
if (!extract_quoted(line, 0, extension, sizeof(extension))) continue;
if (!extract_quoted(line, 1, dir, sizeof(dir))) continue;
if (!extract_quoted(line, 2, include_dot_str, sizeof(include_dot_str))) continue;
if (!extract_quoted(line, 3, configs_str, sizeof(configs_str))) continue;
} else {
// Старый формат без кавычек (4 пробельно-разделенных токена)
new pos1 = strfind(line, " ");
if (pos1 == -1) continue;
copy(extension, sizeof(extension), line);
extension[pos1] = 0;
new temp[256];
copy(temp, sizeof(temp), line[pos1 + 1]);
new pos2 = strfind(temp, " ");
if (pos2 == -1) continue;
copy(dir, sizeof(dir), temp);
dir[pos2] = 0;
copy(temp, sizeof(temp), temp[pos2 + 1]);
new pos3 = strfind(temp, " ");
if (pos3 == -1) continue;
copy(include_dot_str, sizeof(include_dot_str), temp);
include_dot_str[pos3] = 0;
copy(configs_str, sizeof(configs_str), temp[pos3 + 1]);
}
new include_dot = str_to_num(include_dot_str);
new ext[32];
if (include_dot) {
format(ext, sizeof(ext), ".%s", extension);
} else {
copy(ext, sizeof(ext), extension);
}
// Разделить configs по |
new configs[5][128];
new count_configs = 0;
new start = 0;
new len_configs = strlen(configs_str);
for (new i = 0; i <= len_configs; i++) {
if (i == len_configs || configs_str == '|') {
new len_part = i - start;
formatex(configs[count_configs], sizeof(configs[]), "%.*s", len_part, configs_str[start]);
configs[count_configs][len_part] = 0;
trim(configs[count_configs]);
count_configs++;
start = i + 1;
if (count_configs >= 5) break;
}
}
// Обработать каждый config
for (new c = 0; c < count_configs; c++) {
new config_path[128];
copy(config_path, sizeof(config_path), configs[c]);
if (config_path[0] != '/') {
new temp_dir[128];
get_localinfo("amxx_configsdir", temp_dir, sizeof(temp_dir));
format(config_path, sizeof(config_path), "%s/%s", temp_dir, configs[c]);
}
new Trie:files = TrieCreate();
// Прочитать существующие
new file_read = fopen(config_path, "r");
if (file_read) {
new existing_line[64];
while (!feof(file_read)) {
fgets(file_read, existing_line, sizeof(existing_line) - 1);
trim(existing_line);
if (strlen(existing_line) > 0) {
TrieSetCell(files, existing_line, 1);
}
}
fclose(file_read);
}
// Сканировать dir
new filename[64];
new FileType:type;
new dirh = open_dir(dir, filename, sizeof(filename) - 1, type);
if (dirh) {
do {
new len = strlen(filename);
new ext_len = strlen(ext);
if (len > ext_len && strfind(filename, ext) == len - ext_len) {
if (!TrieKeyExists(files, filename)) {
TrieSetCell(files, filename, 1);
}
}
} while (next_file(dirh, filename, sizeof(filename) - 1, type));
close_dir(dirh);
}
// Записать обратно
new file_write = fopen(config_path, "w");
if (file_write) {
new key[64];
new Snapshot: snap = TrieSnapshotCreate(files);
new count = TrieSnapshotLength(snap);
for (new i = 0; i < count; i++) {
TrieSnapshotGetKey(snap, i, key, sizeof(key) - 1);
fprintf(file_write, "%s\n", key);
}
TrieSnapshotDestroy(snap);
fclose(file_write);
log_amx("Updated %s with %d files.", config_path, count);
}
TrieDestroy(files);
}
}
fclose(file_ini);
log_amx("File list creation completed.");
}
// Вспомогательная функция: извлечение n-го фрагмента в кавычках
stock bool:extract_quoted(const input[], index, output[], outlen) {
new len = strlen(input);
new quote_count = -1;
new i = 0;
while (i < len) {
if (input == '"') {
quote_count++;
new start = i + 1;
// Нечетные номера кавычек содержат содержимое
if ((quote_count % 2) == 0) {
// пропуск — это открывающая кавычка
} else {
new content_index = (quote_count - 1) / 2;
if (content_index == index) {
// найти закрывающую кавычку
new j = start;
while (j < len && input[j] != '"') j++;
new copy_len = j - start;
if (copy_len >= outlen) copy_len = outlen - 1;
for (new k = 0; k < copy_len; k++) output[k] = input[start + k];
output[copy_len] = 0;
trim(output);
return true;
}
}
}
i++;
}
return false;
}