From 3c55b59c8d4cc1b4d9f01b4e2953e740c6654440 Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Sat, 17 Jan 2026 15:03:37 +0300 Subject: [PATCH] Fixing bugs, more freq updated --- server/server.cpp | 7 ++- src/Game.cpp | 43 +++++++++++++++++ src/Game.h | 1 + src/network/ClientState.h | 25 ++++++---- src/network/WebSocketClient.cpp | 84 ++++++++++++++++++++++++++++----- src/network/WebSocketClient.h | 4 +- 6 files changed, 136 insertions(+), 28 deletions(-) diff --git a/server/server.cpp b/server/server.cpp index 7eb849d..b15f016 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -42,9 +42,6 @@ class Session : public std::enable_shared_from_this { void process_message(const std::string& msg) { auto now_server = std::chrono::system_clock::now(); - // : - // ROT:ANGLE:MAG:TIMESTAMP - // VEL:SELECTED_VEL:TIMESTAMP auto parts = split(msg, ':'); if (parts.empty()) return; @@ -73,6 +70,7 @@ class Session : public std::enable_shared_from_this { if (parts[0] == "ROT") { state_.discreteAngle = std::stoi(parts[2]); state_.discreteMag = std::stof(parts[3]); + state_.handle_full_sync(parts, 4); std::cout << "ROT id = " << this->id_ << " discreteMag=" << state_.discreteMag << std::endl; state_.apply_lag_compensation(now_server); state_.lastUpdateServerTime = now_server; @@ -80,12 +78,13 @@ class Session : public std::enable_shared_from_this { } else if (parts[0] == "VEL") { state_.selectedVelocity = std::stoi(parts[2]); + state_.handle_full_sync(parts, 3); state_.apply_lag_compensation(now_server); state_.lastUpdateServerTime = now_server; retranslateMessage(msg); } else if (parts[0] == "PING") { - state_.handle_full_sync(parts); + state_.handle_full_sync(parts, 2); std::cout << "PING id = " << this->id_ <<" discreteMag=" << state_.discreteMag << std::endl; state_.apply_lag_compensation(now_server); state_.lastUpdateServerTime = now_server; diff --git a/src/Game.cpp b/src/Game.cpp index ad01455..30628ef 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -245,6 +245,7 @@ namespace ZL std::chrono::system_clock::now().time_since_epoch() ).count(); std::string msg = "VEL:" + std::to_string(now_ms) + ":" + std::to_string(Environment::shipSelectedVelocity); + msg = msg + ":" + formPingMessageContent(); networkClient->Send(msg); } }); @@ -583,6 +584,18 @@ namespace ZL renderer.PushMatrix(); renderer.LoadIdentity(); + renderer.TranslateMatrix({ 0,0, -1.0f * Environment::zoom }); + renderer.RotateMatrix(Environment::inverseShipMatrix); + renderer.TranslateMatrix(-Environment::shipPosition); + + Eigen::Vector3f relativePos = playerState.position;// -Environment::shipPosition; + renderer.TranslateMatrix(relativePos); + + // 3. Поворот врага + renderer.RotateMatrix(playerState.rotation); + + /* + // 1. Камера и вид игрока renderer.TranslateMatrix({ 0, 0, -1.0f * Environment::zoom }); renderer.RotateMatrix(Environment::inverseShipMatrix); @@ -601,6 +614,8 @@ namespace ZL // В твоем drawShip() есть: renderer.TranslateMatrix({ 0, -6.f, 0 }); renderer.TranslateMatrix({ 0, -6.f, 0 }); + */ + renderer.DrawVertexRenderStruct(spaceship); renderer.PopMatrix(); } @@ -638,6 +653,7 @@ namespace ZL ).count(); // 1. Извлекаем кватернион из матрицы поворота + /* Eigen::Quaternionf q(Environment::shipMatrix); // 2. Формируем строку PING согласно протоколу сервера @@ -657,6 +673,8 @@ namespace ZL + std::to_string(Environment::shipSelectedVelocity) + ":" + std::to_string(Environment::lastSentMagnitude) + ":" // Используем те же static переменные из блока ROT + std::to_string(Environment::lastSentAngle); + */ + std::string pingMsg = "PING:" + std::to_string(now_ms) + ":" + formPingMessageContent(); networkClient->Send(pingMsg); std::cout << "Sending: " << pingMsg << std::endl; @@ -720,6 +738,7 @@ namespace ZL // Формируем сетевой пакет // Нам нужно отправить: дискретный угол, дискретную силу и текущую матрицу/позицию для синхронизации std::string msg = "ROT:" + std::to_string(now_ms) + ":" + std::to_string(discreteAngle) + ":" + std::to_string(discreteMag); + msg = msg + ":" + formPingMessageContent(); networkClient->Send(msg); } @@ -784,6 +803,7 @@ namespace ZL // Формируем сетевой пакет // Нам нужно отправить: дискретный угол, дискретную силу и текущую матрицу/позицию для синхронизации std::string msg = "ROT:" + std::to_string(now_ms) + ":" + std::to_string(discreteAngle) + ":" + std::to_string(discreteMag); + msg = msg + ":" + formPingMessageContent(); networkClient->Send(msg); } @@ -1138,5 +1158,28 @@ namespace ZL } + std::string Game::formPingMessageContent() + { + Eigen::Quaternionf q(Environment::shipMatrix); + + std::string pingMsg = std::to_string(Environment::shipPosition.x()) + ":" + + std::to_string(Environment::shipPosition.y()) + ":" + + std::to_string(Environment::shipPosition.z()) + ":" + + std::to_string(q.w()) + ":" + + std::to_string(q.x()) + ":" + + std::to_string(q.y()) + ":" + + std::to_string(q.z()) + ":" + + std::to_string(Environment::currentAngularVelocity.x()) + ":" + + std::to_string(Environment::currentAngularVelocity.y()) + ":" + + std::to_string(Environment::currentAngularVelocity.z()) + ":" + + std::to_string(Environment::shipVelocity) + ":" + + std::to_string(Environment::shipSelectedVelocity) + ":" + + std::to_string(Environment::lastSentMagnitude) + ":" // Используем те же static переменные из блока ROT + + std::to_string(Environment::lastSentAngle); + + + return pingMsg; + } + } // namespace ZL diff --git a/src/Game.h b/src/Game.h index 296f654..0b916ed 100644 --- a/src/Game.h +++ b/src/Game.h @@ -52,6 +52,7 @@ namespace ZL { void handleMotion(int mx, int my); void extrapolateRemotePlayers(); + std::string formPingMessageContent(); SDL_Window* window; SDL_GLContext glContext; diff --git a/src/network/ClientState.h b/src/network/ClientState.h index 4d29b8f..0074c8a 100644 --- a/src/network/ClientState.h +++ b/src/network/ClientState.h @@ -14,7 +14,7 @@ constexpr float SHIP_ACCEL = 1.0f * 1000.0f; constexpr float ROTATION_SENSITIVITY = 0.002f; struct ClientState { - int id; + int id = 0; Eigen::Vector3f position = { 0, 0, 45000.0f }; Eigen::Matrix3f rotation = Eigen::Matrix3f::Identity(); Eigen::Vector3f currentAngularVelocity = Eigen::Vector3f::Zero(); @@ -201,19 +201,26 @@ struct ClientState { return s; } - void handle_full_sync(const std::vector& parts) { + void handle_full_sync(const std::vector& parts, int startFrom) { // Позиция - position = { std::stof(parts[2]), std::stof(parts[3]), std::stof(parts[4]) }; + position = { std::stof(parts[startFrom]), std::stof(parts[startFrom+1]), std::stof(parts[startFrom+2]) }; // Для вращения клиент должен прислать либо кватернион, либо углы Эйлера. // Предположим, мы передаем 4 значения кватерниона для экономии: - Eigen::Quaternionf q(std::stof(parts[5]), std::stof(parts[6]), std::stof(parts[7]), std::stof(parts[8])); + Eigen::Quaternionf q( + std::stof(parts[startFrom+3]), + std::stof(parts[startFrom+4]), + std::stof(parts[startFrom+5]), + std::stof(parts[startFrom+6])); rotation = q.toRotationMatrix(); - currentAngularVelocity = Eigen::Vector3f{ std::stof(parts[9]), std::stof(parts[10]), std::stof(parts[11]) }; - velocity = std::stof(parts[12]); - selectedVelocity = std::stoi(parts[13]); - discreteMag = std::stof(parts[14]); - discreteAngle = std::stoi(parts[15]); + currentAngularVelocity = Eigen::Vector3f{ + std::stof(parts[startFrom+7]), + std::stof(parts[startFrom+8]), + std::stof(parts[startFrom+9]) }; + velocity = std::stof(parts[startFrom+10]); + selectedVelocity = std::stoi(parts[startFrom+11]); + discreteMag = std::stof(parts[startFrom+12]); + discreteAngle = std::stoi(parts[startFrom+13]); } }; diff --git a/src/network/WebSocketClient.cpp b/src/network/WebSocketClient.cpp index 477e6ba..7039c9b 100644 --- a/src/network/WebSocketClient.cpp +++ b/src/network/WebSocketClient.cpp @@ -69,13 +69,14 @@ namespace ZL { void WebSocketClient::Poll() { std::lock_guard lock(queueMutex); - auto nowTime = std::chrono::system_clock::now(); - - auto now_ms = std::chrono::duration_cast( - nowTime.time_since_epoch() - ).count(); - while (!messageQueue.empty()) { + + auto nowTime = std::chrono::system_clock::now(); + + auto now_ms = std::chrono::duration_cast( + nowTime.time_since_epoch() + ).count(); + std::string msg = messageQueue.front(); messageQueue.pop(); @@ -93,10 +94,65 @@ namespace ZL { if (subType == "VEL") { rp.selectedVelocity = std::stoi(parts[4]); + int startFrom = 5; + rp.position = { std::stof(parts[startFrom]), std::stof(parts[startFrom+1]), std::stof(parts[startFrom+2]) }; + Eigen::Quaternionf q( + std::stof(parts[startFrom + 3]), + std::stof(parts[startFrom + 4]), + std::stof(parts[startFrom + 5]), + std::stof(parts[startFrom + 6])); + rp.rotation = q.toRotationMatrix(); + + rp.currentAngularVelocity = Eigen::Vector3f{ + std::stof(parts[startFrom + 7]), + std::stof(parts[startFrom + 8]), + std::stof(parts[startFrom + 9]) }; + rp.velocity = std::stof(parts[startFrom + 10]); + rp.selectedVelocity = std::stoi(parts[startFrom + 11]); + rp.discreteMag = std::stof(parts[startFrom + 12]); + rp.discreteAngle = std::stoi(parts[startFrom + 13]); + /*position = { std::stof(parts[startFrom]), std::stof(parts[startFrom+1]), std::stof(parts[startFrom+2]) }; + + // , . + // , 4 : + Eigen::Quaternionf q( + std::stof(parts[startFrom+3]), + std::stof(parts[startFrom+4]), + std::stof(parts[startFrom+5]), + std::stof(parts[startFrom+6])); + rotation = q.toRotationMatrix(); + + currentAngularVelocity = Eigen::Vector3f{ + std::stof(parts[startFrom+7]), + std::stof(parts[startFrom+8]), + std::stof(parts[startFrom+9]) }; + velocity = std::stof(parts[startFrom+10]); + selectedVelocity = std::stoi(parts[startFrom+11]); + discreteMag = std::stof(parts[startFrom+12]); + discreteAngle = std::stoi(parts[15]); + */ + } else if (subType == "ROT") { rp.discreteAngle = std::stoi(parts[4]); rp.discreteMag = std::stof(parts[5]); + int startFrom = 6; + rp.position = { std::stof(parts[startFrom]), std::stof(parts[startFrom + 1]), std::stof(parts[startFrom + 2]) }; + Eigen::Quaternionf q( + std::stof(parts[startFrom + 3]), + std::stof(parts[startFrom + 4]), + std::stof(parts[startFrom + 5]), + std::stof(parts[startFrom + 6])); + rp.rotation = q.toRotationMatrix(); + + rp.currentAngularVelocity = Eigen::Vector3f{ + std::stof(parts[startFrom + 7]), + std::stof(parts[startFrom + 8]), + std::stof(parts[startFrom + 9]) }; + rp.velocity = std::stof(parts[startFrom + 10]); + rp.selectedVelocity = std::stoi(parts[startFrom + 11]); + rp.discreteMag = std::stof(parts[startFrom + 12]); + rp.discreteAngle = std::stoi(parts[startFrom + 13]); } std::cout << "EVENT Received discreteMag=" << rp.discreteMag << std::endl; @@ -121,12 +177,15 @@ namespace ZL { } } else if (msg.rfind("WORLD_UPDATE|", 0) == 0) { - parseWorldUpdate(msg); + parseWorldUpdate(msg, nowTime); } } } - void WebSocketClient::parseWorldUpdate(const std::string& msg) { + void WebSocketClient::parseWorldUpdate(const std::string& msg, std::chrono::system_clock::time_point now_ms) { + // , (TaskManager) + std::lock_guard lock(playersMutex); + // : WORLD_UPDATE|server_now_ms|count|id,x,y,z,w,qx,qy,qz,v;... auto parts = split(msg, '|'); if (parts.size() < 4) return; @@ -143,14 +202,12 @@ namespace ZL { if (id == this->clientId) continue; // // RemotePlayer - updateRemotePlayer(id, vals, serverTime); + updateRemotePlayer(id, vals, serverTime, now_ms); } } - void WebSocketClient::updateRemotePlayer(int id, const std::vector& vals, uint64_t serverTime) { - // , (TaskManager) - std::lock_guard lock(playersMutex); - + void WebSocketClient::updateRemotePlayer(int id, const std::vector& vals, uint64_t serverTime, std::chrono::system_clock::time_point now_ms) { + auto& rp = remotePlayers[id]; rp.id = id; @@ -168,6 +225,7 @@ namespace ZL { std::cout << "PING Received discreteMag=" << rp.discreteMag << std::endl; rp.lastUpdateServerTime = uptime_timepoint; + rp.apply_lag_compensation(now_ms); } diff --git a/src/network/WebSocketClient.h b/src/network/WebSocketClient.h index d5472d4..54062d2 100644 --- a/src/network/WebSocketClient.h +++ b/src/network/WebSocketClient.h @@ -40,8 +40,8 @@ namespace ZL { void Connect(const std::string& host, uint16_t port) override; void Poll() override; - void parseWorldUpdate(const std::string& msg); - void updateRemotePlayer(int id, const std::vector& vals, uint64_t serverTime); + void parseWorldUpdate(const std::string& msg, std::chrono::system_clock::time_point now_ms); + void updateRemotePlayer(int id, const std::vector& vals, uint64_t serverTime, std::chrono::system_clock::time_point now_ms); void Send(const std::string& message) override; void doWrite();