Jump to content
adain

[ Tutorial ] System of Register / Login on Dini

Recommended Posts

Hello everybody, today I want to give u basic registration system on your server.

All files will be in or under thread. Don't be so rude if you are a pro scripter. I tried to make it step by step (to have less errors in compiling in early stages)

Beforehand: sorry for my english. THIS TOPIC IS JUST CREATED THAT'S IT CAN BE UPDATED

Important - create folder in scriptfiles and called it 'Users'

 

Part 1: Beginning

Let's start. We will create our system on dini (because I like it most of all)

Firstly we need to download Dini include: Dini.inc (now clickable)

After that open pawno and on the top of the mode write:

#include <dini> // Briefly - to add new functions

 

Now we will create some defines to get a faster access and don't waste time while scripting

#define Users "/Users/%s.ini" // withour typing this -> "/Users/%s.ini" we will write it shorter, like this -> Users

 

Now we need to create PlayerInfo

enum pInfo // for player statistic we will use enum, because it's much better than this -> new Admin[MAX_PLAYERS]; new Score[MAX_PLAYERS];
{
	pPass, // This will contain information about user password
	pAdmin, // It as u may have understood will contain the level of admin user have (0 - user, 1 - admin 1 LvL and etc.)
	pDeath, // Will contain info how much times we died by playing on server
	pScore, // Will contain info about player Score for SetPlayerScore
	pLogged
}
new PlayerInfo[ MAX_PLAYERS ][ pInfo ]; // how to use it look down
new file_dini[ 128 ]; // It's our var to file
new hacking_password[ MAX_PLAYERS ]; // for anti-hack =)

Now if you are compile there will be some warnings, but anyway, code is compiled

Part 2: Creating Register/Login

So let's start creating the most essential part

Let's start from the player connecting.

Firstly. Let's create some useful functions in the end of the mode

stock GetName(playerid) // If you don't want to write a lot of code to get players name, add this to the end
{
	new name[ MAX_PLAYER_NAME ]; // var for saving our name
	GetPlayerName(playerid, name, sizeof( name )); // Get name of player by using his id
	return name; // deduce player name to functions where we need
}
//==============================================================================
stock IsPlayerRegistered( playerid ) // Get info Is player account already exist?
{
	format( file_dini, sizeof( file_dini ), Users, GetName(playerid)); // It looks folder 'Users' and find player by name
	return ( dini_Exists( file_dini ) ) ? true : false;
}
//==============================================================================
stock IsLoggedIn( id )
{
	return ( PlayerInfo[ id ][ pLogged ] == 1 ) ? true : false;
}
//==============================================================================
stock IsRegistered( id )
{
	return ( PlayerInfo[ id ][ pLogged ] == 2 ) ? true : false;
}
//==============================================================================

 

 

Secondly. Find in your mode public OnPlayerConnect, so now we will add some condition (Is Player Registered... etc)

public OnPlayerConnect( playerid )
{
	format( file_dini, sizeof( file_dini ), Users, GetName(playerid)); // 'Users' means path to account folder
	if( dini_Exists( file_dini )) // look if folder 'Users' has the file with name (for example: Nick.ini)
	{
		SendClientMessage(playerid, -1, "Usage: /login [password]");
	}
	else // if there is no file with players stats, let's show him message about registration
	{
		SendClientMessage(playerid, -1, "Usage: /register [password]");
	}
	return 1;
}

 

 

Thirdly. Create functions to make commands and understand space between them (/cmds 123, -> /cmds_123 )

To make it we need to create the stock which will help us to know about space between commands, example -> /register 1234 (so it's two part, first - /register, and second it's 1234 after space). Create strtok (u can find it in wiki)

strtok(const string[], &index)
{
	new length = strlen(string);
	while ((index < length) && (string[index] <= ' '))
	{
		index++;
	}

	new offset = index;
	new result[20];
	while ((index < length) && (string[index] > ' ') && ((index - offset) < (sizeof(result) - 1)))
	{
		result[index - offset] = string[index];
		index++;
	}
	result[index - offset] = EOS;
	return result;
}

It gives us possibility to create command like -> /ban [playerid], /kick [playerid], /givemoney [playerid], /busted [playerid]

 

 

Fourthly :D . Let's make it! Create our commands register/login

Find in your mode public OnPlayerCommandText

public OnPlayerCommandText(playerid, cmdtext[])
{
	format( file_dini, sizeof( file_dini ), Users, GetName(playerid)); // Get account access
//------------------------------------------------------------------------------

	new str[144]; // create new var for format
	new cmd[256];
	new tmp[256];
//	new gplayerid;

	new idx;
	cmd = strtok(cmdtext, idx);

//------------------------------------------------------------------------------

	if ( strcmp( cmd, "/register", true ) == 0)
	{
		tmp = strtok( cmdtext, idx );
		if ( IsPlayerRegistered( playerid ) ) return SendClientMessage( playerid, COLOR_RED, "Account with this name exist" );
		else if ( !strlen( tmp ) ) return SendClientMessage( playerid, COLOR_GREEN, "Usage: /register [password]" );
		else
		{
			dini_Create( file_dini ); // Create our file, example you nick is David, it will create David.ini in folder 'Users'


			dini_Set( file_dini, "Password", tmp); // let's write player password to file
			dini_IntSet( file_dini , "Admin", 0); // admin rights = 0;
			dini_IntSet( file_dini , "Death", 0); //

			GivePlayerMoney(playerid, 1250);

			SendClientMessage(playerid, 0x00FF00FF, "You are successfully registered");
		}
		return 1;
	}

//------------------------------------------------------------------------------

	if ( strcmp( cmd, "/login", true ) == 0 || strcmp( cmd, "/log", true ) == 0)
	{
		tmp = strtok( cmdtext, idx );
		if ( IsLoggedIn( playerid ) ) return SendClientMessage( playerid, 0x0000FFFF, "You are logged.");
		if ( !strlen( tmp ) ) return SendClientMessage( playerid, 0xFF0000ff, "Usage: /login [password]");
		if ( IsRegistered( playerid ) ) return SendClientMessage( playerid, 0x0000FFFF, "This account not registered");

		new tmppass[64];
		strmid(tmppass, tmp, 0, strlen(cmdtext), 255);

		new pass_confirm[ 256 ];
		pass_confirm = dini_Get( file_dini, "Password" );

		if ( strcmp( tmp, pass_confirm, true ) == 0 )
		{
 			format( file_dini, sizeof( file_dini ), Users, GetName(playerid));

	    	//-----------------=-=-=-=------------------------------------------
			PlayerInfo[ playerid ][ pAdmin ] = dini_Int(file_dini,"Admin");
			PlayerInfo[ playerid ][ pDeath ] = dini_Int(file_dini,"Death");
			PlayerInfo[ playerid ][ pScore ] = dini_Int(file_dini,"Score");
			//------------------------------------------------------------------
			PlayerInfo[ playerid ][ pLogged ] = 1; // able to spawn

		
			SpawnPlayer(playerid);
			SendClientMessage( playerid, -1, "You are logged in!" );
		}
		else
		{
        SendClientMessage( playerid, COLOR_DBLUE, "Incorrect password" );
        hacking_password[ playerid ]++;

        switch( hacking_password[ playerid ] )
        {
            case 1: SendClientMessage(playerid, COLOR_YELLOW, "Attempt left: 2");
  			case 2: SendClientMessage(playerid, COLOR_YELLOW, "Attempt left: 1");
  			case 3:
  			{
  			    format( str, sizeof( str ), " %s kicked by hacking password", GetName(playerid));
  			    SendClientMessageToAll(COLOR_DBLUE, str);



  			    Kick(playerid);
  			}
		}
		}
		return 1;
	}
//==============================================================================
	return 1;
}
                                                                                             

 

Finally we did it! But we need to create the system of saving players data...

 

Part 3: Saving Data

Find in your mode public OnPlayerDisconnect

public OnPlayerDisconnect(playerid, reason)
{
	format( file_dini, sizeof( file_dini ), Users, GetName(playerid));
	if(dini_Exists( file_dini ))
	{
		dini_IntSet( file_dini , "Admin", PlayerInfo[ playerid ][ pAdmin ]);
        //----------------------------------------------------------------------
		dini_IntSet( file_dini , "Death", PlayerInfo[ playerid ][ pDeath ]);
		dini_IntSet( file_dini , "Score", PlayerInfo[ playerid ][ pScore ]);
    }
	return 1;
}

 

Now you can test it. Topics in update wait for UPD =)

File to download: Dini.incdudb.incdutils.inc

Edited by adain
  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

I've got some issues connecting with editing my thread, so some fixes to error, add after includes this lines

#define COLOR_GREEN 0x33AA33AA // Green
#define COLOR_RED 0xAA3333AA // Red
#define COLOR_DBLUE 0x00CED1AA // Blue
#define COLOR_YELLOW 0xFFFF00AA // Yellow
/* u can find html color in google, by using -> 'html colors' 
HTML Code -> 0xRRGGBBTT, example -> 0x00FF00FF (very high green for DM or Drift server)*/ 

 

Edited by adain

Share this post


Link to post
Share on other sites
10 минут назад, f0Re3t сказал:

Dini? seriously? you in what century live? long ago came up with mysql already

Do you really think beginners will start scripting from MySQL? MySQL good for everybody who want UCP, but it has disadvantages too, it's very slow. In adddition in RW-MP 0.1.2 i recommend to use Dini.

Firstly, it's very easy to undertand Dini.

Secondly. Dini is absolutely enough for Drifts/DM/Race and even for RP

Thirdly. MySQL is crap of SAMP, that can only give u UCP. Tell who are you without phpMyAdmin? Why do I need to wait for about 1-2 minute to start server. In addition to this now RW-MP is not in state to run Super High AAA+ RP project, that's MySQL is useless for now...

 

And 'Yes' I create this thread for beginners...

Edited by adain

Share this post


Link to post
Share on other sites
1 минуту назад, Albert_Doderman сказал:

 

 

You did not specify the color codes

Please look my second post :)

Share this post


Link to post
Share on other sites
8 часов назад, adain сказал:

Do you really think beginners will start scripting from MySQL? MySQL good for everybody who want UCP, but it has disadvantages too, it's very slow. In adddition in RW-MP 0.1.2 i recommend to use Dini.

Firstly, it's very easy to undertand Dini.

Secondly. Dini is absolutely enough for Drifts/DM/Race and even for RP

Thirdly. MySQL is crap of SAMP, that can only give u UCP. Tell who are you without phpMyAdmin? Why do I need to wait for about 1-2 minute to start server. In addition to this now RW-MP is not in state to run Super High AAA+ RP project, that's MySQL is useless for now...

 

And 'Yes' I create this thread for beginners...

Yes, beginners should start with the fact that more modern and not old shit. mysql slow? who do you laugh then, it performs requests at a rate of 1 in ten thousand per second, your Dini - 1.3 seconds per record and 800 milliseconds to read over 500 files and 64 keys when mysql would have gone on the strength of a couple of milliseconds

Share this post


Link to post
Share on other sites
3 godziny temu, f0Re3t napisał:

Yes, beginners should start with the fact that more modern and not old shit. mysql slow? who do you laugh then, it performs requests at a rate of 1 in ten thousand per second, your Dini - 1.3 seconds per record and 800 milliseconds to read over 500 files and 64 keys when mysql would have gone on the strength of a couple of milliseconds

I agree with this. I had SA-MP server few years ago where i wrote much data for player when player disconnected and with dini server had "global lag" for ~5 seconds. I rewrited all to MySQL and problem disappeared. Additionally I can manage server trough website and create e.g. function to search player stats and display it in SA-MP trough fragment of nickname or IP. I don't know if I can do this trough dini. For me MySQL is better and I'm using it in my every gamemode.

  • Thanks 1

Share this post


Link to post
Share on other sites
10 минут назад, critical сказал:

I agree with this. I had SA-MP server few years ago where i wrote much data for player when player disconnected and with dini server had "global lag" for ~5 seconds. I rewrited all to MySQL and problem disappeared. Additionally I can manage server trough website and create e.g. function to search player stats and display it in SA-MP trough fragment of nickname or IP. I don't know if I can do this trough dini. For me MySQL is better and I'm using it in my every gamemode.

likely, if you do a search on the file name in all categories and read it, and then separation of information, but it will take a lot of very time

Share this post


Link to post
Share on other sites
22 часа назад, adain сказал:

Thirdly. MySQL is crap of SAMP, that can only give u UCP. T

MySQL is CRAP

AHAHAHA ROFL.... Are you seriously? Do you saw other big project not into SAMP/GTA World? Probably not.

 

You think that Facebook or Twitter saving data in files? It's mockery for your hard drive.

  • Like 2

Share this post


Link to post
Share on other sites
21 минуту назад, Twixxx сказал:

dude, ur code is horribly. pls dont share anything like that .-.

Show me please your super-optimized registration. Keybord master.

Edited by adain

Share this post


Link to post
Share on other sites
13 часов назад, adain сказал:

Show me please your super-optimized registration. Keybord master.

lul, ok.

 

#include <dini> // Briefly - to add new functions

#define COLOR_GREEN		0x33AA33AA // Green
#define COLOR_RED 		0xAA3333AA // Red
#define COLOR_DBLUE 	0x00CED1AA // Blue
#define COLOR_YELLOW 	0xFFFF00AA // Yellow

#define MIN_PLAYER_PASSWORD_LENGTH	4
#define MAX_PLAYER_PASSWORD_LENGTH	16

enum e_PLAYER_INFO
{
	pName[MAX_PLAYER_NAME], // player name
	pPass[MAX_PLAYER_PASSWORD_LENGTH],
	pAdmin,
	pDeath,
	pScore
}
new 
	PlayerInfo[MAX_PLAYERS][e_PLAYER_INFO];

#define PlayerName(%0)	PlayerInfo[%0][pName] // you dont even need that bullshit: stock GetName (who even returns STRING DUDE?????!!!!!)

new
	bool:IsPlayerLogged[MAX_PLAYERS char],
	wrongPasswordAttemps[MAX_PLAYERS char]; // use char cause u can use incorret password no more than 3 times

public OnPlayerConnect( playerid )
{
	GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);

	new
		file_dini[13 - 2 + MAX_PLAYER_NAME];

	format(file_dini, sizeof(file_dini), "/Users/%s.ini", PlayerName(playerid));
	IsPlayerLogged{playerid} = false;

	if(dini_Exists(file_dini))
	{
		PlayerInfo[playerid][pPass] = dini_Get(file_dini, "Password");
		SendClientMessage(playerid, -1, !"Usage: /login [password]");
	}
	else
		SendClientMessage(playerid, -1, !"Usage: /register [password]");

	return 1;
}
public OnPlayerDisconnect(playerid, reason)
{
	new
		file_dini[13 - 2 + MAX_PLAYER_NAME];

	format(file_dini, sizeof(file_dini), "/Users/%s.ini", PlayerName(playerid));

	if(dini_Exists(file_dini))
	{
		dini_IntSet(file_dini, "Admin", PlayerInfo[playerid][pAdmin]);
		dini_IntSet(file_dini, "Death", PlayerInfo[playerid][pDeath]);
		dini_IntSet(file_dini, "Score", PlayerInfo[playerid][pScore]);
    }
	return 1;
}

// just use zcmd, dc_cmd etc.
CMD:login(playerid, params[])
{
	if(isnull(params))
		return SendClientMessage(playerid, -1, !"Usage: /login [password]");

	if(IsPlayerLogged{playerid} == true)
		return SendClientMessage(playerid, -1, !"Error: You are already logged in.");

	if(strcmp(PlayerInfo[playerid][pPass], params, true))
	{
		if(wrongPasswordAttemps{playerid} != 0)
			wrongPasswordAttemps{playerid} = 0;

		new
			file_dini[13 - 2 + MAX_PLAYER_NAME];

		format(file_dini, sizeof(file_dini), "/Users/%s.ini", PlayerName(playerid));

		PlayerInfo[playerid][pAdmin] = dini_Int(file_dini, "Admin");
		PlayerInfo[playerid][pDeath] = dini_Int(file_dini, "Death");
		PlayerInfo[playerid][pScore] = dini_Int(file_dini, "Score");
		IsPlayerLogged{playerid} = true;

		SpawnPlayer(playerid);
		SendClientMessage(playerid, -1, !"You are logged in.");
	}
	else
	{
		wrongPasswordAttemps{playerid}++;

		switch(wrongPasswordAttemps{playerid})
        {
            case 1: SendClientMessage(playerid, COLOR_YELLOW, !"Attempt left: 2");
  			case 2: SendClientMessage(playerid, COLOR_YELLOW, !"Attempt left: 1");
  			case 3:
  			{
  				new
  					string[29 - 2 + MAX_PLAYER_NAME];

  			    format(string, sizeof(string), "%s kicked by hacking password", PlayerName(playerid));
  			    SendClientMessageToAll(COLOR_DBLUE, str);

  			    Kick(playerid);
  			}
		}
	}
	return 1;
}
CMD:register(playerid, params[])
{
	if(isnull(params))
		return SendClientMessage(playerid, -1, !"Usage: /register [password]");

	if(IsPlayerLogged{playerid} == true)
		return SendClientMessage(playerid, -1, !"Error: You are already registered.");

	if(!(MIN_PLAYER_PASSWORD_LENGTH <= strlen(params) <= MAX_PLAYER_PASSWORD_LENGTH))
		return 1;

	PlayerInfo[playerid][pPass][0] = EOS;
	strmid(PlayerInfo[playerid][pPass], params, 0, strlen(params), MAX_PLAYER_PASSWORD_LENGTH);

	new
		file_dini[13 - 2 + MAX_PLAYER_NAME];

	format(file_dini, sizeof(file_dini), "/Users/%s.ini", PlayerName(playerid));

	dini_Create(file_dini);

	dini_Set(file_dini, "Password", PlayerInfo[playerid][pPass]);
	dini_IntSet(file_dini , "Admin", 0);
	dini_IntSet(file_dini , "Death", 0);

	GivePlayerMoney(playerid, 1250);

	SpawnPlayer(playerid);
	SendClientMessage(playerid, 0x00FF00FF, !"You are successfully registered.");
	
	return 1;
}

thats all, cutie, w/o all ur "beautiful" code.

Edited by Twixxx

Share this post


Link to post
Share on other sites
В 17.01.2018 в 13:55, Twixxx сказал:

thats all, cutie, w/o all ur "beautiful" code.

Yes your code is not bad but it doesn't mean that it's better than mine. I do not use zcmd, dcmd, or any other, only default.

Edited by adain

Share this post


Link to post
Share on other sites
5 часов назад, adain сказал:

Yes your code is not bad but it doesn't mean that it's better than mine. I do not use zcmd, dcmd, or any other, only default.

lol why that doenst mean that my code is better than yours? that means, dude. And if ur staying with strcmp - ok, np, keep doing crutch with ur code.
if u cant understand why ur code is ... bad - just write me (i know ur russian): vk.com/twixyck.

Edited by Twixxx

Share this post


Link to post
Share on other sites
В 21.01.2018 в 18:21, s2sk сказал:

Шел 2018 год. Люди до сих пор думали что файлы проще баз данных и использовали Dini|MXINI. Этот мир деградирует на глазах.

 

С чего-то надо начинать, почему нет? Причем тут деградация? С точки зрения облегченной работы (я  веду речь о использовании SQL и различных СУБД) - да, это легче, так как не придется таскать туда-сюда кучу файлов с аккаунтами и т.д. Но для начальной разработки, так сказать, чтобы вникнуть в суть - сойдет.

Edited by 0x23C023

Share this post


Link to post
Share on other sites
Posted (edited)
On 14.01.2018 at 10:10 PM, adain said:

Do you really think beginners will start scripting from MySQL? MySQL good for everybody who want UCP, but it has disadvantages too, it's very slow. In adddition in RW-MP 0.1.2 i recommend to use Dini.

Firstly, it's very easy to undertand Dini.

Secondly. Dini is absolutely enough for Drifts/DM/Race and even for RP

Thirdly. MySQL is crap of SAMP, that can only give u UCP. Tell who are you without phpMyAdmin? Why do I need to wait for about 1-2 minute to start server. In addition to this now RW-MP is not in state to run Super High AAA+ RP project, that's MySQL is useless for now...

 

And 'Yes' I create this thread for beginners...

I think beginners should start with more advantageous things. Only for UCP? Let's reason logically, why, then, does most people use MySQL? Why not files? And above all, MySQL cannot be slower.

At least let's look at the dini algorithm. For example, the function dini_Exists:

stock  dini_Exists(filename[]) {
	if (fexist(filename)) return true;
	return false;
}

So, what do we have: dini_Exists call fexist, but do you really think it's very fast? Then look at this code. Also, functions are called there that have even more operations. This I'm not talking about dini_Set & dini_Get.

 

Firstly, there are lot of tutorials on the internet, or at least documentations on the wiki.

Secondly, why MySQL not enough?

Thirdly, UCP is only one of advantages, I think many should understand this. And HOW can instability make MySQL useless?

You advise beginners to use something that would not be worth.

 

And do not you think that the code using MySQL will be more readable?

Edited by KashCherry
  • Like 2

Share this post


Link to post
Share on other sites
Posted (edited)

If you think about it, didn't you got  the idea for new tutorial? (The same tutorial but with mysql). If you need help, you can write me in discord.

Edited by KashCherry

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.

×