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!