#include <a_samp>
#include <a_mysql>
#include <zcmd>
#include <sscanf2>
native WP_Hash(buffer[], len, const str[]);
#define SQL_HOST "localhost"
#define SQL_USER "root"
#define SQL_PASS ""
#define SQL_DATABASE "tester"
new SQL = -1;
enum pInfo {
ID,
Name[MAX_PLAYER_NAME],
Password[129],
Level,
Admin,
AdminTitle[64],
Float:Health,
Float:Armour,
bool:IsLoggedIn,
bool:IsRegistered,
LoginAttempts,
}
new Player[MAX_PLAYERS][pInfo];
new MySQLCheck[MAX_PLAYERS];
enum dialogs {
DIALOG_REGISTER,
DIALOG_LOGIN,
DIALOG_UNUSED,
}
public OnGameModeInit()
{
SetGameModeText("MySQL / Admin System v0.1");
SQL = mysql_connect(SQL_HOST, SQL_USER, SQL_DATABASE, SQL_PASS);
mysql_debug(1);
SetupPlayerTable();
return 1;
}
public OnGameModeExit()
{
mysql_close();
return 1;
}
public OnPlayerConnect(playerid)
{
new query[128];//New query being defined.
MySQLCheck[playerid]++;Here is our check being put into place.
for(new pInfo:e; e < pInfo; ++e)//Here we reset the playerdata to make sure no wrong data is assigned.
Player[playerid][e] = 0;
GetPlayerName(playerid, Player[playerid][Name], MAX_PLAYER_NAME);// We assign the players name to a the variable, Player[playerid][Name].
mysql_format(SQL, query, sizeof(query), "SELECT * FROM `players` WHERE `username` = '%e' LIMIT 1", Player[playerid][Name]);
//This is the select query we use to retrieve the playerdata from the SQL if any exists.
mysql_tquery(SQL, query, "OnAccountRetrieve","dd", playerid, MySQLCheck[playerid]);//This is a tquery, it allows you to use cached or non-cached queries. This one is cached.
return 1;
}
forward OnAccountRetrieve(playerid, mysql_check);//Here we use forward because we're creating a public.
public OnAccountRetrieve(playerid, mysql_check)
{
if(mysql_check != MySQLCheck[playerid])//Here we check if the check does not equal the value stored in MySQLCheck, we kick the player.
{
Kick(playerid);
}
new str[128];//New string.
if(cache_num_rows() > 0)//If there are rows then we load the login.
{
SetPlayerData(playerid);//Here we set the players data, This assigns data to all the variables.
format(str, sizeof(str), "MySQL Account and Admin System, Welcome %s. Please login below:", Player[playerid][Name]);//Here we format a message for out password dialog.
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login", str, "Continue", "Cancel");
Player[playerid][IsRegistered] = true;//We set the Variable IsRegistered to True, so it knows we're not a new player.
}
else //Else we load the registration.
{
format(str, sizeof(str), "MySQL Account and Admin System, Welcome %s. Please register below:", Player[playerid][Name]);//Registration String,
ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration", str, "Continue", "Cancel");//Registration Dialog
Player[playerid][IsRegistered] = false;//He we set it to false so we know that the player is new.
}
return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
{
switch(dialogid)
{
case DIALOG_LOGIN://Setting the case to the right dialog.
{
if(!response)//This means, if they click cancel. They'll be kicked.
{
Kick(playerid);
}
if(strlen(inputtext) <= 5)//This checks if the password is equal or shorter than 5 characters.
{
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login",
"Your password must be longer than 5 characters!\nPlease enter your password in the field below:",
"Login", "Abort");// If it is less or equal to 5 characters, It brings the dialog back up along with an error message.
}
new encoded_pass[129];//Defining the hashed password.
WP_Hash(encoded_pass, sizeof(encoded_pass), inputtext);//This hashes the password that you entered.
if(strcmp(encoded_pass, Player[playerid][Password]) == 0)//This is checking if the password is the same as the password in the password variable.
{
ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Success!", "You have successfully logged in!", "Continue", "");//If it is, It logs you in successfully.
Player[playerid][IsLoggedIn] = true;//This set the LoggedIn variable to true, for use in later commands.
SetSpawnInfo(playerid, 0, 20,2177.6423,-1770.3905,13.5434,0.0,0,0,0,0,0,0);
SpawnPlayer(playerid);
}
else//This is if your password is wrong, it gives you 3 chances to re-enter it before kicking you.
{
Player[playerid][LoginAttempts]++;//This increases the variable by one each time you get your password wrong.
if(Player[playerid][LoginAttempts] >= 3)//This if statement determines if you have enter the password incorrectly too many time.
{
ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Error","You have mistyped your password too often (3 times).", "Okay", "");
DelayedKick(playerid);//This is the kick.
}
else
ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Error","Wrong password!\nPlease enter your password in the field below:", "Login", "Abort");
//This is the error message for entering the wrong password.
}
}
case DIALOG_REGISTER://This sets the dialog to the DIALOG_REGISTER.
{
if(!response)//Again, this kicks the player if he declines the dialog.
return Kick(playerid);
if(strlen(inputtext) <= 5)// This is the same as previously.
{
ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration",
"Your password must be longer than 5 characters!\nPlease enter your password in the field below:",
"Continue", "Cancel");
}
new query[256];//Defining the query to insert the data into the SQL
WP_Hash(Player[playerid][Password], 129, inputtext);//Hashing the password.
mysql_format(SQL, query, sizeof(query), "INSERT INTO `players` (`username`, `password`) VALUES ('%e', '%s')", Player[playerid][Name], Player[playerid][Password]);
//This is mysql_format, it formats the query so you can tell it what to insert into the database. %e is used for usernames and %s strings, e.g. the password.
mysql_tquery(SQL, query, "OnPlayerRegistration", "d", playerid);//This is the query, The format is mysql_tquery(Connhandle,query[],Callback[],format[])
}
default:
return 0;
}
return 1;
}
forward OnPlayerRegistration(playerid);
public OnPlayerRegistration(playerid)
{
Player[playerid][ID] = cache_insert_id();//This means the ID in the SQL is saved to a variable.
ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Registration", "Account successfully registered, you have been automatically logged in.", "Okay", "");
Player[playerid][IsLoggedIn] = true;//Sets the IsLoggedIn Variable to true.
Player[playerid][IsRegistered] = true;//The same as above but for IsRegistered.
SetSpawnInfo(playerid, 0, 20,2177.6423,-1770.3905,13.5434,0.0,0,0,0,0,0,0);//This sets the spawn info. Team, Skin, PosX, PosY, PosZ, Angle and Weapon ID's and ammo.
Player[playerid][Health] = 100.00; //Sets the players health.
Player[playerid][Armour] = 0.00; //Sets the player armour.
Player[playerid][Level] = 1;//Set's the level to 1.
SpawnPlayer(playerid);
return 1;
}
stock SetPlayerData(playerid)// This is assigning the data to variable.
{
Player[playerid][ID] = cache_get_field_content_int(0, "id");// The ID is and int because it's an integer (Number).
cache_get_field_content(0, "password", Player[playerid][Password], SQL, 129);
//The password is a varchar so you need to use cache_get_field_content
Player[playerid][Admin] = cache_get_field_content_int(0,"admin");//The admin is saved as an int because again, it's an integer.
Player[playerid][Health] = cache_get_field_content_float(0, "health");
//The health and armour are floats. This lets them hold decimal values like "84.56". So, Positions would be floats too.
Player[playerid][Armour] = cache_get_field_content_float(0, "armour");
cache_get_field_content(0, "admintitle", Player[playerid][AdminTitle], SQL, 64);
//the admin title is a varchar so it is again retrieved by cache_get_field_content.
Player[playerid][Level] = cache_get_field_content_int(0,"level");
//the level is an integer.
return 1;
}
stock SavePlayerData(playerid)
{
if(Player[playerid][IsLoggedIn] == false)//This checks if the player is logged in, if not, It saves nothing.
return 0;
new Float:GetHealth, Float:GetArmour, admtitle2;
admtitle2 = Player[playerid][AdminTitle];
GetPlayerHealth(playerid, GetHealth);
GetPlayerArmour(playerid, GetArmour);
new query[1000];
mysql_format(SQL, query, sizeof(query), "UPDATE `players` SET `admin` = '%d', `health` = '%f', `armour` = '%f', `admintitle` = '%s', `level` = '%d' WHERE `id` = '%d' LIMIT 1",
Player[playerid][Admin],GetHealth,GetArmour, admtitle2,Player[playerid][Level], Player[playerid][ID]);
mysql_tquery(SQL, query, "", "");
return 1;
}
stock SetupPlayerTable()
{
mysql_query(SQL, "CREATE TABLE IF NOT EXISTS `players` (`id` int(11) NOT NULL auto_increment PRIMARY KEY,`username` varchar(30) NOT NULL,`password` varchar(130) NOT NULL,`admin` int(10) NOT NULL default '0', `health` float(10) NOT NULL default '100.00', `armour` float(10) NOT NULL default '0.00',`admintitle` varchar(64) NOT NULL default 'None',`level` int(10) NOT NULL default '0')", false);
return 1;// This create the table in the database if it isn't there. If it is there. It leaves it.
}
public OnPlayerSpawn(playerid)
{
new str[128];
SetPlayerHealth(playerid, Player[playerid][Health]);//Set's the health and armour.
SetPlayerArmour(playerid, Player[playerid][Armour]);
ShowPlayerDialog(playerid, 200, DIALOG_STYLE_MSGBOX,"MySQL Account and Admin System","This is a simple account system, Hopefully you got it right!","Ok","Cancel");
if(Player[playerid][Admin] >= 1)//If the player is admin, It will do whatever is in the parameter for that player.
{
format(str, 128, "Notice: You're logged in as a %s!", Player[playerid][AdminTitle]);
SendClientMessage(playerid, -1, str);//It sends a message notifying the admin of their rank.
}
return 1;
}
stock DelayedKick(playerid, time=500)
{
SetTimerEx("_KickPlayerDelayed", time, false, "d", playerid);
return 1;
}
forward _KickPlayerDelayed(playerid);
public _KickPlayerDelayed(playerid)
{
Kick(playerid);
return 1;
}
CMD:adminoverride(playerid, params[])
{
new override[64], OverrideAttempts;//We define the variable we need for the command.
if(sscanf(params,"s[64]",override)) return SendClientMessage(playerid, -1, "USAGE:/adminoverride [Password]");
//If the command parameters are empty, then we return a message about the command usage.
if(!strcmp(override, adminpassword))//Here we check if the override entered is the same as the admin password defined at the top.
{
Player[playerid][Admin] = 7;//If it is, we set the admin level to 7.
SendClientMessage(playerid, -1, "NOTICE: You're now a level 7 administrator!");
}
else//Otherwise, we send them a message with and increase their override attempts.
{
SendClientMessage(playerid, -1, "NOTICE: Wrong Password!");
OverrideAttempts ++;//Here we increase the attempts.
}
if(OverrideAttempts == 3)// Now we say if it gets to 3 then we kick the player.
{
DelayedKick(playerid);
}
return 1;
}
CMD:setadmintitle(playerid, params[])
{
new str[128], target,pName[MAX_PLAYER_NAME], targetname[MAX_PLAYER_NAME],admtitle[64];//Command variables.
if(Player[playerid][Admin] != 7) return SendClientMessage(playerid, -1, "SERVER:You're not admin!");//Error message if the player isn't an admin.
if(sscanf(params, "is[64]", target,admtitle)) return SendClientMessage(playerid, -1, "SERVER:/setadmintitle [ID] [Title]");//The usage message like before.
{
GetPlayerName(target, targetname, sizeof(targetname));//Here we get the targets name,
GetPlayerName(playerid, pName, sizeof(pName));// The playerid's name.
format(str, 128, "AdmWarn: %s has set %s's admin title to %s", pName, targetname, admtitle);//Here we format a msg to send to all admins online.
MessageToAdmins(-1, str);
Player[target][AdminTitle] = admtitle;// We set the admintitle variable to what the player entered.
}
return 1;
}
#define adminpassword "testpassword"
stock MessageToAdmins(color,const string[])
{
for(new i = 0; i < MAX_PLAYERS; i++) // Loops through all players
{
if(IsPlayerConnected(i) == 1) // Checks if the player is connected
{
if(Player[i][Admin] >= 1)
{
SendClientMessage(i, color, string);//if player is connected and he's admin level higher then 1 he will get this message
}
}
}
return 1;
}
CMD:deleteaccount(playerid, params[])
{
new query[128];//We define the query
new pid;//Define the accountid
if(Player[playerid][Admin] == 7)//check if the player is a high enough admin level.
{
if(sscanf(params,"d",pid)) return SendClientMessage(playerid, -1, "Usage: /deleteaccount [SQLid]");//Usage Message
mysql_format(SQL, query, sizeof(query),"DELETE FROM `players` WHERE `id` = '%d'",pid);//Here we format the query to delete the players account.
mysql_tquery(SQL, query, "OnAccountDelete","d",playerid);//We fire the query to another call back.
}
else
{
SendClientMessage(playerid,-1, "Notice: You're not an admin!");//if the players is not an admim, It sends this error message.
}
return 1;
}
forward OnAccountDelete(playerid);
public OnAccountDelete(playerid)//New forward and public callback.
{
new affectedrows,str[128];//We define some variables.
affectedrows = cache_affected_rows(SQL);
//Here we set one of the variables to cache_affected_rows which will tell you if anything gets deleted.
format(str,128, "%d rows affected!", affectedrows);//We format the string with our message
SendClientMessage(playerid, -1, str);//Then we send it to the player.
return 1;
}
CMD:resetpassword(playerid, inputtext[])
{
new pid,query[500],WPhash[129];//We define our variables again
if(Player[playerid][Admin] == 7)//We've seen this before, checking if the player is admin
{
if(sscanf(inputtext,"ds[129]",pid,inputtext)) return SendClientMessage(playerid, -1, "Usage: /resetpassword [SQLid] [Password]");//Usage Message
WP_Hash(WPhash, sizeof(WPhash), inputtext);
//Here we hash the password the player enters so it can be stored in the database and recognised properly when the player logs in.
mysql_format(SQL, query, 500, "UPDATE `players` SET `password` = '%s' WHERE `id` = '%d'",WPhash, pid);
//Here we format our query to update the players password where the ID = the pid.
mysql_tquery(SQL, query, "OnPasswordReset","d",playerid);//Fire the query and send it to another callback.
return 1;
}
return 1;
}
forward OnPasswordReset(playerid);//New callback
public OnPasswordReset(playerid)
{
new affectedrows, str[128];//Deinfe the variables.
affectedrows = cache_affected_rows(SQL);
format(str, 128, "%d rows affected!",affectedrows);
SendClientMessage(playerid, -1, str);
return 1;
}
CMD:getsqlid(playerid, params[])
{
new pName[MAX_PLAYER_NAME],query[500];//This ia a command to get the SQL ID needed for the other commands.
if(Player[playerid][Admin] == 7)//Checks the admin level of the player.
{
if(sscanf(params,"s",pName)) return SendClientMessage(playerid, -1, "Usage: /getsqlid [AccountName]");//USage message
mysql_format(SQL,query,500, "SELECT `id`, `username` FROM `players` WHERE `username` = '%s'",pName);//Format query
mysql_tquery(SQL, query, "OnSQLIDRetrieve","d",playerid);//Fire it to another callback.
return 1;
}
return 1;
}
forward OnSQLIDRetrieve(playerid);//New callback.
public OnSQLIDRetrieve(playerid)
{
if(cache_num_rows() < 0)//If there is data in the ID slots you entered in /getsqlid
{
new pid,tempname[64],str[128];
pid = cache_get_field_content_int(0, "id");//We assign the mysql id retrieve to pid.
cache_get_field_content(0, "username", tempname, SQL, 64);//the username to tempname.
format(str, 128, "Username: %s | SQL ID: %d", tempname, pid);//Here we format our string
SendClientMessage(playerid, -1, str);//then send it to the player.
return 1;
}
else//if there isn't data
{
SendClientMessage(playerid, RED,"No results found!");//Send this message
}
return 1;
}
@Giannidw please add msql in server.cfg
and AWESOME TUTORIAL NIGGA! keep making tuts like this please! |
new query[128];//New query being defined.