PDA

Просмотр полной версии : [Include] zmessage - многострочные сообщения



ziggi
09.07.2016, 01:51
Описание

Небольшая библиотека, которая при превышении лимита символов делит отправляемое сообщение на части так, что оно будет гарантировано отправлено целиком.

"Под капотом" перехватываются функции SendClientMessage, SendClientMessageToAll, SendPlayerMessageToPlayer и SendPlayerMessageToAll. Передаваемая строка в них делится без использования дорогостоящих (format) или опасных (strins) функций, алгоритм довольно оптимальный, так что нет причин беспокоиться о заметном снижении производительности.

Использование

Просто подключите zmessage.inc.

Функции

Эта библиотека предоставляет только одну функцию, которая может быть полезной в некоторых случаях (https://github.com/Open-GTO/zmessage/issues/5). Несколько примеров использования можно найти здесь (https://github.com/Open-GTO/zmessage/issues/6).

ZMsg_GetMessages(message[], array[][], const lines = sizeof(array), const line_size = sizeof(array[]))

Параметры:

message[]: Оригинальное сообщение, которое должно быть разделено.
array[][]: Массив, в котором сохраняются разделённые строки.
lines: Количество строк, которое может быть сохранено в массив array.
line_size: Количество символов, которое может быть сохранено в одну строку массива array.

Возвращаемые значения:

Количество строк.



Константы
Доступно несколько констант, некоторые из них можно переназначить.


Константа
Значение по умолчанию
Можно переназначить?
Примечание


ZMSG_MAX_CHAT_LENGTH
MAX_CHATBUBBLE_LENGTH
да



ZMSG_MAX_PLAYER_CHAT_LENGTH
(MAX_CHATBUBBLE_LENGTH / 2)
да



ZMSG_SEPARATORS_LIST
' '
да
Используется в операторе case


ZMSG_HYPHEN_END
" ¬"
да



ZMSG_HYPHEN_START
"» "
да




Скриншот
https://user-images.githubusercontent.com/1020099/31858686-a297fb1e-b706-11e7-9987-64f996a1b1c6.png

Скачать


Последняя версия архивом: https://github.com/Open-GTO/zmessage/releases
Посмотреть не скачивая: https://github.com/Open-GTO/zmessage/blob/master/zmessage.inc

kushichka
09.07.2016, 05:36
Чем функция strins опасна?

TheMallard
09.07.2016, 08:02
Переполнение массива.

Daniel_Cortez
09.07.2016, 08:06
Чем функция strins опасна?
Тем, что никак не использует параметр maxlength и может записать символы за пределы массива, если строка слишком длинная.
Пример можно посмотреть здесь: https://github.com/compuphase/pawn/issues/15

BadPawn
09.07.2016, 11:28
Чем можно заменить strins, если это не format?

Можно к примеру, использовать в строке 2 strcat, но не будет ли это проблемно?...:


static str[49 + MAX_PLAYER_NAME] = "SELECT * FROM `players` WHERE `player_name` = '";
strcat(str, PlayerName(playerid), MAX_PLAYER_NAME);
strcat(str, "'", 1);

ziggi
09.07.2016, 14:01
Чем можно заменить strins, если это не format?

Можно к примеру, использовать в строке 2 strcat, но не будет ли это проблемно?...:


static str[49 + MAX_PLAYER_NAME] = "SELECT * FROM `players` WHERE `player_name` = '";
strcat(str, PlayerName(playerid), MAX_PLAYER_NAME);
strcat(str, "'", 1);

Можно исправить strins, в fixes.inc это реализовано так:

/*
* FIXES_strins(string[], const substr[], pos, maxlength = sizeof string)
*
* FIXES:
* strins
*/

#if defined _ALS_strins
#error _ALS_strins defined
#endif
native BAD_strins(string[], const substr[], pos, maxlength = sizeof string) = strins;

#if FIX_strins
stock FIXES_strins(string[], const substr[], pos, maxlength = sizeof string)
{
if (string[0] > 255)
{
new
strlength = strlen(string),
sublength = strlen(substr),
m4 = maxlength * 4;
// Packed - format doesn't like these strings.
if (strlength + sublength >= m4)
{
if (pos + sublength >= m4)
{
return
string{pos} = '\0',
// Hopefully this doesn't ignore maxlength and does packed.
strcat(string, substr, maxlength);
}
else
{
// pos + sublength is less than maxlength, so this sum MUST
// be positive and gte than "pos", so there's no need for
// additional checks.
string{maxlength - sublength - 1} = '\0';
}
}
return strins(string, substr, pos, maxlength);
}
else if (substr[0] > 255)
{
new
strlength = strlen(string),
sublength = strlen(substr);
// Packed - format doesn't like these strings.
if (strlength + sublength >= maxlength)
{
if (pos + sublength >= maxlength)
{
return
string[pos] = '\0',
// Hopefully this doesn't ignore maxlength and does packed.
strcat(string, substr, maxlength);
}
else
{
// pos + sublength is less than maxlength, so this sum MUST
// be positive and gte than "pos", so there's no need for
// additional checks.
string[maxlength - sublength - 1] = '\0';
}
}
return strins(string, substr, pos, maxlength);
}
else
{
return format(string, maxlength, "%.*s%s%s", pos, string, substr, string[pos]);
}
}

#define _ALS_strins
#define strins FIXES_strins
#endif

Если ты не используешь запакованные строки, то можно использовать эту функцию:

stock _strins(string[], const substr[], pos, maxlength = sizeof string)
{
return format(string, maxlength, "%.*s%s%s", pos, string, substr, string[pos]);
}

Desulaid
09.07.2016, 14:14
На счет запакованных строк. Если запаковать строку в SendClientMessage(), сообщение отправлено не будет.


SendClientMessage(playerid, -1,
!"Допустим, тут у нас такой вот текст на сколько-то там строк, \
да еще пасмурно что-то за окном, хотя середина лета!! \
Хотите шутеечку? Колобок повесился))))0)00 \
Смешно? Я знал! Орити в галосену000))0 \
Лел.");

ziggi
09.07.2016, 14:16
На счет запакованных строк. Если запаковать строку в SendClientMessage(), сообщение отправлено не будет.


SendClientMessage(playerid, -1,
!"Допустим, тут у нас такой вот текст на сколько-то там строк, \
да еще пасмурно что-то за окном, хотя середина лета!! \
Хотите шутеечку? Колобок повесился))))0)00 \
Смешно? Я знал! Орити в галосену000))0 \
Лел.");

Не учёл, поправлю.

UPD: Обновлено. Добавлена (https://github.com/Open-GTO/zmessage/commit/db20f1789402eb25f2744bc35e9f853214eaef08) поддержка запакованных строк.

kushichka
09.07.2016, 20:48
Тем, что никак не использует параметр maxlength и может записать символы за пределы массива, если строка слишком длинная.
Пример можно посмотреть здесь: https://github.com/compuphase/pawn/issues/15

Вики говорит что такой параметр существует, как он может не работать?
http://ihost.pro-pawn.ru/image.php?di=6HSF

ziggi
09.07.2016, 20:59
Вики говорит что такой параметр существует, как он может не работать?
http://ihost.pro-pawn.ru/image.php?di=6HSF

Это одна из многочисленных ошибок Pawn.

kushichka
09.07.2016, 21:27
Это одна из многочисленных ошибок Pawn.

а как насчет strmid?

ziggi
09.07.2016, 21:32
а как насчет strmid?

С ней всё нормально. Ошибки есть в strcmp, tolower, toupper, sleep, valstr. Список ошибок SA-MP и Pawn с их исправлением можешь посмотреть здесь (https://github.com/ziggi/sa-mp-fixes).

ziggi
25.10.2016, 23:57
v1.2
- Исправлена поддержка запакованных строк.

v2.0
- Перенос теперь не обрывает слова.

Страница загрузки на GitHub: https://github.com/Open-GTO/zmessage/releases

Замечание: если вам не нужны переносы сохраняющие целостность слов, то используйте версии v1 для большей производительности.

ziggi
27.10.2016, 09:10
v3.0

- Добавлена поддержка символов переноса в конце и начале строки. Значения могут быть заданы с помощью константы ZMSG_HYPHEN_END и ZMSG_HYPHEN_START, значения по умолчанию равны " ¬" и "» " соответственно.

Страница загрузки на GitHub: https://github.com/Open-GTO/zmessage/releases

Nexius_Tailer
27.10.2016, 15:24
Небольшая помарочка:

#if !defined _samp_included
#error Please include a_samp or a_npc before zlang //zmsg
#endif

Outsider
06.10.2017, 01:38
Не знаю что со мной не так, но ничего не работает.

DeimoS
06.10.2017, 02:51
Не знаю что со мной не так, но ничего не работает.

Ну так расскажи что ты делаешь (как подключаешь и как используешь).

Outsider
06.10.2017, 03:12
Ну, #include <zmessage> и SendClientMessege.

Вряд ли его можно как-то специфично юзать. Пробовал 3.1 и 3.0, пробовал использовать ZMsg_SendClientMessage — толку нет.

upd: Протестил на new.pwn, где ничего кроме двух инклюдов (самп и змессадж) нет — там ситуация аналогичная.

DeimoS
06.10.2017, 03:24
Покажи какие ещё инклуды подключаешь

Outsider
06.10.2017, 03:27
upd: Протестил на new.pwn, где ничего кроме двух инклюдов (самп и змессадж) нет — там ситуация аналогичная.

А у себя: pawn.CMD, sscanf, mxINI

DeimoS
06.10.2017, 03:54
Так а ты как проверяешь-то? Надеюсь не просто в окно чата пишешь и отправляешь результат в SendClientMessage?

Outsider
06.10.2017, 04:20
Так и делаю. А должен как-то иначе? Мне ведь и нужно, чтобы сообщение игрока разделялось.

DeimoS
06.10.2017, 04:23
Так и делаю. А должен как-то иначе? Мне ведь и нужно, чтобы сообщение игрока разделялось.

Ну так оно будет разделяться только если строка, передаваемая в SendClientMessage, будет больше 144 символов. А в чат умещается только 128. Раз у тебя "не работает", значит сообщение меньше 144 получается.
Вот тебе простой пример:

public OnPlayerConnect(playerid)
{
SendClientMessage(playerid, -1,
"\
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq\
qqqqqqqqqqqqq\
");
return 1;
}

Outsider
06.10.2017, 04:25
Дык там же у константы это значение делится на два.

ZMSG_MAX_PLAYER_CHAT_LENGTH (MAX_CHATBUBBLE_LENGTH / 2)

DeimoS
06.10.2017, 04:28
Дык только для функций SendPlayerMessageToPlayer и SendPlayerMessageToAll. Для SendClientMessage/SendClientMessageToAll действует макрос ZMSG_MAX_CHAT_LENGTH, который по умолчанию равен MAX_CHATBUBBLE_LENGTH, а тот, в свою очередь, равен 144

Outsider
06.10.2017, 04:29
Алсо, вызвал SendClientMessage в OnPlayerConnect и получил какую-то полную жесть, зафлудило символами переноса вплоть до зависания игры.

DeimoS
06.10.2017, 04:31
Только что скачал и проверил
https://i.imgur.com/mAiXG8b.png

Outsider
06.10.2017, 04:34
Значит вывод напрашивается сам собой. Буду пытаться отлаживать. Спасибо тебе.

DeimoS
06.10.2017, 04:37
Значит вывод напрашивается сам собой. Буду пытаться отлаживать. Спасибо тебе.

И какой же вывод напрашивается? Пока что всё указывает на то, что ты не понял как правильно использовать библиотеку и уже обвинил весь свет в том, что она не работает :)

Outsider
06.10.2017, 04:56
И какой же вывод напрашивается?

Я говорил о том, что где-то сам допустил ошибку. ))

ziggi
22.10.2017, 09:52
zmessage v3.1.1

- Добавлен перенос последнего цвета на следующую строку.

123
23.10.2017, 02:46
Что по производительности?

ziggi
23.10.2017, 07:18
Что по производительности?

Должно быть норм, лишних действий в коде нет (по крайней мере я их не вижу).

ziggi
23.12.2017, 19:10
zmessage v3.1.2

Исправлен вход в бесконечный цикл в некоторых случаях.

zmessage v3.1.3

Возвращён спецификатор const в функции сообщений.

zmessage v3.2

Добавлена функция ZMsg_GetMessages, которая может быть полезной в некоторых случаях (https://github.com/Open-GTO/zmessage/issues/5). Несколько примеров использования можно найти здесь (https://github.com/Open-GTO/zmessage/issues/6).

ZMsg_GetMessages(message[], array[][], const lines = sizeof(array), const line_size = sizeof(array[]))

Параметры:

message[]: Оригинальное сообщение, которое должно быть разделено.
array[][]: Массив, в котором сохраняются разделённые строки.
lines: Количество строк, которое может быть сохранено в массив array.
line_size: Количество символов, которое может быть сохранено в одну строку массива array.

Возвращаемые значения:

Количество строк.

Batya_Montes
17.01.2019, 17:24
довольно странно, что в общую длину строки учитываются коды цвета {......} и строка переносится не так как надо

ziggi
02.02.2019, 22:10
довольно странно, что в общую длину строки учитываются коды цвета {......} и строка переносится не так как надо

SendClientMessage и производные функции не могут отправлять строки длиной больше, чем 144 символа, в эту длину входит и цвет в {......}.

Salik_Davince
05.06.2019, 07:23
Можно ли сделать константы "ZMSG_HYPHEN_START | ZMSG_HYPHEN_END" параметром в функции разделения сообщения, будет гораздо удобнее, иначе бывают такие примеры когда нужно в новой строке сообщения добавить Никнейм либо что то еще -

Пример:


Salik_Davince говорит: Что то там, больше символов в тексте...
Salik_Davince говорит: ... Текст который разделился на 2 части.

execution
22.02.2020, 10:38
Немного не догоняю, в чём проблема.

Подключаю:
#define ZMSG_HYPHEN_END " ..."
#define ZMSG_HYPHEN_START "... "
#include <zmessage>

Использую:

CMD:test(playerid, params[])
{
new
string[MAX_CHATBUBBLE_LENGTH];
GetPlayerName(playerid, string, MAX_PLAYER_NAME);
format(string, sizeof string, "%s[%d] %s",
name, playerid, params);

new
array_message[2][ZMSG_MAX_PLAYER_CHAT_LENGTH],
lines;

lines = ZMsg_GetMessages(string, array_message);

for (new i = 0; i < lines; ++i)
{
SendClientMessage(playerid, -1, array_message[i]);
}

return 1;
}

Получаем (такое случается, когда размер текста больше ZMSG_MAX_PLAYER_CHAT_LENGTH)



Name_Surname[23] ...
... ...