player connect-disconnect

This commit is contained in:
Vladislav Khorev committed 2026-11-06 22:07:47 +06:00
1 parent 3f68a8ba07
commit 2e6b93f3ac
16 files changed
+305 -62

No files matched your search

+77 -16
View File
@@ -4,6 +4,7 @@
#include <iomanip>
#include <limits>
#include <sstream>
#include <type_traits>
namespace FRG {
@@ -143,7 +144,18 @@ std::uint64_t LockstepTimeline::schedule(
{
const std::uint64_t sequence = nextCommandSequence_++;
pending_[currentTick_ + inputDelayTicks_].push_back(
{sequence, playerId, target});
ScheduledDestinationCommand{sequence, playerId, target});
return sequence;
}
std::uint64_t LockstepTimeline::scheduleCharacterEnabled(
const std::string& locationId, const std::string& characterId,
bool enabled)
{
const std::uint64_t sequence = nextCommandSequence_++;
pending_[currentTick_ + 1].push_back(
ScheduledCharacterEnabledCommand{
sequence, locationId, characterId, enabled});
return sequence;
}
@@ -182,12 +194,26 @@ bool parseDestinationInputMessage(
std::string makeTickMessage(const TickMessage& message)
{
nlohmann::json commands = nlohmann::json::array();
for (const ScheduledDestinationCommand& command : message.commands) {
commands.push_back({
{"commandSequence", command.commandSequence},
{"playerId", command.playerId},
{"target", targetJson(command.target)}
});
for (const ScheduledCommand& scheduled : message.commands) {
std::visit([&commands](const auto& command) {
using T = std::decay_t<decltype(command)>;
if constexpr (std::is_same_v<T, ScheduledDestinationCommand>) {
commands.push_back({
{"type", "destination"},
{"commandSequence", command.commandSequence},
{"playerId", command.playerId},
{"target", targetJson(command.target)}
});
} else {
commands.push_back({
{"type", "character_enabled"},
{"commandSequence", command.commandSequence},
{"locationId", command.locationId},
{"characterId", command.characterId},
{"enabled", command.enabled}
});
}
}, scheduled);
}
return envelope("tick", {
{"tickId", message.tickId},
@@ -209,22 +235,57 @@ bool parseTickMessage(
message.commands.clear();
std::uint64_t previousSequence = 0;
for (const nlohmann::json& value : payload["commands"]) {
ScheduledDestinationCommand command;
if (!value.is_object() ||
!readTick(value, "commandSequence", command.commandSequence, error) ||
!value.contains("playerId") || !value["playerId"].is_string() ||
!value.contains("target") ||
!readTarget(value["target"], command.target, error)) {
!readTick(value, "commandSequence", previousSequence, error)) {
if (error.empty()) error = "invalid scheduled command";
return false;
}
command.playerId = value["playerId"].get<std::string>();
if (command.playerId.empty() || command.commandSequence == 0 ||
command.commandSequence <= previousSequence) {
const std::string type = value.value("type", "destination");
ScheduledCommand command;
if (type == "destination") {
ScheduledDestinationCommand destination;
destination.commandSequence = previousSequence;
if (!value.contains("playerId") || !value["playerId"].is_string() ||
!value.contains("target") ||
!readTarget(value["target"], destination.target, error)) {
if (error.empty()) error = "invalid destination command";
return false;
}
destination.playerId = value["playerId"].get<std::string>();
if (destination.playerId.empty()) {
error = "destination command playerId must not be empty";
return false;
}
command = std::move(destination);
} else if (type == "character_enabled") {
ScheduledCharacterEnabledCommand enabled;
enabled.commandSequence = previousSequence;
if (!value.contains("locationId") || !value["locationId"].is_string() ||
!value.contains("characterId") || !value["characterId"].is_string() ||
!value.contains("enabled") || !value["enabled"].is_boolean()) {
error = "invalid character enabled command";
return false;
}
enabled.locationId = value["locationId"].get<std::string>();
enabled.characterId = value["characterId"].get<std::string>();
enabled.enabled = value["enabled"].get<bool>();
if (enabled.locationId.empty() || enabled.characterId.empty()) {
error = "character enabled command IDs must not be empty";
return false;
}
command = std::move(enabled);
} else {
error = "unsupported scheduled command type";
return false;
}
if (previousSequence == 0 ||
(!message.commands.empty() &&
previousSequence <= std::visit(
[](const auto& item) { return item.commandSequence; },
message.commands.back()))) {
error = "commands must have unique increasing sequences";
return false;
}
previousSequence = command.commandSequence;
message.commands.push_back(std::move(command));
}
message.stateHash = payload.value("stateHash", std::string());