diff --git a/include/server/IServerSocket.h b/include/server/IServerSocket.h index c3f7af4..79ce209 100644 --- a/include/server/IServerSocket.h +++ b/include/server/IServerSocket.h @@ -14,6 +14,7 @@ class IServerSocket { utils::Signal OnReceive; void Send(PlayerID a_PlayerId, const protocol::PacketBase& a_Packet); + void Broadcast(const protocol::PacketBase& a_Packet); IServerSocket() {} virtual ~IServerSocket() {} diff --git a/include/server/IServerState.h b/include/server/IServerState.h index 6b9f9ad..e79a5bf 100644 --- a/include/server/IServerState.h +++ b/include/server/IServerState.h @@ -9,10 +9,6 @@ namespace server { class Server; class IServerState : private utils::SlotGuard { - protected: - void SendPacket(PlayerID a_Id, const protocol::PacketBase& a_Packet); - void SetNewState(const std::shared_ptr& a_NewState); - public: virtual void HandlePacket(PlayerID a_Id, const protocol::PacketBase& a_Packet) = 0; virtual void Update(float a_Delta) = 0; @@ -22,6 +18,12 @@ class IServerState : private utils::SlotGuard { IServerState(); virtual ~IServerState(); + protected: + void SendPacket(PlayerID a_Id, const protocol::PacketBase& a_Packet); + void BroadcastPacket(const protocol::PacketBase& a_Packet); + void SetNewState(const std::shared_ptr& a_NewState); + virtual void Init() {} + private: Server* m_Server; diff --git a/include/server/PlayerIds.h b/include/server/PlayerIds.h index 6166a26..ca523ec 100644 --- a/include/server/PlayerIds.h +++ b/include/server/PlayerIds.h @@ -35,6 +35,14 @@ class PlayerIds { m_PeerToPlayer.erase(a_PeerId); m_PlayerToPeer.erase(playerId); } + + auto begin() { + return m_PeerToPlayer.begin(); + } + + auto end() { + return m_PeerToPlayer.end(); + } }; } // namespace server diff --git a/include/server/Server.h b/include/server/Server.h index 77e79d6..83542c7 100644 --- a/include/server/Server.h +++ b/include/server/Server.h @@ -3,6 +3,7 @@ #include #include #include +#include namespace td { namespace server { @@ -11,19 +12,23 @@ class Server { private: std::shared_ptr m_Socket; std::shared_ptr m_State; + std::chrono::time_point m_LastTime; public: - Server(const std::shared_ptr& a_Socket) : m_Socket(a_Socket) {} + Server(const std::shared_ptr& a_Socket) : m_Socket(a_Socket), m_LastTime(std::chrono::system_clock::now()) {} - void Update(float a_Delta) { - m_State->Update(a_Delta); - } + void Update(); void UpdateState(const std::shared_ptr& a_State) { m_State = a_State; m_State->SetServer(this); } + private: + void Update(float a_Delta) { + m_State->Update(a_Delta); + } + friend class IServerState; }; diff --git a/include/server/socket/FakeSocket.h b/include/server/socket/FakeSocket.h index 20b4f05..cdb1893 100644 --- a/include/server/socket/FakeSocket.h +++ b/include/server/socket/FakeSocket.h @@ -12,6 +12,9 @@ class FakeSocket : public IServerSocket { utils::Signal OnSend; + void ConnectFakePeer(PeerID a_Peer); + void DisconnectFakePeer(PeerID a_Peer); + protected: virtual void SendPeer(PeerID a_Peer, const protocol::PacketBase& a_Packet) override; }; diff --git a/include/server/state/GameState.h b/include/server/state/GameState.h index 05b739b..83d8530 100644 --- a/include/server/state/GameState.h +++ b/include/server/state/GameState.h @@ -1,21 +1,33 @@ #pragma once #include +#include +#include namespace td { namespace server { -class GameState : public IServerState{ +class GameStateHandler; + +class GameState : public IServerState { private: - /* data */ + std::shared_ptr m_World; + sim::ServerSimulation m_Simulation; + float m_Time; + public: - GameState(/* args */) {} + GameState(const std::shared_ptr& a_World); ~GameState() {} 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) override; virtual void OnPlayerLeave(PlayerID a_Id) override; + + protected: + virtual void Init() override; + + friend class GameStateHandler; }; } // namespace server diff --git a/include/server/state/GameStateHandler.h b/include/server/state/GameStateHandler.h new file mode 100644 index 0000000..afc202f --- /dev/null +++ b/include/server/state/GameStateHandler.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace td { +namespace server { + +class GameState; + +class GameStateHandler : public protocol::PacketHandler { + private: + GameState& m_GameState; + PlayerID m_PlayerId; + + using protocol::PacketHandler::Handle; + + public: + GameStateHandler(GameState& a_GameState, PlayerID a_PlayerId); + + virtual void Handle(const protocol::packets::SpawnTroopPacket& a_Packet) override; + virtual void Handle(const protocol::packets::PlaceTowerPacket& a_Packet) override; +}; + +} // namespace server +} // namespace td diff --git a/include/server/state/LobbyState.h b/include/server/state/LobbyState.h index f0ac688..e427139 100644 --- a/include/server/state/LobbyState.h +++ b/include/server/state/LobbyState.h @@ -5,11 +5,12 @@ namespace td { namespace server { +// this class is temporary useless class LobbyState : public IServerState { private: - /* data */ + std::shared_ptr m_World; public: - LobbyState(/* args */) {} + LobbyState(const std::shared_ptr& a_World) : m_World(a_World) {} ~LobbyState() {} virtual void HandlePacket(PlayerID a_Id, const protocol::PacketBase& a_Packet) override; diff --git a/include/td/Maths.h b/include/td/Maths.h index 023ea6d..aff9373 100644 --- a/include/td/Maths.h +++ b/include/td/Maths.h @@ -1,6 +1,6 @@ #pragma once -#include +#include namespace td { @@ -183,6 +183,35 @@ T Lerp(T v0, T v1, T t) { } // namespace maths +template +sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec2& a_Vec) { + return a_Buffer << a_Vec.x << a_Vec.y; +} +template +sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, Vec2& a_Vec) { + return a_Buffer >> a_Vec.x >> a_Vec.y; +} + +template +sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec3& a_Vec) { + return a_Buffer << a_Vec.x << a_Vec.y << a_Vec.z; +} + +template +sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, Vec3& a_Vec) { + return a_Buffer >> a_Vec.x >> a_Vec.y >> a_Vec.z; +} + + +template +sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec4& a_Vec) { + return a_Buffer << a_Vec.x << a_Vec.y << a_Vec.z << a_Vec.w; +} + +template +sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, Vec4& a_Vec) { + return a_Buffer >> a_Vec.x >> a_Vec.y >> a_Vec.z >> a_Vec.w; +} } // namespace td diff --git a/include/td/Types.h b/include/td/Types.h index cafc172..b126919 100644 --- a/include/td/Types.h +++ b/include/td/Types.h @@ -12,6 +12,10 @@ namespace td { using FpFloat = fpm::fixed_16_16; +using StepTime = std::uint16_t; + +constexpr int STEP_TIME = 50; + enum class TeamColor : std::int8_t { None = -1, Blue, @@ -61,15 +65,11 @@ using TowerID = std::uint16_t; using PlayerID = std::uint8_t; using EntityID = std::uint16_t; -struct TowerCoords { - std::int16_t x; - std::int16_t y; -}; +using TowerCoords = Vec2; using EntityCoords = Vec2; using PeerID = std::uint16_t; -using StepsType = std::uint16_t; enum class Direction : std::uint8_t { PositiveX = 1 << 0, diff --git a/include/td/game/World.h b/include/td/game/World.h index d941932..9177cd6 100644 --- a/include/td/game/World.h +++ b/include/td/game/World.h @@ -1,25 +1,25 @@ #pragma once -#include #include #include +#include namespace td { namespace game { class World { protected: + // header TowerTileColorPalette m_TowerPlacePalette; Color m_WalkablePalette; std::vector m_DecorationPalette; Color m_Background; - - ChunkList m_Chunks; - SpawnColorPalette m_SpawnColorPalette; - TilePalette m_TilePalette; + //data + ChunkList m_Chunks; + std::shared_ptr m_CurrentState; std::shared_ptr m_NextState; @@ -28,6 +28,7 @@ class World { public: World(); + World(World&&) = default; bool LoadMap(const protocol::pdata::WorldHeader& worldHeader); bool LoadMap(const protocol::pdata::WorldData& worldData); @@ -130,8 +131,9 @@ class World { private: void TickMobs(std::uint64_t delta); void CleanDeadMobs(); - }; +using WorldPtr = std::shared_ptr; + } // namespace game } // namespace td \ No newline at end of file diff --git a/include/td/protocol/packet/PacketData.h b/include/td/protocol/packet/PacketData.h index 8bdcc39..4e3ac86 100644 --- a/include/td/protocol/packet/PacketData.h +++ b/include/td/protocol/packet/PacketData.h @@ -7,7 +7,11 @@ #include // Make it dynamic ? +#ifdef NDEBUG #define LOCKSTEP_BUFFER_SIZE 10 +#else +#define LOCKSTEP_BUFFER_SIZE 1 +#endif namespace td { namespace protocol { @@ -45,7 +49,7 @@ struct PlayerLeave { struct PredictCommand { CommandPtr m_Command; - std::uint16_t m_FrameNumber; + StepTime m_FrameNumber; }; /** Keep alive */ @@ -73,7 +77,7 @@ struct BeginGame { }; struct LockSteps { - std::uint16_t m_FirstFrameNumber; + StepTime m_FirstFrameNumber; std::array m_LockSteps; }; @@ -95,6 +99,7 @@ struct WorldData { game::ChunkList m_Chunks; }; +// TODO: spawn multiple troops at the same time struct SpawnTroop { sp::BitField m_Type; sp::BitField m_Level; diff --git a/include/td/protocol/packet/PacketSerialize.h b/include/td/protocol/packet/PacketSerialize.h index 29c2331..9fd0328 100644 --- a/include/td/protocol/packet/PacketSerialize.h +++ b/include/td/protocol/packet/PacketSerialize.h @@ -4,36 +4,7 @@ namespace td { -template -sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec2& a_Vec) { - return a_Buffer << a_Vec.x << a_Vec.y; -} -template -sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, Vec2& a_Vec) { - return a_Buffer >> a_Vec.x >> a_Vec.y; -} - -template -sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec3& a_Vec) { - return a_Buffer << a_Vec.x << a_Vec.y << a_Vec.z; -} - -template -sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, Vec3& a_Vec) { - return a_Buffer >> a_Vec.x >> a_Vec.y >> a_Vec.z; -} - - -template -sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec4& a_Vec) { - return a_Buffer << a_Vec.x << a_Vec.y << a_Vec.z << a_Vec.w; -} - -template -sp::DataBuffer& operator>>(sp::DataBuffer& a_Buffer, Vec4& a_Vec) { - return a_Buffer >> a_Vec.x >> a_Vec.y >> a_Vec.z >> a_Vec.w; -} namespace game { diff --git a/include/td/simulation/GameHistory.h b/include/td/simulation/GameHistory.h deleted file mode 100644 index 806286a..0000000 --- a/include/td/simulation/GameHistory.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace td { -namespace game { - -class GameHistory { - private: - using HistorySizeType = StepsType; - - std::vector> m_History; - - public: - GameHistory(); - - void SetLockStep(HistorySizeType a_Index, protocol::LockStep&& a_LockStep); - - const protocol::LockStep& GetLockStep(HistorySizeType a_Index) const; - - bool HasLockStep(HistorySizeType a_Index) const; - - void FromPacket(td::protocol::pdata::LockSteps&& a_Steps); - - td::protocol::packets::LockStepsPacket ToPacket(HistorySizeType a_StartIndex); -}; - -} // namespace game -} // namespace td diff --git a/include/td/simulation/ServerSimulation.h b/include/td/simulation/ServerSimulation.h index aaadbad..599041f 100644 --- a/include/td/simulation/ServerSimulation.h +++ b/include/td/simulation/ServerSimulation.h @@ -25,6 +25,8 @@ class ServerSimulation : public protocol::CommandHandler { protocol::packets::LockStepsPacket Update(); + protocol::packets::LockStepsPacket MakePacket(); + // no checks are done ! virtual void Handle(const protocol::commands::SpawnTroopCommand& a_SpawnTroop) override; diff --git a/src/main.cpp b/src/main.cpp index aa9f185..72ad7fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,9 +1,9 @@ #include -#include #include #include #include +#include #include #include #include @@ -17,7 +17,7 @@ #include #include -#include +#include class WorldApply : public td::protocol::PacketHandler { private: @@ -36,6 +36,24 @@ class WorldApply : public td::protocol::PacketHandler { } }; +class ClientHandler : public td::protocol::PacketHandler { + private: + td::sim::ClientSimulation& m_Simulation; + + using td::protocol::PacketHandler::Handle; + + public: + ClientHandler(td::sim::ClientSimulation& a_Simulation) : m_Simulation(a_Simulation) {} + + void Handle(const td::protocol::packets::LockStepsPacket& a_LockStep) { + m_Simulation.Handle(a_LockStep); + } + + void Handle(const td::protocol::packets::PredictCommandPacket& a_Predict) { + m_Simulation.Handle(a_Predict); + } +}; + void Save(const td::protocol::PacketBase& header, const td::protocol::PacketBase& data) { auto comp = std::make_shared(); @@ -48,7 +66,7 @@ void Save(const td::protocol::PacketBase& header, const td::protocol::PacketBase stream.WriteMessage(data, false); } -td::game::World GetWorld() { +td::game::WorldPtr GetWorld() { auto comp = std::make_shared(); std::ifstream fStream("test/tdmap.tdmap2"); @@ -59,8 +77,8 @@ td::game::World GetWorld() { auto header = stream.ReadMessage(td::protocol::PacketID::WorldHeader); auto data = stream.ReadMessage(td::protocol::PacketID::WorldData); - td::game::World w; - auto wa = std::make_shared(w); + auto w = std::make_shared(); + auto wa = std::make_shared(*w); td::protocol::PacketDispatcher d; d.RegisterHandler(wa); @@ -80,24 +98,12 @@ void FastForward(td::game::World& a_World, const td::sim::GameHistory& a_LockSte } } -td::sim::GameHistory GetCustomHistory() { - constexpr std::size_t MAX_COUNT = 20 * 60 * 40; - - td::sim::GameHistory gh(MAX_COUNT); - - auto spawn = td::protocol::CommandPtr( - std::make_shared(td::EntityType::Zombie, 0, td::Vec2fp{td::FpFloat(77), td::FpFloat(13)}, 0)); - gh[0].push_back(spawn); - - auto tower = td::protocol::CommandPtr( - std::make_shared(td::TowerType::Archer, 0, td::TowerCoords{77, 13})); - gh[0].push_back(tower); - - return gh; -} - int main(int argc, char** argv) { - td::game::World w = GetWorld(); + td::game::WorldPtr serverWorld = GetWorld(); + + // server + auto fakeSocket = std::make_shared(); + td::server::Server server(fakeSocket); // init GL context td::Display display(1920, 1080, "Tower-Defense 2"); @@ -106,42 +112,40 @@ int main(int argc, char** argv) { display.OnAspectRatioChange.Connect([&cam](float a_AspectRatio) { cam.UpdatePerspective(a_AspectRatio); }); - td::sim::GameHistory gh = GetCustomHistory(); + td::game::WorldPtr clientWorld = GetWorld(); td::render::RenderPipeline renderer; - renderer.AddRenderer(cam, w); - renderer.AddRenderer(cam, w); - renderer.AddRenderer(cam, w); + renderer.AddRenderer(cam, *clientWorld); + renderer.AddRenderer(cam, *clientWorld); + renderer.AddRenderer(cam, *clientWorld); cam.SetCamPos({77, 7, 13}); cam.UpdatePerspective(display.GetAspectRatio()); - td::sim::ClientSimulation simulation(w, 50); + td::sim::ClientSimulation simulation(*clientWorld, td::STEP_TIME); + ClientHandler clientHandler(simulation); - display.OnKeyDown.Connect([&simulation](SDL_Keycode key) { - static int counter = 0; + // temporary tests + display.OnKeyDown.Connect([&fakeSocket](SDL_Keycode key) { if (key == SDLK_A) { - auto spawn = td::protocol::CommandPtr( - std::make_shared(td::EntityType::Zombie, 0, td::Vec2fp{td::FpFloat(77), td::FpFloat(13)}, 0)); - std::array steps{}; - steps[0].push_back(spawn); - td::protocol::packets::LockStepsPacket packet{counter * LOCKSTEP_BUFFER_SIZE * 3, steps}; - simulation.Handle(packet); - counter++; + fakeSocket->OnReceive(0, td::protocol::packets::SpawnTroopPacket(td::EntityType::Zombie, 1)); + } else if (key == SDLK_Z) { + fakeSocket->OnReceive(0, td::protocol::packets::PlaceTowerPacket(td::TowerType::Archer, td::TowerCoords(77, 13))); } }); + fakeSocket->ConnectFakePeer(0); - // server - auto socket = std::make_shared(); - td::server::Server server(socket); - server.UpdateState(std::make_shared()); - server.Update(1.0f); - server.Update(1.0f); - socket->OnDisconnect(0); + // packets from the server to the client + fakeSocket->OnSend.Connect([&clientHandler](td::PeerID a_Peer, const td::protocol::PacketBase& a_Packet) { + a_Packet.Dispatch(clientHandler); + }); + + server.UpdateState(std::make_shared(serverWorld)); while (!display.IsCloseRequested()) { display.PollEvents(); + server.Update(); float lerp = simulation.Update(); renderer.Render(lerp); display.Update(); diff --git a/src/server/IServerSocket.cpp b/src/server/IServerSocket.cpp index ccf9cda..3deeb4d 100644 --- a/src/server/IServerSocket.cpp +++ b/src/server/IServerSocket.cpp @@ -21,5 +21,11 @@ void IServerSocket::Send(PlayerID a_PlayerId, const protocol::PacketBase& a_Pack SendPeer(m_Ids.GetPeerId(a_PlayerId), a_Packet); } +void IServerSocket::Broadcast(const protocol::PacketBase& a_Packet) { + for (auto [peerId, playerId] : m_Ids) { + SendPeer(peerId, a_Packet); + } +} + } // namespace server } // namespace td diff --git a/src/server/IServerState.cpp b/src/server/IServerState.cpp index cdd9f04..3f99642 100644 --- a/src/server/IServerState.cpp +++ b/src/server/IServerState.cpp @@ -10,6 +10,7 @@ void IServerState::SetServer(Server* a_Server) { Connect(m_Server->m_Socket->OnConnect, std::bind(&IServerState::OnPlayerJoin, this, std::placeholders::_1)); Connect(m_Server->m_Socket->OnDisconnect, std::bind(&IServerState::OnPlayerLeave, this, std::placeholders::_1)); Connect(m_Server->m_Socket->OnReceive, std::bind(&IServerState::HandlePacket, this, std::placeholders::_1, std::placeholders::_2)); + Init(); } IServerState::IServerState() : m_Server(nullptr) {} @@ -20,6 +21,10 @@ void IServerState::SendPacket(PlayerID a_Id, const protocol::PacketBase& a_Packe m_Server->m_Socket->Send(a_Id, a_Packet); } +void IServerState::BroadcastPacket(const protocol::PacketBase& a_Packet) { + m_Server->m_Socket->Broadcast(a_Packet); +} + void IServerState::SetNewState(const std::shared_ptr& a_NewState) { m_Server->UpdateState(a_NewState); } diff --git a/src/server/Server.cpp b/src/server/Server.cpp index b648900..453e3af 100644 --- a/src/server/Server.cpp +++ b/src/server/Server.cpp @@ -1 +1,14 @@ -#include \ No newline at end of file +#include + +namespace td { +namespace server { + +void Server::Update() { + auto timeElapsed = std::chrono::system_clock::now() - m_LastTime; + float timeSeconds = std::chrono::duration(timeElapsed).count(); + Update(timeSeconds); + m_LastTime = std::chrono::system_clock::now(); +} + +} // namespace server +} // namespace td diff --git a/src/server/socket/FakeSocket.cpp b/src/server/socket/FakeSocket.cpp index ebe3a5d..aa2da4d 100644 --- a/src/server/socket/FakeSocket.cpp +++ b/src/server/socket/FakeSocket.cpp @@ -7,5 +7,13 @@ void FakeSocket::SendPeer(PeerID a_Peer, const protocol::PacketBase& a_Packet) { OnSend(a_Peer, a_Packet); } +void FakeSocket::ConnectFakePeer(PeerID a_Peer) { + OnConnectPeer(a_Peer); +} + +void FakeSocket::DisconnectFakePeer(PeerID a_Peer) { + OnDisconnectPeer(a_Peer); +} + } // namespace server } // namespace td diff --git a/src/server/state/GameState.cpp b/src/server/state/GameState.cpp index 6a28183..8ea3ff4 100644 --- a/src/server/state/GameState.cpp +++ b/src/server/state/GameState.cpp @@ -1,25 +1,36 @@ #include +#include #include namespace td { namespace server { -void GameState::HandlePacket(PlayerID a_Id, const protocol::PacketBase& a_Packet) { +GameState::GameState(const std::shared_ptr& a_World) : m_World(a_World), m_Simulation(*m_World, STEP_TIME), m_Time(0) {} +void GameState::Init() { + std::cout << "Switched to Game state !\n"; + BroadcastPacket(m_Simulation.MakePacket()); +} + +void GameState::HandlePacket(PlayerID a_Id, const protocol::PacketBase& a_Packet) { + GameStateHandler handler(*this, a_Id); + a_Packet.Dispatch(handler); } void GameState::Update(float a_Delta) { - + static const float stepTimeSecond = static_cast(STEP_TIME) / 1000.0f; + m_Time += a_Delta; + if (m_Time > stepTimeSecond) { + m_Time = std::fmod(m_Time, stepTimeSecond); + auto lockStepPacket = m_Simulation.Update(); + BroadcastPacket(lockStepPacket); + } } -void GameState::OnPlayerJoin(PlayerID a_Id) { +void GameState::OnPlayerJoin(PlayerID a_Id) {} -} - -void GameState::OnPlayerLeave(PlayerID a_Id) { - std::cout << "Game leave !" << std::endl; -} +void GameState::OnPlayerLeave(PlayerID a_Id) {} } // namespace server } // namespace td diff --git a/src/server/state/GameStateHandler.cpp b/src/server/state/GameStateHandler.cpp new file mode 100644 index 0000000..3b0e9fc --- /dev/null +++ b/src/server/state/GameStateHandler.cpp @@ -0,0 +1,24 @@ +#include +#include + +namespace td { +namespace server { + +GameStateHandler::GameStateHandler(GameState& a_GameState, PlayerID a_PlayerId) : m_GameState(a_GameState), m_PlayerId(a_PlayerId) {} + +// TODO: redo this +void GameStateHandler::Handle(const protocol::packets::SpawnTroopPacket& a_Packet) { + static const EntityCoords DEFAULT_POS(td::FpFloat(77), td::FpFloat(13)); + + td::protocol::commands::SpawnTroopCommand spawn(*a_Packet->m_Type, *a_Packet->m_Level, DEFAULT_POS, m_PlayerId); + m_GameState.m_Simulation.Handle(spawn); +} + +// TODO: and this +void GameStateHandler::Handle(const protocol::packets::PlaceTowerPacket& a_Packet) { + td::protocol::commands::PlaceTowerCommand place(a_Packet->m_Type, m_PlayerId, a_Packet->m_Position); + m_GameState.m_Simulation.Handle(place); +} + +} // namespace server +} // namespace td diff --git a/src/server/state/LobbyState.cpp b/src/server/state/LobbyState.cpp index 7db94e4..e9a1b1c 100644 --- a/src/server/state/LobbyState.cpp +++ b/src/server/state/LobbyState.cpp @@ -11,7 +11,7 @@ void LobbyState::HandlePacket(PlayerID a_Id, const protocol::PacketBase& a_Packe } void LobbyState::Update(float a_Delta) { - SetNewState(std::make_shared()); + SetNewState(std::make_shared(m_World)); } void LobbyState::OnPlayerJoin(PlayerID a_Id) { @@ -19,7 +19,7 @@ void LobbyState::OnPlayerJoin(PlayerID a_Id) { } void LobbyState::OnPlayerLeave(PlayerID a_Id) { - std::cout << "Lobby leave !" << std::endl; + } } // namespace server diff --git a/src/td/simulation/ClientSimulation.cpp b/src/td/simulation/ClientSimulation.cpp index 7d43c36..e8045e6 100644 --- a/src/td/simulation/ClientSimulation.cpp +++ b/src/td/simulation/ClientSimulation.cpp @@ -2,6 +2,8 @@ #include +#include + namespace td { namespace sim { @@ -30,13 +32,13 @@ ClientSimulation::ClientSimulation(game::World& a_World, GameHistory&& a_History ClientSimulation::ClientSimulation(game::World& a_World, std::uint64_t a_StepTime) : m_StepTime(a_StepTime), m_World(a_World), - m_History(std::numeric_limits::max()), + m_History(std::numeric_limits::max()), m_CurrentTime(0), m_LastTime(GetTime()), m_CurrentStep(0), m_LastSnapshot(std::make_shared()), m_LastValidStep(0) { - Step(); + // Step(); } float ClientSimulation::Update() { @@ -45,7 +47,7 @@ float ClientSimulation::Update() { m_LastTime = GetTime(); if (m_CurrentTime > m_StepTime) { Step(); - m_CurrentTime -= m_StepTime; + m_CurrentTime %= m_StepTime; } return (float)m_CurrentTime / (float)m_StepTime; } @@ -69,25 +71,25 @@ void ClientSimulation::Handle(const protocol::packets::LockStepsPacket& a_LockSt FastReplay(); } -void ClientSimulation::Handle(const protocol::packets::PredictCommandPacket& a_Predict) { - -} +void ClientSimulation::Handle(const protocol::packets::PredictCommandPacket& a_Predict) {} void ClientSimulation::FastForward(std::size_t a_Count) { for (std::size_t i = 0; i < a_Count; i++) { Step(); } + std::cout << "Was behind " << a_Count << " ticks !\n"; } void ClientSimulation::FastReplay() { - if (m_LastValidStep >= m_CurrentStep) + if (m_LastValidStep + 1 >= m_CurrentStep) return; m_World.ResetSnapshots(m_LastSnapshot, m_LastSnapshot); + // TODO: cover holes const std::size_t stepCount = m_CurrentStep - m_LastValidStep; m_CurrentStep = m_LastValidStep; - + FastForward(stepCount); } diff --git a/src/td/simulation/GameHistory.cpp b/src/td/simulation/GameHistory.cpp deleted file mode 100644 index fd36519..0000000 --- a/src/td/simulation/GameHistory.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include - -namespace td { -namespace game { - -GameHistory::GameHistory() : m_History(std::numeric_limits::max()) {} - -void GameHistory::SetLockStep(HistorySizeType a_Index, protocol::LockStep&& a_LockStep) { - m_History[a_Index] = std::move(a_LockStep); -} - -const protocol::LockStep& GameHistory::GetLockStep(HistorySizeType a_Index) const { - return *m_History[a_Index]; -} - -bool GameHistory::HasLockStep(HistorySizeType a_Index) const { - return m_History[a_Index].has_value(); -} - -void GameHistory::FromPacket(protocol::pdata::LockSteps&& a_Steps) { - for (int i = 0; i < LOCKSTEP_BUFFER_SIZE; i++) { - protocol::LockStep& step = a_Steps.m_LockSteps[i]; - SetLockStep(i + a_Steps.m_FirstFrameNumber, std::move(step)); - } -} - -protocol::packets::LockStepsPacket GameHistory::ToPacket(HistorySizeType a_StartIndex) { - std::array steps; - for (int i = 0; i < LOCKSTEP_BUFFER_SIZE; i++) { - steps[i] = GetLockStep(a_StartIndex + i); - } - return {a_StartIndex, std::move(steps)}; -} - -} // namespace game -} // namespace td diff --git a/src/td/simulation/ServerSimulation.cpp b/src/td/simulation/ServerSimulation.cpp index 497d866..bde94dd 100644 --- a/src/td/simulation/ServerSimulation.cpp +++ b/src/td/simulation/ServerSimulation.cpp @@ -4,20 +4,24 @@ namespace td { namespace sim { ServerSimulation::ServerSimulation(game::World& a_World, std::uint64_t a_StepTime) : - m_World(a_World), m_StepTime(a_StepTime), m_CurrentTime(0) {} + m_World(a_World), m_StepTime(a_StepTime), m_CurrentTime(0), m_History(std::numeric_limits::max()) {} protocol::packets::LockStepsPacket ServerSimulation::Update() { std::lock_guard lock(m_Mutex); - + m_World.Tick(m_History[m_CurrentTime], FpFloat(m_StepTime) / FpFloat(1000)); m_CurrentTime++; + return MakePacket(); +} + +protocol::packets::LockStepsPacket ServerSimulation::MakePacket() { std::array nextSteps; std::copy(m_History.begin() + m_CurrentTime, m_History.begin() + m_CurrentTime + nextSteps.size(), nextSteps.begin()); return {m_CurrentTime, std::move(nextSteps)}; } -template +template void AddToCommandHistory(protocol::LockStep& a_LockStep, const T& a_Cmd) { a_LockStep.push_back({std::make_shared(a_Cmd)}); }