[Tutorial] YINI Tutorial - Optimised - Easy-to-use
#1

YINI Tutorial
(I know there are plenty of these, but I believe this is to be the most optimised one released.)

Step 1:
Open a new Pawno file and press New.
Delete all of the filterscript details and add this under a_samp include:
pawn Code:
#include <ysi\y_ini>
Next is to add the following code:
pawn Code:
#define DIALOG_LOGIN 0 // Dialog for Login
#define DIALOG_REGISTER 1 // Dialog for Register

// ========== COLOURS ===========
#define COL_WHITE "{FFFFFF}" // Colours
#define COL_RED "{F81414}"
#define COL_GREEN "{00FF22}"
#define COL_LIGHTBLUE "{00CED1}"

#define PATH "/Users/%s.ini" // User Path to save files.
Step 2:

Players enum:
pawn Code:
enum pInfo
{
    pPass,
    pCash,
    pScore,
    pInterior,
    Float:pPosX,
    Float:pPosY,
    Float:pPosZ,
    Float:pPosA,
    pVW,
}
new PlayerInfo[MAX_PLAYERS][pInfo];
Here, we're saving the players variables.

Now, under OnPlayerRequestClass, add this:
pawn Code:
SetUpPlayer(playerid);
Why? I'll explain this a bit later during the tutorial.

Step 3:
Under OnPlayerConnect:
pawn Code:
if(fexist(UserPath(playerid)))
    {
        INI_ParseFile(UserPath(playerid), "LoadUser_%s", .bExtra = true, .extra = playerid);
        ShowPlayerDialog(playerid, 2, DIALOG_STYLE_PASSWORD,""COL_WHITE"Login",""COL_WHITE"{13A2AF}We have found your account in the database!\n{35A813}Please proceed with your login.\n\n{FFFFFF}Type your password below to login.","Login","Quit");
    }
    else
    {
        ShowPlayerDialog(playerid, 1, DIALOG_STYLE_PASSWORD,""COL_WHITE"Register",""COL_WHITE"{13A2AF}We haven't found your account in the database!\n{35A813}Please proceed with your password you wish to use.\n\n{FFFFFF}Type your password below.","Login","Quit");
    }
Here we're parsing(loading) the users account, we load it before the dialog simply because, we need to load the users password then see if he gets the input right.
Under OnPlayerDisconnect:
pawn Code:
SaveUser(playerid);
(Again, I'll explain this a bit later)

Step 4:

OnDialogResponse:
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, "Registering a new account","You have entered an invalid password.\nType your password below to register a new account.","Register","Quit");
                NewUser(playerid, udb_hash(inputtext));
            }
        }
       
        case DIALOG_LOGIN:
        {
            if(!response) return Kick ( playerid );
            if(response)
            {
                if(udb_hash(inputtext) == PlayerInfo[playerid][pPass]) return 1;
                else
                {
                    ShowPlayerDialog(playerid, 2, DIALOG_STYLE_PASSWORD,""COL_WHITE"Login",""COL_WHITE"{13A2AF}We have found your account in the database!\n{35A813}But you've entered the wrong password\n\n{FFFFFF}Type your password again below to login.","Login","Quit");
                }
            }
        }
    }
    return 1;
}
Here "if(udb_hash(inputtext) == PlayerInfo[playerid][pPass]) return 1;" we return one so it sends them to OnPlayerRequestClass where our "SetUpPlayer(player);" is.

Step 5:
All this is self explanatory:
pawn Code:
#define User_Path "Users/%s.ini"
UserPath(playerid)
{
    new playername[MAX_PLAYER_NAME + 6 + 4];
    format(playername, sizeof(playername), User_Path, GetPlayerNameEx(playerid));
    return playername;
}
GetPlayerNameEx(playerid)
{
    new string[MAX_PLAYER_NAME], str[MAX_PLAYER_NAME];
    GetPlayerName(playerid, string, MAX_PLAYER_NAME);
    strmid(str, string, 0, strlen(string), MAX_PLAYER_NAME);
    for(new i = 0; i < MAX_PLAYER_NAME; i++)
    {
        if(str[i] == '_') str[i] = ' ';
    }
    return str;
}
udb_hash(buf[]) {
    new length=strlen(buf);
    new s1 = 1;
    new s2 = 0;
    new n;
    for (n=0; n<length; n++)
    {
       s1 = (s1 + buf[n]) % 65521;
       s2 = (s2 + s1)     % 65521;
    }
    return (s2 << 16) + s1;
}
forward LoadUser_Statistics(playerid, name[], value[]);
public LoadUser_Statistics(playerid, name[], value[])
{
    INI_Int("Password", PlayerInfo[playerid][pPass]);
    INI_Int("Cash", PlayerInfo[playerid][pCash]);
    INI_Int("Score", PlayerInfo[playerid][pScore]);
    INI_Int("Interior", PlayerInfo[playerid][pInterior]);
    INI_Float("PosX", PlayerInfo[playerid][pPosX]);
    INI_Float("PosY", PlayerInfo[playerid][pPosY]);
    INI_Float("PosZ", PlayerInfo[playerid][pPosZ]);
    INI_Float("PosA", PlayerInfo[playerid][pPosA]);
    INI_Int("VirtualWorld", PlayerInfo[playerid][pVW]);
    return 1;
}
SaveUser(playerid)
{
    new INI:File = INI_Open(UserPath(playerid));
    INI_SetTag(File,"Statistics");
    INI_WriteInt(File, "Cash", PlayerInfo[playerid][pCash]);
    INI_WriteInt(File, "Score", PlayerInfo[playerid][pScore]);
    INI_WriteInt(File,"Interior", GetPlayerInterior(playerid));
    GetPlayerPos(playerid, PlayerInfo[playerid][pPosX], PlayerInfo[playerid][pPosY], PlayerInfo[playerid][pPosZ]);
    INI_WriteFloat(File,"PosX", PlayerInfo[playerid][pPosX]);
    INI_WriteFloat(File,"PosY", PlayerInfo[playerid][pPosY]);
    INI_WriteFloat(File,"PosZ", PlayerInfo[playerid][pPosZ]);
    GetPlayerFacingAngle(playerid, PlayerInfo[playerid][pPosA]);
    INI_WriteFloat(File,"PosA", PlayerInfo[playerid][pPosA]);
    INI_WriteInt(File,"VirtualWorld", GetPlayerVirtualWorld(playerid));
    INI_Close(File);
    return 1;
}
NewUser(playerid, password)
{
    new INI:File = INI_Open(UserPath(playerid));
    INI_SetTag(File,"Statistics");
    INI_WriteInt(File, "Password", password);
    INI_WriteInt(File, "Cash", 500);
    INI_WriteInt(File, "Score", 0);
    INI_WriteInt(File, "Interior", 0);
    INI_WriteFloat(File, "PosX", 1543.2990);
    INI_WriteFloat(File, "PosY", -1669.3713);
    INI_WriteFloat(File, "PosZ", 13.5562);
    INI_WriteFloat(File, "PosA", 88.9816);
    INI_WriteInt(File, "VirtualWorld", 0);
    INI_Close(File);

    INI_ParseFile(UserPath(playerid), "LoadUser_%s", .bExtra = true, .extra = playerid);
}
SetUpPlayer(playerid)
{
    SetSpawnInfo(playerid, 0, 26, PlayerInfo[playerid][pPosX],PlayerInfo[playerid][pPosY],PlayerInfo[playerid][pPosZ],PlayerInfo[playerid][pPosA],0,0,0,0,0,0);
    SetPlayerInterior(playerid, PlayerInfo[playerid][pInterior]);
    SetPlayerVirtualWorld(playerid, PlayerInfo[playerid][pVW]);
    SpawnPlayer(playerid);
   
    SetPlayerFacingAngle(playerid, PlayerInfo[playerid][pPosA]);
    GivePlayerMoney(playerid, PlayerInfo[playerid][pCash]);
    SetPlayerScore(playerid, PlayerInfo[playerid][pScore]);
    return 1;
}
Okay so, as I said, we've got "SetUpPlayer" as you can see, it sets the player up so you bypass the SA:MP spectate bug. "NewUser" writes the users file out so it can then continue to log him in. "SavePlayer" saves the player.

Why have I done this?
1) Easy to make alterations to Files (Optimised for Easy Alterations)
2) Server Sided lag is reduced.

Credits:
- IceCube!: Helping out.
- ******: YSI.
- Binx: Writing the code with help from IceCube!
Reply
#2

Good Job , Thanks for the tutorial .
Reply
#3

pawn Code:
GetPlayerNameEx(playerid)
{
    new string[MAX_PLAYER_NAME];
    GetPlayerName(playerid, string, MAX_PLAYER_NAME);
    for(new i = 0; i < MAX_PLAYER_NAME; i++)
    {
        if(string[i] == '_') string[i] = ' ';
    }
    return string;
}
It will work, no ?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)