/
VladimirGavrilov
/
MatchmakerApp
Обзор
Документация
Войти
/
VladimirGavrilov
/
MatchmakerApp
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
MatchmakerApp/GameServerManager.cpp
211 строк
7 KB
VladimirGavrilov
turn on steam on the server
02 май 2025, 03:42
02 май 2025, 03:42
be5c1db
Код
Авторство
О чём код?
#include "GameServerManager.hpp" #include <iostream> #include <windows.h> #include <sstream> #include <set> #include <algorithm> #include <wininet.h> #pragma comment(lib, "wininet.lib") std::string publicIP; GameServerManager::GameServerManager() { publicIP = GetPublicIP(); if (publicIP.empty()) { std::cerr << "[ERROR] Could not retrieve public IP!" << std::endl; } else { std::cout << "[INFO] Public IP: " << publicIP << std::endl; } } bool GameServerManager::IsServerAlive(const ServerInfo& server) { if (server.processHandle == NULL) return false; DWORD result = WaitForSingleObject(server.processHandle, 0); return result == WAIT_TIMEOUT; } void GameServerManager::CleanupDeadServers() { servers.erase(std::remove_if(servers.begin(), servers.end(), [](const ServerInfo& server) { if (!server.processHandle) return false; DWORD result = WaitForSingleObject(server.processHandle, 0); if (result != WAIT_TIMEOUT) { std::cout << "[INFO] Removing dead server: " << server.ip << std::endl; CloseHandle(server.processHandle); return true; } return false; }), servers.end()); } int GameServerManager::GetNextAvailablePort() { int basePort = 7778; std::set<int> usedPorts; for (const auto& server : servers) { size_t colonPos = server.ip.find(':'); if (colonPos != std::string::npos) { int port = std::stoi(server.ip.substr(colonPos + 1)); usedPorts.insert(port); } } int port = basePort; while (usedPorts.find(port) != usedPorts.end()) { ++port; } return port; } std::string GameServerManager::GetConnectURL(const std::string& playerName, const std::string& id, const std::string& color,const std::string& selectedIp) { CleanupDeadServers(); std::cout << "[INFO] Servers number: " << servers.size() << std::endl; // Try to reconnect to previous server for (auto& server : servers) { if (server.connectedPlayers.find(id) != server.connectedPlayers.end()) { std::cout << "[INFO] Player " << id << " found on server " << server.ip << std::endl; if (IsServerAlive(server)) { std::cout << "[INFO] Server is alive, reconnecting..." << std::endl; return server.ip + "?PlayerName=" + playerName + "?IDPlayer=" + id + "?Color=" + color; } else { std::cout << "[WARNING] Server is dead. Will find a new one." << std::endl; break; } } } // Try to join an existing server for (auto& server : servers) { if (server.currentPlayers < server.maxPlayers && IsServerAlive(server)) { server.currentPlayers++; server.connectedPlayers.insert(id); std::cout << "[INFO] Using an existing server: " << server.ip << std::endl; std::cout << "[DEBUG] Server: " << server.ip << ", Players: " << server.currentPlayers << "/" << server.maxPlayers << std::endl; return server.ip + "?PlayerName=" + playerName + "?IDPlayer=" + id + "?Color=" + color; } } // Launch new server int newPort = GetNextAvailablePort(); std::cout << "[INFO] No free servers. Trying to start a new one on the port: " << newPort << std::endl; HANDLE serverHandle = NULL; if (LaunchNewServer("/Game/ThirdPerson/Maps/ThirdPersonMapMatch", newPort, playerName, &serverHandle)) { std::string newIP = selectedIp + ":" + std::to_string(newPort); ServerInfo newServer(newIP, 2, 1); newServer.connectedPlayers.insert(id); newServer.processHandle = serverHandle; servers.push_back(newServer); std::cout << "[SUCCESS] The server is running on " << newIP << std::endl; return newIP + "?PlayerName=" + playerName + "?IDPlayer=" + id + "?Color=" + color; } else { std::cout << "[ERROR] Failed to start new server!" << std::endl; return "none"; } } bool GameServerManager::IsLocalIP(const std::string& ip) { return ip.rfind("192.", 0) == 0 || ip.rfind("10.", 0) == 0 || ip == "127.0.0.1"; } std::string GameServerManager::GetAvailableServer() { for (const auto& server : servers) { if (server.currentPlayers < server.maxPlayers && IsServerAlive(server)) { return server.ip; } } return "none"; } void GameServerManager::AddServer(const std::string& ip, int maxPlayers) { std::cout << "[INFO] AddNewServer: " << servers.size() << std::endl; servers.push_back({ ip, maxPlayers, 1 }); } void GameServerManager::PrintServers() { for (const auto& server : servers) { std::cout << "IP: " << server.ip << ", Max: " << server.maxPlayers << ", Current: " << server.currentPlayers << std::endl; } } bool GameServerManager::LaunchNewServer(const std::string& mapName, int port, const std::string& playerName, HANDLE* outHandle) { std::string exePath = "E:\\UE\\Builds\\Work\\3.Serv\\WindowsServer\\TestProject\\Binaries\\Win64\\TestProjectServer.exe"; std::ostringstream commandLine; commandLine << "\"" << exePath << "\" " << mapName << " -port=" << port << " -log" << " -PlayerName=" << playerName << " -server -log"; STARTUPINFOA si = { sizeof(si) }; PROCESS_INFORMATION pi; BOOL success = CreateProcessA( NULL, (LPSTR)commandLine.str().c_str(), NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi ); if (!success) { DWORD error = GetLastError(); std::cerr << "Failed to launch server process. Error: " << error << std::endl; return false; } if (outHandle != nullptr) { *outHandle = pi.hProcess; } else { CloseHandle(pi.hProcess); } CloseHandle(pi.hThread); return true; } std::string GetPublicIP() { HINTERNET hInternet = InternetOpenA("IP Getter", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); if (!hInternet) return ""; HINTERNET hFile = InternetOpenUrlA(hInternet, "http://api.ipify.org", NULL, 0, INTERNET_FLAG_RELOAD, 0); if (!hFile) { InternetCloseHandle(hInternet); return ""; } char buffer[128]; DWORD bytesRead; std::string ip; while (InternetReadFile(hFile, buffer, sizeof(buffer) - 1, &bytesRead) && bytesRead != 0) { buffer[bytesRead] = '\0'; ip += buffer; } InternetCloseHandle(hFile); InternetCloseHandle(hInternet); return ip; }