1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-07-12 16:58:39 +00:00

Fix anticheat

This commit is contained in:
Perttu Ahola 2013-08-03 23:16:37 +03:00
parent bc5db9b027
commit 742614180c
5 changed files with 146 additions and 70 deletions

View file

@ -934,7 +934,6 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
m_peer_id(peer_id_),
m_inventory(NULL),
m_last_good_position(0,0,0),
m_last_good_position_age(0),
m_time_from_last_punch(0),
m_nocheat_dig_pos(32767, 32767, 32767),
m_nocheat_dig_time(0),
@ -1002,7 +1001,6 @@ void PlayerSAO::addedToEnvironment(u32 dtime_s)
m_player->setPlayerSAO(this);
m_player->peer_id = m_peer_id;
m_last_good_position = m_player->getPosition();
m_last_good_position_age = 0.0;
}
// Called before removing from environment
@ -1106,6 +1104,19 @@ void PlayerSAO::step(float dtime, bool send_recommended)
m_moved = true;
}
//dstream<<"PlayerSAO::step: dtime: "<<dtime<<std::endl;
// Set lag pool maximums based on estimated lag
const float LAG_POOL_MIN = 5.0;
float lag_pool_max = m_env->getMaxLagEstimate() * 2.0;
if(lag_pool_max < LAG_POOL_MIN)
lag_pool_max = LAG_POOL_MIN;
m_dig_pool.setMax(lag_pool_max);
m_move_pool.setMax(lag_pool_max);
// Increment cheat prevention timers
m_dig_pool.add(dtime);
m_move_pool.add(dtime);
m_time_from_last_punch += dtime;
m_nocheat_dig_time += dtime;
@ -1115,66 +1126,8 @@ void PlayerSAO::step(float dtime, bool send_recommended)
{
v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition();
m_last_good_position = pos;
m_last_good_position_age = 0;
m_player->setPosition(pos);
}
else
{
if(m_is_singleplayer || g_settings->getBool("disable_anticheat"))
{
m_last_good_position = m_player->getPosition();
m_last_good_position_age = 0;
}
else
{
/*
Check player movements
NOTE: Actually the server should handle player physics like the
client does and compare player's position to what is calculated
on our side. This is required when eg. players fly due to an
explosion. Altough a node-based alternative might be possible
too, and much more lightweight.
*/
float player_max_speed = 0;
float player_max_speed_up = 0;
if(m_privs.count("fast") != 0){
// Fast speed
player_max_speed = BS * 20;
player_max_speed_up = BS * 20;
} else {
// Normal speed
player_max_speed = BS * 4.0;
player_max_speed_up = BS * 4.0;
}
// Tolerance
player_max_speed *= 2.5;
player_max_speed_up *= 2.5;
m_last_good_position_age += dtime;
if(m_last_good_position_age >= 1.0){
float age = m_last_good_position_age;
v3f diff = (m_player->getPosition() - m_last_good_position);
float d_vert = diff.Y;
diff.Y = 0;
float d_horiz = diff.getLength();
/*infostream<<m_player->getName()<<"'s horizontal speed is "
<<(d_horiz/age)<<std::endl;*/
if(d_horiz <= age * player_max_speed &&
(d_vert < 0 || d_vert < age * player_max_speed_up)){
m_last_good_position = m_player->getPosition();
} else {
actionstream<<"Player "<<m_player->getName()
<<" moved too fast; resetting position"
<<std::endl;
m_player->setPosition(m_last_good_position);
m_moved = true;
}
m_last_good_position_age = 0;
}
}
}
if(send_recommended == false)
return;
@ -1267,7 +1220,6 @@ void PlayerSAO::setPos(v3f pos)
m_player->setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
m_last_good_position_age = 0;
// Force position change on client
m_moved = true;
}
@ -1279,7 +1231,6 @@ void PlayerSAO::moveTo(v3f pos, bool continuous)
m_player->setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
m_last_good_position_age = 0;
// Force position change on client
m_moved = true;
}
@ -1503,6 +1454,59 @@ std::string PlayerSAO::getPropertyPacket()
return gob_cmd_set_properties(m_prop);
}
void PlayerSAO::checkMovementCheat()
{
if(isAttached() || m_is_singleplayer ||
g_settings->getBool("disable_anticheat"))
{
m_last_good_position = m_player->getPosition();
}
else
{
/*
Check player movements
NOTE: Actually the server should handle player physics like the
client does and compare player's position to what is calculated
on our side. This is required when eg. players fly due to an
explosion. Altough a node-based alternative might be possible
too, and much more lightweight.
*/
float player_max_speed = 0;
float player_max_speed_up = 0;
if(m_privs.count("fast") != 0){
// Fast speed
player_max_speed = m_player->movement_speed_fast;
player_max_speed_up = m_player->movement_speed_fast;
} else {
// Normal speed
player_max_speed = m_player->movement_speed_walk;
player_max_speed_up = m_player->movement_speed_walk;
}
// Tolerance. With the lag pool we shouldn't need it.
//player_max_speed *= 2.5;
//player_max_speed_up *= 2.5;
v3f diff = (m_player->getPosition() - m_last_good_position);
float d_vert = diff.Y;
diff.Y = 0;
float d_horiz = diff.getLength();
float required_time = d_horiz/player_max_speed;
if(d_vert > 0 && d_vert/player_max_speed > required_time)
required_time = d_vert/player_max_speed;
if(m_move_pool.grab(required_time)){
m_last_good_position = m_player->getPosition();
} else {
actionstream<<"Player "<<m_player->getName()
<<" moved too fast; resetting position"
<<std::endl;
m_player->setPosition(m_last_good_position);
m_moved = true;
}
}
}
bool PlayerSAO::getCollisionBox(aabb3f *toset) {
//update collision box
*toset = m_player->getCollisionbox();
@ -1516,3 +1520,4 @@ bool PlayerSAO::getCollisionBox(aabb3f *toset) {
bool PlayerSAO::collideWithObjects(){
return true;
}