· 6 years ago · Oct 05, 2019, 01:58 PM
1#define DEBUG
2
3#define PLUGIN_AUTHOR "SZOKOZ/EXE KL"
4#define PLUGIN_VERSION "1.00"
5#define MODULE_NAME "ASteamBot_BuyRank"
6
7#include <sourcemod>
8#include <sdktools>
9#include <ASteambot>
10#include <multicolors>
11
12#pragma semicolon 1
13#pragma newdecls required
14#pragma dynamic 131072
15
16#define ITEM_ID "itemID"
17#define ITEM_NAME "itemName"
18#define ITEM_VALUE "itemValue"
19#define ITEM_DONATED "itemDonated"
20#define RANKP_ITEMOPTS "items"
21#define RANKP_TIME "rankDuration"
22#define RANKP_NAME "packageName"
23#define RANKP_ID "id"
24#define RANKP_FLAGS "adminLevels"
25#define MAX_OPTION_ITEMS 8
26
27#define STRING(%1) %1,sizeof(%1)
28#define ISEMPTY(%1) !%1[0]
29
30char CREATE_TABLE[] = "CREATE TABLE IF NOT EXISTS `purchasedranks`"...
31 "("...
32 "`purchaseid` INT NOT NULL AUTO_INCREMENT, "...
33 "`id64` VARCHAR(64) NOT NULL, "...
34 "`flags` INT NOT NULL, "...
35 "`expires` INT NOT NULL, "...
36 "PRIMARY KEY(`purchaseid`)"...
37 ")"...
38 "ENGINE = InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;";
39
40char INSERT_PLAYER[] = "INSERT IGNORE INTO `purchasedranks`"...
41" (`id64`, `flags`, `expires`) VALUES ('%s', %d, %d)";
42
43char GET_PLAYER[] = "SELECT * FROM `purchasedranks` WHERE `id64` = '%s' AND `expires` > %d";
44
45ArrayList g_hRankPackages;
46ArrayList g_hTF2Items[MAXPLAYERS];
47ArrayList g_hCSGOItems[MAXPLAYERS];
48ArrayList g_hDOTA2Items[MAXPLAYERS];
49StringMap g_hPendingPackageActivation[MAXPLAYERS];
50Database g_hDb;
51
52public Plugin myinfo =
53{
54 name = "ASteamBot_BuyRank",
55 author = PLUGIN_AUTHOR,
56 description = "Buy Admin Levels via SteamBot",
57 version = PLUGIN_VERSION,
58 url = "szokoz.eu"
59};
60
61public void OnAllPluginsLoaded()
62{
63 //Ensure that there is not late-load problems.
64 if (LibraryExists("ASteambot"))
65 ASteambot_RegisterModule(MODULE_NAME);
66 else
67 SetFailState("ASteambot_Core is not present/not running. Plugin can't continue !");
68}
69
70public void OnPluginStart()
71{
72 Database.Connect(OnDbConnect, MODULE_NAME);
73
74 RegConsoleCmd("sm_donaterank", CMD_GetRank,
75 "Create a trade offer and send it to the player for VIP or Admin.");
76 RegConsoleCmd("sm_rangok", CMD_GetRank,
77 "Create a trade offer and send it to the player for VIP or Admin.");
78
79 g_hRankPackages = new ArrayList();
80 LoadTranslations("ASteambot.buyrank.phrases");
81}
82
83public void OnPluginEnd()
84{
85 ASteambot_RemoveModule();
86}
87
88public void OnConfigsExecuted()
89{
90 LoadRankPackages();
91}
92
93public void OnClientPostAdminFilter(int client)
94{
95 SQL_GetPlayerActivePackages(client, PostAdminFilter_SQLResult);
96}
97
98void PostAdminFilter_SQLResult(int client, StringMap rPackage)
99{
100 if (!IsClientValid(client))
101 {
102 PrintToServer("PAF:Client %d invalid.", client);
103 return;
104 }
105
106
107 if (rPackage == null)
108 {
109 PrintToServer("PAF:Package invalid.");
110 return;
111 }
112
113
114 int expires;
115 rPackage.GetValue(RANKP_TIME, expires);
116 PrintToServer("Expires paf: %d", expires);
117
118 if (expires <= GetTime())
119 return;
120
121
122 int flags;
123 rPackage.GetValue(RANKP_FLAGS, flags);
124 AddUserFlags(client, view_as<AdminFlag>(flags));
125 PrintToServer("Client %d has been given adminflag %d", client, flags);
126}
127
128public Action CMD_GetRank(int client, int args)
129{
130 if (!IsClientValid)
131 return Plugin_Handled;
132
133 if (!ASteambot_IsConnected())
134 {
135 CPrintToChat(client, "%s {fullred}%t", MODULE_NAME, "ASteambot_NotConnected");
136 return Plugin_Handled;
137 }
138
139 CPrintToChat(client, "%s {green}%t", MODULE_NAME, "TradeOffer_WaitItems");
140
141 SQL_GetPlayerActivePackages(client, OnCmdRank_SQLResult);
142
143 return Plugin_Handled;
144}
145
146void OnCmdRank_SQLResult(int client, StringMap packageMap)
147{
148 if (!IsClientValid(client))
149 {
150 return;
151 }
152
153 if (packageMap != null)
154 {
155 CPrintToChat(client, "%s {green}%s", MODULE_NAME, "You already have an active package!");
156 return;
157 }
158
159 char clientSteamID[40];
160 GetClientAuthId(client, AuthId_Steam2, clientSteamID, sizeof(clientSteamID));
161 ASteambot_SendMesssage(AS_SCAN_INVENTORY, clientSteamID);
162}
163
164void LoadRankPackages()
165{
166 KeyValues kv = CreateKeyValues("Rank_Packages");
167 if (!FileToKeyValues(kv, "addons/sourcemod/configs/rankpackages.cfg"))
168 {
169 SetFailState("%s Config File Cannot Be Accessed!", MODULE_NAME);
170 return;
171 }
172
173 static char rPackage[256];
174 static char flagString[256];
175 static char items[1024];
176 int ranktime;
177
178 kv.GotoFirstSubKey();
179 int i;
180 char id[4];
181 do
182 {
183 kv.GetSectionName(STRING(rPackage));
184 kv.GetString(RANKP_FLAGS, STRING(flagString));
185 ranktime = kv.GetNum(RANKP_TIME);
186 kv.GetString(RANKP_ITEMOPTS, STRING(items));
187 ArrayList packageOptions = ParseItemString(items);
188 StringMap packageMap = new StringMap();
189 IntToString(i++, STRING(id));
190 packageMap.SetString(RANKP_ID, id);
191 packageMap.SetString(RANKP_NAME, rPackage);
192 packageMap.SetValue(RANKP_FLAGS, ParseFlagString(flagString));
193 packageMap.SetValue(RANKP_TIME, ranktime);
194 packageMap.SetValue(RANKP_ITEMOPTS, packageOptions);
195 g_hRankPackages.Push(packageMap);
196 }
197 while (KvGotoNextKey(kv));
198}
199
200int ParseFlagString(const char[] flags)
201{
202 char flagNames[32][16];
203 int flagCount = ExplodeString(flags, ",", flagNames, sizeof(flagNames), sizeof(flagNames[]));
204 int flag;
205 for (int i = 0; i < flagCount; i++)
206 {
207 AdminFlag admFlag;
208 bool success = FindFlagByName(flagNames[i], admFlag);
209 PrintToServer("Flag conversion %b, %s to %d", success, flagNames[i], admFlag);
210 flag |= view_as<int>(admFlag);
211 }
212
213 return flag;
214}
215
216ArrayList ParseItemString(const char[] items)
217{
218 ArrayList array = new ArrayList();
219 static char itemsoptions[4][256];
220 int options = ExplodeString(items, "|", itemsoptions, sizeof(itemsoptions), sizeof(itemsoptions[]));
221
222 for (int i = 0; i < options; i++)
223 {
224 static char itemsoption[MAX_OPTION_ITEMS][64];
225 int count =
226 ExplodeString(itemsoptions[i], ",", itemsoption, sizeof(itemsoption), sizeof(itemsoption[]));
227
228 ArrayList optionItems = new ArrayList(sizeof(itemsoption[]));
229 for (int j = 0; j < count; j++)
230 {
231 optionItems.PushString(itemsoption[j]);
232 }
233 array.Push(optionItems);
234 }
235
236 return array;
237}
238
239public void OnDbConnect(Database db, const char[] error, any data)
240{
241 if (db == null)
242 {
243 SetFailState("Unable to establish database connection to %s: %s", MODULE_NAME, error);
244 }
245 else
246 {
247 db.Query(OnTableCreate, CREATE_TABLE);
248 g_hDb = db;
249 }
250}
251
252void SQL_AddNewPurchase(int client, StringMap packageMap, Function callback)
253{
254 if (g_hDb == null)
255 return;
256
257 if (!IsClientValid(client))
258 return;
259
260 char id64[32];
261 GetClientAuthId(client, AuthId_SteamID64, STRING(id64));
262
263 int flags, time;
264 packageMap.GetValue(RANKP_FLAGS, flags);
265 bool timesuccess = packageMap.GetValue(RANKP_TIME, time);
266 PrintToServer("TimeRetrieved:%b, Duration:%d days", timesuccess, time);
267 static char query[512];
268 //expiry: current time in seconds plus days in seconds
269 int expiry = GetTime() + (time * 60 * 60 * 24);
270 packageMap.SetValue(RANKP_TIME, expiry);
271 Format(STRING(query), INSERT_PLAYER, id64, flags, expiry);
272 DataPack dp = new DataPack();
273 dp.WriteCell(client);
274 dp.WriteCell(packageMap);
275 dp.WriteFunction(callback);
276 g_hDb.Query(OnInsertQuery, query, dp);
277 PrintToServer("Threaded Query Sent for Adding Purchase: Client %d", client);
278}
279
280void SQL_GetPlayerActivePackages(int client, Function callback)
281{
282 if (g_hDb == null)
283 return;
284
285 if (!IsClientValid(client))
286 return;
287
288 char id64[32];
289 GetClientAuthId(client, AuthId_SteamID64, STRING(id64));
290
291 static char query[512];
292 Format(STRING(query), GET_PLAYER, id64, GetTime());
293
294 DataPack dp = new DataPack();
295 dp.WriteCell(client);
296 dp.WriteFunction(callback);
297 g_hDb.Query(OnGetQuery, query, dp);
298}
299
300public void OnTableCreate(Database db, DBResultSet results, const char[] error, any data)
301{
302
303}
304
305public void OnInsertQuery(Database db, DBResultSet results, const char[] error, any data)
306{
307 DataPack dp = view_as<DataPack>(data);
308 dp.Reset();
309
310 int client = dp.ReadCell();
311 StringMap packageMap = dp.ReadCell();
312 Function callback = dp.ReadFunction();
313
314 delete dp;
315
316 if (!ISEMPTY(error))
317 {
318 PrintToServer("Error: %s", error);
319 return;
320 }
321
322
323 Call_StartFunction(INVALID_HANDLE, callback);
324 Call_PushCell(client);
325 Call_PushCell(packageMap);
326 Call_Finish();
327}
328
329public void OnGetQuery(Database db, DBResultSet results, const char[] error, any data)
330{
331 DataPack dp = view_as<DataPack>(data);
332 dp.Reset();
333
334 int client = dp.ReadCell();
335 Function callback = dp.ReadFunction();
336
337 delete dp;
338
339 if (!results.HasResults)
340 return;
341
342 if (!results.RowCount)
343 {
344 Call_StartFunction(INVALID_HANDLE, callback);
345 Call_PushCell(client);
346 Call_PushCell(0);
347 Call_Finish();
348 return;
349 }
350
351 while (results.FetchRow())
352 {
353 StringMap activePackage = new StringMap();
354 char id64[32];
355 results.FetchString(1, STRING(id64));
356 activePackage.SetString("id64", id64);
357 activePackage.SetValue(RANKP_FLAGS, results.FetchInt(2));
358 activePackage.SetValue(RANKP_TIME, results.FetchInt(3));
359 Call_StartFunction(INVALID_HANDLE, callback);
360 Call_PushCell(client);
361 Call_PushCell(activePackage);
362 Call_Finish();
363 }
364}
365
366public int ASteambot_Message(AS_MessageType MessageType, char[] message, const int messageSize)
367{
368 PrintToServer("MessageType: %d, Message:%s", MessageType, message);
369 char[][] parts = new char[4][messageSize];
370 char steamID[40];
371
372 ExplodeString(message, "/", parts, 4, messageSize);
373 Format(steamID, sizeof(steamID), parts[0]);
374
375 int client = ASteambot_FindClientBySteam64(steamID);
376
377 if (MessageType == AS_NOT_FRIENDS && client != -1)
378 {
379 CPrintToChat(client, "%s {green}%t", MODULE_NAME, "Steam_NotFriends");
380 char clientSteamID[30];
381
382 GetClientAuthId(client, AuthId_Steam2, clientSteamID, sizeof(clientSteamID));
383 ASteambot_SendMesssage(AS_FRIEND_INVITE, clientSteamID);
384
385 CPrintToChat(client, "%s {green}%t", MODULE_NAME, "Steam_FriendInvitSend");
386 }
387 else if (MessageType == AS_SCAN_INVENTORY && client != -1)
388 {
389 CPrintToChat(client, "%s {green}%t", MODULE_NAME, "TradeOffer_InventoryScanned");
390 PrepareInventories(client, parts[1], parts[2], parts[3], messageSize);
391 }
392 else if (MessageType == AS_TRADEOFFER_DECLINED && client != -1)
393 {
394 CPrintToChat(client, "%s {red}%t", MODULE_NAME, "TradeOffer_Declined");
395 g_hPendingPackageActivation[client] = null;
396 char packageName[256];
397 g_hPendingPackageActivation[client].GetString(RANKP_NAME, STRING(packageName));
398 char id64[32];
399 GetClientAuthId(client, AuthId_SteamID64, STRING(id64));
400 LogToFile("BuyRanksTradeLog.log", "Trade Offer for Package %s Denied by %N(%s)",
401 packageName, client, id64);
402 }
403 else if (MessageType == AS_TRADEOFFER_SUCCESS && client != -1)
404 {
405 /*char[] offerID = new char[messageSize];
406 char[] value = new char[messageSize];
407
408 Format(offerID, messageSize, parts[1]);
409 Format(value, messageSize, parts[2]);*/
410
411 char pName[45];
412 GetClientName(client, pName, sizeof(pName));
413 CPrintToChat(client, "%s {green}%t", MODULE_NAME, "TradeOffer_Success", pName);
414 PrintToServer("adding purchase to db for client %d", client);
415 char packageName[256];
416 g_hPendingPackageActivation[client].GetString(RANKP_NAME, STRING(packageName));
417 char id64[32];
418 GetClientAuthId(client, AuthId_SteamID64, STRING(id64));
419 LogToFile("BuyRanksTradeLog.log", "Trade Offer for Package %s Accepted by %N(%s)",
420 packageName, client, id64);
421 SQL_AddNewPurchase(client, g_hPendingPackageActivation[client], PostAdminFilter_SQLResult);
422
423 //ModVIP(client, "add", 0, VIPDuration[client] );
424 }
425}
426
427public void PrepareInventories(int client, const char[] tf2, const char[] csgo, const char[] dota2, int charSize)
428{
429 int tf2_icount = CountCharInString(tf2, ',') + 1;
430 int csgo_icount = CountCharInString(csgo, ',') + 1;
431 int dota2_icount = CountCharInString(dota2, ',') + 1;
432
433 g_hTF2Items[client] = CreateArray(tf2_icount);
434 g_hCSGOItems[client] = CreateArray(csgo_icount);
435 g_hDOTA2Items[client] = CreateArray(dota2_icount);
436
437 CreateInventory(client, tf2, tf2_icount, g_hTF2Items[client]);
438 CreateInventory(client, csgo, csgo_icount, g_hCSGOItems[client]);
439 CreateInventory(client, dota2, dota2_icount, g_hDOTA2Items[client]);
440
441 DisplayVIPPackageSelection(client);
442}
443
444public void CreateInventory(int client, const char[] strinventory, int itemCount, Handle inventory)
445{
446 if (!StrEqual(strinventory, "EMPTY"))
447 {
448 char[][] items = new char[itemCount][60];
449
450 ExplodeString(strinventory, ",", items, itemCount, 60);
451
452 for (int i = 0; i < itemCount; i++)
453 {
454 char itemInfos[3][30];
455 ExplodeString(items[i], "=", itemInfos, sizeof itemInfos, sizeof itemInfos[]);
456
457 Handle TRIE_Item = CreateTrie();
458 SetTrieString(TRIE_Item, ITEM_ID, itemInfos[0]);
459 SetTrieString(TRIE_Item, ITEM_NAME, itemInfos[1]);
460 SetTrieValue(TRIE_Item, ITEM_VALUE, StringToFloat(itemInfos[2]));
461 SetTrieValue(TRIE_Item, ITEM_DONATED, 0);
462 PushArrayCell(inventory, TRIE_Item);
463 }
464 }
465 else if (StrEqual(strinventory, "ERROR"))
466 {
467 CPrintToChat(client, "%s {fullred}%t", MODULE_NAME, "TradeOffer_ItemsError", strinventory);
468 }
469}
470
471public void DisplayVIPPackageSelection(int client)
472{
473 ArrayList viableClientPackages = ViableClientPackages(client);
474
475 if(viableClientPackages.Length == 0)
476 {
477 CPrintToChat(client, "%s {fullred}%t", MODULE_NAME, "VIP_NoPackageAvailable");
478 return;
479 }
480
481 CPrintToChat(client, "%s {green}%t", MODULE_NAME, "TradeOffer_SelectTradeOffer");
482
483 Menu menu = new Menu(MenuHandle_MainMenu);
484 menu.SetTitle("Select a VIP package :");
485
486 for (int i = 0; i < viableClientPackages.Length; i++)
487 {
488 StringMap packageMap = viableClientPackages.Get(i);
489 char pname[64];
490 char num[4];
491 packageMap.GetString(RANKP_ID, STRING(num));
492 packageMap.GetString(RANKP_NAME, STRING(pname));
493 menu.AddItem(num, pname);
494 }
495
496 menu.ExitBackButton = true;
497 menu.Display(client, MENU_TIME_FOREVER);
498}
499
500public ArrayList ViableClientPackages(int client)
501{
502 ArrayList viableClientPackages = new ArrayList();
503
504 for (int i = 0; i < g_hRankPackages.Length; i++)
505 {
506 StringMap packageMap = g_hRankPackages.Get(i);
507 ArrayList options;
508 int itemFound = 0;
509 char mainItemName[64];
510 char packageName[256];
511
512 GetTrieValue(packageMap, RANKP_ITEMOPTS, options);
513 GetTrieString(packageMap, RANKP_NAME, packageName, sizeof(packageName));
514
515 for (int j = 0; j < options.Length; j++)
516 {
517 ArrayList option = options.Get(j);
518 for (int k = 0; k < option.Length; k++)
519 {
520 option.GetString(k, STRING(mainItemName));
521 char itemID[30];
522 bool result = GetItemID(client, mainItemName, itemID, sizeof(itemID));
523
524 if(result && StrEqual(itemID, "NOT_FOUND") == false)
525 itemFound++;
526 }
527
528 if (itemFound == option.Length)
529 {
530 viableClientPackages.Push(packageMap);
531 break;
532 }
533
534 }
535
536 ResetInventories(client);
537 }
538
539 return viableClientPackages;
540}
541
542public int MenuHandle_MainMenu(Handle menu, MenuAction action, int client, int itemIndex)
543{
544 if (action == MenuAction_Select)
545 {
546 char description[32];
547 GetMenuItem(menu, itemIndex, description, sizeof(description));
548
549 ShowPackageMenu(client, StringToInt(description));
550 }
551 else if (action == MenuAction_End)
552 {
553 CloseHandle(menu);
554 }
555}
556
557public void ShowPackageMenu(int client, int packageID)
558{
559 ArrayList options;
560 char iname[50];
561 char itemID[30];
562 char packageName[55];
563 StringMap packageMap = g_hRankPackages.Get(packageID);
564
565 packageMap.GetString(RANKP_NAME, packageName, sizeof(packageName));
566 packageMap.GetValue(RANKP_ITEMOPTS, options);
567
568 Menu menu = new Menu(MenuHandle_PackageSelect);
569 menu.SetTitle(packageName);
570
571 for (int i = 0; i < options.Length; i++)
572 {
573 ArrayList option = options.Get(i);
574 for (int j = 0; j < option.Length; j++)
575 {
576 option.GetString(j, iname, sizeof(iname));
577 PrintToServer("%s zzz", iname);
578 if(GetItemID(client, iname, itemID, sizeof(itemID)))
579 {
580 PrintToServer("%s added to mofo menu", iname);
581 menu.AddItem(itemID, iname, ITEMDRAW_DEFAULT);
582 }
583 else
584 {
585 PrintToServer("heh?%d", j);
586 menu.RemoveAllItems();
587 break;
588 }
589 }
590
591 if (menu.ItemCount > 0)
592 {
593 g_hPendingPackageActivation[client] = packageMap;
594 break;
595 }
596 }
597
598 menu.AddItem("OK", "OK!");
599 menu.ExitBackButton = true;
600 menu.Display(client, MENU_TIME_FOREVER);
601}
602
603public int MenuHandle_PackageSelect(Handle menu, MenuAction action, int client, int itemIndex)
604{
605 if (action == MenuAction_Select)
606 {
607 char itemID[32];
608 GetMenuItem(menu, itemIndex, itemID, sizeof(itemID));
609 if(StrEqual(itemID, "OK"))
610 {
611 Handle items = CreateArray(100);
612 char itemList[512];
613 char itemName[64];
614 for (int i = 0; i < itemIndex; i++)
615 {
616 GetMenuItem(menu, i, itemID, sizeof(itemID), _, STRING(itemName));
617 PushArrayString(items, itemID);
618 StrCat(STRING(itemList), itemName);
619 }
620
621 char packageName[256];
622 g_hPendingPackageActivation[client].GetString(RANKP_NAME, STRING(packageName));
623 char id64[32];
624 GetClientAuthId(client, AuthId_SteamID64, STRING(id64));
625 LogToFile("BuyRanksTradeLog.log", "%t to %N(%s) with the following items from package %s: %s",
626 "TradeOffer_Initiated", client, id64, packageName, itemList);
627 CPrintToChat(client, "%s {green}%t", MODULE_NAME, "TradeOffer_Created");
628 ASteambot_CreateTradeOffer(client, items);
629 }
630 else
631 {
632 CPrintToChat(client, "%s {fullred}%t", MODULE_NAME, "VIP_Denied");
633 }
634 }
635 else if (action == MenuAction_End)
636 {
637 CloseHandle(menu);
638 }
639}
640
641public bool GetItemID(int client, const char[] mainItemName, char[] itemID, int itemIDsize)
642{
643 if(GetItemIDFromInventory(g_hTF2Items[client], mainItemName, itemID, itemIDsize))
644 return true;
645 else if(GetItemIDFromInventory(g_hCSGOItems[client], mainItemName, itemID, itemIDsize))
646 return true;
647 else if(GetItemIDFromInventory(g_hDOTA2Items[client], mainItemName, itemID, itemIDsize))
648 return true;
649
650 return false;
651}
652
653public bool GetItemIDFromInventory(Handle inventory, const char[] mainItemName, char[] itemID, int itemIDsize)
654{
655 char itemName[100];
656 for (int i = 0; i < GetArraySize(inventory); i++)
657 {
658 Handle t = GetArrayCell(inventory, i);
659 GetTrieString(t, ITEM_NAME, itemName, sizeof(itemName));
660
661 if (StrEqual(itemName, mainItemName))
662 {
663 int donated = -1;
664 GetTrieValue(t, ITEM_DONATED, donated);
665 if(donated == 0)
666 {
667 SetTrieValue(t, ITEM_DONATED, 1);
668 GetTrieString(t, ITEM_ID, itemID, itemIDsize);
669 return true;
670 }
671 }
672 }
673
674 return false;
675}
676
677public int CountCharInString(const char[] str, int c)
678{
679 int i = 0, count = 0;
680
681 while (str[i] != '\0')
682 {
683 if (str[i++] == c)
684 count++;
685 }
686
687 return count;
688}
689
690public void ResetInventory(Handle inventory)
691{
692 for (int i = 0; i < GetArraySize(inventory); i++)
693 {
694 Handle t = GetArrayCell(inventory, i);
695 SetTrieValue(t, ITEM_DONATED, 0);
696 }
697}
698
699public void ResetInventories(int client)
700{
701 ResetInventory(g_hTF2Items[client]);
702 ResetInventory(g_hCSGOItems[client]);
703 ResetInventory(g_hDOTA2Items[client]);
704}
705
706bool IsClientValid(int client)
707{
708 if (0 < client <= MaxClients)
709 {
710 return IsClientInGame(client);
711 }
712
713 return false;
714}