added boxes from server
This commit is contained in:
parent
96d879076a
commit
cacc18dc7e
@ -11,6 +11,8 @@
|
|||||||
#define _USE_MATH_DEFINES
|
#define _USE_MATH_DEFINES
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "../src/network/ClientState.h"
|
#include "../src/network/ClientState.h"
|
||||||
|
#include <random>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
// Вспомогательный split
|
// Вспомогательный split
|
||||||
std::vector<std::string> split(const std::string& s, char delimiter) {
|
std::vector<std::string> split(const std::string& s, char delimiter) {
|
||||||
@ -31,6 +33,16 @@ using tcp = net::ip::tcp;
|
|||||||
|
|
||||||
class Session;
|
class Session;
|
||||||
|
|
||||||
|
struct ServerBox {
|
||||||
|
Eigen::Vector3f position;
|
||||||
|
Eigen::Matrix3f rotation;
|
||||||
|
float collisionRadius = 2.0f;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<ServerBox> g_serverBoxes;
|
||||||
|
std::mutex g_boxes_mutex;
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Session>> g_sessions;
|
std::vector<std::shared_ptr<Session>> g_sessions;
|
||||||
std::mutex g_sessions_mutex;
|
std::mutex g_sessions_mutex;
|
||||||
|
|
||||||
@ -38,6 +50,7 @@ class Session : public std::enable_shared_from_this<Session> {
|
|||||||
websocket::stream<beast::tcp_stream> ws_;
|
websocket::stream<beast::tcp_stream> ws_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
int id_;
|
int id_;
|
||||||
|
bool is_writing_ = false;
|
||||||
|
|
||||||
ClientStateInterval timedClientStates;
|
ClientStateInterval timedClientStates;
|
||||||
|
|
||||||
@ -84,6 +97,52 @@ class Session : public std::enable_shared_from_this<Session> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sendBoxesToClient() {
|
||||||
|
std::lock_guard<std::mutex> lock(g_boxes_mutex);
|
||||||
|
|
||||||
|
std::string boxMsg = "BOXES:";
|
||||||
|
for (const auto& box : g_serverBoxes) {
|
||||||
|
Eigen::Quaternionf q(box.rotation);
|
||||||
|
boxMsg += 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()) + "|";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!boxMsg.empty() && boxMsg.back() == '|') {
|
||||||
|
boxMsg.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
send_message(boxMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_message(std::string msg) {
|
||||||
|
auto ss = std::make_shared<std::string>(std::move(msg));
|
||||||
|
|
||||||
|
if (is_writing_) {
|
||||||
|
|
||||||
|
ws_.async_write(net::buffer(*ss),
|
||||||
|
[self = shared_from_this(), ss](beast::error_code ec, std::size_t) {
|
||||||
|
if (ec) {
|
||||||
|
std::cerr << "Write error: " << ec.message() << std::endl;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
is_writing_ = true;
|
||||||
|
ws_.async_write(net::buffer(*ss),
|
||||||
|
[self = shared_from_this(), ss](beast::error_code ec, std::size_t) {
|
||||||
|
self->is_writing_ = false;
|
||||||
|
if (ec) {
|
||||||
|
std::cerr << "Write error: " << ec.message() << std::endl;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit Session(tcp::socket&& socket, int id)
|
explicit Session(tcp::socket&& socket, int id)
|
||||||
@ -92,6 +151,16 @@ public:
|
|||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
|
sendBoxesToClient();
|
||||||
|
|
||||||
|
auto timer = std::make_shared<net::steady_timer>(ws_.get_executor());
|
||||||
|
timer->expires_after(std::chrono::milliseconds(100));
|
||||||
|
timer->async_wait([self = shared_from_this(), timer](const boost::system::error_code& ec) {
|
||||||
|
if (!ec) {
|
||||||
|
self->send_message("ID:" + std::to_string(self->id_));
|
||||||
|
self->do_read();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
@ -105,15 +174,15 @@ public:
|
|||||||
if (ec) return;
|
if (ec) return;
|
||||||
std::cout << "Client " << self->id_ << " connected\n";
|
std::cout << "Client " << self->id_ << " connected\n";
|
||||||
self->init();
|
self->init();
|
||||||
self->send_message("ID:" + std::to_string(self->id_));
|
// self->send_message("ID:" + std::to_string(self->id_));
|
||||||
self->do_read();
|
// self->do_read();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_message(std::string msg) {
|
/*void send_message(std::string msg) {
|
||||||
auto ss = std::make_shared<std::string>(std::move(msg));
|
auto ss = std::make_shared<std::string>(std::move(msg));
|
||||||
ws_.async_write(net::buffer(*ss), [ss](beast::error_code, std::size_t) {});
|
ws_.async_write(net::buffer(*ss), [ss](beast::error_code, std::size_t) {});
|
||||||
}
|
}*/
|
||||||
|
|
||||||
int get_id() const {
|
int get_id() const {
|
||||||
return id_;
|
return id_;
|
||||||
@ -151,8 +220,63 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ServerBox> generateServerBoxes(int count) {
|
||||||
|
std::vector<ServerBox> boxes;
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 gen(rd());
|
||||||
|
|
||||||
|
const float MIN_COORD = -100.0f;
|
||||||
|
const float MAX_COORD = 100.0f;
|
||||||
|
const float MIN_DISTANCE = 3.0f;
|
||||||
|
const float MIN_DISTANCE_SQUARED = MIN_DISTANCE * MIN_DISTANCE;
|
||||||
|
const int MAX_ATTEMPTS = 1000;
|
||||||
|
|
||||||
|
std::uniform_real_distribution<> posDistrib(MIN_COORD, MAX_COORD);
|
||||||
|
std::uniform_real_distribution<> angleDistrib(0.0, M_PI * 2.0);
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
bool accepted = false;
|
||||||
|
int attempts = 0;
|
||||||
|
|
||||||
|
while (!accepted && attempts < MAX_ATTEMPTS) {
|
||||||
|
ServerBox box;
|
||||||
|
box.position = Eigen::Vector3f(
|
||||||
|
(float)posDistrib(gen),
|
||||||
|
(float)posDistrib(gen),
|
||||||
|
(float)posDistrib(gen)
|
||||||
|
);
|
||||||
|
|
||||||
|
accepted = true;
|
||||||
|
for (const auto& existingBox : boxes) {
|
||||||
|
Eigen::Vector3f diff = box.position - existingBox.position;
|
||||||
|
if (diff.squaredNorm() < MIN_DISTANCE_SQUARED) {
|
||||||
|
accepted = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (accepted) {
|
||||||
|
float randomAngle = (float)angleDistrib(gen);
|
||||||
|
Eigen::Vector3f axis = Eigen::Vector3f::Random().normalized();
|
||||||
|
box.rotation = Eigen::AngleAxisf(randomAngle, axis).toRotationMatrix();
|
||||||
|
boxes.push_back(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return boxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
try {
|
try {
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(g_boxes_mutex);
|
||||||
|
g_serverBoxes = generateServerBoxes(50);
|
||||||
|
std::cout << "Generated " << g_serverBoxes.size() << " boxes on server\n";
|
||||||
|
}
|
||||||
net::io_context ioc;
|
net::io_context ioc;
|
||||||
tcp::acceptor acceptor{ ioc, {tcp::v4(), 8080} };
|
tcp::acceptor acceptor{ ioc, {tcp::v4(), 8080} };
|
||||||
int next_id = 1000;
|
int next_id = 1000;
|
||||||
|
|||||||
21
src/Game.cpp
21
src/Game.cpp
@ -577,6 +577,27 @@ namespace ZL
|
|||||||
|
|
||||||
latestRemotePlayers = networkClient->getRemotePlayers();
|
latestRemotePlayers = networkClient->getRemotePlayers();
|
||||||
|
|
||||||
|
// Если сервер прислал коробки, применяем их однократно вместо локальной генерации
|
||||||
|
if (!serverBoxesApplied && networkClient) {
|
||||||
|
auto sboxes = networkClient->getServerBoxes();
|
||||||
|
if (!sboxes.empty()) {
|
||||||
|
boxCoordsArr.clear();
|
||||||
|
for (auto &b : sboxes) {
|
||||||
|
BoxCoords bc;
|
||||||
|
bc.pos = b.first;
|
||||||
|
bc.m = b.second;
|
||||||
|
boxCoordsArr.push_back(bc);
|
||||||
|
}
|
||||||
|
boxRenderArr.resize(boxCoordsArr.size());
|
||||||
|
for (int i = 0; i < (int)boxCoordsArr.size(); ++i) {
|
||||||
|
boxRenderArr[i].AssignFrom(boxBase);
|
||||||
|
boxRenderArr[i].RefreshVBO();
|
||||||
|
}
|
||||||
|
boxAlive.assign(boxCoordsArr.size(), true);
|
||||||
|
serverBoxesApplied = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Итерируемся по актуальным данным из extrapolateRemotePlayers
|
// Итерируемся по актуальным данным из extrapolateRemotePlayers
|
||||||
for (auto const& [id, remotePlayer] : latestRemotePlayers) {
|
for (auto const& [id, remotePlayer] : latestRemotePlayers) {
|
||||||
|
|
||||||
|
|||||||
@ -104,6 +104,7 @@ namespace ZL {
|
|||||||
uint64_t lastExplosionTime = 0;
|
uint64_t lastExplosionTime = 0;
|
||||||
const uint64_t explosionDurationMs = 500;
|
const uint64_t explosionDurationMs = 500;
|
||||||
|
|
||||||
|
bool serverBoxesApplied = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ constexpr float SHIP_ACCEL = 1.0f * 1000.0f;
|
|||||||
constexpr float ROTATION_SENSITIVITY = 0.002f;
|
constexpr float ROTATION_SENSITIVITY = 0.002f;
|
||||||
|
|
||||||
constexpr long long SERVER_DELAY = 0; //ms
|
constexpr long long SERVER_DELAY = 0; //ms
|
||||||
constexpr long long CLIENT_DELAY = 200; //ms
|
constexpr long long CLIENT_DELAY = 1000; //ms
|
||||||
constexpr long long CUTOFF_TIME = 5000; //ms
|
constexpr long long CUTOFF_TIME = 5000; //ms
|
||||||
|
|
||||||
struct ClientState {
|
struct ClientState {
|
||||||
|
|||||||
@ -21,5 +21,9 @@ namespace ZL {
|
|||||||
std::unordered_map<int, ClientStateInterval> getRemotePlayers() override {
|
std::unordered_map<int, ClientStateInterval> getRemotePlayers() override {
|
||||||
return std::unordered_map<int, ClientStateInterval>();
|
return std::unordered_map<int, ClientStateInterval>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> getServerBoxes() override {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -15,5 +15,7 @@ namespace ZL {
|
|||||||
virtual bool IsConnected() const = 0;
|
virtual bool IsConnected() const = 0;
|
||||||
virtual void Poll() = 0; // ƒл¤ обработки вход¤щих пакетов
|
virtual void Poll() = 0; // ƒл¤ обработки вход¤щих пакетов
|
||||||
virtual std::unordered_map<int, ClientStateInterval> getRemotePlayers() = 0;
|
virtual std::unordered_map<int, ClientStateInterval> getRemotePlayers() = 0;
|
||||||
|
|
||||||
|
virtual std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> getServerBoxes() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,6 +83,42 @@ namespace ZL {
|
|||||||
std::string msg = messageQueue.front();
|
std::string msg = messageQueue.front();
|
||||||
messageQueue.pop();
|
messageQueue.pop();
|
||||||
|
|
||||||
|
// Обработка списка коробок от сервера
|
||||||
|
if (msg.rfind("BOXES:", 0) == 0) {
|
||||||
|
std::string payload = msg.substr(6); // после "BOXES:"
|
||||||
|
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> parsedBoxes;
|
||||||
|
if (!payload.empty()) {
|
||||||
|
auto items = split(payload, '|');
|
||||||
|
for (auto& item : items) {
|
||||||
|
if (item.empty()) continue;
|
||||||
|
auto parts = split(item, ':');
|
||||||
|
if (parts.size() < 7) continue;
|
||||||
|
try {
|
||||||
|
float px = std::stof(parts[0]);
|
||||||
|
float py = std::stof(parts[1]);
|
||||||
|
float pz = std::stof(parts[2]);
|
||||||
|
Eigen::Quaternionf q(
|
||||||
|
std::stof(parts[3]),
|
||||||
|
std::stof(parts[4]),
|
||||||
|
std::stof(parts[5]),
|
||||||
|
std::stof(parts[6])
|
||||||
|
);
|
||||||
|
Eigen::Matrix3f rot = q.toRotationMatrix();
|
||||||
|
parsedBoxes.emplace_back(Eigen::Vector3f{ px, py, pz }, rot);
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
// пропускаем некорректную запись
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> bLock(boxesMutex);
|
||||||
|
serverBoxes_ = std::move(parsedBoxes);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (msg.rfind("EVENT:", 0) == 0) {
|
if (msg.rfind("EVENT:", 0) == 0) {
|
||||||
auto parts = split(msg, ':');
|
auto parts = split(msg, ':');
|
||||||
if (parts.size() < 5) continue; // EVENT:ID:TYPE:TIME:DATA...
|
if (parts.size() < 5) continue; // EVENT:ID:TYPE:TIME:DATA...
|
||||||
|
|||||||
@ -34,6 +34,10 @@ namespace ZL {
|
|||||||
std::unordered_map<int, ClientStateInterval> remotePlayers;
|
std::unordered_map<int, ClientStateInterval> remotePlayers;
|
||||||
std::mutex playersMutex;
|
std::mutex playersMutex;
|
||||||
|
|
||||||
|
// Серверные коробки
|
||||||
|
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> serverBoxes_;
|
||||||
|
std::mutex boxesMutex;
|
||||||
|
|
||||||
void startAsyncRead();
|
void startAsyncRead();
|
||||||
void processIncomingMessage(const std::string& msg);
|
void processIncomingMessage(const std::string& msg);
|
||||||
|
|
||||||
@ -54,6 +58,11 @@ namespace ZL {
|
|||||||
std::lock_guard<std::mutex> lock(playersMutex);
|
std::lock_guard<std::mutex> lock(playersMutex);
|
||||||
return remotePlayers;
|
return remotePlayers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<Eigen::Vector3f, Eigen::Matrix3f>> getServerBoxes() override {
|
||||||
|
std::lock_guard<std::mutex> lock(boxesMutex);
|
||||||
|
return serverBoxes_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user