Автоматоны Pawn
В языке Pawn есть механизм состояний(автоматон) - это такая система, которая позволяет определить несколько копий одной функции для использования в различных условиях. Я начну объяснять с примера, ибо так получится более наглядно, а ниже подробно опишу эту систему.
Пример🔗︎
Допустим нам нужно сохранить данные игрока и данные гонок, а также сообщить об этом игрокам и гонщикам соответственно. При обычной реализации код выглядит грязновато:
#include <a_samp>
forward data_Save(type);
forward message_Save(type);
enum {
players,
races
}
main() {
data_Save(players);
message_Save(players);
}
public data_Save(type)
{
switch (type) {
case players: {
// saving
}
case races: {
// saving
}
}
}
public message_Save(type)
{
switch (type) {
case players: {
// send message to player
}
case races: {
// send message to racers
}
}
}
А реализация с помощью автоматонов выглядит очень элегантно:
#include <a_samp>
forward data_Save();
forward message_Save();
main() {
state dataType:players;
data_Save();
message_Save();
}
public data_Save() <dataType:players>
{
// saving
}
public data_Save() <dataType:races>
{
// saving
}
public message_Save() <dataType:players>
{
// send message to players
}
public message_Save() <dataType:races>
{
// send message to racers
}
Плюсы этого метода🔗︎
А если понадобится добавить в список выше что-нибудь ещё? Код без автоматонов превратиться в огромный switch
! А если вы, например, захотите перенести код сохранения данных гонки в файл race/data.inc
? Тогда вам придётся создавать дополнительную функцию и заносить её туда! Но с автоматонами это делается гораздо проще.
Ещё можно отметить то, что конструкция, выполненная с помощью автоматонов, работает немного быстрее, чем функция с большим switch
.
Теория🔗︎
state🔗︎
Этим кодом мы устанавливаем для dataType
состояние players
state dataType:players;
Для проверок, связанных с автоматонами, есть сокращённое написание, например этот код:
state (var == 1) dataType:races;
эквивалентен этому:
if (var == 1) {
state dataType:races;
}
entry()🔗︎
Для автоматонов зарезервирована специальная функция entry()
, которая вызывается при установке состояния.
Пример:
#include <a_samp>
main() {
printf("Hello");
state entryTest:message;
printf("World!");
}
entry() <entryTest:message>
{
printf("Test");
}
Результатом выполнения этого кода будет:
Hello
Test
World
Функции🔗︎
Вы можете объявлять функции с одним состоянием:
stock echo(msg[]) <exType:one>
{
print(msg);
}
С несколькими:
stock echo(msg[]) <exType:one,exType:two>
{
print(msg);
}
(эта функция будет вызвана при состоянии one
или two
).
И с любым другим состоянием:
stock echo(msg[]) <>
{
print(msg);
}
(эта функция будет вызвана если не было вызвано ни одной функции со своим состоянием).