some fix/added sync boxes

This commit is contained in:
Vlad 2026-02-06 19:16:17 +06:00
parent 65a2066727
commit da2b6e5577
5 changed files with 288 additions and 52 deletions

View File

@ -45,6 +45,7 @@ struct ServerBox {
Eigen::Vector3f position;
Eigen::Matrix3f rotation;
float collisionRadius = 2.0f;
bool destroyed = false;
};
struct Projectile {
@ -55,6 +56,16 @@ struct Projectile {
float lifeMs = 5000.0f;
};
struct BoxDestroyedInfo {
int boxIndex = -1;
uint64_t serverTime = 0;
Eigen::Vector3f position = Eigen::Vector3f::Zero();
int destroyedBy = -1;
};
std::vector<BoxDestroyedInfo> g_boxDestructions;
std::mutex g_boxDestructions_mutex;
std::vector<ServerBox> g_serverBoxes;
std::mutex g_boxes_mutex;
@ -419,6 +430,36 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
static auto last_snapshot_time = std::chrono::steady_clock::now();
auto now = std::chrono::steady_clock::now();
/*static uint64_t lastTickCount = 0;
if (lastTickCount == 0) {
//lastTickCount = SDL_GetTicks64();
lastTickCount = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
lastTickCount = (lastTickCount / 50) * 50;
return;
}
auto newTickCount = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
newTickCount = (newTickCount / 50) * 50;
int64_t deltaMs = static_cast<int64_t>(newTickCount - lastTickCount);
std::chrono::system_clock::time_point nowRounded = std::chrono::system_clock::time_point(std::chrono::milliseconds(newTickCount));
*/
// For each player
// Get letest state + add time (until newTickCount)
// Calculate if collisions with boxes
// Рассылка Snapshot раз в 1000мс
/*
@ -526,6 +567,98 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
}
}
{
std::lock_guard<std::mutex> bm(g_boxes_mutex);
const float projectileHitRadius = 1.5f;
const float boxCollisionRadius = 2.0f;
std::vector<std::pair<size_t, size_t>> boxProjectileCollisions;
for (size_t bi = 0; bi < g_serverBoxes.size(); ++bi) {
if (g_serverBoxes[bi].destroyed) continue;
Eigen::Vector3f boxWorld = g_serverBoxes[bi].position + Eigen::Vector3f(0.0f, 6.0f, 45000.0f);
for (size_t pi = 0; pi < g_projectiles.size(); ++pi) {
const auto& pr = g_projectiles[pi];
Eigen::Vector3f diff = pr.pos - boxWorld;
float thresh = boxCollisionRadius + projectileHitRadius;
if (diff.squaredNorm() <= thresh * thresh) {
boxProjectileCollisions.push_back({ bi, pi });
}
}
}
for (const auto& [boxIdx, projIdx] : boxProjectileCollisions) {
g_serverBoxes[boxIdx].destroyed = true;
Eigen::Vector3f boxWorld = g_serverBoxes[boxIdx].position + Eigen::Vector3f(0.0f, 0.0f, 45000.0f);
BoxDestroyedInfo destruction;
destruction.boxIndex = static_cast<int>(boxIdx);
destruction.serverTime = now_ms;
destruction.position = boxWorld;
destruction.destroyedBy = g_projectiles[projIdx].shooterId;
{
std::lock_guard<std::mutex> dm(g_boxDestructions_mutex);
g_boxDestructions.push_back(destruction);
}
std::cout << "Server: Box " << boxIdx << " destroyed by projectile from player "
<< g_projectiles[projIdx].shooterId << std::endl;
}
}
{
std::lock_guard<std::mutex> bm(g_boxes_mutex);
std::lock_guard<std::mutex> lm(g_sessions_mutex);
const float shipCollisionRadius = 15.0f;
const float boxCollisionRadius = 2.0f;
for (size_t bi = 0; bi < g_serverBoxes.size(); ++bi) {
if (g_serverBoxes[bi].destroyed) continue;
Eigen::Vector3f boxWorld = g_serverBoxes[bi].position + Eigen::Vector3f(0.0f, 0.0f, 45000.0f);
for (auto& session : g_sessions) {
{
std::lock_guard<std::mutex> gd(g_dead_mutex);
if (g_dead_players.find(session->get_id()) != g_dead_players.end()) {
continue;
}
}
ClientState shipState;
if (!session->fetchStateAtTime(now, shipState)) continue;
Eigen::Vector3f diff = shipState.position - boxWorld;
float thresh = shipCollisionRadius + boxCollisionRadius;
if (diff.squaredNorm() <= thresh * thresh) {
g_serverBoxes[bi].destroyed = true;
BoxDestroyedInfo destruction;
destruction.boxIndex = static_cast<int>(bi);
destruction.serverTime = now_ms;
destruction.position = boxWorld;
destruction.destroyedBy = session->get_id();
{
std::lock_guard<std::mutex> dm(g_boxDestructions_mutex);
g_boxDestructions.push_back(destruction);
}
std::cout << "Server: Box " << bi << " destroyed by ship collision with player "
<< session->get_id() << std::endl;
break;
}
}
}
}
if (!deathEvents.empty()) {
for (const auto& death : deathEvents) {
std::string deadMsg = "DEAD:" +
@ -543,6 +676,23 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
}
}
{
std::lock_guard<std::mutex> dm(g_boxDestructions_mutex);
for (const auto& destruction : g_boxDestructions) {
std::string boxMsg = "BOX_DESTROYED:" +
std::to_string(destruction.boxIndex) + ":" +
std::to_string(destruction.serverTime) + ":" +
std::to_string(destruction.position.x()) + ":" +
std::to_string(destruction.position.y()) + ":" +
std::to_string(destruction.position.z()) + ":" +
std::to_string(destruction.destroyedBy);
broadcastToAll(boxMsg);
std::cout << "Server: Broadcasted BOX_DESTROYED for box " << destruction.boxIndex << std::endl;
}
g_boxDestructions.clear();
}
update_world(timer, ioc);
});
}

View File

@ -764,6 +764,7 @@ namespace ZL
for (auto const& [id, remotePlayer] : remotePlayerStates) {
const ClientState& playerState = remotePlayer;
if (deadRemotePlayers.count(id)) continue;
renderer.PushMatrix();
renderer.LoadIdentity();
@ -1177,7 +1178,7 @@ namespace ZL
}
}
for (int i = 0; i < boxCoordsArr.size(); ++i) {
/*for (int i = 0; i < boxCoordsArr.size(); ++i) {
if (!boxAlive[i]) continue;
Vector3f boxWorld = boxCoordsArr[i].pos + Vector3f{ 0.0f, 0.0f, 45000.0f };
Vector3f diff = Environment::shipState.position - boxWorld;
@ -1230,7 +1231,7 @@ namespace ZL
break;
}
}
}
}*/
uiManager.update(static_cast<float>(delta));
lastTickCount = newTickCount;
@ -1510,9 +1511,46 @@ namespace ZL
if (!respawns.empty()) {
for (const auto& respawnId : respawns) {
deadRemotePlayers.erase(respawnId);
auto it = remotePlayerStates.find(respawnId);
if (it != remotePlayerStates.end()) {
it->second.position = Vector3f{ 0.f, 0.f, 45000.f };
it->second.velocity = 0.0f;
it->second.rotation = Eigen::Matrix3f::Identity();
}
std::cout << "Client: Remote player " << respawnId << " respawned, removed from dead list" << std::endl;
}
}
auto boxDestructions = networkClient->getPendingBoxDestructions();
if (!boxDestructions.empty()) {
std::cout << "Game: Received " << boxDestructions.size() << " box destruction events" << std::endl;
for (const auto& destruction : boxDestructions) {
int idx = destruction.boxIndex;
if (idx >= 0 && idx < (int)boxCoordsArr.size()) {
if (boxAlive[idx]) {
boxAlive[idx] = false;
boxRenderArr[idx].data.PositionData.clear();
boxRenderArr[idx].vao.reset();
boxRenderArr[idx].positionVBO.reset();
boxRenderArr[idx].texCoordVBO.reset();
showExplosion = true;
explosionEmitter.setUseWorldSpace(true);
explosionEmitter.setEmissionPoints(std::vector<Vector3f>{ destruction.position });
explosionEmitter.emit();
lastExplosionTime = SDL_GetTicks64();
std::cout << "Game: Box " << idx << " destroyed by player "
<< destruction.destroyedBy << std::endl;
}
}
}
}
}
}

View File

@ -23,6 +23,13 @@ namespace ZL {
int killerId = -1;
};
struct BoxDestroyedInfo {
int boxIndex = -1;
uint64_t serverTime = 0;
Eigen::Vector3f position = Eigen::Vector3f::Zero();
int destroyedBy = -1;
};
class INetworkClient {
public:
virtual ~INetworkClient() = default;
@ -39,5 +46,6 @@ namespace ZL {
virtual std::vector<DeathInfo> getPendingDeaths() = 0;
virtual std::vector<int> getPendingRespawns() = 0;
virtual int GetClientId() const { return -1; }
virtual std::vector<BoxDestroyedInfo> getPendingBoxDestructions() = 0;
};
}

View File

@ -85,6 +85,13 @@ namespace ZL {
return copy;
}
std::vector<BoxDestroyedInfo> WebSocketClient::getPendingBoxDestructions() {
std::lock_guard<std::mutex> lock(boxDestructionsMutex_);
auto copy = pendingBoxDestructions_;
pendingBoxDestructions_.clear();
return copy;
}
void WebSocketClient::Poll() {
std::lock_guard<std::mutex> lock(queueMutex);
@ -159,6 +166,35 @@ namespace ZL {
continue;
}
if (msg.rfind("BOX_DESTROYED:", 0) == 0) {
auto parts = split(msg, ':');
if (parts.size() >= 7) {
try {
BoxDestroyedInfo destruction;
destruction.boxIndex = std::stoi(parts[1]);
destruction.serverTime = std::stoull(parts[2]);
destruction.position = Eigen::Vector3f(
std::stof(parts[3]),
std::stof(parts[4]),
std::stof(parts[5])
);
destruction.destroyedBy = std::stoi(parts[6]);
{
std::lock_guard<std::mutex> lock(boxDestructionsMutex_);
pendingBoxDestructions_.push_back(destruction);
}
std::cout << "Client: Received BOX_DESTROYED for box " << destruction.boxIndex
<< " destroyed by player " << destruction.destroyedBy << std::endl;
}
catch (const std::exception& e) {
std::cerr << "Client: Error parsing BOX_DESTROYED: " << e.what() << std::endl;
}
}
continue;
}
if (msg.rfind("PROJECTILE:", 0) == 0) {
auto parts = split(msg, ':');
if (parts.size() >= 10) {

View File

@ -46,6 +46,9 @@ namespace ZL {
std::vector<int> pendingRespawns_;
std::mutex respawnMutex_;
std::vector<BoxDestroyedInfo> pendingBoxDestructions_;
std::mutex boxDestructionsMutex_;
void startAsyncRead();
void processIncomingMessage(const std::string& msg);
@ -75,6 +78,7 @@ namespace ZL {
std::vector<ProjectileInfo> getPendingProjectiles() override;
std::vector<DeathInfo> getPendingDeaths() override;
std::vector<int> getPendingRespawns() override;
std::vector<BoxDestroyedInfo> getPendingBoxDestructions() override;
};
}
#endif