Гайд Создание отдельного чата при помощи итераторов

  • Автор темы deleted-user-520255
  • Дата начала
D

deleted-user-520255

Гость
Автор темы
Всем привет. Сегодня создадим отдельный чат для игроков, а также узнаем про итераторы.
Итератор - это объект, благодаря которому можно перемещаться по элементам некоторой последовательности.
Именно, это нам скажет гугл, если мы введем запрос: "Что такое Итератор?"
Сначала, вам может показаться, что это все сложно, непонятно и т.п т.к т.е т.д
Но давайте разберем итераторы на примере создание команды /a



Начнем.

Начнем с того, что создадим наш итератор(Для этого вам потребуется установить инклуд foreach):
C:
new Iterator:Admins<MAX_PLAYERS>;
В <> пишется максимальное значение итератора(В нашем случае, MAX_PLAYERS(Макс. значение игроков))
Теперь у нас есть пустой итератор
Поскольку, мы делаем команду /a, нам нужно добавлять админа в итератор при авторизации.
Для этого, вам понадобится мод, в котором уже есть /alogin.
Идем в команду /alogin и пытаемся понять как она работает.
В основном, она работает через диалог(Но, все равно, может и через саму команду)
Теперь, нам нужно добавить админа в итератор после успешной авторизации.
Делается это вот так:
C:
Iter_Add(Admins,playerid);
Метод Add добавляет значение к указанному итератору.
В нашем случае, как значение, мы указываем id игрока.
(В начале указывается итератор, а потом значение, которое мы прибавляем)
Теперь, после того как, мы добавили игрока к итератору, можно приступать к созданию самой команды.
Начнем с того, что добавим функцию, которая отправит сообщение игроку.​
C:
stock SendAdminMessage(color,const astring[])
{
    foreach(new i: Admins) SendClientMessage(i,color,astring);
    return 1;
}
Наш сток будет принимать в себя цвет и саму строчку.
Разберем сам цикл:
Переменная i будет равняться айди всех админов(Потому что, Admins - это название нашего итератора) , поэтому в функции SendClientMessage вместо playerid и т.п мы используем i
Теперь приступим к созданию команды /a​
C:
CMD:a(playerid,params[])
{
    if(!Iter_Contains(Admins,playerid)) return SCM(playerid,COLOR_WHITE,"Вы не авторизовались как администратор");
    if(sscanf(params,"s[144]",params[0])) return SCM(playerid,COLOR_WHITE,"Используйте /a [Текст]");
    static const fmt_achat[]="[A] %s: %s";
    new achat[sizeof(fmt_achat)+(-2+20)+(-2+144)];
    format(achat,sizeof(achat),fmt_achat,players[playerid][name],params[0]);
    SendAdminMessage(COLOR_WHITE,achat);
    return 1;
}
Теперь разберем код:
if(!Iter_Contains) - Если указанное значение не принадлежит итератору(В нашем случае, значение - playerid)
Короче, сработает, если игрок не авторизовался в alogin
if(sscanf(params,"s[144]",params[0])) (Убедитесь в наличие плагина sscanf!) - Здесь, нас интересует "s[144]" и params[0]
В кавычках то, что должно идти в параметры
s - это тип данных(string(В переводе "Строка"))
144 - это макс. возможное кол-во символов в строке.
И если игрок написал все правильно(Например "/a Привет"), тогда параметр s[144] запишется в params[0]
Если вы не понимаете, что такое параметры:
Например, у админа есть команда кик(/kick) и чтобы команда выполнилась, он должен написать туда id и причину(Например, /kick 0 идиот)
Так вот 0 и идиот будет являться параметрами. 0 - это первый параметр, идиот - второй.
Еще, можно записывать параметры не в params, а в обыч. переменные(Заменив params на любое название переменной(Конечно же не глобальной))
Команда кик в sscanf выглядит вот так:
C:
if(sscanf(params,"ds[24]",params[0],params[1])) return SCM(playerid,COLOR_WHITE,"Используйте /kick [ID] [Причина]");
d - это целое число(Т.к id игрока не может быть 4.6 или строкой)
s[24] - строка, которая хранит причину и она не может быть больше 24 символов
Переходим к заключению:
Теперь будем разбирать каждую строчку:
C:
static const fmt_achat[]="[A] %s: %s";
Создаем статическую константу для форматирования, чтобы рассчитать длину строки(Может показаться сложным, но на деле не так)
Переменная, объявленная с ключ. словом static будет храниться всегда, а const запрещает изменять значение переменной.
C:
new achat[sizeof(fmt_achat)+(-2+20)+(-2+144)];
Создаем новую строку, чтобы рассчитать длину строки правильно
Теперь подробнее:
Как вы знаете, все строки в Pawno имеют размерности(new str[256];)
Это тот случай, когда размер имеет значение(Гы)
Размерность - это максимальное кол-во символов в строке
Если мы сделаем вот так:
C:
new str[5]="Привет";
То столкнемся с ошибкой, что у нас размерность не правильная.
Но и сильно большую размерность ставить НЕЛЬЗЯ!
Почему
: Потому что 1 незанятый символ = 1 незанятому байту.
Если вы всегда будете неправильно рассчитывать строки - ваш сервер будет сильно лагать(И т.п)
(Вообще, функция format принимает: строка, которая будет отформатирована, размерность, форматируемые данные)
Теперь, рассмотрим эту строку еще раз.
В размерность я написал: sizeof(fmt_achat)
Оператор sizeof возвращает длину строки(Кол-во символов)
И тогда размерность строки будет - 10, потому что "[A] %s: %s" - это 10 символов(Кавычки не считаются)
Далее, я пишу следующее: +(-2+20)+(-2+144)
Что это такое:
Когда мы хотим отформатировать строку, мы используем спецификатор.
Спецификатор - это тип данных, на место которого станет значение при формате
Подробнее:

C:
new per=10;
printf("The Per Is %d",per);

                                                two
new str[6]="Привет"
printf("The Str Is %s",str);
Здесь, я привет сразу два примера: Со строкой и с переменной, которая хранит целое число.
При форматировании, на место спецификатора(%s %d %f и т.п) встанет, какое-то значение(Точнее, то которое мы указали в форматировании, (per и str в printf))
Вернемся к нашей строчке:
Так, почему же все таки -2?
Потому что оператор sizeof возвращает длину строки вместе со спецификатором, а когда мы форматируем строки, на место спецификатора становится значение, а сам спецификатор убирается. Поэтому, мы отнимаем память, занятую спецификатором и добавляем макс. размерность значения(У ника макс. размер - 20, у params[0] - 144).
Форматирование:
C:
format(achat,sizeof(achat),fmt_achat,players[playerid][name],params[0]);
В форматируемые данные пишем нашу стат. константу
И наконец, отправляем отформатированную строку:
C:
SendAdminMessage(COLOR_WHITE,achat);
Исправление ошибок:
error 017: undefined symbol "players"| error 017: undefined symbol "name"
Вместо players используйте название своего массива(В основном, player_info, pInfo, PInfo)
error 017: undefined symbol "COLOR_WHITE" | error 017: undefined symbol "SCM"
Добавьте к начало мода:
C:
#define SCM SendClientMessage
#define COLOR_WHITE 0xFFFFFFFF