diff --git a/server/server.cpp b/server/server.cpp index 1bcd2a6..b981e90 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -160,17 +160,19 @@ private: std::lock_guard lock(g_boxes_mutex); std::string boxMsg = "BOXES:"; - for (const auto& box : g_serverBoxes) { + for (size_t i = 0; i < g_serverBoxes.size(); ++i) { + const auto& box = g_serverBoxes[i]; Eigen::Quaternionf q(box.rotation); - boxMsg += std::to_string(box.position.x()) + ":" + + boxMsg += std::to_string(i) + ":" + + std::to_string(box.position.x()) + ":" + std::to_string(box.position.y()) + ":" + std::to_string(box.position.z()) + ":" + std::to_string(q.w()) + ":" + std::to_string(q.x()) + ":" + std::to_string(q.y()) + ":" + - std::to_string(q.z()) + "|"; + std::to_string(q.z()) + ":" + + (std::to_string(box.destroyed ? 1 : 0)) + "|"; } - if (!boxMsg.empty() && boxMsg.back() == '|') boxMsg.pop_back(); send_message(boxMsg); diff --git a/src/Space.cpp b/src/Space.cpp index c0944eb..3aafd38 100644 --- a/src/Space.cpp +++ b/src/Space.cpp @@ -331,7 +331,7 @@ namespace ZL auto rotMatrix2 = quat2.toRotationMatrix(); cargoBase.RotateByMatrix(rotMatrix2); //cargoBase.RotateByMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())).toRotationMatrix()); - cargoBase.Move(Vector3f{ 1.2, 0, -5 }); + cargoBase.Move(Vector3f{ 0, 0, -5 }); cargo.AssignFrom(cargoBase); cargo.RefreshVBO(); @@ -639,13 +639,15 @@ namespace ZL // Если сервер прислал коробки, применяем их однократно вместо локальной генерации if (!serverBoxesApplied && networkClient) { auto sboxes = networkClient->getServerBoxes(); + auto destroyedFlags = networkClient->getServerBoxDestroyedFlags(); if (!sboxes.empty()) { boxCoordsArr.clear(); - for (auto& b : sboxes) { + boxCoordsArr.resize(sboxes.size()); + for (size_t i = 0; i < sboxes.size(); ++i) { BoxCoords bc; - bc.pos = b.first; - bc.m = b.second; - boxCoordsArr.push_back(bc); + bc.pos = sboxes[i].first; + bc.m = sboxes[i].second; + boxCoordsArr[i] = bc; } boxRenderArr.resize(boxCoordsArr.size()); for (int i = 0; i < (int)boxCoordsArr.size(); ++i) { @@ -653,6 +655,11 @@ namespace ZL boxRenderArr[i].RefreshVBO(); } boxAlive.assign(boxCoordsArr.size(), true); + if (destroyedFlags.size() == boxAlive.size()) { + for (size_t i = 0; i < boxAlive.size(); ++i) { + if (destroyedFlags[i]) boxAlive[i] = false; + } + } serverBoxesApplied = true; } } diff --git a/src/network/NetworkInterface.h b/src/network/NetworkInterface.h index 74dbdad..2c7e704 100644 --- a/src/network/NetworkInterface.h +++ b/src/network/NetworkInterface.h @@ -41,6 +41,8 @@ namespace ZL { virtual std::vector> getServerBoxes() = 0; + virtual std::vector getServerBoxDestroyedFlags() { return {}; } + virtual std::vector getPendingProjectiles() = 0; virtual std::vector getPendingDeaths() = 0; diff --git a/src/network/WebSocketClientBase.cpp b/src/network/WebSocketClientBase.cpp index 52c82a4..c4f74b3 100644 --- a/src/network/WebSocketClientBase.cpp +++ b/src/network/WebSocketClientBase.cpp @@ -41,36 +41,66 @@ namespace ZL { return; } - // Обработка списка коробок от сервера if (msg.rfind("BOXES:", 0) == 0) { - std::string payload = msg.substr(6); // после "BOXES:" - std::vector> parsedBoxes; + std::string payload = msg.substr(6); + std::vector> parsed; if (!payload.empty()) { auto items = split(payload, '|'); for (auto& item : items) { - if (item.empty()) return; + if (item.empty()) continue; auto parts = split(item, ':'); - if (parts.size() < 7) return; + if (parts.size() < 9) { + return; + } try { - float px = std::stof(parts[0]); - float py = std::stof(parts[1]); - float pz = std::stof(parts[2]); + int idx = std::stoi(parts[0]); + float px = std::stof(parts[1]); + float py = std::stof(parts[2]); + float pz = std::stof(parts[3]); Eigen::Quaternionf q( - std::stof(parts[3]), std::stof(parts[4]), std::stof(parts[5]), - std::stof(parts[6]) + std::stof(parts[6]), + std::stof(parts[7]) ); + bool destroyed = (std::stoi(parts[8]) != 0); + Eigen::Matrix3f rot = q.toRotationMatrix(); - parsedBoxes.emplace_back(Eigen::Vector3f{ px, py, pz }, rot); + parsed.emplace_back(idx, Eigen::Vector3f{ px, py, pz }, rot, destroyed); } catch (...) { - // пропускаем некорректную запись return; } } } - serverBoxes_ = std::move(parsedBoxes); + + int maxIdx = -1; + for (auto& t : parsed) { + int idx = std::get<0>(t); + if (idx > maxIdx) maxIdx = idx; + } + if (maxIdx < 0) { + serverBoxes_.clear(); + serverBoxesDestroyed_.clear(); + return; + } + + serverBoxes_.clear(); + serverBoxes_.resize((size_t)maxIdx + 1); + serverBoxesDestroyed_.clear(); + serverBoxesDestroyed_.resize((size_t)maxIdx + 1, true); + + for (auto& t : parsed) { + int idx = std::get<0>(t); + const Eigen::Vector3f& pos = std::get<1>(t); + const Eigen::Matrix3f& rot = std::get<2>(t); + bool destroyed = std::get<3>(t); + if (idx >= 0 && idx < serverBoxes_.size()) { + serverBoxes_[idx] = { pos, rot }; + serverBoxesDestroyed_[idx] = destroyed; + } + } + return; } if (msg.rfind("RESPAWN_ACK:", 0) == 0) { diff --git a/src/network/WebSocketClientBase.h b/src/network/WebSocketClientBase.h index 1ca30cb..8d3f97e 100644 --- a/src/network/WebSocketClientBase.h +++ b/src/network/WebSocketClientBase.h @@ -13,8 +13,8 @@ namespace ZL { protected: std::unordered_map remotePlayers; - // Серверные коробки std::vector> serverBoxes_; + std::vector serverBoxesDestroyed_; std::vector pendingProjectiles_; std::vector pendingDeaths_; @@ -40,6 +40,10 @@ namespace ZL { return serverBoxes_; } + std::vector getServerBoxDestroyedFlags() { + return serverBoxesDestroyed_; + } + std::vector getPendingProjectiles() override; std::vector getPendingDeaths() override; std::vector getPendingRespawns() override;