Files
dota_factory/src/lib/sim/CommandManager.cpp

93 lines
2.4 KiB
C++

#include "CommandManager.h"
#include <utility>
#include "Command.h"
#include "ReplayRecorder.h"
#include "Simulation.h"
#include "Tick.h"
namespace
{
// Periodic RNG checksum cadence (see docs/replay_design.md "Cadence").
constexpr Tick kChecksumIntervalTicks = 30;
} // namespace
CommandManager::CommandManager(Simulation& simulation)
: m_simulation(simulation)
{
}
CommandManager::~CommandManager() = default;
void CommandManager::enqueue(std::shared_ptr<const Command> command)
{
if (m_replayMode)
{
return; // playback is driven by the recorded stream; ignore live input
}
if (command)
{
m_queue.push_back(std::move(command));
}
}
void CommandManager::drain()
{
// Apply in FIFO order. A queued ResetCommand reinitializes the simulation in
// place; the reference stays valid and any commands after it apply to the
// fresh state.
for (const std::shared_ptr<const Command>& command : m_queue)
{
if (command->kind == CommandKind::Reset)
{
m_simulation.apply(*command);
if (m_recorder)
{
// Restart is a file boundary: a fresh file with the new seed.
m_recorder->startNewRun(m_simulation.getSeed(),
m_simulation.getRngFingerprint());
}
}
else
{
// Commands drain before the tick batch, so currentTick is the count of
// completed ticks the command is pinned to.
const Tick tick = m_simulation.getCurrentTick();
m_simulation.apply(*command);
if (m_recorder)
{
m_recorder->recordCommand(tick, *command, m_simulation.getRngFingerprint());
}
}
}
m_queue.clear();
}
bool CommandManager::hasPending() const
{
return !m_queue.empty();
}
void CommandManager::setRecorder(std::unique_ptr<ReplayRecorder> recorder)
{
m_recorder = std::move(recorder);
if (m_recorder)
{
m_recorder->startNewRun(m_simulation.getSeed(), m_simulation.getRngFingerprint());
}
}
void CommandManager::setReplayMode(bool replayMode)
{
m_replayMode = replayMode;
}
void CommandManager::recordTickCheckpoint()
{
if (m_recorder && (m_simulation.getCurrentTick() % kChecksumIntervalTicks == 0))
{
m_recorder->recordChecksum(m_simulation.getCurrentTick(), m_simulation.getRngFingerprint());
}
}