Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <a_samp>
- // change MAX_PLAYERS to the amount of players (slots) you want
- // It is by default 1000 (as of 0.3.7 version)
- #undef MAX_PLAYERS
- #define MAX_PLAYERS 100
- #include <a_mysql>
- // MySQL configuration
- #define MYSQL_HOST "127.0.0.1"
- #define MYSQL_USER "root"
- #define MYSQL_PASSWORD "11211121"
- #define MYSQL_DATABASE "samp"
- // how many seconds until it kicks the player for taking too long to login
- #define SECONDS_TO_LOGIN 30
- // default spawn point: Las Venturas (The High Roller)
- #define DEFAULT_POS_X 1958.3783
- #define DEFAULT_POS_Y 1343.1572
- #define DEFAULT_POS_Z 15.3746
- #define DEFAULT_POS_A 270.1425
- #define DEFAULT_SKIN 264
- // MySQL connection handle
- new MySQL: g_SQL;
- // player data
- enum E_PLAYERS
- {
- ID,
- Name[MAX_PLAYER_NAME],
- Password[65], // the output of SHA256_PassHash function (which was added in 0.3.7 R1 version) is always 256 bytes in length, or the equivalent of 64 Pawn cells
- Salt[17],
- Kills,
- Deaths,
- Float: Pos_X,
- Float: Pos_Y,
- Float: Pos_Z,
- Float: Pos_A,
- Interior,
- Skin,
- Account,
- Cache: Cache_ID,
- bool: IsLoggedIn,
- LoginAttempts,
- LoginTimer
- };
- new Player[MAX_PLAYERS][E_PLAYERS];
- new g_MysqlRaceCheck[MAX_PLAYERS];
- // dialog data
- enum
- {
- DIALOG_UNUSED,
- DIALOG_LOGIN,
- DIALOG_REGISTER
- };
- main() {}
- public OnGameModeInit()
- {
- new MySQLOpt: option_id = mysql_init_options();
- mysql_set_option(option_id, AUTO_RECONNECT, true); // it automatically reconnects when loosing connection to mysql server
- g_SQL = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DATABASE, option_id); // AUTO_RECONNECT is enabled for this connection handle only
- if (g_SQL == MYSQL_INVALID_HANDLE || mysql_errno(g_SQL) != 0)
- {
- print("MySQL connection failed. Server is shutting down.");
- SendRconCommand("exit"); // close the server if there is no connection
- return 1;
- }
- print("MySQL connection is successful.");
- return 1;
- }
- public OnGameModeExit()
- {
- // save all player data before closing connection
- for (new i = 0, j = GetPlayerPoolSize(); i <= j; i++) // GetPlayerPoolSize function was added in 0.3.7 version and gets the highest playerid currently in use on the server
- {
- if (IsPlayerConnected(i))
- {
- // reason is set to 1 for normal 'Quit'
- OnPlayerDisconnect(i, 1);
- }
- }
- mysql_close(g_SQL);
- return 1;
- }
- public OnPlayerConnect(playerid)
- {
- g_MysqlRaceCheck[playerid]++;
- ResetPlayerData(playerid);
- return 1;
- }
- public OnPlayerRequestClass(playerid, classid)
- {
- if (Player[playerid][IsLoggedIn] == false)
- {
- TogglePlayerSpectating(playerid, true);
- SetTimerEx("OnPlayerRequestClassEx", 400, false, "d", playerid); // 400 ms
- return 0;
- }
- else if(Player[playerid][IsLoggedIn] == true)
- {
- SpawnPlayer(playerid);
- return 0;
- }
- else return 0;
- }
- forward OnPlayerRequestClassEx(playerid);
- public OnPlayerRequestClassEx(playerid)
- {
- OnPlayerConnectEx(playerid);
- SetPlayerCamera(playerid);
- return 1;
- }
- OnPlayerConnectEx(playerid) {
- GetPlayerName(playerid, Player[playerid][Name], MAX_PLAYER_NAME);
- // send a query to recieve all the stored player data from the table
- new query[103];
- mysql_format(g_SQL, query, sizeof query, "SELECT * FROM `players` WHERE `Username` = '%e' LIMIT 1", Player[playerid][Name]);
- mysql_tquery(g_SQL, query, "OnPlayerDataLoaded", "dd", playerid, g_MysqlRaceCheck[playerid]);
- }
- SetPlayerCamera(playerid)
- {
- SetPlayerCameraPos(playerid, 1249.3018, -1697.8046, 99.9554);
- SetPlayerCameraLookAt(playerid, 1249.6576, -1696.8656, 99.4902);
- return 1;
- }
- public OnPlayerDisconnect(playerid, reason)
- {
- g_MysqlRaceCheck[playerid]++;
- UpdatePlayerData(playerid, reason);
- // if the player was kicked (either wrong password or taking too long) during the login part, remove the data from the memory
- if (cache_is_valid(Player[playerid][Cache_ID]))
- {
- cache_delete(Player[playerid][Cache_ID]);
- Player[playerid][Cache_ID] = MYSQL_INVALID_CACHE;
- }
- // if the player was kicked before the time expires (30 seconds), kill the timer
- if (Player[playerid][LoginTimer])
- {
- KillTimer(Player[playerid][LoginTimer]);
- Player[playerid][LoginTimer] = 0;
- }
- // sets "IsLoggedIn" to false when the player disconnects, it prevents from saving the player data twice when "gmx" is used
- Player[playerid][IsLoggedIn] = false;
- return 1;
- }
- public OnPlayerSpawn(playerid)
- {
- // spawn the player to their last saved position
- SetPlayerInterior(playerid, Player[playerid][Interior]);
- SetPlayerPos(playerid, Player[playerid][Pos_X], Player[playerid][Pos_Y], Player[playerid][Pos_Z]);
- SetPlayerFacingAngle(playerid, Player[playerid][Pos_A]);
- SetPlayerSkin(playerid, Player[playerid][Skin]);
- SetCameraBehindPlayer(playerid);
- return 1;
- }
- public OnPlayerDeath(playerid, killerid, reason)
- {
- return 1;
- }
- public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
- {
- switch (dialogid)
- {
- case DIALOG_UNUSED: return 1; // Useful for dialogs that contain only information and we do nothing depending on whether they responded or not
- case DIALOG_LOGIN:
- {
- if (!response) return Kick(playerid);
- new hashed_pass[65];
- SHA256_PassHash(inputtext, Player[playerid][Salt], hashed_pass, 65);
- if (strcmp(hashed_pass, Player[playerid][Password]) == 0)
- {
- // sets the specified cache as the active cache so we can retrieve the rest player data
- cache_set_active(Player[playerid][Cache_ID]);
- AssignPlayerData(playerid);
- // remove the active cache from memory and unsets the active cache as well
- cache_delete(Player[playerid][Cache_ID]);
- Player[playerid][Cache_ID] = MYSQL_INVALID_CACHE;
- KillTimer(Player[playerid][LoginTimer]);
- Player[playerid][LoginTimer] = 0;
- Player[playerid][IsLoggedIn] = true;
- TogglePlayerSpectating(playerid, false);
- // spawn the player to their last saved position after login
- SetSpawnInfo(playerid, NO_TEAM, DEFAULT_SKIN, Player[playerid][Pos_X], Player[playerid][Pos_Y], Player[playerid][Pos_Z], Player[playerid][Pos_A], 0, 0, 0, 0, 0, 0);
- SpawnPlayer(playerid);
- }
- else
- {
- Player[playerid][LoginAttempts]++;
- if (Player[playerid][LoginAttempts] >= 3)
- {
- ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "[Login step]", "¤Ø³ãÊèÃËÑʼèÒ¹¼Ô´¶Ö§ 3 ¤ÃÑé§, ¨Ö§â´¹ÃкºàµÐÍÍ¡¨Ò¡à«ÔÃì¿àÇÍÃì", "»Ô´", "");
- DelayedKick(playerid);
- }
- else ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "[Login step]", "ÃËÑʼèÒ¹äÁè¶Ù¡µéͧ!\n**¡ÃسÒãÊèÃËÑʼèÒ¹à¾×èÍà¢éÒàÅè¹à¡Á!", "à¢éÒà¡Á", "¡àÅÔ¡");
- }
- }
- case DIALOG_REGISTER:
- {
- if (!response) return Kick(playerid);
- if (strlen(inputtext) <= 3) return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "[Registration step]", "**ÃËÑʼèÒ¹¤ÇÃÁÕÁÒ¡¡ÇèÒ 3 µÑÇÍÑ¡ÉÃ\n***¡ÃسÒãÊèÃËÑʼèÒ¹à¾×èÍŧ·ÐàºÕ¹", "ŧ·ÐàºÕ¹", "¡àÅÔ¡");
- // 16 random characters from 33 to 126 (in ASCII) for the salt
- for (new i = 0; i < 16; i++) Player[playerid][Salt][i] = random(94) + 33;
- SHA256_PassHash(inputtext, Player[playerid][Salt], Player[playerid][Password], 65);
- new query[221];
- mysql_format(g_SQL, query, sizeof query, "INSERT INTO `players` (`Username`, `Password`, `Salt`) VALUES ('%e', '%s', '%e')", Player[playerid][Name], Player[playerid][Password], Player[playerid][Salt]);
- mysql_tquery(g_SQL, query, "OnPlayerRegister", "d", playerid);
- }
- default: return 0; // dialog ID was not found, search in other scripts
- }
- return 1;
- }
- //-----------------------------------------------------
- forward OnPlayerDataLoaded(playerid, race_check);
- public OnPlayerDataLoaded(playerid, race_check)
- {
- /* race condition check:
- player A connects -> SELECT query is fired -> this query takes very long
- while the query is still processing, player A with playerid 2 disconnects
- player B joins now with playerid 2 -> our laggy SELECT query is finally finished, but for the wrong player
- what do we do against it?
- we create a connection count for each playerid and increase it everytime the playerid connects or disconnects
- we also pass the current value of the connection count to our OnPlayerDataLoaded callback
- then we check if current connection count is the same as connection count we passed to the callback
- if yes, everything is okay, if not, we just kick the player
- */
- if (race_check != g_MysqlRaceCheck[playerid]) return Kick(playerid);
- new string[115];
- if(cache_num_rows() > 0)
- {
- // we store the password and the salt so we can compare the password the player inputs
- // and save the rest so we won't have to execute another query later
- cache_get_value(0, "Password", Player[playerid][Password], 65);
- cache_get_value(0, "Salt", Player[playerid][Salt], 17);
- // saves the active cache in the memory and returns an cache-id to access it for later use
- Player[playerid][Cache_ID] = cache_save();
- format(string, sizeof string, "ÊÇÑʴդس (%s), ÂÔ¹´Õµé͹ÃѺà¢éÒÊÙèà«ÔÃì¿àÇÍÃì\n**¡ÃسÒãÊèÃËÑʼèÒ¹à¾×èÍà¢éÒàÅè¹à¡Á!", Player[playerid][Name]);
- ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "[Login step]", string, "à¢éÒà¡Á!", "¡àÅÔ¡");
- // from now on, the player has 30 seconds to login
- Player[playerid][LoginTimer] = SetTimerEx("OnLoginTimeout", SECONDS_TO_LOGIN * 1000, false, "d", playerid);
- }
- else
- {
- format(string, sizeof string, "ÊÇÑʴդس (%s), ÂÔ¹´Õµé͹ÃѺà¢éÒÊÙèà«ÔÃì¿àÇÍÃì\n***¡ÃسÒãÊèÃËÑʼèÒ¹à¾×èÍŧ·ÐàºÕ¹", Player[playerid][Name]);
- ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "[Registration step]", string, "ŧ·ÐàºÕ¹", "¡àÅÔ¡");
- }
- return 1;
- }
- forward OnLoginTimeout(playerid);
- public OnLoginTimeout(playerid)
- {
- // reset the variable that stores the timerid
- Player[playerid][LoginTimer] = 0;
- ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "[Login step]", "¤Ø³¶Ù¡àµÐÍÍ¡¨Ò¡à«ÔÃì¿àÇÍÃìà¾ÃÒФس AFK", "»Ô´", "");
- DelayedKick(playerid);
- return 1;
- }
- forward OnPlayerRegister(playerid);
- public OnPlayerRegister(playerid)
- {
- // retrieves the ID generated for an AUTO_INCREMENT column by the sent query
- Player[playerid][ID] = cache_insert_id();
- new string[115];
- format(string, sizeof string, "ÊÇÑʴդس (%s), ÂÔ¹´Õµé͹ÃѺà¢éÒÊÙèà«ÔÃì¿àÇÍÃì\n**¡ÃسÒãÊèÃËÑʼèÒ¹à¾×èÍà¢éÒàÅè¹à¡Á!", Player[playerid][Name]);
- ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "[Login step]", string, "à¢éÒà¡Á!", "¡àÅÔ¡");
- return 1;
- }
- forward _KickPlayerDelayed(playerid);
- public _KickPlayerDelayed(playerid)
- {
- Kick(playerid);
- return 1;
- }
- //-----------------------------------------------------
- ResetPlayerData(playerid)
- {
- Player[playerid][IsLoggedIn] = false;
- Player[playerid][Kills] = 0;
- Player[playerid][Deaths] = 0;
- Player[playerid][Pos_X] = DEFAULT_POS_X;
- Player[playerid][Pos_Y] = DEFAULT_POS_Y;
- Player[playerid][Pos_Z] = DEFAULT_POS_Z;
- Player[playerid][Pos_A] = DEFAULT_POS_A;
- Player[playerid][Interior] = 0;
- Player[playerid][Skin] = DEFAULT_SKIN;
- Player[playerid][Account] = 0;
- return 1;
- }
- AssignPlayerData(playerid)
- {
- cache_get_value_int(0, "ID", Player[playerid][ID]);
- cache_get_value_int(0, "Kills", Player[playerid][Kills]);
- cache_get_value_int(0, "Deaths", Player[playerid][Deaths]);
- cache_get_value_float(0, "PosX", Player[playerid][Pos_X]);
- cache_get_value_float(0, "PosY", Player[playerid][Pos_Y]);
- cache_get_value_float(0, "PosZ", Player[playerid][Pos_Z]);
- cache_get_value_float(0, "PosA", Player[playerid][Pos_A]);
- cache_get_value_int(0, "Interior", Player[playerid][Interior]);
- cache_get_value_int(0, "Skin", Player[playerid][Skin]);
- cache_get_value_int(0, "Account", Player[playerid][Account]);
- return 1;
- }
- DelayedKick(playerid, time = 500)
- {
- SetTimerEx("_KickPlayerDelayed", time, false, "d", playerid);
- return 1;
- }
- UpdatePlayerData(playerid, reason)
- {
- if (Player[playerid][IsLoggedIn] == false) return 0;
- // if the client crashed, it's not possible to get the player's position in OnPlayerDisconnect callback
- // so we will use the last saved position (in case of a player who registered and crashed/kicked, the position will be the default spawn point)
- if (reason == 1)
- {
- GetPlayerPos(playerid, Player[playerid][Pos_X], Player[playerid][Pos_Y], Player[playerid][Pos_Z]);
- GetPlayerFacingAngle(playerid, Player[playerid][Pos_A]);
- }
- new query[2048];
- mysql_format(g_SQL, query, sizeof query, "UPDATE `players` SET `PosX` = %f, `PosY` = %f, `PosZ` = %f, `PosA` = %f, `Interior` = %d, `Kills` = %d, `Deaths` = %d, \
- `Skin` = %d, `Account` = %d WHERE `ID` = %d LIMIT 1",
- Player[playerid][Pos_X], Player[playerid][Pos_Y], Player[playerid][Pos_Z], Player[playerid][Pos_A], GetPlayerInterior(playerid), Player[playerid][Kills],
- Player[playerid][Deaths], Player[playerid][Skin], Player[playerid][Account], Player[playerid][ID]);
- mysql_tquery(g_SQL, query);
- return 1;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement