added choising spaceship type for multiplayer and some fix in respawn
This commit is contained in:
parent
5216965496
commit
74c2f786a1
@ -93,6 +93,9 @@ class Session : public std::enable_shared_from_this<Session> {
|
|||||||
public:
|
public:
|
||||||
ClientStateInterval timedClientStates;
|
ClientStateInterval timedClientStates;
|
||||||
|
|
||||||
|
std::string nickname = "Player";
|
||||||
|
int shipType = 0;
|
||||||
|
|
||||||
explicit Session(tcp::socket&& socket, int id)
|
explicit Session(tcp::socket&& socket, int id)
|
||||||
: ws_(std::move(socket)), id_(id) {
|
: ws_(std::move(socket)), id_(id) {
|
||||||
}
|
}
|
||||||
@ -253,7 +256,6 @@ private:
|
|||||||
|
|
||||||
void process_message(const std::string& msg) {
|
void process_message(const std::string& msg) {
|
||||||
if (!IsMessageValid(msg)) {
|
if (!IsMessageValid(msg)) {
|
||||||
// Логируем попытку подмены и просто выходим из обработки
|
|
||||||
std::cout << "[Security] Invalid packet hash. Dropping message: " << msg << std::endl;
|
std::cout << "[Security] Invalid packet hash. Dropping message: " << msg << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -266,7 +268,40 @@ private:
|
|||||||
|
|
||||||
std::string type = parts[0];
|
std::string type = parts[0];
|
||||||
|
|
||||||
if (type == "UPD") {
|
if (type == "JOIN") {
|
||||||
|
std::string nick = "Player";
|
||||||
|
int sType = 0;
|
||||||
|
if (parts.size() >= 2) nick = parts[1];
|
||||||
|
if (parts.size() >= 3) {
|
||||||
|
try { sType = std::stoi(parts[2]); }
|
||||||
|
catch (...) { sType = 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
this->nickname = nick;
|
||||||
|
this->shipType = sType;
|
||||||
|
|
||||||
|
std::cout << "Server: Player " << id_ << " joined as [" << nick << "] shipType=" << sType << std::endl;
|
||||||
|
|
||||||
|
std::string info = "PLAYERINFO:" + std::to_string(id_) + ":" + nick + ":" + std::to_string(sType);
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(g_sessions_mutex);
|
||||||
|
for (auto& session : g_sessions) {
|
||||||
|
if (session->get_id() == this->id_) continue;
|
||||||
|
session->send_message(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(g_sessions_mutex);
|
||||||
|
for (auto& session : g_sessions) {
|
||||||
|
if (session->get_id() == this->id_) continue;
|
||||||
|
std::string otherInfo = "PLAYERINFO:" + std::to_string(session->get_id()) + ":" + session->nickname + ":" + std::to_string(session->shipType);
|
||||||
|
// Отправляем именно новому клиенту
|
||||||
|
this->send_message(otherInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == "UPD") {
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> gd(g_dead_mutex);
|
std::lock_guard<std::mutex> gd(g_dead_mutex);
|
||||||
if (g_dead_players.find(id_) != g_dead_players.end()) {
|
if (g_dead_players.find(id_) != g_dead_players.end()) {
|
||||||
@ -284,20 +319,48 @@ private:
|
|||||||
};
|
};
|
||||||
receivedState.lastUpdateServerTime = uptime_timepoint;
|
receivedState.lastUpdateServerTime = uptime_timepoint;
|
||||||
receivedState.handle_full_sync(parts, 2);
|
receivedState.handle_full_sync(parts, 2);
|
||||||
|
receivedState.nickname = this->nickname;
|
||||||
|
receivedState.shipType = this->shipType;
|
||||||
timedClientStates.add_state(receivedState);
|
timedClientStates.add_state(receivedState);
|
||||||
|
|
||||||
retranslateMessage(cleanMessage);
|
retranslateMessage(cleanMessage);
|
||||||
}
|
}
|
||||||
else if (parts[0] == "RESPAWN") {
|
else if (type == "RESPAWN") {
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> gd(g_dead_mutex);
|
std::lock_guard<std::mutex> gd(g_dead_mutex);
|
||||||
g_dead_players.erase(id_);
|
g_dead_players.erase(id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto now_tp = std::chrono::system_clock::now();
|
||||||
|
uint64_t now_ms = static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::milliseconds>(now_tp.time_since_epoch()).count());
|
||||||
|
|
||||||
|
ClientState st;
|
||||||
|
st.id = id_;
|
||||||
|
st.position = Eigen::Vector3f(0.0f, 0.0f, 45000.0f);
|
||||||
|
st.rotation = Eigen::Matrix3f::Identity();
|
||||||
|
st.currentAngularVelocity = Eigen::Vector3f::Zero();
|
||||||
|
st.velocity = 0.0f;
|
||||||
|
st.selectedVelocity = 0;
|
||||||
|
st.discreteMag = 0.0f;
|
||||||
|
st.discreteAngle = -1;
|
||||||
|
st.lastUpdateServerTime = now_tp;
|
||||||
|
st.nickname = this->nickname;
|
||||||
|
st.shipType = this->shipType;
|
||||||
|
|
||||||
|
timedClientStates.add_state(st);
|
||||||
|
|
||||||
std::string respawnMsg = "RESPAWN_ACK:" + std::to_string(id_);
|
std::string respawnMsg = "RESPAWN_ACK:" + std::to_string(id_);
|
||||||
broadcastToAll(respawnMsg);
|
broadcastToAll(respawnMsg);
|
||||||
|
|
||||||
std::cout << "Server: Player " << id_ << " respawned\n";
|
std::string playerInfo = "PLAYERINFO:" + std::to_string(id_) + ":" + st.nickname + ":" + std::to_string(st.shipType);
|
||||||
|
broadcastToAll(playerInfo);
|
||||||
|
|
||||||
|
std::string eventMsg = "EVENT:" + std::to_string(id_) + ":UPD:" + std::to_string(now_ms) + ":" + st.formPingMessageContent();
|
||||||
|
broadcastToAll(eventMsg);
|
||||||
|
|
||||||
|
std::cout << "Server: Player " << id_ << " respawned, broadcasted RESPAWN_ACK, PLAYERINFO and initial UPD\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (parts[0] == "FIRE") {
|
else if (parts[0] == "FIRE") {
|
||||||
if (parts.size() < 10) return;
|
if (parts.size() < 10) return;
|
||||||
@ -344,8 +407,8 @@ private:
|
|||||||
Eigen::Vector3f(1.5f, 0.9f - 6.f, 5.0f)
|
Eigen::Vector3f(1.5f, 0.9f - 6.f, 5.0f)
|
||||||
};
|
};
|
||||||
|
|
||||||
uint64_t now_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
|
uint64_t now_ms = std::chrono::duration_cast<std::chrono::milliseconds>((
|
||||||
std::chrono::system_clock::now().time_since_epoch()).count();
|
std::chrono::system_clock::now().time_since_epoch())).count();
|
||||||
|
|
||||||
std::lock_guard<std::mutex> pl(g_projectiles_mutex);
|
std::lock_guard<std::mutex> pl(g_projectiles_mutex);
|
||||||
for (int i = 0; i < std::min(shotCount, (int)localOffsets.size()); ++i) {
|
for (int i = 0; i < std::min(shotCount, (int)localOffsets.size()); ++i) {
|
||||||
|
|||||||
26
src/Game.cpp
26
src/Game.cpp
@ -24,6 +24,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "network/LocalClient.h"
|
#include "network/LocalClient.h"
|
||||||
|
#include "network/ClientState.h"
|
||||||
|
|
||||||
|
|
||||||
namespace ZL
|
namespace ZL
|
||||||
@ -122,7 +123,11 @@ namespace ZL
|
|||||||
spaceGameStarted = 1;
|
spaceGameStarted = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
menuManager.onMultiplayerPressed = [this]() {
|
menuManager.onMultiplayerPressed = [this](const std::string& nickname, int shipType) {
|
||||||
|
Environment::shipState.nickname = nickname;
|
||||||
|
Environment::shipState.shipType = shipType;
|
||||||
|
|
||||||
|
networkClient = std::make_unique<LocalClient>();
|
||||||
#ifdef NETWORK
|
#ifdef NETWORK
|
||||||
#ifdef EMSCRIPTEN
|
#ifdef EMSCRIPTEN
|
||||||
networkClient = std::make_unique<WebSocketClientEmscripten>();
|
networkClient = std::make_unique<WebSocketClientEmscripten>();
|
||||||
@ -131,7 +136,26 @@ namespace ZL
|
|||||||
networkClient = std::make_unique<WebSocketClient>(taskManager.getIOContext());
|
networkClient = std::make_unique<WebSocketClient>(taskManager.getIOContext());
|
||||||
networkClient->Connect("localhost", 8081);
|
networkClient->Connect("localhost", 8081);
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
networkClient->Connect("", 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef NETWORK
|
||||||
|
auto localClient = dynamic_cast<ZL::LocalClient*>(networkClient.get());
|
||||||
|
if (localClient) {
|
||||||
|
ZL::ClientState st = Environment::shipState;
|
||||||
|
st.id = localClient->GetClientId();
|
||||||
|
localClient->setLocalPlayerState(st);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
if (networkClient) {
|
||||||
|
std::string joinMsg = std::string("JOIN:") + nickname + ":" + std::to_string(shipType);
|
||||||
|
networkClient->Send(joinMsg);
|
||||||
|
std::cerr << "Sent JOIN: " << joinMsg << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
lastTickCount = 0;
|
lastTickCount = 0;
|
||||||
spaceGameStarted = 1;
|
spaceGameStarted = 1;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -148,10 +148,39 @@ namespace ZL {
|
|||||||
std::cerr << "Failed to push ship selection menu\n";
|
std::cerr << "Failed to push ship selection menu\n";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
uiManager.setButtonCallback("multiplayerButton", [loadGameplayUI, this](const std::string& name) {
|
|
||||||
std::cerr << "Multiplayer button pressed: " << name << " -> load gameplay UI\n";
|
uiManager.setButtonCallback("multiplayerButton", [this, shipSelectionRoot, loadGameplayUI](const std::string& name) {
|
||||||
|
std::cerr << "Multiplayer button pressed: " << name << " -> open ship selection UI\n";
|
||||||
|
if (!shipSelectionRoot) {
|
||||||
|
std::cerr << "Failed to load ship selection UI\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (uiManager.pushMenuFromSavedRoot(shipSelectionRoot)) {
|
||||||
|
uiManager.setButtonCallback("spaceshipButton", [this, loadGameplayUI](const std::string& btnName) {
|
||||||
|
std::string nick = uiManager.getTextFieldValue("nicknameInput");
|
||||||
|
if (nick.empty()) nick = "Player";
|
||||||
|
int shipType = 0;
|
||||||
|
uiManager.popMenu();
|
||||||
loadGameplayUI();
|
loadGameplayUI();
|
||||||
onMultiplayerPressed();
|
if (onMultiplayerPressed) onMultiplayerPressed(nick, shipType);
|
||||||
|
});
|
||||||
|
|
||||||
|
uiManager.setButtonCallback("cargoshipButton", [this, loadGameplayUI](const std::string& btnName) {
|
||||||
|
std::string nick = uiManager.getTextFieldValue("nicknameInput");
|
||||||
|
if (nick.empty()) nick = "Player";
|
||||||
|
int shipType = 1;
|
||||||
|
uiManager.popMenu();
|
||||||
|
loadGameplayUI();
|
||||||
|
if (onMultiplayerPressed) onMultiplayerPressed(nick, shipType);
|
||||||
|
});
|
||||||
|
|
||||||
|
uiManager.setButtonCallback("backButton", [this](const std::string& btnName) {
|
||||||
|
uiManager.popMenu();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cerr << "Failed to push ship selection menu\n";
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
uiManager.setButtonCallback("multiplayerButton2", [this](const std::string& name) {
|
uiManager.setButtonCallback("multiplayerButton2", [this](const std::string& name) {
|
||||||
@ -164,7 +193,6 @@ namespace ZL {
|
|||||||
|
|
||||||
if (uiManager.pushMenuFromSavedRoot(multiplayerSavedRoot)) {
|
if (uiManager.pushMenuFromSavedRoot(multiplayerSavedRoot)) {
|
||||||
|
|
||||||
// Callback для кнопки подключения
|
|
||||||
uiManager.setButtonCallback("connectButton", [this](const std::string& buttonName) {
|
uiManager.setButtonCallback("connectButton", [this](const std::string& buttonName) {
|
||||||
std::string serverAddress = uiManager.getTextFieldValue("serverInputField");
|
std::string serverAddress = uiManager.getTextFieldValue("serverInputField");
|
||||||
|
|
||||||
@ -176,16 +204,12 @@ namespace ZL {
|
|||||||
uiManager.setText("statusText", "Connecting to " + serverAddress + "...");
|
uiManager.setText("statusText", "Connecting to " + serverAddress + "...");
|
||||||
std::cerr << "Connecting to server: " << serverAddress << std::endl;
|
std::cerr << "Connecting to server: " << serverAddress << std::endl;
|
||||||
|
|
||||||
// Здесь добавить вашу логику подключения к серверу
|
|
||||||
// connectToServer(serverAddress);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Callback для кнопки назад
|
|
||||||
uiManager.setButtonCallback("backButton", [this](const std::string& buttonName) {
|
uiManager.setButtonCallback("backButton", [this](const std::string& buttonName) {
|
||||||
uiManager.popMenu();
|
uiManager.popMenu();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Callback для отслеживания ввода текста
|
|
||||||
uiManager.setTextFieldCallback("serverInputField",
|
uiManager.setTextFieldCallback("serverInputField",
|
||||||
[this](const std::string& fieldName, const std::string& newText) {
|
[this](const std::string& fieldName, const std::string& newText) {
|
||||||
std::cout << "Server input field changed to: " << newText << std::endl;
|
std::cout << "Server input field changed to: " << newText << std::endl;
|
||||||
|
|||||||
@ -35,7 +35,7 @@ namespace ZL {
|
|||||||
std::function<void()> onFirePressed;
|
std::function<void()> onFirePressed;
|
||||||
|
|
||||||
std::function<void(const std::string&, int)> onSingleplayerPressed;
|
std::function<void(const std::string&, int)> onSingleplayerPressed;
|
||||||
std::function<void()> onMultiplayerPressed;
|
std::function<void(const std::string&, int)> onMultiplayerPressed;
|
||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -267,6 +267,16 @@ namespace ZL
|
|||||||
Environment::zoom = DEFAULT_ZOOM;
|
Environment::zoom = DEFAULT_ZOOM;
|
||||||
Environment::tapDownHold = false;
|
Environment::tapDownHold = false;
|
||||||
|
|
||||||
|
if (networkClient) {
|
||||||
|
try {
|
||||||
|
networkClient->Send(std::string("RESPAWN"));
|
||||||
|
std::cout << "Client: Sent RESPAWN to server\n";
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
std::cerr << "Client: Failed to send RESPAWN\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::cerr << "Game restarted\n";
|
std::cerr << "Game restarted\n";
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -677,8 +687,6 @@ namespace ZL
|
|||||||
{
|
{
|
||||||
if (!textRenderer) return;
|
if (!textRenderer) return;
|
||||||
|
|
||||||
//#ifdef NETWORK
|
|
||||||
// 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);
|
||||||
@ -688,18 +696,12 @@ namespace ZL
|
|||||||
if (deadRemotePlayers.count(id)) continue;
|
if (deadRemotePlayers.count(id)) continue;
|
||||||
|
|
||||||
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) // дальность прорисовки никнейма
|
|
||||||
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); // дальность прорисовки никнейма
|
Vector3f labelWorld = shipWorld + Vector3f{ 0.f, -4.f, 0.f };
|
||||||
if (alpha < 0.01f)
|
|
||||||
continue; */
|
|
||||||
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;
|
||||||
@ -707,18 +709,21 @@ namespace ZL
|
|||||||
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 displayName;
|
||||||
std::string label = "Player (" + std::to_string(st.id) + ") " + std::to_string((int)dist) + "m";
|
if (!st.nickname.empty() && st.nickname != "Player") {
|
||||||
|
displayName = st.nickname;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
displayName = "Player (" + std::to_string(st.id) + ")";
|
||||||
|
}
|
||||||
|
std::string label = displayName + " " + std::to_string((int)dist) + "m";
|
||||||
|
|
||||||
// TODO: nickname sync
|
textRenderer->drawText(label, uiX + 1.f, uiY + 1.f, scale, true, { 0.f, 0.f, 0.f, alpha });
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Space::pickTargetId() const
|
int Space::pickTargetId() const
|
||||||
@ -1288,6 +1293,10 @@ namespace ZL
|
|||||||
|
|
||||||
for (auto const& [id, remotePlayer] : latestRemotePlayers) {
|
for (auto const& [id, remotePlayer] : latestRemotePlayers) {
|
||||||
|
|
||||||
|
if (networkClient && id == networkClient->GetClientId()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!remotePlayer.canFetchClientStateAtTime(nowRoundedWithDelay))
|
if (!remotePlayer.canFetchClientStateAtTime(nowRoundedWithDelay))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@ -1296,7 +1305,6 @@ namespace ZL
|
|||||||
ClientState playerState = remotePlayer.fetchClientStateAtTime(nowRoundedWithDelay);
|
ClientState playerState = remotePlayer.fetchClientStateAtTime(nowRoundedWithDelay);
|
||||||
|
|
||||||
remotePlayerStates[id] = playerState;
|
remotePlayerStates[id] = playerState;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& p : projectiles) {
|
for (auto& p : projectiles) {
|
||||||
|
|||||||
@ -79,7 +79,6 @@ namespace ZL {
|
|||||||
try {
|
try {
|
||||||
int respawnedPlayerId = std::stoi(parts[1]);
|
int respawnedPlayerId = std::stoi(parts[1]);
|
||||||
pendingRespawns_.push_back(respawnedPlayerId);
|
pendingRespawns_.push_back(respawnedPlayerId);
|
||||||
remotePlayers.erase(respawnedPlayerId);
|
|
||||||
std::cout << "Client: Received RESPAWN_ACK for player " << respawnedPlayerId << std::endl;
|
std::cout << "Client: Received RESPAWN_ACK for player " << respawnedPlayerId << std::endl;
|
||||||
}
|
}
|
||||||
catch (...) {}
|
catch (...) {}
|
||||||
@ -202,6 +201,11 @@ namespace ZL {
|
|||||||
|
|
||||||
{
|
{
|
||||||
auto& rp = remotePlayers[remoteId];
|
auto& rp = remotePlayers[remoteId];
|
||||||
|
if (!rp.timedStates.empty()) {
|
||||||
|
const ClientState& last = rp.timedStates.back();
|
||||||
|
remoteState.nickname = last.nickname;
|
||||||
|
remoteState.shipType = last.shipType;
|
||||||
|
}
|
||||||
rp.add_state(remoteState);
|
rp.add_state(remoteState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +222,7 @@ namespace ZL {
|
|||||||
if (playerParts.size() < 15) return; // ID + 14 полей ClientState
|
if (playerParts.size() < 15) return; // ID + 14 полей ClientState
|
||||||
|
|
||||||
int rId = std::stoi(playerParts[0]);
|
int rId = std::stoi(playerParts[0]);
|
||||||
if (rId == clientId) return; // Свое состояние игрок знает лучше всех (Client Side Prediction)
|
if (rId == clientId) return; // Свое состояние игрок знает лучше всех, (Client Side Prediction)
|
||||||
|
|
||||||
ClientState remoteState;
|
ClientState remoteState;
|
||||||
remoteState.id = rId;
|
remoteState.id = rId;
|
||||||
@ -230,6 +234,40 @@ namespace ZL {
|
|||||||
remotePlayers[rId].add_state(remoteState);
|
remotePlayers[rId].add_state(remoteState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (msg.rfind("PLAYERINFO:", 0) == 0) {
|
||||||
|
if (parts.size() >= 4) {
|
||||||
|
try {
|
||||||
|
int pid = std::stoi(parts[1]);
|
||||||
|
if (pid == clientId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string nick = parts[2];
|
||||||
|
int st = std::stoi(parts[3]);
|
||||||
|
|
||||||
|
auto it = remotePlayers.find(pid);
|
||||||
|
if (it != remotePlayers.end() && !it->second.timedStates.empty()) {
|
||||||
|
auto& states = it->second.timedStates;
|
||||||
|
states.back().nickname = nick;
|
||||||
|
states.back().shipType = st;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ClientState cs;
|
||||||
|
cs.id = pid;
|
||||||
|
cs.nickname = nick;
|
||||||
|
cs.shipType = st;
|
||||||
|
cs.lastUpdateServerTime = std::chrono::system_clock::now();
|
||||||
|
remotePlayers[pid].add_state(cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Client: PLAYERINFO received. id=" << pid << " nick=" << nick << " shipType=" << st << std::endl;
|
||||||
|
}
|
||||||
|
catch (...) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string WebSocketClientBase::SignMessage(const std::string& msg) {
|
std::string WebSocketClientBase::SignMessage(const std::string& msg) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user