mirror of
https://github.com/ornfelt/azerothcore_lua_scripts
synced 2026-08-22 06:26:03 -04:00
1244 lines
45 KiB
Diff
1244 lines
45 KiB
Diff
|
|
diff --git a/sql/anticheat.sql b/sql/anticheat.sql
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..a7326738446
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/sql/anticheat.sql
|
||
|
|
@@ -0,0 +1,30 @@
|
||
|
|
+DROP TABLE IF EXISTS `players_reports_status`;
|
||
|
|
+
|
||
|
|
+CREATE TABLE `players_reports_status` (
|
||
|
|
+ `guid` int(10) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `creation_time` int(10) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `average` float NOT NULL DEFAULT '0',
|
||
|
|
+ `total_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `speed_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `fly_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `jump_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `waterwalk_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `teleportplane_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `climb_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ PRIMARY KEY (`guid`)
|
||
|
|
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='';
|
||
|
|
+
|
||
|
|
+DROP TABLE IF EXISTS `daily_players_reports`;
|
||
|
|
+CREATE TABLE `daily_players_reports` (
|
||
|
|
+ `guid` int(10) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `creation_time` int(10) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `average` float NOT NULL DEFAULT '0',
|
||
|
|
+ `total_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `speed_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `fly_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `jump_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `waterwalk_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `teleportplane_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ `climb_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
|
||
|
|
+ PRIMARY KEY (`guid`)
|
||
|
|
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='';
|
||
|
|
diff --git a/src/server/game/Anticheat/AnticheatData.cpp b/src/server/game/Anticheat/AnticheatData.cpp
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..0a614739666
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/server/game/Anticheat/AnticheatData.cpp
|
||
|
|
@@ -0,0 +1,132 @@
|
||
|
|
+/*
|
||
|
|
+ * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||
|
|
+ *
|
||
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
||
|
|
+ * under the terms of the GNU General Public License as published by the
|
||
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||
|
|
+ * option) any later version.
|
||
|
|
+ *
|
||
|
|
+ * This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
|
+ * more details.
|
||
|
|
+ *
|
||
|
|
+ * You should have received a copy of the GNU General Public License along
|
||
|
|
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+#include "AnticheatData.h"
|
||
|
|
+
|
||
|
|
+AnticheatData::AnticheatData()
|
||
|
|
+{
|
||
|
|
+ lastOpcode = 0;
|
||
|
|
+ totalReports = 0;
|
||
|
|
+ for (uint8 i = 0; i < MAX_REPORT_TYPES; i++)
|
||
|
|
+ {
|
||
|
|
+ typeReports[i] = 0;
|
||
|
|
+ tempReports[i] = 0;
|
||
|
|
+ tempReportsTimer[i] = 0;
|
||
|
|
+ }
|
||
|
|
+ average = 0;
|
||
|
|
+ creationTime = 0;
|
||
|
|
+ hasDailyReport = false;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+AnticheatData::~AnticheatData()
|
||
|
|
+{
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetDailyReportState(bool b)
|
||
|
|
+{
|
||
|
|
+ hasDailyReport = b;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+bool AnticheatData::GetDailyReportState()
|
||
|
|
+{
|
||
|
|
+ return hasDailyReport;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetLastOpcode(uint32 opcode)
|
||
|
|
+{
|
||
|
|
+ lastOpcode = opcode;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetPosition(float x, float y, float z, float o)
|
||
|
|
+{
|
||
|
|
+ lastMovementInfo.pos = { x, y, z, o };
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+uint32 AnticheatData::GetLastOpcode() const
|
||
|
|
+{
|
||
|
|
+ return lastOpcode;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+const MovementInfo& AnticheatData::GetLastMovementInfo() const
|
||
|
|
+{
|
||
|
|
+ return lastMovementInfo;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetLastMovementInfo(MovementInfo& moveInfo)
|
||
|
|
+{
|
||
|
|
+ lastMovementInfo = moveInfo;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+uint32 AnticheatData::GetTotalReports() const
|
||
|
|
+{
|
||
|
|
+ return totalReports;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetTotalReports(uint32 _totalReports)
|
||
|
|
+{
|
||
|
|
+ totalReports = _totalReports;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetTypeReports(uint32 type, uint32 amount)
|
||
|
|
+{
|
||
|
|
+ typeReports[type] = amount;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+uint32 AnticheatData::GetTypeReports(uint32 type) const
|
||
|
|
+{
|
||
|
|
+ return typeReports[type];
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+float AnticheatData::GetAverage() const
|
||
|
|
+{
|
||
|
|
+ return average;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetAverage(float _average)
|
||
|
|
+{
|
||
|
|
+ average = _average;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+uint32 AnticheatData::GetCreationTime() const
|
||
|
|
+{
|
||
|
|
+ return creationTime;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetCreationTime(uint32 _creationTime)
|
||
|
|
+{
|
||
|
|
+ creationTime = _creationTime;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetTempReports(uint32 amount, uint8 type)
|
||
|
|
+{
|
||
|
|
+ tempReports[type] = amount;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+uint32 AnticheatData::GetTempReports(uint8 type)
|
||
|
|
+{
|
||
|
|
+ return tempReports[type];
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatData::SetTempReportsTimer(uint32 time, uint8 type)
|
||
|
|
+{
|
||
|
|
+ tempReportsTimer[type] = time;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+uint32 AnticheatData::GetTempReportsTimer(uint8 type)
|
||
|
|
+{
|
||
|
|
+ return tempReportsTimer[type];
|
||
|
|
+}
|
||
|
|
diff --git a/src/server/game/Anticheat/AnticheatData.h b/src/server/game/Anticheat/AnticheatData.h
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..876c0543bea
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/server/game/Anticheat/AnticheatData.h
|
||
|
|
@@ -0,0 +1,74 @@
|
||
|
|
+/*
|
||
|
|
+ * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||
|
|
+ *
|
||
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
||
|
|
+ * under the terms of the GNU General Public License as published by the
|
||
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||
|
|
+ * option) any later version.
|
||
|
|
+ *
|
||
|
|
+ * This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
|
+ * more details.
|
||
|
|
+ *
|
||
|
|
+ * You should have received a copy of the GNU General Public License along
|
||
|
|
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+#ifndef SC_ACDATA_H
|
||
|
|
+#define SC_ACDATA_H
|
||
|
|
+
|
||
|
|
+#include "AnticheatMgr.h"
|
||
|
|
+#include "Player.h"
|
||
|
|
+
|
||
|
|
+#define MAX_REPORT_TYPES 6
|
||
|
|
+
|
||
|
|
+class AnticheatData
|
||
|
|
+{
|
||
|
|
+public:
|
||
|
|
+ AnticheatData();
|
||
|
|
+ ~AnticheatData();
|
||
|
|
+
|
||
|
|
+ void SetLastOpcode(uint32 opcode);
|
||
|
|
+ uint32 GetLastOpcode() const;
|
||
|
|
+
|
||
|
|
+ const MovementInfo& GetLastMovementInfo() const;
|
||
|
|
+ void SetLastMovementInfo(MovementInfo& moveInfo);
|
||
|
|
+
|
||
|
|
+ void SetPosition(float x, float y, float z, float o);
|
||
|
|
+
|
||
|
|
+ uint32 GetTotalReports() const;
|
||
|
|
+ void SetTotalReports(uint32 _totalReports);
|
||
|
|
+
|
||
|
|
+ uint32 GetTypeReports(uint32 type) const;
|
||
|
|
+ void SetTypeReports(uint32 type, uint32 amount);
|
||
|
|
+
|
||
|
|
+ float GetAverage() const;
|
||
|
|
+ void SetAverage(float _average);
|
||
|
|
+
|
||
|
|
+ uint32 GetCreationTime() const;
|
||
|
|
+ void SetCreationTime(uint32 creationTime);
|
||
|
|
+
|
||
|
|
+ void SetTempReports(uint32 amount, uint8 type);
|
||
|
|
+ uint32 GetTempReports(uint8 type);
|
||
|
|
+
|
||
|
|
+ void SetTempReportsTimer(uint32 time, uint8 type);
|
||
|
|
+ uint32 GetTempReportsTimer(uint8 type);
|
||
|
|
+
|
||
|
|
+ void SetDailyReportState(bool b);
|
||
|
|
+ bool GetDailyReportState();
|
||
|
|
+private:
|
||
|
|
+ uint32 lastOpcode;
|
||
|
|
+ MovementInfo lastMovementInfo;
|
||
|
|
+ //bool disableACCheck;
|
||
|
|
+ //uint32 disableACCheckTimer;
|
||
|
|
+ uint32 totalReports;
|
||
|
|
+ uint32 typeReports[MAX_REPORT_TYPES];
|
||
|
|
+ float average;
|
||
|
|
+ uint32 creationTime;
|
||
|
|
+ uint32 tempReports[MAX_REPORT_TYPES];
|
||
|
|
+ uint32 tempReportsTimer[MAX_REPORT_TYPES];
|
||
|
|
+ bool hasDailyReport;
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
+#endif
|
||
|
|
diff --git a/src/server/game/Anticheat/AnticheatMgr.cpp b/src/server/game/Anticheat/AnticheatMgr.cpp
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..50b4763ad8b
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/server/game/Anticheat/AnticheatMgr.cpp
|
||
|
|
@@ -0,0 +1,438 @@
|
||
|
|
+/*
|
||
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
||
|
|
+ * under the terms of the GNU General Public License as published by the
|
||
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||
|
|
+ * option) any later version.
|
||
|
|
+ *
|
||
|
|
+ * This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
|
+ * more details.
|
||
|
|
+ *
|
||
|
|
+ * You should have received a copy of the GNU General Public License along
|
||
|
|
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+#include "AnticheatMgr.h"
|
||
|
|
+#include "AnticheatScripts.h"
|
||
|
|
+#include "DatabaseEnv.h"
|
||
|
|
+#include "Log.h"
|
||
|
|
+#include "MapManager.h"
|
||
|
|
+#include "ObjectAccessor.h"
|
||
|
|
+#include "Player.h"
|
||
|
|
+#include "World.h"
|
||
|
|
+
|
||
|
|
+#define CLIMB_ANGLE 1.9f
|
||
|
|
+
|
||
|
|
+AnticheatMgr::AnticheatMgr()
|
||
|
|
+{
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+AnticheatMgr::~AnticheatMgr()
|
||
|
|
+{
|
||
|
|
+ m_Players.clear();
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::JumpHackDetection(Player* player, MovementInfo /* movementInfo */,uint32 opcode)
|
||
|
|
+{
|
||
|
|
+ if ((sWorld->getIntConfig(CONFIG_ANTICHEAT_DETECTIONS_ENABLED) & JUMP_HACK_DETECTION) == 0)
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ uint32 key = player->GetGUID().GetCounter();
|
||
|
|
+
|
||
|
|
+ if (m_Players[key].GetLastOpcode() == MSG_MOVE_JUMP && opcode == MSG_MOVE_JUMP)
|
||
|
|
+ {
|
||
|
|
+ BuildReport(player,JUMP_HACK_REPORT);
|
||
|
|
+ TC_LOG_DEBUG("entities.player.character", "AnticheatMgr:: Jump-Hack detected player GUID %s",player->GetGUID().ToString().c_str());
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::WalkOnWaterHackDetection(Player* player, MovementInfo /* movementInfo */)
|
||
|
|
+{
|
||
|
|
+ if ((sWorld->getIntConfig(CONFIG_ANTICHEAT_DETECTIONS_ENABLED) & WALK_WATER_HACK_DETECTION) == 0)
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ uint32 key = player->GetGUID().GetCounter();
|
||
|
|
+ if (!m_Players[key].GetLastMovementInfo().HasMovementFlag(MOVEMENTFLAG_WATERWALKING))
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ // if we are a ghost we can walk on water
|
||
|
|
+ if (!player->IsAlive())
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ if (player->HasAuraType(SPELL_AURA_FEATHER_FALL) ||
|
||
|
|
+ player->HasAuraType(SPELL_AURA_SAFE_FALL) ||
|
||
|
|
+ player->HasAuraType(SPELL_AURA_WATER_WALK))
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ TC_LOG_DEBUG("entities.player.character", "AnticheatMgr:: Walk on Water - Hack detected player GUID %s",player->GetGUID().ToString().c_str());
|
||
|
|
+ BuildReport(player,WALK_WATER_HACK_REPORT);
|
||
|
|
+
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::FlyHackDetection(Player* player, MovementInfo /* movementInfo */)
|
||
|
|
+{
|
||
|
|
+ if ((sWorld->getIntConfig(CONFIG_ANTICHEAT_DETECTIONS_ENABLED) & FLY_HACK_DETECTION) == 0)
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ uint32 key = player->GetGUID().GetCounter();
|
||
|
|
+ if (!m_Players[key].GetLastMovementInfo().HasMovementFlag(MOVEMENTFLAG_FLYING))
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ if (player->HasAuraType(SPELL_AURA_FLY) ||
|
||
|
|
+ player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) ||
|
||
|
|
+ player->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED))
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ TC_LOG_DEBUG("entities.player.character", "AnticheatMgr:: Fly-Hack detected player GUID %s",player->GetGUID().ToString().c_str());
|
||
|
|
+ BuildReport(player,FLY_HACK_REPORT);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::TeleportPlaneHackDetection(Player* player, MovementInfo movementInfo)
|
||
|
|
+{
|
||
|
|
+ if ((sWorld->getIntConfig(CONFIG_ANTICHEAT_DETECTIONS_ENABLED) & TELEPORT_PLANE_HACK_DETECTION) == 0)
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ uint32 key = player->GetGUID().GetCounter();
|
||
|
|
+
|
||
|
|
+ if (m_Players[key].GetLastMovementInfo().pos.GetPositionZ() != 0 ||
|
||
|
|
+ movementInfo.pos.GetPositionZ() != 0)
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ if (movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING))
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ float x, y, z;
|
||
|
|
+ player->GetPosition(x, y, z);
|
||
|
|
+ float ground_Z = player->GetMap()->GetHeight(x, y, z);
|
||
|
|
+ float z_diff = fabs(ground_Z - z);
|
||
|
|
+
|
||
|
|
+ // we are not really walking there
|
||
|
|
+ if (z_diff > 1.0f)
|
||
|
|
+ {
|
||
|
|
+ TC_LOG_DEBUG("entities.player.character", "AnticheatMgr:: Teleport To Plane - Hack detected player GUID %s",player->GetGUID().ToString().c_str());
|
||
|
|
+ BuildReport(player,TELEPORT_PLANE_HACK_REPORT);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::StartHackDetection(Player* player, MovementInfo movementInfo, uint32 opcode)
|
||
|
|
+{
|
||
|
|
+ if (!sWorld->getBoolConfig(CONFIG_ANTICHEAT_ENABLE))
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ if (player->IsGameMaster())
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ uint32 key = player->GetGUID().GetCounter();
|
||
|
|
+
|
||
|
|
+ if (player->IsInFlight() || player->GetTransport() || player->GetVehicle())
|
||
|
|
+ {
|
||
|
|
+ m_Players[key].SetLastMovementInfo(movementInfo);
|
||
|
|
+ m_Players[key].SetLastOpcode(opcode);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ SpeedHackDetection(player,movementInfo);
|
||
|
|
+ FlyHackDetection(player,movementInfo);
|
||
|
|
+ WalkOnWaterHackDetection(player,movementInfo);
|
||
|
|
+ JumpHackDetection(player,movementInfo,opcode);
|
||
|
|
+ TeleportPlaneHackDetection(player, movementInfo);
|
||
|
|
+ ClimbHackDetection(player,movementInfo,opcode);
|
||
|
|
+
|
||
|
|
+ m_Players[key].SetLastMovementInfo(movementInfo);
|
||
|
|
+ m_Players[key].SetLastOpcode(opcode);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+// basic detection
|
||
|
|
+void AnticheatMgr::ClimbHackDetection(Player *player, MovementInfo movementInfo, uint32 opcode)
|
||
|
|
+{
|
||
|
|
+ if ((sWorld->getIntConfig(CONFIG_ANTICHEAT_DETECTIONS_ENABLED) & CLIMB_HACK_DETECTION) == 0)
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ uint32 key = player->GetGUID().GetCounter();
|
||
|
|
+
|
||
|
|
+ if (opcode != MSG_MOVE_HEARTBEAT ||
|
||
|
|
+ m_Players[key].GetLastOpcode() != MSG_MOVE_HEARTBEAT)
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ // in this case we don't care if they are "legal" flags, they are handled in another parts of the Anticheat Manager.
|
||
|
|
+ if (player->IsInWater() ||
|
||
|
|
+ player->IsFlying() ||
|
||
|
|
+ player->IsFalling())
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ Position playerPos;
|
||
|
|
+
|
||
|
|
+ float deltaZ = fabs(playerPos.GetPositionZ() - movementInfo.pos.GetPositionZ());
|
||
|
|
+ float deltaXY = movementInfo.pos.GetExactDist2d(&playerPos);
|
||
|
|
+
|
||
|
|
+ float angle = Position::NormalizeOrientation(tan(deltaZ/deltaXY));
|
||
|
|
+
|
||
|
|
+ if (angle > CLIMB_ANGLE)
|
||
|
|
+ {
|
||
|
|
+ TC_LOG_DEBUG("entities.player.character", "AnticheatMgr:: Climb-Hack detected player GUID %s",player->GetGUID().ToString().c_str());
|
||
|
|
+ BuildReport(player,CLIMB_HACK_REPORT);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::SpeedHackDetection(Player* player,MovementInfo movementInfo)
|
||
|
|
+{
|
||
|
|
+ if ((sWorld->getIntConfig(CONFIG_ANTICHEAT_DETECTIONS_ENABLED) & SPEED_HACK_DETECTION) == 0)
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ uint32 key = player->GetGUID().GetCounter();
|
||
|
|
+
|
||
|
|
+ // We also must check the map because the movementFlag can be modified by the client.
|
||
|
|
+ // If we just check the flag, they could always add that flag and always skip the speed hacking detection.
|
||
|
|
+ // 369 == DEEPRUN TRAM
|
||
|
|
+ if (m_Players[key].GetLastMovementInfo().HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && player->GetMapId() == 369)
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ uint32 distance2D = (uint32)movementInfo.pos.GetExactDist2d(&m_Players[key].GetLastMovementInfo().pos);
|
||
|
|
+ uint8 moveType = 0;
|
||
|
|
+
|
||
|
|
+ // we need to know HOW is the player moving
|
||
|
|
+ // TO-DO: Should we check the incoming movement flags?
|
||
|
|
+ if (player->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING))
|
||
|
|
+ moveType = MOVE_SWIM;
|
||
|
|
+ else if (player->IsFlying())
|
||
|
|
+ moveType = MOVE_FLIGHT;
|
||
|
|
+ else if (player->HasUnitMovementFlag(MOVEMENTFLAG_WALKING))
|
||
|
|
+ moveType = MOVE_WALK;
|
||
|
|
+ else
|
||
|
|
+ moveType = MOVE_RUN;
|
||
|
|
+
|
||
|
|
+ // how many yards the player can do in one sec.
|
||
|
|
+ uint32 speedRate = (uint32)(player->GetSpeed(UnitMoveType(moveType)) + movementInfo.jump.xyspeed);
|
||
|
|
+
|
||
|
|
+ // how long the player took to move to here.
|
||
|
|
+ uint32 timeDiff = getMSTimeDiff(m_Players[key].GetLastMovementInfo().time,movementInfo.time);
|
||
|
|
+
|
||
|
|
+ if (!timeDiff)
|
||
|
|
+ timeDiff = 1;
|
||
|
|
+
|
||
|
|
+ // this is the distance doable by the player in 1 sec, using the time done to move to this point.
|
||
|
|
+ uint32 clientSpeedRate = distance2D * 1000 / timeDiff;
|
||
|
|
+
|
||
|
|
+ // we did the (uint32) cast to accept a margin of tolerance
|
||
|
|
+ if (clientSpeedRate > speedRate)
|
||
|
|
+ {
|
||
|
|
+ BuildReport(player,SPEED_HACK_REPORT);
|
||
|
|
+ TC_LOG_DEBUG("entities.player.character", "AnticheatMgr:: Speed-Hack detected player GUID %s",player->GetGUID().ToString().c_str());
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::StartScripts()
|
||
|
|
+{
|
||
|
|
+ new AnticheatScripts();
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::HandlePlayerLogin(Player* player)
|
||
|
|
+{
|
||
|
|
+ // we must delete this to prevent errors in case of crash
|
||
|
|
+ CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u",player->GetGUID().GetCounter());
|
||
|
|
+ // we initialize the pos of lastMovementPosition var.
|
||
|
|
+ m_Players[player->GetGUID().GetCounter()].SetPosition(player->GetPositionX(),player->GetPositionY(),player->GetPositionZ(),player->GetOrientation());
|
||
|
|
+ QueryResult resultDB = CharacterDatabase.PQuery("SELECT * FROM daily_players_reports WHERE guid=%u;",player->GetGUID().GetCounter());
|
||
|
|
+
|
||
|
|
+ if (resultDB)
|
||
|
|
+ m_Players[player->GetGUID().GetCounter()].SetDailyReportState(true);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::HandlePlayerLogout(Player* player)
|
||
|
|
+{
|
||
|
|
+ // TO-DO Make a table that stores the cheaters of the day, with more detailed information.
|
||
|
|
+
|
||
|
|
+ // We must also delete it at logout to prevent have data of offline players in the db when we query the database (IE: The GM Command)
|
||
|
|
+ CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u",player->GetGUID().GetCounter());
|
||
|
|
+ // Delete not needed data from the memory.
|
||
|
|
+ m_Players.erase(player->GetGUID().GetCounter());
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::SavePlayerData(Player* player)
|
||
|
|
+{
|
||
|
|
+ CharacterDatabase.PExecute("REPLACE INTO players_reports_status (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,creation_time) VALUES (%u,%f,%u,%u,%u,%u,%u,%u,%u,%u);",player->GetGUID().GetCounter(),m_Players[player->GetGUID().GetCounter()].GetAverage(),m_Players[player->GetGUID().GetCounter()].GetTotalReports(), m_Players[player->GetGUID().GetCounter()].GetTypeReports(SPEED_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(FLY_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(JUMP_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(WALK_WATER_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(CLIMB_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetCreationTime());
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+uint32 AnticheatMgr::GetTotalReports(uint32 lowGUID)
|
||
|
|
+{
|
||
|
|
+ return m_Players[lowGUID].GetTotalReports();
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+float AnticheatMgr::GetAverage(uint32 lowGUID)
|
||
|
|
+{
|
||
|
|
+ return m_Players[lowGUID].GetAverage();
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+uint32 AnticheatMgr::GetTypeReports(uint32 lowGUID, uint8 type)
|
||
|
|
+{
|
||
|
|
+ return m_Players[lowGUID].GetTypeReports(type);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+bool AnticheatMgr::MustCheckTempReports(uint8 type)
|
||
|
|
+{
|
||
|
|
+ if (type == JUMP_HACK_REPORT)
|
||
|
|
+ return false;
|
||
|
|
+
|
||
|
|
+ return true;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::BuildReport(Player* player,uint8 reportType)
|
||
|
|
+{
|
||
|
|
+ uint32 key = player->GetGUID().GetCounter();
|
||
|
|
+
|
||
|
|
+ if (MustCheckTempReports(reportType))
|
||
|
|
+ {
|
||
|
|
+ uint32 actualTime = getMSTime();
|
||
|
|
+
|
||
|
|
+ if (!m_Players[key].GetTempReportsTimer(reportType))
|
||
|
|
+ m_Players[key].SetTempReportsTimer(actualTime,reportType);
|
||
|
|
+
|
||
|
|
+ if (getMSTimeDiff(m_Players[key].GetTempReportsTimer(reportType),actualTime) < 3000)
|
||
|
|
+ {
|
||
|
|
+ m_Players[key].SetTempReports(m_Players[key].GetTempReports(reportType)+1,reportType);
|
||
|
|
+
|
||
|
|
+ if (m_Players[key].GetTempReports(reportType) < 3)
|
||
|
|
+ return;
|
||
|
|
+ } else
|
||
|
|
+ {
|
||
|
|
+ m_Players[key].SetTempReportsTimer(actualTime,reportType);
|
||
|
|
+ m_Players[key].SetTempReports(1,reportType);
|
||
|
|
+ return;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ // generating creationTime for average calculation
|
||
|
|
+ if (!m_Players[key].GetTotalReports())
|
||
|
|
+ m_Players[key].SetCreationTime(getMSTime());
|
||
|
|
+
|
||
|
|
+ // increasing total_reports
|
||
|
|
+ m_Players[key].SetTotalReports(m_Players[key].GetTotalReports()+1);
|
||
|
|
+ // increasing specific cheat report
|
||
|
|
+ m_Players[key].SetTypeReports(reportType,m_Players[key].GetTypeReports(reportType)+1);
|
||
|
|
+
|
||
|
|
+ // diff time for average calculation
|
||
|
|
+ uint32 diffTime = getMSTimeDiff(m_Players[key].GetCreationTime(),getMSTime()) / IN_MILLISECONDS;
|
||
|
|
+
|
||
|
|
+ if (diffTime > 0)
|
||
|
|
+ {
|
||
|
|
+ // Average == Reports per second
|
||
|
|
+ float average = float(m_Players[key].GetTotalReports()) / float(diffTime);
|
||
|
|
+ m_Players[key].SetAverage(average);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (sWorld->getIntConfig(CONFIG_ANTICHEAT_MAX_REPORTS_FOR_DAILY_REPORT) < m_Players[key].GetTotalReports())
|
||
|
|
+ {
|
||
|
|
+ if (!m_Players[key].GetDailyReportState())
|
||
|
|
+ {
|
||
|
|
+ CharacterDatabase.PExecute("REPLACE INTO daily_players_reports (guid,average,total_reports,speed_reports,fly_reports,jump_reports,waterwalk_reports,teleportplane_reports,climb_reports,creation_time) VALUES (%u,%f,%u,%u,%u,%u,%u,%u,%u,%u);",player->GetGUID().GetCounter(),m_Players[player->GetGUID().GetCounter()].GetAverage(),m_Players[player->GetGUID().GetCounter()].GetTotalReports(), m_Players[player->GetGUID().GetCounter()].GetTypeReports(SPEED_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(FLY_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(JUMP_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(WALK_WATER_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(TELEPORT_PLANE_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetTypeReports(CLIMB_HACK_REPORT),m_Players[player->GetGUID().GetCounter()].GetCreationTime());
|
||
|
|
+ m_Players[key].SetDailyReportState(true);
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (m_Players[key].GetTotalReports() > sWorld->getIntConfig(CONFIG_ANTICHEAT_REPORTS_INGAME_NOTIFICATION))
|
||
|
|
+ {
|
||
|
|
+ // display warning at the center of the screen, hacky way?
|
||
|
|
+ std::string str = "";
|
||
|
|
+ str = "|cFFFFFC00[AC]|cFF00FFFF[|cFF60FF00" + std::string(player->GetName().c_str()) + "|cFF00FFFF] Possible cheater!";
|
||
|
|
+ WorldPacket data(SMSG_NOTIFICATION, (str.size()+1));
|
||
|
|
+ data << str;
|
||
|
|
+ sWorld->SendGlobalGMMessage(&data);
|
||
|
|
+ WorldPacket data2(SMSG_CHAT_SERVER_MESSAGE, (str.size()+1));
|
||
|
|
+ data2 << str;
|
||
|
|
+ sWorld->SendGlobalGMMessage(&data2);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::AnticheatGlobalCommand(ChatHandler* handler)
|
||
|
|
+{
|
||
|
|
+ // MySQL will sort all for us, anyway this is not the best way we must only save the anticheat data not whole player's data!.
|
||
|
|
+ ObjectAccessor::SaveAllPlayers();
|
||
|
|
+
|
||
|
|
+ QueryResult resultDB = CharacterDatabase.Query("SELECT guid,average,total_reports FROM players_reports_status WHERE total_reports != 0 ORDER BY average ASC LIMIT 3;");
|
||
|
|
+ if (!resultDB)
|
||
|
|
+ {
|
||
|
|
+ handler->PSendSysMessage("No players found.");
|
||
|
|
+ return;
|
||
|
|
+ } else
|
||
|
|
+ {
|
||
|
|
+ handler->SendSysMessage("=============================");
|
||
|
|
+ handler->PSendSysMessage("Players with the lowest averages:");
|
||
|
|
+ do
|
||
|
|
+ {
|
||
|
|
+ Field *fieldsDB = resultDB->Fetch();
|
||
|
|
+
|
||
|
|
+ uint32 guid = fieldsDB[0].GetUInt32();
|
||
|
|
+ float average = fieldsDB[1].GetFloat();
|
||
|
|
+ uint32 total_reports = fieldsDB[2].GetUInt32();
|
||
|
|
+
|
||
|
|
+ if (Player* player = ObjectAccessor::FindPlayerByLowGUID(guid))
|
||
|
|
+ handler->PSendSysMessage("Player: %s Average: %f Total Reports: %u",player->GetName().c_str(),average,total_reports);
|
||
|
|
+
|
||
|
|
+ } while (resultDB->NextRow());
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ resultDB = CharacterDatabase.Query("SELECT guid,average,total_reports FROM players_reports_status WHERE total_reports != 0 ORDER BY total_reports DESC LIMIT 3;");
|
||
|
|
+
|
||
|
|
+ // this should never happen
|
||
|
|
+ if (!resultDB)
|
||
|
|
+ {
|
||
|
|
+ handler->PSendSysMessage("No players found.");
|
||
|
|
+ return;
|
||
|
|
+ } else
|
||
|
|
+ {
|
||
|
|
+ handler->SendSysMessage("=============================");
|
||
|
|
+ handler->PSendSysMessage("Players with the more reports:");
|
||
|
|
+ do
|
||
|
|
+ {
|
||
|
|
+ Field *fieldsDB = resultDB->Fetch();
|
||
|
|
+
|
||
|
|
+ uint32 guid = fieldsDB[0].GetUInt32();
|
||
|
|
+ float average = fieldsDB[1].GetFloat();
|
||
|
|
+ uint32 total_reports = fieldsDB[2].GetUInt32();
|
||
|
|
+
|
||
|
|
+ if (Player* player = ObjectAccessor::FindPlayerByLowGUID(guid))
|
||
|
|
+ handler->PSendSysMessage("Player: %s Total Reports: %u Average: %f",player->GetName().c_str(),total_reports,average);
|
||
|
|
+
|
||
|
|
+ } while (resultDB->NextRow());
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::AnticheatDeleteCommand(uint32 guid)
|
||
|
|
+{
|
||
|
|
+ if (!guid)
|
||
|
|
+ {
|
||
|
|
+ for (AnticheatPlayersDataMap::iterator it = m_Players.begin(); it != m_Players.end(); ++it)
|
||
|
|
+ {
|
||
|
|
+ (*it).second.SetTotalReports(0);
|
||
|
|
+ (*it).second.SetAverage(0);
|
||
|
|
+ (*it).second.SetCreationTime(0);
|
||
|
|
+ for (uint8 i = 0; i < MAX_REPORT_TYPES; i++)
|
||
|
|
+ {
|
||
|
|
+ (*it).second.SetTempReports(0,i);
|
||
|
|
+ (*it).second.SetTempReportsTimer(0,i);
|
||
|
|
+ (*it).second.SetTypeReports(i,0);
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ CharacterDatabase.PExecute("DELETE FROM players_reports_status;");
|
||
|
|
+ }
|
||
|
|
+ else
|
||
|
|
+ {
|
||
|
|
+ m_Players[guid].SetTotalReports(0);
|
||
|
|
+ m_Players[guid].SetAverage(0);
|
||
|
|
+ m_Players[guid].SetCreationTime(0);
|
||
|
|
+ for (uint8 i = 0; i < MAX_REPORT_TYPES; i++)
|
||
|
|
+ {
|
||
|
|
+ m_Players[guid].SetTempReports(0,i);
|
||
|
|
+ m_Players[guid].SetTempReportsTimer(0,i);
|
||
|
|
+ m_Players[guid].SetTypeReports(i,0);
|
||
|
|
+ }
|
||
|
|
+ CharacterDatabase.PExecute("DELETE FROM players_reports_status WHERE guid=%u;",guid);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatMgr::ResetDailyReportStates()
|
||
|
|
+{
|
||
|
|
+ for (AnticheatPlayersDataMap::iterator it = m_Players.begin(); it != m_Players.end(); ++it)
|
||
|
|
+ m_Players[(*it).first].SetDailyReportState(false);
|
||
|
|
+}
|
||
|
|
diff --git a/src/server/game/Anticheat/AnticheatMgr.h b/src/server/game/Anticheat/AnticheatMgr.h
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..5f5a2064e5c
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/server/game/Anticheat/AnticheatMgr.h
|
||
|
|
@@ -0,0 +1,102 @@
|
||
|
|
+/*
|
||
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
||
|
|
+ * under the terms of the GNU General Public License as published by the
|
||
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||
|
|
+ * option) any later version.
|
||
|
|
+ *
|
||
|
|
+ * This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
|
+ * more details.
|
||
|
|
+ *
|
||
|
|
+ * You should have received a copy of the GNU General Public License along
|
||
|
|
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+#ifndef SC_ACMGR_H
|
||
|
|
+#define SC_ACMGR_H
|
||
|
|
+
|
||
|
|
+#include "Common.h"
|
||
|
|
+#include "SharedDefines.h"
|
||
|
|
+#include "ScriptMgr.h"
|
||
|
|
+#include "AnticheatData.h"
|
||
|
|
+#include "Chat.h"
|
||
|
|
+#include "Player.h"
|
||
|
|
+
|
||
|
|
+class Player;
|
||
|
|
+class AnticheatData;
|
||
|
|
+
|
||
|
|
+enum ReportTypes
|
||
|
|
+{
|
||
|
|
+ SPEED_HACK_REPORT = 0,
|
||
|
|
+ FLY_HACK_REPORT,
|
||
|
|
+ WALK_WATER_HACK_REPORT,
|
||
|
|
+ JUMP_HACK_REPORT,
|
||
|
|
+ TELEPORT_PLANE_HACK_REPORT,
|
||
|
|
+ CLIMB_HACK_REPORT,
|
||
|
|
+
|
||
|
|
+ // MAX_REPORT_TYPES
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
+enum DetectionTypes
|
||
|
|
+{
|
||
|
|
+ SPEED_HACK_DETECTION = 1,
|
||
|
|
+ FLY_HACK_DETECTION = 2,
|
||
|
|
+ WALK_WATER_HACK_DETECTION = 4,
|
||
|
|
+ JUMP_HACK_DETECTION = 8,
|
||
|
|
+ TELEPORT_PLANE_HACK_DETECTION = 16,
|
||
|
|
+ CLIMB_HACK_DETECTION = 32
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
+// GUIDLow is the key.
|
||
|
|
+typedef std::map<uint32, AnticheatData> AnticheatPlayersDataMap;
|
||
|
|
+
|
||
|
|
+class TC_GAME_API AnticheatMgr
|
||
|
|
+{
|
||
|
|
+ AnticheatMgr();
|
||
|
|
+ ~AnticheatMgr();
|
||
|
|
+
|
||
|
|
+ public:
|
||
|
|
+ static AnticheatMgr* instance()
|
||
|
|
+ {
|
||
|
|
+ static AnticheatMgr* instance = new AnticheatMgr();
|
||
|
|
+ return instance;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ void StartHackDetection(Player* player, MovementInfo movementInfo, uint32 opcode);
|
||
|
|
+ void DeletePlayerReport(Player* player, bool login);
|
||
|
|
+ void DeletePlayerData(Player* player);
|
||
|
|
+ void CreatePlayerData(Player* player);
|
||
|
|
+ void SavePlayerData(Player* player);
|
||
|
|
+
|
||
|
|
+ void StartScripts();
|
||
|
|
+
|
||
|
|
+ void HandlePlayerLogin(Player* player);
|
||
|
|
+ void HandlePlayerLogout(Player* player);
|
||
|
|
+
|
||
|
|
+ uint32 GetTotalReports(uint32 lowGUID);
|
||
|
|
+ float GetAverage(uint32 lowGUID);
|
||
|
|
+ uint32 GetTypeReports(uint32 lowGUID, uint8 type);
|
||
|
|
+
|
||
|
|
+ void AnticheatGlobalCommand(ChatHandler* handler);
|
||
|
|
+ void AnticheatDeleteCommand(uint32 guid);
|
||
|
|
+
|
||
|
|
+ void ResetDailyReportStates();
|
||
|
|
+ private:
|
||
|
|
+ void SpeedHackDetection(Player* player, MovementInfo movementInfo);
|
||
|
|
+ void FlyHackDetection(Player* player, MovementInfo movementInfo);
|
||
|
|
+ void WalkOnWaterHackDetection(Player* player, MovementInfo movementInfo);
|
||
|
|
+ void JumpHackDetection(Player* player, MovementInfo movementInfo,uint32 opcode);
|
||
|
|
+ void TeleportPlaneHackDetection(Player* player, MovementInfo);
|
||
|
|
+ void ClimbHackDetection(Player* player,MovementInfo movementInfo,uint32 opcode);
|
||
|
|
+
|
||
|
|
+ void BuildReport(Player* player,uint8 reportType);
|
||
|
|
+
|
||
|
|
+ bool MustCheckTempReports(uint8 type);
|
||
|
|
+
|
||
|
|
+ AnticheatPlayersDataMap m_Players; ///< Player data
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
+#define sAnticheatMgr AnticheatMgr::instance()
|
||
|
|
+
|
||
|
|
+#endif
|
||
|
|
diff --git a/src/server/game/Anticheat/AnticheatScripts.cpp b/src/server/game/Anticheat/AnticheatScripts.cpp
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..538db2c8eb7
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/server/game/Anticheat/AnticheatScripts.cpp
|
||
|
|
@@ -0,0 +1,31 @@
|
||
|
|
+/*
|
||
|
|
+ * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||
|
|
+ *
|
||
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
||
|
|
+ * under the terms of the GNU General Public License as published by the
|
||
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||
|
|
+ * option) any later version.
|
||
|
|
+ *
|
||
|
|
+ * This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
|
+ * more details.
|
||
|
|
+ *
|
||
|
|
+ * You should have received a copy of the GNU General Public License along
|
||
|
|
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+#include "AnticheatScripts.h"
|
||
|
|
+#include "AnticheatMgr.h"
|
||
|
|
+
|
||
|
|
+AnticheatScripts::AnticheatScripts(): PlayerScript("AnticheatScripts") {}
|
||
|
|
+
|
||
|
|
+void AnticheatScripts::OnLogout(Player* player)
|
||
|
|
+{
|
||
|
|
+ sAnticheatMgr->HandlePlayerLogout(player);
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void AnticheatScripts::OnLogin(Player* player,bool)
|
||
|
|
+{
|
||
|
|
+ sAnticheatMgr->HandlePlayerLogin(player);
|
||
|
|
+}
|
||
|
|
diff --git a/src/server/game/Anticheat/AnticheatScripts.h b/src/server/game/Anticheat/AnticheatScripts.h
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..1e6aa764db1
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/server/game/Anticheat/AnticheatScripts.h
|
||
|
|
@@ -0,0 +1,32 @@
|
||
|
|
+/*
|
||
|
|
+ * Copyright (C) 2008-2018 TrinityCore <https://www.trinitycore.org/>
|
||
|
|
+ *
|
||
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
||
|
|
+ * under the terms of the GNU General Public License as published by the
|
||
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||
|
|
+ * option) any later version.
|
||
|
|
+ *
|
||
|
|
+ * This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
|
+ * more details.
|
||
|
|
+ *
|
||
|
|
+ * You should have received a copy of the GNU General Public License along
|
||
|
|
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+#ifndef SC_ACSCRIPTS_H
|
||
|
|
+#define SC_ACSCRIPTS_H
|
||
|
|
+
|
||
|
|
+#include "ScriptMgr.h"
|
||
|
|
+
|
||
|
|
+class AnticheatScripts: public PlayerScript
|
||
|
|
+{
|
||
|
|
+ public:
|
||
|
|
+ AnticheatScripts();
|
||
|
|
+
|
||
|
|
+ void OnLogout(Player* player);
|
||
|
|
+ void OnLogin(Player* player,bool);
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
+#endif
|
||
|
|
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
|
||
|
|
index bffd5163ae8..bcae4b5e513 100644
|
||
|
|
--- a/src/server/game/Entities/Player/Player.cpp
|
||
|
|
+++ b/src/server/game/Entities/Player/Player.cpp
|
||
|
|
@@ -29,6 +29,7 @@
|
||
|
|
#include "Player.h"
|
||
|
|
#include "AccountMgr.h"
|
||
|
|
#include "AchievementMgr.h"
|
||
|
|
+#include "AnticheatMgr.h"
|
||
|
|
#include "ArenaTeam.h"
|
||
|
|
#include "ArenaTeamMgr.h"
|
||
|
|
#include "Bag.h"
|
||
|
|
@@ -19599,6 +19600,12 @@ void Player::SaveToDB(CharacterDatabaseTransaction trans, bool create /* = false
|
||
|
|
if (m_session->isLogingOut() || !sWorld->getBoolConfig(CONFIG_STATS_SAVE_ONLY_ON_LOGOUT))
|
||
|
|
_SaveStats(trans);
|
||
|
|
|
||
|
|
+ // we save the data here to prevent spamming
|
||
|
|
+ sAnticheatMgr->SavePlayerData(this);
|
||
|
|
+
|
||
|
|
+ // in this way we prevent to spam the db by each report made!
|
||
|
|
+ // sAnticheatMgr->SavePlayerData(this);
|
||
|
|
+
|
||
|
|
// save pet (hunter pet level and experience and all type pets health/mana).
|
||
|
|
if (Pet* pet = GetPet())
|
||
|
|
pet->SavePetToDB(PET_SAVE_AS_CURRENT);
|
||
|
|
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
|
||
|
|
index bad6e220c1a..42e22258d7b 100644
|
||
|
|
--- a/src/server/game/Handlers/MovementHandler.cpp
|
||
|
|
+++ b/src/server/game/Handlers/MovementHandler.cpp
|
||
|
|
@@ -15,6 +15,7 @@
|
||
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
|
||
|
|
+#include "AnticheatMgr.h"
|
||
|
|
#include "Battleground.h"
|
||
|
|
#include "Common.h"
|
||
|
|
#include "Corpse.h"
|
||
|
|
@@ -372,6 +373,8 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
|
||
|
|
if (opcode == MSG_MOVE_FALL_LAND || opcode == MSG_MOVE_START_SWIM)
|
||
|
|
mover->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_LANDING); // Parachutes
|
||
|
|
|
||
|
|
+ if (plrMover)
|
||
|
|
+ sAnticheatMgr->StartHackDetection(plrMover, movementInfo, opcode);
|
||
|
|
/* process position-change */
|
||
|
|
WorldPacket data(opcode, recvData.size());
|
||
|
|
int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta;
|
||
|
|
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
|
||
|
|
index 2d8882dcaec..e5af0140d14 100644
|
||
|
|
--- a/src/server/game/World/World.cpp
|
||
|
|
+++ b/src/server/game/World/World.cpp
|
||
|
|
@@ -28,6 +28,7 @@
|
||
|
|
#include "AuctionHouseMgr.h"
|
||
|
|
#include "BattlefieldMgr.h"
|
||
|
|
#include "BattlegroundMgr.h"
|
||
|
|
+#include "AnticheatMgr.h"
|
||
|
|
#include "CalendarMgr.h"
|
||
|
|
#include "ChannelMgr.h"
|
||
|
|
#include "CharacterCache.h"
|
||
|
|
@@ -1483,6 +1484,11 @@ void World::LoadConfigSettings(bool reload)
|
||
|
|
m_bool_configs[CONFIG_PDUMP_NO_PATHS] = sConfigMgr->GetBoolDefault("PlayerDump.DisallowPaths", true);
|
||
|
|
m_bool_configs[CONFIG_PDUMP_NO_OVERWRITE] = sConfigMgr->GetBoolDefault("PlayerDump.DisallowOverwrite", true);
|
||
|
|
|
||
|
|
+ m_bool_configs[CONFIG_ANTICHEAT_ENABLE] = sConfigMgr->GetBoolDefault("Anticheat.Enable", true);
|
||
|
|
+ m_int_configs[CONFIG_ANTICHEAT_REPORTS_INGAME_NOTIFICATION] = sConfigMgr->GetIntDefault("Anticheat.ReportsForIngameWarnings", 70);
|
||
|
|
+ m_int_configs[CONFIG_ANTICHEAT_DETECTIONS_ENABLED] = sConfigMgr->GetIntDefault("Anticheat.DetectionsEnabled",31);
|
||
|
|
+ m_int_configs[CONFIG_ANTICHEAT_MAX_REPORTS_FOR_DAILY_REPORT] = sConfigMgr->GetIntDefault("Anticheat.MaxReportsForDailyReport",70);
|
||
|
|
+
|
||
|
|
// Wintergrasp battlefield
|
||
|
|
m_bool_configs[CONFIG_WINTERGRASP_ENABLE] = sConfigMgr->GetBoolDefault("Wintergrasp.Enable", false);
|
||
|
|
m_int_configs[CONFIG_WINTERGRASP_PLR_MAX] = sConfigMgr->GetIntDefault("Wintergrasp.PlayerMax", 100);
|
||
|
|
@@ -3251,6 +3257,8 @@ void World::ResetDailyQuests()
|
||
|
|
// reselect pools
|
||
|
|
sQuestPoolMgr->ChangeDailyQuests();
|
||
|
|
|
||
|
|
+ sAnticheatMgr->ResetDailyReportStates();
|
||
|
|
+
|
||
|
|
// store next reset time
|
||
|
|
time_t now = GameTime::GetGameTime();
|
||
|
|
time_t next = GetNextDailyResetTime(now);
|
||
|
|
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
|
||
|
|
index eeda8e69709..b7c9ff5027a 100644
|
||
|
|
--- a/src/server/game/World/World.h
|
||
|
|
+++ b/src/server/game/World/World.h
|
||
|
|
@@ -147,6 +147,7 @@ enum WorldBoolConfigs
|
||
|
|
CONFIG_DELETE_CHARACTER_TICKET_TRACE,
|
||
|
|
CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES,
|
||
|
|
CONFIG_PRESERVE_CUSTOM_CHANNELS,
|
||
|
|
+ CONFIG_ANTICHEAT_ENABLE,
|
||
|
|
CONFIG_PDUMP_NO_PATHS,
|
||
|
|
CONFIG_PDUMP_NO_OVERWRITE,
|
||
|
|
CONFIG_QUEST_IGNORE_AUTO_ACCEPT,
|
||
|
|
@@ -349,7 +350,10 @@ enum WorldIntConfigs
|
||
|
|
CONFIG_PRESERVE_CUSTOM_CHANNEL_INTERVAL,
|
||
|
|
CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS,
|
||
|
|
CONFIG_LFG_OPTIONSMASK,
|
||
|
|
+ CONFIG_ANTICHEAT_REPORTS_INGAME_NOTIFICATION,
|
||
|
|
+ CONFIG_ANTICHEAT_MAX_REPORTS_FOR_DAILY_REPORT,
|
||
|
|
CONFIG_MAX_INSTANCES_PER_HOUR,
|
||
|
|
+ CONFIG_ANTICHEAT_DETECTIONS_ENABLED,
|
||
|
|
CONFIG_XP_BOOST_DAYMASK,
|
||
|
|
CONFIG_WARDEN_CLIENT_RESPONSE_DELAY,
|
||
|
|
CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF,
|
||
|
|
diff --git a/src/server/scripts/Commands/cs_anticheat.cpp b/src/server/scripts/Commands/cs_anticheat.cpp
|
||
|
|
new file mode 100644
|
||
|
|
index 00000000000..264062d599c
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/src/server/scripts/Commands/cs_anticheat.cpp
|
||
|
|
@@ -0,0 +1,176 @@
|
||
|
|
+/*
|
||
|
|
+ * This program is free software; you can redistribute it and/or modify it
|
||
|
|
+ * under the terms of the GNU General Public License as published by the
|
||
|
|
+ * Free Software Foundation; either version 2 of the License, or (at your
|
||
|
|
+ * option) any later version.
|
||
|
|
+ *
|
||
|
|
+ * This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
|
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
|
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
|
+ * more details.
|
||
|
|
+ *
|
||
|
|
+ * You should have received a copy of the GNU General Public License along
|
||
|
|
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
+ */
|
||
|
|
+
|
||
|
|
+#include "Language.h"
|
||
|
|
+#include "ScriptMgr.h"
|
||
|
|
+#include "ObjectMgr.h"
|
||
|
|
+#include "ObjectAccessor.h"
|
||
|
|
+#include "Chat.h"
|
||
|
|
+#include "AnticheatMgr.h"
|
||
|
|
+#include "Player.h"
|
||
|
|
+#include "World.h"
|
||
|
|
+#include "WorldSession.h"
|
||
|
|
+
|
||
|
|
+using namespace Trinity::ChatCommands;
|
||
|
|
+
|
||
|
|
+class anticheat_commandscript : public CommandScript
|
||
|
|
+{
|
||
|
|
+public:
|
||
|
|
+ anticheat_commandscript() : CommandScript("anticheat_commandscript") { }
|
||
|
|
+
|
||
|
|
+ ChatCommandTable GetCommands() const override
|
||
|
|
+ {
|
||
|
|
+ static ChatCommandTable anticheatCommandTable =
|
||
|
|
+ {
|
||
|
|
+ { "global", HandleAntiCheatGlobalCommand, rbac::RBAC_ROLE_GAMEMASTER, Console::Yes },
|
||
|
|
+ { "player", HandleAntiCheatPlayerCommand, rbac::RBAC_ROLE_GAMEMASTER, Console::Yes },
|
||
|
|
+ { "delete", HandleAntiCheatDeleteCommand, rbac::RBAC_ROLE_ADMINISTRATOR, Console::Yes },
|
||
|
|
+ { "handle", HandleAntiCheatHandleCommand, rbac::RBAC_ROLE_ADMINISTRATOR, Console::Yes },
|
||
|
|
+ { "jail", HandleAnticheatJailCommand, rbac::RBAC_ROLE_GAMEMASTER, Console::Yes },
|
||
|
|
+ { "warn", HandleAnticheatWarnCommand, rbac::RBAC_ROLE_GAMEMASTER, Console::Yes },
|
||
|
|
+ };
|
||
|
|
+
|
||
|
|
+ static ChatCommandTable commandTable =
|
||
|
|
+ {
|
||
|
|
+ { "anticheat", anticheatCommandTable },
|
||
|
|
+ };
|
||
|
|
+
|
||
|
|
+ return commandTable;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ static bool HandleAnticheatWarnCommand(ChatHandler* handler, Optional<PlayerIdentifier> player)
|
||
|
|
+ {
|
||
|
|
+ if (!sWorld->getBoolConfig(CONFIG_ANTICHEAT_ENABLE))
|
||
|
|
+ return false;
|
||
|
|
+
|
||
|
|
+ if (!player)
|
||
|
|
+ player = PlayerIdentifier::FromTarget(handler);
|
||
|
|
+ if (!player || !player->IsConnected())
|
||
|
|
+ {
|
||
|
|
+ handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||
|
|
+ handler->SetSentErrorMessage(true);
|
||
|
|
+ return false;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ ChatHandler(player->GetConnectedPlayer()->GetSession()).SendSysMessage("The anticheat system has reported several times that you may be cheating. You will be monitored to confirm if this is accurate.");
|
||
|
|
+ return true;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ static bool HandleAnticheatJailCommand(ChatHandler* handler, Optional<PlayerIdentifier> player)
|
||
|
|
+ {
|
||
|
|
+ if (!sWorld->getBoolConfig(CONFIG_ANTICHEAT_ENABLE))
|
||
|
|
+ return false;
|
||
|
|
+
|
||
|
|
+ if (!player)
|
||
|
|
+ player = PlayerIdentifier::FromTarget(handler);
|
||
|
|
+ if (!player || !player->IsConnected())
|
||
|
|
+ {
|
||
|
|
+ handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||
|
|
+ handler->SetSentErrorMessage(true);
|
||
|
|
+ return false;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ Player* pTarget = player->GetConnectedPlayer();
|
||
|
|
+
|
||
|
|
+ // teleport both to jail.
|
||
|
|
+ WorldLocation jail {1, 16226.5f, 16403.6f, -64.5f, 3.2f};
|
||
|
|
+ pTarget->TeleportTo(jail);
|
||
|
|
+ handler->GetPlayer()->TeleportTo(jail);
|
||
|
|
+ pTarget->SetHomebind(jail, 876);
|
||
|
|
+
|
||
|
|
+ return true;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ static bool HandleAntiCheatDeleteCommand(ChatHandler* /*handler*/, Variant<EXACT_SEQUENCE("deleteall"), PlayerIdentifier> command)
|
||
|
|
+ {
|
||
|
|
+ if (!sWorld->getBoolConfig(CONFIG_ANTICHEAT_ENABLE))
|
||
|
|
+ return false;
|
||
|
|
+
|
||
|
|
+ if (command.holds_alternative<EXACT_SEQUENCE("deleteall")>())
|
||
|
|
+ sAnticheatMgr->AnticheatDeleteCommand(0);
|
||
|
|
+ else
|
||
|
|
+ sAnticheatMgr->AnticheatDeleteCommand(command.get<PlayerIdentifier>().GetGUID().GetCounter());
|
||
|
|
+
|
||
|
|
+ return true;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ static bool HandleAntiCheatPlayerCommand(ChatHandler* handler, Optional<PlayerIdentifier> player)
|
||
|
|
+ {
|
||
|
|
+ if (!sWorld->getBoolConfig(CONFIG_ANTICHEAT_ENABLE))
|
||
|
|
+ return false;
|
||
|
|
+
|
||
|
|
+ if (!player)
|
||
|
|
+ player = PlayerIdentifier::FromTarget(handler);
|
||
|
|
+ if (!player)
|
||
|
|
+ {
|
||
|
|
+ handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
|
||
|
|
+ handler->SetSentErrorMessage(true);
|
||
|
|
+ return false;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ uint32 guid = player->GetGUID().GetCounter();
|
||
|
|
+
|
||
|
|
+ float average = sAnticheatMgr->GetAverage(guid);
|
||
|
|
+ uint32 total_reports = sAnticheatMgr->GetTotalReports(guid);
|
||
|
|
+ uint32 speed_reports = sAnticheatMgr->GetTypeReports(guid,0);
|
||
|
|
+ uint32 fly_reports = sAnticheatMgr->GetTypeReports(guid,1);
|
||
|
|
+ uint32 jump_reports = sAnticheatMgr->GetTypeReports(guid,3);
|
||
|
|
+ uint32 waterwalk_reports = sAnticheatMgr->GetTypeReports(guid,2);
|
||
|
|
+ uint32 teleportplane_reports = sAnticheatMgr->GetTypeReports(guid,4);
|
||
|
|
+ uint32 climb_reports = sAnticheatMgr->GetTypeReports(guid,5);
|
||
|
|
+
|
||
|
|
+ handler->PSendSysMessage("Information about player %s",player->GetName().c_str());
|
||
|
|
+ handler->PSendSysMessage("Average: %f || Total Reports: %u ",average,total_reports);
|
||
|
|
+ handler->PSendSysMessage("Speed Reports: %u || Fly Reports: %u || Jump Reports: %u ",speed_reports,fly_reports,jump_reports);
|
||
|
|
+ handler->PSendSysMessage("Walk On Water Reports: %u || Teleport To Plane Reports: %u",waterwalk_reports,teleportplane_reports);
|
||
|
|
+ handler->PSendSysMessage("Climb Reports: %u", climb_reports);
|
||
|
|
+
|
||
|
|
+ return true;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ static bool HandleAntiCheatHandleCommand(ChatHandler* handler, bool enable)
|
||
|
|
+ {
|
||
|
|
+ if (enable)
|
||
|
|
+ {
|
||
|
|
+ sWorld->setBoolConfig(CONFIG_ANTICHEAT_ENABLE,true);
|
||
|
|
+ handler->SendSysMessage("The Anticheat System is now: Enabled!");
|
||
|
|
+ }
|
||
|
|
+ else
|
||
|
|
+ {
|
||
|
|
+ sWorld->setBoolConfig(CONFIG_ANTICHEAT_ENABLE,false);
|
||
|
|
+ handler->SendSysMessage("The Anticheat System is now: Disabled!");
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ return true;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ static bool HandleAntiCheatGlobalCommand(ChatHandler* handler)
|
||
|
|
+ {
|
||
|
|
+ if (!sWorld->getBoolConfig(CONFIG_ANTICHEAT_ENABLE))
|
||
|
|
+ {
|
||
|
|
+ handler->PSendSysMessage("The Anticheat System is disabled.");
|
||
|
|
+ return true;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ sAnticheatMgr->AnticheatGlobalCommand(handler);
|
||
|
|
+
|
||
|
|
+ return true;
|
||
|
|
+ }
|
||
|
|
+};
|
||
|
|
+
|
||
|
|
+void AddSC_anticheat_commandscript()
|
||
|
|
+{
|
||
|
|
+ new anticheat_commandscript();
|
||
|
|
+}
|
||
|
|
diff --git a/src/server/scripts/Commands/cs_script_loader.cpp b/src/server/scripts/Commands/cs_script_loader.cpp
|
||
|
|
index dd8fb48f22f..34e4e2bb846 100644
|
||
|
|
--- a/src/server/scripts/Commands/cs_script_loader.cpp
|
||
|
|
+++ b/src/server/scripts/Commands/cs_script_loader.cpp
|
||
|
|
@@ -15,10 +15,14 @@
|
||
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
*/
|
||
|
|
|
||
|
|
+#include "World.h"
|
||
|
|
+#include "AnticheatMgr.h"
|
||
|
|
+
|
||
|
|
// This is where scripts' loading functions should be declared:
|
||
|
|
void AddSC_account_commandscript();
|
||
|
|
void AddSC_achievement_commandscript();
|
||
|
|
void AddSC_ahbot_commandscript();
|
||
|
|
+void AddSC_anticheat_commandscript();
|
||
|
|
void AddSC_arena_commandscript();
|
||
|
|
void AddSC_ban_commandscript();
|
||
|
|
void AddSC_bf_commandscript();
|
||
|
|
@@ -64,6 +68,7 @@ void AddCommandsScripts()
|
||
|
|
AddSC_account_commandscript();
|
||
|
|
AddSC_achievement_commandscript();
|
||
|
|
AddSC_ahbot_commandscript();
|
||
|
|
+ AddSC_anticheat_commandscript();
|
||
|
|
AddSC_arena_commandscript();
|
||
|
|
AddSC_ban_commandscript();
|
||
|
|
AddSC_bf_commandscript();
|
||
|
|
@@ -101,4 +106,5 @@ void AddCommandsScripts()
|
||
|
|
AddSC_ticket_commandscript();
|
||
|
|
AddSC_titles_commandscript();
|
||
|
|
AddSC_wp_commandscript();
|
||
|
|
+ sAnticheatMgr->StartScripts();
|
||
|
|
}
|
||
|
|
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
|
||
|
|
index f475d0248e8..805c82f71c1 100644
|
||
|
|
--- a/src/server/worldserver/worldserver.conf.dist
|
||
|
|
+++ b/src/server/worldserver/worldserver.conf.dist
|
||
|
|
@@ -3293,6 +3293,40 @@ LevelReq.Auction = 1
|
||
|
|
|
||
|
|
LevelReq.Mail = 1
|
||
|
|
|
||
|
|
+#
|
||
|
|
+# Anticheat.Enable
|
||
|
|
+# Description: Enables or disables the Anticheat System functionality
|
||
|
|
+# Default: 1 - (Enabled)
|
||
|
|
+# 0 - (Disabled)
|
||
|
|
+
|
||
|
|
+Anticheat.Enable = 1
|
||
|
|
+
|
||
|
|
+# Anticheat.ReportsForIngameWarnings
|
||
|
|
+# Description: How many reports the player must have to notify to GameMasters ingame when he generates a new report.
|
||
|
|
+# Default: 70
|
||
|
|
+
|
||
|
|
+Anticheat.ReportsForIngameWarnings = 70
|
||
|
|
+
|
||
|
|
+# Anticheat.DetectionsEnabled
|
||
|
|
+# Description: It represents which detections are enabled.
|
||
|
|
+#
|
||
|
|
+# SPEED_HACK_DETECTION = 1
|
||
|
|
+# FLY_HACK_DETECTION = 2
|
||
|
|
+# WALK_WATER_HACK_DETECTION = 4
|
||
|
|
+# JUMP_HACK_DETECTION = 8
|
||
|
|
+# TELEPORT_PLANE_HACK_DETECTION = 16
|
||
|
|
+# CLIMB_HACK_DETECTION = 32
|
||
|
|
+#
|
||
|
|
+# Default: 31
|
||
|
|
+
|
||
|
|
+Anticheat.DetectionsEnabled = 31
|
||
|
|
+
|
||
|
|
+# Anticheat.MaxReportsForDailyReport
|
||
|
|
+# Description: How many reports must the player have to make a report that it is in DB for a day (not only during the player's session).
|
||
|
|
+# Default: 70
|
||
|
|
+
|
||
|
|
+Anticheat.MaxReportsForDailyReport = 70
|
||
|
|
+
|
||
|
|
#
|
||
|
|
# PlayerDump.DisallowPaths
|
||
|
|
# Description: Disallow using paths in PlayerDump output files
|