1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-16 11:33:03 +01:00

Gamestate snapshots (#8819)

* Add initial interface.

* Implement move operator in MemoryStream

* Add pod array serialisation traits.

* Add push_back with move semantics to CircularBuffer

* Initial implementation of GameStateSnapshots

* Add GameStateSnapshots to Context.

* Add mp_desync console command.

* Compare sprite data and fill change list.

* Minor changes.

* Proof of concept.

* Calculate offset instead of using offsetof

* Implement game state difference detection

* Update mp_desync console command.

* Fix identification of sprite remove/add.

* Fix crash when only one peep in park when using mp_desync

* Output state differences into user directory desync folder.

* Add desync debugging as an option.

* Add information to network status when a desync report was created.

* Cast to proper type for %llu.

* Update xcode project

* Add more information to the diffed data.

* Remove client-only relevant fields.

* Cleanup.

* Add better name output for misc sprites

* Add srand0 and tick information to the output

* Bump up network version

* Cleanup

* Set desync_debugging to false as default

* Apply suggestions
This commit is contained in:
ζeh Matt
2019-05-11 21:31:34 +02:00
committed by GitHub
parent 1f6c7c9942
commit c8f822ea70
22 changed files with 1152 additions and 19 deletions

View File

@@ -1549,6 +1549,66 @@ static int32_t cc_replay_normalise(InteractiveConsole& console, const arguments_
return 0;
}
static int32_t cc_mp_desync(InteractiveConsole& console, const arguments_t& argv)
{
int32_t desyncType = 0;
if (argv.size() >= 1)
{
desyncType = atoi(argv[0].c_str());
}
std::vector<rct_sprite*> peeps;
std::vector<rct_sprite*> vehicles;
for (int i = 0; i < MAX_SPRITES; i++)
{
rct_sprite* sprite = get_sprite(i);
if (sprite->generic.sprite_identifier == SPRITE_IDENTIFIER_NULL)
continue;
if (sprite->generic.sprite_identifier == SPRITE_IDENTIFIER_PEEP)
peeps.push_back(sprite);
else if (sprite->generic.sprite_identifier == SPRITE_IDENTIFIER_VEHICLE)
vehicles.push_back(sprite);
}
switch (desyncType)
{
case 0: // Peep t-shirts.
{
if (peeps.empty())
{
console.WriteFormatLine("No peeps");
}
else
{
rct_sprite* sprite = peeps[0];
if (peeps.size() > 1)
sprite = peeps[util_rand() % peeps.size() - 1];
sprite->peep.tshirt_colour = util_rand() & 0xFF;
invalidate_sprite_0(sprite);
}
break;
}
case 1: // Remove random peep.
{
if (peeps.empty())
{
console.WriteFormatLine("No peep removed");
}
else
{
rct_sprite* sprite = peeps[0];
if (peeps.size() > 1)
sprite = peeps[util_rand() % peeps.size() - 1];
sprite->AsPeep()->Remove();
}
break;
}
}
return 0;
}
#pragma warning(push)
#pragma warning(disable : 4702) // unreachable code
static int32_t cc_abort([[maybe_unused]] InteractiveConsole& console, [[maybe_unused]] const arguments_t& argv)
@@ -1670,6 +1730,7 @@ static constexpr const console_command console_command_table[] = {
{ "replay_start", cc_replay_start, "Starts a replay", "replay_start <name>"},
{ "replay_stop", cc_replay_stop, "Stops the replay", "replay_stop"},
{ "replay_normalise", cc_replay_normalise, "Normalises the replay to remove all gaps", "replay_normalise <input file> <output file>"},
{ "mp_desync", cc_mp_desync, "Forces a multiplayer desync", "cc_mp_desync [desync_type, 0 = Random t-shirt color on random peep, 1 = Remove random peep ]"},
};
// clang-format on