Working on server optimization

This commit is contained in:
Vladislav Khorev 2026-02-26 22:26:43 +03:00
parent e8f1786a2a
commit be2aa76f8b
3 changed files with 204 additions and 231 deletions

View File

@ -323,7 +323,6 @@ private:
receivedState.shipType = this->shipType;
timedClientStates.add_state(receivedState);
retranslateMessage(cleanMessage);
}
else if (type == "RESPAWN") {
{
@ -433,16 +432,6 @@ private:
}
}
void retranslateMessage(const std::string& msg) {
std::string event_msg = "EVENT:" + std::to_string(id_) + ":" + msg;
std::lock_guard<std::mutex> lock(g_sessions_mutex);
for (auto& session : g_sessions) {
if (session->get_id() != id_) {
session->send_message(event_msg);
}
}
}
};
void broadcastToAll(const std::string& message) {
@ -454,81 +443,61 @@ void broadcastToAll(const std::string& message) {
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;
static auto last_snapshot_time = std::chrono::system_clock::now();
if (lastTickCount == 0) {
//lastTickCount = SDL_GetTicks64();
lastTickCount = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch()
).count();
auto now = std::chrono::system_clock::now();
uint64_t now_ms = static_cast<uint64_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(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мс
/*
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_snapshot_time).count() >= 1000) {
// --- Snapshot every 500ms ---
/*if (std::chrono::duration_cast<std::chrono::milliseconds>(now - last_snapshot_time).count() >= 500) {
last_snapshot_time = now;
auto system_now = std::chrono::system_clock::now();
std::string snapshot_msg = "SNAPSHOT:" + std::to_string(
std::chrono::duration_cast<std::chrono::milliseconds>(
system_now.time_since_epoch()).count()
);
std::string snapshot_msg = "SNAPSHOT:" + std::to_string(now_ms);
std::lock_guard<std::mutex> lock(g_sessions_mutex);
// Формируем общую строку состояний всех игроков
for (auto& session : g_sessions) {
ClientState st = session->get_latest_state(system_now);
ClientState st = session->get_latest_state(now);
snapshot_msg += "|" + std::to_string(session->get_id()) + ":" + st.formPingMessageContent();
}
for (auto& session : g_sessions) {
session->send_message(snapshot_msg);
}
}*/
const std::chrono::milliseconds interval(50);
timer.expires_after(interval);
// --- Tick: broadcast each player's latest state to all others (20Hz) ---
// Send the raw last-known state with its original timestamp, NOT an extrapolated one.
// Extrapolating here causes snap-back: if a player stops rotating, the server would
// keep sending over-rotated positions until the new state arrives, then B snaps back.
{
std::lock_guard<std::mutex> lock(g_sessions_mutex);
for (auto& sender : g_sessions) {
if (sender->timedClientStates.timedStates.empty()) continue;
timer.async_wait([&](const boost::system::error_code& ec) {
if (ec) return;
const ClientState& st = sender->timedClientStates.timedStates.back();
uint64_t stateTime = static_cast<uint64_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(
st.lastUpdateServerTime.time_since_epoch()).count());
auto now = std::chrono::system_clock::now();
uint64_t now_ms = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count());
std::string event_msg = "EVENT:" + std::to_string(sender->get_id()) +
":UPD:" + std::to_string(stateTime) + ":" + st.formPingMessageContent();
for (auto& receiver : g_sessions) {
if (receiver->get_id() != sender->get_id()) {
receiver->send_message(event_msg);
}
}
}
}
// --- Tick: projectile movement and hit detection ---
const float dt = 50.0f / 1000.0f;
std::vector<DeathInfo> deathEvents;
{
std::lock_guard<std::mutex> pl(g_projectiles_mutex);
std::vector<int> indicesToRemove;
float dt = 50.0f / 1000.0f;
for (size_t i = 0; i < g_projectiles.size(); ++i) {
auto& pr = g_projectiles[i];
@ -593,9 +562,9 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
}
}
// --- Tick: box-projectile collisions ---
{
std::lock_guard<std::mutex> bm(g_boxes_mutex);
//const float projectileHitRadius = 1.5f;
const float projectileHitRadius = 5.0f;
const float boxCollisionRadius = 2.0f;
@ -609,7 +578,6 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
for (size_t pi = 0; pi < g_projectiles.size(); ++pi) {
const auto& pr = g_projectiles[pi];
Eigen::Vector3f diff = pr.pos - boxWorld;
//std::cout << "diff norm is " << diff.norm() << std::endl;
float thresh = boxCollisionRadius + projectileHitRadius;
if (diff.squaredNorm() <= thresh * thresh) {
@ -639,6 +607,7 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
}
}
// --- Tick: box-ship collisions ---
{
std::lock_guard<std::mutex> bm(g_boxes_mutex);
std::lock_guard<std::mutex> lm(g_sessions_mutex);
@ -687,7 +656,7 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
}
}
if (!deathEvents.empty()) {
// --- Broadcast deaths ---
for (const auto& death : deathEvents) {
std::string deadMsg = "DEAD:" +
std::to_string(death.serverTime) + ":" +
@ -702,8 +671,8 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
std::cout << "Server: Sent DEAD event - Player " << death.targetId
<< " killed by " << death.killerId << std::endl;
}
}
// --- Broadcast box destructions ---
{
std::lock_guard<std::mutex> dm(g_boxDestructions_mutex);
for (const auto& destruction : g_boxDestructions) {
@ -721,6 +690,10 @@ void update_world(net::steady_timer& timer, net::io_context& ioc) {
g_boxDestructions.clear();
}
// --- Schedule next tick in 50ms ---
timer.expires_after(std::chrono::milliseconds(50));
timer.async_wait([&timer, &ioc](const boost::system::error_code& ec) {
if (ec) return;
update_world(timer, ioc);
});
}

View File

@ -169,7 +169,7 @@ void ClientState::apply_lag_compensation(std::chrono::system_clock::time_point n
while (deltaMsLeftover > 0)
{
long long miniDelta = 50;
long long miniDelta = std::min(50LL, deltaMsLeftover);
simulate_physics(miniDelta);
deltaMsLeftover -= miniDelta;
}
@ -207,7 +207,7 @@ void ClientState::handle_full_sync(const std::vector<std::string>& parts, int st
discreteAngle = std::stoi(parts[startFrom + 13]);
}
std::string ClientState::formPingMessageContent()
std::string ClientState::formPingMessageContent() const
{
Eigen::Quaternionf q(rotation);

View File

@ -50,7 +50,7 @@ struct ClientState {
void handle_full_sync(const std::vector<std::string>& parts, int startFrom);
std::string formPingMessageContent();
std::string formPingMessageContent() const;
};
struct ClientStateInterval