19.07.2011, 16:45
(
Last edited by System64; 27/08/2011 at 07:21 AM.
)

Hi all,
I started scripting for my server and I had a big problems with register and login system, 1st I should login with any password or just press enter, 2nd on GMX stats reset... Peoples told me to leave a y_ini and whirlpool and use something like a dini, dudb, djson... but I didn't! I was persistent and I fixed it, my friend Paradox (not real Paradox, the best player of cod 4) has made almost all of this but I fixed it so I decied to write a tutorial! Let's start!
Features
- Saving money, score, kills, deaths, admin level, vip level, online time...
- Register and login in dialog
- Password hashing
To start "tutorial" we need:
- Whirlpool - To hash passwords in the .ini file (You won't be able to se user's password)
- y_ini - Without this we this can't do anything!
- foreach - For looping, for online time counting
- y_commands - Command procesor, it is fastest and flexibil procesor
- sscanf 2.0 - string splitter, for reading command parameters
I will put this in include, you can download it from here
If you use it as include put on top of your script
pawn Code:
#include <reglog>
1. Defines, enumators etc.
pawn Code:
#define COL_GREEN2 "{33CC00}" //this is color
#define COL_WHITE "{FFFFFF}" //this too
enum pInfo //enumator for player info
{ //opening barrel
pPassword[129], //player password
pKills, //player kills
pDeaths, //player deaths
pAdmin, //player admin level
pMoney, //player money
pScore, //player score
pVIP, //player vip level
pOnline //player online time
} //closing barrel
new PlayerInfo[MAX_PLAYERS][pInfo]; //variable for stats (I don't now how to expalin it better)
native WP_Hash(buffer[], len, const str[]); //native function for hashing passwords
forward LoadUserData(playerid, name[], value[]); //forwarding function LoadUserData
#define INI_Exists(%0) fexist(%0) //just a define, now is a INI_Exists no fexist (I's better for me)
#define DIALOG_REGISTER 1 //define for dialog id
#define DIALOG_LOGIN 2 //define for dialog id
#define USER_FILE "Users/%s.ini" //define for path where will stats save
#define VERSION "1.0.0" //version of your mod/server, I just puted it if you wan't to use it, you can use it in example SetGameModeText, main etc. so when you change version on all place where is version will change :D
pawn Code:
public LoadUserData(playerid, name[], value[]) //new function with playerid, player name and value
{ //opening barrel
INI_String("Password", PlayerInfo[playerid][pPassword], 129); //loading player password, Whirlpool hash 128 characters + NULL
INI_Int("Admin", PlayerInfo[playerid][pAdmin]); //loading player admin level
INI_Int("VIP", PlayerInfo[playerid][pVIP]); //loading player vip level
INI_Int("Money", PlayerInfo[playerid][pMoney]); //loading player money
INI_Int("Score", PlayerInfo[playerid][pScore]); //loading player score
INI_Int("Kills", PlayerInfo[playerid][pKills]); //loading player kills
INI_Int("Deaths", PlayerInfo[playerid][pDeaths]); //loading player deaths
INI_Int("Online", PlayerInfo[playerid][pOnline]); //loading player online time
return 1; //returning true
} //closing barrel
pawn Code:
OnPlayerRegister(playerid, password[]) //We will use this function when player register, parameters are playerid and password
{ //opening barrel
new
hashPassword[129], //variable for hashing password
uFile[35]; //variable for file
format(uFile, 35, USER_FILE, GetName(playerid)); //formating our file, where files saves and getting player name
new
INI:playerFile = INI_Open(uFile); //creating new ini file called playerFile and opening it
WP_Hash(hashPassword, 129, password); //hashing password, Whirlpool hash 128 characters + NULL
INI_WriteString(playerFile, "Password", hashPassword); //writing hashed password
INI_WriteInt(playerFile, "Admin", 0); //writing player admin level
INI_WriteInt(playerFile, "VIP", 0); //writing player vip level
INI_WriteInt(playerFile, "Money", 200); //writing player money
INI_WriteInt(playerFile, "Score", 0); //writing player score
INI_WriteInt(playerFile, "Kills", 0); //writing player kills
INI_WriteInt(playerFile, "Deaths", 0); //writing player deaths
INI_WriteInt(playerFile, "Online", 0); //writing player online time
INI_Close(playerFile); //closing file
SetPVarInt(playerid, "Registered", 1); //setting PVar that player is registered
SetPVarInt(playerid, "Logged", 1); //setting PVar that player is logged
return 1; //returning true
} //closing barrel
pawn Code:
OnPlayerLogin(playerid, password[]) //we will use this when player login, parameters are playerid and player password
{ //opening barrel
new
hashPassword[129], //variable for hashing password
uFile[35]; //variable for file
format(uFile, 35, USER_FILE, GetName(playerid)); //formating file, path where it will be saved and getting player name
INI_ParseFile(uFile, "LoadUserData", .bExtra = true, .extra = playerid); //I don't now what is this xD
WP_Hash(hashPassword, 129, password); //hashing password, Whirlpool hash 128 characters + NULL
if(strcmp(PlayerInfo[playerid][pPassword], hashPassword, true)) //if player type true (Right) password he will be logged in
{ //opening barrel
SetPVarInt(playerid, "Logged", 1); //setting PVar that palyer is logged in
} //closing barrel
return 1; //returning true
} //closin barrel
pawn Code:
OnPlayerLogout(playerid) //we will use this when player logut, when he disconnect, parameter are only playerid
{ //opening barrel
new
uFile[35]; //variable for file
format(uFile, 35, USER_FILE, GetName(playerid)); //formating file, path where it will be saved and getting player name
new
INI:playerFile = INI_Open(uFile); //new ini file called playerFile and opening it
INI_WriteInt(playerFile, "Admin", PlayerInfo[playerid][pAdmin]); //writing player admin level
INI_WriteInt(playerFile, "VIP", PlayerInfo[playerid][pVIP]); //writing player vip level
INI_WriteInt(playerFile, "Money", GetPlayerMoney(playerid)); //writing player money
INI_WriteInt(playerFile, "Score", GetPlayerScore(playerid)); //writing player score
INI_WriteInt(playerFile, "Kills", PlayerInfo[playerid][pKills]); //writing player kills
INI_WriteInt(playerFile, "Deaths", PlayerInfo[playerid][pDeaths]); //writing player deaths
INI_WriteInt(playerFile, "Online", PlayerInfo[playerid][pOnline]); //writing player online time
INI_Close(playerFile); //closing file
return 1; //returning true
} //closing barrel
pawn Code:
forward Online(); //forwarding our function for online time
public Online() //function for online time
{
foreach (Player, i) //looping through all player with foreach
{ //opening barrel
PlayerInfo[i][pOnline] += 1; //this will just increase variable online for 1 more!
} //closing barrel
return 1; //returning true
} //closing barrel
pawn Code:
stock GetName(playerid) //function for getting player name, this is faster than GetPlayerName(I don't mean in miliseconds, just I don't need to create new variable and than use GetPlayerName, I just use this function
{ //opening barrel
new
pName[MAX_PLAYER_NAME]; //variable for player name, max.player name is 24
GetPlayerName(playerid, pName, MAX_PLAYER_NAME); //getting player name
return pName //returning player name;
} //closing barrel
Step 3 - Creating register and login in dialog
Open your script and add this under OnPlayerConnect
pawn Code:
new naslov2[128], text[128], strText[104]; //some new variables for title, text in dialog and text that player type
format(strText, 35, USER_FILE, GetName(playerid)); //formating our file, path where it will be saved and getting player name
if(!INI_Exists(strText)) //if ini doesn't exist player will get this:
{ //opening barrel
format(naslov2, sizeof(naslov2), ""COL_BLUE2" Welcome"COL_WHITE" %s!", GetName(playerid)); //formating our title, some text, colors balabalbal
format(text, sizeof(text), ""COL_WHITE"______________________________\n\n"COL_BLUE2"Name"COL_WHITE" %s"COL_BLUE2" isn't registered!\n\nPlease register!", GetName(playerid)); //formating our text
ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, naslov2, text, "Register", "Exit"); //showing player dialog for registering
} //closing barrel
else //but if exists player will get this
{ //opening barrel
format(naslov2, sizeof(naslov2), ""COL_GREEN2" Welcome"COL_WHITE" %s!", GetName(playerid)); //formating our title, some text, colors...
format(text, sizeof(text),""COL_WHITE"______________________________\n\n"COL_GREEN2"Name"COL_WHITE" %s"COL_GREEN2" is registered!\n\nPlease login!", GetName(playerid)); //formating our text in dialog
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT, naslov2, text, "Login", "Exit"); //showing player dialog for login
} //closing barrel
SetPVarInt(playerid, "Joinned", 1); //setting PVar that player has joinned
pawn Code:
OnPlayerLogout(playerid); //saving stats for player
pawn Code:
switch(dialogid) //switching to dialogid
{ //opening barrel
case DIALOG_REGISTER: //for registering
{ //opening barrel
if(response)
{ //opening barrel
new
strText[179], naslov2[128]; //some variables for text that player type and title
if(strlen(inputtext) >= 4 && strlen(inputtext) <= 35) //if player type password more than 4 and less than 35 characters he will get this
{ //opening barrel
OnPlayerRegister(playerid, inputtext); //Loading stats
format(strText, 125, "You have registered with name {FFFFFF}'%s' {FFFF00}and password {FFFFFF}'%s'{FFFF00}, you are automatic logged in!", GetName(playerid), inputtext); //formating our text
SendClientMessage(playerid, COLOR_YELLOW, strText); //send client message
} //closing barrel
else // else if je type less than 4 or more than 35 characters he will get this
{ //opening barrel
format(naslov2, sizeof(naslov2), ""COL_GREEN2" Welcome"COL_WHITE" %s!", GetName(playerid)); //formating our title
format(strText, 179, ""COL_WHITE"______________________________\n\n"COL_GREEN2"Name"COL_WHITE" %s"COL_GREEN2" isn't registered!\n\n{F81414}Password must be between 4 and 35 characters!", GetName(playerid)); //formating our text
ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_INPUT, naslov2, strText, "Register", "Exit"); //show player again dialog for registering
} //closing barrel
} //closing barrel
else Kick(playerid); //if player choose Exit button, server will kick him, this is for response :D
} //closing barrel
case DIALOG_LOGIN: //for loging
{ //opening barrel
if(response)
{ //opening barrel
new
strText[179], naslov2[128]; //some variables for text that player type and title
if(strlen(inputtext) >= 4 && strlen(inputtext) <= 35) //if player type password more than 4 or less than 35 characters he will get this
{ //opening barrel
OnPlayerLogin(playerid, inputtext); //loading stats
} //closing barrel
else //but if he type less than 4 or more than 35 characters he will get this
{ //opening barrel
format(naslov2, sizeof(naslov2), ""COL_GREEN2" Welcome"COL_WHITE" %s!", GetName(playerid)); //formating our title
format(strText, 179, ""COL_WHITE"______________________________\n\n"COL_GREEN2"Name"COL_WHITE" %s"COL_GREEN2" is registered!\n\n{F81414}You typed wrong password!", GetName(playerid)); //formating our text
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_INPUT, naslov2, strText, "Login", "Exit"); //showing palyer again dialog for login
} //closing barrel
} //closing barrel
else Kick(playerid); //if he choose Exit button it , server will kick him, this is response :D
} //closing barrel
} //closing barrel
pawn Code:
SetPVarInt(playerid, "Joinned", 1); //setting PVar that player is joinned
pawn Code:
if(GetPVarInt(playerid, "Joinned") == 1) //if variable is true player will get this
{
GivePlayerCash(playerid, PlayerInfo[playerid][pMoney]); //setting player money from file
SetPlayerScore(playerid, PlayerInfo[playerid][pScore]); //setting player score from file
SetPVarInt(playerid, "Joinned", 0); //setting PVar taht player is'nt joinned
}
pawn Code:
PlayerInfo[killerid][pKills] ++; //incraseing killerid kils for one more
PlayerInfo[playerid][pDeaths] ++; //increase player deaths for one more
pawn Code:
SetTimer("Online",60*1000*60,1); //timer for Online time counter :D
Here are some useful commands, to give admin, give vip, set money, score, kills, deaths etc.
pawn Code:
YCMD:setscore(playerid, params[], help) //command for set player score
{ //opening barrel
#pragma unused help //i won't use help in this command so I need this, if you don't use this you will get warning
new id,val,string[128], string2[128]; //variables for id of player we want, value and some strings
if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][pAdmin] >= 3) //detecting if is player admin (rcon) and higher than level 3
{ //opening barrel
if(sscanf(params,"ui", id, val)) return SendClientMessage(playerid,COLOR_WHITE,"Usage: /setscore [ID] [Value]"); //parameters are "ui", u is for id and i is for integrer (Number), also we must put after variables! if player don't fill whole parameters he will get message with parameters in that command
else if(id == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_WHITE, "Invalid ID"); //if player isn't online player will get message that player isn't online
else
SetPlayerScore(id, val); //setting player score, id that we want and value that we want
format(string, sizeof(string),"You have set player %s score on %d!",GetName(id), val); //formating message
SendClientMessage(playerid, COLOR_YELLOW, string); //sending message to admin
format(string2, sizeof(string2),"Administrator %s has set your score on %d!",GetName(playerid), val); //formating message
SendClientMessage(id, COLOR_LIME, string2); //sending message to choosed player
} //closing barrel
else SendClientMessage(playerid, COLOR_KRED, "You are not authorized for use this command!"); //if player isn't admin he will get that message
return 1; //returning true
} //closing barrel
pawn Code:
YCMD:setkills(playerid, params[], help)
{
#pragma unused help
new id,val,string[128], string2[128];
if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][pAdmin] >= 3)
{
if (sscanf(params,"ui", id, val)) return SendClientMessage(playerid,COLOR_WHITE,"Usage: /setkills [ID] [Value]");
else if(id == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_WHITE, "Invalid ID");
else
PlayerInfo[id][pKills] = val;
format(string, sizeof(string),"You have set player %s kills on %d!",GetName(id), val);
SendClientMessage(playerid, COLOR_YELLOW,string);
format(string2, sizeof(string2),"Administrator %s has set your kills on %d!",GetName(playerid), val);
SendClientMessage(id, COLOR_LIME, string2);
}
else SendClientMessage(playerid, COLOR_KRED, "You are not authorized for use this command!");
return 1;
}
pawn Code:
YCMD:setdeaths(playerid, params[], help)
{
#pragma unused help
new id,val,string[128], string2[128];
if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][pAdmin] >= 3)
{
if(sscanf(params,"ui", id, val)) return SendClientMessage(playerid,COLOR_WHITE,"Usage: /setdeaths [ID] [Value]");
else if(id == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_WHITE, "Invalid ID");
else
PlayerInfo[id][pDeaths] = val;
format(string, sizeof(string),"You have set player %s deaths on %d!",GetName(id), val);
SendClientMessage(playerid, COLOR_YELLOW, string);
format(string2, sizeof(string2),"Administrator %s has set your deaths on %d!",GetName(playerid), val);
SendClientMessage(id, COLOR_LIME, string2);
}
else SendClientMessage(playerid, COLOR_KRED, "You are not authorized for use this command!");
return 1;
}
pawn Code:
YCMD:givemoney(playerid, params[], help)
{
#pragma unused help
new id, money, string[128], string2[128];
if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][pAdmin] >= 3)
{
if(sscanf(params, "ui", id, money)) return SendClientMessage(playerid, COLOR_WHITE, "Usage: /givemoney [ID] [Amount]");
else if(id == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_WHITE, "Invalid ID");
else
GivePlayerMoney(id, money);
format(string, sizeof(string), "You have give player %s $%d!", GetName(id), money);
SendClientMessage(playerid, COLOR_YELLOW, string);
format(string2, sizeof(string2), "Administrator %s has given you $%d!", GetName(playerid), money);
SendClientMessage(id, COLOR_LIME, string2);
}
else SendClientMessage(playerid, COLOR_KRED, "You are not authorized for use this command!");
return 1;
}
pawn Code:
YCMD:givegun(playerid, params[], help)
{
#pragma unused help
new id,weapon,ammo,string[128], string2[128];
if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][pAdmin] >= 2)
{
if(sscanf(params,"iii",id,weapon,ammo)) return SendClientMessage(playerid,COLOR_WHITE,"Usage: /giveweapon [ID] [Gun ID] [Ammo]");
else if(weapon > 46 || weapon < 1) return SendClientMessage(playerid, COLOR_WHITE, "ID of weapon must be between 1 and 46!");
else if(id == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_WHITE, "Invalid ID");
else
GivePlayerWeapon(id,weapon,ammo);
format(string, sizeof(string),"You have give player %s weapon %d!", GetName(id), weapon);
SendClientMessage(playerid, COLOR_YELLOW, string);
format(string2 ,sizeof(string2),"Administrator %s has given you weapone!", GetName(playerid));
SendClientMessage(id, COLOR_LIME, string2);
}
else SendClientMessage(playerid, COLOR_KRED, "You are not authorized for use this command!");
return 1;
}
pawn Code:
YCMD:setmoney(playerid, params[], help)
{
#pragma unused help
new id, cash, string[128], string2[128];
if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][pAdmin] >= 3)
{
if(sscanf(params,"ui", id, cash)) return SendClientMessage(playerid,COLOR_WHITE,"Usage: /setmoney [ID] [Amount]");
else if(id == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_WHITE, "Invalid ID");
else
ResetPlayerMoney(id);
GivePlayerMoney(id, cash);
format(string, sizeof(string),"You have set player %s money on $%d", GetName(id), cash);
SendClientMessage(playerid,COLOR_YELLOW,string);
format(string2, sizeof(string2),"Administrator %s has se your money on $%d", GetName(playerid), cash);
SendClientMessage(id, COLOR_LIME,string2);
}
else SendClientMessage(playerid, COLOR_KRED, "You are not authorized for use this command!");
return 1;
}
pawn Code:
YCMD:makeadmin(playerid, params[], help)
{
#pragma unused help
new id, lvl, string[128], string2[128];
if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][pAdmin] >= 3)
{
if(sscanf(params, "ui", id, lvl)) return SendClientMessage(playerid, COLOR_WHITE, "Usage: /makeadmin [ID] [Level]");
else if(id == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_WHITE, "Invalid ID");
else if(lvl > 3) return SendClientMessage(playerid, COLOR_WHITE, "Administrator level only can be 1 | 2 | 3");
else
PlayerInfo[id][pAdmin] = lvl;
format(string, sizeof(string), "Administrator %s has set you administrator level on %d!", GetName(playerid), lvl);
SendClientMessage(id, COLOR_LIME, string);
format(string2, sizeof(string2), "You have set player %s administrator level on %d!", GetName(id), lvl);
SendClientMessage(playerid, COLOR_YELLOW, string2);
}
else SendClientMessage(playerid, COLOR_KRED, "You are not authorized for use this command!");
return 1;
}
pawn Code:
YCMD:makevip(playerid, params[], help)
{
#pragma unused help
new id, lvl, string[128], string2[128];
if(IsPlayerAdmin(playerid) || PlayerInfo[playerid][pAdmin] >= 3)
{
if(sscanf(params, "ui", id, lvl)) return SendClientMessage(playerid, COLOR_WHITE, "Usage: /makevip [ID] [Level]");
else if(id == INVALID_PLAYER_ID) return SendClientMessage(playerid, COLOR_WHITE, "Invalid ID");
else if(lvl > 3) return SendClientMessage(playerid, COLOR_WHITE, "VIP level only can be 1 | 2 | 3");
else
PlayerInfo[id][pVIP] = lvl;
format(string, sizeof(string), "Administrator %s has set you VIP level on %d!", GetName(playerid), lvl);
SendClientMessage(id, COLOR_LIME, string);
format(string2, sizeof(string2), "You have set player %s VIP level on %d!", GetName(id), lvl);
SendClientMessage(playerid, COLOR_YELLOW, string2);
}
else SendClientMessage(playerid, COLOR_KRED, "You are not authorized for use this command!");
return 1;
}
pawn Code:
YCMD:admins(playerid, params[], help) //command for online admins
{ //opening barrel
#pragma unused help //in this command I don't use parameter help
#pragma unused params //alo this
new aMsg[MAX_PLAYER_NAME]; //varaible for message, smoething like string
SendClientMessage(playerid, COLOR_KRED, "<~~ Administrators Online ~~>"); //just sends messtog to player
foreach(Player, i) //looping throught all players (Connected players=
if(PlayerInfo[i][pAdmin] == 1) //if is somebody admin level 1 player will get this
{ //opening barrel
format(aMsg, 127, "Gamemaster: %s", GetName(i)); //formating message
SendClientMessage(playerid, COLOR_LIGHTBLUE, aMsg); //sending message
} //clossing barrel
else if(PlayerInfo[i][pAdmin] == 2) //if is somebody admin level 2 player will get this
{ //opening barrel
format(aMsg, 127, "Administrator: %s", GetName(i)); //formating message
SendClientMessage(playerid, COLOR_LIGHTBLUE, aMsg); //sending messgage
} //closing barrel
else if(PlayerInfo[i][pAdmin] == 3) //iis somebody admin level 3 player will get this
{ //opening barrel
format(aMsg, 127, "Owner: %s", GetName(i)); //formating message
SendClientMessage(playerid, COLOR_LIGHTBLUE, aMsg); //sending message
} //closing barrel
return 1; //returning true
} //closing barrel
pawn Code:
YCMD:vip(playerid, params[], help)
{
#pragma unused help
#pragma unused params
new aMsg[MAX_PLAYER_NAME];
SendClientMessage(playerid, COLOR_KRED, "<~~ VIP Members Online ~~>");
foreach(Player, i)
if(PlayerInfo[i][pVIP] == 1)
{
format(aMsg, 127, "Bronze: %s", GetName(i));
SendClientMessage(playerid, COLOR_LIGHTBLUE, aMsg);
}
else if(PlayerInfo[i][pVIP] == 2)
{
format(aMsg, 128, "Silver: %s", GetName(i));
SendClientMessage(playerid, COLOR_LIGHTBLUE, aMsg);
}
else if(PlayerInfo[i][pVIP] == 3)
{
format(aMsg, 129, "Gold: %s", GetName(i));
SendClientMessage(playerid, COLOR_LIGHTBLUE, aMsg);
}
return 1;
}
Paradox - for creating whole script
System32 (Aka System64) - for fixing problems and writtening tutorial