Активный
- Тема Автор
- #1
Когда пригодится
Администраторам приходится запускать десятки периодических процессов: автосейв игроков, напоминания об ивентах, обновление текстдравов. Когда каждый процесс живёт на собственном SetTimer, обслуживать их тяжело. Планировщик объединяет задачи в единый список и даёт ручной контроль.
Структура расписания
Регистрация
Сердце планировщика
Глобальный тикер раз в секунду проверяет накопившееся время и вызывает обработчики.
Инициализация
Примеры обработчиков
Команды для админов
* `/tasks` — вывести список задач с интервалами.
* `/taskoff Autosave` — отключить задачу по имени (TaskEnabled = 0).
* `/taskrun EventHint` — принудительно выполнить обработчик.
Логирование и защита
* Добавьте лог в SchedulerTick, чтобы видеть длительность вызовов.
* Для тяжёлых задач ведите флаг Busy, чтобы не запускать их повторно, пока предыдущий запуск не завершён.
* Старайтесь держать обработчики короткими; сложную работу выносите в отдельные функции и запускайте через CallRemoteFunction/Timers.
Расширение
1. Храните задачи в `tasks.json`, чтобы админы могли редактировать расписание без перекомпиляции.
2. Добавьте поле `TaskArgs`, где держите JSON-строку с параметрами (например, ID события).
3. Реализуйте приоритеты: сначала выполняйте задачи с коротким интервалом, затем остальные.
Проверка
* Создайте тестовую задачу, которая каждые 10 секунд пишет текущую дату в чат.
* Отключите её через `/taskoff`, убедитесь, что сообщения пропали.
* Сделайте одноразовую задачу (repeat = 0), чтобы проверить, что она исчезает после выполнения.
Система унифицированного планировщика задач в Pawn
Когда пригодится
Администраторам приходится запускать десятки периодических процессов: автосейв игроков, выдачу напоминаний о событиях, обновление текстдравов. Если каждый процесс живёт своим SetTimer, разобраться трудно. Планировщик объединяет все таймеры, даёт ручное управление и журнал.
Базовая структура
Регистрация задач
Сердце планировщика
Глобальный таймер раз в секунду проверяет накопившееся время и вызывает нужные обработчики.
Инициализация
Пример обработчиков
Команды для админов
* `/tasks` — выводит список активных задач, интервал и время до следующего запуска.
* `/taskoff Autosave` — отключить задачу по имени (просто ставим `TaskEnabled = 0`).
* `/taskrun EventHint` — принудительно выполнить обработчик и сбросить таймер.
Журналирование
Добавьте лог в `SchedulerTick`, чтобы видеть длительность вызовов. Если обработчик выполняется дольше интервала, сделайте флаг “Busy” и пропускайте следующие циклы, пока задача не завершается.
Расширение
1. Загружайте список задач из `tasks.json`, чтобы админы могли править расписание без перекомпиляции.
2. Добавьте тип `TaskArgs`, где храните параметры (например, ID события), и передавайте их в обработчик через `CallLocalFunction`.
3. Введите приоритеты: сначала выполняем срочные задачи (интервал < 1 мин), потом все остальные.
Почему это работает
Единый планировщик делает сервер прозрачным: из лога видно, какие процессы живут, а какие отключены. Если нужно временно заморозить кусок логики, достаточно отключить одну запись, а не охотиться за сотней SetTimer.
Администраторам приходится запускать десятки периодических процессов: автосейв игроков, напоминания об ивентах, обновление текстдравов. Когда каждый процесс живёт на собственном SetTimer, обслуживать их тяжело. Планировщик объединяет задачи в единый список и даёт ручной контроль.
Структура расписания
Код:
enum TaskInfo
{
TaskName[32],
TaskInterval, // миллисекунды
TaskElapsed, // накопитель
TaskEnabled,
TaskRepeat,
TaskHandler[32]
}
new Scheduler[64][TaskInfo];
new SchedulerCount;
Регистрация
Код:
AddTask(const name[], interval, repeat, const handler[])
{
if(SchedulerCount >= sizeof(Scheduler))
return -1;
new idx = SchedulerCount++;
format(Scheduler[idx][TaskName], 32, "%s", name);
Scheduler[idx][TaskInterval] = interval;
Scheduler[idx][TaskRepeat] = repeat;
Scheduler[idx][TaskHandler] = handler;
Scheduler[idx][TaskElapsed] = 0;
Scheduler[idx][TaskEnabled] = 1;
return idx;
}
Сердце планировщика
Глобальный тикер раз в секунду проверяет накопившееся время и вызывает обработчики.
Код:
forward SchedulerTick();
public SchedulerTick()
{
for(new i = 0; i < SchedulerCount; i++)
{
if(!Scheduler[i][TaskEnabled])
continue;
Scheduler[i][TaskElapsed] += 1000;
if(Scheduler[i][TaskElapsed] >= Scheduler[i][TaskInterval])
{
Scheduler[i][TaskElapsed] = 0;
CallLocalFunction(Scheduler[i][TaskHandler], "i", i);
if(!Scheduler[i][TaskRepeat])
{
Scheduler[i][TaskEnabled] = 0;
}
}
}
return 1;
}
Инициализация
Код:
public OnGameModeInit()
{
AddTask("Autosave", 300000, 1, "Task_Autosave");
AddTask("EventHint", 60000, 1, "Task_EventHint");
SetTimer("SchedulerTick", 1000, true);
return 1;
}
Примеры обработчиков
Код:
forward Task_Autosave(taskid);
public Task_Autosave(taskid)
{
foreach(new i : Player)
{
SavePlayerData(i);
}
printf("[TASK] %s выполнена", Scheduler[taskid][TaskName]);
return 1;
}
forward Task_EventHint(taskid);
public Task_EventHint(taskid)
{
SendClientMessageToAll(-1, "[EVENT] До старта гонки 10 минут!");
return 1;
}
Команды для админов
* `/tasks` — вывести список задач с интервалами.
* `/taskoff Autosave` — отключить задачу по имени (TaskEnabled = 0).
* `/taskrun EventHint` — принудительно выполнить обработчик.
Логирование и защита
* Добавьте лог в SchedulerTick, чтобы видеть длительность вызовов.
* Для тяжёлых задач ведите флаг Busy, чтобы не запускать их повторно, пока предыдущий запуск не завершён.
* Старайтесь держать обработчики короткими; сложную работу выносите в отдельные функции и запускайте через CallRemoteFunction/Timers.
Расширение
1. Храните задачи в `tasks.json`, чтобы админы могли редактировать расписание без перекомпиляции.
2. Добавьте поле `TaskArgs`, где держите JSON-строку с параметрами (например, ID события).
3. Реализуйте приоритеты: сначала выполняйте задачи с коротким интервалом, затем остальные.
Проверка
* Создайте тестовую задачу, которая каждые 10 секунд пишет текущую дату в чат.
* Отключите её через `/taskoff`, убедитесь, что сообщения пропали.
* Сделайте одноразовую задачу (repeat = 0), чтобы проверить, что она исчезает после выполнения.
Система унифицированного планировщика задач в Pawn
Когда пригодится
Администраторам приходится запускать десятки периодических процессов: автосейв игроков, выдачу напоминаний о событиях, обновление текстдравов. Если каждый процесс живёт своим SetTimer, разобраться трудно. Планировщик объединяет все таймеры, даёт ручное управление и журнал.
Базовая структура
Код:
enum TaskInfo
{
TaskName[32],
TaskInterval, // миллисекунды
TaskElapsed, // накопитель
TaskEnabled,
TaskRepeat,
TaskHandler[32]
}
new Scheduler[64][TaskInfo];
new SchedulerCount;
Регистрация задач
Код:
AddTask(const name[], interval, repeat, const handler[])
{
if(SchedulerCount >= sizeof(Scheduler))
return -1;
new idx = SchedulerCount++;
format(Scheduler[idx][TaskName], 32, "%s", name);
Scheduler[idx][TaskInterval] = interval;
Scheduler[idx][TaskRepeat] = repeat;
Scheduler[idx][TaskHandler] = handler;
Scheduler[idx][TaskElapsed] = 0;
Scheduler[idx][TaskEnabled] = 1;
return idx;
}
Сердце планировщика
Глобальный таймер раз в секунду проверяет накопившееся время и вызывает нужные обработчики.
Код:
forward SchedulerTick();
public SchedulerTick()
{
for(new i = 0; i < SchedulerCount; i++)
{
if(!Scheduler[i][TaskEnabled])
continue;
Scheduler[i][TaskElapsed] += 1000;
if(Scheduler[i][TaskElapsed] >= Scheduler[i][TaskInterval])
{
Scheduler[i][TaskElapsed] = 0;
CallLocalFunction(Scheduler[i][TaskHandler], "i", i);
if(!Scheduler[i][TaskRepeat])
{
Scheduler[i][TaskEnabled] = 0;
}
}
}
return 1;
}
Инициализация
Код:
public OnGameModeInit()
{
AddTask("Autosave", 300000, 1, "Task_Autosave");
AddTask("EventHint", 60000, 1, "Task_EventHint");
SetTimer("SchedulerTick", 1000, true);
return 1;
}
Пример обработчиков
Код:
forward Task_Autosave(taskid);
public Task_Autosave(taskid)
{
foreach(new i : Player)
{
SavePlayerData(i);
}
printf("[TASK] %s завершена", Scheduler[taskid][TaskName]);
return 1;
}
forward Task_EventHint(taskid);
public Task_EventHint(taskid)
{
SendClientMessageToAll(-1, "[EVENT] До старта гонки 10 минут!");
return 1;
}
Команды для админов
* `/tasks` — выводит список активных задач, интервал и время до следующего запуска.
* `/taskoff Autosave` — отключить задачу по имени (просто ставим `TaskEnabled = 0`).
* `/taskrun EventHint` — принудительно выполнить обработчик и сбросить таймер.
Журналирование
Добавьте лог в `SchedulerTick`, чтобы видеть длительность вызовов. Если обработчик выполняется дольше интервала, сделайте флаг “Busy” и пропускайте следующие циклы, пока задача не завершается.
Расширение
1. Загружайте список задач из `tasks.json`, чтобы админы могли править расписание без перекомпиляции.
2. Добавьте тип `TaskArgs`, где храните параметры (например, ID события), и передавайте их в обработчик через `CallLocalFunction`.
3. Введите приоритеты: сначала выполняем срочные задачи (интервал < 1 мин), потом все остальные.
Почему это работает
Единый планировщик делает сервер прозрачным: из лога видно, какие процессы живут, а какие отключены. Если нужно временно заморозить кусок логики, достаточно отключить одну запись, а не охотиться за сотней SetTimer.