SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help > Tutorials

Reply
 
Thread Tools Display Modes
Old 18/07/2010, 01:24 PM   #1
WackoX
Guest
 
Posts: n/a
Default Easy MySQL Register/Login system! (Includes every single step!)

Introduction

Introduction

Over the past few years people have been using dini or ffile to create a user register/login system.
I find this very idle, slow, and difficult, and i think a lot of 'new-scripters' feel the same way as i do.

In this tutorial i will show an easy and free example of a MySQL Register/Login system, but you'll have to modify it yourself since i don't know what variables you're going to use in your gamemode.

And yes i know, i thought there was also another MySQL tutorial on the forums, but i think i can make it easyer for you guys.
If you do not agree, pick the one you like, you don't have to do it on my way.


Knowledge

Before you start doing some MySQL scripting inside your gamemode/filterscript, you'll need to have some knowledge about MySQL coding, here a few tips:

int(length) = Can be used for decimals or an integers (1337).
varchar(length) = Can be used for strings (leet), but also for floats (13.37).


Optimization

When you create a gamemode/filterscript, and certainly when based on MySQL, you need to have a good optimized script, otherwise you're gonna run out of RAM or CPU.

I recommend reading Y_Less topic first: http://forum.sa-mp.com/showthread.php?t=57018
When you don't have time for this, remember always, make the strings as short as you can!
(Example: A player name doesn't have to be 256 characters, 24 is the maximum in SA:MP)


Setting Everything Up

Plugins and Includes
Besides from just the scripting, you're gonna need some Plugins and Includes for this.
I recommend using G-sTyLeZzZ's: http://forum.sa-mp.com/showthread.php?t=56564

When you're done dowloading the right parts for your hosting, put the files in the right folders.

(Linux)
File "mysql.inc" >> Folder "Pawno/Includes"
File "mysql.so" >> Folder "Plugins" (Create if not exist)

(Windows)
File "mysql.inc" >> Folder "Pawno/Includes"
File "mysql.dll" >> Folder "Plugins" (Create if not exist)

Add this in your server.cfg:
(Linux) plugins mysql.so
(Windows) plugins mysql.dll


Creating a MySQL Database

Make sure your host has a local MySQL server running, with "PhpMyAdmin" access to it.
(Do NOT use free ones, because most of the time it doesn't work or it is way too slow!)

Go to your PhpMyAdmin site (http://YOUR_HOST_IP_HERE/PhpMyAdmin/) and login.
Now you see something like this:



Enter a new, simple, short name for your database under the text "Create new database", and press "Create".
If everything went alright you will get a notification with the text "Database NAME_HERE has been created.",
now you're inside your MySQL database and left your MySQL homepage.

Now, you want to create a new Table called "Users", now put that in, and the number of fields doesn't matter, you can always change it later,
but it has to be the same amout of variables you're gonna use (for name, password, admin level, etc).

Now, you're gonna see something like this (I've already put those fields in for example)



Like i already said in the topics "Knowledge" and "Optimization", make those 'Length/Values' as short as posible, and use the right 'Types'.
Note: All those field names (Name, Password, Admin, Money) doesn't have to be the same name as the variables inside your Gamemode,
but i recommend it since it's very useful.

When you're done press 'Save', or if you want more fields press 'Go', and leave a field blank when you don't need that one.
Now you will see something like this:



When there are players registered, you can use the button 'Browse', but since there aren't one at the moment, you can't use it.


Creating The Script

Now when you're done create the Database, we're gonna move over to your Gamemode, open that one now.

Add this include:
Code:
#include <a_mysql>
Now add this at the very beginning of your Gamemode (after all the includes).
Put in all the information you got from your host, the IP, the username to login with the password, and the name of the database you just created.
NOTE: Not the name of the Tabel (in this case: Users), but the name of the Database (in this case: Test)!!

Code:
#define MYSQL_HOST	"ip"
#define MYSQL_USER	"username"
#define MYSQL_DB	"database"
#define MYSQL_PASS 	"password"
Code:
#undef MAX_PLAYERS
#define MAX_PLAYERS 50 // Put this as low as you could!
Code:
enum pEnum
{
	Name[MAX_PLAYER_NAME],
	Password[32],
	Admin,
	Money,
};
new UserStats[MAX_PLAYERS][pEnum];

new AccountExists[MAX_PLAYERS];
new PlayerLogged[MAX_PLAYERS];
Now, we're gonna put some large parts inside our gamemode, just put it somewhere it doesn't matter, but i recommend to put it all down.

Code:
ConnectMySQL()
{
	if(mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_DB, MYSQL_PASS))
	    print("[MySQL] Connection to the MySQL Database was successfully!");

	else
	    print("[MySQL] Could not connect to the MySQL Database!");
}

CheckMySQL()
{
	if(mysql_ping() == -1)
		mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_DB, MYSQL_PASS);
}
Code:
CheckAccountExists(account[])
{
	new string[128];
    	format(string, sizeof(string), "SELECT * FROM Users WHERE Name = '%s'", account);
    	mysql_query(string);
    
	mysql_store_result();

	new value;
	value = mysql_num_rows();
	mysql_free_result();
	return value;
}
And you're also gonna need the 'Explode' function, since the 'Split' function is mutch slower:

(Created by Westie)
Code:
explode(const sSource[], aExplode[][], const sDelimiter[] = " ", iVertices = sizeof aExplode, iLength = sizeof aExplode[]) // Created by Westie
{
	new
		iNode,
		iPointer,
		iPrevious = -1,
		iDelimiter = strlen(sDelimiter);

	while(iNode < iVertices)
	{
		iPointer = strfind(sSource, sDelimiter, false, iPointer);

		if(iPointer == -1)
		{
			strmid(aExplode[iNode], sSource, iPrevious, strlen(sSource), iLength);
			break;
		}
		else
		{
			strmid(aExplode[iNode], sSource, iPrevious, iPointer, iLength);
		}

		iPrevious = (iPointer += iDelimiter);
		++iNode;
	}
	return iPrevious;
}

Now put in the Register/Login/Save parts, you'll have to edit them to your varibles!

Code:
RegisterPlayer(playerid, password[])
{
	if(AccountExists[playerid])
		return SendClientMessage(playerid, COLOR_RED, "[ACCOUNT] You're already registered!");

 	if(PlayerLogged[playerid])
		return SendClientMessage(playerid, COLOR_RED, "[ACCOUNT] You're already logged in!");

	if(strlen(password) < 3 || strlen(password) >= 32)
		return SendClientMessage(playerid, COLOR_RED, "[ACCOUNT] Your password is too short or too long!");

	CheckMySQL();

	new string[128];
	format(string, sizeof(string), "INSERT INTO Users (Name,Password) VALUES ('%s','%s')", UserStats[playerid][Name], password);
	mysql_query(string);

    	AccountExists[playerid] = 1;
	SendClientMessage(playerid, COLOR_YELLOW, "[ACCOUNT] Your account has been created, please login now!");

	LoginPlayer(playerid, password);
	return 1;
}

LoginPlayer(playerid, password[])
{
	if(!AccountExists[playerid])
		return SendClientMessage(playerid, COLOR_RED, "[ACCOUNT] You're not registered!");

	if(PlayerLogged[playerid])
	    	return SendClientMessage(playerid, COLOR_RED, "[ACCOUNT] You're already logged in!");

 	if(strlen(password) < 3 || strlen(password) >= 32)
	    	return SendClientMessage(playerid, COLOR_RED, "[ACCOUNT] Your password is too short or too long!");

	CheckMySQL();

    	new string[128];
	format(string, sizeof(string), "SELECT * FROM Users WHERE Name = '%s' AND Password = '%s'", UserStats[playerid][Name], password);
	mysql_query(string);
	mysql_store_result();

	if(!mysql_num_rows())
		return SendClientMessage(playerid, COLOR_RED, "[ACCOUNT] Incorrect password!");

	new row[128]; // The length of 1 'row' total.
	new field[4][32]; // [4] = Amount of fields, [24] = Max length of the bigest field. 

	mysql_fetch_row_format(row, "|");
	explode(row, field, "|");
	mysql_free_result();

	// The field starts here with 1, because the field 'Name' = 0, and we already have the name in a variable.
	format(UserStats[playerid][Password], 32, "%s", field[1]);
 	UserStats[playerid][Admin] = strval(field[2]);
 	UserStats[playerid][Money] = strval(field[3]);

 	GivePlayerMoney(playerid, UserStats[playerid][Money]);
 	
	
	format(string, sizeof(string), "[ACCOUNT] Welcome back %s, you are now logged in!", UserStats[playerid][Name]);
    	SendClientMessage(playerid, COLOR_YELLOW, string);

    	PlayerLogged[playerid] = 1;
    	return 1;
}

SavePlayer(playerid)
{
	if(!PlayerLogged[playerid])
		return 0;

    	UserStats[playerid][Money] = GetPlayerMoney(playerid);
    

	CheckMySQL();
    
    	new string[256];
    	format(string, sizeof(string), "UPDATE Users SET Password='%s',Admin='%d',Money='%d' WHERE Name='%s'", UserStats[playerid][Password], UserStats[playerid][Admin], UserStats[playerid][Money], UserStats[playerid][Name]);
    	mysql_query(string);
    	return 1;
}
Now we're gonna update your OnGameModeInit, OnPlayerConnect and OnPlayerDisconnect:

Code:
public OnGameModeInit()
{
	ConnectMySQL();
	return 1;
}

public OnPlayerConnect(playerid)
{
	GetPlayerName(playerid, UserStats[playerid][Name], MAX_PLAYER_NAME);
	
	if(CheckAccountExists(UserStats[playerid][Name])) AccountExists[playerid] = 1;
	else AccountExists[playerid] = 0;
	return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
	SavePlayer(playerid);

	UserStats[playerid][Admin] = 0;
	UserStats[playerid][Money] = 0;
	return 1;
}
And now the last step, you need to implement the commands.
You can use strcmp+strtok wich is very slow and unuseful, or you can use zcmd or dcmd.

In this case we're going to use dcmd, but you can use whatever you like:

Code:
public OnPlayerCommandText(playerid, cmdtext[])
{
	dcmd(register, 8, cmdtext);
	dcmd(login, 5, cmdtext);
	return 0;
}

dcmd_register(playerid, params[])
{
	RegisterPlayer(playerid, params);
	return 1;
}

dcmd_login(playerid, params[])
{
	LoginPlayer(playerid, params);
	return 1;
}

You're done!
Congratulations with your very first own scripted MySQL based Gamemode!
Put on your server, and you'll see it will connect to the MySQL database and everything works fine!

Last edited by WackoX; 19/07/2010 at 10:14 AM.
  Reply With Quote
Old 18/07/2010, 02:08 PM   #2
Calgon
Godfather
 
Calgon's Avatar
 
Join Date: Jan 2009
Posts: 6,426
Reputation: 1060
Default Re: Easy MySQL Register/Login system!

You've forgotten to add credits for the explode function, created by Westie.
Calgon is offline   Reply With Quote
Old 18/07/2010, 03:21 PM   #3
WackoX
Guest
 
Posts: n/a
Default Re: Easy MySQL Register/Login system!

Quote:
Originally Posted by Calgon View Post
You've forgotten to add credits for the explode function, created by Westie.
Thank you they've been edited! do you also know how to make those screenshots smaller in the [img] code?
It stretches the forum now at my screen.
  Reply With Quote
Old 18/07/2010, 04:18 PM   #4
Kar
High-roller
 
Kar's Avatar
 
Join Date: May 2010
Location: Black Asylum
Posts: 3,130
Reputation: 450
Default Re: Easy MySQL Register/Login system!

wow Nice imma use this in the future
Kar is offline   Reply With Quote
Old 18/07/2010, 04:21 PM   #5
Lewwy
High-roller
 
Lewwy's Avatar
 
Join Date: Nov 2007
Location: Scotland
Posts: 1,564
Reputation: 5
Default Re: Easy MySQL Register/Login system!

No idea why but I did what you said, haven't edited a single piece from your tutorial and when I connect and register, all is well. Once I leave however, everything but my password saves, it leaves it blank. Why is this?
Lewwy is offline   Reply With Quote
Old 18/07/2010, 05:01 PM   #6
WackoX
Guest
 
Posts: n/a
Default Re: Easy MySQL Register/Login system!

Quote:
Originally Posted by Lewwy View Post
No idea why but I did what you said, haven't edited a single piece from your tutorial and when I connect and register, all is well. Once I leave however, everything but my password saves, it leaves it blank. Why is this?
Yes i see it now, i forgot to add the Connection part in the script :P
Please look again at the OnGameModeInit part, and put that one also in your script.

Having more problems? please post them i'd like to help you.
  Reply With Quote
Old 18/07/2010, 05:25 PM   #7
Lewwy
High-roller
 
Lewwy's Avatar
 
Join Date: Nov 2007
Location: Scotland
Posts: 1,564
Reputation: 5
Default Re: Easy MySQL Register/Login system!

I had already done that, everything else loads and saves fine, except my password. It leaves the field blank after I quit or GMX.
Lewwy is offline   Reply With Quote
Old 18/07/2010, 06:36 PM   #8
WackoX
Guest
 
Posts: n/a
Default Re: Easy MySQL Register/Login system!

Quote:
Originally Posted by Lewwy View Post
I had already done that, everything else loads and saves fine, except my password. It leaves the field blank after I quit or GMX.
Fixed, please look at the LoginPlayer part again.
When you load in a string from MySQL, you'll need to use format or strcat.
  Reply With Quote
Old 18/07/2010, 08:32 PM   #9
[HiC]TheKiller
High-roller
 
Join Date: Mar 2008
Location: New Zealand
Posts: 3,031
Reputation: 409
Default Re: Easy MySQL Register/Login system!

A few things that I suggest:

1. Instead of using a enum just use PVars for all of them.
2. Use Sscanf
3. Use dialogs
4. Please explain some of it using comments
5. Did you just copy and paste this from a script?
__________________
[HiC]TheKiller is offline   Reply With Quote
Old 18/07/2010, 09:12 PM   #10
WackoX
Guest
 
Posts: n/a
Default Re: Easy MySQL Register/Login system!

Quote:
Originally Posted by [HiC]TheKiller View Post
A few things that I suggest:

1. Instead of using a enum just use PVars for all of them.
2. Use Sscanf
3. Use dialogs
4. Please explain some of it using comments
5. Did you just copy and paste this from a script?
1. People can change it to whatever they want, and BTW if a standard value has to be like 255 for a house system or something, it reset's it automatically to 0 when a player disconnect, result: bugged house system.

And another way, i don't like the way of pVars:

* They reset automatically when i DON'T want to.
* You cannot use things like Text3D and other stuff in them, result: 2 different ways of saving for 1 system.
* They use less RAM, but take up more CPU.

2. Why? i don't use any parameters at the dcmd part, there's no need for.
3. Like i already said, people can modify whatever they want, and the title says EASY System.
4.
5. Yes, from my own created script, but edited it for the tutorial.
  Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



All times are GMT. The time now is 08:18 AM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.