[Tutorial] Login/Register [Y_INI][WHIRLPOOL][UPDATE SERIES]
#21

Quote:
Originally Posted by DragonZafiro
View Post
why the "INI_Load" and "INI_ParseFile" functions needs a lot of data size on compile?
when i use it, my final .amx gets this size:


when i remove it:


and yes, are that functions, took me a while to realize it was
I couldn't find much on the matter and I never realised it myself, so I'm taking Crayder's word for it.

Quote:
Originally Posted by MicroKyrr
View Post
Also , I get a "wrong password error" when i enter a correct password.
Are you hashing the user's input in the login dialogue or are you checking the stored password against the user's input in plain text? Keep in mind that the user's password is saved as a hash and the user's input is plain text meaning that you have to hash the user's input and check that hash against the stored one.

EDIT: To add to Crayder's recommendation to use SQL, I completely agree. You can go ahead and use file processing as your main medium for storing essential user data and soon realise that it has a lot of restrictions compared to SQL. Nevertheless, it's worth knowing about using file processing this way and it is best understood by practically using it yourself; in my opinion.
Reply
#22

Quote:
Originally Posted by AndySedeyn
View Post
I couldn't find much on the matter and I never realised it myself, so I'm taking Crayder's word for it.



Are you hashing the user's input in the login dialogue or are you checking the stored password against the user's input in plain text? Keep in mind that the user's password is saved as a hash and the user's input is plain text meaning that you have to hash the user's input and check that hash against the stored one.

EDIT: To add to Crayder's recommendation to use SQL, I completely agree. You can go ahead and use file processing as your main medium for storing essential user data and soon realise that it has a lot of restrictions compared to SQL. Nevertheless, it's worth knowing about using file processing this way and it is best understood by practically using it yourself; in my opinion.
Here's the code
PHP Code:
    case DIALOG_LOGIN:
    {
        if(!
response) return Kick(playerid);
        else
        {
            new 
hashpass[129];
            
WP_Hash(hashpasssizeof(hashpass), inputtext);
            if(!
strcmp(hashpassPlayerInfo[playerid][Password]))
            {
                
ShowPlayerDialog(playeridDIALOG_LOGINDIALOG_STYLE_PASSWORD"Login Panel""{FF6600}You have entered an incorrect password of this account!\nPlease enter the correct password to continue!""Login""Quit");
            }
            else
            {
                
SetPlayerScore(playeridPlayerInfo[playerid][Score]);
                
GivePlayerMoney(playeridPlayerInfo[playerid][Cash]);
                
SendClientMessage(playeridGREEN"[SERVER]: You have successfully logged in! Welcome back");
                
PlayerInfo[playerid][Authenticated] = true;
                
TogglePlayerSpectating(playeridfalse);
            }
            return 
1;
            }
        }
    }
    return 
0;

Also , I am not good at SQlite and mysql
Reply
#23

Quote:
Originally Posted by MicroKyrr
View Post
Here's the code
PHP Code:
    case DIALOG_LOGIN:
    {
        if(!
response) return Kick(playerid);
        else
        {
            new 
hashpass[129];
            
WP_Hash(hashpasssizeof(hashpass), inputtext);
            if(
strcmp(hashpassPlayerInfo[playerid][Password], false) != 0)
            {
                
ShowPlayerDialog(playeridDIALOG_LOGINDIALOG_STYLE_PASSWORD"Login Panel""{FF6600}You have entered an incorrect password of this account!\nPlease enter the correct password to continue!""Login""Quit");
            }
            else
            {
                
SetPlayerScore(playeridPlayerInfo[playerid][Score]);
                
GivePlayerMoney(playeridPlayerInfo[playerid][Cash]);
                
SendClientMessage(playeridGREEN"[SERVER]: You have successfully logged in! Welcome back");
                
PlayerInfo[playerid][Authenticated] = true;
                
TogglePlayerSpectating(playeridfalse);
            }
            return 
1;
            }
        }
    }
    return 
0;

Also , I am not good at SQlite and mysql
Are you saving the player's password correctly? Can you show me the 'Password' enumerator and the function responsible for saving the data?
Reply
#24

Quote:
Originally Posted by AndySedeyn
View Post
Are you saving the player's password correctly? Can you show me the 'Password' enumerator and the function responsible for saving the data?
PHP Code:
enum USER_DATA
{
    
Password[129],
    
bool:Authenticated
// Hiding the others. 
PHP Code:
public LoadPlayerData_user(playeridname[], value[])
{
    
INI_String("Password"PlayerInfo[playerid][Password], 129);
    return 
1;

Reply
#25

Quote:
Originally Posted by AndySedeyn
View Post
I couldn't find much on the matter and I never realised it myself, so I'm taking Crayder's word for it.



Are you hashing the user's input in the login dialogue or are you checking the stored password against the user's input in plain text? Keep in mind that the user's password is saved as a hash and the user's input is plain text meaning that you have to hash the user's input and check that hash against the stored one.

EDIT: To add to Crayder's recommendation to use SQL, I completely agree. You can go ahead and use file processing as your main medium for storing essential user data and soon realise that it has a lot of restrictions compared to SQL. Nevertheless, it's worth knowing about using file processing this way and it is best understood by practically using it yourself; in my opinion.
Oh well, whatever, I will keep using y_ini 'til my server becomes popular
Thanks for help
Reply
#26

Since a few people are having problems or some don't know how to use SQLite:

SQLite:
pawn Code:
// ** INCLUDES

#include <a_samp>

// ** NATIVES

// *** WHIRLPOOL

native WP_Hash(buffer[], len, const str[]);

// ** DEFINES

// *** GENERAL

#define MAX_LOGIN_ATTEMPTS 3

// *** FUNCTIONS

#define isnull(%1) ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))
#define strcat_format(%0,%1,%2) format(%0[strlen(%0)], %1 - strlen(%0), %2)

// *** DIALOGS

#define DIALOG_REGISTER 0
#define DIALOG_CONFIRM_REGISTER 1
#define DIALOG_LOGIN 2

// *** PLAYER RESET TYPES

#define PLAYER_RESET_CONNECT 0
#define PLAYER_RESET_DISCONNECT 1

// *** DATABASE

// **** PATHS

#define DATABASE_PATH "database.db"

// **** TABLES

// ***** USERS

// ****** GENERAL

#define TABLE_USERS "USERS"

// ****** CONTENT

#define USER_SQL_ID "sql_id"
#define USER_NAME "name"
#define USER_PASSWORD "password"
#define USER_IP_ADDRESS "ip_address"
#define USER_SCORE "score"
#define USER_CASH "cash"
#define USER_ADMIN_LEVEL "admin_level"

// ** COLORS

// *** GENERAL

#define COLOR_WHITE 0xFFFFFFFF
#define COL_WHITE "{FFFFFF}"

#define COLOR_RED 0xFF0000FF
#define COL_RED "{FF0000}"

// *** CUSTOM

#define COLOR_ACCOUNT 0x37E9A0FF
#define COL_ACCOUNT "{37E9A0}"

// ** ARRAYS AND ENUMERATORS
   
enum eUserInfo
{
    user_info_sql_id,
    user_info_score,
    user_info_cash,
    user_info_admin_level
}

new aUserInfo[MAX_PLAYERS][eUserInfo];

// ** VARIABLES

// *** GLOBAL VARIABLES

// **** DATABASE

new DB:database;

// *** PER-PLAYER VARIABLES

// **** GENERAL

new pPasswordHash[MAX_PLAYERS][129],
pLoginAttempts[MAX_PLAYERS];

// **** PLAYER STATES

new bool:psSignedIn[MAX_PLAYERS] = false;

// ** HOOKS

stock Hook_SetPlayerScore(playerid, score)
{
    aUserInfo[playerid][user_info_score] = score;
    return SetPlayerScore(playerid, score);
}

#if defined _ALS_SetPlayerScore
    #undef SetPlayerScore
#else
    #define _ALS_SetPlayerScore
#endif
#define SetPlayerScore Hook_SetPlayerScore

// ** MAIN

main()
{
    print("Loaded \"sqlite_login_system.amx\".");
}

// ** CALLBACKS

public OnGameModeInit()
{  
    LoadDatabase();
    return 1;
}

public OnGameModeExit()
{
    db_close(database);
    return 1;
}

public OnPlayerConnect(playerid)
{  
    TogglePlayerSpectating(playerid, true);

    ResetPlayerVariables(playerid, PLAYER_RESET_CONNECT);

    new query[300], DBResult:result;
    strcat(query, "SELECT `"#USER_SQL_ID"`");
    strcat(query, " FROM `"#TABLE_USERS"`");
    strcat_format(query, sizeof(query), " WHERE `"#USER_NAME"` = '%q' COLLATE NOCASE LIMIT 1", ReturnPlayerName(playerid));
    result = db_query(database, query);

    if(db_num_rows(result))
    {
        aUserInfo[playerid][user_info_sql_id] = db_get_field_assoc_int(result, USER_SQL_ID);

        ShowLoginDialog(playerid);
    }
    else
    {
        ShowRegisterDialog(playerid);
    }

    db_free_result(result);
    return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
    if(IsPlayerSignedIn(playerid))
    {
        new query[400];
        strcat(query, "UPDATE `"#TABLE_USERS"` SET ");
        strcat_format(query, sizeof(query), "`"#USER_SCORE"` = '%d',", aUserInfo[playerid][user_info_score]);
        strcat_format(query, sizeof(query), "`"#USER_CASH"` = '%d',", aUserInfo[playerid][user_info_cash]);
        strcat_format(query, sizeof(query), "`"#USER_ADMIN_LEVEL"` = '%d'", aUserInfo[playerid][user_info_admin_level]);
        strcat_format(query, sizeof(query), " WHERE `"#USER_SQL_ID"` = '%d'", aUserInfo[playerid][user_info_sql_id]);
        db_query(database, query);
    }

    ResetPlayerVariables(playerid, PLAYER_RESET_DISCONNECT);
    return 1;
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    switch(dialogid)
    {
        case DIALOG_REGISTER:
        {
            if(!response)
            {
                KickPlayer(playerid);
            }
            else if(response)
            {
                if(isnull(inputtext))
                {
                    ShowRegisterDialog(playerid);
                }
                else if(strlen(inputtext) < 3)
                {
                    ShowRegisterDialog(playerid);

                    SendClientMessage(playerid, COLOR_RED, "Your password is too short, please try again.");
                }
                else if(strlen(inputtext) > 20)
                {
                    ShowRegisterDialog(playerid);

                    SendClientMessage(playerid, COLOR_RED, "Your password is too long, please try again.");
                }
                else
                {
                    WP_Hash(pPasswordHash[playerid], 129, inputtext);

                    ShowConfirmPasswordDialog(playerid);
                }
            }
        }
        case DIALOG_CONFIRM_REGISTER:
        {
            if(!response)
            {
                ShowRegisterDialog(playerid);
            }
            else if(response)
            {
                new hash[129];
                WP_Hash(hash, sizeof(hash), inputtext);

                if(isnull(inputtext))
                {
                    ShowConfirmPasswordDialog(playerid);
                }
                else if(!strcmp(pPasswordHash[playerid], hash, true))
                {
                    new name[MAX_PLAYER_NAME];
                    GetPlayerName(playerid, name, MAX_PLAYER_NAME);

                    new query_1[500];
                    strcat(query_1, "INSERT INTO `"#TABLE_USERS"` (");
                    strcat(query_1, "`"#USER_NAME"`,");
                    strcat(query_1, "`"#USER_PASSWORD"`,");
                    strcat(query_1, "`"#USER_IP_ADDRESS"`,");
                    strcat(query_1, "`"#USER_SCORE"`,");
                    strcat(query_1, "`"#USER_CASH"`,");
                    strcat(query_1, "`"#USER_ADMIN_LEVEL"`");
                    strcat(query_1, ") VALUES (");

                    strcat_format(query_1, sizeof(query_1), "'%q',", name); // USER_NAME
                    strcat_format(query_1, sizeof(query_1), "'%q',", hash); // USER_PASSWORD
                    strcat_format(query_1, sizeof(query_1), "'%q',", GetPlayerIP(playerid)); // USER_IP_ADDRESS
                    strcat(query_1, "'0',"); // USER_SCORE
                    strcat(query_1, "'0',"); // USER_CASH
                    strcat(query_1, "'0')"); // USER_ADMIN_LEVEL
                    db_query(database, query_1);

                    new query_2[300], DBResult:result;
                    strcat(query_2, "SELECT `"#USER_SQL_ID"`");
                    strcat(query_2, " FROM `"#TABLE_USERS"`");
                    strcat_format(query_2, sizeof(query_2), " WHERE `"#USER_NAME"` = '%q' COLLATE NOCASE LIMIT 1", name);
                    result = db_query(database, query_2);

                    aUserInfo[playerid][user_info_sql_id] = db_get_field_assoc_int(result, USER_SQL_ID);

                    db_free_result(result);

                    TogglePlayerSpectating(playerid, false);

                    psSignedIn[playerid] = true;

                    SendClientMessage(playerid, COLOR_ACCOUNT, "You have successfully registered your account.");
                }
                else
                {
                    ShowConfirmPasswordDialog(playerid);

                    SendClientMessage(playerid, COLOR_RED, "That's not the same password as the first one.");
                }
            }
        }
        case DIALOG_LOGIN:
        {
            if(!response)
            {
                KickPlayer(playerid);
            }
            else if(response)
            {
                if(isnull(inputtext))
                {
                    ShowLoginDialog(playerid);
                }
                else
                {
                    new hash[129];
                    WP_Hash(hash, sizeof(hash), inputtext);

                    new query_1[500], DBResult:result;
                    strcat(query_1, "SELECT `"#USER_PASSWORD"`,");
                    strcat(query_1, "`"#USER_IP_ADDRESS"`,");
                    strcat(query_1, "`"#USER_SCORE"`,");
                    strcat(query_1, "`"#USER_CASH"`,");
                    strcat(query_1, "`"#USER_ADMIN_LEVEL"`");
                    strcat(query_1, " FROM `"#TABLE_USERS"`");
                    strcat(query_1, " WHERE `"#USER_SQL_ID"` = '%d' COLLATE NOCASE LIMIT 1", aUserInfo[playerid][user_info_sql_id]);
                    result = db_query(database, query_1);

                    if(db_num_rows(result))
                    {
                        new real_hash[129];
                        db_get_field_assoc(result, USER_PASSWORD, real_hash, sizeof(real_hash));

                        if(!isnull(real_hash) && !strcmp(real_hash, hash, true))
                        {
                            new ip_address[16], current_ip_address[16];
                            GetPlayerIp(playerid, ip_address, sizeof(ip_address));

                            db_get_field_assoc(result, USER_IP_ADDRESS, current_ip_address, sizeof(current_ip_address));

                            if(strcmp(ip_address, current_ip_address, true))
                            {
                                new query_2[128];
                                strcat(query_2, "UPDATE `"#TABLE_USERS"` SET ");
                                strcat_format(query_2, sizeof(query_2), "`"#USER_IP_ADDRESS"` = '%q'", ip_address);
                                strcat_format(query_2, sizeof(query_2), " WHERE `"#USER_SQL_ID"` = '%d'", aUserInfo[playerid][user_info_sql_id]);
                                db_query(database, query_2);
                            }

                            TogglePlayerSpectating(playerid, false);

                            SetPlayerScore(playerid, db_get_field_assoc_int(result, USER_SCORE));
                            SetPlayerMoney(playerid, db_get_field_assoc_int(result, USER_CASH));

                            aUserInfo[playerid][user_info_admin_level] = db_get_field_assoc_int(result, USER_ADMIN_LEVEL);

                            psSignedIn[playerid] = true;

                            SendClientMessage(playerid, COLOR_ACCOUNT, "You have successfully logged into your account.");
                        }
                        else
                        {
                            new string[144];
                            pLoginAttempts[playerid] ++;

                            format(string, sizeof(string), "Incorrect password. Attempts left: %d.", (MAX_LOGIN_ATTEMPTS - pLoginAttempts[playerid]));
                            SendClientMessage(playerid, COLOR_RED, string);

                            if(pLoginAttempts[playerid] == MAX_LOGIN_ATTEMPTS)
                            {
                                KickPlayer(playerid);
                            }
                            else
                            {
                                ShowLoginDialog(playerid);
                            }
                        }
                    }

                    db_free_result(result);
                }
            }
        }
    }
    return 1;
}

// ** FUNCTIONS

// *** LOAD COMPONENTS

stock LoadDatabase()
{
    database = db_open(DATABASE_PATH);

    new query_1[400];
    strcat(query_1, "CREATE TABLE IF NOT EXISTS `"#TABLE_USERS"` (");
    strcat(query_1, "`"#USER_SQL_ID"` INTEGER PRIMARY KEY AUTOINCREMENT,");
    strcat(query_1, "`"#USER_NAME"` TEXT,");
    strcat(query_1, "`"#USER_PASSWORD"` TEXT,");
    strcat(query_1, "`"#USER_IP_ADDRESS"` TEXT,");
    strcat(query_1, "`"#USER_SCORE"` INTEGER,");
    strcat(query_1, "`"#USER_CASH"` INTEGER,");
    strcat(query_1, "`"#USER_ADMIN_LEVEL"` INTEGER)");
    db_query(database, query_1);
    return 1;
}

// *** LOAD PER-PLAYER VARIABLES

stock ResetPlayerVariables(playerid, reset_type)
{
    switch(reset_type)
    {
        case PLAYER_RESET_CONNECT:
        {
            // ** ARRAYS AND ENUMERATORS

            aUserInfo[playerid][user_info_sql_id] = 0;
            aUserInfo[playerid][user_info_score] = 0;
            aUserInfo[playerid][user_info_cash] = 0;
            aUserInfo[playerid][user_info_admin_level] = 0;
        }
        case PLAYER_RESET_DISCONNECT:
        {
            // ** GENERAL

            pLoginAttempts[playerid] = 0;

            // ** PLAYER STATES

            psSignedIn[playerid] = false;
        }
    }
    return 1;
}

// *** GENERAL

stock GetPlayerIP(playerid)
{
    new ip_address[16];
    GetPlayerIp(playerid, ip_address, sizeof(ip_address));
    return ip_address;
}

stock ShowRegisterDialog(playerid)
{
    new string[256];
    strcat_format(string, sizeof(string), "{FFFFFF}Welcome, %s!\n\n", ReturnPlayerName(playerid));
    strcat(string, "You must register to play here.");
    ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Register", string, "Next", "Close");
    return 1;
}

stock ShowConfirmPasswordDialog(playerid)
{
    new string[256];
    strcat_format(string, sizeof(string), "{FFFFFF}Welcome, %s!\n\n", ReturnPlayerName(playerid));
    strcat(string, "You must confirm your registration to play here.");
    ShowPlayerDialog(playerid, DIALOG_CONFIRM_REGISTER, DIALOG_STYLE_PASSWORD, "Confirm Registration", string, "Register", "Back");
    return 1;
}

stock ShowLoginDialog(playerid)
{
    new string[256];
    strcat_format(string, sizeof(string), "{FFFFFF}Welcome back, %s!\n\n", ReturnPlayerName(playerid));
    strcat(string, "You must log into play here.");
    ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Log In", string, "Log In", "Close");
    return 1;
}

stock ReturnPlayerName(playerid)
{
    new name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, name, MAX_PLAYER_NAME);
    return name;
}

stock SetPlayerMoney(playerid, cash)
{
    aUserInfo[playerid][user_info_cash] = cash;

    ResetPlayerMoney(playerid);
    return GivePlayerMoney(playerid, cash);
}

stock KickPlayer(playerid)
{
    SetTimerEx("KickPlayerAction", 100, false, "i", playerid);
    return 1;
}

forward KickPlayerAction(playerid);
public KickPlayerAction(playerid)
{
    return Kick(playerid);
}

forward bool:IsPlayerSignedIn(playerid);
public bool:IsPlayerSignedIn(playerid)
{
    return psSignedIn[playerid];
}
Y_INI - Dialogs:
pawn Code:
// ** INCLUDES

#include <a_samp>
#include <YSI\y_ini>

// ** NATIVES

// *** WHIRLPOOL

native WP_Hash(buffer[], len, const str[]);

// ** UN-DEFINES

#undef isnull

// ** DEFINES

// *** FUNCTIONS

#define isnull(%1) ((!(%1[0])) || (((%1[0]) == '\1') && (!(%1[1]))))

// *** DIALOGS

#define DIALOG_REGISTER 0
#define DIALOG_LOGIN 1

// *** DATABASE

#define USER_TAG "player_data"
#define USER_PASSWORD "password"
#define USER_SCORE "score"
#define USER_CASH "cash"
#define USER_KILLS "kills"
#define USER_DEATHS "deaths"
#define USER_ADMIN_LEVEL "admin_level"

// ** ARRAYS AND ENUMERATORS

enum eUserInfo
{
    user_password[129],
    user_score,
    user_cash,
    user_kills,
    user_deaths,
    user_admin_level
}

new aUserInfo[MAX_PLAYERS][eUserInfo];

// ** VARIABLES

// *** PER-PLAYER VARIABLES

// **** PLAYER STATES

new bool:psSignedIn[MAX_PLAYERS] = false;

// ** MAIN

main()
{
    print("Loaded \"ini_login_system.amx\".");
}

// ** CALLBACKS

public OnGameModeInit()
{
    return 1;
}

public OnGameModeExit()
{
    return 1;
}

public OnPlayerConnect(playerid)
{
    if(fexist(UserPath(playerid)))
    {
        INI_ParseFile(UserPath(playerid), "LoadUserData", .bExtra = true, .extra = playerid);

        ShowLoginDialog(playerid, "");
    }
    else
    {
        ShowRegisterDialog(playerid, "");
    }
    return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
    if(IsPlayerSignedIn(playerid))
    {
        new INI:file = INI_Open(UserPath(playerid));
        INI_SetTag(file, USER_TAG);

        INI_WriteInt(file, USER_SCORE, GetPlayerScore(playerid));
        INI_WriteInt(file, USER_CASH, GetPlayerMoney(playerid));
        INI_WriteInt(file, USER_KILLS, aUserInfo[playerid][user_kills]);
        INI_WriteInt(file, USER_DEATHS, aUserInfo[playerid][user_deaths]);
        INI_WriteInt(file, USER_ADMIN_LEVEL, aUserInfo[playerid][user_admin_level]);

        INI_Close(file);
    }

    ResetPlayerVariables(playerid);
    return 1;
}

public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
    switch(dialogid)
    {
        case DIALOG_REGISTER:
        {
            if(!response)
            {
                KickPlayer(playerid);
            }
            else if(response)
            {
                if(isnull(inputtext))
                {
                    ShowRegisterDialog(playerid, "Enter a password.");
                }
                else
                {
                    new length = strlen(inputtext);
                    if(length < 6)
                    {
                        ShowRegisterDialog(playerid, "Password is too short.");
                    }
                    else if(length > 20)
                    {
                        ShowRegisterDialog(playerid, "Password is too long.");
                    }
                    else
                    {
                        new hash[129];
                        WP_Hash(hash, sizeof(hash), inputtext);

                        new INI:file = INI_Open(UserPath(playerid));
                        INI_SetTag(file, USER_TAG);

                        INI_WriteString(file, USER_PASSWORD, hash);
                        INI_WriteInt(file, USER_SCORE, 0);
                        INI_WriteInt(file, USER_CASH, 0);
                        INI_WriteInt(file, USER_KILLS, 0);
                        INI_WriteInt(file, USER_DEATHS, 0);
                        INI_WriteInt(file, USER_ADMIN_LEVEL, 0);

                        INI_Close(file);

                        psSignedIn[playerid] = true;

                        SendClientMessage(playerid, -1, "You have successfully registered your account.");
                    }
                }
            }
        }
        case DIALOG_LOGIN:
        {
            if(!response)
            {
                KickPlayer(playerid);
            }
            else if(response)
            {
                if(isnull(inputtext))
                {
                    ShowLoginDialog(playerid, "Enter a password.");
                }
                else
                {
                    new hash[129];
                    WP_Hash(hash, sizeof(hash), inputtext);

                    if(!strcmp(aUserInfo[playerid][user_password], hash, false))
                    {
                        INI_ParseFile(UserPath(playerid), "LoadUserData", .bExtra = true, .extra = playerid);

                        SetPlayerScore(playerid, aUserInfo[playerid][user_score]);
                        GivePlayerMoney(playerid, aUserInfo[playerid][user_cash]);

                        psSignedIn[playerid] = true;

                        SendClientMessage(playerid, -1, "You have successfully logged in to your account.");
                    }
                    else
                    {
                        ShowLoginDialog(playerid, "Incorrect password.");
                    }
                }
            }
        }
    }
    return 1;
}

// ** FUNCTIONS

stock ResetPlayerVariables(playerid)
{
    // ** ARRAYS AND ENUMERATORS

    aUserInfo[playerid][user_password][0] = EOS;
    aUserInfo[playerid][user_score] = 0;
    aUserInfo[playerid][user_cash] = 0;
    aUserInfo[playerid][user_kills] = 0;
    aUserInfo[playerid][user_deaths] = 0;
    aUserInfo[playerid][user_admin_level] = 0;

    // ** PER-PLAYER VARIABLES

    // *** PLAYER STATES

    psSignedIn[playerid] = false;
    return 1;
}

forward LoadUserData(playerid, name[], value[]);
public LoadUserData(playerid, name[], value[])
{
    INI_String(USER_PASSWORD, aUserInfo[playerid][user_password], 129);
    INI_Int(USER_SCORE, aUserInfo[playerid][user_score]);
    INI_Int(USER_CASH, aUserInfo[playerid][user_cash]);
    INI_Int(USER_KILLS, aUserInfo[playerid][user_kills]);
    INI_Int(USER_DEATHS, aUserInfo[playerid][user_deaths]);
    INI_Int(USER_ADMIN_LEVEL, aUserInfo[playerid][user_admin_level]);
    return 1;
}

stock ShowRegisterDialog(playerid, error[])
{
    new string[256];
    strcat(string, "Welcome. This account is not registered.\n");
    strcat(string, "Enter a password below to register an account.");
   
    if(!isnull(error))
    {
        strcat(string, "\n\n{FF0000}");
        strcat(string, error);
    }

    ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Register", string, "Register", "Close");
    return 1;
}

stock ShowLoginDialog(playerid, error[])
{
    new string[256];
    strcat(string, "Welcome back. This account is already registered.\n");
    strcat(string, "Insert your password to log into your account.");

    if(!isnull(error))
    {
        strcat(string, "\n\n{FF0000}");
        strcat(string, error);
    }

    ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login", string, "Login", "Close");
    return 1;
}

stock KickPlayer(playerid)
{
    SetTimerEx("KickPlayerAction", 100, false, "i", playerid);
    return 1;
}

forward KickPlayerAction(playerid);
public KickPlayerAction(playerid)
{
    Kick(playerid);
    return 1;
}

stock UserPath(playerid)
{
    new string[50], name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, name, sizeof(name));

    format(string, sizeof(string), "/Users/%s.ini", name);
    return string;
}

forward bool:IsPlayerSignedIn(playerid);
public bool:IsPlayerSignedIn(playerid)
{
    return psSignedIn[playerid];
}
Y_INI - CMDs:
pawn Code:
// ** INCLUDES

#include <a_samp>
#include <YSI\y_ini>
#include <sscanf>
#include <zcmd>

// ** NATIVES

// *** WHIRLPOOL

native WP_Hash(buffer[], len, const str[]);

// ** DEFINES

// *** DATABASE

#define USER_TAG "player_data"
#define USER_PASSWORD "password"
#define USER_SCORE "score"
#define USER_CASH "cash"
#define USER_KILLS "kills"
#define USER_DEATHS "deaths"
#define USER_ADMIN_LEVEL "admin_level"

// ** ARRAYS AND ENUMERATORS

enum eUserInfo
{
    user_password[129],
    user_score,
    user_cash,
    user_kills,
    user_deaths,
    user_admin_level
}

new aUserInfo[MAX_PLAYERS][eUserInfo];

// ** VARIABLES

// *** PER-PLAYER VARIABLES

// **** PLAYER STATES

new bool:sSignedIn[MAX_PLAYERS] = false;

// ** MAIN

main()
{
    print("Loaded \"cmd_ini_login_system.amx\".");
}

// ** CALLBACKS

public OnGameModeInit()
{
    return 1;
}

public OnGameModeExit()
{
    return 1;
}

public OnPlayerDisconnect(playerid, reason)
{
    if(IsPlayerSignedIn(playerid))
    {
        new INI:file = INI_Open(UserPath(playerid));
        INI_SetTag(file, USER_TAG);
        INI_WriteInt(file, USER_SCORE, GetPlayerScore(playerid));
        INI_WriteInt(file, USER_CASH, GetPlayerMoney(playerid));
        INI_WriteInt(file, USER_KILLS, aUserInfo[playerid][user_kills]);
        INI_WriteInt(file, USER_DEATHS, aUserInfo[playerid][user_deaths]);
        INI_WriteInt(file, USER_ADMIN_LEVEL, aUserInfo[playerid][user_admin_level]);
        INI_Close(file);
    }

    ResetPlayerVariables(playerid);
    return 1;
}

// ** COMMANDS

CMD:register(playerid, params[])
{
    if(IsPlayerSignedIn(playerid))
    {
        SendClientMessage(playerid, -1, "You are already registered and logged in.");
    }
    else if(fexist(UserPath(playerid)))
    {
        SendClientMessage(playerid, -1, "This account is already registered, please log in.");
    }
    else
    {
        new password[128];
        if(sscanf(params, "s[128]", password))
        {
            SendClientMessage(playerid, -1, "Usage: /register (password).");
        }
        else
        {
            new hash[129];
            WP_Hash(hash, sizeof(hash), password);

            new INI:file = INI_Open(UserPath(playerid));
            INI_SetTag(file, USER_TAG);
            INI_WriteString(file, USER_PASSWORD, hash);
            INI_WriteInt(file, USER_SCORE, 0);
            INI_WriteInt(file, USER_CASH, 0);
            INI_WriteInt(file, USER_KILLS, 0);
            INI_WriteInt(file, USER_DEATHS, 0);
            INI_WriteInt(file, USER_ADMIN_LEVEL, 0);
            INI_Close(file);

            sSignedIn[playerid] = true;

            SendClientMessage(playerid, -1, "You have successfully registered your account.");
        }
    }
    return 1;
}

CMD:login(playerid, params[])
{
    if(IsPlayerSignedIn(playerid))
    {
        SendClientMessage(playerid, -1, "You are already registered and logged in.");
    }
    else if(!fexist(UserPath(playerid)))
    {
        SendClientMessage(playerid, -1, "This account doesn't exist, please register it first.");
    }
    else
    {
        new password[128];
        if(sscanf(params, "s[128]", password))
        {
            SendClientMessage(playerid, -1, "Usage: /login (password).");
        }
        else
        {
            new hash[129];
            WP_Hash(hash, sizeof(hash), password);

            INI_ParseFile(UserPath(playerid), "LoadUserData", .bExtra = true, .extra = playerid);
           
            if(strcmp(aUserInfo[playerid][user_password], hash, false) == 0)
            {
                INI_ParseFile(UserPath(playerid), "LoadUserData", .bExtra = true, .extra = playerid);

                SetPlayerScore(playerid, aUserInfo[playerid][user_score]);
                GivePlayerMoney(playerid, aUserInfo[playerid][user_cash]);

                sSignedIn[playerid] = true;

                SendClientMessage(playerid, -1, "You have successfully logged in to your account.");
            }
            else
            {
                SendClientMessage(playerid, -1, "Oops, you have entered an incorrect password.");
            }
        }
    }
    return 1;
}

// ** FUNCTIONS

stock ResetPlayerVariables(playerid)
{
    // ** ARRAYS AND ENUMERATORS
   
    aUserInfo[playerid][user_password] = EOS;
    aUserInfo[playerid][user_score] = 0;
    aUserInfo[playerid][user_cash] = 0;
    aUserInfo[playerid][user_kills] = 0;
    aUserInfo[playerid][user_deaths] = 0;
    aUserInfo[playerid][user_admin_level] = 0;

    // ** PER-PLAYER VARIABLES:

    // *** PLAYER STATES

    sSignedIn[playerid] = false;
    return 1;
}

forward LoadUserData(playerid, name[], value[]);
public LoadUserData(playerid, name[], value[])
{
    INI_String(USER_PASSWORD, aUserInfo[playerid][user_password], 129);
    INI_Int(USER_SCORE, aUserInfo[playerid][user_score]);
    INI_Int(USER_CASH, aUserInfo[playerid][user_cash]);
    INI_Int(USER_KILLS, aUserInfo[playerid][user_kills]);
    INI_Int(USER_DEATHS, aUserInfo[playerid][user_deaths]);
    INI_Int(USER_ADMIN_LEVEL, aUserInfo[playerid][user_admin_level]);
    return 1;
}

stock UserPath(playerid)
{
    new string[50], name[MAX_PLAYER_NAME];
    GetPlayerName(playerid, name, sizeof(name));

    format(string, sizeof(string), "/Users/%s.ini", name);
    return string;
}

forward bool:IsPlayerSignedIn(playerid);
public bool:IsPlayerSignedIn(playerid)
{
    return sSignedIn[playerid];
}
I'm not trying to ruin your thread, but I guess people could need them.

Nice tutorial, by the way!
Reply
#27

Quote:
Originally Posted by AndySedeyn
View Post
Topic updated

Being able to log on with any password is a known problem. There is an easy fix for this:

Change:
PHP Code:
INI_ParseFile(UserPath(playerid), "LoadPlayerData_%s", .bExtra true, .extra playerid); 
To
PHP Code:
INI_ParseFile(UserPath(playerid), "LoadPlayerData_user", .bExtra true, .extra playerid); 
I myself don't know what causes this. For some it works with %s and for others it works with _user. Someone who has more insight in the frame of y_ini might be able to provide an explanation for this.
Check this https://sampforum.blast.hk/showthread.php?tid=611118&page=2
Reply
#28

Quote:
Originally Posted by Sreyas
View Post
Will update. Thank you for linking me to the topic.
Reply
#29

Quote:
Originally Posted by AndySedeyn
View Post
Will update. Thank you for linking me to the topic.
your welcome and this tutorial is the best and clean tutorial on the basis of yini
Reply
#30

I'm sorry, i got these errors here:
Quote:

(490) : error 001: expected token: "-string end-", but found "-identifier-"
(490) : warning 215: expression has no effect
(490) : error 001: expected token: ";", but found ")"
(490) : error 029: invalid expression, assumed zero
(490) : fatal error 107: too many error messages on one line

Compilation aborted.Pawn compiler 3.2.3664 Copyright © 1997-2006, ITB CompuPhase


4 Errors.

Line 490:
pawn Code:
if(fexist(UserPath(playerid)))
{
    INI_ParseFile(UserPath(playerid), "LoadPlayerData", .bExtra = true, .extra = playerid);
    format(string, sizeof(string),""COL_LIGHTBLUE"Welcome back to LSGW, "COL_BLUE"%s!\n\n"COL_LIGHTBLUE"To be able to spawn, play, and takes the advantage of the features that we offer, you need to login to this account.\n\n"COL_RED"Insert your password in the field below.\nIf this is not your account, please make one!",name);
    ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Account Login", string, "Login", "Quit");
}
else
{
    format(string, sizeof(string),""COL_LIGHTBLUE"Welcome to LSGW, "COL_BLUE"%s!\n\n"COL_LIGHTBLUE"To be able to spawn, play, and takes the advantage of the features that we offer, you need to register an account.\n\n"COL_RED"Insert your password in the field below.\nDon't ever give it to other people, even our administrators!",name);
    ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, "Account Register", "Welcome. This account is not registered.\n\nEnter your desired password below to register:", "Register", "Quit");
}
Above Line 490:
pawn Code:
pInfo[playerid][AdminLevel] = 0;
pInfo[playerid][LoggedIn] = false;
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)