Skip to content

Commit

Permalink
Process future ticks
Browse files Browse the repository at this point in the history
  • Loading branch information
nerudaj committed May 18, 2024
1 parent 74fb965 commit bc727f2
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 13 deletions.
2 changes: 2 additions & 0 deletions src/lib-app/include/app/AppStateIngame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ class [[nodiscard]] AppStateIngame final : public dgm::AppState
std::vector<mem::Rc<ControllerInterface>> inputs;
Scene scene;
RollbackManager<FrameState, 10> stateManager;
std::unordered_map<size_t, std::unordered_map<PlayerIdxType, InputSchema>>
futureInputs; // indexed by tick
mem::Box<GameLoop> gameLoop;
DemoFileHandler demoFileHandler;
mem::Box<dgm::Camera> camera;
Expand Down
39 changes: 29 additions & 10 deletions src/lib-app/src/app/AppStateIngame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,20 @@ void AppStateIngame::handleNetworkUpdate(const ServerUpdateData& update)

for (auto&& inputData : update.inputs)
{
stateManager.get(inputData.tick).inputs.at(inputData.clientId) =
inputData.input;
if (stateManager.isTickTooOld(inputData.tick))
{
throw std::runtime_error(
"Got outdated input, game desynced, exiting");
}
else if (stateManager.isTickTooNew(inputData.tick))
{
futureInputs[inputData.tick][inputData.clientId] = inputData.input;
}
else
{
stateManager.get(inputData.tick).inputs.at(inputData.clientId) =
inputData.input;
}
}
}

Expand All @@ -168,17 +180,22 @@ AppStateIngame::FrameState AppStateIngame::snapshotInputsIntoNewFrameState()
})
| std::ranges::to<decltype(FrameState::inputs)>() };

if (futureInputs.contains(scene.tick))
{
for (auto&& [playerIdx, input] : futureInputs[scene.tick])
{
state.inputs.at(playerIdx) = input;
}
futureInputs.erase(scene.tick);
}

if (!hasFocus)
{
state.inputs[client->getMyIndex()] = InputSchema {};
}

client->sendCurrentFrameInputs(lastTick, state.inputs);

// The following lines disables local input and drives everything throught
// the network
state.inputs[client->getMyIndex()] = InputSchema {};

// TODO: rework demos
/*if (settings->cmdSettings.playDemo)
{
Expand All @@ -190,10 +207,12 @@ AppStateIngame::FrameState AppStateIngame::snapshotInputsIntoNewFrameState()
}
state.inputs[0] = nlohmann::json::parse(line);
}
else
{
demoFileHandler.writeLine(nlohmann::json(state.inputs[0]).dump());
}*/
else*/
demoFileHandler.writeLine(nlohmann::json(client->getMyIndex()).dump());

// The following lines disables local input and drives everything throught
// the network
state.inputs[client->getMyIndex()] = InputSchema {};

return state;
}
Expand Down
15 changes: 12 additions & 3 deletions src/lib-game/include/utils/RollbackManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class [[nodiscard]] RollbackManager final
using BufferIndexType = BufferType::BufferIndexType;

public:
// insert until tick
void insert(dgm::UniversalReference<T> auto&& item, size_t tick)
{
assert(buffer.isEmpty() || tick > endIterator.tick);
Expand All @@ -29,7 +30,7 @@ class [[nodiscard]] RollbackManager final
[[nodiscard]] constexpr std::expected<BufferIndexType, ErrorMessage>
getIndexForTick(size_t tick) noexcept
{
if (endIterator.tick < tick || (endIterator.tick - tick) >= Capacity)
if (isTickTooNew(tick) || isTickTooOld(tick))
return std::unexpected(std::format(
"Requested index is not in buffer, endIterator.tick: {}, tick: "
"{}, Capacity: {}",
Expand All @@ -40,8 +41,6 @@ class [[nodiscard]] RollbackManager final
return endIterator.bufferIdx - (endIterator.tick - tick);
}

// TODO: forEachItemSinceTickXYZ

template<
size_t HowMuchToUnroll = Capacity,
class = std::enable_if<HowMuchToUnroll <= Capacity>>
Expand Down Expand Up @@ -76,6 +75,16 @@ class [[nodiscard]] RollbackManager final
return buffer.getSize() == 1u;
}

[[nodiscard]] constexpr bool isTickTooOld(size_t tick) const noexcept
{
return endIterator.tick > tick && (endIterator.tick - tick) >= Capacity;
}

[[nodiscard]] constexpr bool isTickTooNew(size_t tick) const noexcept
{
return buffer.isEmpty() || tick > endIterator.tick;
}

private:
[[nodiscard]] constexpr auto&& last(this auto&& self) noexcept
{
Expand Down

0 comments on commit bc727f2

Please sign in to comment.