SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help > Tutorials

Reply
 
Thread Tools Display Modes
Old 29/01/2017, 02:39 PM   #11
DerickClark
High-roller
 
DerickClark's Avatar
 
Join Date: Jul 2012
Posts: 1,570
Reputation: 9
Default Re: MySQL [R41-2] Registration System

Hmm i might update my password with hash and salt.
only have hash.

My code is Different from this tho

Good tut.
__________________
LS-CNR
DerickClark is offline   Reply With Quote
Old 29/01/2017, 02:49 PM   #12
X337
Banned
 
Join Date: Sep 2014
Location: Indonesia
Posts: 823
Reputation: 174
Default Re: MySQL [R41-2] Registration System

Well explained, thank you for this tutorial.
X337 is offline   Reply With Quote
Old 29/01/2017, 03:07 PM   #13
Gammix
High-roller
 
Gammix's Avatar
 
Join Date: Jan 2015
Location: Ottawa, Canada
Posts: 1,603
Reputation: 612
Default Re: MySQL [R41-2] Registration System

Quote:
Originally Posted by Variable™ View Post
I won't talk too much, I have debugged what you have said above just to show that your statements are wrong. Well, I have made a message prints to the log once the server shuts down with the "/rcon exit" method.

My OnPlayerDisconnect Code:
Code:
public OnPlayerDisconnect(playerid, reason)
{
	Corrupt_Check[playerid]++;

	new DB_Query[256];
	//Running a query to save the player's data using the stored stuff.
	mysql_format(Database, DB_Query, sizeof(DB_Query), "UPDATE `PLAYERS` SET `SCORE` = %d, `CASH` = %d, `KILLS` = %d, `DEATHS` = %d WHERE `ID` = %d LIMIT 1",
	pInfo[playerid][Score], pInfo[playerid][Cash], pInfo[playerid][Kills], pInfo[playerid][Deaths], pInfo[playerid][ID]);

	mysql_tquery(Database, DB_Query);

	if(cache_is_valid(pInfo[playerid][Player_Cache])) //Checking if the player's cache ID is valid.
	{
		cache_delete(pInfo[playerid][Player_Cache]); // Deleting the cache.
		pInfo[playerid][Player_Cache] = MYSQL_INVALID_CACHE; // Setting the stored player Cache as invalid.
	}

	pInfo[playerid][LoggedIn] = 0;
	print("OnPlayerDisconnect has been called."); // Sending message once OnPlayerDisconnect is called.
	return 1;
}
The result of the code:
Code:
[13:40:00] [connection] 10.42.0.74:61008 requests connection cookie.
[13:40:01] [connection] incoming connection: 10.42.0.74:61008 id: 0
[13:40:01] [join] Variable has joined the server (0:10.42.0.74)
[13:40:12] RCON (In-Game): Player #0 (Variable) has logged in.
[13:40:14] RCON (In-Game): Player [Variable] sent command: exit
[13:40:14] --- Server Shutting Down.
[13:40:14] OnPlayerDisconnect has been called.
[13:40:15] [part] Variable has left the server (0:0)
You saw the message being sent twice in the log? Nope.
Hopefully you'll next time make sure of what you state before you do and thanks.

You can also try that by yourself.

=======================================

Would like to make sure the OnPlayerDisconnect doesn't get called twice? Here's another evidence!

When I removed the part from OnGameModeExit, the message didn't show anymore.

Code:
public OnGameModeExit()
{
/*    for(new i = 0, j = GetPlayerPoolSize(); i <= j; i++) // Getting the highest player ID in the game.
    {
		if(IsPlayerConnected(i)) // Checking if the players stored in "i" are connected.
		{
			OnPlayerDisconnect(i, 1); // We do that so players wouldn't lose their data upon server's close.
		}
	}*/

	mysql_close(Database); // Closing the database.
	return 1;
}
Same stuff at OnPlayerDisconnect, as in this code:
Code:
public OnPlayerDisconnect(playerid, reason)
{
	Corrupt_Check[playerid]++;

	new DB_Query[256];
	//Running a query to save the player's data using the stored stuff.
	mysql_format(Database, DB_Query, sizeof(DB_Query), "UPDATE `PLAYERS` SET `SCORE` = %d, `CASH` = %d, `KILLS` = %d, `DEATHS` = %d WHERE `ID` = %d LIMIT 1",
	pInfo[playerid][Score], pInfo[playerid][Cash], pInfo[playerid][Kills], pInfo[playerid][Deaths], pInfo[playerid][ID]);

	mysql_tquery(Database, DB_Query);

	if(cache_is_valid(pInfo[playerid][Player_Cache])) //Checking if the player's cache ID is valid.
	{
		cache_delete(pInfo[playerid][Player_Cache]); // Deleting the cache.
		pInfo[playerid][Player_Cache] = MYSQL_INVALID_CACHE; // Setting the stored player Cache as invalid.
	}

	pInfo[playerid][LoggedIn] = 0;
	print("OnPlayerDisconnect has been called."); // Sending message once OnPlayerDisconnect is called.
	return 1;
}
The result from the log:
Code:
[13:57:34] [connection] 10.42.0.74:61529 requests connection cookie.
[13:57:35] [connection] incoming connection: 10.42.0.74:61529 id: 0
[13:57:35] [join] Variable has joined the server (0:10.42.0.74)
[13:57:49] RCON (In-Game): Player #0 (Variable) has logged in.
[13:57:52] RCON (In-Game): Player [Variable] sent command: exit
[13:57:52] --- Server Shutting Down.
[13:57:52] [part] Variable has left the server (0:0)
Seen the log message? Nothing has been called as the message didn't print to the log, that means its not even called. So, if I don't use my way, no one's stats will be saved once server closes.

For "/rcon gmx" method
  • If you kick at OnGameModeExit it'll call OnPlayerDisconnect, if you don't do anything at OnGameModeExit, once you close the server, no one's stats will be saved and will just save if you RESTART server only.

Which means, my solution is the finest for now.
That might only be the case for "/rcon exit", cause it is generally called when gamemode exits. Even at "changemode" or "gmx", OnPlayerDisconnect is called properly. I would rather hook "/rcon exit" with saving player data than doing it always when gamemode exits.
But anyways gamemode exit happens only once or twice in a long time period unless your mode requires gamemode switching for new rounds/games, where this could be concern for developers.
__________________

Howz it going?!


Gammix is offline   Reply With Quote
Old 29/01/2017, 08:20 PM   #14
PowerPC603
High-roller
 
Join Date: Nov 2010
Location: Belgium
Posts: 1,752
Reputation: 238
Default Re: MySQL [R41-2] Registration System

I don't see why you save a cache for later use.

When a player connects, just load his ID in the database that matches his name and load the hashed password and salt, store all 3 (password, salt and ID) in the array pInfo and ShowPlayerDialog to input a password.
Then in that callback (OnDialogResponse), check if the hashed input is the same as the stored hashed password.
If so, send a new query to load the remaining data and store that as well in your pInfo array.

No need to save cache and having to remember to delete it later on.



Also, saving everything inside OnPlayerDisconnect is also questionable.
With so little data, it won't matter that much.
But once you have a huge gamemode, you'll want to split up datasaving.



In my gamemode, I have so much data that my query would be at least 5000 characters long when I would save everything at once in one huge query upon logging out.

Just save whatever changes using a small query and save it immediately.

A player gets money? Save it.
A player receives a scorepoint? Save it.

A player buys a vehicle or a house? Save the money with one query, and update the housedata with a second query.

I'm having a full-blown auction system in my gamemode to auction houses and vehicles to other players, all controlled via one single menu built with textdraws (my vehicle-menu).

Players can place bids on houses and the system also has an automatic system linked to it.
Once a house is put up for auction, the house will automatically transferred to the highest bidder who has the money for it after 7 days, even when both parties (seller and buyer) are offline.
If no bids were there, or nobody has the money for it, the house goes to the bank.
Also vehicles can be browsed that are put up for auction.

House-owners also need to pay a weekly maintenance fee to keep their houses and vehicles.
If they can't afford it, the house is automatically put up for auction along with the vehicles linked to that house.

Doing such a system with queries only inside OnPlayerDisconnect is mindblowing and practically impossible to do.

If I would only save whenever the server shuts down, the server would need several thousand huge queries to update every house on the server,
every house-vehicle (which could be several tens of thousands), just in case something was edited.

Just save whatever needs to be saved at the moment it changes, and use small queries to do it.

Nothing as easy as a function like this:
PHP Code:
// This function is used to give (or take) money to/from the player
Player_GiveMoney(playeridamount)
{
    
// Setup local variables
    
new query[128];

    
// Add the given Money to the player's account
    
APlayerData[playerid][Money] = APlayerData[playerid][Money] + amount;

    
// Also update the client immediately instead of waiting for the GlobalTimer1000 to update it
    
ResetPlayerMoney(playerid);
    
GivePlayerMoney(playeridAPlayerData[playerid][Money]);

    
// Update money for this player in the player's account in MySQL
    
mysql_format(SQL_dbquerysizeof(query), "UPDATE playerdata SET Money = '%i' WHERE UserID = '%i'"APlayerData[playerid][Money], APlayerData[playerid][UserID]);
    
mysql_tquery(SQL_dbquery"""");

    return 
1;

Whenever a player gets money or pays money, his account in the database has also been updated at once.

That way, you can also lose the Corrupt_Check thing, whatever it does.
The data was already saved while playing, logging in fast after a player disconnects won't corrupt data as there is nothing saved in there.



What if your server suddenly crashes? Then nothing would be saved for hours.
You'll lose hours of progress of your players, who in turn will not be happy because they need to spend hours again to get back what was lost.


The only thing I'm saving in my OnPlayerDisconnect callback, is the fuel for all my house-vehicles, as fuel changes every second while driving, this would mean one query per second per vehicle and is too much at once.
And for the rest of the code in there, is to delete the house-vehicles from the server's memory when a player logs out and clearing variables.



When creating an account, add some default values for values to shorten the INSERT query as well upon registering.
Since score, kills, deaths and cash are 0 to begin with, you can simply have MySQL fill in those for you automatically when your table has default values of 0 assigned to those columns.



Also, clearing an array with an enum is much easier than clearing every variable one by one.
You can clear them all at once for a single player.

Instead of doing:
PHP Code:
//Resetting player information.
pInfo[playerid][Kills] = 0;
pInfo[playerid][Deaths] = 0;
pInfo[playerid][PasswordFails] = 0
You can do:
PHP Code:
new clean[ENUM_PLAYER_DATA];
pInfo[playerid] = clean
Not much of a space-saver here, but you never have to edit that code again when you add a variable to the enum.
So less likely to forget to clear one.
__________________
Gamemode: PPC_Trucking
Extras-file (for PPC_Trucking): /delproperty, /evict, /propertyid, /porthouse, /portbus, /properties
------------------------------------------------------------------------------------
PPC-Trucking-V2 (home-hosted, only open on occasion for testing purposes): ppctruckingv2.no-ip.info:7777
Youtube channel: https://www.youtube.com/channel/UC-4...Mpglma8f0Ld-YQ
------------------------------------------------------------------------------------
Filterscripts: PPC_Speedometer - PPC_Housing - PPC_Business
PowerPC603 is offline   Reply With Quote
Old 09/02/2017, 02:09 PM   #15
princejeet1510
Big Clucker
 
princejeet1510's Avatar
 
Join Date: Mar 2016
Location: Trying to figure it out.
Posts: 117
Reputation: 4
Default Re: MySQL [R41-2] Registration System

Learned from it a lot....But can you explain ORM....I just need to know some basics of it.
__________________
princejeet1510 is offline   Reply With Quote
Old 09/02/2017, 05:12 PM   #16
Variable™
Gangsta
 
Variable™'s Avatar
 
Join Date: Jul 2015
Location: Fort Carson
Posts: 592
Reputation: 95
Default Re: MySQL [R41-2] Registration System

Will make another tutorial for the use of ORM in a new thread soon!
__________________
Variable™ is offline   Reply With Quote
Old 13/02/2017, 03:21 PM   #17
Runn3R
Huge Clucker
 
Runn3R's Avatar
 
Join Date: Dec 2013
Location: Croatia, Split
Posts: 381
Reputation: 35
Default Re: MySQL [R41-2] Registration System

Quote:
Originally Posted by Gammix View Post
That might only be the case for "/rcon exit", cause it is generally called when gamemode exits. Even at "changemode" or "gmx", OnPlayerDisconnect is called properly. I would rather hook "/rcon exit" with saving player data than doing it always when gamemode exits.
But anyways gamemode exit happens only once or twice in a long time period unless your mode requires gamemode switching for new rounds/games, where this could be concern for developers.

And this is why folks you always update the data on the go.

If the player recieved some money from somewhere update it! Is it so hard to make a query instead of making 5 big queries to handle all of that in one blast? I don't think so.
Runn3R is offline   Reply With Quote
Old 25/02/2017, 06:26 PM   #18
TheLeech
Big Clucker
 
Join Date: Aug 2015
Location: Under your bed
Posts: 59
Reputation: 3
Default Re: MySQL [R41-2] Registration System

Anyone else having the issue that when you restart the server, Players can log into the accounts using any password?
TheLeech is offline   Reply With Quote
Old 27/02/2017, 05:48 AM   #19
Sabur
Big Clucker
 
Join Date: Jul 2013
Posts: 80
Reputation: 15
Default Re: MySQL [R41-2] Registration System

What you basically did is copy example login-system-cache from mysql github and changed some variables name and released it as a tutorial.
https://raw.githubusercontent.com/pB...stem-cache.pwn
Sabur is offline   Reply With Quote
Old 27/02/2017, 11:02 PM   #20
Variable™
Gangsta
 
Variable™'s Avatar
 
Join Date: Jul 2015
Location: Fort Carson
Posts: 592
Reputation: 95
Default Re: MySQL [R41-2] Registration System

Quote:
Originally Posted by Sabur View Post
What you basically did is copy example login-system-cache from mysql github and changed some variables name and released it as a tutorial.
https://raw.githubusercontent.com/pB...stem-cache.pwn
Quite funny that people without a sufficient enough experience are arguing for nothing, who don't even know that it doesn't mean someone is copying pieces of codes in case of similarities. You can't just say that an admin script is like all the others because both have /ban command, pal. My code is quite different and just a small similarity which doesn't mean that I copied it.

@TheLeech: Impossible, make sure you have properly copied and assigned the codes as explained above.

Last edited by Variable™; 09/06/2017 at 10:53 AM.
Variable™ is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Simple MySQL registration system ? sampkinq Scripting Help 2 01/07/2016 07:40 PM
[HELP] Problem with MySQL Registration system dudu.r.oliveira Scripting Help 6 14/06/2015 05:05 AM
[Tutorial] [VIDEO] MySQL ORM r38: How to pair GM with MySQL & creation of registration/connection system cArnasLT Tutorials 3 19/05/2014 02:08 PM
[FilterScript] Advanced registration system (MySQL) iRaiDeN Filterscripts 19 05/05/2014 10:46 AM
[MySQL] Advanced Registration System Carlton Filterscripts 52 11/04/2014 07:23 AM


All times are GMT. The time now is 04:54 PM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.