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

+40 -2
View File
@@ -60,12 +60,38 @@ int main()
parsedInput.target.isApprox(Eigen::Vector3f(1.23f, 0.f, -5.68f)),
"destination input was not normalized");
FRG::CharacterActionInputMessage actionInput{
8, "set_target", "hostile_npc"};
FRG::CharacterActionInputMessage parsedActionInput;
require(
FRG::parseCharacterActionInputMessage(
FRG::makeCharacterActionInputMessage(actionInput),
parsedActionInput, error),
"character action input did not round trip");
require(
parsedActionInput.clientSequence == 8 &&
parsedActionInput.action == "set_target" &&
parsedActionInput.targetId == "hostile_npc",
"character action input fields did not round trip");
require(
!FRG::parseCharacterActionInputMessage(
R"({"protocolVersion":2,"type":"character_action","payload":{"clientSequence":1,"action":"unknown","targetId":""}})",
parsedActionInput, error),
"unknown character action was accepted");
require(
!FRG::parseCharacterActionInputMessage(
R"({"protocolVersion":2,"type":"character_action","payload":{"clientSequence":1,"action":"set_target","targetId":""}})",
parsedActionInput, error),
"empty attack target was accepted");
FRG::TickMessage tick;
tick.tickId = 43;
tick.commands.push_back(FRG::ScheduledDestinationCommand{
1, "player", parsedInput.target});
tick.commands.push_back(FRG::ScheduledCharacterEnabledCommand{
2, "uni_exterior", "player2", true});
tick.commands.push_back(FRG::ScheduledCharacterActionCommand{
3, "player", "set_target", "hostile_npc"});
tick.stateHash = "0123456789abcdef";
FRG::TickMessage parsedTick;
require(
@@ -73,11 +99,15 @@ int main()
FRG::makeTickMessage(tick), parsedTick, error),
"tick message did not round trip");
require(
parsedTick.tickId == 43 && parsedTick.commands.size() == 2 &&
parsedTick.tickId == 43 && parsedTick.commands.size() == 3 &&
std::holds_alternative<FRG::ScheduledCharacterEnabledCommand>(
parsedTick.commands[1]) &&
std::get<FRG::ScheduledCharacterEnabledCommand>(
parsedTick.commands[1]).enabled,
parsedTick.commands[1]).enabled &&
std::holds_alternative<FRG::ScheduledCharacterActionCommand>(
parsedTick.commands[2]) &&
std::get<FRG::ScheduledCharacterActionCommand>(
parsedTick.commands[2]).targetId == "hostile_npc",
"tick contents did not round trip");
require(
@@ -134,12 +164,20 @@ int main()
"scheduled commands were not finalized in stable order");
timeline.scheduleCharacterEnabled("uni_exterior", "player2", true);
timeline.scheduleCharacterAction("player", "clear_attack_target");
const FRG::TickMessage presenceTick = timeline.advance();
require(
presenceTick.commands.size() == 1 &&
std::holds_alternative<FRG::ScheduledCharacterEnabledCommand>(
presenceTick.commands[0]),
"character enabled command was not scheduled for the next tick");
const FRG::TickMessage actionTick =
timeline.advance();
require(
actionTick.commands.size() == 1 &&
std::holds_alternative<FRG::ScheduledCharacterActionCommand>(
actionTick.commands[0]),
"character action was not scheduled with input delay");
return EXIT_SUCCESS;
}
+49
View File
@@ -104,6 +104,55 @@ int main()
}),
"client did not consume finalized lockstep ticks");
client->submit(FRG::SetCharacterTargetCommand{
"stale_location", "spoofed_character", "hostile_npc"});
std::this_thread::sleep_for(std::chrono::milliseconds(20));
server.update();
server.update();
require(
waitFor([&]() {
client->update(0);
secondClient->update(0);
return client->snapshot()->players.at("player").state.attackTargetId ==
"hostile_npc" &&
secondClient->snapshot()->players.at("player").state.attackTargetId ==
"hostile_npc" &&
authoritative.snapshot()->players.at("player").state.attackTargetId ==
"hostile_npc";
}),
"target command was not delayed and rebroadcast");
client->submit(FRG::ClearCharacterAttackTargetCommand{
"stale_location", "spoofed_character"});
std::this_thread::sleep_for(std::chrono::milliseconds(20));
server.update();
server.update();
require(
waitFor([&]() {
client->update(0);
secondClient->update(0);
return client->snapshot()->players.at("player").state.attackTargetId.empty() &&
secondClient->snapshot()->players.at("player").state.attackTargetId.empty() &&
authoritative.snapshot()->players.at("player").state.attackTargetId.empty();
}),
"clear attack target command was not delayed and rebroadcast");
client->submit(FRG::TryCharacterAttackComboCommand{
"stale_location", "spoofed_character"});
std::this_thread::sleep_for(std::chrono::milliseconds(20));
server.update();
server.update();
require(
waitFor([&]() {
client->update(0);
secondClient->update(0);
return client->snapshot()->revision ==
secondClient->snapshot()->revision &&
client->snapshot()->revision ==
authoritative.snapshot()->revision;
}),
"attack combo command was not rebroadcast in lockstep");
secondClient.reset();
std::this_thread::sleep_for(std::chrono::milliseconds(50));
server.update();