Перейти к содержанию
Авторизация  
#Rips

Система регистрации и авторизации [MYSQL R39-2]

Рекомендуемые сообщения

Alex_Dredd

Жаль лимит лайков исчерпал  :D83DDE25:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
#Rips

Вот и продолжение "Системы регистрации и авторизации на MYSQL"

Теперь, нам нужно скачать DenWer или же OpenServer, я буду использовать DenWer так как он мне привычен

 

Официальный сайт DenWer'a, где Вы можете скачать сам DenWer: Перейти

Официальный сайт OpenServer'a, где Вы можете скачать сам OpenServer: Отсутствует  | P.s Найду данный сайт и добавлю его

 

На YouTube много уроков по установке Локального Сервера.

 

Когда, мы установили DenWer нам необходимо запустить денвер, нажмите по Иконке Start Denwer и ждите, когда он включиться. Когда, он включился заходим в браузер и URL поиске вводим: localhost/tools/phpmyadmin, когда Вы перешли нам нужно создать базу, а дальше смотрите по скриншотам, которые будет в спойлере

1.

EsKeqTu.png

2.

GhGoOGd.png

 

 

Теперь, когда создали таблицу на Локальном сервере нам нужно сделать Enum в моде, где будут записываться данные будущего аккаунта.

 

Данный Enum после переменной connects, в данном Enum'e нам понадобиться тока, pID, pName[MAX_PLAYER_NAME], pKey[21], pLVL, pSex, pChar, pCash

pID - Номер игрового аккаунта, который будет автоматически создаваться в базе данных
pName[MAX_PLAYER_NAME] - Игровой ник, который будем записывать в MYSQL запросе на создание аккаунта
pKey[21] - Пароль от игрового аккаунта
pLVL - Уровень будущего игрового аккаунта, который зададим при регистрации аккаунта
pSex - Пол игрового аккаунта(персонажа)
pChar - Одежда персонажа(SKIN ID), в данную переменную Enum'a запишем ID скина, который будет носить персонаж
pCash - Игровая валюта, которую имеет персонаж

Данный Enum будет выглядеть именно вот так:

enum PInfo
{
	pID, pName[MAX_PLAYER_NAME],
	pKey[24], pEmail[42], pLVL, pSex, pChar, pCash
}
new PlayerInfo[MAX_PLAYERS][PInfo];

Данный Enum будет для каждого нового игрока, для этого Мы и используем MAX_PLAYERS.

 

Когда, создали Enum PlayerInfo нам нужно перейти в public OnPlayerConnect(playerid).

 

В данном паблике объявляем переменную с определенном количество ячейк. Все спросят как ее объявить? Мы сделаем данную переменную локальную к данному public'y.

new string[100];

Теперь нужно нам определить игровой ник игрока, с которого заходит игрок для этого воспользуемся функцией GetPlayerName. В которой параметры: playerid, const name[], len

playerid - ID игрока, имя которого Вы хотите узнать.
const name[] - Строка для хранения полученного имени, передаётся по ссылке.
len - Количество копируемых в name символов. Рекомендуется использовать 'MAX_PLAYER_NAME'.

Мы объявим ее вот так:

GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);

На данный момент у Вас должно выглядеть именно вот так:

new string[100];
GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);

Теперь нужно создать с помощью format запрос:

Подробную информацию о данной функции можете посмотреть на wiki.sa-mp.com: Перейти

format(string, sizeof(string),"SELECT `pLVL` FROM `accounts` WHERE `pName` = '%s'", PlayerInfo[playerid][pName]);
mysql_function_query(connects, string, true, "OnPlayerRegCheck", "d", playerid);

Параметры mysql_function_query, а точнее натив:

native mysql_tquery(connectionHandle, query[], callback[] = "", format[] = "", {Float,_}:...);

connectionHandle - Подключение к базе данных

query - Строка для хранения полученного имени, передаётся по ссылке P.s Точно не могу объяснить что данный query делает, просто забыл :c

callback[] - Паблик в, котором будет все происходить

format[] - Отсутствует. Если появиться информация, то она будет добавлена

{float, _}:... - Отсутствует. Если появиться информация, то она будет добавлена 

 

Теперь после инклудов(include) создадим макросы, которые будут использоваться в дальнейшем уроке.

#define     publics%0(%1)	forward%0(%1); public%0(%1)
#define     SPD         ShowPlayerDialog
#define     SCM 	SendClientMessage

Данный макрос убирает forward и public, теперь мы можем использовать тока publics, который мы создали.

 

Теперь мы должны создать publics, в котором будут показываться диалоги регистрации и авторизации.

Данный publics Вы можете создать после переменных и enum'oв или же в конце мода перед stock'aми.

 

Я буду писать данный publics перед stock'ами

publics OnPlayerRegCheck(playerid)
{
     new rows[2]; - Данная переменная будет определять имеется ли аккаунта в базе данных или нет
     cache_get_data(rows[0], rows[1]);
     if(rows[0]) // Авторизация
     {
     }
     else // Регистрация
     {
     }
     return 1;
}

Завтра будет продолжение написание "Системы регистрации и авторизации на MYSQL"

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
#Rips

Вот и продолжение "Системы регистрации и авторизации на MYSQL" #3

Мы остановили на том, что сделали publics где будут показывать диалоги регистрации и авторизации.

Нам в данном publics, понадобиться сейчас тока проверка в else. Нам нужно выводить диалог где будет написано о регистрации.

В else { 'Именно внутри этой проверки' } нам нужно прописать 

SPD(playerid, 1, DIALOG_STYLE_INPUT, "Регистрация", "{FFFFFF}Привет, дорогой друг!\nТы зашел на сервер, тебе нужно зарегистрироваться!", "Далее", "Отмена");

SPD - Это макрос, который мы делали в позапрошлом посту. Параметры ShowPlayerDialog:

(playerid, dialogid, style, caption[], info[], button1[], button2[])

playerid	ID игрока, которому будет показан диалог.
dialogid	Уникальный ID диалога. Используется в OnDialogResponse. При значении, равном -1, любой текущий диалог будет скрыт с экрана игрока.
style	        Стиль диалогового окна.
caption[]	Заголовок окна.
info[]	        Текст самого диалога. Можно использовать \n для перевода строки и \t для табуляции.
button1[]	Название первой (левой) кнопки диалога.
button2[]	Название второй (правой) кнопки.


Возвращаемые значения:
1: Функция успешно выполнена.
0: Функции не удалось выполниться. Игрок не подключен.

Вид диалогов можете узнать на официальном сайта SA-MP'a: Перейти на wiki.sa-mp.com

В данный момент будет выглядеть вот так:

publics OnPlayerRegCheck(playerid)
{
    new rows[2]; - Данная переменная будет определять имеется ли аккаунта в базе данных или нет
    cache_get_data(rows[0], rows[1]);
    if(rows[0]) // Авторизация
    {
    }
    else // Регистрация
    {
         SPD(playerid, 1, DIALOG_STYLE_INPUT, "Регистрация", "{FFFFFF}Привет, дорогой друг!\nТы зашел на сервер, тебе нужно зарегистрироваться!", "Далее", "Отмена");
    }
    return 1;
}

Теперь нам нужно перейти в public OnDialogResponse

В данном publics должны прописать switch(dialogid)

 

Оператор

switch – это оператор выбора. Он удобен в первую очередь тем, что может заменить много условий if, которые проверяют значение одной переменной. Представим себе такой пример. У нас есть
целочисленная переменная pawn, значение которой нужно проверить. И в зависимости от того, какое значение у данной переменной выполнить соответствующий код.
new pawn;
switch(samp)
{
case 0: //аналог условия if(samp == 0)
{
print(”Переменная samp = 0”);
}
case 1: //аналог условия if(samp == 1)
{
print(”Переменная samp = 1”);
}
} 

Обратите внимание, если в фигурных скобках указано одно действие, его можно упростить так же как в случае с обычной условной конструкцией.

Но, что если переменная не попадает ни под одно условие в операторе switch. Тогда можно использовать default, он выполняется только в том случае, если switch не попадает ни в один из case.

new pawn;
switch(samp)
{
case 0: printf(”Переменная samp = 0”);
case 1: printf(”Переменная samp = 1” );
default: printf(”Переменная samp = %d” , samp);
}  

То же самое можно сделать и с помощью обычной условной конструкции if, тогда код выглядел бы следующим образом:

if(samp == 0)
{
printf(”Переменная samp = 0”); //все равно что case 0
}
else if(samp == 1)
{
printf(”Переменная samp = 1”); //все равно что case 1
}
else
{
printf(”Переменная samp = %d” , samp); //все равно что default
} 

Этот способ удобнее и читабельнее чем много if конструкций идущих подряд. Еще одно отличие, что в case можно указать диапазон значений куда проще, чем в обычной условной конструкции if.

case 0..2: printf(”Переменная samp = %d” , samp); //условие внутри switch
if(samp > 0 && samp < 2) printf(”Переменная samp = %d” , samp); //то же условие, но уже в if 

Для закрепления знаний по данному урока продемонстрирую вам один из примеров использования данного оператора в функции OnPlayerDisconnect. В данной функции параметр reason возвращает ID причины отключения игрока от сервера. Благодаря этому параметру можно сделать вот такой код оповещения игроков об уходе игрока с сервера с пояснением причины.
 

switch(reason)
{
case 0:
{
GetPlayerName(playerid,plname,24);
format(string,sizeof(string), "*** %s вылетел с сервера.(ID:%d)",plname,playerid);
SendClientMessageToAll(0xAA3333AA,string);
}
case 1:
{
GetPlayerName(playerid,plname,24);
format(string,sizeof(string), "*** %s покинул сервер.(ID:%d)",plname,playerid);
SendClientMessageToAll(0xAA3333AA,string);
}
case 2:
{
GetPlayerName(playerid,plname,24);
format(string,sizeof(string), "*** %s был кикнут.(ID:%d)",plname,playerid);
SendClientMessageToAll(0xAA3333AA,string);
}
} 

Этот пример можно упростить с помощью вот такой stock функции.

stock GetName(playerid)
{
new nick[MAX_PLAYER_NAME];
GetPlayerName(playerid, nick, sizeof(nick));
return nick;
} 

В этом случае функцию GetPlayerName можно просто убрать из switch, а вместо переменной plname подставить вызов данной функции. Саму переменную plname также нужно удалить.

Автор данной информации: Cloud

 

 

 

Когда, мы прописали switch(dialogid) он должен выглядеть именно вот так:

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    switch(dialogid)
    {
    }
    return 1;
}

Теперь нужно прописать номер нашего диалога:

Внутри switch(dialogid) должны прописать вот так:

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    switch(dialogid)
    {
         case 1:
         {
         }
    }
    return 1;
}

В данном case 1, Мы должны сделать проверки на нажатие первой кнопки, пустое поле, на определенное количество символов и на русские символы

Данный код будет выглядеть вот так:

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
	switch(dialogid)
	{
	    case 1:
	    {
	        if(response)
	        {
	                        if(!strlen(inputtext)) return SPD(playerid, 1, DIALOG_STYLE_INPUT, "Регистрация", "{FFFFFF}Привет, дорогой друг!\nТы зашел на сервер, тебе нужно зарегистрироваться!", "Далее", "Отмена");
                                // В данной проверки мы проверяем на, то, что пустое поле или нет. Если данное поле пустое то возвращаем ему диалог
				if(strlen(inputtext) < 6 || strlen(inputtext) > 24)
				{
					SPD(playerid, 1, DIALOG_STYLE_INPUT, "Регистрация", "{FFFFFF}Привет, дорогой друг!\nТы зашел на сервер, тебе нужно зарегистрироваться!", "Далее", "Отмена");
	    			        return SCM(playerid, -1, "Пароль должен не меньше 6 и более 24 символов.");
				}
                                // В данной проверки если у игрока меньше 6 и больше 24 символов в пароле, то мы возвращаем диалог и выдаем сообщения
				for(new i = strlen(inputtext); i != 0; --i)
				switch(inputtext[i])
				{
					case 'А'..'Я', 'а'..'я', '=', ' ':
					{
					    SPD(playerid, 1, DIALOG_STYLE_INPUT, "Регистрация", "{FFFFFF}Привет, дорогой друг!\nТы зашел на сервер, тебе нужно зарегистрироваться!", "Далее", "Отмена");
	    				    return SCM(playerid, -1, "Пароль не должен состоять из русских символов.");
					}
				}
                                // В данной проверки мы сообщаем о том, что у данного игрока в пароле не может быть Русских Символов и других знаком, если они допущены то мы возвращаем диалог и выдаем сообщение
				strmid(PlayerInfo[playerid][pKey], inputtext, 0, strlen(inputtext), 24); // В данной функции мы записываем пароль будущего аккаунта
				SPD(playerid, 2, DIALOG_STYLE_INPUT, "Электронная почта", "Пожалуйста введите действующий электронный адрес,\nесли вы забудете пароль на него будет выслан новый пароль", "Далее", "Отмена"); // После записи пароля Мы показываем след. диалог
			}
			else { SCM(playerid, -1, "Вы были кикнуты серверов. Чтобы выйти из игры, введите /q (/quit)"); Kick(playerid); }
		}
	}
	return 1;
}

Продолжение будет в течение 2-4 часов.

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
noname_idk

strmid(PlayerInfo[playerid][pKey], inputtext, 0, strlen(inputtext), 24);

strins гораздо удобнее в данном случае.

 

else { SCM(playerid, -1, "Вы были кикнуты серверов. Чтобы выйти из игры, введите /q (/quit)"); Kick(playerid); }

Кто Вас научил весь код писать в одну строку?

 

А так плюс за старания... Быть может и не Вы автор, но кому-нибудь будет полезно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Na'Vi

Хороший урок

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Miron_Moraev

Хороший урок. Но, таких регистраций/авторизаций пруд пруди. Если хочешь можешь сделать на ОРМ запросах, будет полезней.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Web

ORM не нужен. То что выше, вырезано. Можно сделать и лучше. Лучший мануал по созданию авторизации и регистрации в сети от Деймоса. Возможно ее сюда уже выкладывали. Ну и врятли бы он разрешил ее сюда выложить.

Изменено пользователем Wеb

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
#Rips

,на счет функции благодарю, а на счет второго я че не много ступил, когда это писал 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Bakston

А где продолжение!?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
noname_idk

@Bakston, а что тебе еще надо? Вообще, уже давно есть более новые версии MySQL с примерами реализации на них системы регистрации. Эти примеры непосредственно от автора библиотеки MySQL для серверов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Bakston

, да я пытаюсь начать нулячий мод (учусь только)! В принципе в логах, по этому примеру, подключение идёт, но с одной поправочкой

Если убрать:

native mysql_tquery(connectionHandle, query[], callback[] = "", format[] = "", {Float,_}:...); 

то при компиляции проблем нет!

Если добавить строку Pawno ругается

error 029: invalid expression, assumed zero
error 017: undefined symbol "connectionHandle"
warning 215: expression has no effect
error 028: invalid subscript (not an array or too many subscripts): "format"
fatal error 107: too many error messages on one line

Может поэтому, когда захожу на сервер, окна регистрации/авторизации нет!? И сервер постоянно перезапускается!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
noname_idk

@Bakston, скинь-ка весь include a_mysql. Вообще такого быть не должно. Скорее всего кто-то лез в файл a_mysql (чего делать не рекомендуется, в будущем будут проблемы).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Bakston

, вот:

/**
 * MySQL plugin R39-2
 */


#if defined mysql_included
	#endinput
#endif
#define mysql_included


/**
 * Common error codes
 *
 * Client: http://dev.mysql.com/doc/refman/5.1/en/error-messages-client.html
 * Server: http://dev.mysql.com/doc/refman/5.1/en/error-messages-server.html
 */

#define ER_DBACCESS_DENIED_ERROR 		1044
#define ER_ACCESS_DENIED_ERROR 			1045
#define ER_UNKNOWN_TABLE 				1109
#define ER_SYNTAX_ERROR 				1149
#define CR_SERVER_GONE_ERROR 			2006
#define CR_SERVER_LOST 					2013
#define CR_COMMAND_OUT_OF_SYNC 			2014
#define CR_SERVER_LOST_EXTENDED 		2055


enum E_LOGLEVEL
{
	LOG_NONE = 0,
	LOG_ERROR = 1,
	LOG_WARNING = 2,
	LOG_DEBUG = 4,
	
	LOG_ALL = LOG_ERROR | LOG_WARNING | LOG_DEBUG
};

enum E_LOGTYPE
{
	LOG_TYPE_TEXT = 1,
	LOG_TYPE_HTML = 2
};

enum ORM_Error
{
	ERROR_OK,
	ERROR_NO_DATA
};

enum E_VAR_DATATYPE 
{
	DATATYPE_INT,
	DATATYPE_FLOAT,
	DATATYPE_STRING
};

enum E_MYSQL_OPTION
{
	DUPLICATE_CONNECTIONS,
	LOG_TRUNCATE_DATA
};

enum E_EXECTIME_UNIT
{
	UNIT_MILLISECONDS,
	UNIT_MICROSECONDS
};


#define mysql_real_escape_string 					mysql_escape_string
#define cache_num_fields 							cache_get_field_count
#define cache_num_rows 								cache_get_row_count
#define mysql_function_query(%0,%1,%2,%3,"%4"%5) 	mysql_tquery(%0,%1,%3,#%4%5)
#define mysql_reload(%0) 							mysql_tquery(%0,"FLUSH PRIVILEGES")
#define mysql_debug(%0)								(%0?mysql_log(LOG_ALL):mysql_log())
#define ismysqlnull(%0) 							(strcmp(%0,"NULL",false)==0)


// ORM functions
native ORM:orm_create(const table[], connectionHandle = 1);
native orm_destroy(ORM:id);

native ORM_Error:orm_errno(ORM:id);

native orm_apply_cache(ORM:id, row);
native orm_select(ORM:id, callback[] = "", format[] = "", {Float, _}:...);
/*
native orm_select_inline(ORM:id, callback:Callback, format[], {Float,_}:...); //y_inline
*/
native orm_update(ORM:id);
native orm_insert(ORM:id, callback[] = "", format[] = "", {Float, _}:...);
/*
native orm_insert_inline(ORM:id, callback:Callback, format[], {Float,_}:...); //y_inline
*/
native orm_delete(ORM:id, bool:clearvars=true);

native orm_load(ORM:id, callback[] = "", format[] = "", {Float, _}:...) = orm_select;
native orm_save(ORM:id, callback[] = "", format[] = "", {Float, _}:...);

native orm_addvar_int(ORM:id, &var, varname[]);
native orm_addvar_float(ORM:id, &Float:var, varname[]);
native orm_addvar_string(ORM:id, var[], var_maxlen, varname[]);

native orm_delvar(ORM:id, varname[]);
native orm_setkey(ORM:id, varname[]);


// MySQL functions
native mysql_log(E_LOGLEVEL:loglevel = LOG_ERROR | LOG_WARNING, E_LOGTYPE:logtype = LOG_TYPE_TEXT);
native mysql_connect(const host[], const user[], const database[], const password[], port = 3306, bool:autoreconnect = true, pool_size = 2);
native mysql_close(connectionHandle = 1);
native mysql_reconnect(connectionHandle = 1);

native mysql_unprocessed_queries(connectionHandle = 1);
native mysql_current_handle();
native mysql_option(E_MYSQL_OPTION:type, value);

native mysql_errno(connectionHandle = 1);
native mysql_escape_string(const source[], destination[], connectionHandle = 1, max_len = sizeof(destination));
native mysql_format(connectionHandle, output[], len, format[], {Float,_}:...);
native mysql_pquery(connectionHandle, query[], callback[] = "", format[] = "", {Float,_}:...);
/*
native mysql_pquery_inline(connHandle, query[], callback:Callback, format[], {Float,_}:...); //y_inline
*/
native mysql_tquery(connectionHandle, query[], callback[] = "", format[] = "", {Float,_}:...);
/*
native mysql_tquery_inline(connHandle, query[], callback:Callback, format[], {Float,_}:...); //y_inline
*/
native Cache:mysql_query(conhandle, query[], bool:use_cache = true);

native mysql_stat(destination[], connectionHandle = 1, max_len = sizeof(destination));
native mysql_get_charset(destination[], connectionHandle = 1, max_len = sizeof(destination));
native mysql_set_charset(charset[], connectionHandle = 1);


// Cache functions
native cache_get_data(&num_rows, &num_fields, connectionHandle = 1);
native cache_get_row_count(connectionHandle = 1);
native cache_get_field_count(connectionHandle = 1);
native cache_get_field_name(field_index, destination[], connectionHandle = 1, max_len = sizeof(destination));

native cache_get_row(row, field_idx, destination[], connectionHandle = 1, max_len = sizeof(destination));
native cache_get_row_int(row, field_idx, connectionHandle = 1);
native Float:cache_get_row_float(row, field_idx, connectionHandle = 1);

native cache_get_field_content(row, const field_name[], destination[], connectionHandle = 1, max_len = sizeof(destination));
native cache_get_field_content_int(row, const field_name[], connectionHandle = 1);
native Float:cache_get_field_content_float(row, const field_name[], connectionHandle = 1);

native Cache:cache_save(connectionHandle = 1);
native cache_delete(Cache:cache_id, connectionHandle = 1);
native cache_set_active(Cache:cache_id, connectionHandle = 1);
native cache_is_valid(Cache:cache_id, connectionHandle = 1);

native cache_affected_rows(connectionHandle = 1);
native cache_insert_id(connectionHandle = 1);
native cache_warning_count(connectionHandle = 1);

native cache_get_query_exec_time(E_EXECTIME_UNIT:unit = UNIT_MICROSECONDS);
native cache_get_query_string(destination[], max_len = sizeof(destination));


// Forward declarations
forward OnQueryError(errorid, error[], callback[], query[], connectionHandle);


#if defined MYSQL_USE_YINLINE || defined E_CALLBACK_DATA
	#if !defined E_CALLBACK_DATA
		#include <YSI\y_inline>
	#endif
	
	static g_MySQL_InlineData[1000][E_CALLBACK_DATA];
	static g_MySQL_VarArray[32][YSI_MAX_STRING];
	static g_MySQL_AddressArray[32];

	stock MySQL_Internal_SaveInline(callback:CB) 
	{
		static bool:g_MySQL_LazyInit = true;
		if(g_MySQL_LazyInit == true) 
		{
			//set g_MySQL_InlineData empty
			for(new i=0; i < sizeof(g_MySQL_InlineData); ++i)
				for(new E_CALLBACK_DATA:e = E_CALLBACK_DATA:0; e < E_CALLBACK_DATA; ++e)
					g_MySQL_InlineData[i][e] = 0;
			g_MySQL_LazyInit = false;
		}
		
		for(new i=0; i < sizeof(g_MySQL_InlineData); ++i)
			if(_:g_MySQL_InlineData[i][E_CALLBACK_DATA_POINTER] == 0)
				if (Callback_Get(CB, g_MySQL_InlineData[i]))
					return i;
					
		return -1;
	}
	
	#define mysql_pquery_inline(%0,%1,%2,"%3"%4) \
		mysql_pquery(%0,%1,"FJ37DH3JG_MYSQL_INTERNAL","d"#%3,MySQL_Internal_SaveInline(%2)%4)
		
	#define mysql_tquery_inline(%0,%1,%2,"%3"%4) \
		mysql_tquery(%0,%1,"FJ37DH3JG_MYSQL_INTERNAL","d"#%3,MySQL_Internal_SaveInline(%2)%4)
	
	#define orm_select_inline(%0,%1,"%2"%3) \
		orm_select(%0,"FJ37DH3JG_MYSQL_INTERNAL","d"#%2,MySQL_Internal_SaveInline(%1)%3)
	
	#define orm_insert_inline(%0,%1,"%2"%3) \
		orm_insert(%0,"FJ37DH3JG_MYSQL_INTERNAL","d"#%2,MySQL_Internal_SaveInline(%1)%3)


	forward FJ37DH3JG_MYSQL_INTERNAL(...);
	public FJ37DH3JG_MYSQL_INTERNAL(...) 
	{
		new InlineDataIndex = getarg(0);
		if(InlineDataIndex < 0)
			return 0;
		
		for(new i=0; i < numargs()-1; ++i) 
		{
			for(new l=0; l < YSI_MAX_STRING; ++l) 
			{
				new TmpVal = getarg(i+1, l);
				if(l == 0 || g_MySQL_VarArray[i][l-1] < 256)
					g_MySQL_VarArray[i][l] = TmpVal;
				else 
					break;
			}
			
			g_MySQL_AddressArray[i] = AMX_GetRelativeAddress(g_MySQL_VarArray[i][0]);
		}
		
		Callback_Array(g_MySQL_InlineData[InlineDataIndex], g_MySQL_AddressArray);
		
		Callback_Release(g_MySQL_InlineData[InlineDataIndex]);
		for(new E_CALLBACK_DATA:e = E_CALLBACK_DATA:0; e < E_CALLBACK_DATA; ++e)
			g_MySQL_InlineData[InlineDataIndex][e] = 0;
		
		for(new i=0; i < numargs()-1; ++i) 
		{
			g_MySQL_AddressArray[i] = 0;
			for(new l=0, lmax=strlen(g_MySQL_VarArray[i]); l < lmax; ++l)
				g_MySQL_VarArray[i][l] = 0;
		}
		return 1;
	}
#endif

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
noname_idk

@Bakston, зачем тебе такая древняя версия?) Уже давно доказано, что R41 среди всех имеющихся на данный момент самая шустрая. Плюс к этому в каждой новой версии исправлены предыдущие баги и добавлено что-то новое, возможно, нужное тебе (пусть даже и не сейчас). Просто R39-2 даже в списке официальных релизов MySQL нет. А значит, скорее всего, в ней присутствует многозначимая ошибка. Советую даже не копаться в причине ошибки и переходить на другую версию (запомни: чем новее, тем лучше. На данный момент R41-4 самая новая). Список официальных релизов: https://github.com/pBlueG/SA-MP-MySQL/releases.

 

P.s. если ты уже много чего сделал на этой версии, не бейся о стол, в жизни все бывает  :-D . Можешь написать мне в ВК или личку, без проблем помогу с переводом (бесплатно конечно).

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
Bakston

,спасибо за содействие в моих начинаниях! Повторюсь, я только начал сам писать свой мод (до этого пробовал слитые сервера перелопачивать (были удачи), что как то не айс) и пока решил довольствоваться системой регистрации (ну я так понимаю это начало начал). Ну чтоб хоть можно было побегать на своём сервере, но пока даже зайти на него не могу. Ломаю голову, перебираю туториалы, короче пока голова болит от столкновения о стену))) 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
noname_idk

@Bakston, пиши, задавай все вопросы (вообще неважно по какому поводу), не стесняйся. Я ценю людей, стремящихся разбираться в чем-либо и с удовольствием им помогаю. Вот пример регистрации на одной из последних версий MySQL (правда ORM, что не во всем хорошо): https://github.com/pBlueG/SA-MP-MySQL/blob/master/example_scripts/login_system-cache.pwn.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
Авторизация  

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу

×

Важная информация

Мы разместили cookie-файлы на ваше устройство, чтобы помочь сделать этот сайт лучше. Вы можете изменить свои настройки cookie-файлов, или продолжить без изменения настроек.