From 5b6254c690859168c36898b0f12d851748ba4e38 Mon Sep 17 00:00:00 2001 From: Persson-dev Date: Fri, 22 Aug 2025 12:24:58 +0200 Subject: [PATCH] send map when arriving late --- include/client/state/GameState.h | 2 +- include/client/state/LobbyState.h | 1 + include/server/state/GameState.h | 2 ++ include/td/protocol/packet/PacketData.h | 2 -- include/td/simulation/ClientSimulation.h | 2 +- include/td/simulation/ServerSimulation.h | 4 +++- src/client/state/GameState.cpp | 4 ++-- src/client/state/LobbyState.cpp | 5 ++++- src/server/state/GameState.cpp | 15 ++++++++++++++- src/td/display/state/DebugWorldState.cpp | 9 ++++----- src/td/simulation/ClientSimulation.cpp | 12 ++++++++++-- src/td/simulation/ServerSimulation.cpp | 10 ++++++++++ 12 files changed, 52 insertions(+), 16 deletions(-) diff --git a/include/client/state/GameState.h b/include/client/state/GameState.h index 8e4acde..9467e97 100644 --- a/include/client/state/GameState.h +++ b/include/client/state/GameState.h @@ -14,7 +14,7 @@ class GameState : public ClientState { float m_CurrentLerp; public: - GameState(Client& a_Client, const game::WorldPtr& a_World, std::uint64_t a_StepTime); + GameState(Client& a_Client, const game::WorldPtr& a_World, std::uint64_t a_StepTime, const std::vector a_FirstSteps); ~GameState() {} virtual void Update(float a_Delta) override; diff --git a/include/client/state/LobbyState.h b/include/client/state/LobbyState.h index 5b4de28..3dc0840 100644 --- a/include/client/state/LobbyState.h +++ b/include/client/state/LobbyState.h @@ -18,6 +18,7 @@ class LobbyState : public ClientState { virtual void Handle(const protocol::packets::WorldHeaderPacket& a_Packet) override; virtual void Handle(const protocol::packets::WorldDataPacket& a_Packet) override; + virtual void Handle(const protocol::packets::BeginGamePacket& a_Packet) override; }; } // namespace client diff --git a/include/server/state/GameState.h b/include/server/state/GameState.h index 1b70ad2..17008fb 100644 --- a/include/server/state/GameState.h +++ b/include/server/state/GameState.h @@ -22,6 +22,8 @@ class GameState : public ServerState { virtual void HandlePacket(PlayerID a_Id, const protocol::PacketBase& a_Packet) override; virtual void Update(float a_Delta) override; + virtual void OnPlayerJoin(PlayerID a_Id, const td::PlayerInfo& a_Info) override; + friend class GameStateHandler; }; diff --git a/include/td/protocol/packet/PacketData.h b/include/td/protocol/packet/PacketData.h index 49f2e07..0c3edf5 100644 --- a/include/td/protocol/packet/PacketData.h +++ b/include/td/protocol/packet/PacketData.h @@ -67,8 +67,6 @@ struct ChatMessage { std::string m_Text; }; -// TODO: handle players joining in the first second - struct BeginGame { std::vector m_BlueTeam; std::vector m_RedTeam; diff --git a/include/td/simulation/ClientSimulation.h b/include/td/simulation/ClientSimulation.h index 7a24f29..2e3dd0c 100644 --- a/include/td/simulation/ClientSimulation.h +++ b/include/td/simulation/ClientSimulation.h @@ -39,7 +39,7 @@ class ClientSimulation : public protocol::PacketHandler { * \brief Live update constructor (continuous game updates) * \param a_StepTime in ms */ - ClientSimulation(std::shared_ptr a_World, std::uint64_t a_StepTime); + ClientSimulation(std::shared_ptr a_World, std::uint64_t a_StepTime, const std::vector& a_FirstSteps); /** * \return the progress [0-1] between two steps diff --git a/include/td/simulation/ServerSimulation.h b/include/td/simulation/ServerSimulation.h index 61af852..4f8051a 100644 --- a/include/td/simulation/ServerSimulation.h +++ b/include/td/simulation/ServerSimulation.h @@ -16,7 +16,7 @@ class ServerSimulation : public protocol::CommandHandler { game::World& m_World; std::uint64_t m_StepTime; std::uint64_t m_CurrentTime; - std::vector m_History; + std::vector m_History; using protocol::CommandHandler::Handle; @@ -27,6 +27,8 @@ class ServerSimulation : public protocol::CommandHandler { protocol::packets::LockStepsPacket MakePacket(); + std::vector GetFirstLocksteps(); + // no checks are done ! virtual void Handle(const protocol::commands::SpawnTroopCommand& a_SpawnTroop) override; diff --git a/src/client/state/GameState.cpp b/src/client/state/GameState.cpp index 975d6c5..e6da5dd 100644 --- a/src/client/state/GameState.cpp +++ b/src/client/state/GameState.cpp @@ -3,8 +3,8 @@ namespace td { namespace client { -GameState::GameState(Client& a_Client, const std::shared_ptr& a_World, std::uint64_t a_StepTime) : - ClientState(a_Client), m_World(a_World), m_Simulation(a_World, a_StepTime) { +GameState::GameState(Client& a_Client, const std::shared_ptr& a_World, std::uint64_t a_StepTime, const std::vector a_FirstSteps) : + ClientState(a_Client), m_World(a_World), m_Simulation(a_World, a_StepTime, a_FirstSteps) { m_Simulation.OnMissingLockSteps.Connect([this](const std::vector& a_MissingSteps) { SendPacket(protocol::packets::LockStepRequestPacket(a_MissingSteps)); }); diff --git a/src/client/state/LobbyState.cpp b/src/client/state/LobbyState.cpp index a67c3de..8d9afc3 100644 --- a/src/client/state/LobbyState.cpp +++ b/src/client/state/LobbyState.cpp @@ -15,7 +15,10 @@ void LobbyState::Handle(const protocol::packets::WorldHeaderPacket& a_Packet) { void LobbyState::Handle(const protocol::packets::WorldDataPacket& a_Packet) { m_World->LoadMap(*a_Packet); - ChangeState(m_World, STEP_TIME); +} + +void LobbyState::Handle(const protocol::packets::BeginGamePacket& a_Packet) { + ChangeState(m_World, STEP_TIME, a_Packet->m_FirstLocksteps); } void LobbyState::Update(float a_Delta) {} diff --git a/src/server/state/GameState.cpp b/src/server/state/GameState.cpp index 09cea6e..d46aba0 100644 --- a/src/server/state/GameState.cpp +++ b/src/server/state/GameState.cpp @@ -7,10 +7,12 @@ namespace td { namespace server { -GameState::GameState(Server& a_Server, const std::shared_ptr& a_World) : ServerState(a_Server), m_World(a_World), m_Simulation(*m_World, STEP_TIME), m_Time(0) { +GameState::GameState(Server& a_Server, const std::shared_ptr& a_World) : + ServerState(a_Server), m_World(a_World), m_Simulation(*m_World, STEP_TIME), m_Time(0) { std::cout << "[Server] Switched to Game state !\n"; BroadcastPacket(a_World->GetPacketHeader()); BroadcastPacket(a_World->GetPacketData()); + BroadcastPacket(protocol::packets::BeginGamePacket()); BroadcastPacket(m_Simulation.MakePacket()); } @@ -30,5 +32,16 @@ void GameState::Update(float a_Delta) { } } +void GameState::OnPlayerJoin(PlayerID a_Id, const td::PlayerInfo& a_Info) { + SendPacket(a_Id, m_World->GetPacketHeader()); + SendPacket(a_Id, m_World->GetPacketData()); + + // TODO: real teams + std::vector team; + std::vector locksteps = m_Simulation.GetFirstLocksteps(); + + BroadcastPacket(protocol::packets::BeginGamePacket(team, team, locksteps)); +} + } // namespace server } // namespace td diff --git a/src/td/display/state/DebugWorldState.cpp b/src/td/display/state/DebugWorldState.cpp index d39e710..0bd7ede 100644 --- a/src/td/display/state/DebugWorldState.cpp +++ b/src/td/display/state/DebugWorldState.cpp @@ -47,12 +47,11 @@ DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) { }); m_Client->ChangeState("Player0"); - std::cout << "Switched to login!\n"; - // // client2 - // auto clientFakeSocket2 = client::FakeSocket::Connect(serverFakeSocket); - // m_Client2 = std::make_unique(clientFakeSocket2, "Player1"); - // m_Client2->ChangeState("Player1"); + // client2 + auto clientFakeSocket2 = client::FakeSocket::Connect(serverFakeSocket); + m_Client2 = std::make_unique(clientFakeSocket2, "Player1"); + m_Client2->ChangeState("Player1"); // camera m_Camera.SetCamPos({77, 7, 13}); diff --git a/src/td/simulation/ClientSimulation.cpp b/src/td/simulation/ClientSimulation.cpp index c90c999..dfb69c6 100644 --- a/src/td/simulation/ClientSimulation.cpp +++ b/src/td/simulation/ClientSimulation.cpp @@ -30,14 +30,22 @@ ClientSimulation::ClientSimulation(std::shared_ptr a_World, GameHis Step(); } -ClientSimulation::ClientSimulation(std::shared_ptr a_World, std::uint64_t a_StepTime) : +ClientSimulation::ClientSimulation( + std::shared_ptr a_World, std::uint64_t a_StepTime, const std::vector& a_FirstSteps) : m_StepTime(a_StepTime), m_World(a_World), m_History(std::numeric_limits::max()), m_CurrentTime(0), m_CurrentStep(0), m_LastSnapshot(std::make_shared()), - m_LastValidStep(0) {} + m_LastValidStep(0) { + if (!a_FirstSteps.empty()) { + for (std::size_t i = 0; i < a_FirstSteps.size(); i++) { + m_History[i] = a_FirstSteps[i]; + } + FastForward(a_FirstSteps.size()); + } +} float ClientSimulation::Update(float a_Delta) { // TODO: handle freezes (m_CurrentTime > 2 * m_StepTime) diff --git a/src/td/simulation/ServerSimulation.cpp b/src/td/simulation/ServerSimulation.cpp index 311dff8..903b1a3 100644 --- a/src/td/simulation/ServerSimulation.cpp +++ b/src/td/simulation/ServerSimulation.cpp @@ -47,6 +47,16 @@ protocol::packets::LockStepResponsePacket ServerSimulation::GetResponse( return {result}; } +std::vector ServerSimulation::GetFirstLocksteps() { + std::vector result; + if (m_CurrentTime <= LOCKSTEP_BUFFER_SIZE) + return result; + + result.reserve(m_CurrentTime); + result.insert(result.begin(), m_History.begin(), m_History.begin() + m_CurrentTime); + return result; +} + } // namespace sim } // namespace td