some fix/added sync boxes
This commit is contained in:
parent
65a2066727
commit
da2b6e5577
@ -45,6 +45,7 @@ struct ServerBox {
|
|||||||
Eigen::Vector3f position;
|
Eigen::Vector3f position;
|
||||||
Eigen::Matrix3f rotation;
|
Eigen::Matrix3f rotation;
|
||||||
float collisionRadius = 2.0f;
|
float collisionRadius = 2.0f;
|
||||||
|
bool destroyed = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Projectile {
|
struct Projectile {
|
||||||
@ -55,6 +56,16 @@ struct Projectile {
|
|||||||
float lifeMs = 5000.0f;
|
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::vector<ServerBox> g_serverBoxes;
|
||||||
std::mutex g_boxes_mutex;
|
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();
|
static auto last_snapshot_time = std::chrono::steady_clock::now();
|
||||||
auto now = 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мс
|
// Рассылка 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()) {
|
if (!deathEvents.empty()) {
|
||||||
for (const auto& death : deathEvents) {
|
for (const auto& death : deathEvents) {
|
||||||
std::string deadMsg = "DEAD:" +
|
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);
|
update_world(timer, ioc);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
136
src/Game.cpp
136
src/Game.cpp
@ -246,7 +246,7 @@ namespace ZL
|
|||||||
ZL::CheckGlError();
|
ZL::CheckGlError();
|
||||||
|
|
||||||
|
|
||||||
//#ifndef SIMPLIFIED
|
//#ifndef SIMPLIFIED
|
||||||
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("defaultColor", "resources/shaders/defaultColor.vertex", "resources/shaders/defaultColor_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/env_sky.vertex", "resources/shaders/env_sky_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/env_sky.vertex", "resources/shaders/env_sky_web.fragment", CONST_ZIP_FILE);
|
||||||
@ -255,14 +255,14 @@ namespace ZL
|
|||||||
renderer.shaderManager.AddShaderFromFiles("planetStone", "resources/shaders/planet_stone.vertex", "resources/shaders/planet_stone_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("planetStone", "resources/shaders/planet_stone.vertex", "resources/shaders/planet_stone_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("planetLand", "resources/shaders/planet_land.vertex", "resources/shaders/planet_land_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("planetLand", "resources/shaders/planet_land.vertex", "resources/shaders/planet_land_web.fragment", CONST_ZIP_FILE);
|
||||||
|
|
||||||
/*#else
|
/*#else
|
||||||
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("default", "resources/shaders/default.vertex", "resources/shaders/default_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/default_env.vertex", "resources/shaders/default_env_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("env_sky", "resources/shaders/default_env.vertex", "resources/shaders/default_env_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "resources/shaders/default_texture.vertex", "resources/shaders/default_texture_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("defaultAtmosphere", "resources/shaders/default_texture.vertex", "resources/shaders/default_texture_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("planetBake", "resources/shaders/default_texture.vertex", "resources/shaders/default_texture_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("planetBake", "resources/shaders/default_texture.vertex", "resources/shaders/default_texture_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("planetStone", "resources/shaders/default_texture.vertex", "resources/shaders/default_texture_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("planetStone", "resources/shaders/default_texture.vertex", "resources/shaders/default_texture_web.fragment", CONST_ZIP_FILE);
|
||||||
renderer.shaderManager.AddShaderFromFiles("planetLand", "resources/shaders/default_texture.vertex", "resources/shaders/default_texture_web.fragment", CONST_ZIP_FILE);
|
renderer.shaderManager.AddShaderFromFiles("planetLand", "resources/shaders/default_texture.vertex", "resources/shaders/default_texture_web.fragment", CONST_ZIP_FILE);
|
||||||
#endif*/
|
#endif*/
|
||||||
|
|
||||||
bool cfgLoaded = sparkEmitter.loadFromJsonFile("resources/config/spark_config.json", renderer, CONST_ZIP_FILE);
|
bool cfgLoaded = sparkEmitter.loadFromJsonFile("resources/config/spark_config.json", renderer, CONST_ZIP_FILE);
|
||||||
bool projCfgLoaded = projectileEmitter.loadFromJsonFile("resources/config/spark_projectile_config.json", renderer, CONST_ZIP_FILE);
|
bool projCfgLoaded = projectileEmitter.loadFromJsonFile("resources/config/spark_projectile_config.json", renderer, CONST_ZIP_FILE);
|
||||||
@ -764,6 +764,7 @@ namespace ZL
|
|||||||
for (auto const& [id, remotePlayer] : remotePlayerStates) {
|
for (auto const& [id, remotePlayer] : remotePlayerStates) {
|
||||||
|
|
||||||
const ClientState& playerState = remotePlayer;
|
const ClientState& playerState = remotePlayer;
|
||||||
|
if (deadRemotePlayers.count(id)) continue;
|
||||||
|
|
||||||
renderer.PushMatrix();
|
renderer.PushMatrix();
|
||||||
renderer.LoadIdentity();
|
renderer.LoadIdentity();
|
||||||
@ -796,53 +797,53 @@ namespace ZL
|
|||||||
{
|
{
|
||||||
if (!textRenderer) return;
|
if (!textRenderer) return;
|
||||||
|
|
||||||
#ifdef NETWORK
|
#ifdef NETWORK
|
||||||
// 2D поверх 3D
|
// 2D поверх 3D
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
// Берем удаленных игроков
|
// Берем удаленных игроков
|
||||||
//latestRemotePlayers = networkClient->getRemotePlayers();
|
//latestRemotePlayers = networkClient->getRemotePlayers();
|
||||||
|
|
||||||
auto now = std::chrono::system_clock::now();
|
auto now = std::chrono::system_clock::now();
|
||||||
now -= std::chrono::milliseconds(CLIENT_DELAY);
|
now -= std::chrono::milliseconds(CLIENT_DELAY);
|
||||||
|
|
||||||
for (auto const& [id, remotePlayer] : remotePlayerStates)
|
for (auto const& [id, remotePlayer] : remotePlayerStates)
|
||||||
{
|
{
|
||||||
|
|
||||||
const ClientState& st = remotePlayer;
|
const ClientState& st = remotePlayer;
|
||||||
// Позиция корабля в мире
|
// Позиция корабля в мире
|
||||||
Vector3f shipWorld = st.position;
|
Vector3f shipWorld = st.position;
|
||||||
|
|
||||||
float distSq = (Environment::shipState.position - shipWorld).squaredNorm();
|
float distSq = (Environment::shipState.position - shipWorld).squaredNorm();
|
||||||
/*if (distSq > MAX_DIST_SQ) // дальность прорисовки никнейма
|
/*if (distSq > MAX_DIST_SQ) // дальность прорисовки никнейма
|
||||||
continue;*/
|
continue;*/
|
||||||
float dist = sqrt(distSq);
|
float dist = sqrt(distSq);
|
||||||
float alpha = 1.0f; // постоянная видимость
|
float alpha = 1.0f; // постоянная видимость
|
||||||
/*float alpha = std::clamp(1.f - (dist - FADE_START) / FADE_RANGE, 0.f, 1.f); // дальность прорисовки никнейма
|
/*float alpha = std::clamp(1.f - (dist - FADE_START) / FADE_RANGE, 0.f, 1.f); // дальность прорисовки никнейма
|
||||||
if (alpha < 0.01f)
|
if (alpha < 0.01f)
|
||||||
continue; */
|
continue; */
|
||||||
Vector3f labelWorld = shipWorld + Vector3f{ 0.f, -4.f, 0.f }; // регулировка высоты
|
Vector3f labelWorld = shipWorld + Vector3f{ 0.f, -4.f, 0.f }; // регулировка высоты
|
||||||
float sx, sy, depth;
|
float sx, sy, depth;
|
||||||
if (!worldToScreen(labelWorld, sx, sy, depth))
|
if (!worldToScreen(labelWorld, sx, sy, depth))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
float uiX = sx, uiY = sy;
|
float uiX = sx, uiY = sy;
|
||||||
float scale = std::clamp(BASE_SCALE / (dist * PERSPECTIVE_K + 1.f), MIN_SCALE, MAX_SCALE);
|
float scale = std::clamp(BASE_SCALE / (dist * PERSPECTIVE_K + 1.f), MIN_SCALE, MAX_SCALE);
|
||||||
|
|
||||||
// Дефолтный лейбл
|
// Дефолтный лейбл
|
||||||
std::string label = "Player (" + std::to_string(st.id) + ") " + std::to_string((int)dist) + "m";
|
std::string label = "Player (" + std::to_string(st.id) + ") " + std::to_string((int)dist) + "m";
|
||||||
|
|
||||||
// TODO: nickname sync
|
// TODO: nickname sync
|
||||||
|
|
||||||
textRenderer->drawText(label, uiX + 1.f, uiY + 1.f, scale, true, {0.f, 0.f, 0.f, alpha}); // color param
|
textRenderer->drawText(label, uiX + 1.f, uiY + 1.f, scale, true, { 0.f, 0.f, 0.f, alpha }); // color param
|
||||||
textRenderer->drawText(label, uiX, uiY, scale, true, { 1.f, 1.f, 1.f, alpha });
|
textRenderer->drawText(label, uiX, uiY, scale, true, { 1.f, 1.f, 1.f, alpha });
|
||||||
}
|
}
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::processTickCount() {
|
void Game::processTickCount() {
|
||||||
@ -853,7 +854,7 @@ namespace ZL
|
|||||||
std::chrono::system_clock::now().time_since_epoch()
|
std::chrono::system_clock::now().time_since_epoch()
|
||||||
).count();
|
).count();
|
||||||
|
|
||||||
lastTickCount = (lastTickCount / 50)*50;
|
lastTickCount = (lastTickCount / 50) * 50;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -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;
|
if (!boxAlive[i]) continue;
|
||||||
Vector3f boxWorld = boxCoordsArr[i].pos + Vector3f{ 0.0f, 0.0f, 45000.0f };
|
Vector3f boxWorld = boxCoordsArr[i].pos + Vector3f{ 0.0f, 0.0f, 45000.0f };
|
||||||
Vector3f diff = Environment::shipState.position - boxWorld;
|
Vector3f diff = Environment::shipState.position - boxWorld;
|
||||||
@ -1230,7 +1231,7 @@ namespace ZL
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
uiManager.update(static_cast<float>(delta));
|
uiManager.update(static_cast<float>(delta));
|
||||||
lastTickCount = newTickCount;
|
lastTickCount = newTickCount;
|
||||||
@ -1510,9 +1511,46 @@ namespace ZL
|
|||||||
if (!respawns.empty()) {
|
if (!respawns.empty()) {
|
||||||
for (const auto& respawnId : respawns) {
|
for (const auto& respawnId : respawns) {
|
||||||
deadRemotePlayers.erase(respawnId);
|
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;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,13 @@ namespace ZL {
|
|||||||
int killerId = -1;
|
int killerId = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BoxDestroyedInfo {
|
||||||
|
int boxIndex = -1;
|
||||||
|
uint64_t serverTime = 0;
|
||||||
|
Eigen::Vector3f position = Eigen::Vector3f::Zero();
|
||||||
|
int destroyedBy = -1;
|
||||||
|
};
|
||||||
|
|
||||||
class INetworkClient {
|
class INetworkClient {
|
||||||
public:
|
public:
|
||||||
virtual ~INetworkClient() = default;
|
virtual ~INetworkClient() = default;
|
||||||
@ -39,5 +46,6 @@ namespace ZL {
|
|||||||
virtual std::vector<DeathInfo> getPendingDeaths() = 0;
|
virtual std::vector<DeathInfo> getPendingDeaths() = 0;
|
||||||
virtual std::vector<int> getPendingRespawns() = 0;
|
virtual std::vector<int> getPendingRespawns() = 0;
|
||||||
virtual int GetClientId() const { return -1; }
|
virtual int GetClientId() const { return -1; }
|
||||||
|
virtual std::vector<BoxDestroyedInfo> getPendingBoxDestructions() = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,6 +85,13 @@ namespace ZL {
|
|||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<BoxDestroyedInfo> WebSocketClient::getPendingBoxDestructions() {
|
||||||
|
std::lock_guard<std::mutex> lock(boxDestructionsMutex_);
|
||||||
|
auto copy = pendingBoxDestructions_;
|
||||||
|
pendingBoxDestructions_.clear();
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
void WebSocketClient::Poll() {
|
void WebSocketClient::Poll() {
|
||||||
std::lock_guard<std::mutex> lock(queueMutex);
|
std::lock_guard<std::mutex> lock(queueMutex);
|
||||||
|
|
||||||
@ -159,6 +166,35 @@ namespace ZL {
|
|||||||
continue;
|
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) {
|
if (msg.rfind("PROJECTILE:", 0) == 0) {
|
||||||
auto parts = split(msg, ':');
|
auto parts = split(msg, ':');
|
||||||
if (parts.size() >= 10) {
|
if (parts.size() >= 10) {
|
||||||
|
|||||||
@ -46,6 +46,9 @@ namespace ZL {
|
|||||||
std::vector<int> pendingRespawns_;
|
std::vector<int> pendingRespawns_;
|
||||||
std::mutex respawnMutex_;
|
std::mutex respawnMutex_;
|
||||||
|
|
||||||
|
std::vector<BoxDestroyedInfo> pendingBoxDestructions_;
|
||||||
|
std::mutex boxDestructionsMutex_;
|
||||||
|
|
||||||
void startAsyncRead();
|
void startAsyncRead();
|
||||||
void processIncomingMessage(const std::string& msg);
|
void processIncomingMessage(const std::string& msg);
|
||||||
|
|
||||||
@ -75,6 +78,7 @@ namespace ZL {
|
|||||||
std::vector<ProjectileInfo> getPendingProjectiles() override;
|
std::vector<ProjectileInfo> getPendingProjectiles() override;
|
||||||
std::vector<DeathInfo> getPendingDeaths() override;
|
std::vector<DeathInfo> getPendingDeaths() override;
|
||||||
std::vector<int> getPendingRespawns() override;
|
std::vector<int> getPendingRespawns() override;
|
||||||
|
std::vector<BoxDestroyedInfo> getPendingBoxDestructions() override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user