⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usersession.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 4 页
字号:

	msgBuffer.WriteBlob("status", msgBuf, intsWritten * sizeof(int));

	topology()->SendNetworkMessageToUser(data->userID, data->userSessionID, data->userServerID, TSVC_FRIENDS, msgBuffer.Base(), msgBuffer.DataSize());
}


//-----------------------------------------------------------------------------
// Purpose: Tells a user that we're offline (even if we're not)
//			Used when a user is blocked
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_GetSessionInfo_SendingOfflineStatus(int returnVal, void *dataBlock)
{
	if (returnVal < 1)
		return;

	ITrackerUserDatabase::user_t *data = (ITrackerUserDatabase::user_t *)dataBlock;
	if (data->userStatus < 1)
		return;	// they're not online

	// tell the user our status is offline
	CUtlMsgBuffer msgBuffer;
	msgBuffer.WriteInt("_id", TSVC_FRIENDS);
	msgBuffer.WriteInt("count", 1);
	int msgBuf[5];
	int intsWritten = 0;
	msgBuf[intsWritten++] = m_iUserID;
	// write status second
	msgBuf[intsWritten++] = 0;
	// write sessionID third
	msgBuf[intsWritten++] = 0;
	// write blank IP address
	msgBuf[intsWritten++] = 0;
	msgBuf[intsWritten++] = 0;
	if (m_iBuildNum >= COMPATILIBITY_SERVERID_SUPPORT_VERSION_MIN)
	{
		// write empty serverID
		msgBuf[intsWritten++] = 0;
	}

	msgBuffer.WriteBlob("status", msgBuf, intsWritten * sizeof(int));

	// route the message to the user
	topology()->SendNetworkMessageToUser(data->userID, data->userSessionID, data->userServerID, TSVC_FRIENDS, msgBuffer.Base(), msgBuffer.DataSize());
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_FindUsers(int returnVal, void *dataBlock)
{
	ITrackerUserDatabase::FindUsers_t *data = (ITrackerUserDatabase::FindUsers_t *)dataBlock;

	if (data->usersReturned > 0)
	{
		// Success!

		//!! need to send these as one packet
		for (int i = 0; i < data->usersReturned; i++)
		{
			unsigned int friendID = data->userID[i];
			const char *userName = data->userName[i];
			const char *firstName = data->firstName[i];
			const char *lastName = data->lastName[i];

			ISendMessage *msg = CreateUserMessage(TSVC_FRIENDSFOUND);

			msg->WriteUInt("uid", friendID);
			msg->WriteString("UserName", userName);
			msg->WriteString("FirstName", firstName);
			msg->WriteString("LastName", lastName);
		
			SendMessage(msg, NET_RELIABLE);
		}
	}
	else
	{
		// failure, no friends found
		ISendMessage *msg = CreateUserMessage(TSVC_NOFRIENDS);
		SendMessage(msg, NET_RELIABLE);
	}
}

//-----------------------------------------------------------------------------
// Purpose: Returns information about ourself
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_GetInfo(int returnVal, void *dataBlock)
{
	ITrackerUserDatabase::GetInfo_t *data = (ITrackerUserDatabase::GetInfo_t *)dataBlock;

	// send back information about the user
	ISendMessage *msg = CreateUserMessage(TSVC_FRIENDINFO);

	msg->WriteUInt("uid", data->targetID);
	msg->WriteString("UserName", data->userName);
	msg->WriteString("FirstName", data->firstName);
	msg->WriteString("LastName", data->lastName);
	msg->WriteString("email", data->email);

	// if this is the current users details, remember them
	if (data->targetID == m_iUserID)
	{
		v_strncpy(m_szUserName, data->userName, sizeof(m_szUserName));
	}

	SendMessage(msg, NET_RELIABLE);
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_GetFriendInfo_IsAuthed(int returnVal, void *dataBlock)
{
	ITrackerUserDatabase::IsAuthed_t *data = (ITrackerUserDatabase::IsAuthed_t *)dataBlock;
	unsigned int friendID = data->targetID;
	if (data->authLevel > 0 || data->targetID == m_iUserID)
	{
		// get information about the user
		g_pDataManager->TrackerUser(friendID)->User_GetInfo(this, 0, friendID);
	}
	else
	{
		// send a not-authed message
		ISendMessage *msg = CreateUserMessage(TSVC_FRIENDINFO);
		msg->WriteUInt("uid", friendID);
		msg->WriteInt("NotAuthed", 1);
		SendMessage(msg, NET_RELIABLE);
	}
}

//-----------------------------------------------------------------------------
// Purpose: handles the second part of an auth request
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_RequestAuth_IsAuthed(int returnVal, void *dataBlock)
{
	ITrackerUserDatabase::IsAuthed_t *data = (ITrackerUserDatabase::IsAuthed_t *)dataBlock;
	int friendID = data->targetID;

	// if we're blocked, or already authed, we don't need to do any more
	if (data->authLevel > AUTHLEVEL_REQUESTINGAUTH || data->blocked)
		return;

	// grant rights to the friend to be able to get our status
	m_pDB->User_SetAuth(m_iUserID, friendID, AUTHLEVEL_REQUESTINGAUTH);
	ITrackerUserDatabase *friendDB = g_pDataManager->TrackerUser(friendID);
	if (friendDB && friendDB != m_pDB)
	{
		friendDB->User_SetAuth(m_iUserID, friendID, AUTHLEVEL_REQUESTINGAUTH);
	}

	// post an request authorization message
	PostMessageToUser(m_iUserID, friendID, data->extraData, MESSAGEFLAG_REQUESTAUTH | MESSAGEFLAG_AUTHED);
}

//-----------------------------------------------------------------------------
// Purpose: sends the users status to all the friends marked to watch them
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_GetWatchers(int returnVal, void *dataBlock)
{
	int count = returnVal;

	ITrackerUserDatabase::watcher_t *watcher = (ITrackerUserDatabase::watcher_t *)dataBlock;

	// construct the message to send to all the watchers
	CUtlMsgBuffer msgBuffer;
	msgBuffer.WriteInt("_id", TSVC_FRIENDUPDATE);
	msgBuffer.WriteUInt("userID", m_iUserID);
	msgBuffer.WriteInt("status", m_iStatus);
	msgBuffer.WriteUInt("sessionID", m_iSessionID);
	msgBuffer.WriteUInt("serverID", topology()->GetServerID());
	msgBuffer.WriteUInt("IP", m_NetAddress.IP());
	msgBuffer.WriteUInt("port", m_NetAddress.Port());
	if (m_iStatus == STATUS_INGAME && m_iGameIP && m_iGamePort)
	{
		// send down game info as well
		msgBuffer.WriteUInt("GameIP", m_iGameIP);
		msgBuffer.WriteUInt("GamePort", m_iGamePort);
		msgBuffer.WriteString("Game", m_szGameType);
	}

	// loop through all the watchers and send each of them the status update message
	for (int i = 0; i < count; i++)
	{
		if (!watcher[i].userServerID)
			continue;	//!! watcher has bogus info

		if (m_iUserID == watcher[i].userID)
			continue;

		// send the message, routed through the users' server
		topology()->SendNetworkMessageToUser(watcher[i].userID, watcher[i].userSessionID, watcher[i].userServerID, TSVC_FRIENDUPDATE, msgBuffer.Base(), msgBuffer.DataSize());
	}

	// if we're sending our offline status, then this will be the last message we send
	if (m_iStatus == STATUS_OFFLINE)
	{
		// kill the session
		sessionmanager()->FreeUserSession(this);
	}
}

//-----------------------------------------------------------------------------
// Purpose: Basic sort function, for use in qsort
//-----------------------------------------------------------------------------
static int __cdecl IntegerSortFunc(const void *elem1, const void *elem2)
{
	ITrackerUserDatabase::simpleuser_t *e1 = (ITrackerUserDatabase::simpleuser_t *)elem1;
	ITrackerUserDatabase::simpleuser_t *e2 = (ITrackerUserDatabase::simpleuser_t *)elem2;

	if (e1->userID > e2->userID)
	{
		return 1;
	}
	return -1;
}

//-----------------------------------------------------------------------------
// Purpose: Sends a list of friends' status to the friend
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_GetFriendStatus(int returnVal, void *dataBlock)
{
	if (returnVal < 1)
		return;	// no friends

	static const int MAX_USERS = 400;
	static const int MAX_USERS_PER_PACKET = 40;

	// get the data
	ITrackerUserDatabase::user_t *user = (ITrackerUserDatabase::user_t *)dataBlock;
	int count = returnVal;

	if (count >= MAX_USERS)
	{
		g_pConsole->Print(10, "SendStatusOfFriends: user %d has too many friends\n", m_iUserID);
	}

	int friendsUnsent = count;
	ITrackerUserDatabase::user_t *usersToSend = user;
	while (friendsUnsent > 0)
	{
		// create the packet
		ISendMessage *msg = CreateUserMessage(TSVC_FRIENDS);

		// work out how many friends we can fit in this packet
		int processAmount = MAX_USERS_PER_PACKET;
		if (processAmount > friendsUnsent)
		{
			processAmount = friendsUnsent;
		}

		msg->WriteInt("count", processAmount);

		unsigned int msgBuf[MAX_USERS_PER_PACKET * 6];
		int bytesWritten = ConstructFriendsStatusMessageData(usersToSend, processAmount, msgBuf);
		msg->WriteBlob("status", msgBuf, bytesWritten);

		// send the message
		SendMessage(msg, NET_RELIABLE);

		// advance the count
		friendsUnsent -= processAmount;
		usersToSend += processAmount;
	}

	// build a new list of our ingame friends and get their status
	{
		ITrackerUserDatabase::simpleuser_t gamers[MAX_USERS];
		int gamerCount = 0;

		// find all users who are in a game
		for (int i = 0; i < count; i++)
		{
			if (user[i].userStatus == STATUS_INGAME)
			{
				gamers[gamerCount++].userID = user[i].userID;
			}
		}

		if (gamerCount < 1)
			return;	// no gamers in our list

		// batch up users per database
		ITrackerUserDatabase *previousDatabase = g_pDataManager->BaseTrackerUser(gamers[0].userID);
		i = 0;
		int batchCount = 0;
		ITrackerUserDatabase::simpleuser_t *batchStart = gamers + 0;
		while (previousDatabase)
		{
			// get the database
			ITrackerUserDatabase *db;
			if (i == gamerCount)
			{
				db = NULL;
			}
			else
			{
				db = g_pDataManager->BaseTrackerUser(gamers[i].userID);
			}
			
			if (db == previousDatabase)
			{
				i++;
				batchCount++;
				continue;
			}

			if (db != previousDatabase)
			{
				// finish up with the previous server and the batch of users on it

				// get the state of friends in this set
				previousDatabase->User_GetFriendsGameStatus(this, m_iUserID, batchStart, batchCount);

				// move to the next db
				previousDatabase = db;
				batchCount = 0;
				batchStart = gamers + i;
			}

			// go to the next user
			i++;
			batchCount++;
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: Handles the return of a bunch of friends' ingame status
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_GetFriendsGameStatus(int returnVal, void *dataBlock)
{
	if (returnVal < 1)
		return;	// no friends

	// get the data
	ITrackerUserDatabase::gameuser_t *user = (ITrackerUserDatabase::gameuser_t *)dataBlock;
	int count = returnVal;

	// send a packet per friend
	for (int i = 0; i < count; i++)
	{
		if (user[i].userStatus != STATUS_INGAME || user[i].gameIP == 0)
			continue;

		ISendMessage *msg = CreateUserMessage(TSVC_GAMEINFO);

		// write in the details
		// they should already know the sessionID/IP/port of the user
		msg->WriteUInt("userID", user[i].userID);
		msg->WriteInt("status", user[i].userStatus);
		msg->WriteUInt("GameIP", user[i].gameIP);
		msg->WriteUInt("GamePort", user[i].gamePort);
		msg->WriteString("Game", user[i].gameType);

		// send
		SendMessage(msg, NET_RELIABLE);
	}
}


//-----------------------------------------------------------------------------
// Purpose: Takes a list of users, and adds watches to them
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_GetFriendList(int returnVal, void *dataBlock)
{
	if (returnVal < 1)
		return;	// no friends

	ITrackerUserDatabase::simpleuser_t *user = (ITrackerUserDatabase::simpleuser_t *)dataBlock;
	int friendCount = returnVal;

	// sort the list of friends by their userID, so we ensure they are grouped correctly
	qsort(dataBlock, friendCount, sizeof(ITrackerUserDatabase::simpleuser_t), IntegerSortFunc);

	// batch up a set of users
	ITrackerUserDatabase *previousDatabase = g_pDataManager->BaseTrackerUser(user[0].userID);
	int i = 0;
	int batchCount = 0;
	ITrackerUserDatabase::simpleuser_t *batchStart = user + 0;
	while (previousDatabase)
	{
		// get the database
		ITrackerUserDatabase *db;
		if (i == friendCount)
		{
			db = NULL;
		}
		else
		{
			db = g_pDataManager->BaseTrackerUser(user[i].userID);
		}
		
		if (db == previousDatabase)
		{
			i++;
			batchCount++;
			continue;
		}

		if (db != previousDatabase)
		{
			// finish up with the previous server and the batch of users on it

			// add watches to these users (this call is non-blocking)
			previousDatabase->User_AddWatcher(m_iUserID, m_iSessionID, topology()->GetServerID(), batchStart, batchCount);

			// get the state of friends in this set
			previousDatabase->User_GetFriendsStatus(this, m_iUserID, batchStart, batchCount);

			// move to the next db
			previousDatabase = db;
			batchCount = 0;
			batchStart = user + i;
		}

		// go to the next user
		i++;
		batchCount++;
	}
}

//-----------------------------------------------------------------------------
// Purpose: We have retrieved a message
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_GetMessage(int returnVal, void *dataBlock)
{
	if (returnVal < 1)
		return;  // no message, so bail
	
	ITrackerUserDatabase::UserMessage_t *data = (ITrackerUserDatabase::UserMessage_t *)dataBlock;

	// make sure the user is in the specified build range
	if ((!data->mininumBuild || m_iBuildNum >= data->mininumBuild) && (!data->maximumBuild || m_iBuildNum <= data->maximumBuild))
	{
		// send to the user the message
		ISendMessage *msg = CreateUserMessage(TSVC_MESSAGE);

		msg->WriteUInt("uid", data->fromUserID);
		msg->WriteString("UserName", data->name);
		msg->WriteString("Text", data->text);
		msg->WriteInt("flags", data->flags);

		SendMessage(msg, NET_RELIABLE);
	}

	// delete the message from the db
	m_pDB->User_DeleteMessage(this, m_iUserID, data->msgID);
}

//-----------------------------------------------------------------------------
// Purpose: Delete message has returned
//-----------------------------------------------------------------------------
void CUserSession::DBMsg_DeleteMessage(int returnVal, void *data)
{
	if (returnVal > 0)
	{
		// message has been deleted successfully, so check for more messages
		m_pDB->User_GetMessage(this, m_iUserID);
	}
}

//-----------------------------------------------------------------------------
// Purpose: Safe string copy
//-----------------------------------------------------------------------------
void v_strncpy(char *dest, const char *src, int bufsize)
{
	if (src == dest)
		return;

	strncpy(dest, src, bufsize - 1);
	dest[bufsize - 1] = 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -