Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.

Реклама


 
IP:176.32.36.96:7777 Ha6op adm,liderov + bonuse.

**Как получить V.I.P** (Перейти)
Чтобы заказать рекламу на Pro-Pawn.Ru, обращайтесь в Skype.
Баннерная реклама 100руб/мес, Текстовая 50руб/мес.
Страница 1 из 26 123 11 ... ПоследняяПоследняя
Показано с 1 по 10 из 259
  1. #1
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    3,138
    Репутация:
    1263 ±

    Создание системы регистрации на основе плагина MySQL [R39/R40]

    Доброго времени суток.
    В этом уроке я попытаюсь объяснить Вам, как создаётся система записи/загрузки аккаунтов на основе плагина MySQL от BlueG.
    Код, предоставленный в статье, актуален для веток "R39" и "R40".
    Начнём.




    Плагин MySQL от BlueG:



     F.A.Q. <Как скачать с GitHub>

    1. Переходим по ссылке выше и скачиваем нужную версию плагина

     Скриншот






    2. Разархивируем скачанный архив и его содержимое перемещаем в папку с модом

     Скриншот






    3. Открываем файл "server.cfg" и ищем строчку "plugins".
    - Если нашли, то приписываем ко всем прочим плагинам новый - "mysql"
    - Если не нашли, то добавляем в самый конец файла новую строку - "plugins mysql"

    * Если сервер запускается в Ubuntu Linux / CentOS, к названию плагина приписываем расширение ".so" ("mysql.so"). Если же Windows, то приписывать к названию плагина ничего не нужно.

     Скриншот






    4. Открываем скрипт, в который будем прописывать регистрацию и подключаем инклюд MySQL (я буду использовать стандартный пустой мод, ссылку на который помещу в конце урока).

     Скриншот









    База данных:


    • Софт для работы с базой данных:
      Для работы с базой данных (чтение/редактирование) я предпочитаю использовать Denwer. О нём я Вам и расскажу.
      P.S. Если Вы боитесь софта с закрытым исходным кодом, можете использовать любую другую программу, но инструкции по работе с ней придётся искать самостоятельно
      (так же буду не против, если Вы напишете мне название этой программы. Возможно, я дополню свой урок, рассказав о ней)

      Официальный сайт программы denwer.ru На нём Вы можете как скачать программу,
      так и найти кучу полезной информации по работе с ней.
      Я лишь опишу Вам о тех её возможностях,
      что пригодятся Вам при создании нашей системы.
      Страница в википедии ru.wikipedia.org/wiki/Денвер_(программа) Так же есть немного полезной информации

       F.A.Q. <Как скачать с официального сайта Denwer>

      1. Переходим на сайт и нажимаем на кнопку "Скачать Денвер", выбрав самую последнюю версию PHP

         Скриншот сайта




      2. Если Вы ещё не застигли выход "Денвер 4" и создатели ещё не убрали регистрацию, Вас попросят зарегистрироваться. Просто вводим свою почту и жмём на кнопку "Получить ссылку на скачивание" (самый первый раз я "регистрировался" там ещё около года назад и до сих пор, кроме сообщения с ссылкой, никаких сообщений с этого сайта не приходило, так что за какой-либо спам можете не бояться)

         Скриншот




      3. Заходим на почту, находим сообщение, переходим по ссылке и радуемся началу загрузки

         Скриншот сообщения





       F.A.Q. <Установка Denwer>
      1. Нажимаем на кнопку "Да" в окне, с вопросом "Вы действительно хотите установить базовый пакет?"
      2. После распаковки файлов инсталлятора откроется веб-браузер, который нужно будет закрыть
      3. Далее появится консоль, в которой от нас попросят нажать Enter. Нажимаем.
      4. Далее консоль попросит нас ввести путь, в который инстайллер установит Denwer. Если Вам подходит установка в диск С, просто нажимайте Enter. Иначе введите свой путь. В обоих случаях нужно будет подтвердить свой выбор, нажав на клавишу "Y" (русская "н") и Enter.
      5. Далее идёт пояснение того, что произойдёт при следующем шаге. Если интересно - читаем. И в любом случае жмём Enter.
      6. Теперь нам нужно указать букву, которая будет обозначать имя нового виртуального диска, нужного для работы Denwer. Выбираем незанятую букву (открываем "Мой компьютер" и смотрим под какими буквами созданы локальные диски/дисководы и прочее. И потом выбираем незанятую) и жмём Enter.
      7. После этого консоль проверит работоспособность утилиты subst и если всё сделано верно (буква для имени не занята и утилита работает) - консоль сообщит об этом и попросит нажать Enter. Жмём.
      8. После распаковки всех нужных файлов и создания нового виртуального диска, консоль предложит выбрать режим, в котором будет работать Denwer. Нам подойдёт первый вариант, поэтому пишем в консоль "1".
      9. Теперь консоль предложит нам создать ярлыки на рабочем столе. Тут уж решайте сами. Я создал :)


       F.A.Q. <Как открыть веб-приложение для работы с СУБД MySQL (Denwer)>

      • После установки находим ярлык "Start Denwer" и запускаем его

      • Открываем любой браузер и в адресную строку прописываем "localhost" и если все порты открыты/антивирус не блокирует работу программы - видим надпись "Ура, заработало!". Если не видим - читаем инструкцию из спойлера выше/открываем порты/добавляем Denwer в исключения брандмауэра и антивируса/переустанавливаем Denver.

         Скриншот





      • Прокручиваем страницу до таблицы с двумя столбцами. В первом видим какие-то адреса, а во-втором - описание к ним. Нам нужен адрес "http://localhost/Tools/phpMyAdmin". Выбираем его

         Скриншот





        Открывшаяся страница - это "phpMyAdmin" - веб-приложение, созданное для работы с СУБД MySQL. Именно через него Вы сможете управлять базой данных и просматривать/редактировать данные в таблицах.



       F.A.Q. <Краткий экскурс по phpMyAdmin>
      Вкладка "Обзор"


      Во вкладке "Обзор" находится содержимое выбранной базы данных. Если данная вкладка неактивна - таблица пуста.


      Типы столбцов


      MySQL поддерживает все основные виды столбцов и кучу их подвидов (которые, как я понимаю, нужны для оптимизации работы таблицы), но я расскажу Вам лишь о самых основных (те, которые потребуются нам для простой работы с данными)

      INT - это, как Вы могли уже догадаться, Integer (от англ. "Целое число"). В нём мы можем хранить все данные, являющиеся целым числом (деньги, уровень, кол-во смертей/убийств и прочее).
      VARCHAR - это тип данных, в котором хранятся строки (буквы любого регистра/числа/спец.символы). Максимальная длина строки, которую может хранить такое поле - 255 символов. VARCHAR - это усовершенствованная версия типа столбца CHAR, главной отличительной особенностью которого является то, что если при создании столбца с типом CHAR прописать 100 символов, а записать, например, 50 - остальные 50 ячеек будут заполнены пробелами. В VARCHAR же сохранится именно 50 символов + 1 символ для нуль-символа (конца строки).
      FLOAT - это тип данных, в котором можно хранить вещественные числа (дробные/числа с плавающей точкой)

      Всё остальное лично мной не использовалось и о всех тонкостях поведать Вам я не могу. Но Вы всегда можете прочитать об этом на официальной странице MySQL =)


      Создание нового столбца (поля)


      Новый столбец (поле) создать очень просто. Для этого находим нужную нам таблицу, открываем её, жмём на вкладку "Структура" и ищем последний столбец. Под ним есть надпись "Добавить" и далее идут настройки. Именно эта строка нам и нужна.
      В поле после "Добавить" пишем то число столбцов, которое нам нужно добавит в таблицу (если они должны располагаться друг за другом). Далее выбираем позицию, в которую нам нужно добавить эти поля (это может быть как начало/конец таблицы, так и определённое поле, после которого новые поля и будут добавлены). Выбираем нужную позицию и жмём "Ок". Далее нужно настроить новые столбцы и всё :)

       Скриншот






      Идентификатор


      Идентификаторы нужны в таблице для того, чтоб можно было с лёгкостью связать данные нескольких таблиц, опираясь на данные какой-то одной. MySQL самостоятельно устанавливает идентификатор для новой строки в момент создания этой строки. Ни в коем случае не меняйте данный параметр вручную. Изменять его может исключительно MySQL!

       Сброс auto_increment до определённого значения
      ДЕЛАЙТЕ ЭТО С ОСТОРОЖНОСТЬЮ! ПРИ НЕПРАВИЛЬНОМ ОБРАЩЕНИИ С AUTO_INCREMENT ВОЗМОЖНА ПОРЧА ДАННЫХ.

      1. Открываем таблицу, в которой будем менять значение поля с auto_increment
      2. Находим вкладку "Операции" и открываем её
      3. Находим поле AUTO_INCREMENT и меняем значение напротив поля на нужное
      Готово. Теперь при создании нового поля значение AUTO_INCREMENT будет равно установленному и начнётся отсчёт именно с него



    • Работа с базой данных:

      В данной инструкции я расскажу Вам о том, как создать базу данных в Denwer (об этой программе я рассказал выше)

      1. Открываем phpMyAdmin, если не сделали этого ранее

      2. В панели сверху выбираем пункт "Базы данных"

         Скриншот



      3. В поле под надписью "Создать базу данных" вводим имя нашей базы данных (я введу "sa-mp". Вы можете написать своё) и в поле "Сравнение" выбираем "utf8_general_ci". После того, как совершили эти действия, нажимаем на кнопку "Создать".

         Скриншот



      4. Если всё сделали правильно, phpMyAdmin уведомит Вас о успешном создании нашей базы данных и в списке слева появится новая запись.
         Скриншот



        Если нет - исправляем ошибки, о которых сообщит phpMyAdmin, и создаём.





    Создание системы аккаунтов:

    • Создание таблицы для хранения аккаунтов:

      1. Выбираем базу данных, в которой будем создавать таблицу (если Вы создавали базу данных вместе со мной, то выбираем "sa-mp")

      2. На открывшейся странице находим окошко "Создать таблицу" и вводим данные о таблице:
        • В поле "Имя таблицы" вводим "accounts"
        • В поле "Количество столбцов" вводим "3"

        и нажимаем "ОК"
         Скриншот



      3. Структуру новой таблицы заполняем следующим образом:

          Открыть/закрыть
        • Первый столбец
          - Имя столбца: id
          - Тип столбца: INT
          - Длина/значения: 11
          Все остальные значения, кроме A_I, не трогаем. Находим A_I (Auto Increment) и ставим галочку.
          Идентификаторов не может быть больше одного в таблице. Да оно и не нужно =)


        • Второй столбец
          - Имя столбца: player_name
          - Тип столбца: VARCHAR
          - Длина/значения: 24 (так как длина ника в SA-MP не может превышать 24 символа)
          Все остальные значения не трогаем.

        • Третий столбец
          - Имя столбца: password
          - Тип столбца: VARCHAR
          - Длина/значения: 30 (Я ограничу длину пароля игрока 30-ю символами. Вы можете сделать меньше/больше)
          Все остальные значения не трогаем.


        Внимание:
        MySQL чувствительна к регистру, поэтому если Вы решили записать имена столбцов иначе, учитывайте это в дальнейшем.

         Скриншот




    • Создание самой системы:

      1. Данные для подключения
        В начало нашего скрипта (под "#include <a_samp>") добавим:
        PHP код:
        #include <a_mysql>

        #define MYSQL_HOST                "localhost"//Адрес, по которому расположен MySQL-Сервер
        #define MYSQL_USER                "root"//Имя пользователя, на которого была создана база данных
        #define MYSQL_DATABASE            "sa-mp"// Имя базы данных
        #define MYSQL_PASSWORD            ""//Пароль для доступа к серверу MySQL 
        Так же нужно добавить переменную, в которой будет хранится ID подключения к базе данных
          Открыть/закрыть
         Для R39
        PHP код:
        new mysql_connect_ID

         Для R40
        PHP код:
        new MySQL:mysql_connect_ID


         Разбор кода
        PHP код:
        #include <a_mysql> 
        Собственно, подключаем инклюд, в котором хранится объявление всех функций для работы с плагином

        PHP код:
        #define MYSQL_HOST                "localhost" 
        Этот макрос хранит в себе адрес хостинга, где хранится база данных (мы будем запускать на ПК, поэтому указываем адрес локальной сети).

        PHP код:
        #define MYSQL_USER                "root" 
        Этот макрос хранит в себе имя пользователя, у которого имеется доступ к базе данных (так как мы запускаем мод на ПК, у нас это администратор. Когда будете запускать мод на хостинге, Вам выдадут особое имя)

        PHP код:
        #define MYSQL_DATABASE            "first_database" 
        Этот макрос содержит в себе имя базы данных. Если при создании БД Вы прописывали имя отличное от моего, измените его на то, что указали Вы.

        PHP код:
        #define MYSQL_PASSWORD            "" 
        Этот макрос хранит в себе пароль, который требуется для подключения к базе данных. Так как мы работаем на ПК и в Denwer по-умолчанию он не указан, пароль мы не указываем. При работе с хостингами нужно указывать пароль от хостинга.

        PHP код:
        new mysql_connect_ID;
        //new MySQL:mysql_connect_ID; 
        Это целочисленная переменная, в которой мы будем хранить ID подключения, которое потребуется для работы большинства функций.


         Скриншот







      2. Подключение к базе данных
        Теперь нам нужно связать сервер с нашей базой данных. Для этого в OnGameModeInIt пропишем следующий код:

          Открыть/закрыть
         Для R39
        PHP код:
        mysql_connect_ID mysql_connect(MYSQL_HOSTMYSQL_USERMYSQL_DATABASEMYSQL_PASSWORD); 


         Для R40
        PHP код:
        mysql_connect_ID mysql_connect(MYSQL_HOSTMYSQL_USERMYSQL_PASSWORDMYSQL_DATABASE); 


        Так же, если Вы хотите сохранять в базу данных текст на русском, следует добавить следующие запросы прямо после подключения (автор реализации - $continue$)
          Открыть/закрыть
         Для R39
        PHP код:
        mysql_function_query(mysql_connect_ID, !"SET CHARACTER SET 'utf8'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET NAMES 'utf8'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET character_set_client = 'cp1251'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET character_set_connection = 'cp1251'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET character_set_results = 'cp1251'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET SESSION collation_connection = 'utf8_general_ci'"false""""); 
         Получится так
        PHP код:
        mysql_connect_ID mysql_connect(MYSQL_HOSTMYSQL_USERMYSQL_DATABASEMYSQL_PASSWORD);
        mysql_function_query(mysql_connect_ID, !"SET CHARACTER SET 'utf8'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET NAMES 'utf8'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET character_set_client = 'cp1251'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET character_set_connection = 'cp1251'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET character_set_results = 'cp1251'"false"""");
        mysql_function_query(mysql_connect_ID, !"SET SESSION collation_connection = 'utf8_general_ci'"false""""); 


         Для R40
        PHP код:
        mysql_tquery(mysql_connect_ID, !"SET CHARACTER SET 'utf8'""""");
        mysql_tquery(mysql_connect_ID, !"SET NAMES 'utf8'""""");
        mysql_tquery(mysql_connect_ID, !"SET character_set_client = 'cp1251'""""");
        mysql_tquery(mysql_connect_ID, !"SET character_set_connection = 'cp1251'""""");
        mysql_tquery(mysql_connect_ID, !"SET character_set_results = 'cp1251'""""");
        mysql_tquery(mysql_connect_ID, !"SET SESSION collation_connection = 'utf8_general_ci'"""""); 
         Получится так
        PHP код:
        mysql_connect_ID mysql_connect(MYSQL_HOSTMYSQL_USERMYSQL_PASSWORDMYSQL_DATABASE);
        mysql_tquery(mysql_connect_ID, !"SET CHARACTER SET 'utf8'""""");
        mysql_tquery(mysql_connect_ID, !"SET NAMES 'utf8'""""");
        mysql_tquery(mysql_connect_ID, !"SET character_set_client = 'cp1251'""""");
        mysql_tquery(mysql_connect_ID, !"SET character_set_connection = 'cp1251'""""");
        mysql_tquery(mysql_connect_ID, !"SET character_set_results = 'cp1251'""""");
        mysql_tquery(mysql_connect_ID, !"SET SESSION collation_connection = 'utf8_general_ci'"""""); 


         Разбор кода
          Открыть/закрыть
         Для R39
        Функция mysql_connect нужна для подключения плагина к базе данных. Она имеет 7 параметров, из которых только 4 первых обязательны к заполнению.
        PHP код:
        native mysql_connect(const host[], const user[], const database[], const password[], port 3306bool:autoreconnect truepool_size 2);
        /*------------------------------------------------------------------------------------------------------------------------------------------
        const host[] - Адрес хостинга, на котором расположена база данных. Этот адрес у нас хранится в макросе "MYSQL_HOST"
        const user[] - Имя пользователя, который имеет доступ к базе данных. Это имя записано в макросе "MYSQL_USER"
        const database[] - Имя базы данных, к которой нужно подключиться. Это имя записано в макросе "MYSQL_DATABASE"
        const password[] - Пароль от хостинга, на котором расположена база данных. Этот пароль записан в макросе "MYSQL_PASSWORD"
        port = 3306 - Порт, по которому производится подключение. Его нужно прописывать только в случае, когда идёт работа с несколькими базами данных (НЕ ТАБЛИЦАМИ). В нашем случае мы значение не трогали.
        bool:autoreconnect = true - Настройки автоматического переподключения к базе данных, если связь с БД была потеряна
        pool_size = 2 - Число потоков, по которым будет работать плагин. */ 

         Для R40
        Функция mysql_connect нужна для подключения плагина к базе данных. Она имеет 5 параметров, из которых только 4 первых обязательны к заполнению.
        PHP код:
        native MySQL:mysql_connect(const host[], const user[], const password[], const database[], MySQLOpt:option_id MySQLOpt:0);
        /*------------------------------------------------------------------------------------------------------------------------------------------
        const host[] - Адрес хостинга, на котором расположена база данных. Этот адрес у нас хранится в макросе "MYSQL_HOST"
        const user[] - Имя пользователя, который имеет доступ к базе данных. Это имя записано в макросе "MYSQL_USER"
        const password[] - Пароль от хостинга, на котором расположена база данных. Этот пароль записан в макросе "MYSQL_PASSWORD"
        const database[] - Имя базы данных, к которой нужно подключиться. Это имя записано в макросе "MYSQL_DATABASE"
        MySQLOpt:option_id - Опция, с которой создаётся подключение. Более подробнее я расскажу об этом в отдельной статье*/ 


        Данная функция возвращает ID подключения, который мы и записали в переменную.

         Скриншот




         Дополнение: Отслеживание качества подключения
        Так же Вы можете добавить простую проверку, которая будет отображать в логах то, насколько удачно произошло подключение к базе данных и выведет причину (либо код ошибки) в случае, если подключение не удалось. Для этого сразу после кода о подключении добавим такой код:
        PHP код:
        switch(mysql_errno())
        {
            case 
        0: print("Подключение к базе данных удалось");
            case 
        1044: print("Подключение к базе данных не удалось [Указано неизвестное имя пользователя]");
            case 
        1045: print("Подключение к базе данных не удалось [Указан неизвестный пароль]");
            case 
        1049: print("Подключение к базе данных не удалось [Указана неизвестная база данных]");
            case 
        2003: print("Подключение к базе данных не удалось [Хостинг с базой данных недоступен]");
            case 
        2005: print("Подключение к базе данных не удалось [Указан неизвестный адрес хостинга]");
            default: 
        printf("Подключение к базе данных не удалось [Неизвестная ошибка. Код ошибки: %d]"mysql_errno());

        Где mysql_errno - функция, которая возвращает ID ошибки при отправке запросов к базе данных.

         Скриншот








      3. "Перечисление" (enum) для хранения данных

         Немного лирики
        Для хранения данных мы можем использовать либо связку "enum + двумерный массив", либо просто массивы, либо pVar. Удобнее всего использовать связку "enum + двумерный массив", но Вы можете использовать другой способ, если достаточно осведомлены о нём и считаете его удобным.
        Как я уже писал ранее, это вводный урок и поэтому мы реализуем хранение лишь трёх параметров: ID аккаунта, имя игрока и пароль от аккаунта. А раз с способом хранения данных мы определились, а так же определились с данными, которые будем хранить - можно приступать к написанию кода.

        Под наши данные для подключения добавим следующий код:
        PHP код:
        enum e_PLAYER_INFO
        {
            
        pID,
            
        pName[MAX_PLAYER_NAME],
            
        pPassword[31]
        };
        new 
        pInfo[MAX_PLAYERS][e_PLAYER_INFO]; 
         Разбор кода

         enum
        PHP код:
        enum e_PLAYER_INFO//Объявление перечисления
        {
            
        pID,//Первый член перечисления. Так как значение не указано, по-умолчанию имеет ID 0
            
        pName[MAX_PLAYER_NAME],//Второй член перечисления. Имеет ID 1
            
        pPassword[31]//Третий член перечисления. Имеет ID 2
        };
        new 
        pInfo[MAX_PLAYERS][e_PLAYER_INFO];//Двумерный массив, где первая группа ячеек подразумевает разделение на 1000 ячеек (под каждого игрока), а вторая - обращение к членам перечисления 

        PHP код:
        enum e_PLAYER_INFO
        /*---------------------
        enum - оператор
        e_PLAYER_INFO - название перечисления*/ 
        enum - англ. Enumeration (Перечисление) - это тип, состоящий из набора целочисленных констант, называемых перечислителями. Перечисление позволяет объединить данные разных типов в одну "группу". Enum состоит из самого оператора и названия перечисления/

        PHP код:
        pID
        Первый член перечисления, а по совместительству и ячейка, в которой будет хранится ID аккаунта игрока. Имеет целочисленный тип и может хранить только целые числа (КЭП)

        PHP код:
        pName[MAX_PLAYER_NAME], 
        Второй член перечисления, а по совместительству и ячейка, в которой будет хранится имя аккаунта. Для хранения строки требуется массив, который мы и создали. В базе данных мы выделили 24 ячейки под хранение ника, поэтому и тут нам глупо выделять меньше/больше.

        PHP код:
        pPassword[31
        Третий член массива, а по совместительству и ячейка, в которой будет хранится пароль от аккаунта. Тут мы, опять же, создали массив и выделили 31ячеек (так как решили, что пароль игрока не должен будет превышать эти самые 30 ячеек + 1 символ на конец строки. Если в базе данных Вы выделяли другие число ячеек для столбца - прописывайте своё значение)

        PHP код:
        new pInfo[MAX_PLAYERS][e_PLAYER_INFO]; 
        Массив, через который мы будем обращаться у нужному нам члену перечисления за данными. В первой группе ячеек мы будем указывать ID игрока (ID Игрока будет равен номеру ячейки, в которой будут записываться его данные. Так мы с лёгкостью сможем в дальнейшем с этими данными работать). Во второй группе ячеек мы будем указывать имя члена перечисления, которое так же вызовет нужную нам ячейку с данными


         Скриншот








      4. Поиск игрока в базе данных и запись ника в массив

        Теперь нам нужно сделать запрос для поиска игрока в базе данных, а так же записать ник игрока (ибо игрок не сможет сменить свой ник без нашего ведома, поэтому логичнее всего просто 1 раз записать его при входе и уже использовать массив, чем каждый раз вызывать GetPlayerName).
        В OnPlayerConnect вставим:
          Открыть/закрыть
         Для R39
        PHP код:
        GetPlayerName(playeridpInfo[playerid][pName], MAX_PLAYER_NAME);
        new 
        query_string[49+MAX_PLAYER_NAME-4];
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]);
        mysql_function_query(mysql_connect_IDquery_stringtrue"FindPlayerInTable","i"playerid); 
         Разбор кода
        PHP код:
        GetPlayerName(playeridpInfo[playerid][pName], MAX_PLAYER_NAME); 
        С помощью функции GetPlayerName мы записали имя игрока в наш массив, дабы в будущем получить возможность брать имя игрока из этого массива, а не вызывать повторно функцию GetPlayerName.

        PHP код:
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]); 
        С помощью функции format мы вставили имя в наш запрос, который заставит плагин просмотреть таблицу на предмет строк, в которых данные столбца "player_name" совпадают с именем игрока.

        PHP код:
        mysql_function_query(mysql_connect_IDquery_stringtrue"FindPlayerInTable""i"playerid);
        /* А это и есть та самая функция, которая отправляет команду таблице через плагин.
        ----------------------------------------------------------------------------------------------

        mysql_function_query - название функции

        mysql_connect_ID - Первый параметр функции, в котором указывается ID базы данных, с которой идёт работа

        query_string - Второй параметр функции, в котором пишется сам запрос с которым плагин обратится к базе данных

        true - Третий параметр, который отвечает за кэширование запроса. Кэширование нужно только для тех запросов, в результате которых из таблицы должно вернуть какие-либо данные (например, найдена ли нужная строка или же какие данные записаны в той или иной строке. Если мы обновляем данные в таблице - кэширование не требуется)

        "FindPlayerInTable" - Четвёртый параметр, в котором указывается имя паблика, в который будут помещены данные, возвращённые из базы данных (требуется только в случае запросов с кэшированием)

        "i" - Пятый параметр, который позволяет передать в паблик, указанный в четвёртом параметре, какие-либо данные из того участка кода, в котором был отправлен запрос в базу данных. Работает точно так же, как SetTimerEx (в этом параметре указываются типы данных, которые будут переданы. Сами данные указываются в следующем параметре)

        playerid - Шестой параметр, в котором и указываются все данные для передачи в указанный паблик. Это может быть любой тип данных из тех, кто доступны в Pawn. 


         Для R40
        PHP код:
        GetPlayerName(playeridpInfo[playerid][pName], MAX_PLAYER_NAME);
        new 
        query_string[49+MAX_PLAYER_NAME-4];
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]);
        mysql_tquery(mysql_connect_IDquery_string"FindPlayerInTable","i"playerid); 
         Разбор кода
        PHP код:
        GetPlayerName(playeridpInfo[playerid][pName], MAX_PLAYER_NAME); 
        С помощью функции GetPlayerName мы записали имя игрока в наш массив, дабы в будущем получить возможность брать имя игрока из этого массива, а не вызывать повторно функцию GetPlayerName.

        PHP код:
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]); 
        С помощью функции format мы вставили имя в наш запрос, который заставит плагин просмотреть таблицу на предмет строк, в которых данные столбца "player_name" совпадают с именем игрока.

        PHP код:
        mysql_tquery(mysql_connect_IDquery_string"FindPlayerInTable""i"playerid);
        /* А это и есть та самая функция, которая отправляет команду таблице через плагин.
        ----------------------------------------------------------------------------------------------

        mysql_tquery - название функции

        mysql_connect_ID - Первый параметр функции, в котором указывается ID базы данных, с которой идёт работа

        query_string - Второй параметр функции, в котором пишется сам запрос с которым плагин обратится к базе данных

        "FindPlayerInTable" - Третий параметр, в котором указывается имя паблика, в который будут помещены данные, возвращённые из базы данных (требуется только в случае запросов с кэшированием)

        "i" - Четвёртый параметр, который позволяет передать в паблик, указанный в четвёртом параметре, какие-либо данные из того участка кода, в котором был отправлен запрос в базу данных. Работает точно так же, как SetTimerEx (в этом параметре указываются типы данных, которые будут переданы. Сами данные указываются в следующем параметре)

        playerid - Пятый параметр, в котором и указываются все данные для передачи в указанный паблик. Это может быть любой тип данных из тех, кто доступны в Pawn. 




         Скриншот




        Так же нам нужно эти данные записать в наш массив. Для этого мы идём в самый конец скрипта (для удобства) и вставляем туда следующий код:
          Открыть/закрыть
         Для R39
        PHP код:
        forward FindPlayerInTable(playerid);
        public 
        FindPlayerInTable(playerid)
        {
            new 
        rowsfields;
            
        cache_get_data(rowsfields);
            if(!
        rows)
            {
                
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""Введите пароль для регистрации нового аккаунта:""Регистрация""Выход");
            }
            else
            {
                
        ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""Введите пароль от аккаунта для того, чтоб продолжить игру:""Вход""Выход");
                
        cache_get_field_content(0"password"pInfo[playerid][pPassword], mysql_connect_id31);
            }
            return 
        1;

         Разбор кода
        PHP код:
        forward FindPlayerInTable(playerid);
        public 
        FindPlayerInTable(playerid
        Так мы объявляем новый колбэк, указывая его имя и параметры, которые должны передаваться при вызове этого колбэка.

        PHP код:
        new rowsfields
        Создаём две переменные, в которые запишем число строк и столбцов, которые будут возвращены в результате обработки нашего запроса

        PHP код:
        cache_get_data(rowsfields);
        /* Это и есть та самая запись.
        ------------------------------
        cache_get_data - имя функции, которая возвращает число строк и столбцов, возвращённых в результате обработки запроса
        rows - первый параметр функции, который хранит в себе число строк, возвращённых MySQL
        fields - второй параметр функции, который хранит в себе число столбцов, возвращённых MySQL
        Оба параметра обязательны*/ 
        PHP код:
        if(!rows
        Проверка, которая звучит так: "Если число строк, возвращённых MySQL, равно нулю...". Иначе говоря, если MySQL вернуло 0 строк после обработки запроса, значит аккаунт игрока не создан и нам можно предложить создать этот самый аккаунт игроку.

        PHP код:
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""Введите пароль для регистрации нового аккаунта:""Регистрация""Выход"); 
        Собственно, сам диалог регистрации
         Подробнее о диалоге
        PHP код:
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""Введите пароль для регистрации нового аккаунта:""Регистрация""Выход");
        /*------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        ShowPlayerDialog - Имя функции, которая отвечает за показ диалога
        playerid - Первый параметр, который отвечает за то, какому игроку показывать диалог (указывается ID игрока)
        dRegister - Второй параметр, в котором указывается ID диалога, по которому мы потом будем добавлять различные действия для этого самого диалога (dRegister - макрос, который мы создадим чуть позже)
        DIALOG_STYLE_INPUT - Третий параметр, в котором указывается стиль диалога (в данном случае это диалог с полем для ввода пользовательских данных)
        "Регистрация нового пользователя" - Четвёртый параметр, в котором указывается текст, который будет отображаться в шапке диалога
        "Введите пароль для регистрации нового аккаунта:" - Пятый параметр, в котором указывается текст самого диалогового окна
        "Регистрация" - Седьмой параметр, в котором мы указываем текст, содержащийся в левой кнопке диалогового окна
        "Выход" - Восьмой параметр, в котором указываем текст, содержащийся в правой кнопке диалогового окна
        */ 
        Или же прочтите статьи о диалоговых окнах на wiki.sa-mp.com:



        PHP код:
        else 
        Если проверка "if(!rows)" не сработала, значит MySQL нашёл в таблице аккаунт с нужным именем. А раз нашёл, значит показываем диалог с авторизацией и запишем пароль от аккаунта для дальнейших проверок

        PHP код:
        cache_get_field_content(0"password"pInfo[playerid][pPassword], mysql_connect_id31);
        /*-------------------------------------------------------------------------------------------------------------------------
        cache_get_field_content - название функции, которая возвращает значение указанного столбца
        0 - первый параметр функции, в котором указывается порядковый номер строки, возвращённой запросом (НЕ В ТАБЛИЦЕ). Более подробно расскажу чуть ниже
        "password" - второй параметр, в котором указывается имя столбца, значение которого нам нужно получить
        pInfo[playerid][pPassword] - третий параметр, в котором указывается массив для записи данных, которые вернёт функция
        mysql_connect_id - четвёртый параметр, в котором указывается ID соединения с базой данных
        31- пятый параметр, в котором указываться максимальный размер строки, которую может вернуть функция (ставить столько, сколько выделено в таблице для столбца и в скрипте для массива)
        */ 



         Для R40
        PHP код:
        forward FindPlayerInTable(playerid);
        public 
        FindPlayerInTable(playerid)
        {
            new 
        rows;
            
        cache_get_row_count(rows);

            if(!
        rows)
            {
                
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""Введите пароль для регистрации нового аккаунта:""Регистрация""Выход");
            }
            else
            {
                
        ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""Введите пароль от аккаунта для того, чтоб продолжить игру:""Вход""Выход");
                
        cache_get_value_name(0"password"pInfo[playerid][pPassword], 31);
            }
            return 
        1;

         Разбор кода
        PHP код:
        forward FindPlayerInTable(playerid);
        public 
        FindPlayerInTable(playerid
        Так мы объявляем новый колбэк, указывая его имя и параметры, которые должны передаваться при вызове этого колбэка.

        PHP код:
        new rows
        Создаём переменную, в которую запишем число строк, которые будут возвращены в результате обработки нашего запроса


        PHP код:
        cache_get_row_count(rows);
        /* Это и есть та самая запись. 
        ------------------------------
        cache_get_row_count - имя функции, которая возвращает число строк, возвращённых в результате обработки запроса 
        rows - параметр функции, который хранит в себе число строк, возвращённых MySQL */ 
        PHP код:
        if(!rows
        Проверка, которая звучит так: "Если число строк, возвращённых MySQL, равно нулю...". Иначе говоря, если MySQL вернуло 0 строк после обработки запроса, значит аккаунт игрока не создан и нам можно предложить создать этот самый аккаунт игроку.

        PHP код:
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""Введите пароль для регистрации нового аккаунта:""Регистрация""Выход"); 
        Собственно, сам диалог регистрации
         Подробнее о диалоге
        PHP код:
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""Введите пароль для регистрации нового аккаунта:""Регистрация""Выход");
        /*------------------------------------------------------------------------------------------------------------------------------------------------------------------------
        ShowPlayerDialog - Имя функции, которая отвечает за показ диалога
        playerid - Первый параметр, который отвечает за то, какому игроку показывать диалог (указывается ID игрока)
        dRegister - Второй параметр, в котором указывается ID диалога, по которому мы потом будем добавлять различные действия для этого самого диалога (dRegister - макрос, который мы создадим чуть позже)
        DIALOG_STYLE_INPUT - Третий параметр, в котором указывается стиль диалога (в данном случае это диалог с полем для ввода пользовательских данных)
        "Регистрация нового пользователя" - Четвёртый параметр, в котором указывается текст, который будет отображаться в шапке диалога
        "Введите пароль для регистрации нового аккаунта:" - Пятый параметр, в котором указывается текст самого диалогового окна
        "Регистрация" - Седьмой параметр, в котором мы указываем текст, содержащийся в левой кнопке диалогового окна
        "Выход" - Восьмой параметр, в котором указываем текст, содержащийся в правой кнопке диалогового окна
        */ 
        Или же прочтите статьи о диалоговых окнах на wiki.sa-mp.com:



        PHP код:
        else 
        Если проверка "if(!rows)" не сработала, значит MySQL нашёл в таблице аккаунт с нужным именем. А раз нашёл, значит показываем диалог с авторизацией и запишем пароль от аккаунта для дальнейших проверок

        PHP код:
        cache_get_value_name(0"password"pInfo[playerid][pPassword], mysql_connect_ID31);
        /*-------------------------------------------------------------------------------------------------------------------------
        cache_get_value_name - название функции, которая возвращает значение указанного столбца
        0 - первый параметр функции, в котором указывается порядковый номер строки, возвращённой запросом (НЕ В ТАБЛИЦЕ). Более подробно расскажу чуть ниже
        "password" - второй параметр, в котором указывается имя столбца, значение которого нам нужно получить
        pInfo[playerid][pPassword] - третий параметр, в котором указывается массив для записи данных, которые вернёт функция
        mysql_connect_ID - четвёртый параметр, в котором указывается ID соединения с базой данных
        31- пятый параметр, в котором указываться максимальный размер строки, которую может вернуть функция (ставить столько, сколько выделено в таблице для столбца и в скрипте для массива)
        */ 






      5. Создание действий для диалогов регистрации/авторизации

        Сначала нам нужно вспомнить о себе любимых и упростить работу с диалогами, создав ещё одно перечисление, которое будет позволять писать нам на месте ID диалога какие-то слова, намекающие нам на предназначение этого диалога, а не обычные числа. Ведь согласитесь, "dRegister" гораздо сильнее намекает нам на то, что этот диалог является диалогом регистрации, нежели просто "0", "1" или какое-либо ещё число. Но перечисление не только даст нам возможность более лучше понимать предназначение диалога по его ID, но и избавит нас от страха того, что ID диалогов могут перепутаться, ведь перечисление само определит свободный ID и установит его.

        Чтоб создать такое перечисление, находим наше перечисление с данными игроков и выше него создадим ещё одно:
        PHP код:
        enum e_DIALOG_IDs
        {
            
        dKickMessage,//Автоматически займёт ID 0
            
        dRegister,//ID 1
            
        dLogin//ID 2
        }; 
         Если Вы желаете изменить порядковые ID в перечислении
        Если Вы желаете, чтоб первый диалог занимал не ID 0, а, например, ID 10, достаточно присвоить первому члену перечисления "10" и далее перечисление само рассчитает ID для последующих членов:
        PHP код:
        enum e_DIALOG_IDs
        {
            
        dKickMessage 10,//Установим ID 10
            
        dRegister,//ID 11
            
        dLogin//ID 12
        }; 
        Так же у перечисления есть и другие тонкости, но подробнее о них я расскажу в другом уроке.

        Всё =) Теперь достаточно придумывать имя каждому новому диалогу, дописывать его в этот список и тогда Вы точно никогда не запутаетесь при создании новых диалогов.

        Теперь напишем сами действия. В OnDialogResponse добавим:
          Открыть/закрыть
         Для R39

        PHP код:
        switch(dialogid)
        {
            case 
        dRegister:
            {
                if(!
        response)
                {
                    
        ShowPlayerDialog(playeriddKickMessageDIALOG_STYLE_MSGBOX"Оповещение""{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Отказ от регистрации.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат""Выход""");
                    return 
        Kick(playerid);
                }
                if(!
        strlen(inputtext)) return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить регистрацию не введя пароль!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
                else if(
        strlen(inputtext) < 4) return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль слишком короткий!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
                else if(
        strlen(inputtext) > 30) return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль слишком длинный!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
                for(new 
        strlen(inputtext)-1!= -1i--)
                {
                    switch(
        inputtext[i])
                    {
                        case 
        '0'..'9''а'..'я''a'..'z''А'..'Я''A'..'Z': continue;
                        default: return 
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль содержит запрещённые символы!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
                    }
                }
                
        pInfo[playerid][pPassword][0] = EOS;
                
        strins(pInfo[playerid][pPassword], inputtext0);
                
        CreateNewAccount(playeridpInfo[playerid][pPassword]);
                return 
        1;
            }
            case 
        dLogin:
            {
                if(!
        response)
                {
                    
        ShowPlayerDialog(playeriddKickMessageDIALOG_STYLE_MSGBOX"Оповещение""{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Отказ от авторизации.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат""Выход""");
                    return 
        Kick(playerid);
                }
                if(!
        strlen(inputtext)) return ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить авторизацию не введя пароль!\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                for(new 
        strlen(inputtext)-1!= -1i--)
                {
                    switch(
        inputtext[i])
                    {
                        case 
        '0'..'9''а'..'я''a'..'z''А'..'Я''A'..'Z': continue;
                        default: return 
        ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Введённый пароль содержит запрещённые символы!\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                    }
                }
                if(!
        strcmp(pInfo[playerid][pPassword], inputtext))
                {
                    new 
        query_string[49+MAX_PLAYER_NAME];
                    
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]);
                    
        mysql_function_query(mysql_connect_IDquery_stringtrue"UploadPlayerAccount","i"playerid);
                }
                else
                {
                    switch(
        GetPVarInt(playerid"WrongPassword"))
                    {
                        case 
        0ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 3 попытки.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                        case 
        1ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 2 попытки.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                        case 
        2ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 1 попытка.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                        case 
        3ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталась последняя попытка, после чего Вас кикнет.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                        default:
                        {
                            
        ShowPlayerDialog(playeriddKickMessageDIALOG_STYLE_MSGBOX"Оповещение""{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Превышен лимит попыток на ввод пароля.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат""Выход""");
                            return 
        Kick(playerid);
                        }
                    }
                    
        SetPVarInt(playerid"WrongPassword"GetPVarInt(playerid"WrongPassword")+1);
                }
                return 
        1;
            }



         Для R40

        PHP код:
        switch(dialogid)
        {
            case 
        dRegister:
            {
                if(!
        response)
                {
                    
        ShowPlayerDialog(playeriddKickMessageDIALOG_STYLE_MSGBOX"Оповещение""{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Отказ от регистрации.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат""Выход""");
                    return 
        Kick(playerid);
                }
                if(!
        strlen(inputtext)) return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить регистрацию не введя пароль!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
                else if(
        strlen(inputtext) < 4) return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль слишком короткий!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
                else if(
        strlen(inputtext) > 30) return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль слишком длинный!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
                for(new 
        strlen(inputtext)-1!= -1i--)
                {
                    switch(
        inputtext[i])
                    {
                        case 
        '0'..'9''а'..'я''a'..'z''А'..'Я''A'..'Z': continue;
                        default: return 
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль содержит запрещённые символы!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
                    }
                }
                
        pInfo[playerid][pPassword][0] = EOS;
                
        strins(pInfo[playerid][pPassword], inputtext0);
                
        CreateNewAccount(playeridpInfo[playerid][pPassword]);
                return 
        1;
            }
            case 
        dLogin:
            {
                if(!
        response)
                {
                    
        ShowPlayerDialog(playeriddKickMessageDIALOG_STYLE_MSGBOX"Оповещение""{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Отказ от авторизации.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат""Выход""");
                    return 
        Kick(playerid);
                }
                if(!
        strlen(inputtext)) return ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить авторизацию не введя пароль!\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                for(new 
        strlen(inputtext)-1!= -1i--)
                {
                    switch(
        inputtext[i])
                    {
                        case 
        '0'..'9''а'..'я''a'..'z''А'..'Я''A'..'Z': continue;
                        default: return 
        ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Введённый пароль содержит запрещённые символы!\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                    }
                }
                if(!
        strcmp(pInfo[playerid][pPassword], inputtext))
                {
                    new 
        query_string[49+MAX_PLAYER_NAME];
                    
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]);
                    
        mysql_tquery(mysql_connect_IDquery_string"UploadPlayerAccount","i"playerid);
                }
                else
                {
                    switch(
        GetPVarInt(playerid"WrongPassword"))
                    {
                        case 
        0ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 3 попытки.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                        case 
        1ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 2 попытки.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                        case 
        2ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 1 попытка.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                        case 
        3ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталась последняя попытка, после чего Вас кикнет.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                        default:
                        {
                            
        ShowPlayerDialog(playeriddKickMessageDIALOG_STYLE_MSGBOX"Оповещение""{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Превышен лимит попыток на ввод пароля.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат""Выход""");
                            return 
        Kick(playerid);
                        }
                    }
                    
        SetPVarInt(playerid"WrongPassword"GetPVarInt(playerid"WrongPassword")+1);
                }
                return 
        1;
            }


         Разбор кода
        PHP код:
        switch(dialogid
        О switch можно почитать в статье, написанной Ziggi, о операторах в Pawn.
        Если попытаться перевести эту строку кода с машинного языка на человеческий, то смысл этой строки состоит в том, что тут мы указываем оператору switch переменную, значение которой мы будем сравнивать с заданными нами значениями в последующем коде.


        PHP код:
        case dRegister
        Эта строка всё так же относится к switch. Именно тут мы указываем значения, которые будем искать в "dialogid". В данном случае мы указали не число, а член перечисления, который подразумевает под собой ID "1"


        PHP код:
        if(!response)
        {
            
        ShowPlayerDialog(playeriddKickMessageDIALOG_STYLE_MSGBOX"Оповещение""{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Отказ от регистрации.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат""Вход""Выход");
            return 
        Kick(playerid);

        Тут мы проверяем значение параметра "response". Если оно равно нулю, значит игрок нажал на вторую (правую) кнопку или Esc (то бишь, попытался закрыть диалоговое окно) и поэтому мы его отсоединяем от сервера, показывая диалог-оповещение.
         Что за восклицательный знак перед response?
        Восклицательный знак перед параметром означает то, что мы ожидаем увидеть в "response" значение "false". Следовательно, эта проверка может выглядеть и так "if(response == 0)".

        Для тех, кто не в курсе:
        PHP код:
        false 0
        true 
        "любое значение, не равное нулю" 



        PHP код:
        if(!strlen(inputtext)) return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Вы не можете продолжить регистрацию не введя пароль!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
        else if(
        strlen(inputtext) < 4) return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль слишком короткий!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
        else if(
        strlen(inputtext) > 30) return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль слишком длинный!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
        for(new 
        strlen(inputtext)-1!= -1i--)
        {
            switch(
        inputtext[i])
            {
                case 
        '0'..'9''а'..'я''a'..'z''А'..'Я''A'..'Z': continue;
                default: return 
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль содержит запрещённые символы!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
            }

        Это серия различных проверок того, что ввёл игрок в поле для ввода (в данном случае - это пароль). Вот разбор первых трёх условий
        PHP код:
        if(!strlen(inputtext)) // Если игрок ничего не ввёл в поле для ввода...
        else if(strlen(inputtext) < 4// Если длинна введённого игроком текста меньше четырёх символов...
        else if(strlen(inputtext) > 30// Если длинна введённого игроком текста больше 30 символов... 
        При срабатывании каждого из условий игроку будет показан диалог, в котором будет указано то, какая из проверок не сработала и что игрок сделал не так.

        Теперь разберёмся с циклом.
        PHP код:
        for(new strlen(inputtext)-1!= -1i--)
        {
            switch(
        inputtext[i])
            {
                case 
        '0'..'9''а'..'я''a'..'z''А'..'Я''A'..'Z': continue;
                default: return 
        ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль содержит запрещённые символы!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход");
            }

        О циклах можно прочесть, опять же, в статье, написанной Ziggi об операторах. Я же расскажу подробнее о структуре.
        PHP код:
        for(new strlen(inputtext)-1!= -1i--)
        /*--------------------------------------------
        new i = strlen(inputtext)-1
        // strlen вернёт число символов, введённых игроком в поле для ввода (текст, введённый игроком, хранится в inputtext), но strlen учитывает и нуль-символ, который нам совсем не нужен. Поэтому от возвращённого функцией strlen числа отнимем единицу и запишем это число в переменную "i".
        --------------------------------------------
        i != -1
        // Тут мы задаём условие, которое звучит так: "Если "i" не равно "-1" - совершаем новый такт в цикле. Иначе останавливаем выполнение цикла". Стоит заметить, что проверка "!=" (не равно) подразумевает под собой то, что число "-1" не входит в поле видимости цикла (то есть, при "i" равной "-1", код в теле цикла не сработает. На последней итерации (такте) цикла переменная "i" будет равна "0").
        --------------------------------------------
        i--
        // Ну а тут мы просто отнимаем единицу от значения, хранящегося в "i". Эта запись равносильна следующим:
        1) "i -= 1"
        2) "i = i - 1"
        */ 
        Ну а это
        PHP код:
        switch(inputtext[i]) 
        уже знакомый нам switch, где мы проверяем значение определённой ячейки в массиве (ID этой ячейки хранится в "i")

         Немного о кодировках
        Теперь окунёмся в теоретическую часть, слабо относящуюся к уроку, которая поможет понять код, разбираемый дальше.
        Любая машина, которая в перспективе может поднять восстание и уничтожить жизнь на Земле, не понимает ничего, кроме нулей и единиц. Но мы, человеки создавшие этих киборгов-убийц, не согласились плясать под их дудку и придумали различные способы конвертировать привычные нам символы, отличные от нуля и единицы, в привычные киборгам-убийцам нули и единицы. Эти способы мы обозвали кодировками. Кодировок на сегодняшний день есть достаточно много и все они представляют из себя что-то типа таблиц, где за каждым символом, понятным нам, закреплён набор других символов (если кодировка направлена на двоичную систему счисления, с которой и работают машины, то это будет набор нулей и единиц. Ну а если нет, то, в любом случае, данные из отличной от двоичной системы счисления, конвертируются в двоичную систему счисления и только потом подаются машине). И какой бы символ Вы не попытались всунуть машине, она конвертирует его в набор нулей и единиц, опираясь на заданную в неё кодировку, и только потом будет с ним работать (кстати, именно по причине того, что в каждой кодировке за символами может быть закреплено любое кол-во нулей и единиц, которое заблагорассудится создателю этой кодировки, случается искажение текста, если напечатать текст в редакторе с одной кодировкой, а после переключить на другую. То есть, машина не может сама определить кодировку и если в одной кодировке за символом "@" закреплён такой набор нулей и единиц - "01110", а в другой, например, "01010", машина выдаст Вам не "@", а что-то совсем другое).
        В общем, наматываем на ус следующее:
        1) Однажды Ваш тостер поджарит не хлебушек, а Вас.
        2) Машины работают с набором нулей и единиц. Вся информация, какой бы она не была, конвертируется в нули и единицы. А для того, чтоб мы могли как-то контролировать этот процесс, придумали кодировки.

        Когда намотка на ус завершена, приступаем к дальнейшему разбору кода.


        switch работает исключительно с числами. В case нельзя указать ни переменную, ни слово в привычном для всех виде. Поэтому есть два варианта:
        1) Открывать таблицу символов для ASCII кодировки и искать тот набор нулей и единиц, что соответствует нашему символу. Ну и вписывать его.
        2) Использовать апостроф и операцию, что я описал в первом пункте, машина сделает за Вас.
        В коде выше мы используем именно второй способ, ибо он гораздо нагляднее.
        PHP код:
        case '0'..'9''а'..'я''a'..'z''А'..'Я''A'..'Z': continue; 
        Как я уже описывал выше, в switch мы проверяем каждый символ в ведённой игроком строке. А тут мы указываем то, какие из символов мы ищем. В данном случае если мы находим одну из цифр или же букв кириллического/латинского алфавита в любом из регистров, то мы пропускаем итерацию и смотрим содержимое следующей ячейки в массиве с строкой. То есть, тут мы указываем все символы, что разрешены в пароле.

        PHP код:
        default: return ShowPlayerDialog(playeriddRegisterDIALOG_STYLE_INPUT"Регистрация нового пользователя""{FF0000}Ошибка: {FFFFFF}Пароль содержит запрещённые символы!\nВведите пароль для регистрации нового аккаунта:\n{C0C0C0}Примечание:\n{666666}- Пароль чувствителен к регистру.\n- Пароль должен содержать от 4 до 30 символов.\n- Пароль может содержать латинские/кириллические символы и цифры (aA-zZ, аА-яЯ, 0-9).""Регистрация""Выход"); 
        default в "switch" - это как else в "if". То есть, если ни одно из условий в case не сработало, значит в дело вступает код из default. И в данном случае мы показываем игроку диалог в котором сказано, что тот ввёл запрещённый символ, отличный от перечисленных в case.


        Если ни одно из условий выше не сработало, значит игрок удовлетворил все наши правила по поводу введённого пароля и можно приступить к дальнейшей регистрации. Этот код:
        PHP код:
        pInfo[playerid][pPassword][0] = EOS
        Обнулит значение массива, хранящего пароль, дабы в нём по какой-либо причине не остался пароль предыдущего пользователя при регистрации нового. А этот код:
        PHP код:
        strins(pInfo[playerid][pPassword], inputtext0); 
        запишет введённый игроком пароль в массив pInfo, в ячейку с номером, хранящимся в playerid, которая сама разделяется на то число ячеек, сколько членов перечисления указано в enum (в данном случае в ячейку, которая равна ячейке "pPassword", а это ячейка с ID 2).
        О функции strins можно прочесть тут.


        А тут
        PHP код:
        CreateNewAccount(playeridpInfo[playerid][pPassword]); 
        Мы вызываем самописанную функцию, в которой будет хранится код создания аккаунта (запросы и прочее).




        В диалоге с авторизацией условия практически идентичны, поэтому описывать их не буду, а перейду сразу к новому условию:
          Открыть/закрыть
         Для R39
        PHP код:
        if(!strcmp(pInfo[playerid][pPassword], inputtext))
        {
            new 
        query_string[49+MAX_PLAYER_NAME];
            
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]);
            
        mysql_function_query(mysql_connect_IDquery_stringtrue"UploadPlayerAccount","i"playerid);
        }
        else
        {
            switch(
        GetPVarInt(playerid"WrongPassword"))
            {
                case 
        0ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 3 попытки.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                case 
        1ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 2 попытки.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                case 
        2ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 1 попытка.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                case 
        3ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталась последняя попытка, после чего Вас кикнет.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                default:
                {
                    
        ShowPlayerDialog(playeriddKickMessageDIALOG_STYLE_MSGBOX"Оповещение""{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Превышен лимит попыток на ввод пароля.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат""Вход""Выход");
                    return 
        Kick(playerid);
                }
            }
            
        SetPVarInt(playerid"WrongPassword"GetPVarInt(playerid"WrongPassword")+1);



        PHP код:
        if(!strcmp(pInfo[playerid][pPassword], inputtext)) 
        Тут мы сравниваем введённый игроком пароль с тем, что загрузили в массив pInfo ранее (при показе диалогов в "FindPlayerInTable")
        Если пароли совпали, то отправляем запрос в базу данных, который загрузит из таблицы все данные об игроке и удалим pVar, в котором мы подсчитываем число попыток ввести пароль
        PHP код:
        new query_string[49+MAX_PLAYER_NAME];
        /* Массив, 49 ячеек которого нужны для хранения текста запроса и 24 ячейки (MAX_PLAYER_NAME равно 24)
        для хранения ника игрока. Точнее, тут мы указали максимально возможную длину запроса*/
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]);
        /*SELECT * FROM - Указываем, что нам нужны данные всех столбцов...
        `accounts`- Указываем имя таблицы, в которой нужно искать
        WHERE `player_name` = '%s' - Указываем то, на основе каких данных нужно делать выборку (в данном случае грузим все найденные данные, исходя из имени игрока)*/
        mysql_function_query(mysql_connect_IDquery_stringtrue"UploadPlayerAccount","i"playerid);
        /*Напоминаю, что название функции, в которую будут возвращены данные из таблицы, указываются в четвёртом параметре и сейчас эта функция называется "UploadPlayerAccount"*/ 
        Ну а если не совпали, показываем игроку сообщение о том, что он неверно ввёл пароль и прибавляем к pVar для подсчёта попыток единицу. Когда значение pVar будет больше трёх, кикаем игрока.


         Для R40
        PHP код:
        if(!strcmp(pInfo[playerid][pPassword], inputtext))
        {
            new 
        query_string[49+MAX_PLAYER_NAME];
            
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]);
            
        mysql_tquery(mysql_connect_IDquery_string"UploadPlayerAccount","i"playerid);
        }
        else
        {
            switch(
        GetPVarInt(playerid"WrongPassword"))
            {
                case 
        0ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 3 попытки.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                case 
        1ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 2 попытки.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                case 
        2ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталось 1 попытка.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                case 
        3ShowPlayerDialog(playeriddLoginDIALOG_STYLE_INPUT"Авторизация""{FF0000}Ошибка: {FFFFFF}Вы ввели неверный пароль! У Вас осталась последняя попытка, после чего Вас кикнет.\nВведите пароль от аккаунта для входа на сервер:""Вход""Выход");
                default:
                {
                    
        ShowPlayerDialog(playeriddKickMessageDIALOG_STYLE_MSGBOX"Оповещение""{FFFFFF}Вы были кикнуты с сервера.\n{FF0000}Причина: Превышен лимит попыток на ввод пароля.\n{FFFFFF}Для выхода с сервера введите \"/q\" в чат""Вход""Выход");
                    return 
        Kick(playerid);
                }
            }
            
        SetPVarInt(playerid"WrongPassword"GetPVarInt(playerid"WrongPassword")+1);



        PHP код:
        if(!strcmp(pInfo[playerid][pPassword], inputtext)) 
        Тут мы сравниваем введённый игроком пароль с тем, что загрузили в массив pInfo ранее (при показе диалогов в "FindPlayerInTable")
        Если пароли совпали, то отправляем запрос в базу данных, который загрузит из таблицы все данные об игроке и удалим pVar, в котором мы подсчитываем число попыток ввести пароль
        PHP код:
        new query_string[49+MAX_PLAYER_NAME];
        /* Массив, 49 ячеек которого нужны для хранения текста запроса и 24 ячейки (MAX_PLAYER_NAME равно 24)
        для хранения ника игрока. Точнее, тут мы указали максимально возможную длину запроса*/
        format(query_stringsizeof(query_string), "SELECT * FROM `accounts` WHERE `player_name` = '%s'"pInfo[playerid][pName]);
        /*SELECT * FROM - Указываем, что нам нужны данные всех столбцов...
        `accounts`- Указываем имя таблицы, в которой нужно искать
        WHERE `player_name` = '%s' - Указываем то, на основе каких данных нужно делать выборку (в данном случае грузим все найденные данные, исходя из имени игрока)*/
        mysql_tquery(mysql_connect_IDquery_string"UploadPlayerAccount","i"playerid);
        /*Напоминаю, что название функции, в которую будут возвращены данные из таблицы, указываются в четвёртом параметре и сейчас эта функция называется "UploadPlayerAccount"*/ 
        Ну а если не совпали, показываем игроку сообщение о том, что он неверно ввёл пароль и прибавляем к pVar для подсчёта попыток единицу. Когда значение pVar будет больше трёх, кикаем игрока.



         Скриншот











      6. Создание/загрузка аккаунта игрока

        Создание аккаунта:
        В самый конец мода вставим этот stock:
          Открыть/закрыть
         Для R39
        PHP код:
        stock CreateNewAccount(playeridpassword[])
        {
            new 
        query_string[66+MAX_PLAYER_NAME-4+30];
            
        format(query_stringsizeof(query_string), "INSERT INTO `accounts` (`player_name`, `password`) VALUES ('%s', '%s')"pInfo[playerid][pName], password);
            
        mysql_function_query(mysql_connect_IDquery_stringtrue"UploadPlayerAccountNumber""i"playerid);


            
        format(query_stringsizeof(query_string), "Аккаунт %s успешно зарегистрирован. Администрация желает Вам приятной игры!"pInfo[playerid][pName]);
            
        SendClientMessage(playerid0xFFFFFF00query_string);
            
        SpawnPlayer(playerid);
            return 
        1;

         Разбор кода
        PHP код:
        CreateNewAccount(playeridpassword[]) 
        Собственно, сама функция с двумя параметрами: числовой, который хранит ID игрока и в виде массива, который хранит пароль.
        PHP код:
        format(query_stringsizeof(query_string), "INSERT INTO `accounts` (`player_name`, `password`) VALUES ('%s', '%s')"pInfo[playerid][pName], password); 
        Данным запросом мы обновляем данные в таблице на те, что игрок ввёл при регистрации. В данный запрос нужно добавлять обновление только тех данных, что можно заполучить только в момент регистрации (например, IP игрока). Имя и пароль мы сохраняем для того, чтоб при выходе с сервера мы могли сохранить остальные данные, опираясь на имя игрока (то есть, возраст, пол и прочее можно сохранить и при выходе, а не забивать этот запрос. Тут только важная информация, которую либо не достать в дальнейшем, либо без которой дальнейшая работа каких-либо систем невозможна).

        PHP код:
        mysql_function_query(mysql_connect_IDquery_stringtrue"UploadPlayerAccountNumber""i"playerid); 
        Эта функция, в целом, Вам известна по предыдущим моим объяснениям в данном уроке, но есть одно "но". Вообще, при отправке запроса "INSERT INTO", не нужно указывать ни кэширование запроса (третий параметр (true)), ни коллбэк, который будет являться кэшем. Но после создания аккаунта нам надо узнать номер строки (значение столбца ID), который занял этот аккаунт для того, чтоб потом мы могли сохранить все изменения при выходе игрока. Для этого можно использовать функцию "cache_insert_id", которая как раз и вернёт нужное нам значение (о ней я расскажу позже). Но чтоб она сработала, как раз и нужно, чтоб MySQL вернуло данные о запросе, поэтому я и дописал тут коллбэк.

        PHP код:
        format(query_stringsizeof(query_string), "Аккаунт %s успешно зарегистрирован. Администрация желает Вам приятной игры!"pInfo[playerid][pName]);
        SendClientMessage(playerid0xFFFFFF00query_string); 
        Тут мы оповещаем игрока о успешной регистрации :)
        PHP код:
        SpawnPlayer(playerid); 
        Ну а этой функцией мы отправляем игрока на спавн. Она практически идентична (а, возможно, и полностью идентична) вызову коллбэка OnPlayerSpawn напрямую, но лучше использовать именно функцию.


        А вот и сам коллбэк, который вернёт ID аккаунта:
        PHP код:
        forward UploadPlayerAccountNumber(playerid);
        public 
        UploadPlayerAccountNumber(playeridpInfo[playerid][pID] = cache_insert_id(mysql_connect_ID); 
         Разбор кода
        Собственно, тут Вам должно быть известно всё, кроме самого главного - функции cache_insert_id.
        Эта функция имеет всего один необязательный параметр, в котором указывается ID подключения к БД.
        PHP код:
        cache_insert_id(connectionHandle 1); 
        Эта функция возвращает значение столбца с параметром AUTO_INCREMENT, которое появилось после "INSERT" запроса.


         Для R40
        PHP код:
        stock CreateNewAccount(playeridpassword[])
        {
            new 
        query_string[66+MAX_PLAYER_NAME-4+30];
            
        format(query_stringsizeof(query_string), "INSERT INTO `accounts` (`player_name`, `password`) VALUES ('%s', '%s')"pInfo[playerid][pName], password);
            
        mysql_tquery(mysql_connect_IDquery_string"UploadPlayerAccountNumber""i"playerid);


            
        format(query_stringsizeof(query_string), "Аккаунт %s успешно зарегистрирован. Администрация желает Вам приятной игры!"pInfo[playerid][pName]);
            
        SendClientMessage(playerid0xFFFFFF00query_string);
            
        SpawnPlayer(playerid);
            return 
        1;

         Разбор кода
        PHP код:
        CreateNewAccount(playeridpassword[]) 
        Собственно, сама функция с двумя параметрами: числовой, который хранит ID игрока и в виде массива, который хранит пароль.
        PHP код:
        format(query_stringsizeof(query_string), "INSERT INTO `accounts` (`player_name`, `password`) VALUES ('%s', '%s')"pInfo[playerid][pName], password); 
        Данным запросом мы обновляем данные в таблице на те, что игрок ввёл при регистрации. В данный запрос нужно добавлять обновление только тех данных, что можно заполучить только в момент регистрации (например, IP игрока). Имя и пароль мы сохраняем для того, чтоб при выходе с сервера мы могли сохранить остальные данные, опираясь на имя игрока (то есть, возраст, пол и прочее можно сохранить и при выходе, а не забивать этот запрос. Тут только важная информация, которую либо не достать в дальнейшем, либо без которой дальнейшая работа каких-либо систем невозможна).

        PHP код:
        mysql_tquery(mysql_connect_IDquery_string"UploadPlayerAccountNumber""i"playerid); 
        Эта функция, в целом, Вам известна по предыдущим моим объяснениям в данном уроке.

        PHP код:
        format(query_stringsizeof(query_string), "Аккаунт %s успешно зарегистрирован. Администрация желает Вам приятной игры!"pInfo[playerid][pName]);
        SendClientMessage(playerid0xFFFFFF00query_string); 
        Тут мы оповещаем игрока о успешной регистрации :)
        PHP код:
        SpawnPlayer(playerid); 
        Ну а этой функцией мы отправляем игрока на спавн. Она практически идентична (а, возможно, и полностью идентична) вызову коллбэка OnPlayerSpawn напрямую, но лучше использовать именно функцию.


        А вот и сам коллбэк, который вернёт ID аккаунта:
        PHP код:
        forward UploadPlayerAccountNumber(playerid);
        public 
        UploadPlayerAccountNumber(playeridpInfo[playerid][pID] = cache_insert_id(); 
         Разбор кода
        Собственно, тут Вам должно быть известно всё, кроме самого главного - функции cache_insert_id.
        Эта функция не имеет параметров.
        PHP код:
        cache_insert_id(); 
        Эта функция возвращает значение столбца с параметром AUTO_INCREMENT, которое появилось после "INSERT" запроса.


        Загрузка аккаунта:
          Открыть/закрыть
         Для R39
        PHP код:
        forward UploadPlayerAccount(playerid);
        public 
        UploadPlayerAccount(playerid)
        {
            
        pInfo[playerid][pID] = cache_get_field_content_int(0"id"mysql_connect_ID);
            
        SendClientMessage(playerid0xFFFFFF00"Вы успешно авторизировались!");
            
        SpawnPlayer(playerid);
            return 
        1;

         Разбор кода
        Пока что в нашей таблице всего 3 столбца: ID аккаунта, имя и пароль. Имя мы узнали в момент входа игрока на сервер, а пароль в момент авторизации, поэтому грузить повторно их бессмысленно. Осталось загрузить только ID аккаунта, который потом можно использовать в различных системах (например, в системе личного транспорта этот самый транспорт привязать к ID аккаунта игрока).
        PHP код:
        pInfo[playerid][pID] = cache_get_field_content_int(0"id"mysql_connect_ID); 
        В данной версии плагина существует три функции для работы с тремя основными типами данных. О них Вы можете узнать, открыв спойлер ниже.
         Функции


        cache_get_field_content_int - Функция, которая работает с целочисленными данными.

        Параметры:
        PHP код:
        cache_get_field_content_int(row, const field_name[], connectionHandle 1);
        /*------------------------------------------------
        row - Номер строки в ВОЗВРАЩЁННЫХ данных, с которой будем работать (первая строка всегда равна нулю и так как в результате запроса строк не может быть больше одной, мы ставим "0")
        const field_name[] - Имя столбца, из которого и будем брать значение
        connectionHandle - ID базы данных*/ 
        Пример использования:
        PHP код:
        new variable cache_get_field_content_int(0"level"dbHandle);
        printf("Уровень игрока равен %d"variable); 


        cache_get_field_content - Функция, которая работает с строками.

        Параметры:
        PHP код:
        cache_get_field_content(row, const field_name[], destination[], connectionHandle 1max_len=sizeof(destination));
        /*-----------------------------------------------------------------------------------------------------------------
        row - Номер строки в ВОЗВРАЩЁННЫХ данных, с которой будем работать (первая строка всегда равна нулю)
        const field_name[] - Имя столбца, из которого и будем брать значение
        destination[] - Массив, в который будет записан текст из столбца
        connectionHandle - ID базы данных
        max_len - Необязательный параметр. Изначально равен числу ячеек в массиве, который указали в "destination"*/ 
        Пример использования:
        PHP код:
        new player_name[MAX_PLAYER_NAME];
        cache_get_field_content(0"player_name"player_namedbHandle);
        printf("Имя игрока - %s"player_name); 
        Примечание: Если в данной функции указать двумерный массив, параметр "max_len" обязателен к заполнению, так как оператор "sizeof" не сможет вернуть размер двумерного массива.
        Пример:
        PHP код:
        new player_name[MAX_PLAYERS][MAX_PLAYER_NAME];
        cache_get_field_content(0"player_name"player_name[playerid], dbHandleMAX_PLAYER_NAME);// В последнем параметре мы указали размер второго индекса массива "player_name"
        printf("Имя игрока - %s"player_name); 


        cache_get_field_content_float - Функция, которая работает с вещественным типом данных.

        Параметры:
        PHP код:
        cache_get_field_content_float(row, const field_name[], connectionHandle 1);
        /*-----------------------------------------------------------------------------------------------------------------
        row - Номер строки в ВОЗВРАЩЁННЫХ данных, с которой будем работать (первая строка всегда равна нулю)
        const field_name[] - Имя столбца, из которого и будем брать значение
        connectionHandle - ID базы данных*/ 
        Пример использования:
        PHP код:
        new Floathealth cache_get_field_content_float(0"player_health"dbHandle);
        printf("У игрока %f жизней"health); 


        Ну а предназначение этих строк
        PHP код:
        SendClientMessage(playerid0xFFFFFF00"Вы успешно авторизировались!");
        SpawnPlayer(playerid); 
        Вам и так известно :)


         Для R40

        PHP код:
        forward UploadPlayerAccount(playerid);
        public 
        UploadPlayerAccount(playerid)
        {
            
        cache_get_value_name_int(0"id"pInfo[playerid][pID]);
            
        SendClientMessage(playerid0xFFFFFF00"Вы успешно авторизировались!");
            
        SpawnPlayer(playerid);
            return 
        1;

         Разбор кода
        Пока что в нашей таблице всего 3 столбца: ID аккаунта, имя и пароль. Имя мы узнали в момент входа игрока на сервер, а пароль в момент авторизации, поэтому грузить повторно их бессмысленно. Осталось загрузить только ID аккаунта, который потом можно использовать в различных системах (например, в системе личного транспорта этот самый транспорт привязать к ID аккаунта игрока).
        PHP код:
        cache_get_value_name_int(0"id"pInfo[playerid][pID]); 
        В данной версии плагина существует три функции для работы с тремя основными типами данных. О них Вы можете узнать, открыв спойлер ниже.
         Функции


        cache_get_value_name_int - Функция, которая работает с целочисленными данными.

        Параметры:
        PHP код:
        cache_get_value_name_int(row_idx, const column_name[], &destination);
        /*------------------------------------------------
        row_idx - Номер строки в ВОЗВРАЩЁННЫХ данных, с которой будем работать (первая строка всегда равна нулю и так как в результате запроса строк не может быть больше одной, мы ставим "0")
        const column_name[] - Имя столбца, из которого и будем брать значение
        &destination - Переменная, в которую запишется возвращённый результат*/ 
        Пример использования:
        PHP код:
        new variable;
        cache_get_value_name_int(0"level"variable);
        printf("Уровень игрока равен %d"variable); 


        cache_get_value_name - Функция, которая работает с строками.

        Параметры:
        PHP код:
        cache_get_value_name(row_idx, const column_name[], destination[], max_len sizeof(destination));
        /*-----------------------------------------------------------------------------------------------------------------
        row_idx - Номер строки в ВОЗВРАЩЁННЫХ данных, с которой будем работать (первая строка всегда равна нулю)
        const column_name[] - Имя столбца, из которого и будем брать значение
        destination[] - Массив, в который будет записан текст из столбца
        max_len - Необязательный параметр. Изначально равен числу ячеек в массиве, который указали в "destination"*/ 
        Пример использования:
        PHP код:
        new player_name[MAX_PLAYER_NAME];
        cache_get_value_name(0"player_name"player_name);
        printf("Имя игрока - %s"player_name); 
        Примечание: Если в данной функции указать двумерный массив, параметр "max_len" обязателен к заполнению, так как оператор "sizeof" не сможет вернуть размер двумерного массива.
        Пример:
        PHP код:
        new player_name[MAX_PLAYERS][MAX_PLAYER_NAME];
        cache_get_value_name(0"player_name"player_name[playerid], MAX_PLAYER_NAME);// В последнем параметре мы указали размер второго индекса массива "player_name"
        printf("Имя игрока - %s"player_name); 


        cache_get_field_content_float - Функция, которая работает с вещественным типом данных.

        Параметры:
        PHP код:
        cache_get_value_name_float(row_idx, const column_name[], &Float:destination);
        /*-----------------------------------------------------------------------------------------------------------------
        row_idx - Номер строки в ВОЗВРАЩЁННЫХ данных, с которой будем работать (первая строка всегда равна нулю)
        const column_name[] - Имя столбца, из которого и будем брать значение
        &Float:destination - Переменная, в которую запишется возвращённый результат*/ 
        Пример использования:
        PHP код:
        new Floathealth;
        cache_get_value_name_float(0"player_health"health);
        printf("У игрока %f жизней"health); 


        Ну а предназначение этих строк
        PHP код:
        SendClientMessage(playerid0xFFFFFF00"Вы успешно авторизировались!");
        SpawnPlayer(playerid); 
        Вам и так известно :)


         Скриншот







      7. Сохранение аккаунта

        Так же, в самом конце, добавим новый stock
          Открыть/закрыть
         Для R39
        PHP код:
        stock SaveAccount(playerid)
        {
            new 
        query_string[(21)+(16+11)+(20+MAX_PLAYER_NAME)+(16+30)] = "UPDATE `accounts` SET";

            
        format(query_stringsizeof(query_string), "%s `player_name` = '%s',"query_stringpInfo[playerid][pName]);
            
        format(query_stringsizeof(query_string), "%s `password` = '%s'"query_stringpInfo[playerid][pPassword]);

            
        format(query_stringsizeof(query_string), "%s WHERE `id` = '%d'"query_stringpInfo[playerid][pID]);
            
        mysql_function_query(mysql_connect_IDquery_stringfalse"""");
            return 
        1;



         Для R40
        PHP код:
        stock SaveAccount(playerid)
        {
            new 
        query_string[(21)+(16+11)+(20+MAX_PLAYER_NAME)+(16+30)] = "UPDATE `accounts` SET";

            
        format(query_stringsizeof(query_string), "%s `player_name` = '%s',"query_stringpInfo[playerid][pName]);
            
        format(query_stringsizeof(query_string), "%s `password` = '%s'"query_stringpInfo[playerid][pPassword]);

            
        format(query_stringsizeof(query_string), "%s WHERE `id` = '%d'"query_stringpInfo[playerid][pID]);
            
        mysql_tquery(mysql_connect_IDquery_string"""");
            return 
        1;



         Немного моего мнения
        Так как это всего лишь урок и тут мы делаем сохранение всего 3-х столбцов, сохранять, кроме имени и пароля, больше нечего. Но вообще, как я считаю, сохранять имя и пароль при выходе бессмысленно, ибо что первое, что второе не может быть никак изменено игроком без нашего ведома (только мы можем позволить игроку сменить ник, написав для этого функцию). Поэтому и сохранять эти данные следует прямо во время изменения, а не при каждом выходе. При выходе можно сохранять такую вещь, как координаты или здоровье. Ну, на крайний случай, ещё деньги, если Вам не по силам написать античит, при этом сделав сохранение денег при каждом их изменении так, чтоб сервер при этом не закидал MySQL запросами. Практически всё остальноё можно и нужно сохранять прямиком при внесении изменений в информацию (уровень/ID дома, которым игрок владеет/ID фракции и прочая информация, которая изменяется не так часто и изменение которой можно 100% отследить). Но это лишь моё мнение и Вы можете к нему не прислушиваться. От того, что Вы будете сохранять всё при выходе, хуже от этого не станет.


          Открыть/закрыть
         Для R39
         Разбор кода
        PHP код:
        new query_string[(21)+(16+11)+(20+MAX_PLAYER_NAME)+(16+30)] = "UPDATE `accounts` SET"
        Объявление массива, в котором будет хранится запрос. Для удобства каждая часть запроса, помещённая в отдельный format, выделена скобками. Первое число в скобках означает число ячеек, которое нужно для хранения текста до форматирования (то есть, до вставки в него ника/пароля и прочих данных), а второе - число ячеек, которое требуется для хранения вставляемых данных. "+1" в конце - это ячейка для нуль-символа. Таким образом, работа с массивом делается максимально удобной для редактирования.
         Текущее сопоставление данных в ячейке с строками
        PHP код:
        stock SaveAccount(playerid)
        {
            new 
        query_string[(21)+(16+11)+(20+MAX_PLAYER_NAME)+(16+30)+1] = "UPDATE `accounts` SET";// "UPDATE `accounts` SET" - (21)

            
        format(query_stringsizeof(query_string), "%s `player_name` = '%s',"query_stringpInfo[playerid][pName]);// (20+MAX_PLAYER_NAME)
            
        format(query_stringsizeof(query_string), "%s `password` = '%s'"query_stringpInfo[playerid][pPassword]);// (16+30)

            
        format(query_stringsizeof(query_string), "%s WHERE `id` = '%d'"query_stringpInfo[playerid][pID]);// (16+11)
            
        mysql_function_query(mysql_connect_IDquery_stringfalse"""");
            return 
        1;


         Как правильно высчитывать длину строки
        Один символ в строке равен одной ячейке. Заполнители: "%s, %d, %f и т.д." - не занимают ячеек, так как на их места появляются вставляемые данные => при счёте их не учитывать. При хранении строки стоит учитывать, что существует нуль-символ, который сигнализирует машине об окончании строки, поэтому к реальному размеру строки всегда прибавляем единицу. (НО: при вставке одной строки в другую, нуль-символ строки, которая идёт позади/внутри другой строки, исчезает, поэтому для вставляемой строки учитывается только реальный размер).

        Примеры:
         Нуль-символ
        Имеется строка - "Приветствую, игрок". Если посчитать число символов в ней (включая пробелы!), то всего их насчитаем ровно 18. Значит массив, в который мы будем записывать строку должен выглядеть так?
        PHP код:
        new string[18]; 
        А вот и нет. Ведь есть ещё нуль-символ, для которого тоже нужно место. Если это место ему не предоставить, машина отбросит все символы, что не помещаются в 18 ячеек (если строка больше 18 ячеек) и ещё один, на место которого и поставит нуль-символ. Поэтому для хранения такой строки нам понадобится 19 ячеек и массив будет выглядеть так:
        PHP код:
        new string[19]; 

         Заполнители
        Имеется строка - "Приветствую, %s", в которую мы хотим поместить имя игрока. Если посчитать число символов в ней (включая пробелы!), то всего их насчитаем ровно 15. Но не забываем, что заполнители веса не имеют, так как на их месте появляются вставляемые данные. Поэтому число ячеек равно не 15, а 13. Дабы ещё и удовлетворить потребности нуль-символа, выделим для него ещё одну ячейку и получим 14. Но и это ещё не всё. Раз мы решили вставлять ник игрока, то пора нам обратиться к официальной документации для SA-MP. Информацию можно поискать на официальном форуме или wiki-страничке, а можно открыть инклюды, что идут вместе с сервером и посмотреть там. В данном случае нам нужно узнать то, сколько ячеек в текущей версии мультиплеера, может занимать ник игрока. Что искать на форуме Вам, надеюсь, объяснять не нужно, а вот в инклюдах нужно искать всё то, что хоть как-то связано с именем игрока. Логично предположить, что макрос, содержащий информацию о максимальной длине ника, будет содержать слова "MAX" и "NAME", так что ищем среди макросов всё, что нам хоть как-то подходит. В данном случае нужный нам макрос хранится в инклюде "a_samp" и выглядит он так
        PHP код:
        #define MAX_PLAYER_NAME                            (24) 
        Скобки макросу нужны для максимальной совместимости с кодом, поэтому просто не обращаем на них внимания. Из макроса мы узнаём, что максимально возможная длина имени равна 24 символам. Так что к нашему числу ячеек (14) нужно прибавить 24 и именно это будет финальным размером нашего массива. В итоге получим следующее:
        PHP код:
        new string[38]; 
        Таким образом мы выделили ровно столько ячеек, сколько может использоваться в случае, когда у игрока длина ника равна 24 символам и такой массив можно назвать оптимизированным.
         Другие варианты записи размера ячеек:

        Запись
        PHP код:
        new string[38]; 
        Равносильна следующим записям:
        • PHP код:
          new string[14+MAX_PLAYER_NAME]; 
        • PHP код:
          new string[13+MAX_PLAYER_NAME+1]; 
        • PHP код:
          new string[14+24]; 
        • PHP код:
          new string[13+24+1]; 
        • PHP код:
          new string[(14)+(24)]; 
        • PHP код:
          new string[1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1]; 
        • И т.д.

        Все эти записи в итоге будут выглядеть как первая (new string[38];). Преобразование произойдёт в момент компиляции, так что о быстродействии заботиться не стоит :) Я лишь советую Вам использовать стандартные макросы, если они были даны разработчиками. Ибо тогда, если вдруг разработчики SA-MP, например, поменяют длину ника игрока, Вам будет достаточно перекомпилировать мод и жить дальше, а не уменьшать/увеличивать каждое значение вручную.


         Склейка строк
        Имеется три строки и три массива, которые хранят эти строки
        PHP код:
        new string_1[7] = "Привет";
        new 
        string_2[3] = ", ";//запятая + пробел + нуль-символ
        new string_3[6] = "игрок"
        Нам нужно все эти три строки склеить в одну. Воспользуемся функцией format. Выглядеть код будет так
        PHP код:
        format(string_allsizeof(string_all), "%s%s%s"string_1string_2string_3); 
        Как правильно подсчитать размер для массива "string_all"? Просто сложить размер трёх ячеек и всё? Нет, не верно. Ведь при создании массивов для хранения строк по отдельности мы учитывали наличие нуль-символа, который сигнализирует о конце строки. А это значит, что при склейке эти значения нам совсем не нужны, ведь какой нуль-символ может быть в середине строки? Для верного подсчёта строки нам потребуется просто высчитать настоящий размер строк (или просто отнять от текущего кол-ва ячеек массивов единицу) и уже после этого прибавить к ним единицу. В итоге у нас выйдет такой массив:
        PHP код:
        new string_all[14]; 


        После объявления массива мы сразу же запишем в него начало запроса, которое не требует вставки в себя каких-либо данных.


        PHP код:
        format(query_stringsizeof(query_string), "%s `player_name` = '%s'"query_stringpInfo[playerid][pName]);
        format(query_stringsizeof(query_string), "%s `password` = '%s'"query_stringpInfo[playerid][pPassword]); 
        Это сохранение имени игрока и пароля. "%s" в начале строки нужна для того, чтоб те данные, что уже имеются в query_string, поместились в начало строки и новые данные "приклеились" к ним. Вставка новых данных будет выглядеть так:
        PHP код:
        format(query_stringsizeof(query_string), "%s `имя_столбца` = 'заполнитель'"query_string/*переменная для вставки*/); 
        Только не забываем подсчитать длину этой строки и добавить нужное число ячеек к массиву :) А так же запомните, что новая запись должна иметь в самом конце запятую, если она не стоит последней.
         Пример
        PHP код:
        stock SaveAccount(playerid)
        {
            new 
        query_string[(21)+(15+11)+(20+MAX_PLAYER_NAME)+(16+30)+(22+11)+(19+11)] = "UPDATE `accounts` SET";

            
        format(query_stringsizeof(query_string), "%s `player_name` = '%s',"query_stringpInfo[playerid][pName]);//Запятая есть
            
        format(query_stringsizeof(query_string), "%s `password` = '%s',"query_stringpInfo[playerid][pPassword]);//Запятая есть
            
        format(query_stringsizeof(query_string), "%s `account_level` = '%d',"query_stringpInfo[playerid][pLevel]);//Запятая есть
            
        format(query_stringsizeof(query_string), "%s `admin_level` = '%d'"query_stringpInfo[playerid][pAdmin]);//Запятой нет

            
        format(query_stringsizeof(query_string), "%s WHERE `id` = '%d'"query_stringpInfo[playerid][pID]);//И тут нет
            
        mysql_function_query(mysql_connect_IDquery_stringfalse"""");
            return 
        1;

        В итоге выйдет следующий запрос:
        PHP код:
        UPDATE `accountsSET `player_name` = 'Имя_игрока', `password` = 'Пароль', `account_level` = 'Уровень игрока', `admin_level` = 'Уровень админки' WHERE `player_name` = 'Имя_игрока' 
        То есть, запятые отделяют друг от друга данные для сохранения и MySQL таким образом определяет где заканчивается информация для одного столбца и начинается для следующего. Именно поэтому к предпоследней строке (в данном случае это сохранение админки) запятая не ставится (кто не понял: если поставить запятую, то MySQL будет искать после неё следующий блок данных, но найдёт лишь оператор "WHERE". Из-за этого случится ошибка и запрос не обработается)

        И да, это не самый оптимизированный вариант (постоянный вызов функции format, вместо одного), но использование подобного метода не навредит Вашему моду. Я использовал именно его потому, что он максимально удачен в плане "оптимизация/понятность/удобство" и для новичков это самый лучший вариант.


        PHP код:
        format(query_stringsizeof(query_string), "%s WHERE `id` = '%d'"query_stringpInfo[playerid][pID]); 
        Окончание нашего запроса, где мы указываем, что нужный аккаунт нужно искать по ID. Новые данные на сохранение нужно помещать между этой строкой и объявлением массива. Желательно в том порядке, в котором расположены столбцы в таблице (для Вашего же удобства).


        PHP код:
        mysql_function_query(mysql_connect_IDquery_stringfalse""""); 
        Отправляем полученный запрос. Мы обновляем данные в базе данных и никаких данных в ответ не ждём, поэтому и кэширование нам не нужно => и функцию мы никакую не вызываем.


         Для R40
         Разбор кода
        PHP код:
        new query_string[(21)+(16+11)+(20+MAX_PLAYER_NAME)+(16+30)] = "UPDATE `accounts` SET"
        Объявление массива, в котором будет хранится запрос. Для удобства каждая часть запроса, помещённая в отдельный format, выделена скобками. Первое число в скобках означает число ячеек, которое нужно для хранения текста до форматирования (то есть, до вставки в него ника/пароля и прочих данных), а второе - число ячеек, которое требуется для хранения вставляемых данных. "+1" в конце - это ячейка для нуль-символа. Таким образом, работа с массивом делается максимально удобной для редактирования.
         Текущее сопоставление данных в ячейке с строками
        PHP код:
        stock SaveAccount(playerid)
        {
            new 
        query_string[(21)+(16+11)+(20+MAX_PLAYER_NAME)+(16+30)+1] = "UPDATE `accounts` SET";// "UPDATE `accounts` SET" - (21)

            
        format(query_stringsizeof(query_string), "%s `player_name` = '%s',"query_stringpInfo[playerid][pName]);// (20+MAX_PLAYER_NAME)
            
        format(query_stringsizeof(query_string), "%s `password` = '%s'"query_stringpInfo[playerid][pPassword]);// (16+30)

            
        format(query_stringsizeof(query_string), "%s WHERE `id` = '%d'"query_stringpInfo[playerid][pID]);// (16+11)
            
        mysql_tquery(mysql_connect_IDquery_string"""");
            return 
        1;


         Как правильно высчитывать длину строки
        Один символ в строке равен одной ячейке. Заполнители: "%s, %d, %f и т.д." - не занимают ячеек, так как на их места появляются вставляемые данные => при счёте их не учитывать. При хранении строки стоит учитывать, что существует нуль-символ, который сигнализирует машине об окончании строки, поэтому к реальному размеру строки всегда прибавляем единицу. (НО: при вставке одной строки в другую, нуль-символ строки, которая идёт позади/внутри другой строки, исчезает, поэтому для вставляемой строки учитывается только реальный размер).

        Примеры:
         Нуль-символ
        Имеется строка - "Приветствую, игрок". Если посчитать число символов в ней (включая пробелы!), то всего их насчитаем ровно 18. Значит массив, в который мы будем записывать строку должен выглядеть так?
        PHP код:
        new string[18]; 
        А вот и нет. Ведь есть ещё нуль-символ, для которого тоже нужно место. Если это место ему не предоставить, машина отбросит все символы, что не помещаются в 18 ячеек (если строка больше 18 ячеек) и ещё один, на место которого и поставит нуль-символ. Поэтому для хранения такой строки нам понадобится 19 ячеек и массив будет выглядеть так:
        PHP код:
        new string[19]; 

         Заполнители
        Имеется строка - "Приветствую, %s", в которую мы хотим поместить имя игрока. Если посчитать число символов в ней (включая пробелы!), то всего их насчитаем ровно 15. Но не забываем, что заполнители веса не имеют, так как на их месте появляются вставляемые данные. Поэтому число ячеек равно не 15, а 13. Дабы ещё и удовлетворить потребности нуль-символа, выделим для него ещё одну ячейку и получим 14. Но и это ещё не всё. Раз мы решили вставлять ник игрока, то пора нам обратиться к официальной документации для SA-MP. Информацию можно поискать на официальном форуме или wiki-страничке, а можно открыть инклюды, что идут вместе с сервером и посмотреть там. В данном случае нам нужно узнать то, сколько ячеек в текущей версии мультиплеера, может занимать ник игрока. Что искать на форуме Вам, надеюсь, объяснять не нужно, а вот в инклюдах нужно искать всё то, что хоть как-то связано с именем игрока. Логично предположить, что макрос, содержащий информацию о максимальной длине ника, будет содержать слова "MAX" и "NAME", так что ищем среди макросов всё, что нам хоть как-то подходит. В данном случае нужный нам макрос хранится в инклюде "a_samp" и выглядит он так
        PHP код:
        #define MAX_PLAYER_NAME                            (24) 
        Скобки макросу нужны для максимальной совместимости с кодом, поэтому просто не обращаем на них внимания. Из макроса мы узнаём, что максимально возможная длина имени равна 24 символам. Так что к нашему числу ячеек (14) нужно прибавить 24 и именно это будет финальным размером нашего массива. В итоге получим следующее:
        PHP код:
        new string[38]; 
        Таким образом мы выделили ровно столько ячеек, сколько может использоваться в случае, когда у игрока длина ника равна 24 символам и такой массив можно назвать оптимизированным.
         Другие варианты записи размера ячеек:

        Запись
        PHP код:
        new string[38]; 
        Равносильна следующим записям:
        • PHP код:
          new string[14+MAX_PLAYER_NAME]; 
        • PHP код:
          new string[13+MAX_PLAYER_NAME+1]; 
        • PHP код:
          new string[14+24]; 
        • PHP код:
          new string[13+24+1]; 
        • PHP код:
          new string[(14)+(24)]; 
        • PHP код:
          new string[1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1]; 
        • И т.д.

        Все эти записи в итоге будут выглядеть как первая (new string[38];). Преобразование произойдёт в момент компиляции, так что о быстродействии заботиться не стоит :) Я лишь советую Вам использовать стандартные макросы, если они были даны разработчиками. Ибо тогда, если вдруг разработчики SA-MP, например, поменяют длину ника игрока, Вам будет достаточно перекомпилировать мод и жить дальше, а не уменьшать/увеличивать каждое значение вручную.


         Склейка строк
        Имеется три строки и три массива, которые хранят эти строки
        PHP код:
        new string_1[7] = "Привет";
        new 
        string_2[3] = ", ";//запятая + пробел + нуль-символ
        new string_3[6] = "игрок"
        Нам нужно все эти три строки склеить в одну. Воспользуемся функцией format. Выглядеть код будет так
        PHP код:
        format(string_allsizeof(string_all), "%s%s%s"string_1string_2string_3); 
        Как правильно подсчитать размер для массива "string_all"? Просто сложить размер трёх ячеек и всё? Нет, не верно. Ведь при создании массивов для хранения строк по отдельности мы учитывали наличие нуль-символа, который сигнализирует о конце строки. А это значит, что при склейке эти значения нам совсем не нужны, ведь какой нуль-символ может быть в середине строки? Для верного подсчёта строки нам потребуется просто высчитать настоящий размер строк (или просто отнять от текущего кол-ва ячеек массивов единицу) и уже после этого прибавить к ним единицу. В итоге у нас выйдет такой массив:
        PHP код:
        new string_all[14]; 


        После объявления массива мы сразу же запишем в него начало запроса, которое не требует вставки в себя каких-либо данных.


        PHP код:
        format(query_stringsizeof(query_string), "%s `player_name` = '%s'"query_stringpInfo[playerid][pName]);
        format(query_stringsizeof(query_string), "%s `password` = '%s'"query_stringpInfo[playerid][pPassword]); 
        Это сохранение имени игрока и пароля. "%s" в начале строки нужна для того, чтоб те данные, что уже имеются в query_string, поместились в начало строки и новые данные "приклеились" к ним. Вставка новых данных будет выглядеть так:
        PHP код:
        format(query_stringsizeof(query_string), "%s `имя_столбца` = 'заполнитель'"query_string/*переменная для вставки*/); 
        Только не забываем подсчитать длину этой строки и добавить нужное число ячеек к массиву :) А так же запомните, что новая запись должна иметь в самом конце запятую, если она не стоит последней.
         Пример
        PHP код:
        stock SaveAccount(playerid)
        {
            new 
        query_string[(21)+(15+11)+(20+MAX_PLAYER_NAME)+(16+30)+(22+11)+(19+11)] = "UPDATE `accounts` SET";

            
        format(query_stringsizeof(query_string), "%s `player_name` = '%s',"query_stringpInfo[playerid][pName]);//Запятая есть
            
        format(query_stringsizeof(query_string), "%s `password` = '%s',"query_stringpInfo[playerid][pPassword]);//Запятая есть
            
        format(query_stringsizeof(query_string), "%s `account_level` = '%d',"query_stringpInfo[playerid][pLevel]);//Запятая есть
            
        format(query_stringsizeof(query_string), "%s `admin_level` = '%d'"query_stringpInfo[playerid][pAdmin]);//Запятой нет

            
        format(query_stringsizeof(query_string), "%s WHERE `id` = '%d'"query_stringpInfo[playerid][pID]);//И тут нет
            
        mysql_tquery(mysql_connect_IDquery_string"""");
            return 
        1;

        В итоге выйдет следующий запрос:
        PHP код:
        UPDATE `accountsSET `player_name` = 'Имя_игрока', `password` = 'Пароль', `account_level` = 'Уровень игрока', `admin_level` = 'Уровень админки' WHERE `player_name` = 'Имя_игрока' 
        То есть, запятые отделяют друг от друга данные для сохранения и MySQL таким образом определяет где заканчивается информация для одного столбца и начинается для следующего. Именно поэтому к предпоследней строке (в данном случае это сохранение админки) запятая не ставится (кто не понял: если поставить запятую, то MySQL будет искать после неё следующий блок данных, но найдёт лишь оператор "WHERE". Из-за этого случится ошибка и запрос не обработается)

        И да, это не самый оптимизированный вариант (постоянный вызов функции format, вместо одного), но использование подобного метода не навредит Вашему моду. Я использовал именно его потому, что он максимально удачен в плане "оптимизация/понятность/удобство" и для новичков это самый лучший вариант.


        PHP код:
        format(query_stringsizeof(query_string), "%s WHERE `id` = '%d'"query_stringpInfo[playerid][pID]); 
        Окончание нашего запроса, где мы указываем, что нужный аккаунт нужно искать по ID. Новые данные на сохранение нужно помещать между этой строкой и объявлением массива. Желательно в том порядке, в котором расположены столбцы в таблице (для Вашего же удобства).


        PHP код:
        mysql_tquery(mysql_connect_IDquery_string""""); 
        Отправляем полученный запрос. Мы обновляем данные в базе данных и никаких данных в ответ не ждём, поэтому и кэширование нам не нужно => и функцию мы никакую не вызываем.

        И в OnPlayerDisconnect
        PHP код:
        SaveAccount(playerid); 



      8. Отключение от базы данных

        Так же нужно не забыть добавить запрос к плагину MySQL на отключение от нашей базы данных. Делается это просто.
        В OnGameModeExit
        PHP код:
        mysql_close(mysql_connect_ID); 



      9. Обнуление массива с данными
        Это действие требуется для того, чтоб данные одного игрока не перемешались с данными другого в случае, если один игрок вышел и второй зашёл на тот же слот.

        Делается это просто. Сначала в OnPlayerDisconnect, после "SaveAccount(playerid);" добавим:
        PHP код:
        RemovePlayerInfo(playerid); 
        А после в конец скрипта:
        PHP код:
        stock RemovePlayerInfo(playerid)
        {
            
        pInfo[playerid][pID] = 0;
            
        pInfo[playerid][pName][0] = EOS;
            
        pInfo[playerid][pPassword][0] = EOS;
            return 
        1;

         Разбор кода
        PHP код:
        pInfo[playerid][pName][0] = EOS
        Член pName в перечислении e_PLAYER_INFO является массивом (в нём мы храним текст). А так, как сервер обрабатывает строки до первого нуль-символа (о них я рассказывал выше), для обнуления такого массива достаточно самую первую ячейку приравнять к этому самому нуль-символу и тогда сервер посчитает, что строка пустая.
        Но что же такое "EOS"? "EOS", по-сути, в Pawn равнозначна нулю. То есть, мы спокойно могли записать
        PHP код:
        pInfo[playerid][pName][0] = 0;
        /*Не путать с 
        pInfo[playerid][pName][0] = '0';
        или
        pInfo[playerid][pName][0] = "0";
        В этих случаях мы приравниваем первую ячейку не к нулю, а к тому набору нулей и единиц (или же числу, если брать не двоичную систему счисления), которому нуль равен в кодировке "utf8_general_ci". А нам нужен именно нуль как целое число. Только тогда сервер поймёт, что массив пуст.*/ 
        и всё бы работало как надо. Так же эта запись идентична записи
        PHP код:
        pInfo[playerid][pName][0] = '\0'
        где "\0" обозначает нуль-символ.

        Поэтому если Вам нужно обновить строки, обновляйте их правильно. Переменные с вещественным типом данных следует обнулять как "0.0", ибо "девятый пункт рекомендаций"





      10. Проверка на авторизацию игрока
        Эта проверка может пригодится в случаях, когда нужно запретить игроку выполнять какие-либо действия пока он не авторизировался.

        В начало мода, к переменным, добавим следующий массив:
        PHP код:
        new player_is_authorized[MAX_PLAYERS char]; 
         Почему именно массив, а не pVar
        Причина одна - данные будут хранится и использоваться на протяжении всего времени, что игрок находится на сервере.
        Те же, кто использует pVar в подобных случаях, не очень понимает их предназначения. А логичнее всего их использовать для хранения временной информации, и вот почему:
        1) Многие считают, что при удалении pVar, память на сервере освобождается. Отнюдь, это не так. Скажу даже больше, если Вы не используете pVar, на сервере всё равно выделяется память под них. Ведь принцип работы pVar схож с принципами работы оперативной памяти. То есть, при запуске сервера резервируется определённое количество памяти. Теперь, когда вы создаёте pVar, часть этой памяти отдаётся под хранение записанных туда данных. Вот Вы попользовались этими данными и удалили pVar. Память, что требовалась для хранения Ваших данных, не стала вдруг свободной для всего. Она освободилась исключительно для нового pVar. Вы не сможете отдать участок памяти, где хранилась информация о pVar, под массив или что-то ещё. Нет. Она предназначена исключительно для pVar. Поэтому надеяться на какую-то оптимизацию в этом случае не стоит.

        2) Исходя из первого пункта следует, что глупо в pVar хранить информацию, которая будет востребована на протяжении всего нахождения игрока на сервере. Вот для временной информации pVar прекрасно подойдёт! Допустим, Вам нужно сохранить число, которое игрок ввёл как параметр для команды и вы сохранили его в pVar. Этот pVar занял свою ячейку в памяти (пусть это будет ячейка под номером 1). Далее Вы сохранили в pVar деньги игрока, дабы игрок смог через пол часа посмотреть то, насколько он смог разбогатеть (это уже будет pVar, который поместится в ячейку 2). Теперь Вы совершили все манипуляции с числом, что записывали в первый pVar и удалили его с помощью специальной функции DeletePVar. Пол часа ещё не прошло и второй pVar не задействован, поэтому удалять его мы не будем. Теперь нам понадобилось сохранить текущий уровень здоровья игрока. Мы создаём новый pVar и, по-идее, он должен занять ячейку под номером 3, ведь это совершенно новый pVar, который мы ещё не использовали ранее. Но нет, он займёт ячейку под номером 1, ведь до этого Вы удалили из неё pVar с числом.
        "Так всё равно же выделяется память, как и в случае с массивами!" - скажете Вы. Но вот Вам простой пример
         Пример

        PHP код:
        /* Ситуация:
        Нам нужно временно хранить данные для дальнейшего использования. Всего пусть будет 2 разных случая.*/
        //Вариант решения №1
        new array_1[MAX_PLAYERS];
        new 
        array_2[MAX_PLAYERS];
        //...
        array_2[playerid] = 1;
        if(
        array_2[playerid] == 1)...
        //...
        array_1[playerid] = 98;
        if(
        array_1[playerid] == 65)...

        //Вариант решения №2
        new array_1[MAX_PLAYERS];
        //...
        array_1[playerid] = 1;
        if(
        array_1[playerid] == 1)...
        //...
        array_1[playerid] = 98;
        if(
        array_1[playerid] == 65)...

        //Вариант решения №3
        SetPVarInt(playerid"Array_1"1);
        if(
        GetPVarInt(playerid"Array_1") == 1DeletePVar(playerid"Array_1");
        //...
        SetPVarInt(playerid"Array_2"98);
        if(
        GetPVarInt(playerid"Array_2") == 65DeletePVar(playerid"Array_2"); 

        В первом случае мы создаём 2 массива по 500 ячеек и они хранятся в памяти сервера всегда.
        Во втором случае мы создаём один массив на 500 ячеек и уже с ним работаем всё время. Это уже более похоже на pVar, но есть одно НО. Мы не сможем хранить в массиве одновременно несколько данных.
        В третьем случае мы используем pVar, где каждый pVar имеет своё уникальное имя и использует ту память, что уже и так была зарезервирована сервером. Если бы мы имели возможность сохранять в одном массиве несколько данных одновременно, то это было бы похоже именно на второй вариант.
        В общем, pVar хороши там, где данные не будут использоваться при каждом написании в чат или использовании команды (как это будет в случае с проверкой на авторизацию). Поэтому использовать их надо с умом.
         Постскриптум
        pVar можно представить следующим образом:
        PHP код:
        new player_variables_int[MAX_PLAYERS][30];
        new 
        player_variables_string[MAX_PLAYERS][30][500];
        new 
        Floatplayer_variables_float[MAX_PLAYERS][30]; 
        И уже имена pVar давать в виде макросов. То есть:
        PHP код:
        #define player_health 0
        player_variables_float[playerid][player_health] = 100.0
        Только вся разница в том, что в случае с pVar машина сама подсчитает для Вас то число ячеек, которое потребуется для хранения данных и выделить нужное количество данных из зарезервированного участка памяти, а не Вы это будете делать. Ну и зачем выделять столько памяти, когда это уже давно сделали за Вас? :)
        Надеюсь теперь люди осознают всю прелесть pVar и перестанут использовать их где ни попадя.


        А далее есть два варианта: либо использовать массив напрямую, либо сделать макрос-функцию, которую уже и использовать дальше. Я опишу оба варианта, а дальше выбирать только Вам :)
         Вариант первый: Использование макроса
        В начало мода, после перечислений, добавляем следующее:
        PHP код:
        //Макросы-функции
        #define IsPlayerAuthorized(%0)             player_is_authorized{%0}
        #define SetPlayerAuthorized(%0,%1)         player_is_authorized{%0} = %1

        //Макросы для удобства
        #define PLAYER_OFFLINE         0
        #define PLAYER_ONLINE         1 
        Теперь в UploadPlayerAccount/CreateNewAccount, перед SpawnPlayer, добавить
        PHP код:
        SetPlayerAuthorized(playeridPLAYER_ONLINE); 
        Всё. Теперь осталось добавить проверки.
        В OnPlayerText добавляем следующее:
        PHP код:
        if(!IsPlayerAuthorized(playerid))
        {
            
        SendClientMessage(playerid, -1"Вы не авторизировались и не можете писать в чат!");
            return 
        0;

         или же...
        PHP код:
        if(IsPlayerAuthorized(playerid) == PLAYER_OFFLINE)
        {
            
        SendClientMessage(playerid, -1"Вы не авторизировались и не можете писать в чат!");
            return 
        0;



        В начало OnPlayerCommandText
        PHP код:
        if(!IsPlayerAuthorized(playerid)) return SendClientMessage(playerid, -1"Вы не авторизировались и не можете использовать команды!"); 
         или же...
        PHP код:
        if(IsPlayerAuthorized(playerid) == PLAYER_OFFLINE) return SendClientMessage(playerid, -1"Вы не авторизировались и не можете использовать команды!"); 


        Всё :) Главное помните, что данные проверки должны находится всегда в самом начале коллбэков/функций. Иначе код, что стоит выше них, успеет выполнится для неавторизированного игрока

         Вариант второй: Прямое использование

        Теперь в UploadPlayerAccount/CreateNewAccount, перед SpawnPlayer, добавить
        PHP код:
        player_is_authorized{playerid} = 1
        Всё. Теперь осталось добавить проверки.
        В OnPlayerText добавляем следующее:
        PHP код:
        if(!player_is_authorized{playerid})
        {
            
        SendClientMessage(playerid, -1"Вы не авторизировались и не можете писать в чат!");
            return 
        0;

         или же...
        PHP код:
        if(player_is_authorized{playerid} == 0)
        {
            
        SendClientMessage(playerid, -1"Вы не авторизировались и не можете писать в чат!");
            return 
        0;



        В начало OnPlayerCommandText
        PHP код:
        if(!player_is_authorized{playerid}) return SendClientMessage(playerid, -1"Вы не авторизировались и не можете использовать команды!"); 
         или же...
        PHP код:
        if(player_is_authorized{playerid} == 0) return SendClientMessage(playerid, -1"Вы не авторизировались и не можете использовать команды!"); 


        Всё :) Главное помните, что данные проверки должны находится всегда в самом начале коллбэков/функций. Иначе код, что стоит выше них, успеет выполнится для неавторизированного игрока. И ID переменная, хранящая ID Игрока, должна находится не в квадратных скобках, а в фигурных.



    Если есть какие-либо вопросы, если что-то непонятно объяснено или есть какие-либо дополнения/исправления для данного урока, прошу написать об этом ниже. Всем постараюсь помочь, все мнения приму к сведению.
    С вами был DeimoS. Спасибо за внимание
    Автор урока - DeimoS
    Копирование данного материала запрещено без разрешения автора




    UPD: Исправление ошибок "Запуск программы невозможен, так как на компьютере отсутствует MSVCP***.dll. Попробуйте переустановить программу"

    Цитата Сообщение от Nurick Посмотреть сообщение
    Сообщение об ошибке Требуемый компонент
    MSVCP120.dll Microsoft Visual C++ 2013
    MSVCP110.dll Microsoft Visual C++ 2012
    MSVCP100.dll Microsoft Visual C++ 2010
    MSVCP90.dll Microsoft Visual C++ 2008
    MSVCP80.dll Microsoft Visual C++ 2005

    Microsoft Visual C++ 2013 Redistributable Package
    32 - bit
    64 - bit
    Microsoft Visual C++ 2012 Redistributable Package
    32 - bit
    64 - bit
    Microsoft Visual C++ 2010 Redistributable Package
    32 - bit
    64 - bit
    Microsoft Visual C++ 2008 Redistributable Package
    32 - bit
    64 - bit
    Microsoft Visual C++ 2005 Redistributable Package
    32 - bit
    64 - bit
    Цитата Сообщение от Osetin Посмотреть сообщение
    Готовый код регистрации (R39) на Pastebin: http://pastebin.com/QiymnrPK
    Готовый код регистрации (R40) на Pastebin: http://pastebin.com/BFDpSDtx



    Интересные статьи на подобную тему:
    * [Урок] О плагине MySQL R40 от pBlueG (описание нововведений/отличия от R39 и т.п.)
    Последний раз редактировалось DeimoS; 09.09.2016 в 18:50.

  2. 37 пользователя(ей) сказали cпасибо:
    #ball (15.06.2015)1136_man (27.07.2015)Anton Styazhkin (26.05.2015)ArtZet (16.08.2016)Astrakhan30 (05.06.2016)BadPawn (29.02.2016)Blood (23.02.2016)Camelot (29.06.2015)Daniel_Cortez (11.02.2016)Danny_Marcelo (03.11.2016)Dr_Watson (14.02.2016)Gabriel (12.05.2015)Geebrox (12.10.2016)HarrWe (26.07.2016)Ildars (13.10.2016)karevkhvdrift (09.09.2016)KrutoyKrosch (23.12.2016)kushichka (09.07.2016)Londlem (27.10.2016)Long- (30.12.2016)m1n1vv (13.10.2015)McLuhan (04.02.2016)MrJu[N]ior (09.03.2016)Mr_LemoneZ (30.12.2016)Nurick (05.08.2015)Osetin (24.10.2016)paik (24.07.2016)Processing (24.01.2016)Profyan (09.09.2016)Quman (08.08.2015)Redsan (08.06.2016)seriu (12.02.2016)vovandolg (23.10.2016)wAx (12.02.2016)[ForD] (24.01.2016)Иван Бубнов (26.12.2015)Тузик (08.09.2016)
  3. #2
    Аватар для Stats
    Пользователь

    Статус
    Оффлайн
    Регистрация
    01.09.2014
    Сообщений
    16
    Репутация:
    0 ±
    Прочитал чуть меньше половины, просто нет слов. Никогда не видел чтоб так подробно все описывали. Большое спасибо. Пошел читать далее и разбираться.

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

    Статус
    Оффлайн
    Регистрация
    19.04.2014
    Адрес
    Уфа, Россия
    Сообщений
    298
    Репутация:
    50 ±
    Правда устал читать, но это этого стоило! Много чего узнал, спасибо вам.

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

    Статус
    Оффлайн
    Регистрация
    20.01.2014
    Адрес
    Saint-Petersburg
    Сообщений
    89
    Репутация:
    33 ±
    Отличный мануал,все описано подробно :)

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

    Статус
    Оффлайн
    Регистрация
    31.01.2014
    Адрес
    Россия
    Сообщений
    213
    Репутация:
    1 ±
    При запуске мода, появляется вот такая ошибка. Все попробовал сделать, ничего не выходит. Ни установка, ни прописка в команде пуска.
    Подскажите что делать. Ошибка - Скриншот

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

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    3,138
    Репутация:
    1263 ±
    Цитата Сообщение от Skyline Посмотреть сообщение
    При запуске мода, появляется вот такая ошибка. Все попробовал сделать, ничего не выходит. Ни установка, ни прописка в команде пуска.
    Подскажите что делать. Ошибка - Скриншот
    У Вас не установлен распространяемый пакет Microsoft Visual C++. Ставить советую не самую последнюю, а начиная с 2005, ибо последующая версия не содержит компоненты предыдущей, а данный пакет может пригодится не только для работы MySQL.
    P.S. Если сейчас у Вас на компьютере установлена какая-то из версий сего пакета, удалите её и установите вручную последовательно каждую версию.
    И да, не выделяйте текст сообщения чёрным вручную. На форуме существует не только светный стиль, но и тёмный. И в нём текст Ваших сообщений читается очень плохо
    Связаться со мной можно в личных сообщениях этой группы

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

    Steve Pavlina

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

    Статус
    Оффлайн
    Регистрация
    19.04.2014
    Адрес
    Уфа, Россия
    Сообщений
    298
    Репутация:
    50 ±
    Сообщение об ошибке Требуемый компонент
    MSVCP120.dll Microsoft Visual C++ 2013
    MSVCP110.dll Microsoft Visual C++ 2012
    MSVCP100.dll Microsoft Visual C++ 2010
    MSVCP90.dll Microsoft Visual C++ 2008
    MSVCP80.dll Microsoft Visual C++ 2005

    Microsoft Visual C++ 2013 Redistributable Package
    32 - bit
    64 - bit
    Microsoft Visual C++ 2012 Redistributable Package
    32 - bit
    64 - bit
    Microsoft Visual C++ 2010 Redistributable Package
    32 - bit
    64 - bit
    Microsoft Visual C++ 2008 Redistributable Package
    32 - bit
    64 - bit
    Microsoft Visual C++ 2005 Redistributable Package
    32 - bit
    64 - bit
    Последний раз редактировалось Nurick; 12.05.2016 в 10:17.

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

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

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

    Статус
    Оффлайн
    Регистрация
    19.04.2014
    Адрес
    Уфа, Россия
    Сообщений
    298
    Репутация:
    50 ±
    "DeimoS" не могли бы объяснить какая разница между вашим посылаемым запросом либо если я буду посылать так:

    PHP код:
    forward OnPlayerDataLoaded(playerid); 
    PHP код:
    new connectionHandle;
    enum E_PLAYER
    {
        
    PlayerName[MAX_PLAYER_NAME]
    };
    new 
    PlayerInfo[MAX_PLAYERS][E_PLAYER]; 

    PHP код:
    connectionHandle mysql_connect("127.0.0.1""root""db_dayton""");
    if(
    mysql_errno() != 0)
            print(
    "Не удается подключиться к базе данных!"); 
    PHP код:
        new query[128];
        
    GetPlayerName(playeridPlayerInfo[playerid][PlayerName], MAX_PLAYER_NAME);
        
    mysql_format(connectionHandlequerysizeof(query), "SELECT * FROM `players` WHERE `username` = '%e'"PlayerInfo[playerid][PlayerName]);
        
    mysql_tquery(connectionHandlequery"OnPlayerDataLoaded""d"playerid); 
    PHP код:
    public OnPlayerDataLoaded(playerid)
    {
        
    /*...*/
        
    return 1;


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

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    3,138
    Репутация:
    1263 ±
    Если речь о mysql_tquery, то, если открыть инклюд MySQL, можно увидеть такой макрос:
    PHP код:
    #define mysql_function_query(%0,%1,%2,%3,"%4"%5)     mysql_tquery(%0,%1,%3,#%4%5) 
    То бишь, разницы никакой нет. Просто в mysql_function_query добавлен параметр кэширования, как я понимаю, для наглядности во время чтения кода (то бишь, чтоб можно было узнать о назначении запроса, не выискивая текст самого запроса). Я привык пользоваться этим макросом поэтому и использовал его. Описывать настоящую функцию не стал, ибо и так много информации сторонней в уроке.
    Ну а если что-то ещё интересует - прошу уточнить.
    Связаться со мной можно в личных сообщениях этой группы

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

    Steve Pavlina

  12. Пользователь сказал cпасибо:
    #enotya (21.08.2016)
 

 
Страница 1 из 26 12311 ... ПоследняяПоследняя

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

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

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

Ваши права

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