mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-03 16:55:24 +01:00 
			
		
		
		
	Send ActiveObjects once right after Init2
This commit is contained in:
		@@ -1243,8 +1243,14 @@ void Client::sendPlayerPos()
 | 
			
		||||
	u8 camera_fov    = map.getCameraFov();
 | 
			
		||||
	u8 wanted_range  = map.getControl().wanted_range;
 | 
			
		||||
 | 
			
		||||
	// Save bandwidth by only updating position when something changed
 | 
			
		||||
	if(myplayer->last_position        == myplayer->getPosition() &&
 | 
			
		||||
	// Save bandwidth by only updating position when
 | 
			
		||||
	// player is not dead and something changed
 | 
			
		||||
 | 
			
		||||
	if (m_activeobjects_received && myplayer->isDead())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (
 | 
			
		||||
			myplayer->last_position     == myplayer->getPosition() &&
 | 
			
		||||
			myplayer->last_speed        == myplayer->getSpeed()    &&
 | 
			
		||||
			myplayer->last_pitch        == myplayer->getPitch()    &&
 | 
			
		||||
			myplayer->last_yaw          == myplayer->getYaw()      &&
 | 
			
		||||
 
 | 
			
		||||
@@ -339,6 +339,8 @@ public:
 | 
			
		||||
	{ return m_nodedef_received; }
 | 
			
		||||
	bool mediaReceived()
 | 
			
		||||
	{ return !m_media_downloader; }
 | 
			
		||||
	const bool activeObjectsReceived() const
 | 
			
		||||
	{ return m_activeobjects_received; }
 | 
			
		||||
 | 
			
		||||
	u16 getProtoVersion()
 | 
			
		||||
	{ return m_proto_ver; }
 | 
			
		||||
@@ -539,6 +541,7 @@ private:
 | 
			
		||||
	std::queue<ClientEvent *> m_client_event_queue;
 | 
			
		||||
	bool m_itemdef_received = false;
 | 
			
		||||
	bool m_nodedef_received = false;
 | 
			
		||||
	bool m_activeobjects_received = false;
 | 
			
		||||
	bool m_mods_loaded = false;
 | 
			
		||||
	ClientMediaDownloader *m_media_downloader;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -463,6 +463,10 @@ void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
 | 
			
		||||
		infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
 | 
			
		||||
				<< ". The packet is unreliable, ignoring" << std::endl;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// m_activeobjects_received is false before the first
 | 
			
		||||
	// TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD packet is received
 | 
			
		||||
	m_activeobjects_received = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Client::handleCommand_ActiveObjectMessages(NetworkPacket* pkt)
 | 
			
		||||
 
 | 
			
		||||
@@ -298,9 +298,6 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
 | 
			
		||||
	infostream << "Server: Sending content to "
 | 
			
		||||
			<< getPlayerName(pkt->getPeerId()) << std::endl;
 | 
			
		||||
 | 
			
		||||
	// Send player movement settings
 | 
			
		||||
	SendMovement(pkt->getPeerId());
 | 
			
		||||
 | 
			
		||||
	// Send item definitions
 | 
			
		||||
	SendItemDef(pkt->getPeerId(), m_itemdef, protocol_version);
 | 
			
		||||
 | 
			
		||||
@@ -312,9 +309,25 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
 | 
			
		||||
	// Send media announcement
 | 
			
		||||
	sendMediaAnnouncement(pkt->getPeerId(), lang);
 | 
			
		||||
 | 
			
		||||
	RemoteClient *client;
 | 
			
		||||
	{
 | 
			
		||||
		MutexAutoLock(m_con);
 | 
			
		||||
		client = getClient(pkt->getPeerId(), CS_InitDone);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send active objects
 | 
			
		||||
	{
 | 
			
		||||
		PlayerSAO *sao = getPlayerSAO(pkt->getPeerId());
 | 
			
		||||
		if (client && sao)
 | 
			
		||||
			SendActiveObjectRemoveAdd(client, sao);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Send detached inventories
 | 
			
		||||
	sendDetachedInventories(pkt->getPeerId(), false);
 | 
			
		||||
 | 
			
		||||
	// Send player movement settings
 | 
			
		||||
	SendMovement(pkt->getPeerId());
 | 
			
		||||
 | 
			
		||||
	// Send time of day
 | 
			
		||||
	u16 time = m_env->getTimeOfDay();
 | 
			
		||||
	float time_speed = g_settings->getFloat("time_speed");
 | 
			
		||||
@@ -323,11 +336,10 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
 | 
			
		||||
	SendCSMRestrictionFlags(pkt->getPeerId());
 | 
			
		||||
 | 
			
		||||
	// Warnings about protocol version can be issued here
 | 
			
		||||
	if (getClient(pkt->getPeerId())->net_proto_version < LATEST_PROTOCOL_VERSION) {
 | 
			
		||||
	if (client->net_proto_version < LATEST_PROTOCOL_VERSION) {
 | 
			
		||||
		SendChatMessage(pkt->getPeerId(), ChatMessage(CHATMESSAGE_TYPE_SYSTEM,
 | 
			
		||||
				L"# Server: WARNING: YOUR CLIENT'S VERSION MAY NOT BE FULLY COMPATIBLE "
 | 
			
		||||
				L"WITH THIS SERVER!"));
 | 
			
		||||
 | 
			
		||||
			L"# Server: WARNING: YOUR CLIENT'S VERSION MAY NOT BE FULLY COMPATIBLE "
 | 
			
		||||
			L"WITH THIS SERVER!"));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										215
									
								
								src/server.cpp
									
									
									
									
									
								
							
							
						
						
									
										215
									
								
								src/server.cpp
									
									
									
									
									
								
							@@ -620,124 +620,27 @@ void Server::AsyncRunStep(bool initial_step)
 | 
			
		||||
 | 
			
		||||
		m_clients.lock();
 | 
			
		||||
		const RemoteClientMap &clients = m_clients.getClientList();
 | 
			
		||||
		ScopeProfiler sp(g_profiler, "Server: update visible objects");
 | 
			
		||||
 | 
			
		||||
		// Radius inside which objects are active
 | 
			
		||||
		static thread_local const s16 radius =
 | 
			
		||||
			g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;
 | 
			
		||||
 | 
			
		||||
		// Radius inside which players are active
 | 
			
		||||
		static thread_local const bool is_transfer_limited =
 | 
			
		||||
			g_settings->exists("unlimited_player_transfer_distance") &&
 | 
			
		||||
			!g_settings->getBool("unlimited_player_transfer_distance");
 | 
			
		||||
		static thread_local const s16 player_transfer_dist =
 | 
			
		||||
			g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
 | 
			
		||||
		s16 player_radius = player_transfer_dist;
 | 
			
		||||
		if (player_radius == 0 && is_transfer_limited)
 | 
			
		||||
			player_radius = radius;
 | 
			
		||||
		ScopeProfiler sp(g_profiler, "Server: update objects within range");
 | 
			
		||||
 | 
			
		||||
		for (const auto &client_it : clients) {
 | 
			
		||||
			RemoteClient *client = client_it.second;
 | 
			
		||||
 | 
			
		||||
			// If definitions and textures have not been sent, don't
 | 
			
		||||
			// send objects either
 | 
			
		||||
			if (client->getState() < CS_DefinitionsSent)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			RemotePlayer *player = m_env->getPlayer(client->peer_id);
 | 
			
		||||
			if (!player) {
 | 
			
		||||
				// This can happen if the client timeouts somehow
 | 
			
		||||
			// This can happen if the client times out somehow
 | 
			
		||||
			if (!m_env->getPlayer(client->peer_id))
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			PlayerSAO *playersao = player->getPlayerSAO();
 | 
			
		||||
			PlayerSAO *playersao = getPlayerSAO(client->peer_id);
 | 
			
		||||
			if (!playersao)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
 | 
			
		||||
			if (my_radius <= 0) my_radius = radius;
 | 
			
		||||
			//infostream << "Server: Active Radius " << my_radius << std::endl;
 | 
			
		||||
 | 
			
		||||
			std::queue<u16> removed_objects;
 | 
			
		||||
			std::queue<u16> added_objects;
 | 
			
		||||
			m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
 | 
			
		||||
					client->m_known_objects, removed_objects);
 | 
			
		||||
			m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
 | 
			
		||||
					client->m_known_objects, added_objects);
 | 
			
		||||
 | 
			
		||||
			// Ignore if nothing happened
 | 
			
		||||
			if (removed_objects.empty() && added_objects.empty()) {
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			std::string data_buffer;
 | 
			
		||||
 | 
			
		||||
			char buf[4];
 | 
			
		||||
 | 
			
		||||
			// Handle removed objects
 | 
			
		||||
			writeU16((u8*)buf, removed_objects.size());
 | 
			
		||||
			data_buffer.append(buf, 2);
 | 
			
		||||
			while (!removed_objects.empty()) {
 | 
			
		||||
				// Get object
 | 
			
		||||
				u16 id = removed_objects.front();
 | 
			
		||||
				ServerActiveObject* obj = m_env->getActiveObject(id);
 | 
			
		||||
 | 
			
		||||
				// Add to data buffer for sending
 | 
			
		||||
				writeU16((u8*)buf, id);
 | 
			
		||||
				data_buffer.append(buf, 2);
 | 
			
		||||
 | 
			
		||||
				// Remove from known objects
 | 
			
		||||
				client->m_known_objects.erase(id);
 | 
			
		||||
 | 
			
		||||
				if(obj && obj->m_known_by_count > 0)
 | 
			
		||||
					obj->m_known_by_count--;
 | 
			
		||||
				removed_objects.pop();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Handle added objects
 | 
			
		||||
			writeU16((u8*)buf, added_objects.size());
 | 
			
		||||
			data_buffer.append(buf, 2);
 | 
			
		||||
			while (!added_objects.empty()) {
 | 
			
		||||
				// Get object
 | 
			
		||||
				u16 id = added_objects.front();
 | 
			
		||||
				ServerActiveObject* obj = m_env->getActiveObject(id);
 | 
			
		||||
 | 
			
		||||
				// Get object type
 | 
			
		||||
				u8 type = ACTIVEOBJECT_TYPE_INVALID;
 | 
			
		||||
				if (!obj)
 | 
			
		||||
					warningstream << FUNCTION_NAME << ": NULL object" << std::endl;
 | 
			
		||||
				else
 | 
			
		||||
					type = obj->getSendType();
 | 
			
		||||
 | 
			
		||||
				// Add to data buffer for sending
 | 
			
		||||
				writeU16((u8*)buf, id);
 | 
			
		||||
				data_buffer.append(buf, 2);
 | 
			
		||||
				writeU8((u8*)buf, type);
 | 
			
		||||
				data_buffer.append(buf, 1);
 | 
			
		||||
 | 
			
		||||
				if(obj)
 | 
			
		||||
					data_buffer.append(serializeLongString(
 | 
			
		||||
							obj->getClientInitializationData(client->net_proto_version)));
 | 
			
		||||
				else
 | 
			
		||||
					data_buffer.append(serializeLongString(""));
 | 
			
		||||
 | 
			
		||||
				// Add to known objects
 | 
			
		||||
				client->m_known_objects.insert(id);
 | 
			
		||||
 | 
			
		||||
				if(obj)
 | 
			
		||||
					obj->m_known_by_count++;
 | 
			
		||||
 | 
			
		||||
				added_objects.pop();
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			u32 pktSize = SendActiveObjectRemoveAdd(client->peer_id, data_buffer);
 | 
			
		||||
			verbosestream << "Server: Sent object remove/add: "
 | 
			
		||||
					<< removed_objects.size() << " removed, "
 | 
			
		||||
					<< added_objects.size() << " added, "
 | 
			
		||||
					<< "packet size is " << pktSize << std::endl;
 | 
			
		||||
			SendActiveObjectRemoveAdd(client, playersao);
 | 
			
		||||
		}
 | 
			
		||||
		m_clients.unlock();
 | 
			
		||||
 | 
			
		||||
		// Save mod storages if modified
 | 
			
		||||
		m_mod_storage_save_timer -= dtime;
 | 
			
		||||
		if (m_mod_storage_save_timer <= 0.0f) {
 | 
			
		||||
			infostream << "Saving registered mod storages." << std::endl;
 | 
			
		||||
@@ -1089,9 +992,9 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
 | 
			
		||||
	return playersao;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void Server::handleCommand(NetworkPacket* pkt)
 | 
			
		||||
inline void Server::handleCommand(NetworkPacket *pkt)
 | 
			
		||||
{
 | 
			
		||||
	const ToServerCommandHandler& opHandle = toServerCommandTable[pkt->getCommand()];
 | 
			
		||||
	const ToServerCommandHandler &opHandle = toServerCommandTable[pkt->getCommand()];
 | 
			
		||||
	(this->*opHandle.handler)(pkt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1925,12 +1828,106 @@ void Server::SendPlayerFormspecPrepend(session_t peer_id)
 | 
			
		||||
	Send(&pkt);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u32 Server::SendActiveObjectRemoveAdd(session_t peer_id, const std::string &datas)
 | 
			
		||||
void Server::SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao)
 | 
			
		||||
{
 | 
			
		||||
	NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
 | 
			
		||||
	pkt.putRawString(datas.c_str(), datas.size());
 | 
			
		||||
	// Radius inside which objects are active
 | 
			
		||||
	static thread_local const s16 radius =
 | 
			
		||||
		g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;
 | 
			
		||||
 | 
			
		||||
	// Radius inside which players are active
 | 
			
		||||
	static thread_local const bool is_transfer_limited =
 | 
			
		||||
		g_settings->exists("unlimited_player_transfer_distance") &&
 | 
			
		||||
		!g_settings->getBool("unlimited_player_transfer_distance");
 | 
			
		||||
 | 
			
		||||
	static thread_local const s16 player_transfer_dist =
 | 
			
		||||
		g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
 | 
			
		||||
 | 
			
		||||
	s16 player_radius = player_transfer_dist == 0 && is_transfer_limited ?
 | 
			
		||||
		radius : player_transfer_dist;
 | 
			
		||||
 | 
			
		||||
	s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
 | 
			
		||||
	if (my_radius <= 0)
 | 
			
		||||
		my_radius = radius;
 | 
			
		||||
 | 
			
		||||
	std::queue<u16> removed_objects, added_objects;
 | 
			
		||||
	m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
 | 
			
		||||
		client->m_known_objects, removed_objects);
 | 
			
		||||
	m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
 | 
			
		||||
		client->m_known_objects, added_objects);
 | 
			
		||||
 | 
			
		||||
	int removed_count = removed_objects.size();
 | 
			
		||||
	int added_count   = added_objects.size();
 | 
			
		||||
 | 
			
		||||
	if (removed_objects.empty() && added_objects.empty())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	char buf[4];
 | 
			
		||||
	std::string data;
 | 
			
		||||
 | 
			
		||||
	// Handle removed objects
 | 
			
		||||
	writeU16((u8*)buf, removed_objects.size());
 | 
			
		||||
	data.append(buf, 2);
 | 
			
		||||
	while (!removed_objects.empty()) {
 | 
			
		||||
		// Get object
 | 
			
		||||
		u16 id = removed_objects.front();
 | 
			
		||||
		ServerActiveObject* obj = m_env->getActiveObject(id);
 | 
			
		||||
 | 
			
		||||
		// Add to data buffer for sending
 | 
			
		||||
		writeU16((u8*)buf, id);
 | 
			
		||||
		data.append(buf, 2);
 | 
			
		||||
 | 
			
		||||
		// Remove from known objects
 | 
			
		||||
		client->m_known_objects.erase(id);
 | 
			
		||||
 | 
			
		||||
		if (obj && obj->m_known_by_count > 0)
 | 
			
		||||
			obj->m_known_by_count--;
 | 
			
		||||
 | 
			
		||||
		removed_objects.pop();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Handle added objects
 | 
			
		||||
	writeU16((u8*)buf, added_objects.size());
 | 
			
		||||
	data.append(buf, 2);
 | 
			
		||||
	while (!added_objects.empty()) {
 | 
			
		||||
		// Get object
 | 
			
		||||
		u16 id = added_objects.front();
 | 
			
		||||
		ServerActiveObject* obj = m_env->getActiveObject(id);
 | 
			
		||||
 | 
			
		||||
		// Get object type
 | 
			
		||||
		u8 type = ACTIVEOBJECT_TYPE_INVALID;
 | 
			
		||||
		if (!obj)
 | 
			
		||||
			warningstream << FUNCTION_NAME << ": NULL object" << std::endl;
 | 
			
		||||
		else
 | 
			
		||||
			type = obj->getSendType();
 | 
			
		||||
 | 
			
		||||
		// Add to data buffer for sending
 | 
			
		||||
		writeU16((u8*)buf, id);
 | 
			
		||||
		data.append(buf, 2);
 | 
			
		||||
		writeU8((u8*)buf, type);
 | 
			
		||||
		data.append(buf, 1);
 | 
			
		||||
 | 
			
		||||
		if (obj)
 | 
			
		||||
			data.append(serializeLongString(
 | 
			
		||||
				obj->getClientInitializationData(client->net_proto_version)));
 | 
			
		||||
		else
 | 
			
		||||
			data.append(serializeLongString(""));
 | 
			
		||||
 | 
			
		||||
		// Add to known objects
 | 
			
		||||
		client->m_known_objects.insert(id);
 | 
			
		||||
 | 
			
		||||
		if (obj)
 | 
			
		||||
			obj->m_known_by_count++;
 | 
			
		||||
 | 
			
		||||
		added_objects.pop();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, data.size(), client->peer_id);
 | 
			
		||||
	pkt.putRawString(data.c_str(), data.size());
 | 
			
		||||
	Send(&pkt);
 | 
			
		||||
	return pkt.getSize();
 | 
			
		||||
 | 
			
		||||
	verbosestream << "Server::SendActiveObjectRemoveAdd: "
 | 
			
		||||
		<< removed_count << " removed, " << added_count << " added, "
 | 
			
		||||
		<< "packet size is " << pkt.getSize() << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
 | 
			
		||||
 
 | 
			
		||||
@@ -469,7 +469,7 @@ private:
 | 
			
		||||
		bool vertical, const std::string &texture,
 | 
			
		||||
		const struct TileAnimationParams &animation, u8 glow);
 | 
			
		||||
 | 
			
		||||
	u32 SendActiveObjectRemoveAdd(session_t peer_id, const std::string &datas);
 | 
			
		||||
	void SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao);
 | 
			
		||||
	void SendActiveObjectMessages(session_t peer_id, const std::string &datas,
 | 
			
		||||
		bool reliable = true);
 | 
			
		||||
	void SendCSMRestrictionFlags(session_t peer_id);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user