[Tutorial] Login / Register System Using Southclaw's INI System!
#1

EDIT: Sorry the script is not compiled and will bump into bugs i will be fixing them ASAP when i have time and again i apologize.
Register / Login System Using Southclaw's INI System


Introduction

Do you want to use y_ini but don't want to download the whole library just for one include ?
Or maybe you want to use dini because it is easy to use, but you can't because it is slow ?
Or do you want to use MySQL or SQLite but don't know how, or maybe don't want to ?

Then if your answer to all of these questions is yes then this system is for you.

It was released in 2011/06/19 By [HLF]Southclaw, and as some of the current INI systems it is based on cache, however i don't have much to say let's start working.

What Do We Need

You can apply this on any script you like, in this tutorial we are going to use the blank script (generated when you click on 'new' in PAWNO) and off course we will need the include itself, you can get it from It's Original Topic (Click!) and we will need the Whirlpool plugin to hash password, you can get it from Here that's all we need for now open PAWNO and follow the steps
Steps!


Step 1
First of all we need to include the system on top of your script so it will look like this
pawn Код:
#include    <a_samp>
#include    <INI>
By including it the functions will be available for you to use and you can see the function in PAWN's function list on your right hand side of the screen.
Step 2
Now we need to define the user's path for ease of use so under your includes add this
pawn Код:
#define     USER_PATH           "Accounts/%s.ini"
When a new user registers his INI file will get written to a folder called Accounts in your scriptfiles directory, please create the folder Accounts in your scriptfiles otherwise it won't work.
Step 3
Now as usual we need an enum to store our variables inside, so under your defines add
pawn Код:
enum Info
{
    IP[16],
    Password[129],
    Admin,
    Score,
    Money,
    Deaths,
    Kills,
    Float:PosX,
    Float:PosY,
    Float:PosZ,
    Float:PosA,
    IsRegistered,
    MyMotto[128]
}
The enum you see above will save each player's :
  • IP Address
  • Password
  • Admin Level
  • Score
  • Money
  • Number Of Kills He Made
  • Number Of Times He Died
  • His Position So We Can Load It When He Re-Connects
  • If He Is Registered Or Not
  • His Motto
and under the enum add
pawn Код:
new PlayerInfo[MAX_PLAYERS][Info];
By using MAX_PLAYERS the enum will be available to each player so later on we can use PlayerInfo[playerid][Admin] for example.
Step 4
Now we need to add the Whirlpool native so under the declaration we made on the last step add
pawn Код:
native WP_Hash(buffer[], len, const str[]);
the above function will let us use the hashing function provided by the Whirlpool plugin.

And we need to make a stock for user's path you so add this anywhere in your script (because when the script needs a stock it will look for it through top to bottom)
pawn Код:
stock UserPath(playerid)
{
    new pName[MAX_PLAYER_NAME], Path[60];
    GetPlayerName(playerid, pName, sizeof(pName));
    format(Path, sizeof(Path), USER_PATH, pName);
    return Path;
}
this is pretty self explanatory, but again, what are we doing is declaring two variables a pName to get player's name and store it inside pName, and Path to form user's path, the MAX_PLAYER_NAME is 24, this stock will return User's path.
Step 5
Now under your OnGameModeInit callback we need to add
pawn Код:
file_OS();
TBH, i actually don't know what that is and why we added it, but when i didn't it just can't save player's data (I hope Soutclaw will come and tell me).
Step 5
Now when a player joins when need to check if he has a account (registered), or it is the first time he is joining (not registered), so we can show the dialog to him, please note that the upcoming code can be added under OnPlayerConnect, OnPlayerRequestClass, OnPlayerSpawn, and OnPlayerRequestSpawn, however in this tutorial i am going to stick with OnPlayerConnect.
pawn Код:
public OnPlayerConnect(playerid)
{
    if(fexist(UserPath(playerid)))
    {
        ShowPlayerDialog(playerid, 1, DIALOG_STYLE_PASSWORD, "Login", "Please Login By Writing Your Password Below", "Login", "Leave");
    }
    else
    {
        ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Create An Account", "Please Create An Account On Our Server Before You Continue", "Register", "Leave");
    }
    return 1;
}
If the player's file exists then show the login dialog to him, else if it doesn't exist the show the register dialog so he can register, and make a new account on the server.
Step 6
Now under your OnDialogResponse add the following
pawn Код:
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    if(dialogid == 0) // If it is the register dialog
    {
        if(response) // if the player pressed the first button in our case Register.
        {
            if(!strlen(inputtext) || strlen(inputtext) > 100) // if the text ISN'T between 1 - 100 characters.
            {
                ShowPlayerDialog(playerid, 0, DIALOG_STYLE_PASSWORD, "Create An Account", "Please Create An Account On Our Server Before You Continue", "Register", "Leave");
                SendClientMessage(playerid, -1, "Your password must be between (1 - 100) characters");
            }
            else // if the text IS between 1 - 100 characters.
            {
                new pName[MAX_PLAYER_NAME], pIP[16], HashPass[129]; // Creating 3 variables for player's name, IP, and a variable for hasing user's password.
                GetPlayerName(playerid, pName, sizeof(pName)); // getting player's name and storing it inside the pName variable we created above ^.
                GetPlayerIp(playerid, pIP, sizeof(pIP)); // getting player's IP and saving it inside the pIP variable we created before.
                WP_Hash(HashPass, sizeof(HashPass), inputtext); // we are hashing inputtext (meaning the text the player wrote under the register dialog).
                file_Create(UserPath(playerid)); // Creating the file in (Accounts/%s.ini)
                file_Open(UserPath(playerid)); // opening the file
                file_SetStr("Password", HashPass); // setting the player's password to the hashed number.
                file_SetStr("IP", pIP); // setting player's IP to his IP
                file_SetVal("Admin", 0); // setting his admin level to 0
                file_SetVal("Score", 0); // setting his score to 0
                file_SetVal("Money", 500); // setting his money to 500 (NOTE: you also need to use GivePlayerMoney under OnPlayerSpawn).
                file_SetVal("Deaths", 0); // setting his kills to 0
                file_SetVal("Kills", 0); // setting his deaths to 0
                file_SetFloat("PosX", 0.0); // setting his X position to 0.0
                file_SetFloat("PosY", 0.0); // setting his Y position to 0.0
                file_SetFloat("PosZ", 0.0); // setting his Z position to 0.0
                file_SetFloat("PosA", 0.0); // setting his Angle to 0.0
                file_SetVal("IsRegistered", 1);
                file_SetStr("MyMotto", "You Don't Have A Motto Set One Using /setmotto");
                file_Save(UserPath(playerid)); // saving the file.
                file_Close(); // closing the file (NOTE: ALWAYS AND I DO MEAN ALWAYS close a file don't keep it open)
                SendClientMessage(playerid, -1, "you have been reged successfully"); // Sending a message to the player telling him he have been successfully registered the color -1 is white.
            }
        }
    }
    else if(dialogid == 1) // if he is registered then show him the login dialog
    {
        if(response) // if he clicked the first button in our case LOGIN
        {
            new HashPass[129]; // creating a variable to store get the hashed password from his file
            WP_Hash(HashPass, sizeof(HashPass), inputtext); // hashing the text he entered under the login dialog
            if(!strcmp(HashPass, PlayerInfo[playerid][Password])) // comparing it to the text in his file if it is true
            {
                file_Open(UserPath(playerid)); // open his file
                PlayerInfo[playerid][Admin] = file_GetVal("Admin"); // set each variable in his enum to the one in his file
                PlayerInfo[playerid][Score] = file_GetVal("Score");
                PlayerInfo[playerid][Money] = file_GetVal("Money");
                PlayerInfo[playerid][Deaths] = file_GetVal("Deaths");
                PlayerInfo[playerid][Kills] = file_GetVal("Kills");
                PlayerInfo[playerid][PosX] = file_GetFloat("PosX");
                PlayerInfo[playerid][PosY] = file_GetFloat("PosY");
                PlayerInfo[playerid][PosZ] = file_GetFloat("PosZ");
                PlayerInfo[playerid][PosA] = file_GetFloat("PosA");
                PlayerInfo[playerid][IsRegistered] = file_GetVal("IsRegistered");
                file_Close(); // Closing the file.
            }
            else
            {
                SendClientMessage(playerid, -1, "wrong password entered try again"); // if the password doesn't match the one in his file then tell him that it is incorrect
                ShowPlayerDialog(playerid, 1, DIALOG_STYLE_PASSWORD, "Login", "Please Login By Writing Your Password Below", "Login", "Leave"); // and re-show the login dialog
            }
        }
    }
    return 1;
}
i explained everything in a comment near the code so i won't explain it here.
Step 7
We are almost finished, the last thing we need to do is get the player's information when he leaves and save them to his file to do that add the following lines to your OnPlayerDisconnect.
pawn Код:
public OnPlayerDisconnect(playerid, reason)
{
    if(fexist(UserPath(playerid)))
    {
        GetPlayerPos(playerid, PlayerInfo[playerid][PosX], PlayerInfo[playerid][PosY], PlayerInfo[playerid][PosZ]);
        GetPlayerFacingAngle(playerid, PlayerInfo[playerid][PosA]);
        file_Open(UserPath(playerid));
        file_SetVal("Admin", PlayerInfo[playerid][Admin]);
        file_SetVal("Score", PlayerInfo[playerid][Score]);
        file_SetVal("Money", PlayerInfo[playerid][Money]);
        file_SetVal("Deaths", PlayerInfo[playerid][Deaths]);
        file_SetVal("Kills", PlayerInfo[playerid][Kills]);
        file_SetFloat("PosX", PlayerInfo[playerid][PosX]);
        file_SetFloat("PosY", PlayerInfo[playerid][PosY]);
        file_SetFloat("PosZ", PlayerInfo[playerid][PosZ]);
        file_SetFloat("PosA", PlayerInfo[playerid][PosA]);
        file_SetVal("IsRegistered", PlayerInfo[playerid][IsRegistered]);
        file_SetStr("MyMotto", PlayerInfo[playerid][MyMotto]);
        file_Close();
    }
    return 1;
}
Now what we are doing above is checking if the player's file exists, if it does the get the location where the player was when he disconnected, and save them to his enum then afterwords save each enum into a line in his file, simple as that.

Extra Stuff (Additions)
Now we are going to make a motto system (meaning each player can set a motto for himself, so make a command using zcmd, like this.
pawn Код:
CMD:setmotto(playerid, params[])
{
    if(PlayerInfo[playerid][IsRegistered] == 1) // if he is registered
    {
        if(IsNull(params)) return SendClientMessage(playerid, -1, "USAGE: /setmotto [your motto]"); // if he didn't write any parameters
        PlayerInfo[playerid][MyMotto] = params; // set his motto to the parameter he wrote
        SendClientMessage(playerid, -1, "SUCCESS: you have been successfully changed your motto into %s", params); // send him a success message
    }
    else SendClientMessage(playerid, -1, "You are not registered so you can't use this command"); // if he isn't registered
    return 1; // the command is successfully done
}
I explained what you need to know in the comments.

Now we need the player to see his motto when he logs in so under OnPlayerSpawn add
pawn Код:
public OnPlayerSpawn(playerid)
{
    PlayerInfo[playerid][MyMotto] = file_dGetStr(UserPath(playerid), "MyMotto"); // setting the MyMotto variable inside our enum to the MyMotto line in the player's user file
    new Str[128];
    format(Str, sizeof(Str), "Welcome Back Your Motto Is : %s", PlayerInfo[playerid][MyMotto]); // formatting the message that we are going to send him.
    SendClientMessage(playerid, -1, Str);
    return 1;
}
In the code above we used the direct reading functions, to be specific the string reading one, please note that the direct reading is very fast for ONLY ONE LINES not multiple.

Footnotes
  • If you face any problems please inform me
  • If you can't understand a part tell me
  • If there are any grammer mistakes again tell me.
  • I know the player won't spawn where he was when he left, that is because i didn't add how to load it, it is easy to add just use SetPlayerPos under your OnPlayerSpawn and that's it, if i have time i will add it later, sorry.
Credits

[HLF]Southclaw - For The INI System
****** - For Whirlpool
Reply
#2

Cool.Everything I can say.
Reply
#3

Very well explained +rep x 2
Reply
#4

Thank you both.
Reply
#5

This looks great, but i'm wondering one thing.. How can I make a command to make someone as an administrator?
Reply
#6

Quote:
Originally Posted by nogh445
Посмотреть сообщение
This looks great, but i'm wondering one thing.. How can I make a command to make someone as an administrator?
This is an example command
pawn Код:
CMD:setadmin(playerid, params[])
{
    new pName[MAX_PLAYER_NAME], Str[128], tName[MAX_PLAYER_NAME], Level, targetid;
    if(IsPlayerAdmin(playerid))
    {
        if(sscanf(params, "ui", targetid, Level))
        {
            SendClientMessage(playerid, -1, "{FFFF00}Usage : {FFFFFF}/setadmin [playerid] [level]");
            SendClientMessage(playerid, -1, "{FF0000}Levels : {FFFFFF}(0 - Normal Player, 1 - VIP Member, 2 - Moderator, 3 - Admin, 4 - Server Developer, 5 - Server Owner)");
        }
        else
        {
            GetPlayerName(playerid, pName, sizeof(pName));
            GetPlayerName(targetid, tName, sizeof(tName));
            if(!IsPlayerConnected(targetid)) return SendClientMessage(playerid, -1, "{FF0000}Error : {FFFFFF}The Player Is Not Connected");
            format(Str, sizeof(Str), "You Have Made %s an admin level %i", tName, Level);
            SendClientMessage(playerid, -1, Str);
            format(Str, sizeof(Str), "%s has made you an admin level %i", pName, Level);
            SendClientMessage(targetid, -1, Str);
            GameTextForPlayer(targetid, "~g~Promoted", 5000, 5);
            PlayerInfo[targetid][Admin] = Level;
        }
    }
    else SendClientMessage(playerid, -1, "{FF0000}Error : {FFFFFF}Only Server {FF0000}Owners{FFFFFF} Can Use This Command");
    return 1;
}
to use the command you need to have sscanf, and zcmd, and be logged in to RCON change the messages though.

I am going to expand the tutorial if i have more time maybe add some admin commands.

and put some information on the direct reading functions.
Reply
#7

Quote:
Originally Posted by [HLF]Southclaw
Посмотреть сообщение
Looks great, thanks Lexi!
I will add this to the thread, I might update the script soon too, maybe with some new features such as tagging and hopefully a speed increase
I am going to update the thread as i said above, to add information about direct reading functions, and some admin commands, once i am free.
Reply
#8

For me the x, y, and z positions keep going back to 0.00000 in my player file when I /q
pawn Код:
public OnPlayerDisconnect(playerid, reason)
{
    if(fexist(UserPath(playerid)))
    {
        file_Open(UserPath(playerid));
        file_SetVal("Admin", PlayerInfo[playerid][Admin]);
        file_SetVal("Health", PlayerInfo[playerid][Health]);
        file_SetVal("Armor", PlayerInfo[playerid][Armor]);
        file_SetVal("Money", PlayerInfo[playerid][Money]);
        file_SetVal("Skin", PlayerInfo[playerid][Skin]);
        file_SetVal("Level", PlayerInfo[playerid][Level]);
        file_SetVal("Banned", PlayerInfo[playerid][Banned]);
        file_SetFloat("Posx", PlayerInfo[playerid][Posx]);
        file_SetFloat("Posy", PlayerInfo[playerid][Posy]);
        file_SetFloat("Posz", PlayerInfo[playerid][Posz]);
        file_Close();
    }
    return 1;
}
This is on player disconnect..
I'm not sure why it is not saving them.
Reply
#9

This is where its used at:
pawn Код:
if(PlayerInfo[playerid][Banned] == 0)
            {
                TogglePlayerSpectating(playerid, 0);
                SetSpawnInfo(playerid, NO_TEAM, PlayerInfo[playerid][Skin], PlayerInfo[playerid][Posx],PlayerInfo[playerid][Posy],PlayerInfo[playerid][Posz], 0.0, 0, 0, 0, 0, 0, 0);
                SpawnPlayer(playerid);
                SetPlayerSkin(playerid, PlayerInfo[playerid][Skin]);
                SetPlayerScore(playerid, PlayerInfo[playerid][Level]);
                GivePlayerMoney(playerid, PlayerInfo[playerid][Money]);
            }
            else if(PlayerInfo[playerid][Banned] == 1)
            {
                SendClientMessage(playerid, COLOR_RED, "YOU HAVE BEEN BANNED FROM THIS SERVER.");
                Kick(playerid);
            }
Reply
#10

Quote:
Originally Posted by nogh445
Посмотреть сообщение
For me the x, y, and z positions keep going back to 0.00000 in my player file when I /q
pawn Код:
public OnPlayerDisconnect(playerid, reason)
{
    if(fexist(UserPath(playerid)))
    {
        GetPlayerPos(playerid, PlayerInfo[playerid][PosX], PlayerInfo[playerid][PosY], PlayerInfo[playerid][PosZ]);
        GetPlayerFacingAngle(playerid, PlayerInfo[playerid][PosA]);
        file_Open(UserPath(playerid));
        file_SetVal("Admin", PlayerInfo[playerid][Admin]);
        file_SetVal("Health", PlayerInfo[playerid][Health]);
        file_SetVal("Armor", PlayerInfo[playerid][Armor]);
        file_SetVal("Money", PlayerInfo[playerid][Money]);
        file_SetVal("Skin", PlayerInfo[playerid][Skin]);
        file_SetVal("Level", PlayerInfo[playerid][Level]);
        file_SetVal("Banned", PlayerInfo[playerid][Banned]);
        file_SetFloat("Posx", PlayerInfo[playerid][Posx]);
        file_SetFloat("Posy", PlayerInfo[playerid][Posy]);
        file_SetFloat("Posz", PlayerInfo[playerid][Posz]);
        file_Close();
    }
    return 1;
}
This is on player disconnect..
I'm not sure why it is not saving them.
You should get the player's position, i edited the code above check it.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)