Set up basic deterministic lockstep
This commit is contained in:
1 parent
28c6e83eda
commit
23fef6f349
26 files changed
+1172
-239
No files matched your search
@@ -0,0 +1,90 @@
|
||||
#include "game_server/InternalGameServer.h"
|
||||
#include "game_server/WebsocketGameClient.h"
|
||||
#include "game_server/WebsocketGameServer.h"
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace {
|
||||
|
||||
void require(bool condition, const char* message)
|
||||
{
|
||||
if (condition) return;
|
||||
std::cerr << "WebsocketLockstepTests: " << message << '\n';
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
template <class Predicate>
|
||||
bool waitFor(Predicate predicate)
|
||||
{
|
||||
const auto deadline =
|
||||
std::chrono::steady_clock::now() + std::chrono::seconds(3);
|
||||
while (std::chrono::steady_clock::now() < deadline) {
|
||||
if (predicate()) return true;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
FRG::CampaignConfig campaign;
|
||||
campaign.id = "test_lockstep";
|
||||
|
||||
FRG::InternalGameServer authoritative;
|
||||
authoritative.startCampaign(campaign, {}, true, false);
|
||||
FRG::WebsocketGameServer server(
|
||||
authoritative, {"player"}, "lockstep-v2:test_lockstep",
|
||||
"127.0.0.1", 0);
|
||||
auto client = std::make_unique<FRG::WebsocketGameClient>(
|
||||
"127.0.0.1", std::to_string(server.port()), "/");
|
||||
|
||||
require(
|
||||
waitFor([&]() { return client->connected(); }),
|
||||
"client did not connect");
|
||||
require(
|
||||
waitFor([&]() {
|
||||
client->update(0);
|
||||
return client->initialized();
|
||||
}),
|
||||
"client did not receive initial state");
|
||||
require(client->localPlayerId() == "player", "wrong player slot assigned");
|
||||
|
||||
FRG::WebsocketGameClient overflow(
|
||||
"127.0.0.1", std::to_string(server.port()), "/");
|
||||
require(
|
||||
waitFor([&]() {
|
||||
overflow.update(0);
|
||||
return overflow.rejected();
|
||||
}),
|
||||
"connection beyond configured slots was not rejected");
|
||||
|
||||
client->submit(FRG::SetCharacterDestinationCommand{
|
||||
{}, "spoofed", Eigen::Vector3f(1.234f, 0.f, 2.345f), "ignored"});
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
||||
server.update();
|
||||
server.update();
|
||||
require(
|
||||
waitFor([&]() {
|
||||
client->update(0);
|
||||
return client->snapshot()->revision > 1;
|
||||
}),
|
||||
"client did not consume finalized lockstep ticks");
|
||||
|
||||
client.reset();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
FRG::WebsocketGameClient replacement(
|
||||
"127.0.0.1", std::to_string(server.port()), "/");
|
||||
require(
|
||||
waitFor([&]() {
|
||||
replacement.update(0);
|
||||
return replacement.initialized();
|
||||
}),
|
||||
"disconnected player slot was not reusable");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in new issue
Block a user