MOP TTEX 144 Опубликовано 14 июля, 2018 Всем привет, с Вами @MOP TTEX. Сегодня я начинаю писать мод с нуля для форума.Пожалуйста, не пишите Ваши "спасибо/уже было/ниче нового не придумал?" - я буду все обновления скидывать сюда. Спасибо) Для начала создадим базу данных "server". В ней сделаем таблицу user.Содержимое: ID INT AUTO INCREMENT, Name VAR CHAR (24), Pass VAR CHAR (24), Skin INT, Sex INT. Теперь перейдем к самому моду.Создаем новый файл (CTRL + N) Кидаем это в начало: #include a_mysql #define MPN MAX_PLAYER_NAME//шоб дофига букв не писать #define SQL_HOST "localhost"//хост для бд #define SQL_USER "root"//логин бд #define SQL_DB "server"//имя бд #define SQL_PASS ""//пароль #define SERVER_NAME "CR-MP.RU RolePlay | All So Cool"// - для удобства название сервера в hostname #define SERVER_VERSION "0.0.1"// - для удобства версия сервера #define SERVER_MAP "Где-то в России..." // - для удобства карта сервера #define MP MAX_PLAYERS//шоб дофига букв не писать forward FindPlayer(i); forward LoadRegister(i); forward LoadLogin(i); forward Login(playerid); enum PDATE { pPass[64],//пароль pName[MPN],//имя pSex,//пол игрока pSkin,//Скин игрока }; enum { REG, REG1, REG2, LOG } new pDate[MAX_PLAYERS][PDATE];//массив с нашими данными аккаунта new mysql_connect_id;// переменная подключения к БД new PlayerLogged[MP];//проверка залогинился игрок или нет В OnGameModeInit mysql_connect_id = mysql_connect(SQL_HOST, SQL_USER, SQL_DB, SQL_PASS);//собственно подключение к бд SetGameModeText(SERVER_VERSION);//ставим версию в мультиплеере new string[8+2+20] = "hostname %s";//ставим название в мультиплеере format(string, 30, string, SERVER_NAME);//ставим версию в мультиплеере В OnGameModeExit mysql_close(mysql_connect_id); В OnPlayerRequestClass if(PlayerLogged[playerid]) return SpawnPlayer(playerid);//если нажал F4 - спавним В OnPlayerConnect GetPlayerName(playerid, pDate[playerid][pName], MPN);//узнаем имя сразу при подключении PlayerLogged[playerid] = 0;//ставим логин на 0, то есть он не залогинен new string[31+24+7+5] = "SELECT * FROM `user` WHERE `Name` = '%s'";//форматируем запрос << есть ли аккаунт с таким именем >> format(string, 68, string, pDate[playerid][pName]);//как и выше mysql_tquery(mysql_connect_id, string, "FindPlayer", "i", playerid);//собсна отправляем запросчег Создаем дополнительные паблики public Login(playerid) { new rows, fields; cache_get_data(rows, fields); if(!rows) { SendClientMessage(playerid, 0x33aa33aa, "Ошибка!"); Kick(playerid); return 1; } pDate[playerid][pSex] = cache_get_field_content_int(0, "Sex", mysql_connect_id); pDate[playerid][pSkin] = cache_get_field_content_int(0, "Skin", mysql_connect_id); PlayerLogged[playerid] = 1; SpawnPlayer(playerid); return 1; } stock SPS(playerid, man, woman) { switch(pDate[playerid][pSex]) { case 1: { pDate[playerid][pSkin] = man; SetPlayerSkin(playerid, man); } case 2: { pDate[playerid][pSkin] = woman; SetPlayerSkin(playerid, woman); } } return 1; } public FindPlayer(i) { new rows, fields; cache_get_data(rows, fields); if(!rows) { SetTimerEx("LoadRegister", 2500, false, "i", i);// если аккаунта нет - выводим регистрацию через 2.5 секунды (хз зачем :) ) return 1; } cache_get_field_content(0, "Pass", pDate[i][pPass], mysql_connect_id, 64);//унаем какой пароль SetTimerEx("LoadLogin", 2500, false, "i", i);//аккаунт есть - выводим логин return 1; } public LoadRegister(i) { ShowPlayerDialog(i, REG, DIALOG_STYLE_INPUT, "Регистрация", "\tДобро пожаловать на "SERVER_NAME"\n\n{33aa33}Ваш аккаунт не зарегистрирован...\nВведите свой пароль в окошко ниже:", ">>", ""); return 1; } public LoadLogin(i) { ShowPlayerDialog(i, LOG, DIALOG_STYLE_INPUT, "Авторизация", "\tДобро пожаловать на "SERVER_NAME"\n\n{33aa33}Ваш аккаунт зарегистрирован...\nВведите свой пароль в окошко ниже:", ">>", ""); return 1; } И наконец в OnDialogResponse new string[512];//по возможности можете увеличить switch(dialogid) { case REG: { if(!response) return Kick(playerid);//отказался? пшел вон! if(strlen(inputtext) < 6) return LoadRegister(playerid);//если меньше 6 символов format(pDate[playerid][pPass], (64), "%s", (inputtext)); ShowPlayerDialog(playerid, REG1, DIALOG_STYLE_LIST, "Выберите пол:", "- Мужской\n- Женский", ">>", ""); return 1; } case REG1: { if(!response) return Kick(playerid);//опять отказался? опять пшел вон :) ! pDate[playerid][pSex] = listitem+1;//устанавливаем пол SPS(playerid, 14, 13);//ставим скин PlayerLogged[playerid] = 1;//даем логин SpawnPlayer(playerid);//спавним format(string, 177, "INSERT INTO `user` (`Name`, `Pass`, `Sex`, `Skin`) VALUES ('%s', '%s', '%d', '%d')", pDate[playerid][pName], pDate[playerid][pPass], pDate[playerid][pSex], pDate[playerid][pSex]); mysql_tquery(mysql_connect_id, string);//добавляем аккаунт в БД return 1; } case LOG: { if(!response) return Kick(playerid);//отказался? пшел вон! if(strlen(inputtext) < 6) return LoadLogin(playerid);//если меньше 6 символов if(strcmp(pDate[playerid][pPass], (inputtext))) return LoadLogin(playerid);//если неверный format(string, 128, "SELECT * FROM `user` WHERE `Name` = '%s'", pDate[playerid][pName]); mysql_tquery(mysql_connect_id, string, "Login", "i", playerid); return 1; } } Все. К сожалению скриншотов нет - не у себя дома -> нет криминалки. Надеюсь, кому то пригодится)Автор: MOP TTEXУвидел, что в этом нуждается ChillyWilly, решил делать для всего форума) 7 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
noname_idk 150 Опубликовано 14 июля, 2018 //шоб дофига букв не писать Пройдет время (не месяц, не два, но хотя бы полгода), надумаешь этот мод доработать и напрочь забудешь свои сокращения вида MPN, MP, PSW, PSN и так далее. pDate Наверное, здесь должно было быть pData (данные), а не дата. в OnDialogResponse new string[512];//по возможности можете увеличить В таком случае ее лучше вынести на глобальный уровень (за пределы этой функции), либо сделать статической: static string[512]. 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
Vegas 91 Опубликовано 14 июля, 2018 @MOP TTEX,собсна мускул какой версии? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
noname_idk 150 Опубликовано 14 июля, 2018 @Vegas, R39. 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
#Rips 210 Опубликовано 14 июля, 2018 Не проверял на работу способность, но должно работать верно: [spoiler=Код] #include <a_mysql> new connects; // Переменная отвечающая за подключение к базе данных const server_name[] = "Criminal Russia MultiPlayer R{ (CR-MP.RU)"; enum pInfo { pID, pNames[MAX_PLAYER_NAME], pPassword[26], pSex, pChar } static PlayerInfo[MAX_PLAYERS][pInfo]; const DIALOG_REG = 1, // к DIALOG_REG будет прибавлять +1, то есть 1+1 = 2 и т.д.. DIALOG_LOGIN = 3; // Так же как и DIALOG_REG new PlayerLoginCheck[MAX_PLAYERS char], // Переменная отвечающая за авторизацию игрока PlayerRequestCheck[MAX_PLAYERS char]; // Переменная отвечающая за запрос(OnPlayerRequest) static const CharMan[] = {230, 154, 239}; // Мужские скины static const CharWoman[] = {3, 12, 11}; // Женские скины В паблик OnGameModeInit: connects = mysql_connect("Хостинг", "Пользователь", "База данных", "Пароль"); SetGameModeText("CR-MP.RU | Version 0.0.1"); // Данная функция будет уже прописана с названием мода Simple В паблик OnGameModeExit: mysql_close(connects); // Отключение с базы данных при отключение мода. В паблик OnPlayerRequestClass: if(!PlayerLoginCheck{playerid}) { PlayerRequestCheck{playerid} = 1; } SetSpawnInfo(playerid, 0, 3, 0.0, 0.0, 3.0, 0.0, -1, -1, -1, -1, -1, -1); SpawnPlayer(playerid); В паблик OnPlayerConnect: PlayerLoginCheck{playerid} = 0; // Обнуляем при подключение PlayerRequestCheck{playerid} = 0; // Обнуляем при подключение GetPlayerName(playerid, PlayerInfo[playerid][pNames], MAX_PLAYER_NAME); // Получаем игровой ник В паблик OnPlayerSpawn: if(PlayerRequestCheck{playerid}) { static const select_accounts[] = "SELECT * FROM `accounts` WHERE `pNames` = '%s'"; new string[sizeof(select_accounts)+(-2+MAX_PLAYER_NAME)]; // Подсчитываем количество ячеек (-2 берется под параметр(%s), + MAX_PLAYER_NAME (прибавляем 24 ячееки для ника) format(string, sizeof(string), select_accounts, PlayerInfo[playerid][pNames]); mysql_tquery(connects, string, "OnPlayerFindAccounts","i", playerid); // Проверяем зарегистрирован аккаунт или нет return 1; } if(!PlayerLoginCheck{playerid} || !IsPlayerConnected(playerid)) return SendClientMessage(playerid, -1, "Необходимо авторизоваться!"); Если, игрок нажал кнопку spawn, то его не респавним, а выдаем сообщение Создаем паблик с проверкой на аккаунт: forward OnPlayerFindAccounts(playerid); public OnPlayerFindAccounts(playerid) { if(cache_get_row_count()) { // Авторизация ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT, "Авторизация", "Добро пожаловать на Criminal Russia Role Play\n\nВаш аккаунт зарегистрирован", "Далее", "Отмена"); } else { // Регистрация ShowPlayerDialog(playerid, DIALOG_REG, DIALOG_STYLE_INPUT, "Регистрация", "Добро пожаловать на Criminal Russia Role Play\n\nВаш аккаунт не зарегистрирован", "Далее", "Отмена"); } return 1; } В паблик OnDialogResponse: switch(dialogid) { case DIALOG_REG: { if(!response) return Kick(playerid); // Если нажал кнопку 'Отмена', то кикаем if(!strlen(inputtext) || strlen(inputtext) < 6 || strlen(inputtext) > 26) return ShowPlayerDialog(playerid, DIALOG_REG, DIALOG_STYLE_INPUT, "Регистрация", "Добро пожаловать на Criminal Russia Role Play\n\nВаш аккаунт не зарегистрирован", "Далее", "Отмена"); for(new i = strlen(inputtext); i != 0; --i) switch(inputtext[i]) // Проверяем на русские символы { case 'А'..'Я','а'..'я': return ShowPlayerDialog(playerid, DIALOG_REG, DIALOG_STYLE_INPUT, "Регистрация", "Добро пожаловать на Criminal Russia Role Play\n\nВаш аккаунт не зарегистрирован", "Далее", "Отмена"); } strmid(PlayerInfo[playerid][pPassword], inputtext, 0, strlen(inputtext), 26); // Записываем пароль ShowPlayerDialog(playerid, DIALOG_REG+1, DIALOG_STYLE_MSGBOX, "Регистрация", "Выберите пол персонажа", "Мужской", "Женский"); // Показываем следующий диалог } case DIALOG_REG+1: { new rand = Random(3); if(!response) // Женский { CharMan[rand] = PlayerInfo[playerid][pChar]; } else // Мужской { CharWoman[rand] = PlayerInfo[playerid][pChar]; } SetPlayerSkin(playerid, PlayerInfo[playerid][pChar]); // Выдаем скин PlayerLoginCheck{playerid} = 1; // Ставим значение 1 то, что подключились к серверу PlayerRequestCheck{playerid} = 0; // Обнуляем то, что прошел запрос успешно static const mysql_create_accounts[] = "INSERT INTO `accounts` (`pNames`, `pPassword`, `pSex`, `pChar`) VALUES ('%s', '%s', '%d', '%d')"; new string[sizeof(mysql_create_accounts)+(-2+MAX_PLAYER_NAME)+(-2+26)+(-2+3)+(-2+5)]; format(string, sizeof(string), mysql_create_accounts, PlayerInfo[playerid][pNames], PlayerInfo[playerid][pPassword], PlayerInfo[playerid][pSex], PlayerInfo[playerid][pChar]); mysql_tquery(connects, string); SpawnPlayer(playerid); } case DIALOG_LOGIN: { if(!response) return Kick(playerid); if(!strlen(inputtext)) return ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT, "Авторизация", "Добро пожаловать на Criminal Russia Role Play\n\nВаш аккаунт зарегистрирован", "Далее", "Отмена"); OnPlayerLoadingAccounts(playerid, inputtext); // Делаем запрос на верность пароля } } Создаем сток на запрос верности пароля: stock OnPlayerLoadingAccounts(playerid) { mysql_format(connects, string, sizeof(string),"SELECT * FROM `accounts` WHERE `pNames` = '%s' AND `pKey` = '%s'", PlayerInfo[playerid][pNames], password); mysql_function_query(connects, string, true, "OnPlayerCheckLogin","ds", playerid, password); return 1; } Создаем паблик с загрузкой аккаунта: forward OnPlayerCheckLogin(playerid); public OnPlayerLoadingAccounts(playerid) { new rows[2]; cache_get_data(rows[0], rows[1]); if(!rows[0]) return ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT, "Авторизация", "Добро пожаловать на Criminal Russia Role Play\n\nВаш аккаунт зарегистрирован", "Далее", "Отмена"); PlayerInfo[playerid][pID] = cache_get_field_content_int(0, "pID"); cache_get_field_content(0, "pPassword", PlayerInfo[playerid][pPassword], connects, 26); PlayerInfo[playerid][pChar] = cache_get_field_content_int(0, "pChar"); PlayerInfo[playerid][pSex] = cache_get_field_content_int(0, "pSex"); return 1; } 2 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
noname_idk 150 Опубликовано 16 июля, 2018 const server_name[] = "Criminal Russia MultiPlayer R{ (CR-MP.RU)"; Так только с числами будет работать. Не хватает оператора new или static (лучше static). Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
#Rips 210 Опубликовано 16 июля, 2018 , писал на быструю руку, и не заметил ошибки Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
MOP TTEX 144 Опубликовано 15 октября, 2018 Стоит ли делать продолжение? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
#meow 64 Опубликовано 29 октября, 2018 @MOP TTEX, Да, почему нет? Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
olegp 12 Опубликовано 14 ноября, 2018 Никакого "урока" здесь нет. Набор кода не первого сорта. Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
fromua 0 Опубликовано 1 января, 2019 А где брать начало мода? папку и плагинны Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
MOP TTEX 144 Опубликовано 1 января, 2019 @fromua, http://cr-mp.ru/forum/topic/17068-crmp-rev-c3-windows-server-03e/ 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты
failed 14 Опубликовано 3 января, 2019 (изменено) Делай продолжение Изменено 3 января, 2019 пользователем Nikiyp 1 Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты