struct InputBatch
{
std::map<PlayerId, InputData> inputMap;
bool addInputData (PlayerId id, const InputData& input)
{
if (inputMap.find(id) == inputMap.end())
{
inputMap[id] = input;
return true;
}
return false;
}
};
struct InputQueue
{
std::deque<InputBatch> queue;
void addInput(const InputPacket& inputPacket)
{
if (queue.empty())
queue.emplace_back();
if (!queue.back().addInputData(inputPacket.playerId, inputPacket.inputData))
{
queue.emplace_back();
queue.back().addInputData(inputPacket.playerId, inputPacket.inputData);
}
}
bool isEmpty()
{
return queue.empty();
}
InputBatch pop()
{
auto result = queue.front();
queue.pop_front();
return result;
}
};
// ...
void Host::handleInput()
{
// The host keeps polling input from a separate thread where it receives the inputs from each client...?
for (InputPacket& inputPacket: pollInputFromClients())
{
m_inputQueue.addInput(inputPacket);
}
}
void Host::updatePhysics (sf::Time& accumulator)
{
bool updated = false;
while (accumulator >= m_physics.FRAME_DURATION)
{
if (!m_inputQueue.isEmpty())
{
auto batch = m_inputQueue.pop();
for (auto& pair: batch.inputMap)
{
PlayerId playerId = pair.first;
InputData& inputData = pair.second;
m_players[inputId].handleInput(inputData);
}
}
m_physics.step();
accumulator -= m_physics.FRAME_DURATION;
updated = true;
}
if (updated)
m_physics.update(m_graphics);
}
void Host::tick (sf::Time& accumulator) {
handleInput();
updatePhysics(accumulator);
updateGraphics(accumulator);
}