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 50
- #include <a_mysql>
- #include <zcmd>
- #include <sscanf2>
- // MySQL configuration
- #define MYSQL_HOST "127.0.0.1"
- #define MYSQL_USER "root"
- #define MYSQL_PASSWORD "11211121"
- #define MYSQL_DATABASE "samp"
- // Reverse function
- #define function:%0(%1) forward %0(%1); public %0(%1)
- // how many seconds until it kicks the player for taking too long to login
- #define SECONDS_TO_LOGIN 30
- // Spawn players points
- #define SPAWN_POINT_AIRPORT (0)
- // MySQL connection handle
- new MySQL: g_SQL;
- // WP_hash
- native WP_Hash(buffer[], len, const str[]);
- // player data
- enum E_PLAYERS
- {
- pID,
- pName[MAX_PLAYER_NAME],
- pPassword[129],
- pKills,
- pDeaths,
- Float: pPosX,
- Float: pPosY,
- Float: pPosZ,
- Float: pPosA,
- pInterior,
- pInjured,
- pSpawnPoint,
- pSkin,
- Cache: Cache_ID,
- bool: IsLoggedIn,
- LoginAttempts,
- LoginTimer
- };
- new PlayerInfo[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;
- }
- mysql_log(ALL);
- 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;
- }
- function:Camera(playerid)
- {
- SetPlayerCameraPos(playerid, 1849.9003, -1428.3875, 295.0201);
- SetPlayerCameraLookAt(playerid, 1849.0439, -1427.8647, 294.7950);
- print("Camera running");
- return 1;
- }
- public OnPlayerConnect(playerid)
- {
- g_MysqlRaceCheck[playerid]++;
- // reset player data
- ResetPlayer(playerid);
- /* static const empty_player[E_PLAYERS];
- PlayerInfo[playerid] = empty_player;*/
- GetPlayerName(playerid, PlayerInfo[playerid][pName], MAX_PLAYER_NAME);
- Camera(playerid);
- // 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", PlayerInfo[playerid][pName]);
- mysql_tquery(g_SQL, query, "OnPlayerDataLoaded", "dd", playerid, g_MysqlRaceCheck[playerid]);
- print("OnPlayerConnect running");
- 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(PlayerInfo[playerid][Cache_ID]))
- {
- cache_delete(PlayerInfo[playerid][Cache_ID]);
- PlayerInfo[playerid][Cache_ID] = MYSQL_INVALID_CACHE;
- }
- // if the player was kicked before the time expires (30 seconds), kill the timer
- if (PlayerInfo[playerid][LoginTimer])
- {
- KillTimer(PlayerInfo[playerid][LoginTimer]);
- PlayerInfo[playerid][LoginTimer] = 0;
- }
- // sets "IsLoggedIn" to false when the player disconnects, it prevents from saving the player data twice when "gmx" is used
- PlayerInfo[playerid][IsLoggedIn] = false;
- return 1;
- }
- public OnPlayerRequestClass(playerid, classid)
- {
- if (PlayerInfo[playerid][IsLoggedIn] == false)
- {
- Camera(playerid);
- TogglePlayerSpectating(playerid, true);
- print("OnPlayerRequestClass running");
- return 0;
- }
- else if(PlayerInfo[playerid][IsLoggedIn] == true)
- {
- SetSpawnInfo(playerid, 0, PlayerInfo[playerid][pSkin], PlayerInfo[playerid][pPosX], PlayerInfo[playerid][pPosY], PlayerInfo[playerid][pPosZ], PlayerInfo[playerid][pPosA], 0, 0, 0, 0, 0, 0);
- SpawnPlayer(playerid);
- print("OnPlayerRequestClass Login running");
- return 0;
- }
- else return 0;
- }
- public OnPlayerSpawn(playerid)
- {
- SetPlayersSpawn(playerid);
- SetCameraBehindPlayer(playerid);
- print("OnPlayerSpawn running");
- return 1;
- }
- function:SetPlayersSpawn(playerid)
- {
- switch(PlayerInfo[playerid][pSpawnPoint])
- {
- case SPAWN_POINT_AIRPORT:
- {
- if(PlayerInfo[playerid][pInjured] > 0)
- {
- SetPlayerPos(playerid, 1642.02, -2334.05, 13.5469);
- SetPlayerFacingAngle(playerid, 0.5602);
- SetPlayerInterior(playerid, 0);
- SetPlayerVirtualWorld(playerid, 0);
- SetPlayerSkin(playerid, PlayerInfo[playerid][pSkin]);
- PlayerInfo[playerid][pInjured] = 0;
- }
- else
- {
- SetPlayerInterior(playerid, PlayerInfo[playerid][pInterior]);
- SetPlayerPos(playerid, PlayerInfo[playerid][pPosX], PlayerInfo[playerid][pPosY], PlayerInfo[playerid][pPosZ]);
- SetPlayerFacingAngle(playerid, PlayerInfo[playerid][pPosA]);
- }
- }
- }
- return 1;
- }
- public OnPlayerDeath(playerid, killerid, reason)
- {
- PlayerInfo[playerid][pInjured] ++;
- 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[129];
- WP_Hash(hashed_pass, sizeof(hashed_pass), inputtext);
- if (strcmp(hashed_pass, PlayerInfo[playerid][pPassword]) == 0)
- {
- //correct password, spawn the player
- ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Login", "You have been successfully logged in.", "Okay", "");
- // sets the specified cache as the active cache so we can retrieve the rest player data
- cache_set_active(PlayerInfo[playerid][Cache_ID]);
- AssignPlayerData(playerid);
- // remove the active cache from memory and unsets the active cache as well
- cache_delete(PlayerInfo[playerid][Cache_ID]);
- PlayerInfo[playerid][Cache_ID] = MYSQL_INVALID_CACHE;
- KillTimer(PlayerInfo[playerid][LoginTimer]);
- PlayerInfo[playerid][LoginTimer] = 0;
- new query[128];
- mysql_format(g_SQL, query, sizeof(query), "SELECT * FROM players WHERE Username = '%e' LIMIT 1", PlayerInfo[playerid][pName]);
- mysql_tquery(g_SQL, query, "OnPlayerLogin", "d", playerid);
- print("DIALOG_LOGIN pass correct running");
- }
- else
- {
- PlayerInfo[playerid][LoginAttempts]++;
- if (PlayerInfo[playerid][LoginAttempts] >= 3)
- {
- ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Login", "You have mistyped your password too often (3 times).", "Okay", "");
- DelayedKick(playerid);
- print("DIALOG_LOGIN pass incorrect running");
- }
- else
- {
- ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login", "Wrong password!\nPlease enter your password in the field below:", "Login", "Abort");
- print("DIALOG_LOGIN pass incorrect running2");
- }
- }
- Camera(playerid);
- }
- case DIALOG_REGISTER:
- {
- if (!response) return Kick(playerid);
- if (strlen(inputtext) <= 5) return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration", "Your password must be longer than 5 characters!\nPlease enter your password in the field below:", "Register", "Abort");
- new query[256];
- WP_Hash(PlayerInfo[playerid][pPassword], 129, inputtext);
- mysql_format(g_SQL, query, sizeof query, "INSERT INTO `players` (`Username`, `Password`) VALUES ('%e', '%s')", PlayerInfo[playerid][pName], PlayerInfo[playerid][pPassword]);
- mysql_tquery(g_SQL, query, "OnPlayerRegister", "d", playerid);
- print("DIALOG_REGISTER running");
- }
- default: return 0; // dialog ID was not found, search in other scripts
- }
- return 1;
- }
- //-----------------------------------------------------
- function:OnPlayerLogin(playerid)
- {
- PlayerInfo[playerid][IsLoggedIn] = true;
- TogglePlayerSpectating(playerid, false);
- // spawn the player to their last saved position after login
- SetSpawnInfo(playerid, 0, PlayerInfo[playerid][pSkin], PlayerInfo[playerid][pPosX], PlayerInfo[playerid][pPosY], PlayerInfo[playerid][pPosZ], PlayerInfo[playerid][pPosA], 0, 0, 0, 0, 0, 0);
- SpawnPlayer(playerid);
- print("OnPlayerLogin running");
- return 1;
- }
- function:OnPlayerRegister(playerid)
- {
- // retrieves the ID generated for an AUTO_INCREMENT column by the sent query
- PlayerInfo[playerid][pID] = cache_insert_id();
- ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Registration", "Account successfully registered, you have been automatically logged in.", "Okay", "");
- PlayerInfo[playerid][IsLoggedIn] = true;
- TogglePlayerSpectating(playerid, false);
- SetSpawnInfo(playerid, 0, PlayerInfo[playerid][pSkin], PlayerInfo[playerid][pPosX], PlayerInfo[playerid][pPosY], PlayerInfo[playerid][pPosZ], PlayerInfo[playerid][pPosA], 0, 0, 0, 0, 0, 0);
- SpawnPlayer(playerid);
- print("OnPlayerRegister running");
- return 1;
- }
- function:ResetPlayer(playerid)
- {
- //Player characters:
- PlayerInfo[playerid][IsLoggedIn] = false;
- PlayerInfo[playerid][pID] = 0;
- PlayerInfo[playerid][pKills] = 0;
- PlayerInfo[playerid][pDeaths] = 0;
- PlayerInfo[playerid][pPosX] = 1642.02;
- PlayerInfo[playerid][pPosY] = -2334.05;
- PlayerInfo[playerid][pPosZ] = 13.5469;
- PlayerInfo[playerid][pPosA] = 0.5602;
- PlayerInfo[playerid][pInterior] = 0;
- PlayerInfo[playerid][pInjured] = 0;
- PlayerInfo[playerid][pSpawnPoint] = 0;
- PlayerInfo[playerid][pSkin] = 264;
- return 1;
- }
- function: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)
- {
- cache_get_value(0, "Password", PlayerInfo[playerid][pPassword], 129);
- // saves the active cache in the memory and returns an cache-id to access it for later use
- PlayerInfo[playerid][Cache_ID] = cache_save();
- format(string, sizeof string, "This account (%s) is registered. Please login by entering your password in the field below:", PlayerInfo[playerid][pName]);
- ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login", string, "Login", "Abort");
- // from now on, the player has 30 seconds to login
- PlayerInfo[playerid][LoginTimer] = SetTimerEx("OnLoginTimeout", SECONDS_TO_LOGIN * 1000, false, "d", playerid);
- }
- else
- {
- format(string, sizeof string, "Welcome %s, you can register by entering your password in the field below:", PlayerInfo[playerid][pName]);
- ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration", string, "Register", "Abort");
- }
- Camera(playerid);
- print("OnPlayerDataLoaded running");
- return 1;
- }
- function:OnLoginTimeout(playerid)
- {
- // reset the variable that stores the timerid
- PlayerInfo[playerid][LoginTimer] = 0;
- ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Login", "You have been kicked for taking too long to login successfully to your account.", "Okay", "");
- DelayedKick(playerid);
- return 1;
- }
- function:KickPlayerDelayed(playerid)
- {
- Kick(playerid);
- return 1;
- }
- //-----------------------------------------------------
- AssignPlayerData(playerid)
- {
- cache_get_value_int(0, "ID", PlayerInfo[playerid][pID]);
- cache_get_value_int(0, "Kills", PlayerInfo[playerid][pKills]);
- cache_get_value_int(0, "Deaths", PlayerInfo[playerid][pDeaths]);
- cache_get_value_float(0, "PosX", PlayerInfo[playerid][pPosX]);
- cache_get_value_float(0, "PosY", PlayerInfo[playerid][pPosY]);
- cache_get_value_float(0, "PosZ", PlayerInfo[playerid][pPosZ]);
- cache_get_value_float(0, "PosA", PlayerInfo[playerid][pPosA]);
- cache_get_value_int(0, "Interior", PlayerInfo[playerid][pInterior]);
- cache_get_value_int(0, "Injured", PlayerInfo[playerid][pInjured]);
- cache_get_value_int(0, "SpawnPoint", PlayerInfo[playerid][pSpawnPoint]);
- cache_get_value_int(0, "Skin", PlayerInfo[playerid][pSkin]);
- return 1;
- }
- DelayedKick(playerid, time = 500)
- {
- SetTimerEx("KickPlayerDelayed", time, false, "d", playerid);
- return 1;
- }
- UpdatePlayerData(playerid, reason)
- {
- if (PlayerInfo[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, PlayerInfo[playerid][pPosX], PlayerInfo[playerid][pPosY], PlayerInfo[playerid][pPosZ]);
- GetPlayerFacingAngle(playerid, PlayerInfo[playerid][pPosA]);
- }
- new query[256];
- mysql_format(g_SQL, query, sizeof query, "UPDATE `players` SET `PosX` = %f, `PosY` = %f, `PosZ` = %f, `PosA` = %f, `Interior` = %d WHERE `ID` = %d",
- PlayerInfo[playerid][pPosX],
- PlayerInfo[playerid][pPosY],
- PlayerInfo[playerid][pPosZ],
- PlayerInfo[playerid][pPosA],
- GetPlayerInterior(playerid),
- PlayerInfo[playerid][pID]);
- mysql_tquery(g_SQL, query);
- mysql_format(g_SQL, query, sizeof query, "UPDATE `players` SET `Deaths` = %d, `Kills` = %d, `Injured` = %d, `SpawnPoint` = %d, `Skin` = %d WHERE `ID` = %d",
- PlayerInfo[playerid][pDeaths],
- PlayerInfo[playerid][pKills],
- PlayerInfo[playerid][pInjured],
- PlayerInfo[playerid][pKills],
- PlayerInfo[playerid][pSkin],
- PlayerInfo[playerid][pID]);
- mysql_tquery(g_SQL, query);
- return 1;
- }
- /* Test commands*/
- CMD:test(playerid, params[])
- {
- SetPlayerHealth(playerid, 0);
- return 1;
- }
- CMD:skin(playerid, params[])
- {
- new playerb, skinid;
- if (sscanf(params, "ud", playerb, skinid))
- return SendClientMessage(playerid, -1, "/skin [playerid OR name] [skinid]");
- if(!IsPlayerConnected(playerb))
- return SendClientMessage(playerid, -1, "The player you specified isn't connected.");
- if(PlayerInfo[playerid][IsLoggedIn] == false)
- return SendClientMessage(playerid, -1, "The player you specified isn't logged in.");
- PlayerInfo[playerb][pSkin] = skinid; SetPlayerSkin(playerb, skinid);
- return 1;
- }
Add Comment
Please, Sign In to add comment