[Tutorial] Making a registration system - Using "Y_INI + Whirlpool + Dialogs"
#1

a Registration system - Using "Y_INI + Whirlpool + Dialogs"
First of all, I would like to thank Kush for his tutorial on making a registration system, but in his tutorial he used "udb hash" which is an old way to hash your passwords and could set you in troubles in the nearest future, like what happened to me. So, I decided to make this tutorial to show you how to create a Registration system from the scratch using Y_INI for saving, Whirlpool for hashing passwords and Dialogs for the log-in/registering.


So, welcome to this tutorial where I am going to show you how to make a registration system using Y_INI, Whirlpool and Dialogs. Let's move to our first step,

The first step is the step where you will be downloading the files you need, in our case we will be needing the following:


Download both of them, and install them. Whirlpool goes directly into your server's folder and Y_INI goes to pawno -> include -> YSI Folder(If you don't have YSI folder just put it in include folder).


So, after finishing step one, let us move to the second step where we will be scripting our registration system. Go to Pawno and open a new .pwn file so we can start .. Okay, after opening it add the "Y_INI" at the beginning of your script under #include <a_samp>.


pawn Code:
#include <YSI\y_ini>
"This include contains all necessary functions needed to create our Login and Register system." - Kush

After adding it, let us add the Hashing into our script, so under the includes goes our hashing native

pawn Code:
native WP_Hash(buffer[], len, const str[]);
This one will make the hashing work, so you just installed it into your script.

Alright, after adding them, let us start adding the defines and colors.


A) Let's define the dialogs:

pawn Code:
#define DIALOG_REGISTER 1
#define DIALOG_LOGIN 2
#define DIALOG_SUCCESS_1 3
#define DIALOG_SUCCESS_2 4
B) Defining the path where it will be saving the players' statistics.

pawn Code:
#define PATH "/Players/%s.ini"
C) Adding some colors to make our registration system look better,

pawn Code:
#define COL_WHITE "{FFFFFF}"
#define COL_RED "{F81414}"
#define COL_GREEN "{00FF22}"
#define COL_LIGHTBLUE "{00CED1}"
So after defining the above, let us move to use an enum to save our variables,

pawn Code:
enum pInfo
{
    pPass[129],
    pCash,
    pAdmin,
    pKills,
    pDeaths
}
new PlayerInfo[MAX_PLAYERS][pInfo];
Alright, very well! Now we need something to load the statistics above! We will be adding the following to load the statistics,

pawn Code:
forward LoadUser_data(playerid,name[],value[]);
public LoadUser_data(playerid,name[],value[])
{
    INI_String("Password",PlayerInfo[playerid][pPass], 129);
    INI_Int("Cash",PlayerInfo[playerid][pCash]);
    INI_Int("Admin",PlayerInfo[playerid][pAdmin]);
    INI_Int("Kills",PlayerInfo[playerid][pKills]);
    INI_Int("Deaths",PlayerInfo[playerid][pDeaths]);
    return 1;
}
After doing that, let us move to adding the stock function,

pawn Code:
stock UserPath(playerid)
{
    new string[128],playername[MAX_PLAYER_NAME];
    GetPlayerName(playerid,playername,sizeof(playername));
    format(string,sizeof(string),PATH,playername);
    return string;
}
"The stock function 'UserPath' is merely going to 'grab' the 'PATH' of the User's file." - Kush

Alright, very well! Now let us move to adding the registration system to make it work! Go to OnPlayerConnect, we will be scripting something to check if the player is registered or not.

pawn Code:
public OnPlayerConnect(playerid)
{
    if(fexist(UserPath(playerid)))
    {
        INI_ParseFile(UserPath(playerid), "LoadUser_data", .bExtra = true, .extra = playerid);
        ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD,""COL_WHITE"Login",""COL_WHITE"Type your password below to login.","Login","Quit");
    }
    else
    {
        ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD,""COL_WHITE"Registering...",""COL_WHITE"Type your password below to register a new account.","Register","Quit");
    }
    return 1;
}
"We'll be using the native 'fexist' function to search for our file. Parameters are set to our stock function which we've created. If the file exists, you will receive a 'Login' dialog. If it doesn't, you will receive a register dialog." - Kush

Alright, Awesome! After making that, let us move to making the dialogs respond!

pawn Code:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    switch( dialogid )
    {
        case DIALOG_REGISTER:
        {
            if (!response) return Kick(playerid);
            if(response)
            {
                if(!strlen(inputtext)) return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, ""COL_WHITE"Making your account ..",""COL_RED"You have entered an invalid password.\n"COL_WHITE"Type your password below to register a new account.","Register","Quit");
                new INI:File = INI_Open(UserPath(playerid));
                INI_SetTag(File,"PlayerData");
                new HashPass[129];
                WP_Hash(HashPass, sizeof(HashPass), inputtext);
                INI_WriteString(File, "Password", HashPass);
                INI_WriteInt(File,"Cash",0);
                INI_WriteInt(File,"Admin",-1);
                INI_WriteInt(File,"Kills",0);
                INI_WriteInt(File,"Deaths",0);
                INI_Close(File);
               
                SetSpawnInfo(playerid, 0, 0, 1958.33, 1343.12, 15.36, 269.15, 0, 0, 0, 0, 0, 0);
                ShowPlayerDialog(playerid, DIALOG_SUCCESS_1, DIALOG_STYLE_MSGBOX,""COL_WHITE"Account created!",""COL_GREEN"You've created an account successfuly. Relogging is recommended.","Ok","");
            }
        }

        case DIALOG_LOGIN:
        {
            if ( !response ) return Kick ( playerid );
            if( response )
            {
                new HashPass[129];
                WP_Hash(HashPass, sizeof(HashPass), inputtext);
                if(strcmp(HashPass, PlayerInfo[playerid][pPass]) == 0)
                {
                    INI_ParseFile(UserPath(playerid), "LoadUser_data", .bExtra = true, .extra = playerid);
                    GivePlayerMoney(playerid, PlayerInfo[playerid][pCash]);
                    ShowPlayerDialog(playerid, DIALOG_SUCCESS_2, DIALOG_STYLE_MSGBOX,""COL_WHITE"Success!",""COL_GREEN"You have successfully logged in!","Ok","");
                }
                else
                {
                    ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD,""COL_WHITE"Login",""COL_RED"You have entered an incorrect password.\n"COL_WHITE"Type your password below to login.","Login","Quit");
                }
                return 1;
            }
        }
    }
    return 1;
}
"Instead of using the 'if' statement to define our dialogs, I've used cases as they seem to take less space and are supposedly 'faster'. The (!response) is the function if the first Button hasn't been clicked, it will then kick the player.

The if(!strlen(inputtext)) explains if nothing has been entered into the dialog (input), you would then be prompted to another dialog which shows you 'Incorrect Password'.

If all goes well, the function INI_Open is then 'executed' which loads and opens the Userfile. Once open, the function 'INI_WriteInt' is then called and starts writing the data into the userfile. The Whirlpool Hasher would generate a hash code from the player's inputtext (what you've typed). And after all this is completed, it is then closed by 'INI_Close' function.

Once finished, you will then be prompted to the 'Login' dialog.

In 'DIALOG_LOGIN', if the response is false (you have clicked 'QUIT), you would then be kicked. If given the correct information (password provided), the INI_Parsefile function would then scan and load your player's data." - Kush (But I edited some of the text)
Okay very well going! Now let us define something to save our variables when a player disconnects, so the next step will be for opening the user file, save his latest statistics in server and close his file,

pawn Code:
public OnPlayerDisconnect(playerid, reason)
{
    new INI:File = INI_Open(UserPath(playerid));
    INI_SetTag(File,"PlayerData");
    INI_WriteInt(File,"Cash",GetPlayerMoney(playerid));
    INI_WriteInt(File,"Admin",PlayerInfo[playerid][pAdmin]);
    INI_WriteInt(File,"Kills",PlayerInfo[playerid][pKills]);
    INI_WriteInt(File,"Deaths",PlayerInfo[playerid][pDeaths]);
    INI_Close(File);
    return 1;
}
You might ask, where is the password? The answer is that the password saves by itself while registering, so no worries!

After doing that, we're almost done, let us add something cool, such as OnPlayerDeath, so when a player dies it saves and kills another player saves,


pawn Code:
public OnPlayerDeath(playerid, killerid, reason)
{
    PlayerInfo[killerid][pKills]++;
    PlayerInfo[playerid][pDeaths]++;
    return 1;
}
So, that will increase and decrease the kill/death.

Important notes:

a) Make sure you create " Players " folder in your scriptfiles folder.
b) Make sure you've installed Y_INI and Whirlpool correctly.
In case you couldn't follow up, I've made this Gamemode for you, you may be able to download/view it from here:

Click me.

Finally, I would like to thank:

1) Kush for his great tutorial, without his tutorial I wouldn't be able to make this one today!
2) ****** for the great releases and things he does/create!
Reply
#2

Nice it is good to see people finally using up to date methods like Whirlpool, but you could expand the tutorial with adding simple commands for example a /setadmin command, and a /kick command, because this looks like the tutorial made by newbienoob https://sampforum.blast.hk/showthread.php?tid=352703.

However other then that nice job.
Reply
#3

Thank you and sure, I will be creating commands and such also /stats when I find a free time . About "newbienoob" It's all created by Kush and edited by me, so no worries and I didn't know that there is actually a tutorial like this one .
Reply
#4

Nice, i used it on my server and works well
Reply
#5

Quote:
Originally Posted by Deviant96
View Post
the folder in the scriptfile should be "Users" not "Players"
Ops, yes. I forgot to change the "Users", anyway it's fixed now and uses "Players". - Can you edit your post so nobody gets confused?
Reply
#6

why you added sentances from kush's tutorial ?
Reply
#7

Quote:
Originally Posted by xkirill
View Post
why you added sentances from kush's tutorial ?
Because his explanation is better than mine.
Reply
#8

Then, why you bother creating one if you can't explain it?

Reply
#9

Quote:
Originally Posted by Romel
View Post
Then, why you bother creating one if you can't explain it?

Because, I have explained what I have added. The already added scripts are better to be explained by their creator. I just replaced the password saving with a hashed one using whirlpool for those who don't know how to do it. Seriously, what I have done is not wrong. And yes, I bother creating one, because I want to help SA-MP members new ones and make it easier for others to make their first step in their Gamemode if they're going to use Y_INI. I can explain it, but you seem to be ignorant about that. I explained what I have added into this script and quoted Kush's explanation for a better results and because of my English not being as good as his, I had to put his.
Reply
#10

Let me ask you one thing.
Are you the one who make the password hashing one?
I don't think so. I remember the time which i help you in password hashing one.

Or is this a copy/paste from your script?



I understand you.
But newbienoob already done this tutorial.
Reply
#11

Quote:
Originally Posted by Romel
View Post
Let me ask you one thing.
Are you the one who make the password hashing one?
I don't think so. I remember the time which i help you in password hashing one.

Or is this a copy/paste from your script?



I understand you.
But newbienoob already done this tutorial.
You helped me fixing the problem in my script, and I have presented this tutorial for those who are looking for Kush's tutorial but using a better password-hashing way. What's your problem here? Seriously, if you don't like it, just don't reply.
Reply
#12

Just a same tutorial like of newbienoob but still i appericiate you for your work BUT try to add something new like some commands.
Reply
#13

Please help me! when i run the server it gives me this error:
Script[gamemodes/FreeServer.amx]: Run time error 19: "File or function is not found"
Reply
#14

Quote:
Originally Posted by adithegman
View Post
Please help me! when i run the server it gives me this error:
Script[gamemodes/FreeServer.amx]: Run time error 19: "File or function is not found"
You need to load the Whirlpool plugin.
Reply
#15

I think i didn't installed it corectly....
In the archive the file from Binaries go to plugins and the rest?
Reply
#16

Quote:
Originally Posted by adithegman
View Post
I think i didn't installed it corectly....
In the archive the file from Binaries go to plugins and the rest?
The file Whirlpool.dll is the one you need just place it in your plugins folder you don't need the rest and put :

plugins Whirlpool

line in your server.cfg
Reply
#17

ok thanks a lot
Reply
#18

Nice Work
Reply
#19

Thank you.
Reply
#20

Expand your tutorial a little more with commands to avoid people saying your tutorial is the same as newbienoob's one.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)