summaryrefslogtreecommitdiff
path: root/sourcemod/scripting/gokz-anticheat.sp
diff options
context:
space:
mode:
Diffstat (limited to 'sourcemod/scripting/gokz-anticheat.sp')
-rw-r--r--sourcemod/scripting/gokz-anticheat.sp318
1 files changed, 318 insertions, 0 deletions
diff --git a/sourcemod/scripting/gokz-anticheat.sp b/sourcemod/scripting/gokz-anticheat.sp
new file mode 100644
index 0000000..9925eca
--- /dev/null
+++ b/sourcemod/scripting/gokz-anticheat.sp
@@ -0,0 +1,318 @@
+#include <sourcemod>
+
+#include <dhooks>
+
+#include <movementapi>
+#include <gokz/anticheat>
+#include <gokz/core>
+
+#include <autoexecconfig>
+
+#undef REQUIRE_EXTENSIONS
+#undef REQUIRE_PLUGIN
+#include <gokz/localdb>
+#include <sourcebanspp>
+#include <updater>
+
+#pragma newdecls required
+#pragma semicolon 1
+
+
+
+public Plugin myinfo =
+{
+ name = "GOKZ Anti-Cheat",
+ author = "DanZay",
+ description = "Detects basic player movement cheats",
+ version = GOKZ_VERSION,
+ url = GOKZ_SOURCE_URL
+};
+
+#define UPDATER_URL GOKZ_UPDATER_BASE_URL..."gokz-anticheat.txt"
+
+bool gB_GOKZLocalDB;
+bool gB_SourceBansPP;
+bool gB_SourceBans;
+bool gB_GOKZGlobal;
+
+Handle gH_DHooks_OnTeleport;
+
+int gI_CmdNum[MAXPLAYERS + 1];
+int gI_LastOriginTeleportCmdNum[MAXPLAYERS + 1];
+
+int gI_ButtonCount[MAXPLAYERS + 1];
+int gI_ButtonsIndex[MAXPLAYERS + 1];
+int gI_Buttons[MAXPLAYERS + 1][AC_MAX_BUTTON_SAMPLES];
+
+int gI_BhopCount[MAXPLAYERS + 1];
+int gI_BhopIndex[MAXPLAYERS + 1];
+int gI_BhopLastTakeoffCmdnum[MAXPLAYERS + 1];
+int gI_BhopLastRecordedBhopCmdnum[MAXPLAYERS + 1];
+bool gB_BhopHitPerf[MAXPLAYERS + 1][AC_MAX_BHOP_SAMPLES];
+int gI_BhopPreJumpInputs[MAXPLAYERS + 1][AC_MAX_BHOP_SAMPLES];
+int gI_BhopPostJumpInputs[MAXPLAYERS + 1][AC_MAX_BHOP_SAMPLES];
+bool gB_BhopPostJumpInputsPending[MAXPLAYERS + 1];
+bool gB_LastLandingWasValid[MAXPLAYERS + 1];
+bool gB_BindExceptionPending[MAXPLAYERS + 1];
+bool gB_BindExceptionPostPending[MAXPLAYERS + 1];
+
+ConVar gCV_gokz_autoban;
+ConVar gCV_gokz_autoban_duration_bhop_hack;
+ConVar gCV_gokz_autoban_duration_bhop_macro;
+ConVar gCV_sv_autobunnyhopping;
+
+#include "gokz-anticheat/api.sp"
+#include "gokz-anticheat/bhop_tracking.sp"
+#include "gokz-anticheat/commands.sp"
+
+
+
+// =====[ PLUGIN EVENTS ]=====
+
+public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
+{
+ CreateNatives();
+ RegPluginLibrary("gokz-anticheat");
+ return APLRes_Success;
+}
+
+public void OnPluginStart()
+{
+ LoadTranslations("common.phrases");
+ LoadTranslations("gokz-common.phrases");
+ LoadTranslations("gokz-anticheat.phrases");
+
+ CreateConVars();
+ CreateGlobalForwards();
+ HookEvents();
+ RegisterCommands();
+}
+
+public void OnAllPluginsLoaded()
+{
+ if (LibraryExists("updater"))
+ {
+ Updater_AddPlugin(UPDATER_URL);
+ }
+ gB_GOKZLocalDB = LibraryExists("gokz-localdb");
+ gB_SourceBansPP = LibraryExists("sourcebans++");
+ gB_SourceBans = LibraryExists("sourcebans");
+ gB_GOKZGlobal = LibraryExists("gokz-global");
+
+ for (int client = 1; client <= MaxClients; client++)
+ {
+ if (IsClientInGame(client))
+ {
+ OnClientPutInServer(client);
+ }
+ }
+}
+
+public void OnLibraryAdded(const char[] name)
+{
+ if (StrEqual(name, "updater"))
+ {
+ Updater_AddPlugin(UPDATER_URL);
+ }
+ gB_GOKZLocalDB = gB_GOKZLocalDB || StrEqual(name, "gokz-localdb");
+ gB_SourceBansPP = gB_SourceBansPP || StrEqual(name, "sourcebans++");
+ gB_SourceBans = gB_SourceBans || StrEqual(name, "sourcebans");
+ gB_GOKZGlobal = gB_GOKZGlobal || StrEqual(name, "gokz-global");
+}
+
+public void OnLibraryRemoved(const char[] name)
+{
+ gB_GOKZLocalDB = gB_GOKZLocalDB && !StrEqual(name, "gokz-localdb");
+ gB_SourceBansPP = gB_SourceBansPP && !StrEqual(name, "sourcebans++");
+ gB_SourceBans = gB_SourceBans && !StrEqual(name, "sourcebans");
+ gB_GOKZGlobal = gB_GOKZGlobal && !StrEqual(name, "gokz-global");
+}
+
+
+
+// =====[ CLIENT EVENTS ]=====
+
+public void OnClientPutInServer(int client)
+{
+ OnClientPutInServer_BhopTracking(client);
+ HookClientEvents(client);
+}
+
+public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2])
+{
+ gI_CmdNum[client] = cmdnum;
+ return Plugin_Continue;
+}
+
+public void OnPlayerRunCmdPost(int client, int buttons, int impulse, const float vel[3], const float angles[3], int weapon, int subtype, int cmdnum, int tickcount, int seed, const int mouse[2])
+{
+ if (!IsPlayerAlive(client) || IsFakeClient(client))
+ {
+ return;
+ }
+
+ OnPlayerRunCmdPost_BhopTracking(client, buttons, cmdnum);
+}
+
+public MRESReturn DHooks_OnTeleport(int client, Handle params)
+{
+ // Parameter 1 not null means origin affected
+ gI_LastOriginTeleportCmdNum[client] = !DHookIsNullParam(params, 1) ? gI_CmdNum[client] : gI_LastOriginTeleportCmdNum[client];
+
+ // Parameter 3 not null means velocity affected
+ //gI_LastVelocityTeleportCmdNum[client] = !DHookIsNullParam(params, 3) ? gI_CmdNum[client] : gI_LastVelocityTeleportCmdNum[client];
+
+ return MRES_Ignored;
+}
+
+public void GOKZ_OnFirstSpawn(int client)
+{
+ GOKZ_PrintToChat(client, false, "%t", "Anti-Cheat Warning");
+}
+
+public void GOKZ_AC_OnPlayerSuspected(int client, ACReason reason, const char[] notes, const char[] stats)
+{
+ LogSuspicion(client, reason, notes, stats);
+}
+
+
+
+// =====[ PUBLIC ]=====
+
+void SuspectPlayer(int client, ACReason reason, const char[] notes, const char[] stats)
+{
+ Call_OnPlayerSuspected(client, reason, notes, stats);
+
+ if (gB_GOKZLocalDB)
+ {
+ GOKZ_DB_SetCheater(client, true);
+ }
+
+ if (gCV_gokz_autoban.BoolValue)
+ {
+ BanSuspect(client, reason);
+ }
+}
+
+
+
+// =====[ PRIVATE ]=====
+
+static void CreateConVars()
+{
+ AutoExecConfig_SetFile("gokz-anticheat", "sourcemod/gokz");
+ AutoExecConfig_SetCreateFile(true);
+
+ gCV_gokz_autoban = AutoExecConfig_CreateConVar(
+ "gokz_autoban",
+ "1",
+ "Whether to autoban players when they are suspected of cheating.",
+ _,
+ true,
+ 0.0,
+ true,
+ 1.0);
+
+ gCV_gokz_autoban_duration_bhop_hack = AutoExecConfig_CreateConVar(
+ "gokz_autoban_duration_bhop_hack",
+ "0",
+ "Duration of anticheat autobans for bunnyhop hacking in minutes (0 for permanent).",
+ _,
+ true,
+ 0.0);
+
+ gCV_gokz_autoban_duration_bhop_macro = AutoExecConfig_CreateConVar(
+ "gokz_autoban_duration_bhop_macro",
+ "43200", // 30 days
+ "Duration of anticheat autobans for bunnyhop macroing in minutes (0 for permanent).",
+ _,
+ true,
+ 0.0);
+
+ AutoExecConfig_ExecuteFile();
+ AutoExecConfig_CleanFile();
+
+ gCV_sv_autobunnyhopping = FindConVar("sv_autobunnyhopping");
+}
+
+static void HookEvents()
+{
+ GameData gameData = new GameData("sdktools.games");
+ int offset;
+
+ // Setup DHooks OnTeleport for players
+ offset = gameData.GetOffset("Teleport");
+ gH_DHooks_OnTeleport = DHookCreate(offset, HookType_Entity, ReturnType_Void, ThisPointer_CBaseEntity, DHooks_OnTeleport);
+ DHookAddParam(gH_DHooks_OnTeleport, HookParamType_VectorPtr);
+ DHookAddParam(gH_DHooks_OnTeleport, HookParamType_ObjectPtr);
+ DHookAddParam(gH_DHooks_OnTeleport, HookParamType_VectorPtr);
+ DHookAddParam(gH_DHooks_OnTeleport, HookParamType_Bool);
+
+ delete gameData;
+}
+
+static void HookClientEvents(int client)
+{
+ DHookEntity(gH_DHooks_OnTeleport, true, client);
+}
+
+static void LogSuspicion(int client, ACReason reason, const char[] notes, const char[] stats)
+{
+ char logPath[PLATFORM_MAX_PATH];
+ BuildPath(Path_SM, logPath, sizeof(logPath), AC_LOG_PATH);
+
+ switch (reason)
+ {
+ case ACReason_BhopHack:LogToFileEx(logPath, "%L was suspected of bhop hacking. Notes - %s, Stats - %s", client, notes, stats);
+ case ACReason_BhopMacro:LogToFileEx(logPath, "%L was suspected of bhop macroing. Notes - %s, Stats - %s", client, notes, stats);
+ }
+}
+
+static void BanSuspect(int client, ACReason reason)
+{
+ char banMessage[128];
+ char redirectString[64] = "Contact the server administrator for more info";
+
+ if (gB_GOKZGlobal)
+ {
+ redirectString = "Visit http://rules.global-api.com/ for more info";
+ }
+
+ switch (reason)
+ {
+ case ACReason_BhopHack:
+ {
+ FormatEx(banMessage, sizeof(banMessage), "You have been banned for using a %s.\n%s", "bhop hack", redirectString);
+ AutoBanClient(
+ client,
+ gCV_gokz_autoban_duration_bhop_hack.IntValue,
+ "gokz-anticheat - Bhop hacking",
+ banMessage);
+ }
+ case ACReason_BhopMacro:
+ {
+ FormatEx(banMessage, sizeof(banMessage), "You have been banned for using a %s.\n%s", "bhop macro", redirectString);
+ AutoBanClient(
+ client,
+ gCV_gokz_autoban_duration_bhop_macro.IntValue,
+ "gokz-anticheat - Bhop macroing",
+ banMessage);
+ }
+ }
+}
+
+static void AutoBanClient(int client, int minutes, const char[] reason, const char[] kickMessage)
+{
+ if (gB_SourceBansPP)
+ {
+ SBPP_BanPlayer(0, client, minutes, reason);
+ }
+ else if (gB_SourceBans)
+ {
+ SBBanPlayer(0, client, minutes, reason);
+ }
+ else
+ {
+ BanClient(client, minutes, BANFLAG_AUTO, reason, kickMessage, "gokz-anticheat", 0);
+ }
+} \ No newline at end of file