Added battles in networking

This commit is contained in:
Vladislav Khorev committed 2026-11-07 14:27:22 +06:00
1 parent be8ee31f03
commit 40527f10ac
8 files changed
+302 -36

No files matched your search

+98 -7
View File
@@ -96,6 +96,27 @@ nlohmann::json targetJson(const Eigen::Vector3f& target)
return nlohmann::json::array({target.x(), target.y(), target.z()});
}
bool validCharacterAction(
const std::string& action, const std::string& targetId,
std::string& error)
{
if (action != "set_target" &&
action != "clear_attack_target" &&
action != "try_attack_combo") {
error = "unsupported character action";
return false;
}
if (action == "set_target" && targetId.empty()) {
error = "set_target requires a targetId";
return false;
}
if (action != "set_target" && !targetId.empty()) {
error = "targetId is only valid for set_target";
return false;
}
return true;
}
} // namespace
std::string makeInitialStateMessage(const InitialStateMessage& message)
@@ -159,6 +180,16 @@ std::uint64_t LockstepTimeline::scheduleCharacterEnabled(
return sequence;
}
std::uint64_t LockstepTimeline::scheduleCharacterAction(
const std::string& playerId, std::string action, std::string targetId)
{
const std::uint64_t sequence = nextCommandSequence_++;
pending_[currentTick_ + inputDelayTicks_].push_back(
ScheduledCharacterActionCommand{
sequence, playerId, std::move(action), std::move(targetId)});
return sequence;
}
TickMessage LockstepTimeline::advance()
{
TickMessage result;
@@ -191,6 +222,38 @@ bool parseDestinationInputMessage(
return readTarget(payload["target"], message.target, error);
}
std::string makeCharacterActionInputMessage(
const CharacterActionInputMessage& message)
{
return envelope("character_action", {
{"clientSequence", message.clientSequence},
{"action", message.action},
{"targetId", message.targetId}
});
}
bool parseCharacterActionInputMessage(
const std::string& text, CharacterActionInputMessage& message,
std::string& error)
{
nlohmann::json payload;
if (!parseEnvelope(text, "character_action", payload, error))
return false;
if (!readTick(payload, "clientSequence", message.clientSequence, error))
return false;
if (!payload.contains("action") || !payload["action"].is_string()) {
error = "action is required";
return false;
}
message.action = payload["action"].get<std::string>();
message.targetId = payload.value("targetId", std::string());
if (!payload.contains("targetId") || !payload["targetId"].is_string()) {
error = "targetId must be a string";
return false;
}
return validCharacterAction(message.action, message.targetId, error);
}
std::string makeTickMessage(const TickMessage& message)
{
nlohmann::json commands = nlohmann::json::array();
@@ -205,13 +268,23 @@ std::string makeTickMessage(const TickMessage& message)
{"target", targetJson(command.target)}
});
} else {
commands.push_back({
{"type", "character_enabled"},
{"commandSequence", command.commandSequence},
{"locationId", command.locationId},
{"characterId", command.characterId},
{"enabled", command.enabled}
});
if constexpr (std::is_same_v<T, ScheduledCharacterEnabledCommand>) {
commands.push_back({
{"type", "character_enabled"},
{"commandSequence", command.commandSequence},
{"locationId", command.locationId},
{"characterId", command.characterId},
{"enabled", command.enabled}
});
} else {
commands.push_back({
{"type", "character_action"},
{"commandSequence", command.commandSequence},
{"playerId", command.playerId},
{"action", command.action},
{"targetId", command.targetId}
});
}
}
}, scheduled);
}
@@ -274,6 +347,24 @@ bool parseTickMessage(
return false;
}
command = std::move(enabled);
} else if (type == "character_action") {
ScheduledCharacterActionCommand action;
action.commandSequence = previousSequence;
if (!value.contains("playerId") || !value["playerId"].is_string() ||
!value.contains("action") || !value["action"].is_string() ||
!value.contains("targetId") || !value["targetId"].is_string()) {
error = "invalid character action command";
return false;
}
action.playerId = value["playerId"].get<std::string>();
action.action = value["action"].get<std::string>();
action.targetId = value["targetId"].get<std::string>();
if (action.playerId.empty() ||
!validCharacterAction(action.action, action.targetId, error)) {
if (error.empty()) error = "invalid character action command";
return false;
}
command = std::move(action);
} else {
error = "unsupported scheduled command type";
return false;