• Страница 1 из 1
  • 1
Система регистрации на основе SQLite
Дмитрий Дата: Вторник, 30.09.2014, 20:49 | Сообщение # 1 | Сообщить о нерабочей теме


Аватар для Дмитрий

Добрый день пользователи портала!

Все чаще я стал замечать, что люди пытаются смастерить что-либо на SQLite, но чаще всего это оборачивается крашами, выходами за пределы массивов, левыми запросами и прочей фигней, способствующей поломке сервера.

Сам по себе SQLite (a_sampdb) уже встроен в сервер и не требует никаких манипуляций с плагинами, инклудами и прочими конструкторами.

Для тех, что считает, что SQLite медленная и для сервера она приносит больше вреда, чем пользы - обломитесь, если написать правильно код - все будет работать идеально и без сбоев

Перед использованием SQLite советую почитать мануалы от OFFREAL'a и полазить в википедии, дабы понять как и что устроено.

Пример использования SQLite я покажу на простенькой регистрации, написанной за 10 минут

В начало вашего мода нужно добавить пару переменных и один дефайн:
Код
new DB: users_base;
new DBResult: u_result;

#define database "users.db"  


Переменные DB и DBResult отвечают за саму базу данных и за результат отправки запроса соответственно.
users.db - местоположение вашей базы в папке scriptfiles

Далее перейдем в OnGameModeInit
Код
if(!fexist(database)){//если БД отсутствует
         users_base = db_open(database);//функция 'db_open(base[])' при отсутствии нужной нам базы данных создает пустую БД
         db_query(users_base,"CREATE TABLE USERS(NAME varchar, PASSWORD varchar, MONEY int, KILLS int)");//ну и как итог - заполним базу данных со столбцами "Name, Password, Money, Kills"
     }
     else{//если БД присутствует
         users_base = db_open(database);//тупо откроем ее
     }  


Или же использовать такой метод, кому как удобней
Код
        users_base = db_open(database);//функция 'db_open(base[])' при отсутствии нужной нам базы данных создает пустую БД
         db_query(users_base,"CREATE TABLE IF NOT EXISTS USERS(NAME varchar, PASSWORD varchar, MONEY int, KILLS int)");//Если в БД нет таблицы USERS - заполним базу данных со столбцами "Name, Password, Money, Kills"  


Тут я полагаю всем все понятно, проверяем на существование и открываем или создаем в зависимости от условия

OnGameModeExit в данном уроке смысла юзать нету, т.к. на люниксе при краше сервера данный каллбэк неработает, но для примера -
Код
    for(new i;i!=GetMaxPlayers();i++){
         if(IsPlayerConnected(i) && GetPVarInt(i,"logged") == 1 && !IsPlayerNPC(i)){//на сервере, в системе, и не бот
             save_user(i);//сохраним
         }
     }
     db_close(users_base);//при окончании работы сервера - закроем базу данных


Теперь перейдем непосредственно к выдаче диалога игроку при его подключении на сервер

OnPlayerConnect:
Код
new str[500];
     format(str,sizeof str,"SELECT NAME, PASSWORD FROM USERS WHERE NAME = '%s'",p_name(playerid));//отправим запрос в таблицу на поиск нужного нам игрока
     u_result = db_query(users_base,str);
     if(!db_num_rows(u_result)){//если строки по нужному нам запросы отсутствуют в таблице - значит игрок незарегестрирован на сервере
         ShowPlayerDialog(playerid, 0, DIALOG_STYLE_INPUT, "  ","Зарегестрируйтесь","Вход","Кик");
     }
     else{//нужная нам строка присутствует
         ShowPlayerDialog(playerid, 1, DIALOG_STYLE_INPUT, "  ","Войдите в систему","Вход","Кик");
     }  


Тут я полагаю тоже все понятно, отправили запрос, получили результат, если строк нету - игрока в базе соответственно нету
Код
p_name(playerid){
     new name[24];
     GetPlayerName(playerid,name,24);
     return name;
}  


Это нужно засунуть в конец мода(функция определения имени игрока), у кого есть - настроите сами

При выходе игрока нам требуется сохранить его личные данные
OnPlayerDisconnect
Код
if(GetPVarInt(playerid,"logged") == 1) save_user(playerid);//при выходе игрока - сохраним его, при условии, что он уже вошел в систему  


И в конец мода -
Код
save_user(userid){
     new str[500];
     format(str,500,"UPDATE USERS SET MONEY = '%d', KILLS = '%d' WHERE NAME = '%s'",GetPlayerMoney(userid),GetPlayerScore(userid),p_name(userid));
     db_query(users_base, str);//обновим значения денег и убийств в базе для игрока %s
}  


Здесь мы обновили данные игрока в базе данных при выходе

Для запрета использования команды, или если игрок решит воспользоваться чатом, при этом ненаходясь в системеиспользуем этот код

OnPlayerCommandText & OnPlayerText
Код
if(GetPVarInt(playerid,"logged") == 0) return false;  


Теперь перейдем непосредственно к диалогам
В OnDialogResponse
Код
  if(dialogid == 0){
         if(!response) return Kick(playerid);//если игрок нажал 'ESC' или нажал на вторую кнопку - пошлем его к чертям
         if(!valid_password(inputtext)){//если введен некорректный пароль
             return ShowPlayerDialog(playerid, 0, DIALOG_STYLE_INPUT, "  ","Зарегестрируйтесь","Вход","Кик");
         }
         new str[500];
         format(str,500,"INSERT INTO `USERS` (`NAME`, `PASSWORD`, `MONEY`, `KILLS`) VALUES ('%s', '%s', '0', '0')", p_name(playerid), inputtext);
         db_query(users_base, str);//добавим игрока в таблицу ко всем бабушкам
         SetPVarInt(playerid,"logged",1);//установим пивоварку на 1, т.е. игрок вошел в систему
         SendClientMessage(playerid,-1,"Вы успешно зарегестрировались на сервере!");
         return true;
     }
     if(dialogid == 1){
         if(!response) return Kick(playerid);//если игрок нажал 'ESC' или нажал на вторую кнопку - пошлем его к чертям
         if(!valid_password(inputtext)){//если введен некорректный пароль
             return ShowPlayerDialog(playerid, 1, DIALOG_STYLE_INPUT, "  ","Войдите в систему","Вход","Кик");
         }
         new str[500];
         format(str,500,"SELECT * FROM USERS WHERE NAME = '%s'",p_name(playerid));
         u_result = db_query(users_base, str);
          
         new Field[100];
         db_get_field_assoc( u_result, "PASSWORD", Field, sizeof( Field ) );//запишем пароль из строки в переменную Field

         if(strcmp(Field, inputtext, true) == 0){//если пароли совпали
             db_get_field_assoc( u_result, "MONEY", Field, sizeof( Field ) ), GivePlayerMoney(playerid, strval(Field));
             db_get_field_assoc( u_result, "KILLS", Field, sizeof( Field ) ), SetPlayerScore(playerid, strval(Field));
             SetPVarInt(playerid,"logged",1);//установим пивоварку на 1, т.е. игрок вошел в систему
             SendClientMessage(playerid,-1,"Вы успешно вернулись в систему!");
         }
         else ShowPlayerDialog(playerid, 1, DIALOG_STYLE_INPUT, "  ","Войдите в систему","Вход","Кик");
         return true;
     }


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

Есть еще одна функция для получения значений через ID столбика, тут уже кому как удобнее
Лично я привык через название столбца

http://wiki.sa-mp.com/wiki/Db_get_field_assoc
http://wiki.sa-mp.com/wiki/Db_get_field

Ну и финал - в конец мода добавим функцию для проверки пароля
Код
valid_password(password[]){
     if(!strlen(password)) return false;//пароль тупо пустой
     for(new i;i!=strlen(password);i++){
         switch(password[i]){
             case 'a'..'z','A'..'Z','0'..'9': continue;//допустимые символы: английская расскладка и цифры
             default: return false;//во всех остальных случаях пароль некорректный
         }
     }
     return true;
}


Тут я полагаю тоже все понятно
Вот и все! Для того, чтобы открыть таблицу, используйте программу SQLite Database Browser
Автор урока - Seregamil


From Russia With Love!
  • Страница 1 из 1
  • 1
Поиск: