#include 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_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 void AddToCommandHistory(protocol::LockStep& a_LockStep, const T& a_Cmd) { a_LockStep.push_back({std::make_shared(a_Cmd)}); } void ServerSimulation::Handle(const protocol::commands::SpawnTroopCommand& a_SpawnTroop) { std::lock_guard lock(m_Mutex); AddToCommandHistory(m_History[m_CurrentTime + LOCKSTEP_BUFFER_SIZE], a_SpawnTroop); } void ServerSimulation::Handle(const protocol::commands::PlaceTowerCommand& a_PlaceTower) { std::lock_guard lock(m_Mutex); AddToCommandHistory(m_History[m_CurrentTime + LOCKSTEP_BUFFER_SIZE], a_PlaceTower); } protocol::packets::LockStepResponsePacket ServerSimulation::GetResponse( const protocol::packets::LockStepRequestPacket& a_Missing) const { std::map result; for (StepTime step : a_Missing->m_Missing) { result.emplace(step, m_History[step]); } 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