diff --git a/minetest.conf.example b/minetest.conf.example
index af85d26a2714d1c5e483aa695edcf37d3f93db88..c593e0ec10ed42444a30419a6a48fdc8d8c83aaa 100644
--- a/minetest.conf.example
+++ b/minetest.conf.example
@@ -295,7 +295,10 @@
 # See /privs in game for a full list on your server and mod configuration.
 #default_privs = interact, shout
 # Whether players are shown to clients without any range limit
+# deprecated, use the setting player_transfer_distance instead
 #unlimited_player_transfer_distance = true
+# Defines the maximal player transfer distance in blocks (0 = unlimited)
+#player_transfer_distance = 0
 # Whether to enable players killing each other
 #enable_pvp = true
 # If this is set, players will always (re)spawn at the given position
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index 40313f7a57c587a85de4e58e76b8f1ecb5b7b607..1edddec7b054e507e14597826b5ad0eb3ed3ce28 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -1038,11 +1038,6 @@ bool PlayerSAO::isStaticAllowed() const
 	return false;
 }
 
-bool PlayerSAO::unlimitedTransferDistance() const
-{
-	return g_settings->getBool("unlimited_player_transfer_distance");
-}
-
 std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
 {
 	std::ostringstream os(std::ios::binary);
diff --git a/src/content_sao.h b/src/content_sao.h
index 63e8ef4601f3234a3c0170d67acac704dfa74337..38baeab3a3477c989186572dc3fa937552278d2f 100644
--- a/src/content_sao.h
+++ b/src/content_sao.h
@@ -171,7 +171,6 @@ class PlayerSAO : public ServerActiveObject
 	void addedToEnvironment(u32 dtime_s);
 	void removingFromEnvironment();
 	bool isStaticAllowed() const;
-	bool unlimitedTransferDistance() const;
 	std::string getClientInitializationData(u16 protocol_version);
 	std::string getStaticData();
 	bool isAttached();
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index e3d2dc7b721bdeaa747f36a5ac37c5cd58499a27..32a920ed35ce321b44096d98b7f2461e76a372ba 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -202,7 +202,7 @@ void set_default_settings(Settings *settings)
 	settings->setDefault("give_initial_stuff", "false");
 	settings->setDefault("default_password", "");
 	settings->setDefault("default_privs", "interact, shout");
-	settings->setDefault("unlimited_player_transfer_distance", "true");
+	settings->setDefault("player_transfer_distance", "0");
 	settings->setDefault("enable_pvp", "true");
 	settings->setDefault("disallow_empty_password", "false");
 	settings->setDefault("disable_anticheat", "false");
diff --git a/src/environment.cpp b/src/environment.cpp
index 64c998671886609fa4b2061f0b517bf346de5022..01a7e38dcee5a33964de14a4e92d6f2eee4ff426 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -1345,11 +1345,17 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
 	inside a radius around a position
 */
 void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
+		s16 player_radius,
 		std::set<u16> &current_objects,
 		std::set<u16> &added_objects)
 {
 	v3f pos_f = intToFloat(pos, BS);
 	f32 radius_f = radius * BS;
+	f32 player_radius_f = player_radius * BS;
+
+	if (player_radius_f < 0)
+		player_radius_f = 0;
+
 	/*
 		Go through the object list,
 		- discard m_removed objects,
@@ -1369,12 +1375,15 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
 		// Discard if removed or deactivating
 		if(object->m_removed || object->m_pending_deactivation)
 			continue;
-		if(object->unlimitedTransferDistance() == false){
+
+		f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
+		if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
 			// Discard if too far
-			f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
-			if(distance_f > radius_f)
+			if (distance_f > player_radius_f && player_radius_f != 0)
 				continue;
-		}
+		} else if (distance_f > radius_f)
+			continue;
+
 		// Discard if already on current_objects
 		std::set<u16>::iterator n;
 		n = current_objects.find(id);
@@ -1390,11 +1399,17 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius,
 	inside a radius around a position
 */
 void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
+		s16 player_radius,
 		std::set<u16> &current_objects,
 		std::set<u16> &removed_objects)
 {
 	v3f pos_f = intToFloat(pos, BS);
 	f32 radius_f = radius * BS;
+	f32 player_radius_f = player_radius * BS;
+
+	if (player_radius_f < 0)
+		player_radius_f = 0;
+
 	/*
 		Go through current_objects; object is removed if:
 		- object is not found in m_active_objects (this is actually an
@@ -1423,19 +1438,15 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius,
 			continue;
 		}
 		
-		// If transfer distance is unlimited, don't remove
-		if(object->unlimitedTransferDistance())
-			continue;
-
 		f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f);
-
-		if(distance_f >= radius_f)
-		{
-			removed_objects.insert(id);
+		if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
+			if (distance_f <= player_radius_f || player_radius_f == 0)
+				continue;
+		} else if (distance_f <= radius_f)
 			continue;
-		}
-		
-		// Not removed
+
+		// Object is no longer visible
+		removed_objects.insert(id);
 	}
 }
 
diff --git a/src/environment.h b/src/environment.h
index e8ae044e30ce0d32bab7ffbeebcb03acddf2cded..030235826eca35f63a6361961cb9a50972fb87ad 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -259,6 +259,7 @@ class ServerEnvironment : public Environment
 		inside a radius around a position
 	*/
 	void getAddedActiveObjects(v3s16 pos, s16 radius,
+			s16 player_radius,
 			std::set<u16> &current_objects,
 			std::set<u16> &added_objects);
 
@@ -267,6 +268,7 @@ class ServerEnvironment : public Environment
 		inside a radius around a position
 	*/
 	void getRemovedActiveObjects(v3s16 pos, s16 radius,
+			s16 player_radius,
 			std::set<u16> &current_objects,
 			std::set<u16> &removed_objects);
 	
diff --git a/src/server.cpp b/src/server.cpp
index 2558d0d6fee309b05984d14c96510af06aaee8ef..7be1f5860c25751d71bece9c437ae8d647c1d07a 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -707,7 +707,14 @@ void Server::AsyncRunStep(bool initial_step)
 
 		// Radius inside which objects are active
 		s16 radius = g_settings->getS16("active_object_send_range_blocks");
+		s16 player_radius = g_settings->getS16("player_transfer_distance");
+
+		if (player_radius == 0 && g_settings->exists("unlimited_player_transfer_distance") &&
+				!g_settings->getBool("unlimited_player_transfer_distance"))
+			player_radius = radius;
+
 		radius *= MAP_BLOCKSIZE;
+		player_radius *= MAP_BLOCKSIZE;
 
 		for(std::map<u16, RemoteClient*>::iterator
 			i = clients.begin();
@@ -733,9 +740,9 @@ void Server::AsyncRunStep(bool initial_step)
 
 			std::set<u16> removed_objects;
 			std::set<u16> added_objects;
-			m_env->getRemovedActiveObjects(pos, radius,
+			m_env->getRemovedActiveObjects(pos, radius, player_radius,
 					client->m_known_objects, removed_objects);
-			m_env->getAddedActiveObjects(pos, radius,
+			m_env->getAddedActiveObjects(pos, radius, player_radius,
 					client->m_known_objects, added_objects);
 
 			// Ignore if nothing happened
diff --git a/src/serverlist.cpp b/src/serverlist.cpp
index 245a8b8006b439182665fc86b09b7400380b97ee..4d770a1c2fa559037124f81f3c80befd15bdff39 100644
--- a/src/serverlist.cpp
+++ b/src/serverlist.cpp
@@ -229,7 +229,7 @@ void sendAnnounce(const std::string &action,
 		server["rollback"]          = g_settings->getBool("enable_rollback_recording");
 		server["mapgen"]            = g_settings->get("mg_name");
 		server["privs"]             = g_settings->get("default_privs");
-		server["can_see_far_names"] = g_settings->getBool("unlimited_player_transfer_distance");
+		server["can_see_far_names"] = g_settings->getS16("player_transfer_distance") <= 0;
 		server["mods"]              = Json::Value(Json::arrayValue);
 		for (std::vector<ModSpec>::const_iterator it = mods.begin();
 				it != mods.end();
diff --git a/src/serverobject.h b/src/serverobject.h
index b57d3a2ba6beb968711b84f75a4bf994ed8cf15d..8e80225e4f8b7f60a937588abef358c90a13dd93 100644
--- a/src/serverobject.h
+++ b/src/serverobject.h
@@ -69,9 +69,6 @@ class ServerActiveObject : public ActiveObject
 	// environment
 	virtual bool environmentDeletes() const
 	{ return true; }
-
-	virtual bool unlimitedTransferDistance() const
-	{ return false; }
 	
 	// Create a certain type of ServerActiveObject
 	static ServerActiveObject* create(u8 type,