Пишем мод с нуля (MySQL R39-2 0.3z)

Описание: Уроки по скриптингу
Модератор: SJplayer

Layk M
Автор темы, Прапорщик
Прапорщик
Аватара
Layk M
Автор темы, Прапорщик
Прапорщик
Сообщения: 170
Зарегистрирован: 4 июня 2013
С нами: 10 лет 9 месяцев

#1 Layk » 17 марта 2015, 20:38

Глава I. Файлы, программы нужные нам

Для начала нам понадобится сам сервер. ( http://files.sa-mp.com/samp03z_svr_R1_win32.zip )
Распаковываем все содержимое архива в удобную нам папку.
Далее открываем файл server.cfg (блокнотом) и меняем нужные нам данные на свои, а именно:

Код: Выделить всё

echo Executing Server Config... 
lanmode 0 
// Не меняем! 
rcon_password changeme // Обязательно меняем, или сервер не запустится 
maxplayers 50 // Меняем на свое значение ( максимальное кол-во игроков, до 500 ) 
port 7777 // Порт ( по умолчанию 7777 ) 
hostname SA-MP 0.3 Server // Название сервера 
gamemode0 grandlarc 1 // Название мода, меняем на своё ( У нас это будет new.pwn, Значит меняем grandlarc на new ) 
filterscripts gl_actions gl_realtime gl_property gl_mapicon ls_mall attachments skinchanger vspawner // Удаляем: gl_actions gl_realtime gl_property gl_mapicon ls_mall attachments skinchanger vspawner 
announce 0 // Не меняем 
query 1 // Не меняем 
chatlogging 0 // Не меняем 
weburl www.sa-mp.com // Web-адресс сервера 
onfoot_rate 40 // Не меняем 
incar_rate 40 // Не меняем 
weapon_rate 40 // Не меняем 
stream_distance 300.0 // Не меняем 
stream_rate 1000 // Не меняем 
maxnpc 0 // Не меняем 
logtimeformat [%H:%M:%S] // Не меняем     


Поменяли? Но это ещё не все, приписываем ко всему строку:

Код: Выделить всё

plugins streamer mysql


- Это плагины, объясню позже
У нас получиться что-то вроде этого:

Код: Выделить всё

echo Executing Server Config... 
lanmode 0 
rcon_password 12345  
maxplayers 500 
port 7777 
hostname New RP 
| Client: 0.3x 
gamemode0 new 1 
filterscripts  
announce 0 
query 1 
chatlogging 0 
weburl www
. 
onfoot_rate 40 
incar_rate 40 
weapon_rate 40 
stream_distance 300.0 
stream_rate 1000 
maxnpc 0 
logtimeformat 
[%H:%M:%S] 
plugins streamer mysql


И так, если вы хотите чтобы ваш мод работал правильно, то вам следующие плагины:

Стример
1. Streamer.inc, который лежит в папке pawno/include закидываем к себе в папку pawno/include вашего сервера.
2. Streamer.dll, который лежит в папке plugins закидываем в папку plugins вашего сервера. Примечание: Если сервер находиться на оси Linux, то закидываем Streamer.so, в server.cfg все плагины должны быть написаны с расширением .so.
Например: Streamer.so
Ну все. Нам нужны только эти два файла.
MySQL R39-2 - Мы будем использовать плагин R39-2
1. a_mysql.inc закидываем к себе в папку pawno/include вашего сервера.
2. mysql.dll закидываем в папку plugins вашего сервера.
3. libmysql.dll обязательно кидаем в папку с сервером
Денвер - И самое главное, это Denwer (Denwer обеспечит нам Базу Данных MySQL PhpMyAdmin).
Устанавливаем Denwer. Думаю, вопросы по его установке не возникнут.

Глава II. Начинаем работу


И так, установили Denwer, закинули плагины? Тогда поехали.

Для начала заходим в папку своего сервера, видим там другую папку "pawno", заходим в неё. Далее заходим в саму программу pawno.exe Давайте начнем писать наш мод. Нажмем на самую первую иконку "New". Мы создали новый мод, если мы сохраним его под названием "new" в папку "gamemodes" запустим сервер и зайдем на него ( для захода используйте IP: 127.0.0.1 ), то увидим всем знакомого негра CJ в районе Лас Вентураса, как мы видим это ещё не совсем Role Play мод, так давайте его уже наконец начнем делать! Идем в pawno и начинаем работу. Для начала давайте впишем наши инклуды таким образом:
После строки:

Код: Выделить всё

#include <a_samp>     


Вставляем:

Код: Выделить всё

#include <streamer>
#include <a_mysql>    


Для начала давайте удалим ненужные нам строки:

Код: Выделить всё

#if defined FILTERSCRIPT 
 
public OnFilterScriptInit
() 
{ 
    print
("\n--------------------------------------"); 
    print
(" Blank Filterscript by your name here"); 
    print
("--------------------------------------\n"); 
    return 1
; 
} 
 
public OnFilterScriptExit
() 
{ 
    return 1
; 
} 
 
#else     


Далее заменим:

Код: Выделить всё

main() 
{ 
    print
("\n----------------------------------"); 
    print
(" Blank Gamemode by your name here"); 
    print
("----------------------------------\n"); 


На:

Код: Выделить всё

main()
{
    if(mysql_errno())
        printf(" Подключение к базе `%s` не успешно", mysql_db);
    else
        printf
(" Подключение к базе `%s` успешно", mysql_db);


Кстати немного о main().
Как вы видите функция print при запуске мода покажет нам текст в консоле который мы с вами ввели. Вы можете добавить ещё полей и написать в них что угодно. Так-же функция print служит для поиска багов в моде. Например у вас не работает функция, постепенно вставляйте print в код
Пример: (при проверке рекомендую использовать print)

Код: Выделить всё

stock Some_Function(playerid) 
{ 
    print
("Проверяем подключен ли игрок"); 
    if
(IsPlayerConnected(playerid)) // Если игрок подключен,то 
    { 
        printr
("Проверку прошли, ставим погоду"); 
        SetPlayerWeather
(playerid, 10);// Выводим ему погоду id 10 
        print("Паблик успешно выполнен"); 
    
}


Немного истории...
При написании мода используются различные символы и переменные, разберем их.

Код: Выделить всё

|| - это означает "или", пример PlayerInfo[playerid][pLeader] == 1 || PlayerInfo[playerid][pMember] == 1 ( Рабочий фракции 1 или лидер фракции 1) 
&& - это означает "и", пример PlayerInfo[playerid][pMember] == 1 && PlayerInfo[playerid][pRank] == 3 ( Рабочий фракции 1 и у него 3 ранг ) 
! - это означает "не", пример (!IsPlayerConnected) ( игрок не подключен ) 
if 
- это означает "если", пример  
if 
(!IsPlayerConnected) 
{ 
if PlayerInfo
[playerid][pMember] == 1 && PlayerInfo[playerid][pRank] == 3; и так далее 
else 
- это означает "иначе" , также бывает выражение "else if" - иначе если


Но вернемся к моду И так, удаляем строку:

Код: Выделить всё

#endif     


Удалили? Отлично, перейдем к разборке самого мода.

Давайте для начала пропишем данные к базе MySQL, для этого отступаем одну строку после инклудов и пишем следующее:

Код: Выделить всё

#define mysql_host "localhost" // если запускаем сервер у себя на компьютере, то оставляем 
#define mysql_db "samp" // имя базы данных mysql 
#define mysql_user "root" // пользователь Mysql 
#define mysql_pass "" // пароль от mysql     


Далее давайте отступим ещё одну строчку и вставим следующую строку:

Код: Выделить всё

new mysql_variable


Также отступаем одну строку и вставляем:

Код: Выделить всё

enum pInfo  
{  
    Key
[128],//переменная пароля  
    Level //уровень игрока 
};  
new PlayerInfo
[MAX_PLAYERS][pInfo]; 


Далее идем чуть ниже,в public OnGameModeInit() и вставляем туда следующее:

Код: Выделить всё

mysql_variable = mysql_connect(mysql_host, mysql_user, mysql_db, mysql_pass);
SetGameModeText("Register R39-2"); 


В итоге у нас получится такой паблик (public):

Код: Выделить всё

public OnGameModeInit()
{
    mysql_variable = mysql_connect(mysql_host, mysql_user, mysql_db, mysql_pass);
    SetGameModeText("Register R39-2");
    AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);
    return 1;


Далее таким же образом вставляем следующее в public OnGameModeExit():

Код: Выделить всё

mysql_close(mysql_variable); 


В public OnPlayerConnect(playerid):

Код: Выделить всё

static const
    str
[] = "SELECT `Name` FROM `Accounts` WHERE `Name` = '%s'";

const
    size = sizeof(str)-2+MAX_PLAYER_NAME;

new
    string[size];

mysql_real_escape_string(Name(playerid), Name(playerid));
format(string, sizeof(string), str, Name(playerid));
mysql_function_query(mysql_variable, string, true, "OnPlayerRegCheck", "d", playerid); 


В public OnPlayerText(playerid, text[]):

Код: Выделить всё

if(!GetPVarInt(playerid, "Logged"))
    return !SendClientMessage(playerid, -1, "Что бы писать в чат, нужно быть авторизированым."); 


В public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]):

Код: Выделить всё

switch(dialogid)
{
    case 1://Регистрация
    {
        if(inputtext[0] == '\0')
            return ShowPlayerDialog(playerid,1,DIALOG_STYLE_INPUT,"Регистрация","Добро пожаловать на сервер!\nВаш аккаунт не зарегистрирован!\n\nВведите пароль:","Далее","Отмена");
        OnPlayerRegister(playerid, inputtext);
        return 1;
    }
    case 2://Авторизация
        {
        if(inputtext[0] == '\0')
            return ShowPlayerDialog(playerid,2,DIALOG_STYLE_PASSWORD,"Авторизация","Здравствуйте!\n\nВы зарегистрированы!\nВведите пароль:","Вход","Отмена");
        OnPlayerLogin(playerid, inputtext);
        return 1;
    }


В самый конец кода:

Код: Выделить всё

stock OnPlayerRegister(p, password[])
{
       static const
        str
[] = "INSERT INTO `Accounts` (`Name`, `Key`) VALUES ('%s', '%s')";

    const
        size 
= sizeof(str)-2+MAX_PLAYER_NAME-2+128;
      
    new
        string
[size];
    
    format
(string, sizeof(string), str, Name(p), password);
    mysql_function_query(mysql_variable, string, false, "RegisterCallback", "d", p);
    return 1;
}
 
public RegisterCallback
(playerid);
public RegisterCallback(playerid)
{
    SendClientMessage(playerid, -1, "Вы успешно зарегистрировались!");
    SetPVarInt(playerid,"Logged", 1);
    SpawnPlayer(playerid);
    return 1;
}
 
SavePlayer
(p)
{
    if(GetPVarInt(p,"Logged") > 0)
    {
        static const
            str0
[] = "UPDATE `Accounts` SET `Key`, `Level` = '%d'",
            str1[] = "%s WHERE `Name` = '%s'";
        
        const
            size0 
= sizeof(str0)-2+128-2+16,
            size1 = sizeof(str1)-2+128-2+MAX_PLAYER_NAME;

        #if    size0>size1
            #define    size size0
        #else
            #define size size1
        #endif
        new
            string
[size];
        
        format
(string, sizeof(string), str0, PlayerInfo[p][Key], PlayerInfo[p][Level]);
        format(string, sizeof(string), str1, string, Name(p));
        mysql_query(mysql_variable, string, false);
    }
    return 1;
}
 
stock OnPlayerLogin
(i, password[])
{
       static const
        str
[] ="SELECT * FROM `Accounts` WHERE `Name` = '%s' AND `Key` = '%s'";

    const
        size 
= sizeof(str)-2+MAX_PLAYER_NAME-2+128;

    new
        string
[size];
    
    format
(string, sizeof(string),str, Name(i), password);
    mysql_function_query(mysql_variable, string, true, "LoginCallback", "ds", i, password);
    return 1;
}
 
public LoginCallback
(i, password[]);
public LoginCallback(i, password[])
{
    static const
        str
[] = "Вы ввели неверный пароль ( попыток: %i/ 3 )";
    
    new
        rows
,
        fields,
        maximum[128],
        string[sizeof(str)-2+1];
    
    cache_get_data
(rows, fields);
    if(!rows)
    {
        if(GetPVarInt(i, "wrongPass") == 2)
            return SendClientMessage(i, -1, "Вы ввели неверный пароль уже 3 раза. Вы кикнуты."), Kick(i);

        SetPVarInt(i, "wrongPass", GetPVarInt(i, "wrongPass") + 1);
        format(string, sizeof(string),str, 3 - GetPVarInt(i, "wrongPass"));
        ShowPlayerDialog(i, 2, DIALOG_STYLE_PASSWORD, "Авторизация", string, "Вход", "Выход");
        return 1;
    }
    cache_get_field_content(0, "Level", maximum), PlayerInfo[i][Level] = strval(maximum);
    SetPVarInt(i, "Logged", 1);
    SendClientMessage(i, -1, "Вы успешно авторизовались!");
    SpawnPlayer(i);
    SavePlayer(i);
    return 1;


Этим этапом мы с вами сделали регистрацию, и авторизацию на сервере. Спасибо Jeff_Hardy за данные коды по регистрации и авторизации.
Но это ещё не все, давайте запустим наш Denwer, далее в адресной строке наберем следующую ссылку: http://localhost/Tools/phpMyAdmin/
Создадим нашу Базу Данных samp и зайдем в неё, зайдя в неё мы с вами увидим сверху вкладочку "SQL" или "Структура", жмем на неё.
В появившемся поле мы вставим следующий код:

Код: Выделить всё

CREATE TABLE IF NOT EXISTS `Accounts`
(
  
    
`Name` varchar(24) COLLATE cp1251_bin NOT NULL,  
    
`Key` varchar(30) CHARACTER SET utf8 NOT NULL,  
    
`Level` int(3) NOT NULL  
)
ENGINE=MyISA


Все готово! Теперь мы можем скомпилировать мод (F5) и запустить его.
Автор: Pro-Pawn Team
Исходники: Мод
Изображение


Мэтью
Аватара
Мэтью

Спасибо

#2 Мэтью » 10 апреля 2018, 20:41

Спасибо огромное за урок, только осмелюсь поправить - это не создание мода самп с 0, а создание регистрации сервера самп с 0. Но все равно урок великолепный. Спасибо огромное. Жду следующих уроков. Если есть, то можно пожалуйста ссылку в личку?(https://vk.com/id326784145)


  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Уроки»

Кто сейчас на форуме (по активности за 5 минут)

Сейчас этот раздел просматривают: 6 гостей