Kaynağa Gözat

Optionally extend the active object in a players camera direction.

See #6667

By setting active_object_send_range_blocks > active_block_range a server admin
can allow clients to retrieve active objects futher out from the player at
relatively low cost to the server
(only objects in the players' view cone are considered).
Lars Hofhansl 6 yıl önce
ebeveyn
işleme
5a03b1f5f9
2 değiştirilmiş dosya ile 53 ekleme ve 15 silme
  1. 49 13
      src/serverenvironment.cpp
  2. 4 2
      src/serverenvironment.h

+ 49 - 13
src/serverenvironment.cpp

@@ -292,8 +292,27 @@ void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
 			}
 }
 
-void ActiveBlockList::update(std::vector<v3s16> &active_positions,
-	s16 radius,
+void fillViewConeBlock(v3s16 p0,
+	const s16 r,
+	const v3f camera_pos,
+	const v3f camera_dir,
+	const float camera_fov,
+	std::set<v3s16> &list)
+{
+	v3s16 p;
+	const s16 r_nodes = r * BS * MAP_BLOCKSIZE;
+	for (p.X = p0.X - r; p.X <= p0.X+r; p.X++)
+	for (p.Y = p0.Y - r; p.Y <= p0.Y+r; p.Y++)
+	for (p.Z = p0.Z - r; p.Z <= p0.Z+r; p.Z++) {
+		if (isBlockInSight(p, camera_pos, camera_dir, camera_fov, r_nodes)) {
+			list.insert(p);
+		}
+	}
+}
+
+void ActiveBlockList::update(std::vector<PlayerSAO*> &active_players,
+	s16 active_block_range,
+	s16 active_object_range,
 	std::set<v3s16> &blocks_removed,
 	std::set<v3s16> &blocks_added)
 {
@@ -301,8 +320,25 @@ void ActiveBlockList::update(std::vector<v3s16> &active_positions,
 		Create the new list
 	*/
 	std::set<v3s16> newlist = m_forceloaded_list;
-	for (const v3s16 &active_position : active_positions) {
-		fillRadiusBlock(active_position, radius, newlist);
+	m_abm_list = m_forceloaded_list;
+	for (const PlayerSAO *playersao : active_players) {
+		v3s16 pos = getNodeBlockPos(floatToInt(playersao->getBasePosition(), BS));
+		fillRadiusBlock(pos, active_block_range, m_abm_list);
+		fillRadiusBlock(pos, active_block_range, newlist);
+
+		s16 player_ao_range = std::min(active_object_range, playersao->getWantedRange());
+		// only do this if this would add blocks
+		if (player_ao_range > active_block_range) {
+			v3f camera_dir = v3f(0,0,1);
+			camera_dir.rotateYZBy(playersao->getPitch());
+			camera_dir.rotateXZBy(playersao->getYaw());
+			fillViewConeBlock(pos,
+				player_ao_range,
+				playersao->getEyePosition(),
+				camera_dir,
+				playersao->getFov(),
+				newlist);
+		}
 	}
 
 	/*
@@ -873,10 +909,6 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
 					elapsed_timer.position));
 		}
 	}
-
-	/* Handle ActiveBlockModifiers */
-	ABMHandler abmhandler(m_abms, dtime_s, this, false);
-	abmhandler.apply(block);
 }
 
 void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
@@ -1140,7 +1172,7 @@ void ServerEnvironment::step(float dtime)
 		/*
 			Get player block positions
 		*/
-		std::vector<v3s16> players_blockpos;
+		std::vector<PlayerSAO*> players;
 		for (RemotePlayer *player: m_players) {
 			// Ignore disconnected players
 			if (player->getPeerId() == PEER_ID_INEXISTENT)
@@ -1149,18 +1181,21 @@ void ServerEnvironment::step(float dtime)
 			PlayerSAO *playersao = player->getPlayerSAO();
 			assert(playersao);
 
-			players_blockpos.push_back(
-				getNodeBlockPos(floatToInt(playersao->getBasePosition(), BS)));
+			players.push_back(playersao);
 		}
 
 		/*
 			Update list of active blocks, collecting changes
 		*/
+		// use active_object_send_range_blocks since that is max distance
+		// for active objects sent the client anyway
+		static thread_local const s16 active_object_range =
+				g_settings->getS16("active_object_send_range_blocks");
 		static thread_local const s16 active_block_range =
 				g_settings->getS16("active_block_range");
 		std::set<v3s16> blocks_removed;
 		std::set<v3s16> blocks_added;
-		m_active_blocks.update(players_blockpos, active_block_range,
+		m_active_blocks.update(players, active_block_range, active_object_range,
 			blocks_removed, blocks_added);
 
 		/*
@@ -1187,6 +1222,7 @@ void ServerEnvironment::step(float dtime)
 			MapBlock *block = m_map->getBlockOrEmerge(p);
 			if (!block) {
 				m_active_blocks.m_list.erase(p);
+				m_active_blocks.m_abm_list.erase(p);
 				continue;
 			}
 
@@ -1248,7 +1284,7 @@ void ServerEnvironment::step(float dtime)
 			// Initialize handling of ActiveBlockModifiers
 			ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true);
 
-			for (const v3s16 &p : m_active_blocks.m_list) {
+			for (const v3s16 &p : m_active_blocks.m_abm_list) {
 				MapBlock *block = m_map->getBlockNoCreateNoEx(p);
 				if (!block)
 					continue;

+ 4 - 2
src/serverenvironment.h

@@ -154,8 +154,9 @@ private:
 class ActiveBlockList
 {
 public:
-	void update(std::vector<v3s16> &active_positions,
-		s16 radius,
+	void update(std::vector<PlayerSAO*> &active_players,
+		s16 active_block_range,
+		s16 active_object_range,
 		std::set<v3s16> &blocks_removed,
 		std::set<v3s16> &blocks_added);
 
@@ -168,6 +169,7 @@ public:
 	}
 
 	std::set<v3s16> m_list;
+	std::set<v3s16> m_abm_list;
 	std::set<v3s16> m_forceloaded_list;
 
 private: