[Tutorial] Creating a simple register/save system using R41-2
#1

Hello !!

Introduction:

as i noticed the most of tutorials are outdated and some onces are bugged! so In this tutorial i will show you a simple and fast way to create a simple register system using The lastest version of MySQL by BlueG/maddinat0r (R41-2)

Includes:

We need 2 base includes to create our system

they are :

PHP код:
#include <a_samp> // 0.3.7 Include
#include <a_mysql>// MySQL R41-2 
Please be sure you are using lastest version of mysql include about a_samp it's dosent matter you can use the version of a_samp include that your server work with it

Show Time:

Let's Start:
1- we need to define the mysql information in the top of script

PHP код:
#define MySQL_Host ""
#define MySQL_User ""
#define MySQL_Password ""
#define MySQL_Database "" 
2 - we need to create a handle for mysql but in R41-2 we need to put MySQL: tag in the variable created!

like this :

PHP код:
new MySQL:MHandle
3 - we need to define the dialogs & User Data

PHP код:
enum
{
    
Register,
    
Login
};
enum Player
{
    
Name[MAX_PLAYERS_NAME],
    
Admin,
    
Deaths,
    
Kills
};
new 
PlayerInfo[MAX_PLAYERS][Player
4 - Adding the whirlpool hashing engine

PHP код:
native WP_Hash(buffer[], len, const str[]); 
5 - let's move to OnGamemodeInit Callback

we need to connect server to mysql server and creating the tables

About tables:

We need 1 table called accounts contaning 5 colunms (Name (string), IP(string), Password(string), Deaths(Int), Kills(Int))

so the MySQL Synatax:
PHP код:
CREATE TABLE IF NOT EXISTS `accounts` (`NameVARCHAR(24), `IPVARCHAR(16), `PasswordVARCHAR(129), `AdminINT(2), `DeathsINT(6), `KillsINT(6)) 
let's move to the callback

PHP код:
public OnGameModeInit()
{
    
// Connecting to mysql server using MHandle 
    
MHandle mysql_connect(MySQL_HostMySQL_UserMySQL_PasswordMySQL_Database);
    if(
mysql_errno() != 0// checks if the server failed to connected or not
    
{
        print(
"[MYSQL]: Failed to connect with using Following Informations: ");
        
printf(" Host: %s | User: %s | Password: ****** | Database: %s"MySQL_HostMySQL_UserMySQL_Database);
    }
    else
    {
        
printf("[MYSQL]: Connection Success to database: %s !"MySQL_Database);
        
mysql_query(MHandle"CREATE TABLE IF NOT EXISTS `accounts` (`Name` VARCHAR(24), `IP` VARCHAR(16), `Password` VARCHAR(129), `Admin` INT(2), `Deaths` INT(6), `Kills` INT(6))"); // creating tables once server got connected to mysql server
    
}
    return 
1;

6 - Now we need to setup player on connect

we need to create a separed callback get called when player connect to check if he is registred or not

so it's need be something like that:

PHP код:
forward OnPlayerAccountCheck(playerid);
public 
OnPlayerAccountCheck(playerid)
{
    new 
rows;
    
cache_get_row_count(rows); // Server count how many rows find in the mysql server
    
if(rows// if he find any row then the player registered
    
{
        
cache_get_value_name(0"Password"PlayerInfo[playerid][Password]); // here we get the password of the player account for compare it later with the entred password on the dialog
        
ShowPlayerDialog(playeridLoginDIALOG_STYLE_PASSWORD"Login""Welcome Back !\nWe miss you here !\nPlease fill you password here to get stats back!""Login""Cancel"); 
    }
    else 
// else he is not
    
{
        
ShowPlayerDialog(playeridRegisterDIALOG_STYLE_PASSWORD"Register""Welcome to our server! \nthis account not register at the database \nPlease fill a password to register your account""Register""Cancel");
    }
    return 
1;

Now let's move to OnPlayerConnect:

PHP код:
public OnPlayerConnect(playerid)
{
    new 
query[50];
    
GetPlayerName(playeridPlayerInfo[player][Name], sizeof(PlayerInfo[player][Name])); // gets player name on connect
    
mysql_format(MHandlequerysizeof(query), "SELECT * FROM `accounts` WHERE `Name` = '%e'"PlayerInfo[player][Name]);
    
mysql_tquery(MHandlequery"OnPlayerAccountCheck""i"playerid); // in this step the server checks if player registered or not using the callback up ^^
    
return 1;

7 - Now The Dialogs !!!

we need to create 2 dialogs can load/insert data into the server without any bugs or lag

PHP код:
public OnDialogResponse(playeriddialogidresponselistiteminputtext[])
{
    switch(
dialogid)
    {   
        case 
Login:
        {
            new 
loginattempbuf[129];
            if(!
responseKick(playerid); 
            if(
isnull(PlayerInfo[playerid][Password])) // checks if password correctly loaded else check below :)
            
{
                
SendClientMessage(playerid, -1,"[MYSQL]: Sorry, we have some problems on database right now, Come back later !");
                
Kick(playerid);
                print(
"[MYSQL]: Password Value 'PlayerInfo[playerid][Password]' not correctly loaded! please check OnPlayerAccountCheck callback");
                print(
"[SA-MP Server]: Server shutdown..");
                
SendRconCommand("exit");
                return 
1;
            }
            
WP_Hash(bufsizeof(buf), inputtext);
            if(!
strcmp(bufPlayerInfo[playerid][Password], true)) // comparing the passwords (database & entrerd)
            

                new 
query[70], Cache:GetCache;
                
mysql_format(MHandlequerysizeof(query), "SELECT * FROM `accounts` WHERE `Name` = '%e' LIMIT 1"PlayerInfo[player][Name]);
                
GetCache mysql_query(MHandlequery);
               
                
// Importing data after beigning sure he is the right user
                
new rows
                
cache_get_row_count(rows);
                if(
rows == 1
                {
                    
cache_get_value_name_int(0"Admin"PlayerInfo[playerid][Admin]); 
                    
cache_get_value_name_int(0"Deaths"PlayerInfo[playerid][Deaths]); 
                    
cache_get_value_name_int(0"Kills"PlayerInfo[playerid][Kills]);
                }
                
SendClientMessage(playerid, -1"You have successfully logged in."); 
                
cache_delete(GetCache);
            } 
            else 
// if he entred an wrrong password
            

                if(
loginattemp == 3) return Kick(playerid); // if he entred the same wrrong password 3 times he got kicked
                
SendClientMessage(playerid, -1"You have specified an incorrect password!"); 
                
ShowPlayerDialog(playeridLoginDIALOG_STYLE_PASSWORD"Login""Welcome Back !\nWe miss you here !\nPlease fill you password here to get stats back!""Login""Cancel");
                
loginattemp++; // adding +1 for every attemp
            

        }
        case 
Register:
        {
            if(!
response) return Kick(playerid); 
            if(
strlen(inputtext) < 5
            { 
                
SendClientMessage(playerid, -1"Your password must at least contain more than 4 characters."); 
                return 
ShowPlayerDialog(playeridRegisterDIALOG_STYLE_PASSWORD"Register""Welcome to our server! \nthis account not register at the database \nPlease fill a password to register your account""Register""Cancel");
            } 
            new 
                
query[287], 
                
playerip[16],
                
buf[129]
            ;
            
WP_Hash(bufsizeof(buf), inputtext); // hashing password using Whirlpool engine
            
GetPlayerIp(playeridplayeripsizeof(playerip)); 
            
mysql_format(MHandlequerysizeof(query), "INSERT INTO `accounts` (`Name`, `Password`, `IP`, `Admin`,`Deaths`, `Kills`) VALUES ('%e', '%e', '%e', 0, 0, 0)"PlayerInfo[player][Name], bufplayerip); 
            
mysql_query(MHandlequery); // here inserting the player account in the database as a registered player
        
}
    }
    return 
0;

8 - Now increasing value of Deaths & Kills on every die or kill

it's very simple you can easy do it like that:

PHP код:
public OnPlayerDeath(playeridkilleridreason)
{
    
PlayerInfo[killerid][Kills]++; // increasing Kills value for killer 
    
PlayerInfo[playerid][Deaths]++; // increasing Deaths value for the victim
    
return 1;

9 - Now last step : Save Data on player Disconnect !

we need to update the mysql server rows using a mysql synatax :

like that :
PHP код:
UPDATE `accountsSET `Kills` = '', `Deaths` = '', `Admin` = ''WHERE `name` = '' 
so the callback must be like :

PHP код:
public OnPlayerDisconnect(playeridreason)
{
    new 
querylist[120];
    
mysql_format(MHandlequerylistsizeof(querylist),
    
"UPDATE `accounts` SET `Kills` = %d, `Deaths` = %d, `Admin` = %d WHERE `name` = '%e'"
    
PlayerInfo[playerid][Kills], PlayerInfo[playerid][Deaths], PlayerInfo[playerid][Admin], PlayerInfo[player][Name]);
    
mysql_query(MHandlequerylist); 
    return 
1;

10 - How to create a admin command:

PHP код:
CMD:[nameofcommand](playeridparams[])
{
    
// check if the player is admin
    
if(PlayerInfo[playerid][Admin] == 0) return SendClientMessage(playerid, -1"you are not admin");
    
// codes here ...
    
return 1// if you return 0 the command will not created.
 

Credits:

- SAMP Team for SAMP Includes
- BlueG/maddinat0r for MySQL Includes
- oMa37 check 3th post

Thank you for reading

Yaa
Reply
#2

Love you man.... Didn't tested yet, but the only thing I was looking for!
+Rep.
Reply
#3

1.

Quote:
Originally Posted by Yaa
Посмотреть сообщение
as i noticed the most of tutorials are outdated and some onces are bugged! so In this tutorial i will show you a simple and fast way to create a simple register system using The lastest version of MySQL by BlueG/maddinat0r (R41-2)
Click Here.
This is far better than your tutorial.

2.

Quote:
Originally Posted by Yaa
Посмотреть сообщение
4 - Adding the whirlpool hashing engine

PHP код:
native WP_Hash(buffer[], len, const str[]); 
https://sampwiki.blast.hk/wiki/SHA256_PassHash

3. There are too much spelling mistakes.
4. Use mysql_format instead of format while calling a query, Also don't forget to escape the text (like player name).
5. You don't need to put integers inside ' ', Only strings.

That's not all.

1 Star.
Reply
#4

Use a especific %e for users donґt send Escapes strings

Change

PHP код:
mysql_format(MHandlequerysizeof(query), "SELECT * FROM `accounts` WHERE `Name` = '%s' LIMIT 1"pname); 
To

PHP код:
mysql_format(MHandlequerysizeof(query), "SELECT * FROM `accounts` WHERE `Name` = '%e' LIMIT 1"pname); 
Reply
#5

Quote:
Originally Posted by oMa37
Посмотреть сообщение
1.



Click Here.
This is far better than your tutorial.
i see not tutorial here

Quote:
Originally Posted by oMa37
Посмотреть сообщение
check title please.

Quote:
Originally Posted by oMa37
Посмотреть сообщение
3. There are too much spelling mistakes.
give me the mistakes lemme fix it ?

Quote:
Originally Posted by oMa37
Посмотреть сообщение
4. Use mysql_format instead of format while calling a query, Also don't forget to escape the text (like player name).
it's dosen't matter mysql_format same as format but i will use it

Quote:
Originally Posted by oMa37
Посмотреть сообщение
5. You don't need to put integers inside ' ', Only strings.
also doesn't matter the synatax always keep work with it or without it

Quote:
Originally Posted by oMa37
Посмотреть сообщение
That's not all.

1 Star.
Thank you for you feed back.
Reply
#6

Quote:
Originally Posted by Yaa
Посмотреть сообщение
also doesn't matter the synatax always keep work with it or without it
Nope using ' on integers or other data type forces mysql to do a implicit conversion from strings to integer which is an overload.
Reply
#7

Quote:
Originally Posted by Yaa
Посмотреть сообщение
i see not tutorial here
Stop being a dumbass.

Quote:
Originally Posted by Yaa
Посмотреть сообщение
check title please.
What?

Quote:
Originally Posted by Yaa
Посмотреть сообщение
it's dosen't matter mysql_format same as format but i will use it
It does matter. https://sampwiki.blast.hk/wiki/MySQL#mysql_format

--

You seem like you can't handle the criticisms, Don't bother releasing stuff then.
Reply
#8

Quote:
Originally Posted by oMa37
Посмотреть сообщение
Stop being a dumbass.



What?



It does matter. https://sampwiki.blast.hk/wiki/MySQL#mysql_format

--

You seem like you can't handle the criticisms, Don't bother releasing stuff then.
Thank you.

i learned something today

edited with new edits !

@Sreyas ty
Reply
#9

I would still just say good job yup there were some corrections to be made which you already did......
But I would say to oMa37 atleast he made the tutorial which I really haven't seen yet with a update....Why didn't you made that?
Why you didn't get idea on this topic earlier?
Reply
#10

Quote:
Originally Posted by princejeet1510
Посмотреть сообщение
I would still just say good job yup there were some corrections to be made which you already did......
But I would say to oMa37 atleast he made the tutorial which I really haven't seen yet with a update....Why didn't you made that?
Why you didn't get idea on this topic earlier?
Because a tutorial should not be built on without enough researching on the subjects as you are teaching someone and you should be aware of every part of that topic. No one is not that insane to make a tutorial under 5 minutes like the op did.i'm pretty sure if oma did it he would have done it by researching and it would be much better than this guy's because he lacks basics. I would prefer Vince,Sreyas, Andysedyen,Konstantinos or Lordzy to make a tutorial.You should take a look @ that tutorials.
Reply
#11

Well were you there watching him when he was making tutorial and you guessed that it took 5 minutes?
Anyways lol I don't want to spam the thread....So let's keep it going..
Reply
#12

Quote:
Originally Posted by princejeet1510
View Post
Well were you there watching him when he was making tutorial and you guessed that it took 5 minutes?
Anyways lol I don't want to spam the thread....So let's keep it going..
Well taking a look @ such an un optmised tutorial with less details its common sense to all that how much he took for this.
Reply
#13

Quote:
Originally Posted by princejeet1510
View Post
I would still just say good job yup there were some corrections to be made which you already did......
But I would say to oMa37 atleast he made the tutorial which I really haven't seen yet with a update....Why didn't you made that?
Why you didn't get idea on this topic earlier?
Why would I make this when there is a better version? I would say it's the best version, This one.
Reply
#14

Let me clear things up here since I can clearly see that people don't know how to write tutorials.

First off, I made the same mistake when I made my first tutorial so let's avoid calling me a 'hypocrite' here.

Alright, in my opinion, tutorials should be written by people who know everything there is to know about the subject of their tutorial. This section has been made so others can share their knowledge and let other users learn it as well but that has clearly went over board. People make tutorials for a lot of things except the one thing that is the purpose of this section, which is to transfer your knowledge onto others.

People write a lot of bad tutorials, and let me clear this out, making tutorials is really hard. It, however, depends on what kind of tutorial you're writing but it's not easy. People think it is easy and that's why there arent so many good tutorials out here. They got lost in these, don't even have a name for them.

Teaching other people isn't easy, and there are a lot of people that read these bad tutorials and gain false knowledge. That's why this has to stop!
No hate intended to anyone of course but 80% of the tutorials in this board are bad.

Of course, the things I wrote above wont be read by many people and this will still continue but if you did read it please consider it as an option.
Reply
#15

Quote:
Originally Posted by oMa37
View Post
Why would I make this when there is a better version? I would say it's the best version, This one.
did this tutorial work ? Yes.

did it's take so much cpu ? No.

so it's fine to use .

Also that GhostHacker just another noob come here to talk about optimizing and he not even know what is optimizing

@oMa37 stop it! it's just a file without any explaintion, i can do that just check my scripts at http://github.com/saplayground

and this is my first tutorial So ?

i was evading creating tutorial but i supposed to do after seeying a lots of ppl cannot update from R39-* to R41-2
Reply
#16

Quote:
Originally Posted by Yaa
View Post
@oMa37 stop it! it's just a file without any explaintion, i can do that just check my scripts at http://github.com/saplayground
If you are blind that's not my problem mate.

EDIT:

With integers I meant also the %d specifiers.
Reply
#17

Okay Mr Pro scripter i will tell you what exactly is optmisation is.It is not actually reducing no of lines in a script.It how you hacks with compiler and machine.Also overdoing an optmisation is also bad programming do the optmisation where ever necessary and never should it compromise it with readability.
Lets take a tiny portion of your script.
Code:
public OnPlayerConnect(playerid) 
{ 
    new query[50], pname[MAX_PLAYERS_NAME]; 
    GetPlayerName(playerid, pname, sizeof(pname)); // gets player name on connect 
    mysql_format(MHandle, query, sizeof(query), "SELECT * FROM `accounts` WHERE `Name` = '%e'", pname); 
    mysql_tquery(MHandle, query, "OnPlayerAccountCheck", "i", playerid); // in this step the server checks if player registered or not using the callback up ^^ 
    return 1; 
}
Now this
Code:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) 
{ 
    switch(dialogid) 
    {    
        case Login: 
        { 
            static loginattemp, buf[129], pname[MAX_PLAYERS_NAME]; 
            GetPlayerName(playerid, pname, sizeof(pname)); 

            if(!response) Kick(playerid);  
            if(isnull(PlayerInfo[playerid][Password])) // checks if password correctly loaded else check below :) 
            { 
                SendClientMessage(playerid, -1,"[MYSQL]: Sorry, we have some problems on database right now, Come back later !"); 
                Kick(playerid); 
                print("[MYSQL]: Password Value 'PlayerInfo[playerid][Password]' not correctly loaded! please check OnPlayerAccountCheck callback"); 
                print("[SA-MP Server]: Server shutdown.."); 
                SendRconCommand("exit"); 
                return 1; 
            } 
            WP_Hash(buf, sizeof(buf), inputtext); 
            if(!strcmp(buf, PlayerInfo[playerid][Password], true)) // comparing the passwords (database & entrerd) 
            {  
                new query[70], Cache:GetCache; 
                mysql_format(MHandle, query, sizeof(query), "SELECT * FROM `accounts` WHERE `Name` = '%e' LIMIT 1", pname); 
                GetCache = mysql_query(MHandle, query); 
                
                // Importing data after beigning sure he is the right user 
                new rows;  
                cache_get_row_count(rows); 
                if(rows == 1)  
                { 
                    cache_get_value_name_int(0, "Admin", PlayerInfo[playerid][Admin]);  
                    cache_get_value_name_int(0, "Deaths", PlayerInfo[playerid][Deaths]);  
                    cache_get_value_name_int(0, "Kills", PlayerInfo[playerid][Kills]); 
                } 
                SendClientMessage(playerid, -1, "You have successfully logged in.");  
                cache_delete(GetCache); 
            }  
            else // if he entred an wrrong password 
            {  
                if(loginattemp == 3) return Kick(playerid); // if he entred the same wrrong password 3 times he got kicked 
                SendClientMessage(playerid, -1, "You have specified an incorrect password!");  
                ShowPlayerDialog(playerid, Login, DIALOG_STYLE_PASSWORD, "Login", "Welcome Back !\nWe miss you here !\nPlease fill you password here to get stats back!", "Login", "Cancel"); 
                loginattemp++; // adding +1 for every attemp 
            }  
        } 
        case Register: 
        { 
            if(!response) return Kick(playerid);  
            if(strlen(inputtext) < 5)  
            {  
                SendClientMessage(playerid, -1, "Your password must at least contain more than 4 characters.");  
                return ShowPlayerDialog(playerid, Register, DIALOG_STYLE_PASSWORD, "Register", "Welcome to our server! \nthis account not register at the database \nPlease fill a password to register your account", "Register", "Cancel"); 
            }  
            new  
                query[287],  
                playername[MAX_PLAYER_NAME],  
                playerip[16], 
                buf[129] 
            ; 
            WP_Hash(buf, sizeof(buf), inputtext); // hashing password using Whirlpool engine 
            GetPlayerName(playerid, playername, sizeof(playername));  
            GetPlayerIp(playerid, playerip, sizeof(playerip));  
            mysql_format(MHandle, query, sizeof(query), "INSERT INTO `accounts` (`Name`, `Password`, `IP`, `Admin`,`Deaths`, `Kills`) VALUES ('%e', '%e', '%e', 0, 0, 0)", playername, buf, playerip);  
            mysql_query(MHandle, query); // here inserting the player account in the database as a registered player 
        } 
    } 
    return 0; 
}
You are creating 3 variables to hold the player name in 3 different situations thats just fucking stupidness.
if i were you i will do create an global array to hold the player name,if its thats case i will add it in player enum

Also take a look @ here

Code:
static loginattemp
what the hell? You know what you actually doing ? Your code never going to work even. The code will not allow any player to login if one of the player failed the attempt.Because you are using a static variable whose copy will be created only once in the stack.
Now you can use char arrays instead of plain arrays which will much more memory efficient.
Code:
array_name[size char];
i can go even more and you can get more chilled.
Needless to say 1 star from me.Keep trying.....
Reply
#18

Quote:
Originally Posted by Yaa
View Post
did this tutorial work ? Yes.

did it's take so much cpu ? No.

so it's fine to use .
That's not the point. A tutorial should teach the best method. People reading a tutorial assume that what you've written is the best method to achieve the desired result. I'm sure all that you've written here will work, but as long as you don't understand the concept of keys in SQL you shouldn't write an SQL related tutorial.
Reply
#19

Quote:
Originally Posted by GhostHacker9
View Post
Okay Mr Pro scripter i will tell you what exactly is optmisation is.It is not actually reducing no of lines in a script.It how you hacks with compiler and machine.Also overdoing an optmisation is also bad programming do the optmisation where ever necessary and never should it compromise it with readability.




Quote:
Originally Posted by GhostHacker9
View Post
^^ another bad habit a good programmer cares about data structure rather than code. Instead creating an overhead to this function every time its better to have per player array to hold name on connection and not to mention your database arrangement it also need to normalized.


kill me no ?


Quote:
Originally Posted by Vince
View Post
That's not the point. A tutorial should teach the best method. People reading a tutorial assume that what you've written is the best method to achieve the desired result. I'm sure all that you've written here will work, but as long as you don't understand the concept of keys in SQL you shouldn't write an SQL related tutorial.
thank you
Reply
#20

Still not fixed login attempts.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)