mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 01:05:48 +01:00 
			
		
		
		
	Reorder client initialization (#15554)
Previously, ServerEnv created a player instance before they're fully initialized. This commit moves all initialization steps and callbacks into TOSERVER_CLIENT_READY ^ which includes StageTwoClientInit for player loading or creation
This commit is contained in:
		@@ -1168,24 +1168,25 @@ void Server::yieldToOtherThreads(float dtime)
 | 
			
		||||
	g_profiler->avg("Server::yieldTo...() progress [#]", qs_initial - qs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
 | 
			
		||||
PlayerSAO *Server::StageTwoClientInit(session_t peer_id)
 | 
			
		||||
{
 | 
			
		||||
	std::string playername;
 | 
			
		||||
	PlayerSAO *playersao = NULL;
 | 
			
		||||
	std::unique_ptr<PlayerSAO> sao;
 | 
			
		||||
	{
 | 
			
		||||
		ClientInterface::AutoLock clientlock(m_clients);
 | 
			
		||||
		RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
 | 
			
		||||
		if (client) {
 | 
			
		||||
			playername = client->getName();
 | 
			
		||||
			playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
 | 
			
		||||
			sao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	RemotePlayer *player = m_env->getPlayer(playername.c_str(), true);
 | 
			
		||||
	RemotePlayer *player = sao ? sao->getPlayer() : nullptr;
 | 
			
		||||
 | 
			
		||||
	// If failed, cancel
 | 
			
		||||
	if (!playersao || !player) {
 | 
			
		||||
		if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
 | 
			
		||||
	if (!player) {
 | 
			
		||||
		RemotePlayer *joined = m_env->getPlayer(playername.c_str());
 | 
			
		||||
		if (joined && joined->getPeerId() != PEER_ID_INEXISTENT) {
 | 
			
		||||
			actionstream << "Server: Failed to emerge player \"" << playername
 | 
			
		||||
					<< "\" (player allocated to another client)" << std::endl;
 | 
			
		||||
			DenyAccess(peer_id, SERVER_ACCESSDENIED_ALREADY_CONNECTED);
 | 
			
		||||
@@ -1197,6 +1198,19 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
 | 
			
		||||
		return nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Add player to environment
 | 
			
		||||
	m_env->addPlayer(player);
 | 
			
		||||
 | 
			
		||||
	/* Clean up old HUD elements from previous sessions */
 | 
			
		||||
	player->clearHud();
 | 
			
		||||
 | 
			
		||||
	/* Add object to environment */
 | 
			
		||||
	PlayerSAO *playersao = sao.get();
 | 
			
		||||
	m_env->addActiveObject(std::move(sao));
 | 
			
		||||
 | 
			
		||||
	if (playersao->isNewPlayer())
 | 
			
		||||
		m_script->on_newplayer(playersao);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
		Send complete position information
 | 
			
		||||
	*/
 | 
			
		||||
@@ -3229,9 +3243,7 @@ void Server::reportPrivsModified(const std::string &name)
 | 
			
		||||
		PlayerSAO *sao = player->getPlayerSAO();
 | 
			
		||||
		if(!sao)
 | 
			
		||||
			return;
 | 
			
		||||
		sao->updatePrivileges(
 | 
			
		||||
				getPlayerEffectivePrivs(name),
 | 
			
		||||
				isSingleplayer());
 | 
			
		||||
		sao->updatePrivileges(getPlayerEffectivePrivs(name));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3965,7 +3977,8 @@ void Server::requestShutdown(const std::string &msg, bool reconnect, float delay
 | 
			
		||||
	m_shutdown_state.trigger(delay, msg, reconnect);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
 | 
			
		||||
std::unique_ptr<PlayerSAO> Server::emergePlayer(const char *name, session_t peer_id,
 | 
			
		||||
	u16 proto_version)
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
		Try to get an existing player
 | 
			
		||||
@@ -4008,20 +4021,13 @@ PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_v
 | 
			
		||||
		player = new RemotePlayer(name, idef());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool newplayer = false;
 | 
			
		||||
 | 
			
		||||
	// Load player
 | 
			
		||||
	PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
 | 
			
		||||
	auto playersao = m_env->loadPlayer(player, peer_id);
 | 
			
		||||
 | 
			
		||||
	// Complete init with server parts
 | 
			
		||||
	playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
 | 
			
		||||
	player->protocol_version = proto_version;
 | 
			
		||||
 | 
			
		||||
	/* Run scripts */
 | 
			
		||||
	if (newplayer) {
 | 
			
		||||
		m_script->on_newplayer(playersao);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return playersao;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -194,7 +194,9 @@ public:
 | 
			
		||||
	void Receive(float min_time);
 | 
			
		||||
	void yieldToOtherThreads(float dtime);
 | 
			
		||||
 | 
			
		||||
	PlayerSAO* StageTwoClientInit(session_t peer_id);
 | 
			
		||||
	// Full player initialization after they processed all static media
 | 
			
		||||
	// This is a helper function for TOSERVER_CLIENT_READY
 | 
			
		||||
	PlayerSAO *StageTwoClientInit(session_t peer_id);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Command Handlers
 | 
			
		||||
@@ -626,7 +628,8 @@ private:
 | 
			
		||||
 | 
			
		||||
		Call with env and con locked.
 | 
			
		||||
	*/
 | 
			
		||||
	PlayerSAO *emergePlayer(const char *name, session_t peer_id, u16 proto_version);
 | 
			
		||||
	std::unique_ptr<PlayerSAO> emergePlayer(const char *name, session_t peer_id,
 | 
			
		||||
		u16 proto_version);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
		Variables
 | 
			
		||||
 
 | 
			
		||||
@@ -156,12 +156,14 @@ public:
 | 
			
		||||
 | 
			
		||||
	// Other
 | 
			
		||||
 | 
			
		||||
	void updatePrivileges(const std::set<std::string> &privs, bool is_singleplayer)
 | 
			
		||||
	void updatePrivileges(const std::set<std::string> &privs)
 | 
			
		||||
	{
 | 
			
		||||
		m_privs = privs;
 | 
			
		||||
		m_is_singleplayer = is_singleplayer;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	inline void setNewPlayer() { m_is_new_player = true; }
 | 
			
		||||
	inline bool isNewPlayer()  { return m_is_new_player; }
 | 
			
		||||
 | 
			
		||||
	bool getCollisionBox(aabb3f *toset) const override;
 | 
			
		||||
	bool getSelectionBox(aabb3f *toset) const override;
 | 
			
		||||
	bool collideWithObjects() const override { return true; }
 | 
			
		||||
@@ -202,7 +204,8 @@ private:
 | 
			
		||||
 | 
			
		||||
	// Cached privileges for enforcement
 | 
			
		||||
	std::set<std::string> m_privs;
 | 
			
		||||
	bool m_is_singleplayer;
 | 
			
		||||
	const bool m_is_singleplayer;
 | 
			
		||||
	bool m_is_new_player = false;
 | 
			
		||||
 | 
			
		||||
	u16 m_breath = PLAYER_MAX_BREATH_DEFAULT;
 | 
			
		||||
	f32 m_pitch = 0.0f;
 | 
			
		||||
 
 | 
			
		||||
@@ -667,13 +667,13 @@ void ServerEnvironment::savePlayer(RemotePlayer *player)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PlayerSAO *ServerEnvironment::loadPlayer(RemotePlayer *player, bool *new_player,
 | 
			
		||||
	session_t peer_id, bool is_singleplayer)
 | 
			
		||||
std::unique_ptr<PlayerSAO> ServerEnvironment::loadPlayer(RemotePlayer *player, session_t peer_id)
 | 
			
		||||
{
 | 
			
		||||
	auto playersao = std::make_unique<PlayerSAO>(this, player, peer_id, is_singleplayer);
 | 
			
		||||
	auto playersao = std::make_unique<PlayerSAO>(this, player, peer_id, m_server->isSingleplayer());
 | 
			
		||||
	// Create player if it doesn't exist
 | 
			
		||||
	if (!m_player_database->loadPlayer(player, playersao.get())) {
 | 
			
		||||
		*new_player = true;
 | 
			
		||||
		playersao->setNewPlayer();
 | 
			
		||||
 | 
			
		||||
		// Set player position
 | 
			
		||||
		infostream << "Server: Finding spawn place for player \""
 | 
			
		||||
			<< player->getName() << "\"" << std::endl;
 | 
			
		||||
@@ -692,20 +692,10 @@ PlayerSAO *ServerEnvironment::loadPlayer(RemotePlayer *player, bool *new_player,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Add player to environment
 | 
			
		||||
	addPlayer(player);
 | 
			
		||||
 | 
			
		||||
	/* Clean up old HUD elements from previous sessions */
 | 
			
		||||
	player->clearHud();
 | 
			
		||||
 | 
			
		||||
	/* Add object to environment */
 | 
			
		||||
	PlayerSAO *ret = playersao.get();
 | 
			
		||||
	addActiveObject(std::move(playersao));
 | 
			
		||||
 | 
			
		||||
	// Update active blocks quickly for a bit so objects in those blocks appear on the client
 | 
			
		||||
	m_fast_active_block_divider = 10;
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
	return playersao;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ServerEnvironment::saveMeta()
 | 
			
		||||
 
 | 
			
		||||
@@ -240,8 +240,7 @@ public:
 | 
			
		||||
	// Save players
 | 
			
		||||
	void saveLoadedPlayers(bool force = false);
 | 
			
		||||
	void savePlayer(RemotePlayer *player);
 | 
			
		||||
	PlayerSAO *loadPlayer(RemotePlayer *player, bool *new_player, session_t peer_id,
 | 
			
		||||
		bool is_singleplayer);
 | 
			
		||||
	std::unique_ptr<PlayerSAO> loadPlayer(RemotePlayer *player, session_t peer_id);
 | 
			
		||||
	void addPlayer(RemotePlayer *player);
 | 
			
		||||
	void removePlayer(RemotePlayer *player);
 | 
			
		||||
	bool removePlayerFromDatabase(const std::string &name);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user