增强Steam好友邀请功能,添加连接字符串支持并改进错误处理;实现游戏大厅加入请求的回调

This commit is contained in:
Ayndpa
2025-11-18 21:37:01 +08:00
parent af181bb133
commit e7a09f9d92
3 changed files with 88 additions and 11 deletions

View File

@@ -90,8 +90,15 @@ int main() {
if (filterStr.empty() || nameStr.find(filterStr) != std::string::npos) { if (filterStr.empty() || nameStr.find(filterStr) != std::string::npos) {
ImGui::PushID(friendPair.first.ConvertToUint64()); ImGui::PushID(friendPair.first.ConvertToUint64());
if (ImGui::Button(("邀请 " + friendPair.second).c_str())) { if (ImGui::Button(("邀请 " + friendPair.second).c_str())) {
// Send invite via Steam // Send invite via Steam with lobby ID as connect string
SteamFriends()->InviteUserToGame(friendPair.first, "加入我的游戏房间!"); std::string connectStr = std::to_string(steamManager.getCurrentLobby().ConvertToUint64());
// Safety check for SteamFriends
if (SteamFriends()) {
SteamFriends()->InviteUserToGame(friendPair.first, connectStr.c_str());
std::cout << "Sent invite to " << friendPair.second << " with connect string: " << connectStr << std::endl;
} else {
std::cerr << "SteamFriends() is null! Cannot send invite." << std::endl;
}
} }
ImGui::PopID(); ImGui::PopID();
} }

View File

@@ -11,18 +11,70 @@ void SteamNetworkingManager::OnSteamNetConnectionStatusChanged(SteamNetConnectio
} }
} }
SteamFriendsCallbacks::SteamFriendsCallbacks(SteamNetworkingManager* manager) : manager_(manager) {} SteamFriendsCallbacks::SteamFriendsCallbacks(SteamNetworkingManager* manager) : manager_(manager) {
std::cout << "SteamFriendsCallbacks constructor called" << std::endl;
}
void SteamFriendsCallbacks::OnGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t *pCallback) { void SteamFriendsCallbacks::OnGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t *pCallback) {
std::cout << "GameRichPresenceJoinRequested received" << std::endl;
if (manager_) { if (manager_) {
const char* connectStr = SteamFriends()->GetFriendRichPresence(pCallback->m_steamIDFriend, "connect"); const char* connectStr = pCallback->m_rgchConnect;
std::cout << "Connect string: '" << (connectStr ? connectStr : "null") << "'" << std::endl;
if (connectStr && connectStr[0] != '\0') { if (connectStr && connectStr[0] != '\0') {
uint64 lobbyID = std::stoull(connectStr); try {
CSteamID lobbySteamID(lobbyID); uint64 id = std::stoull(connectStr);
if (!manager_->isHost() && !manager_->isConnected()) { std::string str = connectStr;
manager_->joinLobby(lobbySteamID); std::cout << "Parsed ID: " << id << std::endl;
if (str.find("7656119") == 0) {
// It's a Steam ID, join host directly
std::cout << "Parsed Steam ID: " << id << ", joining host" << std::endl;
if (!manager_->isHost() && !manager_->isConnected()) {
manager_->joinHost(id);
// Start TCP Server if dependencies are set
if (manager_->server_ && !(*manager_->server_)) {
*manager_->server_ = std::make_unique<TCPServer>(8888, manager_);
if (!(*manager_->server_)->start()) {
std::cerr << "Failed to start TCP server" << std::endl;
}
}
} else {
std::cout << "Already host or connected, ignoring join request" << std::endl;
}
} else {
// Assume it's a lobby ID
CSteamID lobbySteamID(id);
std::cout << "Parsed lobby ID: " << id << std::endl;
if (!manager_->isHost() && !manager_->isConnected()) {
std::cout << "Joining lobby from invite: " << id << std::endl;
manager_->joinLobby(lobbySteamID);
} else {
std::cout << "Already host or connected, ignoring invite" << std::endl;
}
}
} catch (const std::exception& e) {
std::cerr << "Failed to parse connect string: " << connectStr << " error: " << e.what() << std::endl;
} }
} else {
std::cerr << "Empty connect string in join request" << std::endl;
} }
} else {
std::cout << "Manager is null" << std::endl;
}
}
void SteamFriendsCallbacks::OnGameLobbyJoinRequested(GameLobbyJoinRequested_t *pCallback) {
std::cout << "GameLobbyJoinRequested received" << std::endl;
if (manager_) {
CSteamID lobbyID = pCallback->m_steamIDLobby;
std::cout << "Lobby ID: " << lobbyID.ConvertToUint64() << std::endl;
if (!manager_->isHost() && !manager_->isConnected()) {
std::cout << "Joining lobby from request: " << lobbyID.ConvertToUint64() << std::endl;
manager_->joinLobby(lobbyID);
} else {
std::cout << "Already host or connected, ignoring lobby join request" << std::endl;
}
} else {
std::cout << "Manager is null" << std::endl;
} }
} }
@@ -30,7 +82,7 @@ SteamNetworkingManager::SteamNetworkingManager()
: m_pInterface(nullptr), hListenSock(k_HSteamListenSocket_Invalid), g_isHost(false), g_isClient(false), g_isConnected(false), : m_pInterface(nullptr), hListenSock(k_HSteamListenSocket_Invalid), g_isHost(false), g_isClient(false), g_isConnected(false),
g_hConnection(k_HSteamNetConnection_Invalid), g_retryCount(0), g_currentVirtualPort(0), g_hConnection(k_HSteamNetConnection_Invalid), g_retryCount(0), g_currentVirtualPort(0),
io_context_(nullptr), clientMap_(nullptr), clientMutex_(nullptr), server_(nullptr), localPort_(nullptr), messageHandler_(nullptr), io_context_(nullptr), clientMap_(nullptr), clientMutex_(nullptr), server_(nullptr), localPort_(nullptr), messageHandler_(nullptr),
steamFriendsCallbacks(this), steamMatchmakingCallbacks(this), currentLobby(k_steamIDNil) { steamFriendsCallbacks(nullptr), steamMatchmakingCallbacks(nullptr), currentLobby(k_steamIDNil) {
// Initialize connection config // Initialize connection config
g_connectionConfig[0].SetInt32(k_ESteamNetworkingConfig_TimeoutInitial, 10000); g_connectionConfig[0].SetInt32(k_ESteamNetworkingConfig_TimeoutInitial, 10000);
g_connectionConfig[1].SetInt32(k_ESteamNetworkingConfig_NagleTime, 0); g_connectionConfig[1].SetInt32(k_ESteamNetworkingConfig_NagleTime, 0);
@@ -39,6 +91,8 @@ SteamNetworkingManager::SteamNetworkingManager()
SteamNetworkingManager::~SteamNetworkingManager() { SteamNetworkingManager::~SteamNetworkingManager() {
stopMessageHandler(); stopMessageHandler();
delete messageHandler_; delete messageHandler_;
delete steamFriendsCallbacks;
delete steamMatchmakingCallbacks;
shutdown(); shutdown();
} }
@@ -49,11 +103,22 @@ bool SteamNetworkingManager::initialize() {
return false; return false;
} }
// Create callbacks after Steam API init
steamFriendsCallbacks = new SteamFriendsCallbacks(this);
steamMatchmakingCallbacks = new SteamMatchmakingCallbacks(this);
SteamNetworkingUtils()->InitRelayNetworkAccess(); SteamNetworkingUtils()->InitRelayNetworkAccess();
SteamNetworkingUtils()->SetGlobalCallback_SteamNetConnectionStatusChanged(OnSteamNetConnectionStatusChanged); SteamNetworkingUtils()->SetGlobalCallback_SteamNetConnectionStatusChanged(OnSteamNetConnectionStatusChanged);
m_pInterface = SteamNetworkingSockets(); m_pInterface = SteamNetworkingSockets();
// Clear Rich Presence on startup
SteamFriends()->ClearRichPresence();
std::cout << "Cleared Rich Presence on startup" << std::endl;
// Check if callbacks are registered
std::cout << "Steam API initialized, callbacks should be registered" << std::endl;
// Get friends list // Get friends list
int friendCount = SteamFriends()->GetFriendCount(k_EFriendFlagAll); int friendCount = SteamFriends()->GetFriendCount(k_EFriendFlagAll);
for (int i = 0; i < friendCount; ++i) { for (int i = 0; i < friendCount; ++i) {
@@ -73,6 +138,8 @@ void SteamNetworkingManager::shutdown() {
if (hListenSock != k_HSteamListenSocket_Invalid) { if (hListenSock != k_HSteamListenSocket_Invalid) {
m_pInterface->CloseListenSocket(hListenSock); m_pInterface->CloseListenSocket(hListenSock);
} }
// Clear Rich Presence on shutdown
SteamFriends()->ClearRichPresence();
SteamAPI_Shutdown(); SteamAPI_Shutdown();
} }
@@ -255,6 +322,8 @@ void SteamMatchmakingCallbacks::OnLobbyCreated(LobbyCreated_t *pCallback) {
std::string lobbyStr = std::to_string(manager_->currentLobby.ConvertToUint64()); std::string lobbyStr = std::to_string(manager_->currentLobby.ConvertToUint64());
SteamFriends()->SetRichPresence("connect", lobbyStr.c_str()); SteamFriends()->SetRichPresence("connect", lobbyStr.c_str());
SteamFriends()->SetRichPresence("status", "主持游戏房间"); SteamFriends()->SetRichPresence("status", "主持游戏房间");
SteamFriends()->SetRichPresence("steam_display", "#StatusWithConnectFormat");
std::cout << "Set Rich Presence connect to: " << lobbyStr << std::endl;
} else { } else {
std::cerr << "Failed to create lobby" << std::endl; std::cerr << "Failed to create lobby" << std::endl;
} }

View File

@@ -22,6 +22,7 @@ class SteamFriendsCallbacks {
public: public:
SteamFriendsCallbacks(SteamNetworkingManager* manager); SteamFriendsCallbacks(SteamNetworkingManager* manager);
STEAM_CALLBACK(SteamFriendsCallbacks, OnGameRichPresenceJoinRequested, GameRichPresenceJoinRequested_t); STEAM_CALLBACK(SteamFriendsCallbacks, OnGameRichPresenceJoinRequested, GameRichPresenceJoinRequested_t);
STEAM_CALLBACK(SteamFriendsCallbacks, OnGameLobbyJoinRequested, GameLobbyJoinRequested_t);
private: private:
SteamNetworkingManager* manager_; SteamNetworkingManager* manager_;
}; };
@@ -122,8 +123,8 @@ private:
// Friends // Friends
std::vector<std::pair<CSteamID, std::string>> friendsList; std::vector<std::pair<CSteamID, std::string>> friendsList;
SteamFriendsCallbacks steamFriendsCallbacks; SteamFriendsCallbacks* steamFriendsCallbacks;
SteamMatchmakingCallbacks steamMatchmakingCallbacks; SteamMatchmakingCallbacks* steamMatchmakingCallbacks;
// Message handler dependencies // Message handler dependencies
boost::asio::io_context* io_context_; boost::asio::io_context* io_context_;