#include "NetworkManager.hpp" #include #include #include NetworkManager::NetworkManager() {loginSocketworldSocket.open(udp::v4()); startLoginReceive(); startWorldReceive ioThread = std::thread([this] { ioContext.run(); }); } NetworkManager::~NetworkManager() { disconnect(); ioContext.stop(); if (ioThread.joinable()) ioThread.join(); } bool NetworkManager::connectToLogin(const std::string& server, uint16_t port) { try { tcp::resolver resolver(ioContext); auto endpoints = resolver.resolve(server, std::to_string(port)); boost::asio::connect(loginSocket, endpoints); loginConnected = true; startLoginReceive(); return true; } catch (std::exception& e) { std::cerr << "Failed to connect to login server: " << e.what() << std::endl; return false; } } bool NetworkManager::connectToWorld(const std::string& server, uint16_t port, const std::string& token) { try { tcp::resolver resolver(ioContext); auto endpoints = resolver.resolve(server, std::to_string(port)); boost::asio::connect(worldSocket, endpoints); // Send authentication json authMsg; authMsg["type"] = "auth"; authMsg["token"] = token; std::string msg = authMsg.dump() + "\n"; boost::asio::write(worldSocket, boost::asio::buffer(msg)); // Wait for auth response boost::asio::streambuf response; boost::asio::read_until(worldSocket, response, '\n'); std::istream response_stream(&response); std::string response_str; std::getline(response_stream, response_str); json authResp = json::parse(response_str); if (authResp["success"] == true) { worldConnected = true; connected = true; startWorldReceive(); return true; } return false; } catch (std::exception& e) { std::cerr << "Failed to connect to world server: " << e.what() << std::endl; return false; } } void NetworkManager::startLoginReceive() { auto self(shared_from_this()); boost::asio::async_read_until(loginSocket, loginBuffer, '\n', [this, self](boost::system::error_code ec, std::size_t length) { if (!ec) { std::istream is(&loginBuffer); std::string line; std::getline(is, line); try { json msg = json::parse(line); processLoginMessage(msg); } catch (json::exception& e) { std::cerr << "JSON parse error: " << e.what() << std::endl; } if (loginConnected) { startLoginReceive(); } void NetworkManager::connectToLoginServer(const std::string& host, uint16_t port) { loginEndpoint = udp::endpoint(ip::make_address(host), port); std::cout << "Login server endpoint set to " << host << ":" << port << "\n"; } void NetworkManager::connectToWorldServer(const std::string& host, uint16_t port) { worldEndpoint = udp::endpoint(ip::make_address(host), port); std::cout << "World server endpoint set to " << host << ":" << port << "\n"; } void NetworkManager::sendLoginRequest(const std::string& username, const std::string& password) { std::vector msg(2 + username.size() + 1 + password.size()); msg[0] = static_cast(MessageType::LoginRequest); msg[1] = static_cast(username.size()); std::memcpy(&msg[2], username.data(), username.size()); msg[2 + username.size()] = static_cast(password.size()); std::memcpy(&msg[3 + username.size()], password.data(), password.size()); loginSocket.send_to(buffer(msg), loginEndpoint); loginResponseReceived = false; } bool NetworkManager::waitForLoginResponse(LoginResult& result, float timeout) { auto start = std::chrono::steady_clock::now(); auto timeoutDuration = std::chrono::milliseconds(static_cast(timeout * 1000)); while (!loginResponseReceived) { if (std::chrono::steady_clock::now() - start > timeoutDuration) { return false; } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } std::lock_guard lock(loginMutex); result = lastLoginResult; return true; } void NetworkManager::sendAuth(const std::array& token) { std::array msg; msg[0] = static_cast(MessageType::Auth); std::memcpy(&msg[1], token.data(), 32); worldSocket.send_to(buffer(msg), worldEndpoint); } void NetworkManager::sendMove(float dx, float dy, float dz) { if (!connected) return; std::array msg{}; msg[0] = static_cast(MessageType::Move); uint32_t id = playerID; std::memcpy(&msg[1], &id, sizeof(id)); std::memcpy(&msg[5], &dx, sizeof(dx)); std::memcpy(&msg[9], &dy, sizeof(dy)); std::memcpy(&msg[13], &dz, sizeof(dz)); worldSocket.send_to(buffer(msg), worldEndpoint); } void NetworkManager::sendHeartbeat() { if (!connected) return; std::array msg{}; msg[0] = static_cast(MessageType::Heartbeat); uint32_t id = playerID; std::memcpy(&msg[1], &id, sizeof(id)); worldSocket.send_to(buffer(msg), worldEndpoint); } void NetworkManager::sendLogout() { if (!connected) return; std::array msg{}; msg[0] = static_cast(MessageType::Logout); uint32_t id = playerID; std::memcpy(&msg[1], &id, sizeof(id)); worldSocket.send_to(buffer(msg), worldEndpoint); connected = false; authenticated = false; playerID = 0; std::lock_guard lock(remotePlayersMutex); remotePlayers.clear(); } void NetworkManager::startLoginReceive() { loginSocket.async_receive_from( buffer(loginRecvBuffer), loginEndpoint, processLoginMessageloginRecvBuffer } }); } void NetworkManager::startWorldReceive() { auto self(shared_from_this()); boost::asio::async_read_until(worldSocket, worldBuffer, '\n', [this, self](boost::system::error_code ec, std::size_t length) { if (!ec) { std::istream is(&worldBuffer); std::string line; std::getline(is, line); try { json msg = json::parse(line); processWorldMessage(msg); } catch (json::exception& e) { std::cerr << "JSON parse error: " << e.what() << std::endl; } if (worldConnected) { startWorldReceive(); } } }); } void NetworkManager::processLoginMessage(const json& msg) { std::string type = msg["type"]; if (type == "loginResponse") { if (msg["success"] == true) { authToken = msg["token"]; worldServerUrl = msg["worldUrl"]; playerID = msg["playerId"]; loginSuccess = true; loginErrorMsg = ""; } else { loginErrorMsg = msg.value("message", "Login failed"); loginSuccess = false; startLoginReceive } } else if (type == "registerResponse") { if (msg["success"] == false) { loginErrorMsg = msg.value("message", "Registration failed"); void NetworkManager::startWorldReceive() { worldSocket.async_receive_from( buffer(worldRecvBuffer), worldEndpoint, [this](std::error_code ec, std::size_t bytes) { if (!ec && bytes > 0) { processWorldMessage(worldRecvBuffer.data(), bytes); } startWorldReceive(); } ); } void NetworkManager::processLoginMessage(const uint8_t* data, std::size_t size) { if (size == 0) return; auto msgType = static_cast(data[0]); switch (msgType) { case MessageType::LoginResponse: handleLoginResponse(data, size); break; default: break; } } void NetworkManager::processWorldMessage(const uint8_t* data, std::size_t size) { case MessageType::AuthResponse: handleAuthResponse(data, size); break; handleLoginResponse3lock_guardlockloginMutex) lastLoginResult.success = (data[1] == 1); uint8_t msgLen = data[2]; if (size >= 3u + msgLen) { lastLoginResult.message = std::string(reinterpret_cast(&data[3]), msgLen); } if (lastLoginResult.success && size >= 3u + msgLen + 32 + 1) { // Extract token std::memcpy(lastLoginResult.token.data(), &data[3 + msgLen], 32); // Extract world host uint8_t hostLen = data[3 + msgLen + 32]; if (size >= 3u + msgLen + 32 + 1 + hostLen + 2 + 4) { lastLoginResult.worldHost = std::string(reinterpret_cast(&data[3 + msgLen + 32 + 1]), hostLen); // Extract world port std::memcpy(&lastLoginResult.worldPort, &data[3 + msgLen + 32 + 1 + hostLen], 2); // Extract player ID std::memcpy(&lastLoginResult.playerID, &data[3 + msgLen + 32 + 1 + hostLen + 2], 4); } } loginResponseReceived = true; if (lastLoginResult.success) { std::cout << "Login successful! World: " << lastLoginResult.worldHost << ":" << lastLoginResult.worldPort << "\n"; } else { std::cout << "Login failed: " << lastLoginResult.message << "\n"; } } void NetworkManager::handleAuthResponse(const uint8_t* data, std::size_t size) { if (size < 3) return; bool success = (data[1] == 1); uint8_t msgLen = data[2]; if (size >= 3u + msgLen) { std::string message(reinterpret_cast(&data[3]), msgLen); if (success) { authenticated = true; std::cout << "World authentication successful\n"; } else { authenticated = false; std::cout << "World authentication failed: " << message << "\n"; } } 17Spawnedat(" << x << ",y, " << z << ") } } } void NetworkManager::processWorldMessage(const json& msg) { std::string type = msg["type"]; if (type == "init") { playerID = msg["playerId"]; serverPosition = {msg["x"], msg["y"], msg["z"]}; serverTimeOfDay = msg["timeOfDay"]; connected = true; std::cout << "Connected to world as player " << playerID << std::endl; } else if (type == "playerMovement") { uint32_t id = msg["playerId"]; if (id != playerID) { std::lock_guard lock(remotePlayersMutex); if (remotePlayers.find(id) != remotePlayers.end()) { remotePlayers[id].position = {msg["x"], msg["y"], msg["z"]}; remotePlayers[id].lastUpdate = GetTime(); } } } else if (type == "playerJoined") { uint32_t id = msg["playerId"]; if (id != playerID) { std::lock_guard lock(remotePlayersMutex); remotePlayers[id] = { id, {msg["x"], msg["y"], msg["z"]}, msg.value("username", "Player"), static_cast(GetTime()) }; std::cout << "Player " << msg["username"] << " joined" << std::endl; } } else if (type == "playerLeft") { uint32_t id = msg["playerId"]; usernameLenusernamePlayerusernameLenusernameusernameLen std::lock_guard lock(remotePlayersMutex); remotePlayers.erase(id); } else if (type == "positionCorrection") { serverPosition = {msg["x"], msg["y"], msg["z"]}; } else if (type == "timeUpdate") { serverTimeOfDay = msg["timeOfDay"]; } else if (type == "chat") { std::cout << "[" << msg["username"] << "]: " << msg["message"] << std::endl; usernameusername << " (ID: " << ) } } void NetworkManager::sendLogin(const std::string& username, const std::string& password) { if (!loginConnected) return; json msg; msg["type"] = "login"; msg["username"] = username; msg["password"] = password; std::string data = msg.dump() + "\n"; boost::asio::async_write(loginSocket, boost::asio::buffer(data), [](boost::system::error_code ec, std::size_t) { if (ec) std::cerr << "Send login error: " << ec.message() << std::endl; }); } void NetworkManager::sendMovement(const Vector3& position, float yaw, float pitch, const Vector3& velocity) { if (!worldConnected) return; json msg; msg["type"] = "movement"; msg["x"] = position.x; msg["y"] = position.y; msg["z"] = position.z; msg["yaw"] = yaw; msg["pitch"] = pitch; msg["velX"] = velocity.x; msg["velY"] = velocity.y; msg["velZ"] = velocity.z; std::string data = msg.dump() + "\n"; boost::asio::async_write(worldSocket, boost::asio::buffer(data), [](boost::system::error_code ec, std::size_t) { if (ec) std::cerr << "Send movement error: " << ec.message() << std::endl; }); } void NetworkManager::handleTimeSync(const uint8_t* data, std::size_t size) { if (size < 5) return; float timeOfDay; memcpy&timeOfDay,&data[1],sizeof(timeOfDay)) serverTimeOfDay.store(timeOfDay); } Vector3 NetworkManager::getPosition() { std::lock_guard lock(positionMutex); return serverPosition; } std::unordered_map NetworkManager::getRemotePlayers() { std::lock_guard lock(remotePlayersMutex); return remotePlayers; }}