blueg7.inc 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535
  1. /*
  2. Legal:
  3. Version: MPL 1.1
  4. The contents of this file are subject to the Mozilla Public License Version
  5. 1.1 the "License"; you may not use this file except in compliance with
  6. the License. You may obtain a copy of the License at
  7. http://www.mozilla.org/MPL/
  8. Software distributed under the License is distributed on an "AS IS" basis,
  9. WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  10. for the specific language governing rights and limitations under the
  11. License.
  12. The Original Code is the YSI framework.
  13. The Initial Developer of the Original Code is Alex "Y_Less" Cole.
  14. Portions created by the Initial Developer are Copyright C 2011
  15. the Initial Developer. All Rights Reserved.
  16. Contributors:
  17. Y_Less
  18. koolk
  19. JoeBullet/Google63
  20. g_aSlice/Slice
  21. Misiur
  22. samphunter
  23. tianmeta
  24. maddinat0r
  25. spacemud
  26. Crayder
  27. Dayvison
  28. Ahmad45123
  29. Zeex
  30. irinel1996
  31. Yiin-
  32. Chaprnks
  33. Konstantinos
  34. Masterchen09
  35. Southclaws
  36. PatchwerkQWER
  37. m0k1
  38. paulommu
  39. udan111
  40. Thanks:
  41. JoeBullet/Google63 - Handy arbitrary ASM jump code using SCTRL.
  42. ZeeX - Very productive conversations.
  43. koolk - IsPlayerinAreaEx code.
  44. TheAlpha - Danish translation.
  45. breadfish - German translation.
  46. Fireburn - Dutch translation.
  47. yom - French translation.
  48. 50p - Polish translation.
  49. Zamaroht - Spanish translation.
  50. Los - Portuguese translation.
  51. Dracoblue, sintax, mabako, Xtreme, other coders - Producing other modes for
  52. me to strive to better.
  53. Pixels^ - Running XScripters where the idea was born.
  54. Matite - Pestering me to release it and using it.
  55. Very special thanks to:
  56. Thiadmer - PAWN, whose limits continue to amaze me!
  57. Kye/Kalcor - SA:MP.
  58. SA:MP Team past, present and future - SA:MP.
  59. Optional plugins:
  60. Gamer_Z - GPS.
  61. Incognito - Streamer.
  62. Me - sscanf2, fixes2, Whirlpool.
  63. */
  64. loadtext core[ysi_players];
  65. enum E_USER_PRELOAD
  66. {
  67. E_USER_PRELOAD_YID,
  68. Language:E_USER_PRELOAD_LANG,
  69. E_USER_PRELOAD_PASS[MAX_PASSWORD_LENGTH + 1],
  70. E_USER_PRELOAD_BITS,
  71. E_USER_PRELOAD_DATE
  72. }
  73. static stock
  74. YSI_g_sPlayerIndexFile,
  75. INI:YSI_g_sPlayerWriteFile = INI_NO_FILE,
  76. YSI_g_sPlayerYID[MAX_PLAYERS] = {-2, ...},
  77. //YSI_g_sCallbacks,
  78. YSI_g_sPreloadData[MAX_PLAYERS][E_USER_PRELOAD];
  79. //#define Player_GetIndexFile(%0,%1) ((YSI_g_sPlayerIndexFile=%1[0]),%0[sizeof(%0)-5]=(('a'<=(YSI_g_sPlayerIndexFile|0x20)<='z')?(YSI_g_sPlayerIndexFile|0x20):(('0'<=YSI_g_sPlayerIndexFile<='9')?('0'):('_'))))
  80. #define Player_GetIndexFile(%0,%1) ((YSI_g_sPlayerIndexFile=%1),%0[USER_FILE_LENGTH+4]=(('a'<=(YSI_g_sPlayerIndexFile|0x20)<='z')?(YSI_g_sPlayerIndexFile|0x20):(('0'<=YSI_g_sPlayerIndexFile<='9')?('0'):('_'))))
  81. //foreign Player_DoLogout(playerid, uid);
  82. foreign Player_TryRegister(playerid, string:password[]);
  83. foreign Player_TryLogin(playerid, string:password[]);
  84. foreign Player_TryGroup(playerid, string:other[], string:password[]);
  85. // No longer global because the YID is shared in all scripts.
  86. //foreign Player_GetYID(playerid);
  87. foreign Player_ChangePassword(playerid, string:password[]);
  88. foreign Player_ForceGroup(playerid, string:other[]);
  89. foreign Player_ForceLogin(playerid);
  90. /*-------------------------------------------------------------------------*//**
  91. * <param name="playerid">Player who changed name.</param>
  92. * <remarks>
  93. * Reload a player's basic data when they change name.
  94. * </remarks>
  95. *//*------------------------------------------------------------------------**/
  96. stock Player_Reload(playerid)
  97. {
  98. new
  99. name[MAX_PLAYER_NAME];
  100. GetPlayerName(playerid, name, sizeof (name));
  101. Player_Preload(name, YSI_g_sPreloadData[playerid]);
  102. }
  103. stock Player_SetPreload(playerid, data[E_USER_PRELOAD])
  104. {
  105. if (VALID_PLAYERID(playerid))
  106. {
  107. YSI_g_sPreloadData[playerid] = data;
  108. }
  109. }
  110. /*-------------------------------------------------------------------------*//**
  111. * <param name="playerid">Player who is logging in.</param>
  112. * <remarks>
  113. * Loads a player's data to an array.
  114. * </remarks>
  115. *//*------------------------------------------------------------------------**/
  116. #if _YSI_PLUGINS_MYSQL == 7
  117. public _Player_Preload(ret[E_USER_PRELOAD])
  118. {
  119. // Need to use some clever AMX hacking to pass the "ret" array...
  120. }
  121. #endif
  122. stock Player_Preload(string:name[], ret[E_USER_PRELOAD])
  123. {
  124. // First, find the player's file. This should be the ONLY place where the
  125. // password is to be loaded.
  126. P:4("Player_Preload called: %s", name);
  127. ret[E_USER_PRELOAD_YID] = -2;
  128. ret[E_USER_PRELOAD_PASS] = '\0';
  129. ret[E_USER_PRELOAD_LANG] = NO_LANGUAGE;
  130. ret[E_USER_PRELOAD_BITS] = 0;
  131. ret[E_USER_PRELOAD_DATE] = 0;
  132. #if _YSI_PLUGINS_MYSQL == 7
  133. // Right then, lets get coding...
  134. new
  135. query[110];
  136. mysql_format(YSI_g_sMySQL, query, "SELECT `uid`, `language`, `hash` FROM `y_users_register` WHERE `name` = '%e' LIMIT 0,1", name);
  137. mysql_function_query(YSI_g_sMySQL, query, true, "_Player_Preload", "ii", );
  138. #else
  139. new
  140. namelen = strlen(name),
  141. filename[] = USER_FILE_PATH "ind_X.YSI",
  142. File:fIndex;
  143. Player_GetIndexFile(filename, name[0]);
  144. fIndex = fopen(filename, io_read);
  145. if (fIndex)
  146. {
  147. P:5("Player_Preload: fIndex OK");
  148. new
  149. line[INDEX_DATA_LINE_LENGTH],
  150. len;
  151. while ((len = fread(fIndex, line)))
  152. {
  153. P:6("Player_Preload: while");
  154. //new
  155. // len;
  156. //len = strlen(line);
  157. // Check if the line is the right length (could be one of three
  158. // lengths depending on newlines). Skip blanks.
  159. if (len < INDEX_DATA_LINE_LENGTH - 3)
  160. {
  161. continue;
  162. }
  163. P:6("Player_Preload: Not len");
  164. // Check the name on the line.
  165. if (!strcmp(line[MAX_INDEX_LENGTH + 1], name, false, namelen) && line[MAX_INDEX_LENGTH + 1 + namelen] == ' ')
  166. {
  167. P:6("Player_Preload: checked name");
  168. // Found the section on this one player.
  169. //P:6("Player_Preload: check pass: %s ?= %s", hash, line[MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME + 1]);
  170. // Save the loaded data.
  171. line[MAX_INDEX_LENGTH] = '\0';
  172. //printf("line: %s", line);
  173. ret[E_USER_PRELOAD_YID] = strval(line);
  174. //printf("%d %d %d", ret[E_USER_PRELOAD_YID], strval(line), strval("00000022"));
  175. //printf("%d", strval(line));
  176. line[MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME + 1 + MAX_PASSWORD_LENGTH + 1 + 2] = '\0';
  177. ret[E_USER_PRELOAD_LANG] = Langs_GetLanguage(line[MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME + 1 + MAX_PASSWORD_LENGTH + 1]);
  178. strcat(ret[E_USER_PRELOAD_PASS], line[MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME + 1], MAX_PASSWORD_LENGTH + 1);
  179. // Load the 32 extra "bits".
  180. ret[E_USER_PRELOAD_BITS] = hexstr(line[MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME + 1 + MAX_PASSWORD_LENGTH + 1 + 2 + 1]);
  181. // Load the user registration date (if they have one).
  182. ret[E_USER_PRELOAD_DATE] = hexstr(line[MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME + 1 + MAX_PASSWORD_LENGTH + 1 + 2 + 1 + 8 + 1]);
  183. P:6("Player_Preload: %s %d %d %x %x", ret[E_USER_PRELOAD_PASS], ret[E_USER_PRELOAD_YID], _:ret[E_USER_PRELOAD_LANG], ret[E_USER_PRELOAD_BITS], ret[E_USER_PRELOAD_DATE]);
  184. fclose(fIndex);
  185. return 1;
  186. }
  187. }
  188. fclose(fIndex);
  189. }
  190. else if (fexist(filename))
  191. {
  192. P:E("Error reading index %c.", filename[0]);
  193. return -1;
  194. }
  195. ret[E_USER_PRELOAD_YID] = -1;
  196. #endif
  197. return 0;
  198. }
  199. stock Language:Player_GetPreloadLanguage(playerid)
  200. {
  201. return Language:YSI_g_sPreloadData[playerid][E_USER_PRELOAD_LANG];
  202. }
  203. stock Player_GetPreloadBits(playerid)
  204. {
  205. return YSI_g_sPreloadData[playerid][E_USER_PRELOAD_BITS];
  206. }
  207. static remotefunc void:_Player_SetPreloadBits(playerid, bits)
  208. {
  209. YSI_g_sPreloadData[playerid][E_USER_PRELOAD_BITS] = bits;
  210. }
  211. stock Player_SetPreloadBits(playerid, bits)
  212. {
  213. broadcastfunc _Player_SetPreloadBits(playerid, bits);
  214. Player_RewritePreload(playerid);
  215. }
  216. stock Player_GetPreloadDate(playerid)
  217. {
  218. if (0 <= YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE] < 1234567890)
  219. {
  220. return -1;
  221. }
  222. return YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE];
  223. }
  224. stock Player_IsRegistered(playerid)
  225. {
  226. return YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID] != -1;
  227. }
  228. hook OnScriptInit()
  229. {
  230. switch (ftouch(USER_FILE_PATH "index.YSI"))
  231. {
  232. case -1:
  233. {
  234. P:E(USER_FILE_PATH "index.YSI does not exist and couldn't be created.");
  235. }
  236. case 1:
  237. {
  238. if (!Player_CreateNewID())
  239. {
  240. P:E(USER_FILE_PATH "index.YSI does not exist and couldn't be created.");
  241. }
  242. }
  243. }
  244. // NOT using "ALS" for chaining.
  245. /*if (funcidx("OnPlayerLogin") != -1)
  246. {
  247. YSI_g_sCallbacks |= 1;
  248. }
  249. if (funcidx("OnPlayerLogout") != -1)
  250. {
  251. YSI_g_sCallbacks |= 2;
  252. }*/
  253. }
  254. public OnGameModeInit()
  255. {
  256. if (YSI_FILTERSCRIPT)
  257. {
  258. //if (YSI_g_sCallbacks & 16)
  259. //{
  260. //Users_OnGameModeInit();
  261. #if defined Users_OnGameModeInit
  262. Users_OnGameModeInit();
  263. #endif
  264. //}
  265. }
  266. else
  267. {
  268. #if defined Users_OnGameModeInit
  269. Users_OnGameModeInit();
  270. #endif
  271. //Users_OnGameModeInit();
  272. Users_DoUpgrade0();
  273. Users_DoUpgrade1();
  274. }
  275. return 1;
  276. }
  277. #if defined _ALS_OnGameModeInit
  278. #undef OnGameModeInit
  279. #else
  280. #define _ALS_OnGameModeInit
  281. #endif
  282. #if defined Users_OnGameModeInit
  283. forward Users_OnGameModeInit();
  284. #endif
  285. #define OnGameModeInit(%0) Users_OnGameModeInit(%0)
  286. public OnFilterScriptInit()
  287. {
  288. //if (funcidx("Users_OnGameModeInit") != -1)
  289. //{
  290. // YSI_g_sCallbacks |= 16;
  291. //}
  292. // DO ALL (MOST) OTHER INITS FIRST. ENSURE WE COME LATER.
  293. //Users_OnFilterScriptInit();
  294. #if defined Users_OnFilterScriptInit
  295. Users_OnFilterScriptInit();
  296. #endif
  297. Users_DoUpgrade0();
  298. Users_DoUpgrade1();
  299. return 1;
  300. }
  301. #if defined _ALS_OnFilterScriptInit
  302. #undef OnFilterScriptInit
  303. #else
  304. #define _ALS_OnFilterScriptInit
  305. #endif
  306. #if defined Users_OnFilterScriptInit
  307. forward Users_OnFilterScriptInit();
  308. #endif
  309. #define OnFilterScriptInit(%0) Users_OnFilterScriptInit(%0)
  310. static stock Users_DoUpgrade0()
  311. {
  312. // Only ever do this upgrade once.
  313. switch (ftouch(USER_FILE_PATH "y_users_v2_1.YSI"))
  314. {
  315. case -1:
  316. {
  317. P:E("Could not upgrade user files.");
  318. }
  319. case 1:
  320. {
  321. #if !defined YSI_DO_USER_UPGRADE
  322. P:E("y_users needs to upgrade user files. Please back up the old ones and recompile/rerun once with YSI_DO_USER_UPGRADE.");
  323. fremove(USER_FILE_PATH "y_users_v2_1.YSI");
  324. #else
  325. // Do the upgrade to add languages to all files (could take a
  326. // little while, but needs doing).
  327. P:I("Please wait, upgrading user files.");
  328. new
  329. ch,
  330. filename[] = USER_FILE_PATH "ind_X.YSI",
  331. File:f,
  332. File:g,
  333. line[INDEX_DATA_LINE_LENGTH],
  334. //Language:def = Langs_GetLanguageAt(0),
  335. code[3];
  336. strcpy(code, Langs_GetCode(Langs_GetLanguageAt(0)));
  337. for (new i = -2; i != 26; ++i)
  338. {
  339. if (i == -2)
  340. {
  341. ch = '_';
  342. }
  343. else if (i == -1)
  344. {
  345. ch = '0';
  346. }
  347. else
  348. {
  349. ch = 'a' + i;
  350. }
  351. Player_GetIndexFile(filename, ch);
  352. f = fopen(filename, io_read);
  353. if (!f)
  354. {
  355. if (fexist(filename))
  356. {
  357. P:E("Upgrade %c failed.", filename[USER_FILE_LENGTH + 4]);
  358. }
  359. continue;
  360. }
  361. g = ftemp();
  362. if (!g)
  363. {
  364. fclose(f);
  365. P:E("Upgrade %c failed.", filename[USER_FILE_LENGTH + 4]);
  366. continue;
  367. }
  368. while ((ch = fread(f, line)))
  369. {
  370. //ch = strlen(line);
  371. if (ch > 3)
  372. {
  373. if (line[ch - 2] < ' ')
  374. {
  375. // "/r/n" or "/n/r".
  376. // Copy the existing line ending.
  377. line[ch + 1] = line[ch - 2];
  378. line[ch + 2] = line[ch - 1];
  379. line[ch - 2] = ' ';
  380. line[ch - 1] = code[0];
  381. line[ch ] = code[1];
  382. line[ch + 3] = '\0';
  383. //line[ch - 1] = '\0';
  384. fwrite(g, line);
  385. }
  386. else
  387. {
  388. // "/n" or "/r".
  389. // Copy the existing line ending.
  390. line[ch + 2] = line[ch - 1];
  391. line[ch - 1] = ' ';
  392. line[ch ] = code[0];
  393. line[ch + 1] = code[1];
  394. line[ch + 2] = '\0';
  395. //line[ch - 1] = '\0';
  396. fwrite(g, line);
  397. }
  398. }
  399. }
  400. fseek(g);
  401. fclose(f);
  402. fremove(filename);
  403. f = fopen(filename, io_write);
  404. if (!f)
  405. {
  406. fclose(g);
  407. P:E("Upgrade %c failed.", filename[USER_FILE_LENGTH + 4]);
  408. continue;
  409. }
  410. while (fread(g, line))
  411. {
  412. fwrite(f, line);
  413. }
  414. fclose(f);
  415. fclose(g);
  416. }
  417. f = fopen(USER_FILE_PATH "index.YSI", io_append);
  418. if (f)
  419. {
  420. fwrite(f, " ");
  421. fclose(f);
  422. }
  423. else
  424. {
  425. P:E("Upgrade index failed.");
  426. }
  427. P:I("Upgrade complete.");
  428. #endif
  429. }
  430. }
  431. }
  432. static stock Users_DoUpgrade1()
  433. {
  434. // Only ever do this upgrade once.
  435. switch (ftouch(USER_FILE_PATH "y_users_v2_2.YSI"))
  436. {
  437. // case 0: Already exists.
  438. case -1:
  439. {
  440. P:E("Could not upgrade user files.");
  441. }
  442. case 1:
  443. {
  444. #if !defined YSI_DO_USER_UPGRADE
  445. P:E("y_users needs to upgrade user files. Please back up the old ones and recompile/rerun once with YSI_DO_USER_UPGRADE.");
  446. fremove(USER_FILE_PATH "y_users_v2_2.YSI");
  447. #else
  448. // Do the upgrade to add languages to all files (could take a
  449. // little while, but needs doing).
  450. P:I("Please wait, upgrading user files.");
  451. new
  452. ch,
  453. hash[MAX_PASSWORD_LENGTH + MAX_INDEX_LENGTH + 1],
  454. filename[] = USER_FILE_PATH "ind_X.YSI",
  455. File:f,
  456. File:g,
  457. line[INDEX_DATA_LINE_LENGTH],
  458. //Language:def = Langs_GetLanguageAt(0),
  459. code[3];
  460. strcpy(code, Langs_GetCode(Langs_GetLanguageAt(0)));
  461. for (new i = -2; i != 26; ++i)
  462. {
  463. if (i == -2)
  464. {
  465. ch = '_';
  466. }
  467. else if (i == -1)
  468. {
  469. ch = '0';
  470. }
  471. else
  472. {
  473. ch = 'a' + i;
  474. }
  475. Player_GetIndexFile(filename, ch);
  476. f = fopen(filename, io_read);
  477. if (!f)
  478. {
  479. if (fexist(filename))
  480. {
  481. P:E("Upgrade %c failed.", filename[USER_FILE_LENGTH + 4]);
  482. }
  483. continue;
  484. }
  485. g = ftemp();
  486. if (!g)
  487. {
  488. fclose(f);
  489. P:E("Upgrade %c failed.", filename[USER_FILE_LENGTH + 4]);
  490. continue;
  491. }
  492. while (fread(f, line))
  493. {
  494. ch = strlen(line);
  495. if (ch > 3)
  496. {
  497. // Get the current hash.
  498. strcpy(hash, line[MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME + 1], MAX_PASSWORD_LENGTH + 1);
  499. //hash[MAX_PASSWORD_LENGTH] = '\0';
  500. // Append their ID (not QUITE their join time, but
  501. // best we can do retrospectively).
  502. //line[MAX_INDEX_LENGTH] = '\0';
  503. strcat(hash, line, sizeof (hash));
  504. //line[MAX_INDEX_LENGTH] = ' ';
  505. //hash[MAX_PASSWORD_LENGTH + MAX_INDEX_LENGTH] = '\0';
  506. //printf("HASH 1: %s", hash);
  507. Player_HashPass(hash, hash);
  508. //printf("HASH 2: %s", hash);
  509. // Copy the correct line ending.
  510. if (line[ch - 2] < ' ')
  511. {
  512. format(line, sizeof (line), "%.*s %s %.2s 00000000 %.8s%s", MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME, line, hash, line[MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME + 1 + MAX_PASSWORD_LENGTH + 1], line[0], line[ch - 2]);
  513. //format(line[ch - 2], 21, " 00000000 %.*s%s", MAX_INDEX_LENGTH, line[0], line[ch - 2]);
  514. }
  515. else
  516. {
  517. format(line, sizeof (line), "%.*s %s %.2s 00000000 %.8s%s", MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME, line, hash, line[MAX_INDEX_LENGTH + 1 + MAX_PLAYER_NAME + 1 + MAX_PASSWORD_LENGTH + 1], line[0], line[ch - 1]);
  518. //format(line[ch - 1], 21, " 00000000 %.*s%s", MAX_INDEX_LENGTH, line[0], line[ch - 1]);
  519. }
  520. fwrite(g, line);
  521. }
  522. }
  523. fseek(g);
  524. fclose(f);
  525. fremove(filename);
  526. f = fopen(filename, io_write);
  527. if (!f)
  528. {
  529. fclose(g);
  530. P:E("Upgrade %c failed.", filename[USER_FILE_LENGTH + 4]);
  531. continue;
  532. }
  533. while (fread(g, line))
  534. {
  535. fwrite(f, line);
  536. }
  537. fclose(f);
  538. fclose(g);
  539. }
  540. f = fopen(USER_FILE_PATH "index.YSI", io_append);
  541. if (f)
  542. {
  543. fwrite(f, " ");
  544. fclose(f);
  545. }
  546. else
  547. {
  548. P:E("Upgrade index failed.");
  549. }
  550. P:I("Upgrade complete.");
  551. #endif
  552. }
  553. }
  554. }
  555. /*hook OnScriptExit()
  556. {
  557. _Player_CloseLogout();
  558. }*/
  559. hook OnPlayerConnect(playerid)
  560. {
  561. P:1("Users_OnPlayerConnect called: %d", playerid);
  562. // -2 means unknown.
  563. YSI_g_sPlayerYID[playerid] = -2;
  564. broadcastfunc _Player_IsLoggedIn(playerid);
  565. if (existproperty(8, YSIM_LOG_IN))
  566. {
  567. new
  568. uid = getproperty(8, YSIM_LOG_IN);
  569. P:5("Users_OnPlayerConnect: Exists %d", uid);
  570. if (uid == -1)
  571. {
  572. new
  573. name[MAX_PLAYER_NAME];
  574. GetPlayerName(playerid, name, sizeof (name));
  575. Player_Preload(name, YSI_g_sPreloadData[playerid]);
  576. }
  577. else
  578. {
  579. // This DOES NOT use "broadcastfunc" as it's local only.
  580. Player_DoLogin(playerid, uid);
  581. }
  582. deleteproperty(8, YSIM_LOG_IN);
  583. }
  584. else
  585. {
  586. P:5("Users_OnPlayerConnect: Doesn't exist");
  587. new
  588. name[MAX_PLAYER_NAME];
  589. GetPlayerName(playerid, name, sizeof (name));
  590. Player_Preload(name, YSI_g_sPreloadData[playerid]);
  591. P:5("Users_OnPlayerConnect: Done Preload");
  592. // Can do checking in here to see if they just rejoined.
  593. }
  594. YSI_g_sPlayerYID[playerid] = -1;
  595. }
  596. hook OnPlayerDisconnect(playerid, reason)
  597. {
  598. P:2("Users_OnPlayerDisconnect called: %d %d %d", playerid, reason, YSI_g_sPlayerYID[playerid]);
  599. if (YSI_g_sPlayerYID[playerid] >= 0)
  600. {
  601. // DO NOT broadcastfunc this in case it's just because of one script being
  602. // unloaded, not the player actually leaving (and thus do everything in
  603. // different scripts separately).
  604. Player_DoLogout(playerid, YSI_g_sPlayerYID[playerid]);
  605. }
  606. YSI_g_sPlayerYID[playerid] = -2;
  607. }
  608. static remotefunc void:_Player_IsLoggedIn(playerid)
  609. {
  610. P:4("_Player_IsLoggedIn called: %d %d", playerid, YSI_g_sPlayerYID[playerid]);
  611. if (YSI_g_sPlayerYID[playerid] != -2)
  612. {
  613. setproperty(8, YSIM_LOG_IN, YSI_g_sPlayerYID[playerid]);
  614. }
  615. }
  616. stock bool:Player_IsLoggedIn(playerid)
  617. {
  618. // -2 should never be an issue, but if it is...
  619. return YSI_g_sPlayerYID[playerid] >= 0;
  620. }
  621. stock Player_GetYID(playerid)
  622. {
  623. return YSI_g_sPlayerYID[playerid];
  624. }
  625. /*-------------------------------------------------------------------------*//**
  626. * <param name="playerid">Player who is logging in.</param>
  627. * <param name="password">Password they entered.</param>
  628. * <param name="f">Show the failed to login message?</param>
  629. * <remarks>
  630. * Tries to log in a player - hashes and checks their password and if it's
  631. * right calls the core login code. It doesn't matter WHICH script does this
  632. * as they ALL get called and ALL track the login status of a player.
  633. * </remarks>
  634. *//*------------------------------------------------------------------------**/
  635. //stock Player_TryLogin(playerid, string:password[], f = 0)
  636. //{
  637. //return _Player_TryLogin(playerid, password, f);
  638. //}
  639. global Player_TryLogin(playerid, string:password[])
  640. {
  641. P:2("Player_TryLogin start");
  642. if (Player_IsLoggedIn(playerid))
  643. {
  644. // They are already logged in.
  645. Text_Send(playerid, $YSI_LOGIN_ALREADY);
  646. return 1;
  647. }
  648. new
  649. hash[MAX_PASSWORD_LENGTH + 8 + 1];
  650. Player_HashPass(password, hash);
  651. format(hash[MAX_PASSWORD_LENGTH], sizeof (hash) - MAX_PASSWORD_LENGTH, "%04x%04x", YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE] >>> 16, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE] & 0xFFFF);
  652. //printf("HASH 1: %s", hash);
  653. Player_HashPass(hash, hash);
  654. //printf("HASH 2: %s", hash);
  655. //Player_HashPass(hash, hash);
  656. switch (YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID])
  657. {
  658. case -2:
  659. {
  660. Text_Send(playerid, $YSI_LOGIN_INDERR);
  661. }
  662. case -1:
  663. {
  664. Text_Send(playerid, $YSI_LOGIN_NOTF);
  665. }
  666. default:
  667. {
  668. // Match the password.
  669. if (YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS][0] && !strcmp(YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS], hash, false, MAX_PASSWORD_LENGTH))
  670. {
  671. // Wipe the password from memory.
  672. memset(YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS], 0, MAX_PASSWORD_LENGTH);
  673. // Extract the uid and call in to the login code.
  674. Langs_SetPlayerLanguage(playerid, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_LANG]);
  675. broadcastfunc Player_DoLogin(playerid, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID]);
  676. Text_Send(playerid, $YSI_LOGIN_LOGIN);
  677. return 1;
  678. }
  679. else
  680. {
  681. Text_Send(playerid, $YSI_LOGIN_WRONG);
  682. }
  683. }
  684. }
  685. return 0;
  686. }
  687. /*-------------------------------------------------------------------------*//**
  688. * <param name="playerid">Player who is logging in.</param>
  689. * <remarks>
  690. * Like "Player_TryLogin" but doesn't take a password so always works.
  691. * </remarks>
  692. *//*------------------------------------------------------------------------**/
  693. global Player_ForceLogin(playerid)
  694. {
  695. P:2("Player_TryLogin start");
  696. if (Player_IsLoggedIn(playerid))
  697. {
  698. // They are already logged in.
  699. Text_Send(playerid, $YSI_LOGIN_ALREADY);
  700. return 1;
  701. }
  702. switch (YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID])
  703. {
  704. case -2:
  705. {
  706. Text_Send(playerid, $YSI_LOGIN_INDERR);
  707. }
  708. case -1:
  709. {
  710. Text_Send(playerid, $YSI_LOGIN_NOTF);
  711. }
  712. default:
  713. {
  714. // Extract the uid and call in to the login code.
  715. YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS] = '\0';
  716. Langs_SetPlayerLanguage(playerid, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_LANG]);
  717. broadcastfunc Player_DoLogin(playerid, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID]);
  718. Text_Send(playerid, $YSI_LOGIN_LOGIN);
  719. return 1;
  720. }
  721. }
  722. return 0;
  723. }
  724. /*static*/ remotefunc void:Player_DoLogin(playerid, uid)
  725. {
  726. // Called when a player logs in - either locally (new script) or globally
  727. // (actually only just logged in).
  728. YSI_g_sPlayerYID[playerid] = uid;
  729. // Load any "uvar" variables.
  730. // Call the hooks version of this.
  731. new
  732. filename[64];
  733. format(filename, sizeof (filename), USER_FILE_PATH "%0" #MAX_INDEX_LENGTH "d.INI", uid);
  734. // INI_ParseFile will ONLY load the data for THIS mode, as well as data
  735. // which is mode independent (though there should be none).
  736. INI_ParseFile(filename, "@yU_%s", .bExtra = true, .extra = playerid, .bLocal = true, .bFilter = false, .filter = #MODE_NAME);
  737. //Hooks_OnPlayerLogin(playerid, uid);
  738. //if (YSI_g_sCallbacks & 1)
  739. //{
  740. //CallLocalFunction("OnPlayerLogin", "ii", playerid, uid);
  741. call OnPlayerLogin(playerid, uid);
  742. //}
  743. }
  744. /*-------------------------------------------------------------------------*//**
  745. * <param name="name">Item to remove.</param>
  746. * <remarks>
  747. * Wrapper for Player_AddToBuffer for removing data.
  748. * </remarks>
  749. *//*------------------------------------------------------------------------**/
  750. stock Player_RemoveEntry(name[])
  751. {
  752. INI_RemoveEntry(YSI_g_sPlayerWriteFile, name);
  753. }
  754. /*-------------------------------------------------------------------------*//**
  755. * <param name="name">Data name.</param>
  756. * <param name="data">Data.</param>
  757. * <remarks>
  758. * Wrapper for Player_AddToBuffer for strings.
  759. * </remarks>
  760. *//*------------------------------------------------------------------------**/
  761. stock Player_WriteString(name[], data[])
  762. {
  763. INI_WriteString(YSI_g_sPlayerWriteFile, name, data);
  764. }
  765. stock Player_WriteArray(const name[], data[], len)
  766. {
  767. //printf("name = %s", name);
  768. //printf("data = %d, %d, %d", data[0], data[1], data[2]);
  769. //printf("len = %d", len);
  770. INI_WriteArray(YSI_g_sPlayerWriteFile, name, data, len);
  771. return 1;
  772. }
  773. /*-------------------------------------------------------------------------*//**
  774. * <param name="name">Data name.</param>
  775. * <param name="data">Integer data.</param>
  776. * <remarks>
  777. * Wrapper for Player_AddToBuffer for integers.
  778. * </remarks>
  779. *//*------------------------------------------------------------------------**/
  780. stock Player_WriteInt(name[], data)
  781. {
  782. INI_WriteInt(YSI_g_sPlayerWriteFile, name, data);
  783. }
  784. /*-------------------------------------------------------------------------*//**
  785. * <param name="name">Data name.</param>
  786. * <param name="data">Hex data.</param>
  787. * <remarks>
  788. * Wrapper for Player_AddToBuffer for integers to be written as hex values.
  789. * </remarks>
  790. *//*------------------------------------------------------------------------**/
  791. stock Player_WriteHex(name[], data)
  792. {
  793. INI_WriteHex(YSI_g_sPlayerWriteFile, name, data);
  794. }
  795. /*-------------------------------------------------------------------------*//**
  796. * <param name="name">Data name.</param>
  797. * <param name="data">Binary data.</param>
  798. * <remarks>
  799. * Wrapper for Player_AddToBuffer for integers to be written as binary values.
  800. * </remarks>
  801. *//*------------------------------------------------------------------------**/
  802. stock Player_WriteBin(name[], data)
  803. {
  804. INI_WriteBin(YSI_g_sPlayerWriteFile, name, data);
  805. }
  806. /*-------------------------------------------------------------------------*//**
  807. * <param name="name">Data name.</param>
  808. * <param name="data">Boolean data.</param>
  809. * <remarks>
  810. * Wrapper for Player_AddToBuffer for booleans.
  811. * </remarks>
  812. *//*------------------------------------------------------------------------**/
  813. stock Player_WriteBool(name[], bool:data)
  814. {
  815. INI_WriteBool(YSI_g_sPlayerWriteFile, name, data);
  816. }
  817. /*-------------------------------------------------------------------------*//**
  818. * <param name="name">Data name.</param>
  819. * <param name="data">Float data.</param>
  820. * <param name="accuracy">number of decimal places to write.</param>
  821. * <remarks>
  822. * Wrapper for Player_AddToBuffer for floats. Uses custom code instead of
  823. * format() as it's actually faster for something simple like this.
  824. * </remarks>
  825. *//*------------------------------------------------------------------------**/
  826. stock Player_WriteFloat(name[], Float:data, accuracy = 6)
  827. {
  828. INI_WriteFloat(YSI_g_sPlayerWriteFile, name, data, accuracy);
  829. }
  830. stock Player_SetTag(tag[])
  831. {
  832. // Make sure we ALWAYS store mode tags with a special prefix.
  833. new
  834. tag2[MAX_INI_TAG] = "@@" #MODE_NAME "-";
  835. strcat(tag2, tag);
  836. //printf("tag = %s, %s", tag, tag2);
  837. INI_SetTag(YSI_g_sPlayerWriteFile, tag2);
  838. }
  839. stock Player_DeleteTag(tag[])
  840. {
  841. INI_DeleteTag(YSI_g_sPlayerWriteFile, tag);
  842. }
  843. //global Player_DoLogout(playerid, uid)
  844. static stock Player_DoLogout(playerid, uid)
  845. {
  846. /*INI:YSI_g_sOneLogoutFile = INI_NO_FILE
  847. YSI_g_sOneLogoutPerson = INVALID_PLAYER_ID*/
  848. new
  849. filename[64];
  850. format(filename, sizeof (filename), USER_FILE_PATH "%0" #MAX_INDEX_LENGTH "d.INI", uid);
  851. YSI_g_sPlayerWriteFile = INI_Open(filename);
  852. if (YSI_g_sPlayerWriteFile != INI_NO_FILE)
  853. {
  854. //Hooks_OnPlayerLogout(playerid, uid);
  855. //if (YSI_g_sCallbacks & 2)
  856. //{
  857. call OnPlayerLogout(playerid, uid);
  858. //}
  859. INI_Close(YSI_g_sPlayerWriteFile);
  860. }
  861. // Do ALL the saving from ONE place. Detect one or many scripts ending.
  862. /*if (YSI_g_sOneLogoutFile == INI_NO_FILE)
  863. {
  864. new
  865. filename[64];
  866. format(filename, sizeof (filename), USER_FILE_PATH "%0" #MAX_INDEX_LENGTH "d.INI", uid);
  867. YSI_g_sOneLogoutFile = INI_Open(filename);
  868. YSI_g_sOneLogoutPerson = playerid;
  869. }
  870. else if (YSI_g_sOneLogoutPerson != playerid)
  871. {
  872. INI_Close(YSI_g_sOneLogoutFile);
  873. }
  874. // Will be called AFTER all "OnPlayerDisconnect" callbacks are called when
  875. // one player leaves, and if more leave it's still used for the last player
  876. // in the list.
  877. //defer _Player_CloseLogout();
  878. _Player_CloseLogout();
  879. // By now "YSI_g_sOneLogoutFile" contains a handle to the user's file,
  880. // either having just been opened, or invoked in a previous call to this
  881. // function from another script still running but loosing the player.
  882. // This could in theory be used from some force-logout script.
  883. YSI_g_sPlayerYID[playerid] = -1;*/
  884. return 1;
  885. }
  886. //static timer _Player_CloseLogout[0]()
  887. /*static stock _Player_CloseLogout()
  888. {
  889. if (YSI_g_sOneLogoutFile != INI_NO_FILE)
  890. {
  891. INI_Close(YSI_g_sOneLogoutFile);
  892. YSI_g_sOneLogoutFile = INI_NO_FILE;
  893. YSI_g_sOneLogoutPerson = INVALID_PLAYER_ID;
  894. }
  895. }*/
  896. /*-------------------------------------------------------------------------*//**
  897. * <param name="pass">Data to hash.</param>
  898. * <remarks>
  899. * Based on my Dad's hash system but slightly modifed. Updated for reverse
  900. * compatability with other login systems. Needs more code for Whirlpool.
  901. * </remarks>
  902. *//*------------------------------------------------------------------------**/
  903. static stock Player_HashPass(pass[], target[])
  904. {
  905. #if defined PP_ADLER32
  906. new
  907. s1 = 1,
  908. s2 = 0,
  909. i,
  910. You_REALLY_shouldnt_use_Adler32;
  911. while (pass[i])
  912. {
  913. s1 = (s1 + pass[i++]) % 65521;
  914. s2 = (s2 + s1) % 65521;
  915. }
  916. //new
  917. // target[MAX_PASSWORD_LENGTH + 1];
  918. format(target, sizeof (target), "%" #MAX_PASSWORD_LENGTH "d", (s2 << 16) + s1);
  919. //return target;
  920. #elseif defined PP_MD5 && defined MD5_Hash
  921. new
  922. You_REALLY_shouldnt_use_MD5;
  923. strcpy(target, MD5_Hash(pass, strlen(pass)));
  924. #elseif defined PP_SHA1
  925. #error SHA1 unsupported.
  926. #elseif defined PP_YSI
  927. static
  928. charset[] = "A,UbRgdnS#|rT_%5+ZvEK¬NF<9¦IH[(C)2O07 Y-Less]$Qw^?/om4;@'8k£Pp.c{&l\\3zay>DfxV:WXjuG6*!1\"i~=Mh`JB}qt",
  929. css = 99;
  930. new
  931. //target[MAX_PASSWORD_LENGTH + 1],
  932. j,
  933. sum = j,
  934. tmp = 0,
  935. i,
  936. mod;
  937. j = strlen(pass);
  938. for (i = 0; i < MAX_PASSWORD_LENGTH || i < j; i++)
  939. {
  940. mod = i % MAX_PASSWORD_LENGTH;
  941. tmp = (i >= j) ? charset[(7 * i) % css] : pass[i];
  942. sum = (sum + chrfind(tmp, charset) + 1) % css;
  943. target[mod] = charset[(sum + target[mod]) % css];
  944. }
  945. target[MAX_PASSWORD_LENGTH] = '\0';
  946. //return target;
  947. #elseif defined WP_Hash
  948. WP_Hash(target, MAX_PASSWORD_LENGTH + 1, pass);
  949. #else
  950. #error Whirlpool (or other) hash not found.
  951. #endif
  952. }
  953. // Hooray for bizare bugs! I think this is because the function above is
  954. // secretly a macro with "if/else" and a block statement, not a real function.
  955. stock Player_SomeWeirdBugFix()
  956. {
  957. }
  958. /*stock Anything0()
  959. {
  960. }*/
  961. /*stock Anything1()
  962. {
  963. }
  964. stock Anything2()
  965. {
  966. }
  967. stock Anything3()
  968. {
  969. }*/
  970. /*stock Anything4()
  971. {
  972. }
  973. stock Anything5()
  974. {
  975. }
  976. stock Anything6()
  977. {
  978. }
  979. stock Anything7()
  980. {
  981. }*/
  982. /*-------------------------------------------------------------------------*//**
  983. * <param name="playerid">Player who is registering.</param>
  984. * <param name="password">The password they entered.</param>
  985. * <remarks>
  986. * Register the player with the given password if there is no-one else with the
  987. * name already. Or log them in if the username and password match an existing
  988. * account. Note that there is no "Player_ForceRegister" as it would do the
  989. * same thing with no less parameters (a password MUST be given to write in the
  990. * file).
  991. * </remarks>
  992. *//*------------------------------------------------------------------------**/
  993. //#endinput
  994. global Player_TryRegister(playerid, string:password[])
  995. {
  996. P:2("Player_TryRegister called");
  997. if (Player_IsLoggedIn(playerid))
  998. {
  999. // They are already logged in.
  1000. Text_Send(playerid, $YSI_LOGIN_ALREADY);
  1001. return 1;
  1002. }
  1003. new
  1004. hash[MAX_PASSWORD_LENGTH + 1 + 8];
  1005. Player_HashPass(password, hash);
  1006. switch (YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID])
  1007. {
  1008. case -2:
  1009. {
  1010. Text_Send(playerid, $YSI_LOGIN_INDERR);
  1011. }
  1012. case -1:
  1013. {
  1014. }
  1015. default:
  1016. {
  1017. // Get the salt.
  1018. format(hash[MAX_PASSWORD_LENGTH], sizeof (hash) - MAX_PASSWORD_LENGTH, "%04x%04x", YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE] >>> 16, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE] & 0xFFFF);
  1019. Player_HashPass(hash, hash);
  1020. // Match the password.
  1021. if (!strcmp(YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS], hash, false, MAX_PASSWORD_LENGTH) && YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS][0])
  1022. {
  1023. // Extract the uid and call in to the login code.
  1024. YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS] = '\0';
  1025. Langs_SetPlayerLanguage(playerid, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_LANG]);
  1026. broadcastfunc Player_DoLogin(playerid, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID]);
  1027. Text_Send(playerid, $YSI_LOGIN_LOGIN);
  1028. return 1;
  1029. }
  1030. else
  1031. {
  1032. //Text_Send(playerid, $YSI_LOGIN_WRONG);
  1033. Text_Send(playerid, $YSI_REG_TAKEN);
  1034. return 0;
  1035. }
  1036. }
  1037. }
  1038. new
  1039. name[MAX_PLAYER_NAME + 1];
  1040. GetPlayerName(playerid, name, sizeof (name));
  1041. //format(name, sizeof (name), "%" #MAX_PLAYER_NAME "s", name);
  1042. new
  1043. filename[64] = USER_FILE_PATH "ind_X.YSI",
  1044. File:fIndex;//,
  1045. //hash[MAX_PASSWORD_LENGTH + 1];
  1046. //Player_HashPass(password, hash);
  1047. Player_GetIndexFile(filename, name[0]);
  1048. fIndex = fopen(filename, io_read);
  1049. P:5("Player_TryRegister: fIndex");
  1050. new
  1051. line[INDEX_DATA_LINE_LENGTH];
  1052. if ((fIndex = fopen(filename, io_append)))
  1053. {
  1054. P:5("Player_TryRegister: Write index.");
  1055. // Write the new user to the index file.
  1056. new
  1057. uid = Player_GetNewID();
  1058. if (uid == -1)
  1059. {
  1060. Text_Send(playerid, $YSI_LOGIN_INDERR);
  1061. return 0;
  1062. }
  1063. new
  1064. d = gettime(),
  1065. date[9];
  1066. format(date, sizeof (date), "%04x%04x", d >>> 16, d & 0xFFFF);
  1067. strcat(hash, date);
  1068. Player_HashPass(hash, hash);
  1069. format(line, sizeof (line), "%0" #MAX_INDEX_LENGTH "d %" #MAX_PLAYER_NAME "s %" #MAX_PASSWORD_LENGTH "s %02s 00000000 %s" INI_NEW_LINE, uid, name, hash, Langs_GetCode(Langs_GetPlayerLanguage(playerid)), date);
  1070. fwrite(fIndex, line);
  1071. fclose(fIndex);
  1072. format(filename, sizeof (filename), USER_FILE_PATH "%0" #MAX_INDEX_LENGTH "d.INI", uid);
  1073. new
  1074. INI:x = INI_Open(filename);
  1075. if (x == INI_NO_FILE)
  1076. {
  1077. Text_Send(playerid, $YSI_LOGIN_NOLOAD);
  1078. }
  1079. else
  1080. {
  1081. INI_SetTag(x, "ysi_names");
  1082. INI_WriteString(x, name, "name");
  1083. INI_Close(x);
  1084. }
  1085. // Call in all scripts.
  1086. broadcastfunc Player_DoLogin(playerid, uid);
  1087. Text_Send(playerid, $YSI_LOGIN_LOGIN);
  1088. return 1;
  1089. }
  1090. else
  1091. {
  1092. Text_Send(playerid, $YSI_ADDU_INDER2);
  1093. return 0;
  1094. }
  1095. }
  1096. global Player_ChangePassword(playerid, string:password[])
  1097. {
  1098. #pragma unused password
  1099. new
  1100. uid = Player_GetYID(playerid);
  1101. if (uid < 0)
  1102. {
  1103. return 0;
  1104. }
  1105. // Create the new password.
  1106. new
  1107. hash[MAX_PASSWORD_LENGTH + 8 + 1];
  1108. Player_HashPass(password, hash);
  1109. format(hash[MAX_PASSWORD_LENGTH], sizeof (hash) - MAX_PASSWORD_LENGTH, "%04x%04x", YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE] >>> 16, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE] & 0xFFFF);
  1110. Player_HashPass(hash, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS]);
  1111. // Save it.
  1112. Player_RewritePreload(playerid);
  1113. // Wipe it.
  1114. memset(YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS], 0, MAX_PASSWORD_LENGTH);
  1115. return 1;
  1116. }
  1117. /*-------------------------------------------------------------------------*//**
  1118. * <param name="playerid">Player whose data should be saved.</param>
  1119. * <remarks>
  1120. * When a player's preload data is modifed (new bit data or changed password),
  1121. * it needs to be written back out to file.
  1122. * </remarks>
  1123. *//*------------------------------------------------------------------------**/
  1124. static stock Player_RewritePreload(playerid)
  1125. {
  1126. if (YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID] < 0)
  1127. {
  1128. return 0;
  1129. }
  1130. // First, find the player's file. This should be the ONLY place where the
  1131. // password is to be loaded.
  1132. //ret[E_USER_PRELOAD_YID] = -2;
  1133. //ret[E_USER_PRELOAD_PASS] = '\0';
  1134. //ret[E_USER_PRELOAD_LANG] = NO_LANGUAGE;
  1135. //ret[E_USER_PRELOAD_BITS] = 0;
  1136. //ret[E_USER_PRELOAD_DATE] = 0;
  1137. new
  1138. name[MAX_PLAYER_NAME + 1];
  1139. GetPlayerName(playerid, name, sizeof (name));
  1140. P:4("Player_RewritePreload called: %s", name);
  1141. #if _YSI_PLUGINS_MYSQL == 7
  1142. // Right then, lets get coding...
  1143. new
  1144. query[110];
  1145. mysql_format(YSI_g_sMySQL, query, "SELECT `uid`, `language`, `hash` FROM `y_users_register` WHERE `name` = '%e' LIMIT 0,1", name);
  1146. mysql_function_query(YSI_g_sMySQL, query, true, "_Player_Preload", "ii", );
  1147. #else
  1148. new
  1149. namelen = strlen(name),
  1150. filename[] = USER_FILE_PATH "ind_X.YSI",
  1151. File:fIndex;
  1152. Player_GetIndexFile(filename, name[0]);
  1153. fIndex = fopen(filename, io_readwrite);
  1154. if (fIndex)
  1155. {
  1156. P:5("Player_RewritePreload: fIndex OK");
  1157. new
  1158. line[INDEX_DATA_LINE_LENGTH],
  1159. len;
  1160. while ((len = fread(fIndex, line)))
  1161. {
  1162. P:6("Player_RewritePreload: while");
  1163. //new
  1164. // len;
  1165. //len = strlen(line);
  1166. // Check if the line is the right length (could be one of three
  1167. // lengths depending on newlines). Skip blanks.
  1168. if (len < INDEX_DATA_LINE_LENGTH - 3)
  1169. {
  1170. continue;
  1171. }
  1172. P:6("Player_RewritePreload: Not len");
  1173. // Check the name on the line.
  1174. if (!strcmp(line[MAX_INDEX_LENGTH + 1], name, false, namelen) && line[MAX_INDEX_LENGTH + 1 + namelen] == ' ')
  1175. {
  1176. P:6("Player_RewritePreload: checked name");
  1177. fseek(fIndex, -len, seek_current);
  1178. //format(line, sizeof (line),
  1179. format(line, sizeof (line),
  1180. "%0" #MAX_INDEX_LENGTH "d %" #MAX_PLAYER_NAME "s %" #MAX_PASSWORD_LENGTH "s %02s %04x%04x %04x%04x" INI_NEW_LINE,
  1181. YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID],
  1182. name,
  1183. YSI_g_sPreloadData[playerid][E_USER_PRELOAD_PASS],
  1184. Langs_GetCode(Langs_GetPlayerLanguage(playerid)),
  1185. YSI_g_sPreloadData[playerid][E_USER_PRELOAD_BITS] >>> 16, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_BITS] & 0xFFFF,
  1186. YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE] >>> 16, YSI_g_sPreloadData[playerid][E_USER_PRELOAD_DATE] & 0xFFFF);
  1187. P:5("Player_RewritePreload: Writing: %s", line);
  1188. fwrite(fIndex, line);
  1189. fclose(fIndex);
  1190. return 1;
  1191. }
  1192. }
  1193. fclose(fIndex);
  1194. }
  1195. else if (fexist(filename))
  1196. {
  1197. P:E("Error reading index %c.", filename[0]);
  1198. return 0;
  1199. }
  1200. //ret[E_USER_PRELOAD_YID] = -1;
  1201. #endif
  1202. return 0;
  1203. }
  1204. /*-------------------------------------------------------------------------*//**
  1205. * <param name="playerid">Player who is joining a group.</param>
  1206. * <param name="other">A player name already in the group.</param>
  1207. * <param name="password">The password of the group.</param>
  1208. * <remarks>
  1209. * Links a player with an existing player such that they share all stats.
  1210. * </remarks>
  1211. *//*------------------------------------------------------------------------**/
  1212. //#endinput
  1213. global Player_TryGroup(playerid, string:other[], string:password[])
  1214. {
  1215. P:2("Player_TryGroup called");
  1216. if (Player_IsLoggedIn(playerid))
  1217. {
  1218. // They are already logged in.
  1219. Text_Send(playerid, $YSI_LOGIN_ALREADY);
  1220. return 1;
  1221. }
  1222. new
  1223. hash[MAX_PASSWORD_LENGTH + 1];
  1224. Player_HashPass(password, hash);
  1225. // Check if the user is not registered already.
  1226. switch (YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID])
  1227. {
  1228. case -2:
  1229. {
  1230. Text_Send(playerid, $YSI_LOGIN_INDERR);
  1231. return 0;
  1232. }
  1233. case -1:
  1234. {
  1235. //Text_Send(playerid, $YSI_LOGIN_NOTF);
  1236. }
  1237. default:
  1238. {
  1239. Text_Send(playerid, $YSI_REG_TAKEN);
  1240. return 0;
  1241. }
  1242. }
  1243. // Check if the new data matches the old.
  1244. new
  1245. ret[E_USER_PRELOAD];
  1246. Player_Preload(other, ret);
  1247. switch (ret[E_USER_PRELOAD_YID])
  1248. {
  1249. case -2:
  1250. {
  1251. Text_Send(playerid, $YSI_LOGIN_INDERR);
  1252. }
  1253. case -1:
  1254. {
  1255. Text_Send(playerid, $YSI_LOGIN_NOTF);
  1256. }
  1257. default:
  1258. {
  1259. // Match the password.
  1260. if (!strcmp(ret[E_USER_PRELOAD_PASS], hash, false, MAX_PASSWORD_LENGTH) && ret[E_USER_PRELOAD_PASS][0])
  1261. {
  1262. new
  1263. name[MAX_PLAYER_NAME + 1];
  1264. GetPlayerName(playerid, name, sizeof (name));
  1265. new
  1266. filename[64] = USER_FILE_PATH "ind_X.YSI";
  1267. Player_GetIndexFile(filename, name[0]);
  1268. new
  1269. File:fIndex = fopen(filename, io_append);
  1270. if (!fIndex)
  1271. {
  1272. Text_Send(playerid, $YSI_ADDU_INDERR2);
  1273. return 0;
  1274. }
  1275. P:5("Player_TryGroup: Write index.");
  1276. new
  1277. uid = ret[E_USER_PRELOAD_YID],
  1278. line[INDEX_DATA_LINE_LENGTH];
  1279. // Use the loaded ID.
  1280. format(line, sizeof (line), "%0" #MAX_INDEX_LENGTH "d %" #MAX_PLAYER_NAME "s %" #MAX_PASSWORD_LENGTH "s %02s" INI_NEW_LINE, uid, name, hash, Langs_GetCode(ret[E_USER_PRELOAD_LANG]));
  1281. fwrite(fIndex, line);
  1282. fclose(fIndex);
  1283. format(filename, sizeof (filename), USER_FILE_PATH "%0" #MAX_INDEX_LENGTH "d.INI", uid);
  1284. new
  1285. INI:x = INI_Open(filename);
  1286. if (x == INI_NO_FILE)
  1287. {
  1288. Text_Send(playerid, $YSI_LOGIN_NOLOAD);
  1289. }
  1290. else
  1291. {
  1292. // Add this name to the list of known names.
  1293. INI_SetTag(x, "ysi_names");
  1294. INI_WriteString(x, name, "name");
  1295. INI_Close(x);
  1296. }
  1297. // Call in all scripts.
  1298. Langs_SetPlayerLanguage(playerid, ret[E_USER_PRELOAD_LANG]);
  1299. broadcastfunc Player_DoLogin(playerid, uid);
  1300. Text_Send(playerid, $YSI_LOGIN_LOGIN);
  1301. return 1;
  1302. }
  1303. else
  1304. {
  1305. Text_Send(playerid, $YSI_LOGIN_WRONG);
  1306. }
  1307. }
  1308. }
  1309. return 0;
  1310. }
  1311. /*-------------------------------------------------------------------------*//**
  1312. * <param name="playerid">Player who is joining a group.</param>
  1313. * <param name="other">A player name already in the group.</param>
  1314. * <remarks>
  1315. * Like "Player_TryGroup", but doesn't take a password and instead just uses
  1316. * the password of the old player (hashed).
  1317. * </remarks>
  1318. *//*------------------------------------------------------------------------**/
  1319. //#endinput
  1320. global Player_ForceGroup(playerid, string:other[])
  1321. {
  1322. P:2("Player_ForceGroup called");
  1323. if (Player_IsLoggedIn(playerid))
  1324. {
  1325. // They are already logged in.
  1326. Text_Send(playerid, $YSI_LOGIN_ALREADY);
  1327. return 1;
  1328. }
  1329. // Check if the user is not registered already.
  1330. switch (YSI_g_sPreloadData[playerid][E_USER_PRELOAD_YID])
  1331. {
  1332. case -2:
  1333. {
  1334. Text_Send(playerid, $YSI_LOGIN_INDERR);
  1335. return 0;
  1336. }
  1337. case -1:
  1338. {
  1339. //Text_Send(playerid, $YSI_LOGIN_NOTF);
  1340. }
  1341. default:
  1342. {
  1343. Text_Send(playerid, $YSI_REG_TAKEN);
  1344. return 0;
  1345. }
  1346. }
  1347. // Check if the new data matches the old.
  1348. new
  1349. ret[E_USER_PRELOAD];
  1350. Player_Preload(other, ret);
  1351. switch (ret[E_USER_PRELOAD_YID])
  1352. {
  1353. case -2:
  1354. {
  1355. Text_Send(playerid, $YSI_LOGIN_INDERR);
  1356. }
  1357. case -1:
  1358. {
  1359. Text_Send(playerid, $YSI_LOGIN_NOTF);
  1360. }
  1361. default:
  1362. {
  1363. new
  1364. name[MAX_PLAYER_NAME + 1];
  1365. GetPlayerName(playerid, name, sizeof (name));
  1366. new
  1367. filename[64] = USER_FILE_PATH "ind_X.YSI";
  1368. Player_GetIndexFile(filename, name[0]);
  1369. new
  1370. File:fIndex = fopen(filename, io_append);
  1371. if (!fIndex)
  1372. {
  1373. Text_Send(playerid, $YSI_ADDU_INDERR2);
  1374. return 0;
  1375. }
  1376. P:5("Player_TryGroup: Write index.");
  1377. new
  1378. uid = ret[E_USER_PRELOAD_YID],
  1379. line[INDEX_DATA_LINE_LENGTH];
  1380. // Use the loaded ID.
  1381. format(line, sizeof (line), "%0" #MAX_INDEX_LENGTH "d %" #MAX_PLAYER_NAME "s %" #MAX_PASSWORD_LENGTH "s %02s" INI_NEW_LINE, uid, name, ret[E_USER_PRELOAD_PASS], Langs_GetCode(ret[E_USER_PRELOAD_LANG]));
  1382. fwrite(fIndex, line);
  1383. fclose(fIndex);
  1384. format(filename, sizeof (filename), USER_FILE_PATH "%0" #MAX_INDEX_LENGTH "d.INI", uid);
  1385. new
  1386. INI:x = INI_Open(filename);
  1387. if (x == INI_NO_FILE)
  1388. {
  1389. Text_Send(playerid, $YSI_LOGIN_NOLOAD);
  1390. }
  1391. else
  1392. {
  1393. // Add this name to the list of known names.
  1394. INI_SetTag(x, "ysi_names");
  1395. INI_WriteString(x, name, "name");
  1396. INI_Close(x);
  1397. }
  1398. // Call in all scripts.
  1399. Langs_SetPlayerLanguage(playerid, ret[E_USER_PRELOAD_LANG]);
  1400. broadcastfunc Player_DoLogin(playerid, uid);
  1401. Text_Send(playerid, $YSI_LOGIN_LOGIN);
  1402. return 1;
  1403. }
  1404. }
  1405. return 0;
  1406. }
  1407. static stock Player_GetNewID()
  1408. {
  1409. new
  1410. File:fHnd = fopen(USER_FILE_PATH "index.YSI", io_readwrite),
  1411. num[MAX_INDEX_LENGTH + 9],
  1412. uid = -1;
  1413. if (fHnd)
  1414. {
  1415. fread(fHnd, num);
  1416. num[strfind(num, " ")] = '\0';
  1417. uid = strval(num) + 1;
  1418. valstr(num, uid);
  1419. fseek(fHnd, 0, seek_start);
  1420. fwrite(fHnd, num);
  1421. fwrite(fHnd, " ");
  1422. fclose(fHnd);
  1423. }
  1424. return uid;
  1425. }
  1426. static stock Player_CreateNewID()
  1427. {
  1428. new
  1429. File:fHnd = fopen(USER_FILE_PATH "index.YSI", io_write);
  1430. if (fHnd)
  1431. {
  1432. fwrite(fHnd, "-1 ");
  1433. fclose(fHnd);
  1434. return 1;
  1435. }
  1436. return 0;
  1437. }