diff --git a/src/player.cpp b/src/player.cpp index 4dc7ff219..ce2e26945 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -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_, diff --git a/src/player.h b/src/player.h index e133c7afb..9476a9be3 100644 --- a/src/player.h +++ b/src/player.h @@ -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: }; diff --git a/src/server.cpp b/src/server.cpp index 78b7e79bd..21ac2b657 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -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::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 "<getName() + <<" tried to access node from too far: " + <<"d="<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);