diff --git a/online_game_tool.cpp b/online_game_tool.cpp index a3e93b3..82559e9 100644 --- a/online_game_tool.cpp +++ b/online_game_tool.cpp @@ -21,16 +21,18 @@ using boost::asio::ip::tcp; // New variables for multiple connections and TCP clients std::vector connections; -std::mutex connectionsMutex; // Add mutex for connections +std::mutex connectionsMutex; // Add mutex for connections int localPort = 0; std::unique_ptr server; -int main() { +int main() +{ boost::asio::io_context io_context; // Initialize Steam Networking Manager SteamNetworkingManager steamManager; - if (!steamManager.initialize()) { + if (!steamManager.initialize()) + { std::cerr << "Failed to initialize Steam Networking Manager" << std::endl; return 1; } @@ -39,15 +41,17 @@ int main() { SteamRoomManager roomManager(&steamManager); // Initialize GLFW - if (!glfwInit()) { + if (!glfwInit()) + { std::cerr << "Failed to initialize GLFW" << std::endl; steamManager.shutdown(); return -1; } // Create window - GLFWwindow* window = glfwCreateWindow(1280, 720, "在线游戏工具", nullptr, nullptr); - if (!window) { + GLFWwindow *window = glfwCreateWindow(1280, 720, "在线游戏工具", nullptr, nullptr); + if (!window) + { std::cerr << "Failed to create GLFW window" << std::endl; glfwTerminate(); SteamAPI_Shutdown(); @@ -59,7 +63,7 @@ int main() { // Initialize ImGui IMGUI_CHECKVERSION(); ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); (void)io; // Load Chinese font io.Fonts->AddFontFromFileTTF("font.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); @@ -80,25 +84,32 @@ int main() { char filterBuffer[256] = ""; // Lambda to render invite friends UI - auto renderInviteFriends = [&]() { + auto renderInviteFriends = [&]() + { ImGui::InputText("过滤朋友", filterBuffer, IM_ARRAYSIZE(filterBuffer)); ImGui::Text("朋友:"); - for (const auto& friendPair : SteamUtils::getFriendsList()) { + for (const auto &friendPair : SteamUtils::getFriendsList()) + { std::string nameStr = friendPair.second; std::string filterStr(filterBuffer); // Convert to lowercase for case-insensitive search std::transform(nameStr.begin(), nameStr.end(), nameStr.begin(), ::tolower); std::transform(filterStr.begin(), filterStr.end(), filterStr.begin(), ::tolower); - if (filterStr.empty() || nameStr.find(filterStr) != std::string::npos) { + if (filterStr.empty() || nameStr.find(filterStr) != std::string::npos) + { ImGui::PushID(friendPair.first.ConvertToUint64()); - if (ImGui::Button(("邀请 " + friendPair.second).c_str())) { + if (ImGui::Button(("邀请 " + friendPair.second).c_str())) + { // Send invite via Steam with lobby ID as connect string std::string connectStr = std::to_string(roomManager.getCurrentLobby().ConvertToUint64()); // Safety check for SteamFriends - if (SteamFriends()) { + if (SteamFriends()) + { SteamFriends()->InviteUserToGame(friendPair.first, connectStr.c_str()); std::cout << "Sent invite to " << friendPair.second << " with connect string: " << connectStr << std::endl; - } else { + } + else + { std::cerr << "SteamFriends() is null! Cannot send invite." << std::endl; } } @@ -108,7 +119,8 @@ int main() { }; // Main loop - while (!glfwWindowShouldClose(window)) { + while (!glfwWindowShouldClose(window)) + { // Poll events glfwPollEvents(); @@ -125,82 +137,128 @@ int main() { // Create a window for online game tool ImGui::Begin("在线游戏工具"); - if (server) { + if (server) + { ImGui::Text("TCP服务器监听端口8888"); ImGui::Text("已连接客户端: %d", server->getClientCount()); } ImGui::Separator(); - if (!steamManager.isHost() && !steamManager.isConnected()) { - if (ImGui::Button("主持游戏房间")) { + if (!steamManager.isHost() && !steamManager.isConnected()) + { + if (ImGui::Button("主持游戏房间")) + { roomManager.startHosting(); } - if (ImGui::Button("搜索游戏房间")) { - roomManager.searchLobbies(); - } - ImGui::InputText("主机Steam ID", joinBuffer, IM_ARRAYSIZE(joinBuffer)); - if (ImGui::Button("加入游戏房间")) { + ImGui::InputText("房间ID", joinBuffer, IM_ARRAYSIZE(joinBuffer)); + if (ImGui::Button("加入游戏房间")) + { uint64 hostID = std::stoull(joinBuffer); - if (steamManager.joinHost(hostID)) { + if (steamManager.joinHost(hostID)) + { // Start TCP Server server = std::make_unique(8888, &steamManager); - if (!server->start()) { + if (!server->start()) + { std::cerr << "Failed to start TCP server" << std::endl; } } } - // Display available lobbies - if (!roomManager.getLobbies().empty()) { - ImGui::Text("可用房间:"); - for (const auto& lobbyID : roomManager.getLobbies()) { - std::string lobbyName = "房间 " + std::to_string(lobbyID.ConvertToUint64()); - if (ImGui::Button(lobbyName.c_str())) { - roomManager.joinLobby(lobbyID); - } - } - } } - if (steamManager.isHost()) { - ImGui::Text("正在主持游戏房间。邀请朋友!"); + if (steamManager.isHost()) + { + ImGui::Text("正在主持游戏房间。邀请朋友!"); ImGui::Separator(); ImGui::InputInt("本地端口", &localPort); ImGui::Separator(); renderInviteFriends(); + ImGui::Separator(); + if (ImGui::Button("断开连接")) + { + roomManager.leaveLobby(); + steamManager.disconnect(); + if (server) + { + server->stop(); + server.reset(); + } + } } - if (steamManager.isConnected() && !steamManager.isHost()) { - ImGui::Text("已连接到游戏房间。邀请朋友!"); + if (steamManager.isConnected() && !steamManager.isHost()) + { + ImGui::Text("已连接到游戏房间。邀请朋友!"); ImGui::Separator(); renderInviteFriends(); + ImGui::Separator(); + if (ImGui::Button("断开连接")) + { + roomManager.leaveLobby(); + steamManager.disconnect(); + if (server) + { + server->stop(); + server.reset(); + } + } } ImGui::End(); - // Room status window - only show when hosting or joined - if (steamManager.isHost() || steamManager.isClient()) { + // Room status window - only show when hosting or connected + if ((steamManager.isHost() || steamManager.isConnected()) && roomManager.getCurrentLobby().IsValid()) + { ImGui::Begin("房间状态"); - if (server) { - ImGui::Text("房间内玩家: %d", server->getClientCount() + 1); // +1 for host - } + if (!steamManager.isHost()) { - std::lock_guard lockConn(connectionsMutex); - ImGui::Text("连接的好友: %d", (int)steamManager.getConnections().size()); + ImGui::Text("与主机延迟: %d ms", steamManager.getHostPing()); } ImGui::Separator(); ImGui::Text("用户列表:"); - if (ImGui::BeginTable("UserTable", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) { + int columnCount = steamManager.isHost() ? 2 : 1; + if (ImGui::BeginTable("UserTable", columnCount, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) + { ImGui::TableSetupColumn("名称"); - ImGui::TableSetupColumn("延迟 (ms)"); - ImGui::TableSetupColumn("连接类型"); + if (steamManager.isHost()) + { + ImGui::TableSetupColumn("延迟 (ms)"); + } ImGui::TableHeadersRow(); { - for (const auto& pair : steamManager.getUserMap()) { + std::vector members = roomManager.getLobbyMembers(); + CSteamID mySteamID = SteamUser()->GetSteamID(); + for (const auto &memberID : members) + { ImGui::TableNextRow(); ImGui::TableNextColumn(); - ImGui::Text("%s", pair.second.name.c_str()); - ImGui::TableNextColumn(); - ImGui::Text("%d", pair.second.ping); - ImGui::TableNextColumn(); - ImGui::Text("%s", pair.second.isRelay ? "中继" : "直连"); + const char *name = SteamFriends()->GetFriendPersonaName(memberID); + ImGui::Text("%s", name); + if (steamManager.isHost()) + { + ImGui::TableNextColumn(); + if (memberID == mySteamID) + { + ImGui::Text("-"); + } + else + { + // Find connection for this member + int ping = 0; + std::lock_guard lockConn(connectionsMutex); + for (const auto &conn : steamManager.getConnections()) + { + SteamNetConnectionInfo_t info; + if (steamManager.getInterface()->GetConnectionInfo(conn, &info)) + { + if (info.m_identityRemote.GetSteamID() == memberID) + { + ping = steamManager.getConnectionPing(conn); + break; + } + } + } + ImGui::Text("%d", ping); + } + } } } ImGui::EndTable(); @@ -225,7 +283,8 @@ int main() { steamManager.stopMessageHandler(); // Cleanup - if (server) { + if (server) + { server->stop(); } ImGui_ImplOpenGL3_Shutdown(); diff --git a/steam/steam_networking_manager.cpp b/steam/steam_networking_manager.cpp index e59e23d..67f38e1 100644 --- a/steam/steam_networking_manager.cpp +++ b/steam/steam_networking_manager.cpp @@ -16,7 +16,7 @@ void SteamNetworkingManager::OnSteamNetConnectionStatusChanged(SteamNetConnectio SteamNetworkingManager::SteamNetworkingManager() : m_pInterface(nullptr), hListenSock(k_HSteamListenSocket_Invalid), g_isHost(false), g_isClient(false), g_isConnected(false), g_hConnection(k_HSteamNetConnection_Invalid), - io_context_(nullptr), server_(nullptr), localPort_(nullptr), messageHandler_(nullptr) + io_context_(nullptr), server_(nullptr), localPort_(nullptr), messageHandler_(nullptr), hostPing_(0) { std::cout << "Initialized SteamNetworkingManager" << std::endl; } @@ -156,20 +156,27 @@ void SteamNetworkingManager::stopMessageHandler() void SteamNetworkingManager::update() { std::lock_guard lock(connectionsMutex); - for (auto &pair : userMap) + // Update ping to host/client connection + if (g_hConnection != k_HSteamNetConnection_Invalid) { - HSteamNetConnection conn = pair.first; - 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->GetConnectionRealTimeStatus(g_hConnection, &status, 0, nullptr)) { - userInfo.ping = status.m_nPing; - userInfo.isRelay = (info.m_idPOPRelay != 0); + hostPing_ = status.m_nPing; } } } +int SteamNetworkingManager::getConnectionPing(HSteamNetConnection conn) const +{ + SteamNetConnectionRealTimeStatus_t status; + if (m_pInterface->GetConnectionRealTimeStatus(conn, &status, 0, nullptr)) + { + return status.m_nPing; + } + return 0; +} + void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *pInfo) { std::lock_guard lock(connectionsMutex); @@ -185,17 +192,11 @@ void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionSta g_hConnection = pInfo->m_hConn; g_isConnected = true; std::cout << "Accepted incoming connection from " << pInfo->m_info.m_identityRemote.GetSteamID().ConvertToUint64() << std::endl; - // Add user info + // Log connection info SteamNetConnectionInfo_t info; SteamNetConnectionRealTimeStatus_t status; 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); - userInfo.ping = status.m_nPing; - userInfo.isRelay = (info.m_idPOPRelay != 0); - userMap[pInfo->m_hConn] = userInfo; std::cout << "Incoming connection details: ping=" << status.m_nPing << "ms, relay=" << (info.m_idPOPRelay != 0 ? "yes" : "no") << std::endl; } } @@ -203,17 +204,12 @@ void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionSta { g_isConnected = true; std::cout << "Connected to host" << std::endl; - // Add user info + // Log connection info SteamNetConnectionInfo_t info; SteamNetConnectionRealTimeStatus_t status; 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); - userInfo.ping = status.m_nPing; - userInfo.isRelay = (info.m_idPOPRelay != 0); - userMap[pInfo->m_hConn] = userInfo; + hostPing_ = status.m_nPing; std::cout << "Outgoing connection details: ping=" << status.m_nPing << "ms, relay=" << (info.m_idPOPRelay != 0 ? "yes" : "no") << std::endl; } } @@ -227,7 +223,7 @@ void SteamNetworkingManager::handleConnectionStatusChanged(SteamNetConnectionSta { connections.erase(it); } - userMap.erase(pInfo->m_hConn); + hostPing_ = 0; std::cout << "Connection closed" << std::endl; } } \ No newline at end of file diff --git a/steam/steam_networking_manager.h b/steam/steam_networking_manager.h index 81125b3..94b5eeb 100644 --- a/steam/steam_networking_manager.h +++ b/steam/steam_networking_manager.h @@ -40,8 +40,9 @@ public: bool isHost() const { return g_isHost; } bool isClient() const { return g_isClient; } bool isConnected() const { return g_isConnected; } - const std::map& getUserMap() const { return userMap; } const std::vector& getConnections() const { return connections; } + int getHostPing() const { return hostPing_; } + int getConnectionPing(HSteamNetConnection conn) const; HSteamNetConnection getConnection() const { return g_hConnection; } ISteamNetworkingSockets* getInterface() const { return m_pInterface; } @@ -81,8 +82,8 @@ private: // Connections std::vector connections; - std::map userMap; std::mutex connectionsMutex; + int hostPing_; // Ping to host (for clients) or average ping (for host) // Connection config int g_retryCount; diff --git a/steam/steam_room_manager.cpp b/steam/steam_room_manager.cpp index e7bd6ed..50e2b53 100644 --- a/steam/steam_room_manager.cpp +++ b/steam/steam_room_manager.cpp @@ -268,4 +268,19 @@ void SteamRoomManager::stopHosting() } leaveLobby(); networkingManager_->getIsHost() = false; +} + +std::vector SteamRoomManager::getLobbyMembers() const +{ + std::vector members; + if (currentLobby != k_steamIDNil) + { + int numMembers = SteamMatchmaking()->GetNumLobbyMembers(currentLobby); + for (int i = 0; i < numMembers; ++i) + { + CSteamID memberID = SteamMatchmaking()->GetLobbyMemberByIndex(currentLobby, i); + members.push_back(memberID); + } + } + return members; } \ No newline at end of file diff --git a/steam/steam_room_manager.h b/steam/steam_room_manager.h index ea67475..441a88a 100644 --- a/steam/steam_room_manager.h +++ b/steam/steam_room_manager.h @@ -53,6 +53,7 @@ public: CSteamID getCurrentLobby() const { return currentLobby; } const std::vector& getLobbies() const { return lobbies; } + std::vector getLobbyMembers() const; void setCurrentLobby(CSteamID lobby) { currentLobby = lobby; } void addLobby(CSteamID lobby) { lobbies.push_back(lobby); }