优化Steam网络管理,添加主机延迟获取功能,重构房间成员管理逻辑
This commit is contained in:
@@ -21,16 +21,18 @@ using boost::asio::ip::tcp;
|
||||
|
||||
// New variables for multiple connections and TCP clients
|
||||
std::vector<HSteamNetConnection> connections;
|
||||
std::mutex connectionsMutex; // Add mutex for connections
|
||||
std::mutex connectionsMutex; // Add mutex for connections
|
||||
int localPort = 0;
|
||||
std::unique_ptr<TCPServer> 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<TCPServer>(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<std::mutex> 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<CSteamID> 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<std::mutex> 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();
|
||||
|
||||
@@ -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<std::mutex> 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<std::mutex> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<HSteamNetConnection, UserInfo>& getUserMap() const { return userMap; }
|
||||
const std::vector<HSteamNetConnection>& 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<HSteamNetConnection> connections;
|
||||
std::map<HSteamNetConnection, UserInfo> userMap;
|
||||
std::mutex connectionsMutex;
|
||||
int hostPing_; // Ping to host (for clients) or average ping (for host)
|
||||
|
||||
// Connection config
|
||||
int g_retryCount;
|
||||
|
||||
@@ -268,4 +268,19 @@ void SteamRoomManager::stopHosting()
|
||||
}
|
||||
leaveLobby();
|
||||
networkingManager_->getIsHost() = false;
|
||||
}
|
||||
|
||||
std::vector<CSteamID> SteamRoomManager::getLobbyMembers() const
|
||||
{
|
||||
std::vector<CSteamID> 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;
|
||||
}
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
|
||||
CSteamID getCurrentLobby() const { return currentLobby; }
|
||||
const std::vector<CSteamID>& getLobbies() const { return lobbies; }
|
||||
std::vector<CSteamID> getLobbyMembers() const;
|
||||
|
||||
void setCurrentLobby(CSteamID lobby) { currentLobby = lobby; }
|
||||
void addLobby(CSteamID lobby) { lobbies.push_back(lobby); }
|
||||
|
||||
Reference in New Issue
Block a user