Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

pawnDialogEngine

Июл
15
0
Пользователь
Dialog Engine for Pawn
Модульная декларативная система диалогов для SA-MP и open.mp

Dialog Engine — это библиотека, написанная полностью на Pawn (include-only), которая позволяет создавать изолированные, чистые и расширяемые диалоговые окна без привязки к хардкодным ID. Забудьте про огромные конструкции switch(dialogid) в OnDialogResponse. Теперь каждый диалог — это независимый модуль.

Основные возможности (Features)
  • Никаких плагинов: чистый Pawn, нулевая зависимость от стороннего софта.
  • Обратная совместимость: вы можете продолжать использовать стандартные ShowPlayerDialog там, где это необходимо.
  • Именованные диалоги: создавайте структуру один раз, вызывайте в любом месте мода по имени.
  • Многошаговые цепочки (inline-dialogs.inc): удобная реализация регистраций, опросов и квестов с автоматической навигацией "Вперед/Назад".
  • Разделение на страницы (paged-dialogs.inc): автоматическая пагинация для длинных списков (DIALOG_STYLE_LIST) со встроенными кнопками перелистывания.
  • Декларативные макросы (dialog-macros.inc): пишите код окон в отдельных файлах для идеальной чистоты мода.
  • Приятные дополнения: интеграция со sscanf2 (dialog-sscanf.inc) и сохранение состояний в SQLite (dialog-persist.inc).
  • Отладка (Debug logging): включите режим логирования для отслеживания жизненного цикла диалогов.

Быстрый старт (Quick start)
Форматирование (BB-код):
#define BASIC_DIALOGS_COUNT (1000) // Резерв ID для старых диалогов
#include "dialog-engine.inc"
#include "dialog-macros.inc"

// Объявляем диалог
DIALOG(WelcomeDialog)
{
    g_Dlg_WelcomeDialog = DialogCreate("welcome");
    DialogSetStyle(g_Dlg_WelcomeDialog, DIALOG_STYLE_MSGBOX);
    DialogSetTitle(g_Dlg_WelcomeDialog, "Welcome");
    DialogSetBody(g_Dlg_WelcomeDialog, "Hello! Ready to play?");
    DialogSetButtons(g_Dlg_WelcomeDialog, "Yes", "No");
    DialogSetHandler(g_Dlg_WelcomeDialog, "Dlg_WelcomeDialog_Response");
}

// Обработчик ответа
DIALOG_RESPONSE(WelcomeDialog)
{
    if (!response)
    {
        Kick(playerid);
        return 1;
    }
    SendClientMessage(playerid, 0x00FF00FF, "Welcome aboard!");
    return 1;
}

public OnGameModeInit()
{
    Dlg_Init_WelcomeDialog(); // Инициализация
    return 1;
}

public OnPlayerCommandText(playerid, cmdtext[])
{
    if (!strcmp(cmdtext, "/welcome", true))
    {
        SHOW_DLG(playerid, WelcomeDialog); // Показ диалога
        return 1;
    }
    return 0;
}

Установка и структура
1. Скопируйте содержимое папки include/ в директорию вашего проекта.
2. Подключите только те модули, которые вам нужны (Core, Inline, Paged, Macros, Sscanf, Persist).

Ссылки и исходный код
Репозиторий проекта на GitHub (доступен под лицензией MIT): https://github.com/killuadoxx/pawnDialogEngine.
Буду рад вашим звездам, баг-репортам и пулл-реквестам!
 
Последнее редактирование модератором:
𝚖𝚎𝚖𝚎𝚗𝚝𝚘 𝚖𝚘𝚛𝚒.
Мар
1,220
13,442
Команда форума
Администратор
Идея, в целом, неплохая, к тому же и удобная во многих смыслах, но есть одно "НО" - я практически на все 100% уверен, что реализация от нейросети. Разворачивание кучи условий в четыре (4) строки, когда это можно сделать в две (2) строки, а то и в одну (1). Не является основным показателем, но тем не менее. Особо не стал углубляться в изучение реализации, ибо хватило 100 первых строк. Есть небольшой вопрос напрямую к разработчику этого чуда: Предположим, что на сервере в данный момент находится 300 человек и каждый игрок одновременно или с небольшим интервалом откроет диалог - что произойдет в данном случае?
 
Июл
15
0
Пользователь
Идея, в целом, неплохая, к тому же и удобная во многих смыслах, но есть одно "НО" - я практически на все 100% уверен, что реализация от нейросети. Разворачивание кучи условий в четыре (4) строки, когда это можно сделать в две (2) строки, а то и в одну (1). Не является основным показателем, но тем не менее. Особо не стал углубляться в изучение реализации, ибо хватило 100 первых строк. Есть небольшой вопрос напрямую к разработчику этого чуда: Предположим, что на сервере в данный момент находится 300 человек и каждый игрок одновременно или с небольшим интервалом откроет диалог - что произойдет в данном случае?
Привет! Спасибо за критику и за то, что уделил время изучению кода, пусть даже первым 100 строкам.
По поводу того что мой код якобы писала нейросеть и по тому что в нем много строк, это я обьясню так: разворачивание условий сделано намеренно. В Pawn читаемость кода и явное разделение логических ветвей гораздо важнее, чем попытки впихнуть всё в однострочные тернарные операторы или сложные побитовые маски. Меньше строк != быстрее или стабильнее. Главная цель инклюда — модульность и удобство поддержки, а не победа в конкурсе по код-гольфингу. Тем более, я сам по себе стараюсь писать читабельный код а не максимально сокращенный. Уж извини за то, что я выбрал такой стиль написания. Он мне привычен.
Теперь по поводу твоего вопроса
Давай разберем это на атомы, учитывая специфику работы сервера SA-MP, ну и аналогичного опенмп
  1. Как мы знаем, Pawn — строго однопоточный. Абсолютно «одновременного» (в один и тот же такт процессора) выполнения кода от разных игроков быть не может. Сервер обрабатывает сетевые пакеты последовательно.
  2. Для самого сервера отправить 300 пакетов RPC_ShowPlayerDialog — это копеечная нагрузка (пару десятков килобайт трафика). Сам движок SA-MP не хранит строки диалогов для каждого игрока в памяти, он просто пушит их в сеть.
  3. Архитектура моего инклюда построена на изоляции данных. При создании диалога через DialogCreate формируется статическая структура (хэндл). Когда игрок вызывает диалог, система берет данные из этого готового шаблона. Здесь нет динамического выделения памяти на ходу под каждого игрока и нет общих глобальных переменных для перезаписи текста (Race Condition исключен). Соответственно, все 300 игроков мгновенно и без багов увидят свои окна.
Где реально может быть затык (но это уже на совести разработчика мода):
Если на этот диалог повесить тяжелую синхронную операцию — например, при открытии окна всеми 300 игроками пойдет прямой (не потоковый) запрос в бд (будь это mysql или иная субд ) за логами или даннымиф. Вот тогда сервер встанет в кратковременный фриз (I/O drop если быть точнее). Но сам Инклюд отработает штатно, так как его задача — менеджмент окон, а не оптимизация чужих баз данных.
Так что за кучу условий в коде можно не переживать — они работают как часы и не создают оверхеда. Если есть конкретные предложения, как сократить те самые строки без потери читаемости — буду рад пулл-реквесту на GitHub! К сожалению, я давно ушел из Pawn разработки и данный инклюд сделал лишь потому-что захотелось сделать что то удобное и что то свое.
 
Июл
15
0
Пользователь
Идея давно не новая и существует куча вариаций. Например:
И тебе привет. Абсолютно с тобой согласен. mdialog это отличный и проверенный движок, глупо отрицать его существование. Да и вообще, за столько лет в Pawn-сообществе было написано огромное количество вариаций диалоговых движков, так что америку я тут точно не открыл.
Как я уже писал чуть выше, я обсуждал эту тему с разработчиком из чата TS и прекрасно понимаю, что идея далеко не новая. Я ведь давно покинул Pawn-разработку и сейчас пишу на Node.js ( кому интересно, специализируюсь на разработке ботов (дс,тг,вк) и автоматизации систем. Сейчас активно изучаю бек ). Этот инклюд для меня — просто личный pet-project и исполнение моей "детской мечты". Мне хотелось реализовать модульную и удобную конкретно для меня структуру, а затем просто поделиться результатом с сообществом.
Я ни в коем случае не пытаюсь конкурировать с mdialog или заменить его. Это просто альтернативный взгляд и еще один открытый инструмент в общую копилку. Возможно, кому-то мой подход тоже покажется удобным для их задач. В любом случае, спасибо за фидбек и за ссылки!
 
𝚖𝚎𝚖𝚎𝚗𝚝𝚘 𝚖𝚘𝚛𝚒.
Мар
1,220
13,442
Команда форума
Администратор
@Killua, по поводу читаемости кода и развертывания условий - ради бога, лишь мои мысли и ни в коем случае не пытался упрекнуть тебя за стилистику написания кода. Главную мысль из моего сообщения ты так и не уловил. Да, ситуации, когда 300 игроков с небольшим интервалом времени (даже с интервалом в 10 секунд) откроют диалог - быть не может, но тем не менее, в теории ситуацию необходимо понимать. Я не спроста выделил в своем сообщении первые 100 строк твоего кода. Основная и главная ошибка, которая есть в этих строках - макрос MAX_ENGINE_DIALOGS, который у тебя в коде определен на 256 ячеек глобального массива. Даже если воспринимать простую теорию и не брать в расчет то, что такая ситуация крайне маловероятна - возможен выход за пределы массива.
 
Июл
15
0
Пользователь
@Killua, по поводу читаемости кода и развертывания условий - ради бога, лишь мои мысли и ни в коем случае не пытался упрекнуть тебя за стилистику написания кода. Главную мысль из моего сообщения ты так и не уловил. Да, ситуации, когда 300 игроков с небольшим интервалом времени (даже с интервалом в 10 секунд) откроют диалог - быть не может, но тем не менее, в теории ситуацию необходимо понимать. Я не спроста выделил в своем сообщении первые 100 строк твоего кода. Основная и главная ошибка, которая есть в этих строках - макрос MAX_ENGINE_DIALOGS, который у тебя в коде определен на 256 ячеек глобального массива. Даже если воспринимать простую теорию и не брать в расчет то, что такая ситуация крайне маловероятна - возможен выход за пределы массива.
Благодарю за поправку. В будующих обновлениях ( если они будут ) поправлю данный ньанс, постараюсь оптимизировать на максимум.
 
Янв
414
76
Пользователь
Ошибок крайне много. Это нейросетевой код. О чем как минимум говорит cмесь стилей программирования:

stock Dialog_StrLenEmpty(const str[]) // Венгерская нотация
#define DIALOG_ENGINE_FIRST_ID // UPPER_CASE
g_ActiveDialog[MAX_PLAYERS] // g_ префикс для глобалов

путаница в хуках/перехватах:

#define _ALS_OnDialogResponse
#define OnDialogResponse DE_OnDialogResponse

Дважды проверяется одно и то же:

if (playerid < 0 || playerid >= MAX_PLAYERS)

Странное приведение bool к int. Притом, что в pawn нет bool как типа. И достаточно было просто использовать int.

new bool:result = ShowPlayerDialog(...);
return _:result;

Да и cтроки в PAWN - это массивы, а не объекты. Ну и Сверхподробная XML-документация (PawnDoc):
Нейросети (особенно ChatGPT и Claude) обожают генерировать документацию в формате XML-тегов (<library>, <summary>, <param>, <remarks>), если их попросить написать «хорошо документированный код».
Живые PAWN-разработчики крайне редко пишут настолько идеальную и подробную XML-документацию для каждого сеттера и геттера. Обычно люди либо не пишут её вовсе, либо используют однострочные комментарии //, либо применяют макрогенераторы.

Нейросети плохо знают специфику таких нишевых языков как pawn и мало обучены на подходящей кодовой базе.
 
Июл
15
0
Пользователь
@pawneror,
Слушай, ну насчет документации ты угадал. Тут скрывать нечего. Я действительно использовал нейросеть для генерации XML-тегов (PawnDoc) под геттеры и сеттеры. Сам я документацию писать не люблю, так как обычно пишу код чисто для себя, а тут решил оформить проект для людей, чтобы всё выглядело цивильно. ИИ для рутины и текстов — отличный инструмент в 26 году, почему бы и нет? Да и разве это плохо? XML не вредит коду.
А вот во всем, что касается самого кода, ты абсолютно мимо со своей аналитикой. Твои признаки того что код был написан нейросетью — это буквально база старой школы Pawn-разработки. Давай разберем:
  1. Смесь стилей: Использование префикса g_ для глобальных переменных, UPPER_CASE для макросов и camelCase для функций — это общепринятый стандарт в SA-MP сообществе еще со времен тем на официальном форуме. Посмотри код библиотек от Y-Less (YSI) или Zeex — там абсолютно такая же структура. Это делается для банальной читаемости кода.
  2. Перехваты (хуки): Стандартный метод через _ALS_OnDialogResponse используется в 99% нормальных инклюдов для SA-MP, чтобы не ломать совместимость с другими скриптами в моде. Нейросети как раз этот метод путают чаще всего и предлагают кривые решения, а тут классика.
  3. Проверка playerid: Это называется defensive programming (оборонительное программирование если тебе нужен перевод). Когда пишешь инклюд, который люди будут подключать в самые разные (и порой очень кривые) моды, лучше перестраховаться на уровне самого движка, чем потом слушать жалобы на краши из-за чужого кода.
  4. Приведение bool к int: В Pawn есть теги (bool:, Float:). Приведение _:result (снятие тега если ты не знал) — это стандартный и чистый способ вернуть число из функции, если нативка SA-MP возвращает логическое значение, а тебе нужно прокинуть его дальше без варнингов компилятора. Строки тут никто объектами и не считал, работа идет с обычными массивами.
Так что за документацию — уел, согласен. А вот сам код написан руками по классическим гайдам и паттернам, которые существовали задолго до появления ChatGPT. Проект открытый, всё работает стабильно, а стилистика — дело вкуса. Если тебе ближе mdialog, то никаких проблем, пользуйся им
 
Сверху