📄 usersession.cpp
字号:
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 + -