#pragma once #include #include #include namespace td { namespace sim { using GameHistory = std::vector; using GameBuffer = std::vector>; // TODO: OnEnd signal class ClientSimulation : public protocol::PacketHandler { private: std::uint64_t m_StepTime; game::World& m_World; GameBuffer m_History; float m_CurrentTime; StepTime m_CurrentStep; std::shared_ptr m_LastSnapshot; StepTime m_LastValidStep; static const protocol::LockStep EMPTY_LOCKSTEP; using protocol::PacketHandler::Handle; public: utils::Signal&> OnMissingLockSteps; /** * \brief Replay constructor * \param a_StepTime in ms */ ClientSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime); /** * \brief Live update constructor (continuous game updates) * \param a_StepTime in ms */ ClientSimulation(game::World& a_World, std::uint64_t a_StepTime); /** * \return the progress [0-1] between two steps */ float Update(float a_Delta); virtual void Handle(const protocol::packets::LockStepsPacket& a_LockSteps) override; virtual void Handle(const protocol::packets::LockStepResponsePacket& a_LockSteps) override; private: /** * \returns false if the empty lockstep was used */ bool Step(); /** * \brief Ticks a_Count times */ std::size_t FastForward(std::size_t a_Count); /** * \brief Tries to recompute simulation if needed (for example in late command receival) */ void FastReplay(); }; } // namespace sim } // namespace td