最初的mangos防加速外挂的C++代码--仅供参考使用
Index: game/MovementHandler.cpp===================================================================
--- game/MovementHandler.cpp (revision 81)
+++ game/MovementHandler.cpp (working copy)
@@ -30,6 +30,9 @@
#include "WaypointMovementGenerator.h"
#include "InstanceSaveMgr.h"
+/*Movement anticheat DEBUG defines */
+//#define MOVEMENT_ANTICHEAT_DEBUG true
+/*end Movement anticheate defines*/
void WorldSession::HandleMoveWorldportAckOpcode( WorldPacket & /*recv_data*/ )
{
sLog.outDebug( "WORLD: got MSG_MOVE_WORLDPORT_ACK." );
@@ -47,7 +50,8 @@
LogoutPlayer(false);
return;
}
-
+ //reset falltimer at teleport
+ GetPlayer()->m_anti_justteleported = 1;
// get the destination map entry, not the current one, this will fix homebind and reset greeting
MapEntry const* mEntry = sMapStore.LookupEntry(loc.mapid);
InstanceTemplate const* mInstance = objmgr.GetInstanceTemplate(loc.mapid);
@@ -179,8 +183,10 @@
uint32 opcode = recv_data.GetOpcode();
sLog.outDebug("WORLD: Recvd %s (%u, 0x%X) opcode", LookupOpcodeName(opcode), opcode, opcode);
- if(GetPlayer()->GetDontMove())
+ if(GetPlayer()->GetDontMove()){
+ GetPlayer()->m_anti_justteleported = 1;
return;
+ }
/* extract packet */
MovementInfo movementInfo;
@@ -202,48 +208,81 @@
{
// transports size limited
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
- if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50 )
+ if( movementInfo.t_x > 60 || movementInfo.t_y > 60 || movementInfo.t_x < -60 || movementInfo.t_y < -60 )
return;
if( !MaNGOS::IsValidMapCoord(movementInfo.x+movementInfo.t_x, movementInfo.y+movementInfo.t_y,
movementInfo.z+movementInfo.t_z, movementInfo.o+movementInfo.t_o) )
return;
-
- // if we boarded a transport, add us to it
- if (!GetPlayer()->m_transport)
+ if ((GetPlayer()->m_anti_transportGUID == 0) && (movementInfo.t_guid !=0))
{
- // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
- for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
+ // if we boarded a transport, add us to it
+ if (!GetPlayer()->m_transport)
{
- if ((*iter)->GetGUID() == movementInfo.t_guid)
+ // elevators also cause the client to send MOVEMENTFLAG_ONTRANSPORT - just unmount if the guid can be found in the transport list
+ for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter)
{
- GetPlayer()->m_transport = (*iter);
- (*iter)->AddPassenger(GetPlayer());
- break;
+ if ((*iter)->GetGUID() == movementInfo.t_guid)
+ {
+ GetPlayer()->m_transport = (*iter);
+ (*iter)->AddPassenger(GetPlayer());
+ break;
+ }
}
}
+ ///GetPlayer()->m_anti_transportGUID = GUID_LOPART(movementInfo.t_guid);
+ //Correct finding GO guid in DB (thanks to GriffonHeart)
+ GameObject *obj = HashMapHolder<GameObject>::Find(movementInfo.t_guid);
+ if(obj)
+ GetPlayer()->m_anti_transportGUID = obj->GetDBTableGUIDLow();
+ else
+ GetPlayer()->m_anti_transportGUID = GUID_LOPART(movementInfo.t_guid);
}
}
- else if (GetPlayer()->m_transport) // if we were on a transport, leave
+ else if (GetPlayer()->m_anti_transportGUID != 0)
{
- GetPlayer()->m_transport->RemovePassenger(GetPlayer());
- GetPlayer()->m_transport = NULL;
+ if (GetPlayer()->m_transport) // if we were on a transport, leave
+ {
+ GetPlayer()->m_transport->RemovePassenger(GetPlayer());
+ GetPlayer()->m_transport = NULL;
+ }
movementInfo.t_x = 0.0f;
movementInfo.t_y = 0.0f;
movementInfo.t_z = 0.0f;
movementInfo.t_o = 0.0f;
movementInfo.t_time = 0;
movementInfo.t_seat = -1;
+ GetPlayer()->m_anti_transportGUID = 0;
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
if (opcode == MSG_MOVE_FALL_LAND && !GetPlayer()->isInFlight())
{
+ GetPlayer()->m_anti_justjumped = 0;
// calculate total z distance of the fall
float z_diff = GetPlayer()->m_lastFallZ - movementInfo.z;
sLog.outDebug("zDiff = %f", z_diff);
Player *target = GetPlayer();
+ /* //movement anticheat "No Fall Damage"
+ if (target->m_anti_beginfalltime != 0)
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outDebug("Movement anticheat: alternate FallTime %d | client falltime %d | m_anti_justteleported = %d",movementInfo.time - GetPlayer()->m_anti_beginfalltime, movementInfo.fallTime, GetPlayer()->m_anti_justteleported );
+ #endif
+ if (target->m_anti_justteleported != 1){
+ uint32 alt_falltime = movementInfo.time - target->m_anti_beginfalltime;
+ movementInfo.fallTime = (alt_falltime < movementInfo.fallTime) ? movementInfo.fallTime : alt_falltime;
+ } else {
+ target->m_anti_justteleported = 0;
+ }
+ target->m_anti_beginfalltime = 0;
+ }
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("Movement anticheat: FallTime %d", movementInfo.fallTime);
+ #endif
+ //end movement anticheate */
+
//Players with low fall distance, Feather Fall or physical immunity (charges used) are ignored
// 14.57 can be calculated by resolving damageperc formular below to 0
if (z_diff >= 14.57f && !target->isDead() && !target->isGameMaster() &&
@@ -291,9 +330,244 @@
GetPlayer()->SetInWater( !GetPlayer()->IsInWater() || GetPlayer()->GetBaseMap()->IsUnderWater(movementInfo.x, movementInfo.y, movementInfo.z) );
}
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outBasic("%s newcoord: tm:%d ftm:%d | %f,%f,%fo(%f) [%X][%s]| transport: %f,%f,%fo(%f)",GetPlayer()->GetName(),movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o,movementInfo.flags, LookupOpcodeName(opcode),movementInfo.t_x,movementInfo.t_y,movementInfo.t_z,movementInfo.t_o);
+ sLog.outBasic("Transport: %d | tguid: %d - %d", GetPlayer()->m_anti_transportGUID, GUID_LOPART(movementInfo.t_guid), GUID_HIPART(movementInfo.t_guid));
+ #endif
/*----------------------*/
+ //---- anti-cheat features -->>>
+ bool check_passed = true;
+ //calc time deltas
+ int32 timedelta = 1500;
+ if (GetPlayer()->m_anti_lastmovetime !=0){
+ timedelta = movementInfo.time - GetPlayer()->m_anti_lastmovetime;
+ GetPlayer()->m_anti_deltamovetime += timedelta;
+ GetPlayer()->m_anti_lastmovetime = movementInfo.time;
+ } else {
+ GetPlayer()->m_anti_lastmovetime = movementInfo.time;
+ }
+
+ uint32 CurrentMStime=getMSTime();
+ uint32 CurrentMStimeDelta = 1500;
+ if (GetPlayer()->m_anti_lastMStime != 0){
+ CurrentMStimeDelta = CurrentMStime - GetPlayer()->m_anti_lastMStime;
+ GetPlayer()->m_anti_deltaMStime += CurrentMStimeDelta;
+ GetPlayer()->m_anti_lastMStime = CurrentMStime;
+ } else {
+ GetPlayer()->m_anti_lastMStime = CurrentMStime;
+ }
+
+ int32 sync_time = GetPlayer()->m_anti_deltamovetime - GetPlayer()->m_anti_deltaMStime;
+
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outBasic("dtime: %d, stime: %d || dMS: %d - dMV: %d || dt: %d", timedelta, CurrentMStime, GetPlayer()->m_anti_deltaMStime, GetPlayer()->m_anti_deltamovetime, sync_time);
+ #endif
+
+ uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination(); //check taxi flight
+ if ((GetPlayer()->m_anti_transportGUID == 0) && World::GetEnableMvAnticheat() && !curDest)
+ {
+ UnitMoveType move_type;
+
+ if (movementInfo.flags & MOVEMENTFLAG_FLYING) move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_FLIGHT_BACK : MOVE_FLIGHT;
+ else if (movementInfo.flags & MOVEMENTFLAG_SWIMMING) move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_SWIM_BACK : MOVE_SWIM;
+ else if (movementInfo.flags & MOVEMENTFLAG_WALK_MODE) move_type = MOVE_WALK;
+ //hmm... in first time after login player has MOVE_SWIMBACK instead MOVE_WALKBACK
+ else move_type = movementInfo.flags & MOVEMENTFLAG_BACKWARD ? MOVE_SWIM_BACK : MOVE_RUN;
+
+ float allowed_delta= 0;
+ float current_speed = GetPlayer()->GetSpeed(move_type);
+ float delta_x = GetPlayer()->GetPositionX() - movementInfo.x;
+ float delta_y = GetPlayer()->GetPositionY() - movementInfo.y;
+ float delta_z = GetPlayer()->GetPositionZ() - movementInfo.z;
+ float real_delta = delta_x * delta_x + delta_y * delta_y;
+ float tg_z = -99999; //tangens
+
+ int32 gmd = World::GetMistimingDelta();
+ if (sync_time > gmd || sync_time < -gmd){
+ timedelta = CurrentMStimeDelta;
+ GetPlayer()->m_anti_mistiming_count++;
+
+ sLog.outError("Movement anticheat: %s is mistaming exception. Exception count: %d, mistiming: %d ms ", GetPlayer()->GetName(), GetPlayer()->m_anti_mistiming_count, sync_time);
+ if (GetPlayer()->m_anti_mistiming_count > World::GetMistimingAlarms())
+ {
+ GetPlayer()->GetSession()->KickPlayer();
+ ///sLog.outError("Movement anticheat: %s is mistaming exception. Exception count: %d, mistiming: %d ms ", GetPlayer()->GetName(), GetPlayer()->m_anti_mistiming_count, sync_time);
+ }
+ check_passed = false;
+ }
+
+ if (timedelta < 0) {timedelta = 0;}
+ float time_delta = (timedelta < 1500) ? (float)timedelta/1000 : 1.5f; //normalize time - 1.5 second allowed for heavy loaded server
+
+ if (!(movementInfo.flags & (MOVEMENTFLAG_FLYING | MOVEMENTFLAG_SWIMMING)))
+ tg_z = (real_delta !=0) ? (delta_z*delta_z / real_delta) : -99999;
+
+ /* //antiOFF fall-damage, MOVEMENTFLAG_UNK4 seted by client if player try movement when falling and unset in this case the MOVEMENTFLAG_FALLING flag.
+ if (movementInfo.flags & (MOVEMENTFLAG_FALLING | MOVEMENTFLAG_UNK4 | MOVEMENTFLAG_JUMPING))
+ {
+ if (GetPlayer()->m_anti_beginfalltime == 0)
+ {
+ GetPlayer()->m_anti_beginfalltime = movementInfo.time;
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outDebug("Movement anticheat: begin fall-time %d",GetPlayer()->m_anti_beginfalltime);
+ #endif
+ }
+ } else {
+ if (GetPlayer()->m_anti_beginfalltime != 0)
+ {
+ GetPlayer()->m_anti_beginfalltime = 0; // reset timer if we landed without MSG_MOVE_FALL_LAND opcode
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outDebug("Movement anticheat: end fall-time %d",GetPlayer()->m_anti_beginfalltime);
+ #endif
+ }
+ }
+ */
+
+ if (current_speed < GetPlayer()->m_anti_last_hspeed)
+ {
+ allowed_delta = GetPlayer()->m_anti_last_hspeed;
+ if (GetPlayer()->m_anti_lastspeed_changetime == 0 )
+ GetPlayer()->m_anti_lastspeed_changetime = movementInfo.time + (uint32)floor(((GetPlayer()->m_anti_last_hspeed / current_speed) * 1000)) + 100; //100ms above for random fluctuating =)))
+ } else allowed_delta = current_speed;
+ allowed_delta = allowed_delta * time_delta;
+ allowed_delta = allowed_delta * allowed_delta + 2;
+
+ // static char const* move_type_name[MAX_MOVE_TYPE] = { "Walk", "Run", "Walkback", "Swim", "Swimback", "Turn", "Fly", "Flyback" };
+ // sLog.outBasic("%s newcoord: tm:%d ftm:%d | %f,%f,%fo(%f) [%X][%s]$%s",GetPlayer()->GetName(),movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o,MovementFlags, LookupOpcodeName(opcode),move_type_name[move_type]);
+ // sLog.outBasic("%f",tg_z);
+
+ if (opcode == MSG_MOVE_JUMP && !GetPlayer()->IsInWater()){
+ if (GetPlayer()->m_anti_justjumped >= 1){
+ ///GetPlayer()->m_anti_justjumped = 0;
+ check_passed = false; //don't process new jump packet
+ } else {
+ GetPlayer()->m_anti_justjumped += 1;
+ }
+ } else if (GetPlayer()->IsInWater()) {
+ GetPlayer()->m_anti_justjumped = 0;
+ }
+ if ((real_delta > allowed_delta)) //&& (delta_z < 1)
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("Movement anticheat: %s is speed exception. {real_delta=%f allowed_delta=%f | current_speed=%f preview_speed=%f time=%f}(%f %f %f %d)[%s]",GetPlayer()->GetName(),real_delta, allowed_delta, current_speed, GetPlayer()->m_anti_last_hspeed,time_delta,GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(), GetPlayer()->GetMapId(),LookupOpcodeName(opcode));
+ #endif
+ check_passed = false;
+ }
+ if ((real_delta>4900.0f) && !(real_delta < allowed_delta))
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("Movement anticheat: %s is teleport exception. {real_delta=%f allowed_delta=%f | current_speed=%f preview_speed=%f time=%f}(%f %f %f %d)",GetPlayer()->GetName(),real_delta, allowed_delta, current_speed, GetPlayer()->m_anti_last_hspeed,time_delta,GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(), GetPlayer()->GetMapId());
+ #endif
+ check_passed = false;
+ }
+ if (movementInfo.time>GetPlayer()->m_anti_lastspeed_changetime)
+ {
+ GetPlayer()->m_anti_last_hspeed = current_speed; // store current speed
+ GetPlayer()->m_anti_last_vspeed = -3.2f;
+ if (GetPlayer()->m_anti_lastspeed_changetime != 0) GetPlayer()->m_anti_lastspeed_changetime = 0;
+ }
+
+ if ((tg_z > 1.56f) && (delta_z < GetPlayer()->m_anti_last_vspeed))
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("Movement anticheat: %s is mountain exception. {tg_z=%f} (%f %f %f %d)",GetPlayer()->GetName(),tg_z, GetPlayer()->GetPositionX(),GetPlayer()->GetPositionY(),GetPlayer()->GetPositionZ(), GetPlayer()->GetMapId());
+ #endif
+ check_passed = false;
+ }
+ if (((movementInfo.flags & (MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_FLYING2)) != 0) && !GetPlayer()->isGameMaster() && !(GetPlayer()->HasAuraType(SPELL_AURA_FLY) || GetPlayer()->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED)))
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("Movement anticheat: %s is fly cheater. {SPELL_AURA_FLY=[%X]} {SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED=[%X]} {SPELL_AURA_MOD_SPEED_FLIGHT=[%X]} {SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS=[%X]} {SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK=[%X]}",
+ GetPlayer()->GetName(),
+ GetPlayer()->HasAuraType(SPELL_AURA_FLY), GetPlayer()->HasAuraType(SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED),
+ GetPlayer()->HasAuraType(SPELL_AURA_MOD_SPEED_FLIGHT), GetPlayer()->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_ALWAYS),
+ GetPlayer()->HasAuraType(SPELL_AURA_MOD_FLIGHT_SPEED_NOT_STACK));
+ #endif
+ check_passed = false;
+ }
+ if (((movementInfo.flags & MOVEMENTFLAG_WATERWALKING) != 0) && !GetPlayer()->isGameMaster() && !(GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK) | GetPlayer()->HasAuraType(SPELL_AURA_GHOST)))
+ {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outError("Movement anticheat: %s is water-walk exception. [%X]{SPELL_AURA_WATER_WALK=[%X]}", GetPlayer()->GetName(), movementInfo.flags, GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK));
+ #endif
+ check_passed = false;
+ }
+ if(movementInfo.z < 0.0001f && movementInfo.z > -0.0001f && ((movementInfo.flags & (MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_CAN_FLY | MOVEMENTFLAG_FLYING | MOVEMENTFLAG_FLYING2)) == 0) && !GetPlayer()->isGameMaster() )
+ {
+ // Prevent using TeleportToPlan.
+ Map *map = GetPlayer()->GetMap();
+ if (map){
+ float plane_z = map->GetHeight(movementInfo.x, movementInfo.y, MAX_HEIGHT) - movementInfo.z;
+ plane_z = (plane_z < -500.0f) ? 0 : plane_z; //check holes in heigth map
+ if(plane_z > 0.1f || plane_z < -0.1f)
+ {
+ GetPlayer()->m_anti_teletoplane_count++;
+ check_passed = false;
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outDebug("Movement anticheat: %s is teleport to plan exception. plane_z: %f ", GetPlayer()->GetName(), plane_z);
+ #endif
+ if (GetPlayer()->m_anti_teletoplane_count > World::GetTeleportToPlaneAlarms())
+ {
+ GetPlayer()->GetSession()->KickPlayer();
+ sLog.outError("Movement anticheat: %s is teleport to plan exception. Exception count: %d ", GetPlayer()->GetName(), GetPlayer()->m_anti_teletoplane_count);
+ }
+ }
+ }
+ } else {
+ if (GetPlayer()->m_anti_teletoplane_count !=0)
+ GetPlayer()->m_anti_teletoplane_count = 0;
+ }
+ } else if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) {
+ //antiwrap =)
+ if (GetPlayer()->m_transport)
+ {
+ float trans_rad = movementInfo.t_x*movementInfo.t_x + movementInfo.t_y*movementInfo.t_y + movementInfo.t_z*movementInfo.t_z;
+ if (trans_rad > 3600.0f)
+ check_passed = false;
+ } else {
+ if (GameObjectData const* go_data = objmgr.GetGOData(GetPlayer()->m_anti_transportGUID))
+ {
+ float delta_gox = go_data->posX - movementInfo.x;
+ float delta_goy = go_data->posY - movementInfo.y;
+ float delta_goz = go_data->posZ - movementInfo.z;
+ int mapid = go_data->mapid;
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outDebug("Movement anticheat: %s on some transport. xyzo: %f,%f,%f", GetPlayer()->GetName(), go_data->posX,go_data->posY,go_data->posZ);
+ #endif
+ if (GetPlayer()->GetMapId() != mapid){
+ check_passed = false;
+ } else if (mapid !=369) {
+ float delta_go = delta_gox*delta_gox + delta_goy*delta_goy;
+ if (delta_go > 3600.0f)
+ check_passed = false;
+ }
+
+ } else {
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outDebug("Movement anticheat: %s on undefined transport.", GetPlayer()->GetName());
+ #endif
+ check_passed = false;
+ }
+ }
+ if (!check_passed){
+ if (GetPlayer()->m_transport)
+ {
+ GetPlayer()->m_transport->RemovePassenger(GetPlayer());
+ GetPlayer()->m_transport = NULL;
+ }
+ movementInfo.t_x = 0.0f;
+ movementInfo.t_y = 0.0f;
+ movementInfo.t_z = 0.0f;
+ movementInfo.t_o = 0.0f;
+ movementInfo.t_time = 0;
+ GetPlayer()->m_anti_transportGUID = 0;
+ }
+ }
/* process position-change */
+ if (check_passed)
+ {
+
Unit *mover = _player->m_mover;
recv_data.put<uint32>(6, getMSTime()); // fix time, offset flags(4) + unk(2)
WorldPacket data(recv_data.GetOpcode(), (mover->GetPackGUID().size()+recv_data.size()));
@@ -326,8 +600,8 @@
if (GetPlayer()->m_lastFallTime >= movementInfo.fallTime || GetPlayer()->m_lastFallZ <=movementInfo.z || recv_data.GetOpcode() == MSG_MOVE_FALL_LAND)
GetPlayer()->SetFallInformation(movementInfo.fallTime, movementInfo.z);
- if(GetPlayer()->isMovingOrTurning())
- GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
+ if(GetPlayer()->isMovingOrTurning())
+ GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
if(movementInfo.z < -500.0f)
{
@@ -355,6 +629,20 @@
GetPlayer()->RepopAtGraveyard();
}
}
+
+ if (GetPlayer()->m_anti_alarmcount > 0){
+ sLog.outError("Movement anticheat: %s produce %d anticheat alarms",GetPlayer()->GetName(),GetPlayer()->m_anti_alarmcount);
+ GetPlayer()->m_anti_alarmcount = 0;
+ }
+ } else {
+ GetPlayer()->m_anti_alarmcount++;
+ WorldPacket data;
+ GetPlayer()->SetUnitMovementFlags(0);
+ GetPlayer()->BuildTeleportAckMsg(&data, GetPlayer()->GetPositionX(), GetPlayer()->GetPositionY(), GetPlayer()->GetPositionZ(), GetPlayer()->GetOrientation());
+ GetPlayer()->GetSession()->SendPacket(&data);
+ GetPlayer()->BuildHeartBeatMsg(&data);
+ GetPlayer()->SendMessageToSet(&data, true);
+ }
}
void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recv_data)
@@ -507,34 +795,31 @@
GetPlayer()->SendMessageToSet(&data, false);
}
-void WorldSession::HandleMoveKnockBackAck( WorldPacket & /*recv_data*/ )
+void WorldSession::HandleMoveKnockBackAck( WorldPacket & recv_data )
{
// CHECK_PACKET_SIZE(recv_data,?);
sLog.outDebug("CMSG_MOVE_KNOCK_BACK_ACK");
// Currently not used but maybe use later for recheck final player position
// (must be at call same as into "recv_data >> x >> y >> z >> orientation;"
- /*
- uint32 flags, time;
- float x, y, z, orientation;
- uint64 guid;
- uint32 sequence;
- uint32 ukn1;
- float xdirection,ydirection,hspeed,vspeed;
+ /* extract packet */
+ MovementInfo movementInfo;
+ uint32 unk1,unk2,unk3;
+ recv_data >> unk1 >> unk2 >> unk3;
+ ReadMovementInfo(recv_data, &movementInfo);
- recv_data >> guid;
- recv_data >> sequence;
- recv_data >> flags >> time;
- recv_data >> x >> y >> z >> orientation;
- recv_data >> ukn1; //unknown
- recv_data >> vspeed >> xdirection >> ydirection >> hspeed;
+ //Save movement flags
+ _player->SetUnitMovementFlags(movementInfo.flags);
- // skip not personal message;
- if(GetPlayer()->GetGUID()!=guid)
- return;
+ #ifdef MOVEMENT_ANTICHEAT_DEBUG
+ sLog.outBasic("%s CMSG_MOVE_KNOCK_BACK_ACK: tm:%d ftm:%d | %f,%f,%fo(%f) [%X]",GetPlayer()->GetName(),movementInfo.time,movementInfo.fallTime,movementInfo.x,movementInfo.y,movementInfo.z,movementInfo.o,movementInfo.flags);
+ sLog.outBasic("%s CMSG_MOVE_KNOCK_BACK_ACK additional: vspeed:%f, hspeed:%f",GetPlayer()->GetName(), movementInfo.j_unk, movementInfo.j_xyspeed);
+ #endif
- // check code
- */
+ _player->m_movementInfo = movementInfo;
+ _player->m_anti_last_hspeed = movementInfo.j_xyspeed;
+ _player->m_anti_last_vspeed = movementInfo.j_unk < 3.2f ? movementInfo.j_unk - 1.0f : 3.2f;
+ _player->m_anti_lastspeed_changetime = movementInfo.time + 1750;
}
void WorldSession::HandleMoveHoverAck( WorldPacket& /*recv_data*/ )
Index: game/Player.cpp
===================================================================
--- game/Player.cpp (revision 81)
+++ game/Player.cpp (working copy)
@@ -398,7 +398,24 @@
m_rest_bonus=0;
rest_type=REST_TYPE_NO;
////////////////////Rest System/////////////////////
+ //movement anticheat
+ m_anti_lastmovetime = 0; //last movement time
+ m_anti_transportGUID = 0; //current transport GUID
+ m_anti_last_hspeed = 7.0f; //horizontal speed, default RUN speed
+ m_anti_lastspeed_changetime = 0; //last speed change time
+ m_anti_last_vspeed = -2.0f; //vertical speed, default max jump height
+ m_anti_beginfalltime = 0; //alternative falling begin time
+ m_anti_justteleported = 0; //seted when player was teleported
+ m_anti_teletoplane_count = 0;//Teleport To Plane alarm counter
+ m_anti_lastMStime = 0; //last movement server time
+ m_anti_deltamovetime = 0;
+ m_anti_deltaMStime = 0;
+ m_anti_mistiming_count = 0;
+
+ m_anti_justjumped = 0; //jump already began
+ m_anti_alarmcount = 0; //alarm counter
+ /////////////////////////////////
m_mailsLoaded = false;
m_mailsUpdated = false;
unReadMails = 0;
@@ -1493,7 +1510,8 @@
sLog.outError("TeleportTo: invalid map %d or absent instance template.", mapid);
return false;
}
-
+ //reset falltimer at teleport
+ m_anti_justteleported = 1;
// preparing unsummon pet if lost (we must get pet before teleportation or will not find it later)
Pet* pet = GetPet();
Index: game/Player.h
===================================================================
--- game/Player.h (revision 81)
+++ game/Player.h (working copy)
@@ -2348,7 +2348,23 @@
float m_rest_bonus;
RestType rest_type;
////////////////////Rest System/////////////////////
+ //movement anticheat
+ uint32 m_anti_lastmovetime; //last movement time
+ uint64 m_anti_transportGUID; //current transport GUID
+ float m_anti_last_hspeed; //horizontal speed, default RUN speed
+ uint32 m_anti_lastspeed_changetime; //last speed change time
+ float m_anti_last_vspeed; //vertical speed, default max jump height
+ uint32 m_anti_beginfalltime; //alternative falling begin time
+ uint32 m_anti_justteleported; //seted when player was teleported
+ uint32 m_anti_teletoplane_count;//Teleport To Plane alarm counter
+ uint32 m_anti_lastMStime; //last movement server time
+ uint32 m_anti_deltamovetime; //client side session time
+ uint32 m_anti_deltaMStime; //server side session time
+ uint32 m_anti_mistiming_count; //mistiming counts before kick
+
+ uint32 m_anti_justjumped; //Jump already began, anti air jump check
+ uint64 m_anti_alarmcount; //alarm counter
// Transports
Transport * m_transport;
Index: game/TaxiHandler.cpp
===================================================================
--- game/TaxiHandler.cpp (revision 81)
+++ game/TaxiHandler.cpp (working copy)
@@ -192,7 +192,7 @@
GetPlayer()->ActivateTaxiPathTo(nodes, 0, npc);
}
-void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& /*recv_data*/)
+void WorldSession::HandleTaxiNextDestinationOpcode(WorldPacket& recv_data)
{
sLog.outDebug( "WORLD: Received CMSG_MOVE_SPLINE_DONE" );
@@ -200,12 +200,79 @@
// 1) end taxi path in far (multi-node) flight
// 2) switch from one map to other in case multim-map taxi path
// we need proccess only (1)
+
+ //movement anticheat code
+ /* extract packet */
+ MovementInfo movementInfo;
+ ReadMovementInfo(recv_data, &movementInfo);
+ //<<< end movement anticheat
+
uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination();
if(!curDest)
+ {
+ //movement anticheat code
+ GetPlayer()->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+ GetPlayer()->m_movementInfo = movementInfo;
+ GetPlayer()->SetUnitMovementFlags(movementInfo.flags);
+
+ int32 timedelta = 0;
+ if (GetPlayer()->m_anti_lastmovetime !=0){
+ timedelta = movementInfo.time - GetPlayer()->m_anti_lastmovetime;
+ GetPlayer()->m_anti_deltamovetime += timedelta;
+ GetPlayer()->m_anti_lastmovetime = movementInfo.time;
+ } else {
+ GetPlayer()->m_anti_lastmovetime = movementInfo.time;
+ }
+
+ uint32 CurTime=getMSTime();
+ uint32 CurTimeDelta = 0;
+ if (GetPlayer()->m_anti_lastMStime != 0){
+ CurTimeDelta = CurTime - GetPlayer()->m_anti_lastMStime;
+ GetPlayer()->m_anti_deltaMStime += CurTimeDelta;
+ GetPlayer()->m_anti_lastMStime = CurTime;
+ } else {
+ GetPlayer()->m_anti_lastMStime = CurTime;
+ }
+
+ //sLog.outBasic("dtime: %d, stime: %d || dMS: %d - dMV: %d || dt: %d", timedelta, CurTime, GetPlayer()->m_anti_deltaMStime, GetPlayer()->m_anti_deltamovetime);
+
+ GetPlayer()->m_anti_justteleported = 1;
+ //<<< end movement anticheat
return;
+ }
TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
+ if(curDestNode && curDestNode->map_id == GetPlayer()->GetMapId())
+ {
+ while(GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType()==FLIGHT_MOTION_TYPE)
+ GetPlayer()->GetMotionMaster()->MovementExpired(false);
+ }
+
+ //movement anticheat code
+ GetPlayer()->SetPosition(movementInfo.x, movementInfo.y, movementInfo.z, movementInfo.o);
+ GetPlayer()->m_movementInfo = movementInfo;
+ GetPlayer()->SetUnitMovementFlags(movementInfo.flags);
+ int32 timedelta = 0;
+ if (GetPlayer()->m_anti_lastmovetime !=0){
+ timedelta = movementInfo.time - GetPlayer()->m_anti_lastmovetime;
+ GetPlayer()->m_anti_deltamovetime += timedelta;
+ GetPlayer()->m_anti_lastmovetime = movementInfo.time;
+ } else {
+ GetPlayer()->m_anti_lastmovetime = movementInfo.time;
+ }
+
+ uint32 CurTime=getMSTime();
+ uint32 CurTimeDelta = 0;
+ if (GetPlayer()->m_anti_lastMStime != 0){
+ CurTimeDelta = CurTime - GetPlayer()->m_anti_lastMStime;
+ GetPlayer()->m_anti_deltaMStime += CurTimeDelta;
+ GetPlayer()->m_anti_lastMStime = CurTime;
+ } else {
+ GetPlayer()->m_anti_lastMStime = CurTime;
+ }
+ //<<< end movement anticheat
+
// far teleport case
if(curDestNode && curDestNode->map_id != GetPlayer()->GetMapId())
{
Index: game/World.cpp
===================================================================
--- game/World.cpp (revision 81)
+++ game/World.cpp (working copy)
@@ -72,7 +72,11 @@
float World::m_MaxVisibleDistanceInFlight = DEFAULT_VISIBILITY_DISTANCE;
float World::m_VisibleUnitGreyDistance = 0;
float World::m_VisibleObjectGreyDistance = 0;
-
+//movement anticheat
+bool World::m_EnableMvAnticheat = true;
+uint32 World::m_TeleportToPlaneAlarms = 50;
+uint32 World::m_MistimingAlarms = 20;
+uint32 World::m_MistimingDelta = 2000;
// ServerMessages.dbc
enum ServerMessageType
{
@@ -537,7 +541,35 @@
sLog.outError("DurabilityLossChance.Block (%f) must be >=0. Using 0.0 instead.",rate_values[RATE_DURABILITY_LOSS_BLOCK]);
rate_values[RATE_DURABILITY_LOSS_BLOCK] = 0.0f;
}
-
+ // movement anticheat
+ m_EnableMvAnticheat = sConfig.GetBoolDefault("Anticheat.Movement.Enable",true);
+ m_TeleportToPlaneAlarms = sConfig.GetIntDefault("Anticheat.Movement.TeleportToPlaneAlarms", 50);
+ if (m_TeleportToPlaneAlarms<20){
+ sLog.outError("Anticheat.Movement.TeleportToPlaneAlarms (%d) must be >=20. Using 20 instead.",m_TeleportToPlaneAlarms);
+ m_TeleportToPlaneAlarms = 20;
+ }
+ if (m_TeleportToPlaneAlarms>100){
+ sLog.outError("Anticheat.Movement.TeleportToPlaneAlarms (%d) must be <=100. Using 100 instead.",m_TeleportToPlaneAlarms);
+ m_TeleportToPlaneAlarms = 100;
+ }
+ m_MistimingDelta = sConfig.GetIntDefault("Anticheat.Movement.MistimingDelta",2000);
+ if (m_MistimingDelta<1000){
+ sLog.outError("Anticheat.Movement.m_MistimingDelta (%d) must be >=1000ms. Using 1000 instead.",m_TeleportToPlaneAlarms);
+ m_MistimingDelta = 1000;
+ }
+ if (m_MistimingDelta>10000){
+ sLog.outError("Anticheat.Movement.m_MistimingDelta (%d) must be <=10000ms. Using 10000 instead.",m_TeleportToPlaneAlarms);
+ m_MistimingDelta = 10000;
+ }
+ m_MistimingAlarms = sConfig.GetIntDefault("Anticheat.Movement.MistimingAlarms",20);
+ if (m_MistimingAlarms<10) {
+ sLog.outError("Anticheat.Movement.MistimingAlarms (%d) must be >=20. Using 10 instead.",m_TeleportToPlaneAlarms);
+ m_MistimingAlarms = 10;
+ }
+ if (m_MistimingAlarms>50){
+ sLog.outError("Anticheat.Movement.m_MistimingAlarms (%d) must be <=50. Using 50 instead.",m_TeleportToPlaneAlarms);
+ m_MistimingAlarms = 50;
+ }
///- Read other configuration items from the config file
m_configs[CONFIG_COMPRESSION] = sConfig.GetIntDefault("Compression", 1);
Index: game/World.h
===================================================================
--- game/World.h (revision 81)
+++ game/World.h (working copy)
@@ -473,7 +473,12 @@
static float GetMaxVisibleDistanceInFlight() { return m_MaxVisibleDistanceInFlight; }
static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; }
static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; }
-
+ //movement anticheat
+ static bool GetEnableMvAnticheat() {return m_EnableMvAnticheat;}
+ static uint32 GetTeleportToPlaneAlarms() {return m_TeleportToPlaneAlarms;}
+ static uint32 GetMistimingDelta() {return m_MistimingDelta;}
+ static uint32 GetMistimingAlarms() {return m_MistimingAlarms;}
+ //<<< end movement anticheat
void ProcessCliCommands();
void QueueCliCommand( CliCommandHolder::Print* zprintf, char const* input ) { cliCmdQueue.add(new CliCommandHolder(input, zprintf)); }
@@ -538,7 +543,11 @@
static float m_MaxVisibleDistanceInFlight;
static float m_VisibleUnitGreyDistance;
static float m_VisibleObjectGreyDistance;
-
+ //movement anticheat enable flag
+ static bool m_EnableMvAnticheat;
+ static uint32 m_TeleportToPlaneAlarms;
+ static uint32 m_MistimingDelta;
+ static uint32 m_MistimingAlarms;
// CLI command holder to be thread safe
ZThread::LockedQueue<CliCommandHolder*, ZThread::FastMutex> cliCmdQueue;
SqlResultQueue *m_resultQueue;
Index: mangosd/mangosd.conf.dist.in
===================================================================
--- mangosd/mangosd.conf.dist.in (revision 81)
+++ mangosd/mangosd.conf.dist.in (working copy)
@@ -1208,6 +1208,30 @@
Network.TcpNodelay = 1
###################################################################################################################
+# MOVEMENT ANTICHEAT
+#
+# Anticheat.Movement.Enable
+# Enable Movement Anticheat
+# Default: 1 - on
+# 0 - off
+#
+# Anticheat.Movement.TeleportToPlaneAlarms
+# maximum alarms before player will be kicked (default 50, allowed 20 - 100)
+#
+# Anticheat.Movement.MistimingDelta
+# mistiming intelval between client and serverside (default 2000 ms, allowed 1000 - 10000 ms)
+#
+# Anticheat.Movement.MistimingAlarms
+# mistiming alarms before player will be kicked (default 20, allowed 10 - 50)
+#
+###################################################################################################################
+
+Anticheat.Movement.Enable = 1
+Anticheat.Movement.TeleportToPlaneAlarms = 50
+Anticheat.Movement.MistimingDelta = 2000
+Anticheat.Movement.MistimingAlarms = 20
+
+###################################################################################################################
# CONSOLE AND REMOTE ACCESS
#
# Console.Enable
|