if (playerspeed.getLength() > 1.0f * BS)
playerspeeddir = playerspeed / playerspeed.getLength();
// Predict to next block
- v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
+ v3f playerpos_predicted = playerpos + playerspeeddir * (MAP_BLOCKSIZE * BS);
v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
// Camera position and direction
v3f camera_pos = sao->getEyePosition();
v3f camera_dir = v3f(0,0,1);
- camera_dir.rotateYZBy(sao->getPitch());
- camera_dir.rotateXZBy(sao->getYaw());
+ camera_dir.rotateYZBy(sao->getLookPitch());
+ camera_dir.rotateXZBy(sao->getRotation().Y);
/*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
<<camera_dir.Z<<")"<<std::endl;*/
*/
s32 new_nearest_unsent_d = -1;
- // get view range and camera fov from the client
+ // Get view range and camera fov (radians) from the client
s16 wanted_range = sao->getWantedRange() + 1;
float camera_fov = sao->getFov();
- const s16 full_d_max = std::min(m_max_send_distance, wanted_range);
- const s16 d_opt = std::min(m_block_optimize_distance, wanted_range);
+ // Distrust client-sent FOV and get server-set player object property
+ // zoom FOV (degrees) as a check to avoid hacked clients using FOV to load
+ // distant world.
+ // (zoom is disabled by value 0)
+ float prop_zoom_fov = sao->getZoomFOV() < 0.001f ?
+ 0.0f :
+ std::max(camera_fov, sao->getZoomFOV() * core::DEGTORAD);
+
+ const s16 full_d_max = std::min(adjustDist(m_max_send_distance, prop_zoom_fov),
+ wanted_range);
+ const s16 d_opt = std::min(adjustDist(m_block_optimize_distance, prop_zoom_fov),
+ wanted_range);
const s16 d_blocks_in_sight = full_d_max * BS * MAP_BLOCKSIZE;
- //infostream << "Fov from client " << camera_fov << " full_d_max " << full_d_max << std::endl;
s16 d_max = full_d_max;
- s16 d_max_gen = std::min(m_max_gen_distance, wanted_range);
+ s16 d_max_gen = std::min(adjustDist(m_max_gen_distance, prop_zoom_fov),
+ wanted_range);
- // Don't loop very much at a time
- s16 max_d_increment_at_time = 2;
+ // Don't loop very much at a time, adjust with distance,
+ // do more work per RTT with greater distances.
+ s16 max_d_increment_at_time = full_d_max / 9 + 1;
if (d_max > d_start + max_d_increment_at_time)
d_max = d_start + max_d_increment_at_time;
+ // cos(angle between velocity and camera) * |velocity|
+ // Limit to 0.0f in case player moves backwards.
+ f32 dot = rangelim(camera_dir.dotProduct(playerspeed), 0.0f, 300.0f);
+
+ // Reduce the field of view when a player moves and looks forward.
+ // limit max fov effect to 50%, 60% at 20n/s fly speed
+ camera_fov = camera_fov / (1 + dot / 300.0f);
+
s32 nearest_emerged_d = -1;
s32 nearest_emergefull_d = -1;
s32 nearest_sent_d = -1;
differs from day-time mesh.
*/
if (d >= d_opt) {
- if (!block->getDayNightDiff())
+ if (!block->getIsUnderground() && !block->getDayNightDiff())
continue;
}
Delete clients
*/
{
- MutexAutoLock clientslock(m_clients_mutex);
+ RecursiveMutexAutoLock clientslock(m_clients_mutex);
for (auto &client_it : m_clients) {
// Delete client
std::vector<session_t> ClientInterface::getClientIDs(ClientState min_state)
{
std::vector<session_t> reply;
- MutexAutoLock clientslock(m_clients_mutex);
+ RecursiveMutexAutoLock clientslock(m_clients_mutex);
for (const auto &m_client : m_clients) {
if (m_client.second->getState() >= min_state)
return reply;
}
+void ClientInterface::markBlockposAsNotSent(const v3s16 &pos)
+{
+ RecursiveMutexAutoLock clientslock(m_clients_mutex);
+ for (const auto &client : m_clients) {
+ if (client.second->getState() >= CS_Active)
+ client.second->SetBlockNotSent(pos);
+ }
+}
+
/**
* Verify if user limit was reached.
* User limit count all clients from HelloSent state (MT protocol user) to Active state
infostream << "* " << player->getName() << "\t";
{
- MutexAutoLock clientslock(m_clients_mutex);
+ RecursiveMutexAutoLock clientslock(m_clients_mutex);
RemoteClient* client = lockedGetClientNoEx(i);
if (client)
client->PrintInfo(infostream);
void ClientInterface::sendToAll(NetworkPacket *pkt)
{
- MutexAutoLock clientslock(m_clients_mutex);
+ RecursiveMutexAutoLock clientslock(m_clients_mutex);
for (auto &client_it : m_clients) {
RemoteClient *client = client_it.second;
void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt,
u16 min_proto_ver)
{
- MutexAutoLock clientslock(m_clients_mutex);
+ RecursiveMutexAutoLock clientslock(m_clients_mutex);
for (auto &client_it : m_clients) {
RemoteClient *client = client_it.second;
NetworkPacket *pkt_to_send = nullptr;
RemoteClient* ClientInterface::getClientNoEx(session_t peer_id, ClientState state_min)
{
- MutexAutoLock clientslock(m_clients_mutex);
+ RecursiveMutexAutoLock clientslock(m_clients_mutex);
RemoteClientMap::const_iterator n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then.
ClientState ClientInterface::getClientState(session_t peer_id)
{
- MutexAutoLock clientslock(m_clients_mutex);
+ RecursiveMutexAutoLock clientslock(m_clients_mutex);
RemoteClientMap::const_iterator n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then.
void ClientInterface::setPlayerName(session_t peer_id, const std::string &name)
{
- MutexAutoLock clientslock(m_clients_mutex);
+ RecursiveMutexAutoLock clientslock(m_clients_mutex);
RemoteClientMap::iterator n = m_clients.find(peer_id);
// The client may not exist; clients are immediately removed if their
// access is denied, and this event occurs later then.
void ClientInterface::DeleteClient(session_t peer_id)
{
- MutexAutoLock conlock(m_clients_mutex);
+ RecursiveMutexAutoLock conlock(m_clients_mutex);
// Error check
RemoteClientMap::iterator n = m_clients.find(peer_id);
void ClientInterface::CreateClient(session_t peer_id)
{
- MutexAutoLock conlock(m_clients_mutex);
+ RecursiveMutexAutoLock conlock(m_clients_mutex);
// Error check
RemoteClientMap::iterator n = m_clients.find(peer_id);
void ClientInterface::event(session_t peer_id, ClientStateEvent event)
{
{
- MutexAutoLock clientlock(m_clients_mutex);
+ RecursiveMutexAutoLock clientlock(m_clients_mutex);
// Error check
RemoteClientMap::iterator n = m_clients.find(peer_id);
u16 ClientInterface::getProtocolVersion(session_t peer_id)
{
- MutexAutoLock conlock(m_clients_mutex);
+ RecursiveMutexAutoLock conlock(m_clients_mutex);
// Error check
RemoteClientMap::iterator n = m_clients.find(peer_id);
void ClientInterface::setClientVersion(session_t peer_id, u8 major, u8 minor, u8 patch,
const std::string &full)
{
- MutexAutoLock conlock(m_clients_mutex);
+ RecursiveMutexAutoLock conlock(m_clients_mutex);
// Error check
RemoteClientMap::iterator n = m_clients.find(peer_id);