Player movement speed and node access distance checking

This commit is contained in:
Perttu Ahola 2011-11-26 14:03:56 +02:00
parent 8bd178c2e5
commit 1bfc3c1eb9
3 changed files with 79 additions and 13 deletions

@ -181,7 +181,9 @@ void Player::deSerialize(std::istream &is)
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env):
Player(env->getGameDef()),
ServerActiveObject(env, v3f(0,0,0))
ServerActiveObject(env, v3f(0,0,0)),
m_last_good_position(0,0,0),
m_last_good_position_age(0)
{
}
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,

@ -207,12 +207,22 @@ public:
/* ServerActiveObject interface */
u8 getType() const
{return ACTIVEOBJECT_TYPE_PLAYER;}
{return ACTIVEOBJECT_TYPE_PLAYER;}
virtual void setPos(v3f pos)
{ setPosition(pos); }
{
setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
m_last_good_position_age = 0;
}
virtual void moveTo(v3f pos, bool continuous)
{ setPosition(pos); }
{
setPosition(pos);
// Movement caused by this command is always valid
m_last_good_position = pos;
m_last_good_position_age = 0;
}
virtual std::string getDescription(){return getName();}
// Returns a reference
@ -222,7 +232,10 @@ public:
virtual bool addToInventory(InventoryItem *item);
virtual void setHP(s16 hp_);
virtual s16 getHP();
v3f m_last_good_position;
float m_last_good_position_age;
private:
};

@ -1325,10 +1325,41 @@ void Server::AsyncRunStep()
/*
Do background stuff
*/
/* Check player movements */
{
JMutexAutoLock lock(m_env_mutex);
JMutexAutoLock lock2(m_con_mutex);
//float player_max_speed = BS * 4.0; // Normal speed
float player_max_speed = BS * 4.0 * 5; // Fast speed
player_max_speed *= 1.5; // Tolerance
for(core::map<u16, RemoteClient*>::Iterator
i = m_clients.getIterator();
i.atEnd() == false; i++)
{
RemoteClient *client = i.getNode()->getValue();
ServerRemotePlayer *player =
(ServerRemotePlayer*)m_env->getPlayer(client->peer_id);
if(player==NULL)
continue;
player->m_last_good_position_age += dtime;
if(player->m_last_good_position_age > 1.0){
float age = player->m_last_good_position_age;
v3f diff = (player->getPosition() - player->m_last_good_position);
if(diff.getLength() <= age * player_max_speed){
player->m_last_good_position = player->getPosition();
} else {
player->setPosition(player->m_last_good_position);
SendMovePlayer(player);
}
player->m_last_good_position_age = 0;
}
}
}
/*
Transform liquids
*/
/* Transform liquids */
m_liquid_transform_timer += dtime;
if(m_liquid_transform_timer >= 1.00)
{
@ -2502,8 +2533,29 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
p_over.Z = readS16(&data[13]);
u16 item_i = readU16(&data[15]);
//TODO: Check that target is reasonably close
ServerRemotePlayer *srp = (ServerRemotePlayer*)player;
/*
Check that target is reasonably close
*/
{
v3f np_f = intToFloat(p_under, BS);
float max_d = BS * 8; // Just some large enough value
float d = srp->m_last_good_position.getDistanceFrom(np_f);
if(d > max_d){
actionstream<<"Player "<<player->getName()
<<" tried to access node from too far: "
<<"d="<<d<<", max_d="<<max_d
<<". ignoring."<<std::endl;
// Re-send block to revert change on client-side
RemoteClient *client = getClient(peer_id);
v3s16 blockpos = getNodeBlockPos(p_under);
client->SetBlockNotSent(blockpos);
// Do nothing else
return;
}
}
/*
0: start digging
*/
@ -2537,7 +2589,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
/*
Run script hook
*/
ServerRemotePlayer *srp = (ServerRemotePlayer*)player;
scriptapi_environment_on_punchnode(m_lua, p_under, n, srp);
} // action == 0
@ -2778,7 +2829,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
/*
Run script hook
*/
ServerRemotePlayer *srp = (ServerRemotePlayer*)player;
scriptapi_environment_on_dignode(m_lua, p_under, n, srp);
}
@ -2926,7 +2976,6 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
/*
Run script hook
*/
ServerRemotePlayer *srp = (ServerRemotePlayer*)player;
scriptapi_environment_on_placenode(m_lua, p_over, n, srp);
/*
@ -4354,6 +4403,8 @@ void Server::RespawnPlayer(Player *player)
if(!repositioned){
v3f pos = findSpawnPos(m_env->getServerMap());
player->setPosition(pos);
srp->m_last_good_position = pos;
srp->m_last_good_position_age = 0;
}
SendMovePlayer(player);
SendPlayerHP(player);