Oblivion_UFF

asdads

Mar 18th, 2020
321
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.37 KB | None | 0 0
  1. #include <a_samp>
  2. #include <a_mysql>
  3. #include <foreach>
  4. #include <mSelection>
  5. #include <streamer>
  6.  
  7. //Configuring MySQL Stuff to set up the connection
  8.  
  9. #define MYSQL_HOST "localhost" // Change this to your MySQL Remote IP or "localhost".
  10. #define MYSQL_USER "root" // Change this to your MySQL Database username.
  11. #define MYSQL_PASS "password" // Change this to your MySQL Database password.
  12. #define MYSQL_DATABASE "san_andreas" // Change this to your MySQL Database name.
  13.  
  14. // Well, don't just enter random information and expect it to work, information
  15. // Should be valid and working fine.
  16.  
  17. #define DIALOG_REGISTER (0)
  18. #define DIALOG_LOGIN (1)
  19.  
  20. // Make sure the dialog IDs above do not match any dialog ID you're using in your
  21. // gamemode otherwise they won't do their job properly.
  22.  
  23. main( )
  24. {
  25.  
  26. }
  27.  
  28.  
  29. new MySQL: Database, Corrupt_Check[MAX_PLAYERS];
  30.  
  31. //Creating an enumerator to store player's data for further use (below).
  32.  
  33. //==============================================================================
  34.  
  35. enum ENUM_PLAYER_DATA
  36. {
  37. ID,
  38. Name[25],
  39.  
  40. Password[65],
  41. Salt[11],
  42.  
  43. PasswordFails,
  44.  
  45. Kills,
  46. Deaths,
  47.  
  48. pSkin,
  49.  
  50. Score,
  51. Cash,
  52.  
  53. Cache: Player_Cache,
  54. bool:LoggedIn
  55. }
  56.  
  57. new pInfo[MAX_PLAYERS][ENUM_PLAYER_DATA];
  58. new skinlist = mS_INVALID_LISTID;
  59.  
  60. //==============================================================================
  61. //==============================================================================
  62.  
  63.  
  64.  
  65.  
  66. public OnGameModeInit()
  67. {
  68. skinlist = LoadModelSelectionMenu("skins.txt");
  69. new MySQLOpt: option_id = mysql_init_options();
  70. mysql_set_option(option_id, AUTO_RECONNECT, true);
  71. Database = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DATABASE, option_id);
  72.  
  73. if(Database == MYSQL_INVALID_HANDLE || mysql_errno(Database) != 0)
  74. {
  75. print("I couldn't connect to the MySQL server, closing.");
  76.  
  77. SendRconCommand("exit");
  78. return 1;
  79. }
  80.  
  81. print("I have connected to the MySQL server."); // If the given MySQL details were all okay, this message prints to the log.
  82.  
  83. mysql_tquery(Database, "CREATE TABLE IF NOT EXISTS `PLAYERS` (`ID` int(11) NOT NULL AUTO_INCREMENT,`USERNAME` varchar(24) NOT NULL,`PASSWORD` char(65) NOT NULL,`SALT` char(11) NOT NULL,`SCORE` mediumint(7), `KILLS` mediumint(7), `CASH` mediumint(7) NOT NULL DEFAULT '0',`DEATHS` mediumint(7) NOT NULL DEFAULT '0',`PSKIN` mediumint(7) NOT NULL DEFAULT '0', PRIMARY KEY (`ID`), UNIQUE KEY `USERNAME` (`USERNAME`))");
  84.  
  85. return 1;
  86. }
  87.  
  88. public OnGameModeExit()
  89. {
  90.  
  91. foreach(new i: Player)
  92. {
  93. if(IsPlayerConnected(i)) // Checking if the players stored in "i" are connected.
  94. {
  95. OnPlayerDisconnect(i, 1); // We do that so players wouldn't lose their data upon server's close.
  96. }
  97. }
  98. mysql_close(Database); // Closing the database.
  99.  
  100. return 1;
  101. }
  102.  
  103. public OnPlayerConnect(playerid)
  104. {
  105. new DB_Query[115];
  106. //Resetting player information.
  107. pInfo[playerid][Kills] = 0;
  108. pInfo[playerid][Deaths] = 0;
  109. pInfo[playerid][PasswordFails] = 0;
  110.  
  111. GetPlayerName(playerid, pInfo[playerid][Name], MAX_PLAYER_NAME); // Getting the player's name.
  112. Corrupt_Check[playerid]++;
  113.  
  114. mysql_format(Database, DB_Query, sizeof(DB_Query), "SELECT * FROM `PLAYERS` WHERE `USERNAME` = '%e' LIMIT 1", pInfo[playerid][Name]);
  115. mysql_tquery(Database, DB_Query, "OnPlayerDataCheck", "ii", playerid, Corrupt_Check[playerid]);
  116. return 1;
  117. }
  118.  
  119. public OnPlayerDisconnect(playerid, reason)
  120. {
  121. Corrupt_Check[playerid]++;
  122.  
  123. new DB_Query[256];
  124. //Running a query to save the player's data using the stored stuff.
  125. mysql_format(Database, DB_Query, sizeof(DB_Query), "UPDATE `PLAYERS` SET `SCORE` = %d, `CASH` = %d, `KILLS` = %d, `DEATHS` = %d WHERE `ID` = %d LIMIT 1",
  126. pInfo[playerid][Score], pInfo[playerid][Cash], pInfo[playerid][Kills], pInfo[playerid][Deaths], pInfo[playerid][ID]);
  127. mysql_tquery(Database, DB_Query);
  128.  
  129. if(cache_is_valid(pInfo[playerid][Player_Cache])) //Checking if the player's cache ID is valid.
  130. {
  131. cache_delete(pInfo[playerid][Player_Cache]); // Deleting the cache.
  132. pInfo[playerid][Player_Cache] = MYSQL_INVALID_CACHE; // Setting the stored player Cache as invalid.
  133. }
  134.  
  135. pInfo[playerid][LoggedIn] = false;
  136. print("OnPlayerDisconnect has been called."); // Sending message once OnPlayerDisconnect is called.
  137. return 1;
  138. }
  139.  
  140. public OnPlayerSpawn(playerid)
  141. {
  142. SetPlayerSkin(playerid, pInfo[playerid][pSkin]);
  143. }
  144.  
  145.  
  146. public OnPlayerDeath(playerid, killerid, reason)
  147. {
  148. // Increase death if self-death or got killed!
  149. pInfo[playerid][Deaths]++;
  150.  
  151. if(killerid != INVALID_PLAYER_ID) // Checking if the killer of the player is valid.
  152. {
  153. //Increasing the kills of the killer and the deaths of the player.
  154. pInfo[killerid][Kills]++;
  155. }
  156. return 1;
  157. }
  158.  
  159. public OnPlayerRequestSpawn(playerid)
  160. {
  161. if(pInfo[playerid][LoggedIn] == false) return 0; // Ignoring the request incase player isn't logged in.
  162. return 1;
  163. }
  164.  
  165. public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
  166. {
  167. switch (dialogid)
  168. {
  169. case DIALOG_LOGIN:
  170. {
  171.  
  172. if(!response) return Kick(playerid);
  173.  
  174. new Salted_Key[65];
  175. SHA256_PassHash(inputtext, pInfo[playerid][Salt], Salted_Key, 65);
  176.  
  177. if(strcmp(Salted_Key, pInfo[playerid][Password]) == 0)
  178. {
  179. // Now, password should be correct as well as the strings
  180. // Matched with each other, so nothing is wrong until now.
  181.  
  182. // We will activate the cache of player to make use of it e.g.
  183. // Retrieve their data.
  184.  
  185. cache_set_active(pInfo[playerid][Player_Cache]);
  186.  
  187. // Okay, we are retrieving the information now..
  188. cache_get_value_int(0, "ID", pInfo[playerid][ID]);
  189.  
  190. cache_get_value_int(0, "KILLS", pInfo[playerid][Kills]);
  191. cache_get_value_int(0, "DEATHS", pInfo[playerid][Deaths]);
  192.  
  193. cache_get_value_int(0, "SCORE", pInfo[playerid][Score]);
  194. cache_get_value_int(0, "CASH", pInfo[playerid][Cash]);
  195. cache_get_value_int(0, "PSKIN", pInfo[playerid][Score]);
  196.  
  197. SetPlayerScore(playerid, pInfo[playerid][Score]);
  198.  
  199. ResetPlayerMoney(playerid);
  200. GivePlayerMoney(playerid, pInfo[playerid][Cash]);
  201.  
  202. // So, we have successfully retrieved data? Now deactivating the cache.
  203.  
  204. cache_delete(pInfo[playerid][Player_Cache]);
  205. pInfo[playerid][Player_Cache] = MYSQL_INVALID_CACHE;
  206.  
  207. pInfo[playerid][LoggedIn] = true;
  208. SendClientMessage(playerid, 0x00FF00FF, "Logged in to the account.");
  209. }
  210. else
  211. {
  212. new String[150];
  213.  
  214. pInfo[playerid][PasswordFails] += 1;
  215. printf("%s has been failed to login. (%d)", pInfo[playerid][Name], pInfo[playerid][PasswordFails]);
  216. // Printing the message that someone has failed to login to his account.
  217.  
  218. if (pInfo[playerid][PasswordFails] >= 3) // If the fails exceeded the limit we kick the player.
  219. {
  220. format(String, sizeof(String), "%s has been kicked Reason: {FF0000}(%d/3) Login fails.", pInfo[playerid][Name], pInfo[playerid][PasswordFails]);
  221. SendClientMessageToAll(0x969696FF, String);
  222. Kick(playerid);
  223. }
  224. else
  225. {
  226. // If the player didn't exceed the limits we send him a message that the password is wrong.
  227. format(String, sizeof(String), "Wrong password, you have %d out of 3 tries.", pInfo[playerid][PasswordFails]);
  228. SendClientMessage(playerid, 0xFF0000FF, String);
  229.  
  230. format(String, sizeof(String), "{FFFFFF}Welcome back, %s.\n\n{0099FF}This account is already registered.\n\
  231. {0099FF}Please, input your password below to proceed to the game.\n\n", pInfo[playerid][Name]);
  232. ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login System", String, "Login", "Leave");
  233. }
  234. }
  235. }
  236. case DIALOG_REGISTER:
  237. {
  238. if(!response) return Kick(playerid);
  239. if(strlen(inputtext) <= 5 || strlen(inputtext) > 60)
  240. {
  241. // If the password length is less than or equal to 5 and more than 60
  242. // It repeats the process and shows error message as seen below.
  243.  
  244. SendClientMessage(playerid, 0x969696FF, "Invalid password length, should be 5 - 60.");
  245.  
  246. new String[150];
  247.  
  248. format(String, sizeof(String), "{FFFFFF}Welcome %s.\n\n{0099FF}This account is not registered.\n\
  249. {0099FF}Please, input your password below to proceed.\n\n", pInfo[playerid][Name]);
  250. ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration System", String, "Register", "Leave");
  251.  
  252. }
  253. else
  254. {
  255.  
  256. // Salting the player's password using SHA256 for a better security.
  257.  
  258. for (new i = 0; i < 10; i++)
  259. {
  260. pInfo[playerid][Salt][i] = random(79) + 47;
  261. }
  262.  
  263. pInfo[playerid][Salt][10] = 0;
  264. SHA256_PassHash(inputtext, pInfo[playerid][Salt], pInfo[playerid][Password], 65);
  265.  
  266. // Show Skin Selection
  267. SendClientMessage(playerid, 0x00FF00FF, "Please select a skin!");
  268. ShowModelSelectionMenu(playerid, skinlist, "Pick A Skin");
  269. }
  270. }
  271. }
  272. return 1;
  273. }
  274.  
  275. forward OnPlayerDataCheck(playerid, corrupt_check);
  276. public OnPlayerDataCheck(playerid, corrupt_check)
  277. {
  278. if (corrupt_check != Corrupt_Check[playerid]) return Kick(playerid);
  279. // You'd have asked already what's corrput_check and how it'd benefit me?
  280. // Well basically MySQL query takes long, incase a player leaves while its not proceeded
  281. // With ID 1 for example, then another player comes as ID 1 it'll basically corrupt the data
  282. // So, once the query is done, the player will have the wrong data assigned for himself.
  283.  
  284. new String[150];
  285.  
  286. if(cache_num_rows() > 0)
  287. {
  288. // If the player exists, everything is okay and nothing is wrongly detected
  289. // The player's password and Saltion key gets stored as seen below
  290. // So we won't have to get a headache just to match player's password.
  291.  
  292. cache_get_value(0, "PASSWORD", pInfo[playerid][Password], 65);
  293. cache_get_value(0, "SALT", pInfo[playerid][Salt], 11);
  294.  
  295. pInfo[playerid][Player_Cache] = cache_save();
  296. // ^ Storing the cache ID of the player for further use later.
  297.  
  298. format(String, sizeof(String), "{FFFFFF}Welcome back, %s.\n\n{0099FF}This account is already registered.\n\
  299. {0099FF}Please, input your password below to proceed to the game.\n\n", pInfo[playerid][Name]);
  300. ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login System", String, "Login", "Leave");
  301. }
  302. else
  303. {
  304. format(String, sizeof(String), "{FFFFFF}Welcome %s.\n\n{0099FF}This account is not registered.\n\
  305. {0099FF}Please, input your password below to proceed to the game.\n\n", pInfo[playerid][Name]);
  306. ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration System", String, "Register", "Leave");
  307. }
  308. return 1;
  309. }
  310.  
  311. //==============================================================================
  312.  
  313. forward OnPlayerRegister(playerid);
  314. public OnPlayerRegister(playerid)
  315. {
  316. // This gets called only when the player registers a new account.
  317. SendClientMessage(playerid, 0x00FF00FF, "You are now registered and has been logged in.");
  318.  
  319.  
  320. // Player Logged in!
  321. pInfo[playerid][LoggedIn] = true;
  322.  
  323. //SetSpawnInfo(playerid, 0, , 2098.5088,1159.1156,11.6484, 65.2418, 0, 0, 0, 0, 0, 0 );
  324. //SpawnPlayer(playerid);
  325. return 1;
  326. }
  327.  
  328.  
  329. public OnPlayerModelSelection(playerid, response, listid, modelid)
  330. {
  331. if(listid == skinlist)
  332. {
  333. if(response)
  334. {
  335. SetPlayerSkin(playerid, modelid); // set player skin
  336. pInfo[playerid][pSkin] = modelid;
  337.  
  338. new DB_Query[225];
  339.  
  340. mysql_format(Database, DB_Query, sizeof(DB_Query), "INSERT INTO `PLAYERS` (`USERNAME`, `PASSWORD`, `SALT`, `SCORE`, `KILLS`, `CASH`, `DEATHS`, `PSKIN`)\
  341. VALUES ('%e', '%s', '%e', '20', '0', '5000', '0', %d)", pInfo[playerid][Name], pInfo[playerid][Password], pInfo[playerid][Salt],pInfo[playerid][pSkin]);
  342.  
  343. mysql_tquery(Database, DB_Query, "OnPlayerRegister", "d", playerid);
  344.  
  345.  
  346.  
  347. }
  348. else if(!response && !pInfo[playerid][LoggedIn])
  349. {
  350. SendClientMessage(playerid, 0x00FF00FF, "Please select a skin!");
  351. ShowModelSelectionMenu(playerid, skinlist, "Pick A Skin");
  352. }
  353. return 1;
  354. }
  355. return 1;
  356. }
  357.  
  358. //==============================================================================
  359.  
  360.  
  361.  
  362.  
  363.  
  364.  
  365.  
  366. // End of script //
Advertisement
Add Comment
Please, Sign In to add comment