[F.A.Q] Оптимизация SendClientMessage / SCMTA - Форум Cheat-Master.ru
  • Страница 1 из 1
  • 1
Модератор форума: Phoenixxx_Czar, Getbackthere, [CM]OlegEhtler  
[F.A.Q] Оптимизация SendClientMessage / SCMTA
DECODE Дата: Среда, 02.08.2017, 09:15 | Сообщение # 1
Coder
Сообщений: 189
Статус: Offline
Доброго времени суток, уважаемые посетители данной темы!

Хотел бы вам предложить способ, который не многим известен, а именно - оптимизация двух функций SendClientMessage (вывод сообщения какому-либо игроку) и SendClientMessageToAll (вывод сообщения всему серверу).
Многие в своем коде используют форматирование с помощью инициализации переменной, с последующим ее форматированием по типу:
Код

new string[MAX_PLAYER_NAME + 30]; // Константа с максимальным размером имени игрока + 30 доп. символов
format(string, sizeof(string), "[DBG] %s[%d] вывел сообщение %s", PlayerName(playerid), playerid, "TestText");
return SendClientMessage(playerid, -1, string);


Или
Код

static const str[] = "[DBG] %s[%d] вывел сообщение %s"; // Константа с заготовленным текстом, автоматический подсчет количества символов.
new string[sizeof(str) + MAX_PLAYER_NAME + 10]; // Исходя из размера константы добавляем доп. 10 ячеек для вывода аргументов.
format(string, sizeof(string), str, PlayerName(playerid), playerid, "SomeText"); // Форматирование строки.
return SendClientMessage(playerid, 0xFFDA03FF, string); // Вывод строки.


Второй вариант, на мой взгляд, удобнее, так как нам нужно меньше заниматься подсчетами, но опять же это не самый лучший вариант. На форуме sa-mp было предложено небольшое решение для оптимизации этих функций. Выглядит это следующим образом:
Код

stock SendMes(playerid, fstring[], {Float, _}:...)
{
    static const STATIC_ARGS = 3;
    new n = (numargs() - STATIC_ARGS) * BYTES_PER_CELL;
    if (n)
    {
        new message[128], arg_start, arg_end;
        #emit CONST.alt        fstring
        #emit LCTRL          5
        #emit ADD
        #emit STOR.S.pri        arg_start
        #emit LOAD.S.alt        n
        #emit ADD
        #emit STOR.S.pri        arg_end
        do
        {
            #emit LOAD.I
            #emit PUSH.pri
            arg_end -= BYTES_PER_CELL;
            #emit LOAD.S.pri      arg_end
        }
        while (arg_end > arg_start);
        // Push the static format parameters.
        #emit PUSH.S          fstring
        #emit PUSH.C          128
        #emit PUSH.ADR         message
        n += BYTES_PER_CELL * 3;
        #emit PUSH.S          n
        #emit SYSREQ.C         format
        n += BYTES_PER_CELL;
        #emit LCTRL          4
        #emit LOAD.S.alt        n
        #emit ADD
        #emit SCTRL          4
        return SendClientMessage(playerid, 0xFFFFFF, message);
    }
    else return SendClientMessage(playerid, 0xFFFFFF, fstring);
}


Код

stock SendMesAll(fstring[], {Float, _}:...)
{
    static const STATIC_ARGS = 2;
    new n = (numargs() - STATIC_ARGS) * BYTES_PER_CELL;
    if (n)
    {
        new message[128], arg_start, arg_end;
        #emit CONST.alt        fstring
        #emit LCTRL          5
        #emit ADD
        #emit STOR.S.pri        arg_start
        #emit LOAD.S.alt        n
        #emit ADD
        #emit STOR.S.pri        arg_end
        do
        {
            #emit LOAD.I
            #emit PUSH.pri
            arg_end -= BYTES_PER_CELL;
            #emit LOAD.S.pri      arg_end
        }
        while (arg_end > arg_start);
        // Push the static format parameters.
        #emit PUSH.S          fstring
        #emit PUSH.C          128
        #emit PUSH.ADR         message
        n += BYTES_PER_CELL * 3;
        #emit PUSH.S          n
        #emit SYSREQ.C         format
        n += BYTES_PER_CELL;
        #emit LCTRL          4
        #emit LOAD.S.alt        n
        #emit ADD
        #emit SCTRL          4
        return SendClientMessageToAll(0xFFFFFF, message);
    }
    else return SendClientMessageToAll(0xFFFFFF, fstring);
}


Есть один небольшой нюанс, ходят слухи, что может крашнуть мод, но лично я не сталкивался с такими ситуациями.

Есть второй вариант, он заключается в удобстве использования функций, не придется по сто раз проводить форматирование и т.д. Это сделает макрос, который выглядит следующим образом:
Код

#define SendFormPlayer(%1,%2,%3)    format(st144,144,%3),SendClientMessage(%1,%2,st144)
#define SendFormAll(%1,%2)          format(st144,144,%2),SendClientMessageToAll(%1,st144)

new str144[144]; // глобальная переменная

stock MyFunction(playerid) // Пробная функция для вывода сообщения.
{
    SendFormAll(0xFFFFFFFF, "Игрок ID: %i ...", playerid);
    return SendFormPlayer(playerid, 0xFFFFFFFF, "Мой ID: %i", playerid);
}  


В принципе, вот и все. Если будут какие-то вопросы, то желательно задавать их в Вконтакте.

По первым двум способам - идет использование функций, которые обращаются напрямую к машине, с помощью ASM (Assembler).

Пример использования функций из первого способа:
Код

SendMes(playerid, 0xFFDA03AA, "%s[%d] вывел сообщение %s", PlayerName(playerid), playerid, "SomeText");
SendMesAll(0xFFDA03AA, "%s[%d] вывел сообщение для всех %s", PlayerName(playerid), playerid, "SomeText"); // Представим, что кто-то ввел команду для вывода сообщения.


Краткий экскурс по ф-иям:
Код

//==================================
#endinput // копирует код.
#emit // обращение к виртуальной машине.
#pragma ctrlchar - Данная директива заменяет escape-символ. (\n)
//==================================


p.s В примерах вызвана функция PlayerName(), ее в данной теме нет, это оптимизированная функция определения имени игрока.


► Оптимизация SCM / SMTA (pawn): http://cheat-master.ru/forum/117-706531-1
► CM Smiles - Mini Chat (v1.0): http://cheat-master.ru/forum/2-706062-1
► [Evolve-RP] - Баг на деньги (история тестера): http://cheat-master.ru/forum/282-709301-1
► Накрутка сообщений в ВКонтакте (new): http://cheat-master.ru/forum/199-709369-1


Сообщение отредактировал DECODE - Среда, 02.08.2017, 09:51
[CM]MaddyS[CM] Дата: Среда, 02.08.2017, 13:54 | Сообщение # 2
Боец
Сообщений: 75
Статус: Offline
Не плохо, +сиг
DECODE Дата: Четверг, 03.08.2017, 15:47 | Сообщение # 3
Coder
Сообщений: 189
Статус: Offline
MbUp.

► Оптимизация SCM / SMTA (pawn): http://cheat-master.ru/forum/117-706531-1
► CM Smiles - Mini Chat (v1.0): http://cheat-master.ru/forum/2-706062-1
► [Evolve-RP] - Баг на деньги (история тестера): http://cheat-master.ru/forum/282-709301-1
► Накрутка сообщений в ВКонтакте (new): http://cheat-master.ru/forum/199-709369-1
=) Дата: Четверг, 03.08.2017, 19:46 | Сообщение # 4
Боец
Сообщений: 271
Статус: Offline
Лучший способ.
Цитата DECODE ()
new string[MAX_PLAYER_NAME + 30]; // Константа с максимальным размером имени игрока + 30 доп. символов
format(string, sizeof(string), "[DBG] %s[%d] вывел сообщение %s", PlayerName(playerid), playerid, "TestText");
return SendClientMessage(playerid, -1, string);


Способ для ленивцев.
Цитата DECODE ()
static const str[] = "[DBG] %s[%d] вывел сообщение %s"; // Константа с заготовленным текстом, автоматический подсчет количества символов.
new string[sizeof(str) + MAX_PLAYER_NAME + 10]; // Исходя из размера константы добавляем доп. 10 ячеек для вывода аргументов.
format(string, sizeof(string), str, PlayerName(playerid), playerid, "SomeText"); // Форматирование строки.
return SendClientMessage(playerid, 0xFFDA03FF, string); // Вывод строки.


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

Далее, в SendMesAll используется SendClientMessageToAll которая выполняет какое количество итераций? Правильно - которое стоит по умолчанию MAX_PLAYERS в инклюде, а именно = 2048 итерации (вроде так). Что на 1048 больше, чем вообще может быть игроков онлайн.

Для таких целей используется:
Код
stock SendMessageAll(color, text[])
{
    foreach(i:Player)
    {
        if(!PLayer[i][Online]) continue; // у кого какая проверка на авторизацию, если вообще нужна
        else if(!PLayer[i][gChat]) continue; // у кого какая проверка на отображение чата, если вообще нужна

        SendClientMessage(i, color, text);
    }
    return 1;
}


Цитата DECODE ()
#define SendFormPlayer(%1,%2,%3)    format(st144,144,%3),SendClientMessage(%1,%2,st144)
#define SendFormAll(%1,%2)          format(st144,144,%2),SendClientMessageToAll(%1,st144)

new str144[144]; // глобальная переменная


Ты используешь переменную для хранения 144-рех символов, но забываешь, что всегда должна быть ячейка под конец строки '/0'. То есть str144[144] должен быть str145[145].

Вот и выходит, что ты вводишь пользователей в заблуждение, оперируя дурными данными.


Сообщение отредактировал =) - Четверг, 03.08.2017, 20:02
DECODE Дата: Четверг, 03.08.2017, 23:14 | Сообщение # 5
Coder
Сообщений: 189
Статус: Offline
Цитата =) ()
Ты используешь переменную для хранения 144-рех символов, но забываешь, что всегда должна быть ячейка под конец строки '/0'. То есть str144[144] должен быть str145[145].

Вот и выходит, что ты вводишь пользователей в заблуждение, оперируя дурными данными.

Ладно, победил. Тут даже спорить не буду, давно отошел от разработок pawn, голова совсем не думает. О способах с функциями - предупредил сразу, насчет строки - тоже просчет, и, да, немного стыдно. Пожалуй, нужно завязывать с этой сферой.


► Оптимизация SCM / SMTA (pawn): http://cheat-master.ru/forum/117-706531-1
► CM Smiles - Mini Chat (v1.0): http://cheat-master.ru/forum/2-706062-1
► [Evolve-RP] - Баг на деньги (история тестера): http://cheat-master.ru/forum/282-709301-1
► Накрутка сообщений в ВКонтакте (new): http://cheat-master.ru/forum/199-709369-1
=) Дата: Пятница, 04.08.2017, 09:16 | Сообщение # 6
Боец
Сообщений: 271
Статус: Offline
Цитата DECODE ()
Ладно, победил. Тут даже спорить не буду, давно отошел от разработок pawn, голова совсем не думает. О способах с функциями - предупредил сразу, насчет строки - тоже просчет, и, да, немного стыдно. Пожалуй, нужно завязывать с этой сферой.


Да я с тобой не воевал. Такие мелочи легко запомнить и дополнить урок.
Любой чего-то да не знает. А вот сдаваться при первых трудностях - вот это постыдно.
Хотя, в павно конечно нет, ведь кому он нужен. Бесполезная трата времени.


Сообщение отредактировал =) - Пятница, 04.08.2017, 09:17
  • Страница 1 из 1
  • 1
Поиск:
Статистика Форума
Лучшие пользователи
Admin [39113]

GеNius [7210]

[CM]Russel [5557]

kenlo763 [4952]

[CM]AGRESSOR [4639]

Snake_Firm [4452]

Сэс [4416]

Artem_Buero [4223]

[CM]Durman [3204]

[CM]Рафаэль [3080]

iMaddy [2855]

sky_Woker [2854]

getrekt [2745]

Новые пользователи
dcvfre [11:04]

Sheroz [10:38]

dominiquevp60 [08:59]

derrickuy11 [05:48]

leannaaw60 [04:45]

nonaxn11 [23:52]

arbuzikkks [17:38]

gwendolyngd2 [16:08]

Drywallwje [11:38]

TronAccs [05:11]

danilka05cher [03:05]

kennethhf2 [00:44]

nikitaw13w [15:10]