1
0

y_users.inc 34 KB

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