forked from JaredScar/Badger-Anticheat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.lua
775 lines (745 loc) · 32.2 KB
/
server.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
-- Server Config:
webhookURL = ''
-- CODE [DO NOT TOUCH]:
BlacklistedEvents = Config.BlacklistedEvents;
local counter = {}
function BanPlayer(src, reason)
local config = LoadResourceFile(GetCurrentResourceName(), "ac-bans.json")
local cfg = json.decode(config)
local ids = ExtractIdentifiers(src);
local playerIP = ids.ip;
local playerSteam = ids.steam;
local playerLicense = ids.license;
local playerXbl = ids.xbl;
local playerLive = ids.live;
local playerDisc = ids.discord;
local banData = {};
banData['ID'] = tonumber(getNewBanID());
banData['ip'] = "NONE SUPPLIED";
banData['reason'] = reason;
banData['license'] = "NONE SUPPLIED";
banData['steam'] = "NONE SUPPLIED";
banData['xbl'] = "NONE SUPPLIED";
banData['live'] = "NONE SUPPLIED";
banData['discord'] = "NONE SUPPLIED";
if ip ~= nil and ip ~= "nil" and ip ~= "" then
banData['ip'] = tostring(ip);
end
if playerLicense ~= nil and playerLicense ~= "nil" and playerLicense ~= "" then
banData['license'] = tostring(playerLicense);
end
if playerSteam ~= nil and playerSteam ~= "nil" and playerSteam ~= "" then
banData['steam'] = tostring(playerSteam);
end
if playerXbl ~= nil and playerXbl ~= "nil" and playerXbl ~= "" then
banData['xbl'] = tostring(playerXbl);
end
if playerLive ~= nil and playerLive ~= "nil" and playerLive ~= "" then
banData['live'] = tostring(playerXbl);
end
if playerDisc ~= nil and playerDisc ~= "nil" and playerDisc ~= "" then
banData['discord'] = tostring(playerDisc);
end
cfg[tostring(GetPlayerName(src))] = banData;
SaveResourceFile(GetCurrentResourceName(), "ac-bans.json", json.encode(cfg, { indent = true }), -1)
end
function getNewBanID()
local config = LoadResourceFile(GetCurrentResourceName(), "ac-bans.json")
local cfg = json.decode(config)
local banID = 0;
for k, v in pairs(cfg) do
banID = banID + 1;
end
return (banID + 1);
end
RegisterNetEvent('Anticheat:CheckStaff')
AddEventHandler('Anticheat:CheckStaff', function()
local src = source;
if IsPlayerAceAllowed(src, 'Anticheat.Bypass') then
TriggerClientEvent('Anticheat:CheckStaffReturn', src, true);
else
TriggerClientEvent('Anticheat:CheckStaffReturn', src, false);
end
end)
RegisterNetEvent('Anticheat:ScreenshotSubmit')
AddEventHandler('Anticheat:ScreenshotSubmit', function()
local src = source;
if not IsPlayerAceAllowed(src, "Anticheat.Bypass") then
local screenshotOptions = {
encoding = 'png',
quality = 1
}
local ids = ExtractIdentifiers(src);
local playerIP = ids.ip;
local playerSteam = ids.steam;
local playerLicense = ids.license;
local playerXbl = ids.xbl;
local playerLive = ids.live;
local playerDisc = ids.discord;
exports['discord-screenshot']:requestCustomClientScreenshotUploadToDiscord(src, webhookURL, screenshotOptions, {
username = '[BADGER-ANTICHEAT] https://github.com/JaredScar/Badger-Anticheat',
avatar_url = 'https://forum.cfx.re/user_avatar/forum.cfx.re/officialbadger/120/258293_2.png',
content = '',
embeds = {
{
color = 16711680,
author = {
name = '[BADGER-ANTICHEAT]',
icon_url = 'https://forum.cfx.re/user_avatar/forum.cfx.re/officialbadger/120/258293_2.png'
},
title = '[Possible Modder] Player has triggered blacklisted keys...',
description = '**__Player Identifiers:__** \n\n'
.. '**Server ID:** `' .. src .. '`\n\n'
.. '**Username:** `' .. GetPlayerName(src) .. '`\n\n'
.. '**IP:** `' .. playerIP .. '`\n\n'
.. '**Steam:** `' .. playerSteam .. '`\n\n'
.. '**License:** `' .. playerLicense .. '`\n\n'
.. '**Xbl:** `' .. playerXbl .. '`\n\n'
.. '**Live:** `' .. playerLive .. '`\n\n'
.. '**Discord:** `' .. playerDisc .. '`\n\n',
footer = {
text = "[" .. src .. "]" .. GetPlayerName(src),
}
}
}
});
end
end)
RegisterCommand('ac-unban', function(source, args, rawCommand)
local src = source;
if (src <= 0) then
-- Console unban
if #args == 0 then
-- Not enough arguments
print('^3[^6Badger-Anticheat^3] ^1Not enough arguments...');
return;
end
local banID = args[1];
if tonumber(banID) ~= nil then
local playerName = UnbanPlayer(banID);
if playerName then
print('^3[^6Badger-Anticheat^3] ^0Player ^1' .. playerName
.. ' ^0has been unbanned from the server by ^2CONSOLE');
TriggerClientEvent('chatMessage', -1, '^3[^6Badger-Anticheat^3] ^0Player ^1' .. playerName
.. ' ^0has been unbanned from the server by ^2CONSOLE');
else
-- Not a valid ban ID
print('^3[^6Badger-Anticheat^3] ^1That is not a valid ban ID. No one has been unbanned!');
end
end
return;
end
if IsPlayerAceAllowed(src, "Badger-Anticheat.ACban") then
if #args == 0 then
-- Not enough arguments
TriggerClientEvent('chatMessage', src, '^3[^6Badger-Anticheat^3] ^1Not enough arguments...');
return;
end
local banID = args[1];
if tonumber(banID) ~= nil then
-- Is a valid ban ID
local playerName = UnbanPlayer(banID);
if playerName then
TriggerClientEvent('chatMessage', -1, '^3[^6Badger-Anticheat^3] ^0Player ^1' .. playerName
.. ' ^0has been unbanned from the server by ^2' .. GetPlayerName(src));
else
-- Not a valid ban ID
TriggerClientEvent('chatMessage', src, '^3[^6Badger-Anticheat^3] ^1That is not a valid ban ID. No one has been unbanned!');
end
else
-- Not a valid number
TriggerClientEvent('chatMessage', src, '^3[^6Badger-Anticheat^3] ^1That is not a valid number...');
end
end
end)
function UnbanPlayer(banID)
local config = LoadResourceFile(GetCurrentResourceName(), "ac-bans.json")
local cfg = json.decode(config)
for k, v in pairs(cfg) do
local id = tonumber(v['ID']);
if id == tonumber(banID) then
local name = k;
cfg[k] = nil;
SaveResourceFile(GetCurrentResourceName(), "ac-bans.json", json.encode(cfg, { indent = true }), -1)
return name;
end
end
return false;
end
--[[
@param src - The player server ID supplied
function isBanned(src)
FOUND: returns { banID: tonumber(banID), reason: tostring(reason) }
NOT FOUND: returns false
]]--
function isBanned(src)
local config = LoadResourceFile(GetCurrentResourceName(), "ac-bans.json")
local cfg = json.decode(config)
local ids = ExtractIdentifiers(src);
local playerIP = ids.ip;
local playerSteam = ids.steam;
local playerLicense = ids.license;
local playerXbl = ids.xbl;
local playerLive = ids.live;
local playerDisc = ids.discord;
for k, v in pairs(cfg) do
local reason = v['reason']
local id = v['ID']
local ip = v['ip']
local license = v['license']
local steam = v['steam']
local xbl = v['xbl']
local live = v['live']
local discord = v['discord']
if tostring(ip) == tostring(playerIP) then return { ['banID'] = id, ['reason'] = reason } end;
if tostring(license) == tostring(playerLicense) then return { ['banID'] = id, ['reason'] = reason } end;
if tostring(steam) == tostring(playerSteam) then return { ['banID'] = id, ['reason'] = reason } end;
if tostring(xbl) == tostring(playerXbl) then return { ['banID'] = id, ['reason'] = reason } end;
if tostring(live) == tostring(playerLive) then return { ['banID'] = id, ['reason'] = reason } end;
if tostring(discord) == tostring(playerDisc) then return { ['banID'] = id, ['reason'] = reason } end;
end
return false;
end
function GetBans()
local config = LoadResourceFile(GetCurrentResourceName(), "ac-bans.json")
local cfg = json.decode(config)
return cfg;
end
local playTracker = {}
Citizen.CreateThread(function()
while true do
Wait(0);
for _, id in pairs(GetPlayers()) do
local ip = ExtractIdentifiers(id).ip;
if playTracker[ip] ~= nil then
playTracker[ip] = playTracker[ip] + 1;
else
playTracker[ip] = 1;
end
end
Wait((1000 * 60)); -- Every minute
end
end)
function GetLatest(count)
local latest = {};
local lowest = 9999999;
local lowestUser = nil;
local ourCount = 0;
local ourArr = {};
for ip, playtime in pairs(playTracker) do
ourArr[ip] = playtime;
end
local retArr = {};
while ourCount < count do
lowest = nil;
local lowestIP = nil;
lowestUser = nil;
for ip, playtime in pairs(ourArr) do
for _, pid in pairs(GetPlayers()) do
local playerIP = ExtractIdentifiers(pid).ip;
if tostring(ip) == tostring(playerIP) then
if lowest == nil or lowest >= playtime then
lowestIP = ip;
lowest = playtime
lowestUser = pid;
end
end
end
end
if lowest ~= nil then
ourArr[lowestIP] = nil;
table.insert(retArr, {lowestUser, lowest});
end
ourCount = ourCount + 1;
end
return retArr;
end
RegisterCommand("entitywipe", function(source, args, raw)
local playerID = args[1]
if (IsPlayerAceAllowed(source, "AntiCheat.Moderation")) then
if (playerID ~= nil and tonumber(playerID) ~= nil) then
EntityWipe(source, tonumber(playerID))
end
end
end, false)
function EntityWipe(source, target)
TriggerClientEvent("anticheat:EntityWipe", -1, tonumber(target))
end
RegisterCommand("latest", function(source, args, rawCommand)
local latestUsers = GetLatest(6);
for i = 1, #latestUsers do
local user = latestUsers[i][1];
local playTime = latestUsers[i][2];
TriggerClientEvent('chatMessage', source, "^5[^1Badger-Anticheat^5] ^3Player ^3[^4".. tostring(user) .. "^3] ^4" ..
GetPlayerName(user) .. " ^3has played ^4" .. playTime ..
" ^3minutes so far...");
end
end)
--[[
Citizen.CreateThread(function()
while true do
Wait(40000); -- Every 40 seconds
for _, id in pairs(GetPlayers()) do
if isBanned(id) then
-- Banned, kick em
DropPlayer(id, "[Badger-Anticheat] " .. bans[tostring(playerIP)]);
end
end
end
end)
]]--
function OnPlayerConnecting(name, setKickReason, deferrals)
deferrals.defer();
print("[Badger-Anticheat] Checking their Ban Data");
local src = source;
local banned = false;
local ban = isBanned(src);
Citizen.Wait(100);
if ban then
-- They are banned
local reason = ban['reason'];
local printMessage = nil;
if string.find(reason, "[Badger-Anticheat]") then
printMessage = ""
else
printMessage = "[Badger-Anticheat] "
end
print("[BANNED PLAYER] Player " .. GetPlayerName(src) .. " tried to join, but was banned for: " .. reason);
deferrals.done(printMessage .. "(BAN ID: " .. ban['banID'] .. ") " .. reason);
banned = true;
CancelEvent();
return;
end
if not banned then
deferrals.done();
end
end
RegisterCommand("acban", function(source, args, raw)
-- /acban <id> <reason>
local src = source;
if IsPlayerAceAllowed(src, "Badger-Anticheat.ACban") then
-- They can ban players this way
if #args < 2 then
-- Not valid enough num of arguments
TriggerClientEvent('chatMessage', source, "^5[^1Badger-Anticheat^5] ^1ERROR: You have supplied invalid amount of arguments... " ..
"^2Proper Usage: /acban <id> <reason>");
return;
end
local id = args[1]
if ExtractIdentifiers(args[1]) ~= nil then
-- Valid player supplied
local ids = ExtractIdentifiers(id);
local steam = ids.steam;
local gameLicense = ids.license;
local discord = ids.discord;
local reason = table.concat(args, ' '):gsub(args[1] .. " ", "");
BanPlayer(args[1], reason);
sendToDisc("[BANNED] Banned by " .. GetPlayerName(src) .. ": _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Reason: **' .. reason .. '**\n' ..
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
DropPlayer(id, "[Badger-Anticheat]: Banned by player " .. GetPlayerName(src) .. " for reason: " .. reason);
else
-- Not a valid player supplied
TriggerClientEvent('chatMessage', source, "^5[^1Badger-Anticheat^5] ^1ERROR: There is no valid player with that ID online... " ..
"^2Proper Usage: /acban <id> <reason>");
end
end
end)
AddEventHandler("playerConnecting", OnPlayerConnecting)
RegisterServerEvent("Anticheat:NoClip")
AddEventHandler("Anticheat:NoClip", function(distance)
if Config.Components.AntiNoclip and not IsPlayerAceAllowed(source, "Anticheat.Bypass") then
local name = GetPlayerName(source)
local id = source;
local ids = ExtractIdentifiers(id);
local steam = ids.steam:gsub("steam:", "");
local steamDec = tostring(tonumber(steam,16));
if counter[ids.steam] ~= nil then
counter[ids.steam] = counter[ids.steam] + 1;
else
counter[ids.steam] = 1;
end
if counter[ids.steam] ~= nil and counter[ids.steam] >= Config.NoClipTriggerCount then
steam = "https://steamcommunity.com/profiles/" .. steamDec;
local gameLicense = ids.license;
local discord = ids.discord;
if (Config.BanComponents.AntiNoClip) then
BanPlayer(id, Config.Messages.NoClipTriggered)
sendToDisc("[BANNED] CONFIRMED HACKER (NoClipping around): _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
else
sendToDisc("CONFIRMED HACKER [NoClipping around]: _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
end
DropPlayer(id, "[Badger-Anticheat]: " .. Config.Messages.NoClipTriggered)
end
Wait(6000);
counter[ids.steam] = counter[ids.steam] - 1;
end
end)
-- Props to Lance Good for this code (most of it at least): [https://github.com/DevLanceGood]
function IsLegal(entity)
local model = GetEntityModel(entity)
if (model ~= nil) then
if (GetEntityType(entity) == 1 and GetEntityPopulationType(entity) == 7) then
local WhitelistPedModels = Config.WhitelistPedModels;
local isWhitelisted = false;
for i = 1, #WhitelistPedModels do
if GetHashKey(WhitelistPedModels[i]) == model then
isWhitelisted = true;
end
end
if not isWhitelisted then
--return "Spawning Peds";
return false;
else
return false;
end
end
for i=1, #Config.BlacklistedModels do
local hashkey = tonumber(Config.BlacklistedModels[i]) ~= nil and tonumber(Config.BlacklistedModels[i]) or GetHashKey(Config.BlacklistedModels[i])
if (hashkey == model) then
if (GetEntityPopulationType(entity) ~= 7) then
return Config.BlacklistedModels[i];
else
return false
end
end
end
end
return false
end
-- End props
RegisterNetEvent("Anticheat:ModderESX")
AddEventHandler("Anticheat:ModderESX", function(type, reason)
local id = source;
local ids = ExtractIdentifiers(id);
local steam = ids.steam:gsub("steam:", "");
local steamDec = tostring(tonumber(steam,16));
steam = "https://steamcommunity.com/profiles/" .. steamDec;
local gameLicense = ids.license;
local discord = ids.discord;
if Config.BanComponents.AntiESX then
BanPlayer(id, reason);
sendToDisc("[BANNED] " .. type .. ": _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
else
sendToDisc("" .. type .. ": _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
end
DropPlayer(id, reason)
end)
RegisterNetEvent("Anticheat:Modder")
AddEventHandler("Anticheat:Modder", function(type, reason)
local id = source;
local ids = ExtractIdentifiers(id);
local steam = ids.steam:gsub("steam:", "");
local steamDec = tostring(tonumber(steam,16));
steam = "https://steamcommunity.com/profiles/" .. steamDec;
local gameLicense = ids.license;
local discord = ids.discord;
if Config.BanComponents.AntiCommands then
BanPlayer(id, reason);
sendToDisc("[BANNED] " .. type .. ": _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
else
sendToDisc("" .. type .. ": _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
end
DropPlayer(id, reason)
end)
RegisterNetEvent("Anticheat:ModderNoKick")
AddEventHandler("Anticheat:ModderNoKick", function(type, reason, bool)
local id = source;
local ids = ExtractIdentifiers(id);
local steam = ids.steam:gsub("steam:", "");
local steamDec = tostring(tonumber(steam,16));
steam = "https://steamcommunity.com/profiles/" .. steamDec;
local gameLicense = ids.license;
local discord = ids.discord;
sendToDisc("" .. type .. ": _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
if bool then
DropPlayer(id, reason)
end
end)
RegisterNetEvent("Anticheat:SpectateTrigger")
AddEventHandler("Anticheat:SpectateTrigger", function(reason)
if Config.Components.AntiSpectate and not IsPlayerAceAllowed(source, "Anticheat.Bypass") then
local id = source;
local ids = ExtractIdentifiers(id);
local steam = ids.steam:gsub("steam:", "");
local steamDec = tostring(tonumber(steam,16));
steam = "https://steamcommunity.com/profiles/" .. steamDec;
local gameLicense = ids.license;
local discord = ids.discord;
if Config.BanComponents.AntiSpectate then
BanPlayer(id, reason);
sendToDisc("[BANNED] CONFIRMED HACKER (Tried spectating a player): _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
else
sendToDisc("CONFIRMED HACKER [Tried spectating a player]: _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
end
DropPlayer(id, reason)
end
end)
AddEventHandler('chatMessage', function(source, name, msg)
local id = source;
local ids = ExtractIdentifiers(id);
local ip = ids.ip;
local steam = ids.steam:gsub("steam:", "");
local steamDec = tostring(tonumber(steam,16));
steam = "https://steamcommunity.com/profiles/" .. steamDec;
local gameLicense = ids.license;
local discord = ids.discord;
local realName = GetPlayerName(source);
if (name ~= realName) then
if Config.BanComponents.AntiFakeMessage then
BanPlayer(id, "[Badger-Anticheat]: " .. Config.Messages.ChatMessageTriggered)
sendToDisc("[BANNED] CONFIRMED HACKER (Fake Chat Message): _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n'
.. 'Tried to say: `' .. msg .. '` with name `' .. name .. '`');
else
sendToDisc("CONFIRMED HACKER [Fake Chat Message]: _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n'
.. 'Tried to say: `' .. msg .. '` with name `' .. name .. '`');
end
DropPlayer(id, "[Badger-Anticheat]: " .. Config.Messages.ChatMessageTriggered)
end
end)
function GetEntityOwner(entity)
if (not DoesEntityExist(entity)) then
return nil
end
local owner = NetworkGetEntityOwner(entity)
if (GetEntityPopulationType(entity) ~= 7) then return nil end
return owner
end
AddEventHandler('explosionEvent', function(sender, ev)
local sender = tonumber(sender)
CancelEvent()
if (sender ~= nil and sender > 0) then
CancelEvent()
end
end)
for i=1, #BlacklistedEvents, 1 do
RegisterServerEvent(BlacklistedEvents[i])
AddEventHandler(BlacklistedEvents[i], function()
local id = source;
local ids = ExtractIdentifiers(id);
local steam = ids.steam:gsub("steam:", "");
local steamDec = tostring(tonumber(steam,16));
steam = "https://steamcommunity.com/profiles/" .. steamDec;
local gameLicense = ids.license;
local discord = ids.discord;
local reason = Config.Messages.BlacklistedEventTriggered:gsub("{EVENT}", BlacklistedEvents[i]);
if Config.BanComponents.AntiBlacklistedEvent then
BanPlayer(id, "[Badger-Anticheat]: " .. reason);
sendToDisc("[BANNED] CONFIRMED HACKER (Tried executing `".. BlacklistedEvents[i] .."`): _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
else
sendToDisc("CONFIRMED HACKER [Tried executing `".. BlacklistedEvents[i] .."`]: _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n');
end
DropPlayer(id, "[Badger-Anticheat]: " .. reason)
end)
end
AddEventHandler("entityCreating", function(entity)
local owner = GetEntityOwner(entity)
local cancelled = false
local model = IsLegal(entity);
if (model) then
if (owner ~= nil and owner > 0) then
local id = owner;
local ids = ExtractIdentifiers(id);
local steam = ids.steam:gsub("steam:", "");
local steamDec = tostring(tonumber(steam,16));
steam = "https://steamcommunity.com/profiles/" .. steamDec;
local gameLicense = ids.license;
local discord = ids.discord;
local reason = Config.Messages.BlacklistedEntity:gsub("{ENTITY}", tostring(model));
sendToDisc("HACKER (Probably) [via Blacklisted Entity]: _[" .. tostring(id) .. "] " .. GetPlayerName(id) .. "_ has spawned something...",
'Steam: **' .. steam .. '**\n' ..
'GameLicense: **' .. gameLicense .. '**\n' ..
'Discord Tag: **<@' .. discord:gsub('discord:', '') .. '>**\n' ..
'Discord UID: **' .. discord:gsub('discord:', '') .. '**\n'
.. 'Blacklisted Item: **' .. tostring(model) .. "**");
DropPlayer(owner, "[Badger-Anticheat]: " .. reason);
end
CancelEvent()
cancelled = true
end
end)
function ExtractIdentifiers(src)
local identifiers = {
steam = "",
ip = "",
discord = "",
license = "",
xbl = "",
live = ""
}
--Loop over all identifiers
for i = 0, GetNumPlayerIdentifiers(src) - 1 do
local id = GetPlayerIdentifier(src, i)
--Convert it to a nice table.
if string.find(id, "steam") then
identifiers.steam = id
elseif string.find(id, "ip") then
identifiers.ip = id
elseif string.find(id, "discord") then
identifiers.discord = id
elseif string.find(id, "license") then
identifiers.license = id
elseif string.find(id, "xbl") then
identifiers.xbl = id
elseif string.find(id, "live") then
identifiers.live = id
end
end
return identifiers
end
function sendToDisc(title, message, footer)
local embed = {}
embed = {
{
["color"] = 16711680, -- GREEN = 65280 --- RED = 16711680
["title"] = "**".. title .."**",
["description"] = "" .. message .. "",
["footer"] = {
["text"] = footer,
},
}
}
PerformHttpRequest(webhookURL,
function(err, text, headers) end, 'POST', json.encode({username = name, embeds = embed}), { ['Content-Type'] = 'application/json' })
end
--Optional Features depending on the server disable if not suitable for yours!
AddEventHandler("clearPedTasksEvent", function(sender, data)
if Config.Components.AntiCancelAnimations then
CancelEvent()
end
-- Stops other players kicking people out of cars
end)
AddEventHandler('removeWeaponEvent', function(sender, data)
if Config.Components.AntiRemoveOtherPlayersWeapons then
CancelEvent()
end
-- Would only affect if you have scripts removing other people's weapons. (stops players removing other players weapons)
end)
AddEventHandler('giveWeaponEvent', function(sender, data)
if Config.Components.StopOtherPlayersGivingEachOtherWeapons then
CancelEvent()
end
-- Stops other players giving people weapons (doesn't affect single people unless you have give weapons on menus and etc.)
end)
CreateThread(function()
if Config.Components.ModMenuChecks then
Wait(1000)
local added = false
for i = 1, GetNumResources() do
local resource_id = i - 1
local resource_name = GetResourceByFindIndex(resource_id)
if resource_name ~= GetCurrentResourceName() then
for k, v in pairs({'fxmanifest.lua', '__resource.lua'}) do
local data = LoadResourceFile(resource_name, v)
if data and type(data) == 'string' and string.find(data, 'acloader.lua') == nil then
data = data .. '\nclient_script "@' .. GetCurrentResourceName() .. '/acloader.lua"'
SaveResourceFile(resource_name, v, data, -1)
print('Added to resource: ' .. resource_name)
added = true
end
end
end
end
if added then
print('Modified 1 or more resources. It is required to restart your server so these changes can now take place.')
end
else
Wait(1000)
local added = false
for i = 1, GetNumResources() do
local resource_id = i - 1
local resource_name = GetResourceByFindIndex(resource_id)
if resource_name ~= GetCurrentResourceName() then
for k, v in pairs({'fxmanifest.lua', '__resource.lua'}) do
local data = LoadResourceFile(resource_name, v)
if data and type(data) == 'string' and string.find(data, 'acloader.lua') ~= nil then
-- data = data:lower()
local removed = string.gsub(data, 'client_script "%@badger%-anticheat%-master%/acloader.lua"', "")
SaveResourceFile(resource_name, v, removed, -1)
print('Removed from resource: ' .. resource_name)
added = true
end
end
end
end
if added then
print('[Badger-AC] Uninstall Mod-Menu-Checks | Modified 1 or more resources. It is required to restart your server so these changes can now take place.')
end
end
end)
local validResourceList
local function collectValidResourceList()
validResourceList = {}
for i = 0, GetNumResources() - 1 do
validResourceList[GetResourceByFindIndex(i)] = true
end
end
collectValidResourceList()
if Config.Components.StopUnauthorizedResources then
AddEventHandler("onResourceListRefresh", collectValidResourceList)
RegisterNetEvent("ANTICHEAT:CHECKRESOURCES")
AddEventHandler("ANTICHEAT:CHECKRESOURCES", function(givenList)
local source = source
Wait(50)
for _, resource in ipairs(givenList) do
if not validResourceList[resource] then
BanPlayer(source, "[Badger-Anticheat]: " .. Config.Messages.UnauthorizedResources:gsub("{RESOURCE}", resource));
end
end
end)
end