· 8 years ago · Dec 20, 2017, 02:46 PM
1#include <a_samp>
2#include <a_mysql>
3#include <streamer>
4#include <sscanf2>
5#include <zcmd>
6
7
8native WP_Hash(buffer[], len, const str[]);
9
10#define WHITE 0xFFFFFFAA
11#define GREY 0xAFAFAFAA
12#define RED 0xFF0000AA
13#define YELLOW 0xFFFF00AA
14#define LIGHTBLUE 0x33CCFFAA
15
16#define CHAT_WHITE "{FFFFFF}"
17#define CHAT_GREY "{AFAFAF}"
18#define CHAT_RED "{FF0000}"
19#define CHAT_YELLOW "{FFFF00}"
20#define CHAT_LIGHTBLUE "{33CCFF}"
21
22forward OnPlayerDataLoaded(playerid, race_check);
23forward OnPlayerRegister(playerid);
24
25
26//MySQL configuration
27#define SQL_HOST "127.0.0.1"
28#define SQL_DB "database"
29#define SQL_USER "root"
30#define SQL_PASS ""
31
32//MySQL connection handle
33new g_SQL = -1;
34
35//player data
36enum E_PLAYERS
37{
38 ID,
39 Name[MAX_PLAYER_NAME],
40 Password[129],
41 Skin_Player,
42 Cash,
43
44 bool:IsLoggedIn,
45 bool:IsRegistered,
46 LoginAttempts,
47 LoginTimer
48};
49new Player[MAX_PLAYERS][E_PLAYERS];
50
51new g_MysqlRaceCheck[MAX_PLAYERS];
52
53//dialog data
54enum
55{
56 DIALOG_INVALID,
57 DIALOG_UNUSED,
58
59 DIALOG_LOGIN,
60 DIALOG_REGISTER,
61};
62
63
64/*
65 * SA-MP callbacks
66 */
67
68public OnGameModeInit()
69{
70 mysql_log(LOG_ERROR | LOG_WARNING, LOG_TYPE_HTML); //logs errors and warnings into a nice .html log file
71 g_SQL = mysql_connect(SQL_HOST, SQL_USER, SQL_DB, SQL_PASS);
72
73 //SetupPlayerTable();
74 return 1;
75}
76
77public OnGameModeExit()
78{
79 //save all player data before closing connection
80 for(new p=0; p < MAX_PLAYERS; ++p)
81 if(IsPlayerConnected(p))
82 UpdatePlayerData(p);
83
84 mysql_close();
85 return 1;
86}
87
88public OnPlayerConnect(playerid)
89{
90 g_MysqlRaceCheck[playerid]++;
91 //reset player data
92 for(new E_PLAYERS:e; e < E_PLAYERS; ++e)
93 Player[playerid][e] = 0;
94
95 new query[128];
96 GetPlayerName(playerid, Player[playerid][Name], MAX_PLAYER_NAME);
97
98 //send a query to recieve all the stored player data from the table
99 mysql_format(g_SQL, query, sizeof(query), "SELECT * FROM `players` WHERE `username` = '%e' LIMIT 1", Player[playerid][Name]);
100 mysql_tquery(g_SQL, query, "OnPlayerDataLoaded", "dd", playerid, g_MysqlRaceCheck[playerid]);
101 return 1;
102}
103
104public OnPlayerDataLoaded(playerid, race_check)
105{
106 /* race condition check:
107 player A connects -> SELECT query is fired -> this query takes very long
108 while the query is still processing, player A with playerid 2 disconnects
109 player B joins now with playerid 2 -> our laggy SELECT query is finally finished, but for the wrong player
110
111 what do we do against it?
112 we create a connection count for each playerid and increase it everytime the playerid connects or disconnects
113 we also pass the current value of the connection count to our OnPlayerDataLoaded callback
114 then we check if current connection count is the same as connection count we passed to the callback
115 if yes, everything is okay, if not, we just kick the player
116 */
117 if(race_check != g_MysqlRaceCheck[playerid])
118 return Kick(playerid);
119
120
121 new string[128];
122 if(cache_num_rows() > 0)
123 {
124 AssignPlayerData(playerid);
125
126 format(string, sizeof(string), CHAT_WHITE "This account (" CHAT_YELLOW "%s" CHAT_WHITE ") is registered. Please login by entering your password in the field below:", Player[playerid][Name]);
127 ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login", string, "Login", "Abort");
128 Player[playerid][IsRegistered] = true;
129 }
130 else
131 {
132 format(string, sizeof(string), CHAT_WHITE "Welcome " CHAT_YELLOW "%s" CHAT_WHITE ", you can register by entering your password in the field below:", Player[playerid][Name]);
133 ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration", string, "Register", "Abort");
134 Player[playerid][IsRegistered] = false;
135 }
136 return 1;
137}
138
139public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
140{
141 if(dialogid == DIALOG_INVALID || dialogid == DIALOG_UNUSED)
142 return 1;
143
144 switch(dialogid)
145 {
146 case DIALOG_LOGIN:
147 {
148 if(!response)
149 return Kick(playerid);
150
151 if(strlen(inputtext) <= 5)
152 return ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login",
153 CHAT_RED "Your password must be longer than 5 characters!\n" CHAT_WHITE "Please enter your password in the field below:",
154 "Login", "Abort");
155
156 new hashed_pass[129];
157 WP_Hash(hashed_pass, sizeof(hashed_pass), inputtext);
158
159 if(strcmp(hashed_pass, Player[playerid][Password]) == 0)
160 {
161 //correct password, spawn the player
162 ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Login", "You have been successfully logged in.", "Okay", "");
163 Player[playerid][IsLoggedIn] = true;
164
165 SetSpawnInfo(playerid, 0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0);
166 SpawnPlayer(playerid);
167 }
168 else
169 {
170 Player[playerid][LoginAttempts]++;
171 if(Player[playerid][LoginAttempts] >= 3)
172 {
173 ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Login", CHAT_RED "You have mistyped your password too often (3 times).", "Okay", "");
174 DelayedKick(playerid);
175 }
176 else
177 ShowPlayerDialog(playerid, DIALOG_LOGIN, DIALOG_STYLE_PASSWORD, "Login", CHAT_RED "Wrong password!\n" CHAT_WHITE "Please enter your password in the field below:", "Login", "Abort");
178 }
179 }
180
181 case DIALOG_REGISTER:
182 {
183 if(!response)
184 return Kick(playerid);
185
186 if(strlen(inputtext) <= 5)
187 return ShowPlayerDialog(playerid, DIALOG_REGISTER, DIALOG_STYLE_PASSWORD, "Registration",
188 CHAT_RED "Your password must be longer than 5 characters!\n" CHAT_WHITE "Please enter your password in the field below:",
189 "Register", "Abort");
190
191 new query[256];
192 WP_Hash(Player[playerid][Password], 129, inputtext);
193 mysql_format(g_SQL, query, sizeof(query), "INSERT INTO `players` (`username`, `password`) VALUES ('%e', '%s')", Player[playerid][Name], Player[playerid][Password]);
194 mysql_tquery(g_SQL, query, "OnPlayerRegister", "d", playerid);
195 }
196
197 default:
198 return 0;
199 }
200 return 1;
201}
202
203public OnPlayerRegister(playerid)
204{
205 Player[playerid][ID] = cache_insert_id();
206
207 ShowPlayerDialog(playerid, DIALOG_UNUSED, DIALOG_STYLE_MSGBOX, "Registration", "Account successfully registered, you have been automatically logged in.", "Okay", "");
208 Player[playerid][IsLoggedIn] = true;
209 Player[playerid][IsRegistered] = true;
210
211 SetSpawnInfo(playerid, 0, 0, 0.0, 0.0, 0.0, 0.0, 0, 0, 0, 0, 0, 0);
212 SpawnPlayer(playerid);
213 return 1;
214}
215
216public OnPlayerSpawn(playerid)
217{
218 ResetPlayerMoney(playerid);
219
220 SetPlayerSkin(playerid, Player[playerid][Skin_Player]);
221 return 1;
222}
223
224public OnPlayerDisconnect(playerid,reason)
225{
226 g_MysqlRaceCheck[playerid]++;
227 UpdatePlayerData(playerid);
228 return 1;
229}
230
231
232/*
233 * functions
234 */
235
236AssignPlayerData(playerid)
237{
238 Player[playerid][ID] = cache_get_field_content_int(0, "id");
239 cache_get_field_content(0, "password", Player[playerid][Password], g_SQL, 129);
240 Player[playerid][Skin_Player] = cache_get_field_content_int(0, "skin_player");
241 Player[playerid][Cash] = cache_get_field_content_int(0, "cash");
242 return 1;
243}
244
245
246
247/*
248UpdatePlayerData(playerid)
249{
250 if(Player[playerid][IsLoggedIn] == false)
251 return 0;
252
253 new query[800];
254 mysql_format(g_SQL, query, sizeof(query), "UPDATE `players` SET `skin_player` = '%d', `cash` = '%d' WHERE `id` = '%d' LIMIT 1",
255 Player[playerid][Skin_Player], Player[playerid][Cash], Player[playerid][ID]);
256
257 mysql_tquery(g_SQL, query);
258 return 1;
259}
260*/
261
262
263
264UpdatePlayerData(playerid)
265{
266 if(Player[playerid][IsLoggedIn] == true)
267 {
268 new query[600];
269 mysql_format(g_SQL, query, sizeof(query), "UPDATE `players` SET `skin_player` = '%d', `cash` = '%d WHERE `id` = '%d' LIMIT 1",
270
271 Player[playerid][Skin_Player],
272 Player[playerid][Cash],
273 Player[playerid][ID]);
274
275 mysql_tquery(g_SQL, query);
276 return 1;
277 }
278}
279
280
281
282
283/*
284SetupPlayerTable()
285{
286 mysql_query(g_SQL, "CREATE TABLE IF NOT EXISTS `players` (`id` int(11) NOT NULL auto_increment PRIMARY KEY,`username` varchar(30) NOT NULL,`password` varchar(130) NOT NULL,`money` int(10) NOT NULL default '0')", false);
287 return 1;
288}
289*/
290
291
292DelayedKick(playerid, time=500)
293{
294 SetTimerEx("_KickPlayerDelayed", time, false, "d", playerid);
295 return 1;
296}
297
298forward _KickPlayerDelayed(playerid);
299public _KickPlayerDelayed(playerid)
300{
301 Kick(playerid);
302 return 1;
303}
304
305CMD:setskin(playerid, params[])
306{
307
308 new playerb, value;
309
310 if(sscanf(params, "ui", playerb, value))
311 return SendClientMessage(playerid, -1, "{88AA88}/setskin {FFFFFF}[playerid/nom] [id skin]");
312
313 GameTextForPlayer(playerid, "nouveau skin", 1000, 1);
314
315 SetPlayerSkin(playerb, value);
316
317 UpdatePlayerData(playerid);
318
319 return 1;
320}
321
322
323CMD:givemoney(playerid, params[])
324{
325
326 new playerb, value;
327
328 if(sscanf(params, "ui", playerb, value))
329 return SendClientMessage(playerid, -1, "{88AA88}/givemoney {FFFFFF}[playerid/nom] [somme]");
330
331 GameTextForPlayer(playerid, "nouveau skin", 1000, 1);
332
333 GivePlayerMoney(playerb, value);
334
335 UpdatePlayerData(playerid);
336
337 return 1;
338}
339
340
341
342main() {}