Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 1 из 3 1 2 3 ПоследняяПоследняя
Показано с 1 по 10 из 26
  1. #1
    Аватар для Nexius_Tailer
    Пользователь

    Статус
    Оффлайн
    Регистрация
    04.01.2015
    Адрес
    Гомель, Беларусь
    Сообщений
    547
    Репутация:
    158 ±

    Команды, работающие независимо от наличия cmd процессора

    Приветствую. Сегодня представлю систему, которая будет полезна при написании каких-либо скриптов для сервера.

    Суть её вот в чём: многие скрипты, например include, которые имеют в себе команды, требуют либо подключения cmd процессора, либо команды в них работают только на стандартном.
    Лично моя политика написания скриптов (не модов) всегда была такой, чтобы конечный скрипт имел как можно меньше зависимостей (а по возможности не имел вообще), ибо в противном случае пользователю нужно следить не только за обновлениями моего скрипта, но и за обновлениями всех тех, подключение которых необходимо, что не очень удобно.
    Либо же, если пользователь никогда бы не использовал тот скрипт, который требуется в моём, но ему приходится (хороший пример - античит на FlyHack с использованием MapAndreas).

    В общем, с помощью этой системы можно делать команды внутри своих модулей (фс, инклудов), которые не будут требовать zcmd, но при его подключении всё также будет работать как и прежде.

    Работает это со всеми cmd процессорами, кроме rCmd, ибо синтаксис команд там абсолютно другой.

    Для этого придётся создать как бы свой cmd процессор в своём скрипте, но работать он будет немного иначе.

    Если вам нужна такая фича в вашем fs/include, код ниже к вашим услугам:

    PHP код:
    #if !defined CMD
        #define CMD:%0(%1) forward cmd_%0(%1); public cmd_%0(%1)
    #endif

    //YCMD и izcmd не блокируют вызов OnPlayerCommandText, поэтому их игнорируем, чтобы команды не дублировались
    #if !defined YCMD && !defined _I_ZCMD_INCLUDED
        
    public OnPlayerCommandText(playeridcmdtext[])
        {
            new 
    cmd[32], params[126], pos;
            while(
    cmdtext[pos] > ' ')
            {
                
    cmd[pos] = cmdtext[pos];
                
    pos++;
            }
            while(
    cmdtext[pos] == ' ')
            {
                
    pos++;
                if(!
    cmdtext[pos])
                {
                    
    params "\1";
                    break;
                }
            }
            
    strcat(paramscmdtext[pos]);
            
    //Здесь уже команды, шапку делаем по методу стандартных
            //Только вместо каких-либо действий вызываем паблик команды, в котором уже будет весь её код
            //if(!strcmp(cmd, "/help", true)) return my_cmd_help(playerid, params); <- Как пример, команда "/help"
            
    return 0;
        }
    #endif 

    Теперь объяснения, что за чем и зачем.

    Дефайн "CMD:" нужен для совместимости с YCMD и прочими командными процессорами, которые не поддерживают объявление команд по типу "cmd_", но в них есть своя совместимость с командами, объявленными через "CMD:".

    Выделение памяти, объяснять подробнее не вижу нужды:
    PHP код:
    new cmd[32], params[126], pos
    Единственное, что cmd в себе позже будет хранить текст "/НашейКоманды", а params - её параметры.

    Далее, вот это:
    PHP код:
    while(cmdtext[pos] > ' ')
    {
        
    cmd[pos] = cmdtext[pos];
        
    pos++;

    Как раз и записывает весь текст команды в массив "cmd" до первого пробела либо конца строки, если команда введена без параметров. Т.е. по сути результат этого равносилен strtok, который мы пишем первый раз в начале OnPlayerCommandText, если команды на strcmp.

    Вот теперь уже в:
    PHP код:
    while(cmdtext[pos] == ' ')
    {
        
    pos++;
        if(!
    cmdtext[pos])
        {
            
    params "\1";
            break;
        }

    Идёт отделение параметров. Ну т.е. пока только мы считаем, с какого символа они начинаются, если начинаются вообще (проверка "!cmdtext[pos]" говорит о том, что если следующий символ в цикле будет равен концу строки, а параметры ещё не обнаружены, то команда введена без параметров).

    И вот тут:
    PHP код:
    strcat(paramscmdtext[pos]); 
    Записываем в отдельную переменную params весь текст параметров, начиная с первого символа после пробела(ов).

    А далее, то что под комментариями - это уже объявление своих команд.
    PHP код:
    if(!strcmp(cmd"/help"true)) return my_cmd_help(playeridparams); //Как пример, команда "/help" 
    Помимо вызова функции каждой команды, эту функцию нужно ещё и объявить (а в ней ещё и код этой самой команды написать).

    Опять же, на примере команды "/help". Объявляем паблик и функцию для команды (где-нибудь в начале или в конце, как вам удобнее):
    PHP код:
    CMD:help(playeridparams[]) return my_cmd_help(playeridparams);
    my_cmd_help(playeridparams[])
    {
        
    #pragma unused params //Это добавлять если только команда не имеет параметров и вам выдаёт варнинг
        //Проверки на залогиненность и т.д.
        //И любые действия, которые должны происходить при вводе "/help"
        
    return 1;


    И да, русские команды добавлять можно, но название паблика команды должно быть на английском. Также работать русские команды будут только если zcmd не подключен (а если станет подключен, то такие команды уже будут вызываться только по альтернативным латинским именам, которые объявлены после "CMD:")!

    Также, по моему, это не пригодится вам, если вы пишите мод, ибо там реально проще будет подключить/не подключить нужный cmd-процессор и нет надобности в гибкости.

    Идею написания "независимых" команд взял у скрипта aview от автора SoNik)), но у него была реализована единственная команда и без параметров.


    UPD: Другой вариант (более компактный)
    Есть такая старая, но классная штука, как dcmd. Так вот, немного её доработав, также можно достичь совместимости.. Правда только для тех zcmd-подобных процессоров, где команды можно вызывать через cmd_"cmdname" (т.е. такие реализации, как Pawn.CMD/YCMD, к сожалению, работать с этим не будут из-за того, что у каждого из них свои префиксы).

    Для начала код оригинального dcmd и синтаксис его команд:
    PHP код:
    #define dcmd(%1,%2,%3) if (!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (dcmd_%1(playerid, ""))) || (((%3)[(%2) + 1] == ' ') && (dcmd_%1(playerid, (%3)[(%2) + 2]))))) return 1 
    PHP код:
    public OnPlayerCommandText(playeridcmdtext[])
    {
        
    dcmd(help4cmdtext); //4 = длина имени команды, равносильно strlen("help")
        
    return 0;
    }

    dcmd_help(playeridparams[])
    {
        
    #pragma unused params //Избежание варнинга, если params не используется
        //Проверки на залогиненность и т.д.
        //И любые действия, которые должны происходить при вводе "/help"
        
    return 1;


    Собственно, немного изменив логику работы и пару названий мы можем сделать это средством создания почти универсальных команд:
    PHP код:
    #define    dcmd2(%1,%2,%3) if(!strcmp((%3)[1], #%1, true, (%2)) && ((((%3)[(%2) + 1] == '\0') && (cmd_%1(playerid, ""))) || (((%3)[(%2) + 1] == ' ') && (cmd_%1(playerid, (%3)[(%2) + 2]))))) return 1 
    Теперь так будет выглядеть наш движок;
    "dcmd2" для избежания путаницы, если вдруг уже имеем обычный dcmd.

    Создание команд придётся сделать таким образом:
    PHP код:
    public OnPlayerCommandText(playeridcmdtext[])
    {
        
    dcmd2(help4cmdtext); //Здесь всё как у обычного dcmd, 4 = strlen("help")
        
    return 0;
    }

    forward cmd_help(playeridparams[]); //А здесь уже синтаксис zcmd команды
    public cmd_help(playeridparams[]) //Объявляем пабликом для того, чтобы команду видел zcmd
    {
        
    //Проверка на залогиненность и т.д.
        //И любые действия, которые должны происходить при вводе "/help"
        
    return 1;


    Принцип работы этого варианта: когда ничего не подключено, dcmd2 вызывает нашу команду (а точнее сверяет через strcmp введённый текст с названием нужной команды, и, если таковая введена, вызывает cmd_"+введённый нами текст до пробела") из OnPlayerCommandText уже не как функцию, а как паблик.
    Как только же мы подключаем zcmd, вызов паблика OnPlayerCommandText прекращается, т.е. dcmd2 перестаёт вызывать команды. Но, т.к. они объявлены синтаксисом zcmd команд и являются пабликами - zcmd их видит и уже вызывает сам.

    Таким образом, это является некой золотой серединой, если вы просто хотите иметь команды, которые по скорости без zmcd работали бы как обычные, но при его подключении начинали бы выполняться им.

    Надеюсь, это было полезно.
    Последний раз редактировалось Nexius_Tailer; 22.06.2023 в 01:23. Причина: Мелкие правки

  2. #2
    Аватар для $continue$
    Пользователь

    Статус
    Оффлайн
    Регистрация
    02.08.2014
    Адрес
    г. Киров (aka Вятка)
    Сообщений
    1,487
    Репутация:
    276 ±
    а оно кому то нужно?
    Поиграть с директивами препроцессора вообще западло?




    ZCMD:
    PHP код:
    #if defined _zcmd_included 
    DC_CMD:
    PHP код:
    #if defined _Pawn && defined DC_CMD 
    Последний раз редактировалось $continue$; 03.04.2016 в 13:39.
    Value your freedom or you will lose it, teaches history. "Don't bother us with politics," respond those who don't want to learn. (c) Richard Stallman

  3. #3
    Аватар для Nexius_Tailer
    Пользователь

    Статус
    Оффлайн
    Регистрация
    04.01.2015
    Адрес
    Гомель, Беларусь
    Сообщений
    547
    Репутация:
    158 ±
    Цитата Сообщение от $continue$ Посмотреть сообщение
    а оно кому то нужно?
    Лично мне да, в начале темы объяснил почему.

    Цитата Сообщение от $continue$ Посмотреть сообщение
    Поиграть с директивами препроцессора вообще западло?
    Ну-ка, код пожалуйста.
    Возможно твой вариант будет гораздо проще, тогда включу его в тему.

    Цитата Сообщение от $continue$ Посмотреть сообщение
    ZCMD:
    PHP код:
    #if defined _zcmd_included 
    DC_CMD:
    PHP код:
    #if defined _Pawn && defined DC_CMD 
    А если я использую izcmd, life-cmd, ещё что-то иное?
    Последний раз редактировалось Nexius_Tailer; 03.04.2016 в 13:41.

  4. #4
    Аватар для $continue$
    Пользователь

    Статус
    Оффлайн
    Регистрация
    02.08.2014
    Адрес
    г. Киров (aka Вятка)
    Сообщений
    1,487
    Репутация:
    276 ±
    Хотя я не продумал тот момент, что DC_CMD/ZCMD могут быть объявлены в любом месте мода. Тогда нужно продумывать другую реализацию.
    Value your freedom or you will lose it, teaches history. "Don't bother us with politics," respond those who don't want to learn. (c) Richard Stallman

  5. #5
    Аватар для Nexius_Tailer
    Пользователь

    Статус
    Оффлайн
    Регистрация
    04.01.2015
    Адрес
    Гомель, Беларусь
    Сообщений
    547
    Репутация:
    158 ±
    Цитата Сообщение от $continue$ Посмотреть сообщение
    Хотя я не продумал тот момент, что DC_CMD/ZCMD могут быть объявлены в любом месте мода. Тогда нужно продумывать другую реализацию.
    И это тоже. Так вот и решение - первый пост :)

  6. #6
    Аватар для ziggi
    Проверенный

    Статус
    Оффлайн
    Регистрация
    14.05.2015
    Сообщений
    1,181
    Репутация:
    790 ±
    Зачем заново изобретать dcmd?

  7. #7
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от ziggi Посмотреть сообщение
    Зачем заново изобретать dcmd?
    Потому что крутые программисты не тратят время на такую чушь, как ознакомление с чужими наработками? Кто же, если не они, будут изобретать велосипеды? Стране нужны велосипеды
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  8. #8
    Аватар для Nexius_Tailer
    Пользователь

    Статус
    Оффлайн
    Регистрация
    04.01.2015
    Адрес
    Гомель, Беларусь
    Сообщений
    547
    Репутация:
    158 ±
    Цитата Сообщение от ziggi Посмотреть сообщение
    Зачем заново изобретать dcmd?
    Хороший вопрос. А работают ли команды, созданные через dcmd, с zcmd к примеру?

  9. #9
    Аватар для TheMallard
    Пользователь

    Статус
    Оффлайн
    Регистрация
    08.12.2015
    Адрес
    San Fierro
    Сообщений
    217
    Репутация:
    39 ±
    Цитата Сообщение от Nexius_Tailer Посмотреть сообщение
    Хороший вопрос. А работают ли команды, созданные через dcmd, с zcmd к примеру?
    Конечно же работает, DCMD по сути просто дефайн и логика у него как у обычных команд, ведь работает все на strcmp.
    Чисто ради удобства и отсутствия необходимости использовать strtok/strrest.

  10. #10
    Аватар для $continue$
    Пользователь

    Статус
    Оффлайн
    Регистрация
    02.08.2014
    Адрес
    г. Киров (aka Вятка)
    Сообщений
    1,487
    Репутация:
    276 ±
    [audio]https://u.teknik.io/56ekx.mp3[/audio]
    Цитата Сообщение от DeimoS Посмотреть сообщение
    Потому что крутые программисты не тратят время на такую чушь, как ознакомление с чужими наработками? Кто же, если не они, будут изобретать велосипеды? Стране нужны велосипеды
    P.S: Добавьте тэг [audio][/audio]!
    Value your freedom or you will lose it, teaches history. "Don't bother us with politics," respond those who don't want to learn. (c) Richard Stallman

 

 
Страница 1 из 3 1 2 3 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •