Set up basic deterministic lockstep

This commit is contained in:
Vladislav Khorev committed 2026-11-05 23:02:53 +06:00
1 parent 28c6e83eda
commit 23fef6f349
26 files changed
+1172 -239

No files matched your search

+24 -6
View File
@@ -1,4 +1,5 @@
#include "game_server/InternalGameServer.h"
#include "game_server/NetworkProtocol.h"
#if defined(NETWORK)
#include "game_server/WebsocketGameServer.h"
#endif
@@ -15,6 +16,7 @@
#include <memory>
#include <string>
#include <thread>
#include <vector>
namespace {
@@ -44,7 +46,7 @@ std::int64_t parsePositiveNumber(const char* value, const char* option)
int main(int argc, char** argv)
{
std::int64_t tickMs = 500;
std::int64_t tickMs = FRG::kSimulationTickMs;
std::int64_t maxTicks = (std::numeric_limits<std::int64_t>::max)();
bool sleepBetweenTicks = true;
std::string campaignId;
@@ -89,14 +91,18 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}
//Temporary override:
campaignId = "battle_zone_multiplayer";
locationId = "uni_exterior";
if (tickMs != FRG::kSimulationTickMs) {
std::cerr << "Network lockstep requires --tick-ms "
<< FRG::kSimulationTickMs << '\n';
return EXIT_FAILURE;
}
std::signal(SIGINT, requestStop);
std::signal(SIGTERM, requestStop);
FRG::InternalGameServer server;
std::vector<std::string> playerSlots;
std::string compatibilityFingerprint = "lockstep-v2";
if (!campaignId.empty()) {
try {
FRG::CampaignRegistry::instance().loadFromJson(campaignsPath);
@@ -138,6 +144,17 @@ int main(int argc, char** argv)
}
}
server.activateLocation(selectedLocation);
playerSlots = campaign->networkPlayerSlots;
for (const std::string& slot : playerSlots) {
if (server.snapshot()->players.count(slot) == 0)
throw std::runtime_error(
"Multiplayer slot '" + slot +
"' is missing from the initial state");
}
compatibilityFingerprint =
campaign->networkCompatibility.empty()
? "lockstep-v2:" + campaignId
: campaign->networkCompatibility;
if (!campaign->tutorial) {
server.submit(FRG::SetTutorialStepCommand{
FRG::TutorialStep::Completed});
@@ -158,7 +175,8 @@ int main(int argc, char** argv)
std::unique_ptr<FRG::WebsocketGameServer> websocketServer;
try {
websocketServer = std::make_unique<FRG::WebsocketGameServer>(
server, listenAddress, static_cast<std::uint16_t>(listenPort));
server, playerSlots, compatibilityFingerprint,
listenAddress, static_cast<std::uint16_t>(listenPort));
} catch (const std::exception& error) {
std::cerr << "WebSocket listener setup failed: "
<< error.what() << '\n';
@@ -174,7 +192,7 @@ int main(int argc, char** argv)
tick < maxTicks && !stopRequested.load(); ++tick) {
nextTick += tickDuration;
#if defined(NETWORK)
websocketServer->update(tickMs);
websocketServer->update();
#else
server.update(tickMs);
#endif