· 9 years ago · May 12, 2017, 11:30 PM
1//-------------------------------------------------------------------//
2//**************************** INCLUDES *****************************//
3//-------------------------------------------------------------------//
4
5#include <a_samp>
6#include <crashdetect>
7#include <YSI\y_iterate>
8#include <a_mysql>
9#include <CTime>
10
11//-------------------------------------------------------------------//
12//************************* DEFINIÇÕES ******************************//
13//********************* Você pode alterar ***************************//
14//-------------------------------------------------------------------//
15
16// --> Configurações
17#define SERVER_NAME ("EasyWay")
18#define SERVER_VERSION ("0.1")
19#define MAX_LOGIN_ATTEMPTS (3)
20
21// --> Cores
22#define COLOR_BLUE (0x2641FEFF)
23#define COLOR_GREY (0xAFAFAFFF)
24#define COLOR_LIGHTRED (0xFF6347FF)
25#define COLOR_LIGHTBLUE (0x33CCFFAA)
26#define COLOR_LIGHTGREEN (0x66ff66FF)
27#define COLOR_CLIENT (0xAAC4E5FF)
28#define COLOR_TEAL (0x00A180FF)
29#define COLOR_ORANGE (0xFF9409FF)
30#define COLOR_PURPLE (0xD0AEEBFF)
31#define COLOR_OPENSERV (0xFFBD9DFF)
32#define COLOR_WHITE (0xFFFFFFFF)
33#define COLOR_PINK (0xFF66FFAA)
34#define COLOR_RED (0xFF0000AA)
35#define COLOR_YELLOW (0xFFFF00AA)
36#define COLOR_GREEN (0x33AA33AA)
37#define COLOR_LIGHTBLUE2 (0x99ccffAA)
38#define COLOR_BROWN (0xA8623EAA)
39#define COLOR_LIGHTBROWN (0xf4ac94AA)
40#define COLOR_LIGHTBROWN2 (0xc7a6afAA)
41
42// --> Cores para dialogs e afins
43#define COLOR_TITLE_DIALOG "{00a180}"
44#define COLORT_GREEN "{49ad00}"
45#define COLORT_YELLOW "{fff600}"
46#define COLORT_WHITE "{ffffff}"
47#define COLORT_LIGHTRED "{e44235}"
48#define COLORT_ORANGE "{ff9409}"
49#define COLORT_ORANGE2 "{f2bb73}"
50#define COLORT_GREY "{a4a4a4}"
51
52//-------------------------------------------------------------------//
53//************************ !DEFINIÇÕES! *****************************//
54//******************** Cuidado ao alterar ***************************//
55//-------------------------------------------------------------------//
56
57#define DIALOG_REGISTER (1) // até 20
58#define DIALOG_LOGIN (21)
59
60#define sendServerMessage(%0,%1) \
61 sendClientMessageEx(%0, COLOR_TEAL, "[SERVER]:{FFFFFF} "%1)
62
63#define sendSyntaxMessage(%0,%1) \
64 sendClientMessageEx(%0, COLOR_GREY, "[USO CORRETO]:{FFFFFF} "%1)
65
66#define sendErrorMessage(%0,%1) \
67 sendClientMessageEx(%0, COLOR_LIGHTRED, "[ERRO]:{FFFFFF} "%1)
68
69#define sendAdminAction(%0,%1) \
70 sendClientMessageEx(%0, COLOR_CLIENT, "[ADMIN]:{FFFFFF} "%1)
71
72#define sendWarningMessage(%0,%1) \
73 sendClientMessageEx(%0, COLOR_YELLOW, "[AVISO]: "%1)
74
75#define MENU_LOGIN_INDEX (1)
76#define MENU_LOGIN_REGISTER (2)
77#define MENU_LOGIN_REGISTER_STAGE_1 (3)
78#define MENU_LOGIN_REGISTER_STAGE_2 (4)
79#define MENU_LOGIN_REGISTER_STAGE_3 (5)
80
81//-------------------------------------------------------------------//
82//*************************** VARIÃVEIS *****************************//
83//-------------------------------------------------------------------//
84
85new Dialog[2048],
86 String[1024],
87 Query[1024],
88 MySQL:MySQL_Connection = MYSQL_INVALID_HANDLE;
89
90enum enum_Player
91{
92 // Data
93 ORM:pORM,
94 pAccountID,
95 pName[24],
96 pPassword[65],
97 pEmail[64],
98 pRegisterDate,
99 pLastLogin,
100
101 // Non-data
102 pDialogID,
103 bool:pKicked,
104 bool:pLogged,
105 pMaxLoginAttempts,
106 pTimerPlayer,
107
108 // Registro
109 registerPassword[30]
110}
111
112new Player[MAX_PLAYERS][enum_Player];
113
114//-------------------------------------------------------------------//
115//**************************** FORWARDS *****************************//
116//-------------------------------------------------------------------//
117
118forward KickTimer(playerid);
119forward OnPlayerDataLoaded(playerid);
120forward OnPlayerRegister(playerid);
121forward OnPlayerUpdateEx(playerid);
122forward TimerOneMinute();
123
124//-------------------------------------------------------------------//
125
126main()
127{
128 print("\n----------------------------------");
129 printf("%s [v%s]", SERVER_NAME, SERVER_VERSION);
130 print("----------------------------------\n");
131}
132
133public OnGameModeInit()
134{
135 printf("[MySQL] Estabelecendo conexão com o servidor..");
136
137 MySQL_Connection = mysql_connect_file("mysql_connection.ini");
138 mysql_log(ALL);
139
140 if(MySQL_Connection == MYSQL_INVALID_HANDLE)
141 {
142 print("[MySQL] Não foi possÃvel realizar a conexão, desligando servidor..");
143 SendRconCommand("exit");
144 }
145 else
146 print("[MySQL] Conexão estabelecida com sucesso.");
147
148 format(String, sizeof(String), "%s [v%s]", SERVER_NAME, SERVER_VERSION);
149 SetGameModeText(String);
150
151 SetTimer("TimerOneMinute", 1000*60, true);
152
153 AddPlayerClass(0, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);
154 return 1;
155}
156
157public OnGameModeExit()
158{
159 mysql_close(MySQL_Connection);
160 return 1;
161}
162
163public OnPlayerRequestClass(playerid, classid)
164{
165 if(!IsPlayerNPC(playerid))
166 {
167 TogglePlayerSpectating(playerid, true);
168 InterpolateCameraPos(playerid, 1350.289306, -1399.634887, 39.952976, 1346.096069, -989.852233, 74.761276, 1000*40);
169 InterpolateCameraLookAt(playerid, 1350.505981, -1394.746826, 38.923583, 1348.108398, -985.276794, 74.885650, 1000*40);
170
171 orm_setkey(Player[playerid][pORM], "Name");
172 orm_select(Player[playerid][pORM], "OnPlayerDataLoaded", "d", playerid);
173 }
174 return 1;
175}
176
177public OnPlayerConnect(playerid)
178{
179 if(!IsPlayerNPC(playerid))
180 {
181 SetSpawnInfo(playerid, 0, 23, 1958.3783, 1343.1572, 15.3746, 269.1425, 0, 0, 0, 0, 0, 0);
182 clearPlayerVars(playerid);
183 loadPlayer(playerid);
184
185 Player[playerid][pTimerPlayer] = SetTimerEx("OnPlayerUpdateEx", 1000, true, "i", playerid);
186 }
187 return 1;
188}
189
190public OnPlayerDataLoaded(playerid)
191{
192 orm_setkey(Player[playerid][pORM], "ID");
193
194 switch(orm_errno(Player[playerid][pORM]))
195 {
196 case ERROR_INVALID:
197 {
198 sendServerMessage(playerid, "Ocorreu algum problema, entre novamente..");
199 kickEx(playerid);
200 }
201 case ERROR_OK: showLoginMenu(playerid, MENU_LOGIN_INDEX);
202 case ERROR_NO_DATA: showLoginMenu(playerid, MENU_LOGIN_REGISTER);
203 }
204}
205
206public OnPlayerRegister(playerid)
207{
208 sendServerMessage(playerid, "Conta criada com sucesso! Você foi o %dº a criar uma conta.", Player[playerid][pAccountID]);
209 Player[playerid][pLogged] = true;
210 TogglePlayerSpectating(playerid, false);
211}
212
213
214public OnPlayerDisconnect(playerid, reason)
215{
216 if(!IsPlayerNPC(playerid))
217 {
218 if(Player[playerid][pTimerPlayer] != 0)
219 KillTimer(Player[playerid][pTimerPlayer]);
220
221 orm_update(Player[playerid][pORM]);
222 orm_destroy(Player[playerid][pORM]);
223 clearPlayerVars(playerid);
224 }
225 return 1;
226}
227
228public OnPlayerSpawn(playerid)
229{
230 return 1;
231}
232
233public OnPlayerDeath(playerid, killerid, reason)
234{
235 return 1;
236}
237
238public OnPlayerText(playerid, text[])
239{
240 return 1;
241}
242
243public OnPlayerCommandText(playerid, cmdtext[])
244{
245 if (strcmp("/mycommand", cmdtext, true, 10) == 0)
246 {
247 // Do something here
248 return 1;
249 }
250 return 0;
251}
252
253public OnPlayerStateChange(playerid, newstate, oldstate)
254{
255 return 1;
256}
257
258public OnRconCommand(cmd[])
259{
260 return 1;
261}
262
263public OnPlayerRequestSpawn(playerid)
264{
265 if(!Player[playerid][pLogged])
266 return false;
267
268 return SpawnPlayer(playerid);
269}
270
271
272public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
273{
274 return 1;
275}
276
277public OnRconLoginAttempt(ip[], password[], success)
278{
279 return 1;
280}
281
282public OnPlayerUpdate(playerid)
283{
284 return 1;
285}
286
287public OnPlayerUpdateEx(playerid)
288{
289
290}
291
292public TimerOneMinute()
293{
294 foreach(new i : Player)
295 {
296 if(!Player[i][pLogged])
297 continue;
298
299 orm_update(Player[i][pORM]);
300 }
301}
302
303public OnPlayerClickPlayer(playerid, clickedplayerid, source)
304{
305 return 1;
306}
307
308public KickTimer(playerid)
309{
310 if(Player[playerid][pKicked])
311 return Kick(playerid);
312
313 return false;
314}
315
316public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
317{
318 if(Player[playerid][pDialogID] != dialogid)
319 {
320 kickEx(playerid);
321 sendWarningMessage(playerid, "Você foi kickado por suspeita de utilizar Dialog-Hack.");
322 return true;
323 }
324
325 switch(dialogid)
326 {
327 case DIALOG_REGISTER:
328 {
329 if(!response)
330 {
331 sendServerMessage(playerid, "Tudo bem, volte quando quiser criar uma conta!");
332 kickEx(playerid);
333 return true;
334 }
335
336 showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_1);
337 return true;
338 }
339 case DIALOG_REGISTER+1:
340 {
341 if(!response)
342 {
343 sendServerMessage(playerid, "Tudo bem, volte quando quiser criar uma conta!");
344 kickEx(playerid);
345 return true;
346 }
347
348 if(isnull(inputtext))
349 return showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_1, ""#COLORT_LIGHTRED"Você precisa digitar uma senha!");
350
351 if(!isValidPassword(inputtext))
352 return showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_1, ""#COLORT_LIGHTRED"Senha inválida (somente 6 à 30 dÃgitos).");
353
354 format(Player[playerid][registerPassword], 30, inputtext);
355 showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_2);
356 return true;
357 }
358 case DIALOG_REGISTER+2:
359 {
360 if(!response)
361 {
362 Player[playerid][registerPassword][0] = EOS;
363 showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_1);
364 return true;
365 }
366
367 if(isnull(inputtext))
368 return showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_2, ""#COLORT_LIGHTRED"Você precisa confirmar sua senha!");
369
370 if(!strcmp(Player[playerid][registerPassword], inputtext))
371 showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_3);
372 else
373 showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_2, ""#COLORT_LIGHTRED"As senhas não combinam!");
374
375 return true;
376 }
377 case DIALOG_REGISTER+3:
378 {
379 if(!response)
380 {
381 Player[playerid][registerPassword][0] = EOS;
382 showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_1);
383 return true;
384 }
385
386 if(isnull(inputtext))
387 return showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_3, ""#COLORT_LIGHTRED"Você precisa digitar algum e-mail!");
388
389 if(!isValidEmail(inputtext))
390 return showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_3, ""#COLORT_LIGHTRED"Digite um e-mail válido!");
391
392 if(SQL_verifyEmail(inputtext))
393 return showLoginMenu(playerid, MENU_LOGIN_REGISTER_STAGE_3, ""#COLORT_LIGHTRED"Este e-mail já está em uso.");
394
395 // --> Registro concluido
396
397 SHA256_PassHash(Player[playerid][registerPassword], "EveryBodyHatesCris", Player[playerid][pPassword], 65);
398 format(Player[playerid][pEmail], 64, inputtext);
399
400 Player[playerid][pRegisterDate] = gettime();
401 Player[playerid][pLastLogin] = gettime();
402
403 orm_insert(Player[playerid][pORM], "OnPlayerRegister", "d", playerid);
404 }
405 case DIALOG_LOGIN:
406 {
407 if(!response)
408 {
409 sendServerMessage(playerid, "Volte sempre.");
410 kickEx(playerid);
411 return true;
412 }
413
414 if(isnull(inputtext))
415 return showLoginMenu(playerid, MENU_LOGIN_INDEX, ""#COLORT_LIGHTRED"Digite sua senha!");
416
417 static hash[65];
418 SHA256_PassHash(inputtext, "EveryBodyHatesCris", hash, 65);
419
420 if(!strcmp(hash, Player[playerid][pPassword]))
421 {
422 Player[playerid][pLogged] = true;
423
424 sendServerMessage(playerid, "Logado com suceso!");
425 sendServerMessage(playerid, "Seu último login foi em %s.", timestampToDate(Player[playerid][pLastLogin]));
426
427 Player[playerid][pLastLogin] = gettime();
428
429 TogglePlayerSpectating(playerid, false);
430 }
431 else
432 {
433 Player[playerid][pMaxLoginAttempts]++;
434
435 if(Player[playerid][pMaxLoginAttempts] == MAX_LOGIN_ATTEMPTS)
436 {
437 sendWarningMessage(playerid, "Você foi kickado por excessos de tentativas.");
438 kickEx(playerid);
439 }
440 else showLoginMenu(playerid, MENU_LOGIN_INDEX, ""#COLORT_LIGHTRED"Senha inválida.");
441 }
442
443 return true;
444 }
445 }
446
447 return false;
448}
449
450//-------------------------------------------------------------------//
451//**************************** FUNÇÕES ******************************//
452//-------------------------------------------------------------------//
453
454// --> Player
455
456stock loadPlayer(playerid)
457{
458 GetPlayerName(playerid, Player[playerid][pName], 24);
459
460 new ORM:ormid = Player[playerid][pORM] = orm_create("players");
461 orm_addvar_int(ormid, Player[playerid][pAccountID], "ID");
462 orm_addvar_string(ormid, Player[playerid][pName], 24, "Name");
463 orm_addvar_string(ormid, Player[playerid][pPassword], 65, "Password");
464 orm_addvar_string(ormid, Player[playerid][pEmail], 64, "Email");
465 orm_addvar_int(ormid, Player[playerid][pLastLogin], "LastLogin");
466 orm_addvar_int(ormid, Player[playerid][pRegisterDate], "RegisterDate");
467}
468
469stock showLoginMenu(playerid, menuid, message[] = "")
470{
471 switch(menuid)
472 {
473 case MENU_LOGIN_INDEX:
474 {
475 format(String, sizeof(String), "%s\n\n", message);
476 format(Dialog, sizeof(Dialog), ""#COLORT_WHITE"Bem-vindo novamente "#COLORT_YELLOW"%s!\n\n%s"#COLORT_WHITE"Digite sua senha para logar:", Player[playerid][pName], (isnull(message) ? "" : String));
477 showPlayerDialogEx(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, ""#COLOR_TITLE_DIALOG"Login", Dialog, "Entrar", "Sair");
478 }
479 case MENU_LOGIN_REGISTER:
480 {
481 format(Dialog, sizeof(Dialog), ""#COLORT_WHITE"Bem-vindo "#COLORT_YELLOW"%s!\n\n"#COLORT_WHITE"Vejo que você não tem uma conta, vamos criar uma?", Player[playerid][pName]);
482 showPlayerDialogEx(playerid, DIALOG_REGISTER, DIALOG_STYLE_MSGBOX, ""#COLOR_TITLE_DIALOG"Registro", Dialog, "Sim", "Não");
483 }
484 case MENU_LOGIN_REGISTER_STAGE_1:
485 {
486 format(String, sizeof(String), "%s\n\n", message);
487 format(Dialog, sizeof(Dialog), "%s"COLORT_WHITE"Para começar, digite uma senha de 6 à 30 dÃgitos:", (isnull(message) ? "" : String));
488 showPlayerDialogEx(playerid, DIALOG_REGISTER+1, DIALOG_STYLE_PASSWORD, ""#COLOR_TITLE_DIALOG"Registro [1/3]", Dialog, "Prosseguir", "Sair");
489 }
490 case MENU_LOGIN_REGISTER_STAGE_2:
491 {
492 format(String, sizeof(String), "%s\n\n", message);
493 format(Dialog, sizeof(Dialog), "%s"COLORT_WHITE"Agora para confirmar, digite novamente a senha escolhida:", (isnull(message) ? "" : String));
494 showPlayerDialogEx(playerid, DIALOG_REGISTER+2, DIALOG_STYLE_PASSWORD, ""#COLOR_TITLE_DIALOG"Registro [2/3]", Dialog, "Prosseguir", "Voltar");
495 }
496 case MENU_LOGIN_REGISTER_STAGE_3:
497 {
498 format(String, sizeof(String), "%s\n\n", message);
499 format(Dialog, sizeof(Dialog), "%s"COLORT_WHITE"Para terminar, digite um e-mail válido:", (isnull(message) ? "" : String));
500 showPlayerDialogEx(playerid, DIALOG_REGISTER+3, DIALOG_STYLE_INPUT, ""#COLOR_TITLE_DIALOG"Registro [3/3]", Dialog, "Concluir", "Voltar");
501 }
502 }
503
504 return true;
505}
506
507stock clearPlayerVars(playerid)
508{
509 // Data
510 Player[playerid][pName][0] = EOS;
511 Player[playerid][pAccountID] = 0;
512 Player[playerid][pPassword][0] = EOS;
513 Player[playerid][pEmail][0] = EOS;
514 Player[playerid][pRegisterDate] = 0;
515 Player[playerid][pLastLogin] = 0;
516
517 // Non-data
518 Player[playerid][pKicked] = false;
519 Player[playerid][pDialogID] = 0;
520 Player[playerid][pLogged] = false;
521 Player[playerid][pMaxLoginAttempts] = 0;
522
523 // Registro
524 Player[playerid][registerPassword][0] = EOS;
525}
526
527
528// --> Utilidades
529
530stock sendClientMessageToAllEx(color, const str[], va_args<>)
531{
532 va_format(String, 144, str, va_start<2>);
533 return SendClientMessageToAll(color, String);
534}
535
536stock sendClientMessageEx(playerid, color, const str[], va_args<>)
537{
538 va_format(String, 144, str, va_start<3>);
539 return SendClientMessage(playerid, color, String);
540}
541
542stock showPlayerDialogEx(playerid, dialogid, style, caption[], info[], button1[], button2[])
543{
544 Player[playerid][pDialogID] = dialogid;
545 ShowPlayerDialog(playerid, dialogid, style, caption, info, button1, button2);
546 return dialogid;
547}
548
549stock kickEx(playerid)
550{
551 if(Player[playerid][pKicked])
552 return false;
553
554 Player[playerid][pKicked] = true;
555 SetTimerEx("KickTimer", 200, false, "d", playerid);
556 return true;
557}
558
559stock isValidPassword(password[])
560{
561 if(30 < strlen(password) || strlen(password) < 6)
562 return false;
563
564 return true;
565}
566
567stock SQL_verifyEmail(email[]) // Checar se o email já é usado, true = sim, false = não
568{
569 static Cache:result, exists;
570
571 mysql_format(MySQL_Connection, Query, sizeof(Query), "SELECT * FROM `players` WHERE `Email` = '%e'", email);
572 result = mysql_query(MySQL_Connection, Query, true);
573 exists = !!cache_num_rows();
574
575 cache_delete(result);
576 return exists;
577}
578
579stock isValidEmail(email[])
580{
581 static const ValidEmails[17][16] = {
582 {"@gmail.com"},
583 {"@hotmail.com.br"},
584 {"@hotmail.com"},
585 {"@globo.com"},
586 {"@globomail.com"},
587 {"@uol.com"},
588 {"@outlook.com"},
589 {"@live.com"},
590 {"@msn.com"},
591 {"@yahoo.com.br"},
592 {"@ymail.com"},
593 {"@rocketmail.com"},
594 {"@ig.com.br"},
595 {"@pop.com.br"},
596 {"@bol.com.br"},
597 {"@oi.com.br"},
598 {"@r7.com"}
599 };
600
601 for(new i; i < sizeof ValidEmails; i++)
602 if(strfind(email, ValidEmails[i], false) != -1)
603 return true;
604
605 return false;
606}
607
608stock timestampToDate(datetime, style = 0)
609{
610 static tm<timestamp>;
611 localtime(Time:datetime, timestamp);
612
613 switch(style)
614 {
615 case 0: strftime(String, 64, "%d/%m/%Y Ã s %X", timestamp);
616 case 1: strftime(String, 64, "%d/%m/%Y", timestamp);
617 }
618 return String;
619}