diff --git a/steamnet/steam_message_handler.cpp b/steamnet/steam_message_handler.cpp index 25e0987..e2e0fe7 100644 --- a/steamnet/steam_message_handler.cpp +++ b/steamnet/steam_message_handler.cpp @@ -52,7 +52,7 @@ void SteamMessageHandler::run() { pollMessages(); // Sleep a bit to avoid busy loop - std::this_thread::sleep_for(std::chrono::milliseconds(10)); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } } diff --git a/steamnet/steam_networking_manager.cpp b/steamnet/steam_networking_manager.cpp index 56c8863..313ec34 100644 --- a/steamnet/steam_networking_manager.cpp +++ b/steamnet/steam_networking_manager.cpp @@ -2,78 +2,111 @@ #include #include -SteamNetworkingManager* SteamNetworkingManager::instance = nullptr; +SteamNetworkingManager *SteamNetworkingManager::instance = nullptr; + +SteamNetworkingConfigValue_t g_connectionConfig; // Static callback function -void SteamNetworkingManager::OnSteamNetConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *pInfo) { - if (instance) { +void SteamNetworkingManager::OnSteamNetConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *pInfo) +{ + if (instance) + { instance->handleConnectionStatusChanged(pInfo); } } -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_) { - const char* connectStr = pCallback->m_rgchConnect; + if (manager_) + { + const char *connectStr = pCallback->m_rgchConnect; std::cout << "Connect string: '" << (connectStr ? connectStr : "null") << "'" << std::endl; - if (connectStr && connectStr[0] != '\0') { - try { + if (connectStr && connectStr[0] != '\0') + { + try + { uint64 id = std::stoull(connectStr); std::string str = connectStr; std::cout << "Parsed ID: " << id << std::endl; - if (str.find("7656119") == 0) { + 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()) { + if (!manager_->isHost() && !manager_->isConnected()) + { manager_->joinHost(id); // Start TCP Server if dependencies are set - if (manager_->server_ && !(*manager_->server_)) { + if (manager_->server_ && !(*manager_->server_)) + { *manager_->server_ = std::make_unique(8888, manager_); - if (!(*manager_->server_)->start()) { + if (!(*manager_->server_)->start()) + { std::cerr << "Failed to start TCP server" << std::endl; } } - } else { + } + else + { std::cout << "Already host or connected, ignoring join request" << std::endl; } - } else { + } + else + { // Assume it's a lobby ID CSteamID lobbySteamID(id); std::cout << "Parsed lobby ID: " << id << std::endl; - if (!manager_->isHost() && !manager_->isConnected()) { + if (!manager_->isHost() && !manager_->isConnected()) + { std::cout << "Joining lobby from invite: " << id << std::endl; manager_->joinLobby(lobbySteamID); - } else { + } + else + { std::cout << "Already host or connected, ignoring invite" << std::endl; } } - } catch (const std::exception& e) { + } + catch (const std::exception &e) + { std::cerr << "Failed to parse connect string: " << connectStr << " error: " << e.what() << std::endl; } - } else { + } + else + { std::cerr << "Empty connect string in join request" << std::endl; } - } else { + } + else + { std::cout << "Manager is null" << std::endl; } } -void SteamFriendsCallbacks::OnGameLobbyJoinRequested(GameLobbyJoinRequested_t *pCallback) { +void SteamFriendsCallbacks::OnGameLobbyJoinRequested(GameLobbyJoinRequested_t *pCallback) +{ std::cout << "GameLobbyJoinRequested received" << std::endl; - if (manager_) { + if (manager_) + { CSteamID lobbyID = pCallback->m_steamIDLobby; std::cout << "Lobby ID: " << lobbyID.ConvertToUint64() << std::endl; - if (!manager_->isHost() && !manager_->isConnected()) { + if (!manager_->isHost() && !manager_->isConnected()) + { std::cout << "Joining lobby from request: " << lobbyID.ConvertToUint64() << std::endl; manager_->joinLobby(lobbyID); - } else { + } + else + { std::cout << "Already host or connected, ignoring lobby join request" << std::endl; } - } else { + } + else + { std::cout << "Manager is null" << std::endl; } } @@ -82,13 +115,16 @@ SteamNetworkingManager::SteamNetworkingManager() : 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), io_context_(nullptr), clientMap_(nullptr), clientMutex_(nullptr), server_(nullptr), localPort_(nullptr), messageHandler_(nullptr), - steamFriendsCallbacks(nullptr), steamMatchmakingCallbacks(nullptr), currentLobby(k_steamIDNil) { + steamFriendsCallbacks(nullptr), steamMatchmakingCallbacks(nullptr), currentLobby(k_steamIDNil) +{ // Initialize connection config - g_connectionConfig[0].SetInt32(k_ESteamNetworkingConfig_TimeoutInitial, 10000); - g_connectionConfig[1].SetInt32(k_ESteamNetworkingConfig_NagleTime, 0); + g_connectionConfig[0].SetInt32(k_ESteamNetworkingConfig_P2P_Transport_ICE_Enable, k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_All); + g_connectionConfig[1].SetInt32(k_ESteamNetworkingConfig_P2P_Transport_SDR_Penalty, 300); + std::cout << "Initialized SteamNetworkingManager" << std::endl; } -SteamNetworkingManager::~SteamNetworkingManager() { +SteamNetworkingManager::~SteamNetworkingManager() +{ stopMessageHandler(); delete messageHandler_; delete steamFriendsCallbacks; @@ -96,9 +132,11 @@ SteamNetworkingManager::~SteamNetworkingManager() { shutdown(); } -bool SteamNetworkingManager::initialize() { +bool SteamNetworkingManager::initialize() +{ instance = this; - if (!SteamAPI_Init()) { + if (!SteamAPI_Init()) + { std::cerr << "Failed to initialize Steam API" << std::endl; return false; } @@ -121,21 +159,25 @@ bool SteamNetworkingManager::initialize() { // Get friends list int friendCount = SteamFriends()->GetFriendCount(k_EFriendFlagAll); - for (int i = 0; i < friendCount; ++i) { + for (int i = 0; i < friendCount; ++i) + { CSteamID friendID = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll); - const char* name = SteamFriends()->GetFriendPersonaName(friendID); + const char *name = SteamFriends()->GetFriendPersonaName(friendID); friendsList.push_back({friendID, name}); } return true; } -void SteamNetworkingManager::shutdown() { +void SteamNetworkingManager::shutdown() +{ leaveLobby(); - if (g_hConnection != k_HSteamNetConnection_Invalid) { + if (g_hConnection != k_HSteamNetConnection_Invalid) + { m_pInterface->CloseConnection(g_hConnection, 0, nullptr, false); } - if (hListenSock != k_HSteamListenSocket_Invalid) { + if (hListenSock != k_HSteamListenSocket_Invalid) + { m_pInterface->CloseListenSocket(hListenSock); } // Clear Rich Presence on shutdown @@ -143,9 +185,11 @@ void SteamNetworkingManager::shutdown() { SteamAPI_Shutdown(); } -bool SteamNetworkingManager::createLobby() { +bool SteamNetworkingManager::createLobby() +{ SteamAPICall_t hSteamAPICall = SteamMatchmaking()->CreateLobby(k_ELobbyTypePublic, 4); - if (hSteamAPICall == k_uAPICallInvalid) { + if (hSteamAPICall == k_uAPICallInvalid) + { std::cerr << "Failed to create lobby" << std::endl; return false; } @@ -153,17 +197,21 @@ bool SteamNetworkingManager::createLobby() { return true; } -void SteamNetworkingManager::leaveLobby() { - if (currentLobby != k_steamIDNil) { +void SteamNetworkingManager::leaveLobby() +{ + if (currentLobby != k_steamIDNil) + { SteamMatchmaking()->LeaveLobby(currentLobby); currentLobby = k_steamIDNil; } } -bool SteamNetworkingManager::searchLobbies() { +bool SteamNetworkingManager::searchLobbies() +{ lobbies.clear(); SteamAPICall_t hSteamAPICall = SteamMatchmaking()->RequestLobbyList(); - if (hSteamAPICall == k_uAPICallInvalid) { + if (hSteamAPICall == k_uAPICallInvalid) + { std::cerr << "Failed to request lobby list" << std::endl; return false; } @@ -171,8 +219,10 @@ bool SteamNetworkingManager::searchLobbies() { return true; } -bool SteamNetworkingManager::joinLobby(CSteamID lobbyID) { - if (SteamMatchmaking()->JoinLobby(lobbyID) != k_EResultOK) { +bool SteamNetworkingManager::joinLobby(CSteamID lobbyID) +{ + if (SteamMatchmaking()->JoinLobby(lobbyID) != k_EResultOK) + { std::cerr << "Failed to join lobby" << std::endl; return false; } @@ -180,25 +230,32 @@ bool SteamNetworkingManager::joinLobby(CSteamID lobbyID) { return true; } -bool SteamNetworkingManager::startHosting() { - if (!createLobby()) { +bool SteamNetworkingManager::startHosting() +{ + if (!createLobby()) + { return false; } - hListenSock = m_pInterface->CreateListenSocketP2P(0, 0, nullptr); - if (hListenSock != k_HSteamListenSocket_Invalid) { + hListenSock = m_pInterface->CreateListenSocketP2P(0, 0, g_connectionConfig); + if (hListenSock != k_HSteamListenSocket_Invalid) + { g_isHost = true; std::cout << "Created listen socket for hosting game room" << std::endl; // Rich Presence is set in OnLobbyCreated callback return true; - } else { + } + else + { std::cerr << "Failed to create listen socket for hosting" << std::endl; leaveLobby(); return false; } } -void SteamNetworkingManager::stopHosting() { - if (hListenSock != k_HSteamListenSocket_Invalid) { +void SteamNetworkingManager::stopHosting() +{ + if (hListenSock != k_HSteamListenSocket_Invalid) + { m_pInterface->CloseListenSocket(hListenSock); hListenSock = k_HSteamListenSocket_Invalid; } @@ -206,7 +263,8 @@ void SteamNetworkingManager::stopHosting() { g_isHost = false; } -bool SteamNetworkingManager::joinHost(uint64 hostID) { +bool SteamNetworkingManager::joinHost(uint64 hostID) +{ CSteamID hostSteamID(hostID); g_isClient = true; g_hostSteamID = hostSteamID; @@ -215,16 +273,20 @@ bool SteamNetworkingManager::joinHost(uint64 hostID) { SteamNetworkingIdentity identity; identity.SetSteamID(hostSteamID); g_hConnection = m_pInterface->ConnectP2P(identity, g_currentVirtualPort, 2, g_connectionConfig); - if (g_hConnection != k_HSteamNetConnection_Invalid) { + if (g_hConnection != k_HSteamNetConnection_Invalid) + { std::cout << "Attempting to connect to host " << hostSteamID.ConvertToUint64() << " with virtual port " << g_currentVirtualPort << std::endl; return true; - } else { + } + else + { std::cerr << "Failed to initiate connection" << std::endl; return false; } } -void SteamNetworkingManager::setMessageHandlerDependencies(boost::asio::io_context& io_context, std::map>& clientMap, std::mutex& clientMutex, std::unique_ptr& server, int& localPort) { +void SteamNetworkingManager::setMessageHandlerDependencies(boost::asio::io_context &io_context, std::map> &clientMap, std::mutex &clientMutex, std::unique_ptr &server, int &localPort) +{ io_context_ = &io_context; clientMap_ = &clientMap; clientMutex_ = &clientMutex; @@ -233,39 +295,49 @@ void SteamNetworkingManager::setMessageHandlerDependencies(boost::asio::io_conte messageHandler_ = new SteamMessageHandler(io_context, m_pInterface, connections, clientMap, clientMutex, connectionsMutex, server, g_isHost, localPort); } -void SteamNetworkingManager::startMessageHandler() { - if (messageHandler_) { +void SteamNetworkingManager::startMessageHandler() +{ + if (messageHandler_) + { messageHandler_->start(); } } -void SteamNetworkingManager::stopMessageHandler() { - if (messageHandler_) { +void SteamNetworkingManager::stopMessageHandler() +{ + if (messageHandler_) + { messageHandler_->stop(); } } -void SteamNetworkingManager::update() { +void SteamNetworkingManager::update() +{ std::lock_guard lock(connectionsMutex); - for (auto& pair : userMap) { + for (auto &pair : userMap) + { HSteamNetConnection conn = pair.first; - UserInfo& userInfo = pair.second; + UserInfo &userInfo = pair.second; SteamNetConnectionInfo_t info; SteamNetConnectionRealTimeStatus_t status; - if (m_pInterface->GetConnectionInfo(conn, &info) && m_pInterface->GetConnectionRealTimeStatus(conn, &status, 0, nullptr)) { + if (m_pInterface->GetConnectionInfo(conn, &info) && m_pInterface->GetConnectionRealTimeStatus(conn, &status, 0, nullptr)) + { userInfo.ping = status.m_nPing; userInfo.isRelay = (info.m_idPOPRelay != 0); } } } -void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *pInfo) { +void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *pInfo) +{ std::lock_guard lock(connectionsMutex); std::cout << "Connection status changed: " << pInfo->m_info.m_eState << " for connection " << pInfo->m_hConn << std::endl; - if (pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_ProblemDetectedLocally) { + if (pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_ProblemDetectedLocally) + { std::cout << "Connection failed: " << pInfo->m_info.m_szEndDebug << std::endl; } - if (pInfo->m_eOldState == k_ESteamNetworkingConnectionState_None && pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_Connecting) { + if (pInfo->m_eOldState == k_ESteamNetworkingConnectionState_None && pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_Connecting) + { m_pInterface->AcceptConnection(pInfo->m_hConn); connections.push_back(pInfo->m_hConn); g_hConnection = pInfo->m_hConn; @@ -274,7 +346,8 @@ void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionSta // Add user info SteamNetConnectionInfo_t info; SteamNetConnectionRealTimeStatus_t status; - if (m_pInterface->GetConnectionInfo(pInfo->m_hConn, &info) && m_pInterface->GetConnectionRealTimeStatus(pInfo->m_hConn, &status, 0, nullptr)) { + if (m_pInterface->GetConnectionInfo(pInfo->m_hConn, &info) && m_pInterface->GetConnectionRealTimeStatus(pInfo->m_hConn, &status, 0, nullptr)) + { UserInfo userInfo; userInfo.steamID = pInfo->m_info.m_identityRemote.GetSteamID(); userInfo.name = SteamFriends()->GetFriendPersonaName(userInfo.steamID); @@ -283,13 +356,16 @@ void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionSta userMap[pInfo->m_hConn] = userInfo; std::cout << "Incoming connection details: ping=" << status.m_nPing << "ms, relay=" << (info.m_idPOPRelay != 0 ? "yes" : "no") << std::endl; } - } else if (pInfo->m_eOldState == k_ESteamNetworkingConnectionState_Connecting && pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_Connected) { + } + else if (pInfo->m_eOldState == k_ESteamNetworkingConnectionState_Connecting && pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_Connected) + { g_isConnected = true; std::cout << "Connected to host" << std::endl; // Add user info SteamNetConnectionInfo_t info; SteamNetConnectionRealTimeStatus_t status; - if (m_pInterface->GetConnectionInfo(pInfo->m_hConn, &info) && m_pInterface->GetConnectionRealTimeStatus(pInfo->m_hConn, &status, 0, nullptr)) { + if (m_pInterface->GetConnectionInfo(pInfo->m_hConn, &info) && m_pInterface->GetConnectionRealTimeStatus(pInfo->m_hConn, &status, 0, nullptr)) + { UserInfo userInfo; userInfo.steamID = pInfo->m_info.m_identityRemote.GetSteamID(); userInfo.name = SteamFriends()->GetFriendPersonaName(userInfo.steamID); @@ -298,38 +374,47 @@ void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionSta userMap[pInfo->m_hConn] = userInfo; std::cout << "Outgoing connection details: ping=" << status.m_nPing << "ms, relay=" << (info.m_idPOPRelay != 0 ? "yes" : "no") << std::endl; } - } else if (pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_ClosedByPeer || pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_ProblemDetectedLocally) { + } + else if (pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_ClosedByPeer || pInfo->m_info.m_eState == k_ESteamNetworkingConnectionState_ProblemDetectedLocally) + { g_isConnected = false; g_hConnection = k_HSteamNetConnection_Invalid; // Remove from connections auto it = std::find(connections.begin(), connections.end(), pInfo->m_hConn); - if (it != connections.end()) { + if (it != connections.end()) + { connections.erase(it); } userMap.erase(pInfo->m_hConn); std::cout << "Connection closed" << std::endl; // Retry if client - if (g_isClient && !g_isConnected && g_retryCount < MAX_RETRIES) { + if (g_isClient && !g_isConnected && g_retryCount < MAX_RETRIES) + { g_retryCount++; g_currentVirtualPort++; SteamNetworkingIdentity identity; identity.SetSteamID(g_hostSteamID); HSteamNetConnection newConn = m_pInterface->ConnectP2P(identity, g_currentVirtualPort, 2, g_connectionConfig); - if (newConn != k_HSteamNetConnection_Invalid) { + if (newConn != k_HSteamNetConnection_Invalid) + { g_hConnection = newConn; std::cout << "Retrying connection attempt " << g_retryCount << " with virtual port " << g_currentVirtualPort << std::endl; - } else { + } + else + { std::cerr << "Failed to initiate retry connection" << std::endl; } } } } -SteamMatchmakingCallbacks::SteamMatchmakingCallbacks(SteamNetworkingManager* manager) : manager_(manager) {} +SteamMatchmakingCallbacks::SteamMatchmakingCallbacks(SteamNetworkingManager *manager) : manager_(manager) {} -void SteamMatchmakingCallbacks::OnLobbyCreated(LobbyCreated_t *pCallback) { - if (pCallback->m_eResult == k_EResultOK) { +void SteamMatchmakingCallbacks::OnLobbyCreated(LobbyCreated_t *pCallback) +{ + if (pCallback->m_eResult == k_EResultOK) + { manager_->currentLobby = pCallback->m_ulSteamIDLobby; std::cout << "Lobby created: " << manager_->currentLobby.ConvertToUint64() << std::endl; // Set Rich Presence with lobby ID @@ -338,38 +423,50 @@ void SteamMatchmakingCallbacks::OnLobbyCreated(LobbyCreated_t *pCallback) { 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; } } -void SteamMatchmakingCallbacks::OnLobbyListReceived(LobbyMatchList_t *pCallback) { +void SteamMatchmakingCallbacks::OnLobbyListReceived(LobbyMatchList_t *pCallback) +{ manager_->lobbies.clear(); - for (uint32 i = 0; i < pCallback->m_nLobbiesMatching; ++i) { + for (uint32 i = 0; i < pCallback->m_nLobbiesMatching; ++i) + { CSteamID lobbyID = SteamMatchmaking()->GetLobbyByIndex(i); manager_->lobbies.push_back(lobbyID); } std::cout << "Received " << pCallback->m_nLobbiesMatching << " lobbies" << std::endl; } -void SteamMatchmakingCallbacks::OnLobbyEntered(LobbyEnter_t *pCallback) { - if (pCallback->m_EChatRoomEnterResponse == k_EChatRoomEnterResponseSuccess) { +void SteamMatchmakingCallbacks::OnLobbyEntered(LobbyEnter_t *pCallback) +{ + if (pCallback->m_EChatRoomEnterResponse == k_EChatRoomEnterResponseSuccess) + { manager_->currentLobby = pCallback->m_ulSteamIDLobby; std::cout << "Entered lobby: " << pCallback->m_ulSteamIDLobby << std::endl; // Only join host if not the host - if (!manager_->isHost()) { + if (!manager_->isHost()) + { CSteamID hostID = SteamMatchmaking()->GetLobbyOwner(pCallback->m_ulSteamIDLobby); - if (manager_->joinHost(hostID.ConvertToUint64())) { + if (manager_->joinHost(hostID.ConvertToUint64())) + { // Start TCP Server if dependencies are set - if (manager_->server_ && !(*manager_->server_)) { + if (manager_->server_ && !(*manager_->server_)) + { *manager_->server_ = std::make_unique(8888, manager_); - if (!(*manager_->server_)->start()) { + if (!(*manager_->server_)->start()) + { std::cerr << "Failed to start TCP server" << std::endl; } } } } - } else { + } + else + { std::cerr << "Failed to enter lobby" << std::endl; } } \ No newline at end of file diff --git a/steamnet/steam_networking_manager.h b/steamnet/steam_networking_manager.h index 6d21b09..635d6ab 100644 --- a/steamnet/steam_networking_manager.h +++ b/steamnet/steam_networking_manager.h @@ -119,7 +119,7 @@ private: std::mutex connectionsMutex; // Connection config - SteamNetworkingConfigValue_t g_connectionConfig[2]; + SteamNetworkingConfigValue_t g_connectionConfig[3]; int g_retryCount; const int MAX_RETRIES = 3; int g_currentVirtualPort;