aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParamat <paramat@users.noreply.github.com>2018-04-15 21:56:05 +0100
committerGitHub <noreply@github.com>2018-04-15 21:56:05 +0100
commit28813702d67f5d56a7e29cb9473278dcc2ea750e (patch)
treea6262ba0d04a2e2ef2693fa287df654347904d9a
parent326eeca306f7bfb53ae3685eef18978dd81e587e (diff)
downloadminetest-28813702d67f5d56a7e29cb9473278dcc2ea750e.tar.gz
minetest-28813702d67f5d56a7e29cb9473278dcc2ea750e.tar.bz2
minetest-28813702d67f5d56a7e29cb9473278dcc2ea750e.zip
FOV: Raise lower limit to avoid zoom-loading of distant world (#7234)
In the client, raise lower limit from 30 to 45 degrees, to avoid server seeing this as a zoom and loading world beyond the server-set limit. Add minimum in settingtypes.txt and enforce lower limit when set using minetest.conf. In the server, distrust the client-sent FOV if below the heuristic zoom threshold and use the player object property 'zoom_fov' to check it, to protect against hacked clients.
-rw-r--r--builtin/settingtypes.txt2
-rw-r--r--src/camera.cpp4
-rw-r--r--src/clientiface.cpp28
-rw-r--r--src/content_sao.cpp5
-rw-r--r--src/content_sao.h1
5 files changed, 33 insertions, 7 deletions
diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt
index 080a57888..b8b864c8b 100644
--- a/builtin/settingtypes.txt
+++ b/builtin/settingtypes.txt
@@ -574,7 +574,7 @@ fullscreen_bpp (Full screen BPP) int 24
vsync (V-Sync) bool false
# Field of view in degrees.
-fov (Field of view) int 72 30 160
+fov (Field of view) int 72 45 160
# Adjust the gamma encoding for the light tables. Higher numbers are brighter.
# This setting is for the client only and is ignored by the server.
diff --git a/src/camera.cpp b/src/camera.cpp
index ebb154137..1bbdb56ea 100644
--- a/src/camera.cpp
+++ b/src/camera.cpp
@@ -71,7 +71,9 @@ Camera::Camera(MapDrawControl &draw_control, Client *client):
*/
m_cache_fall_bobbing_amount = g_settings->getFloat("fall_bobbing_amount");
m_cache_view_bobbing_amount = g_settings->getFloat("view_bobbing_amount");
- m_cache_fov = g_settings->getFloat("fov");
+ // 45 degrees is the lowest FOV that doesn't cause the server to treat this
+ // as a zoom FOV and load world beyond the set server limits.
+ m_cache_fov = std::fmax(g_settings->getFloat("fov"), 45.0f);
m_arm_inertia = g_settings->getBool("arm_inertia");
m_nametags.clear();
}
diff --git a/src/clientiface.cpp b/src/clientiface.cpp
index 3a6caf800..8c429976b 100644
--- a/src/clientiface.cpp
+++ b/src/clientiface.cpp
@@ -192,17 +192,35 @@ void RemoteClient::GetNextBlocks (
*/
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(adjustDist(m_max_send_distance, camera_fov), wanted_range);
- const s16 d_opt = std::min(adjustDist(m_block_optimize_distance, camera_fov), wanted_range);
+ // If below the heuristic zoom threshold (see adjustDist() in numeric.cpp)
+ // 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.
+ // 0.888 radians is slightly larger than the zoom threshold of 1.775 / 2
+ // radians.
+ if (camera_fov < 0.888f) {
+ float prop_zoom_fov = sao->getZoomFOV();
+ // If zoom is disabled by value 0
+ if (prop_zoom_fov < 0.001f)
+ camera_fov = 0.888f;
+ else
+ // Degrees -> radians
+ camera_fov = prop_zoom_fov * core::DEGTORAD;
+ }
+
+ const s16 full_d_max = std::min(adjustDist(m_max_send_distance, camera_fov),
+ wanted_range);
+ const s16 d_opt = std::min(adjustDist(m_block_optimize_distance, camera_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(adjustDist(m_max_gen_distance, camera_fov), wanted_range);
+ s16 d_max_gen = std::min(adjustDist(m_max_gen_distance, camera_fov),
+ wanted_range);
// Don't loop very much at a time, adjust with distance,
// do more work per RTT with greater distances.
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index 3ea219846..c554b775d 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -1473,3 +1473,8 @@ bool PlayerSAO::getSelectionBox(aabb3f *toset) const
return true;
}
+
+float PlayerSAO::getZoomFOV() const
+{
+ return m_prop.zoom_fov;
+}
diff --git a/src/content_sao.h b/src/content_sao.h
index 6583f31d6..59e3b3d4b 100644
--- a/src/content_sao.h
+++ b/src/content_sao.h
@@ -330,6 +330,7 @@ public:
v3f getEyePosition() const { return m_base_position + getEyeOffset(); }
v3f getEyeOffset() const;
+ float getZoomFOV() const;
inline Metadata &getMeta() { return m_meta; }