Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed few multiplayer desync issues. #5578

Merged
merged 11 commits into from Jun 12, 2017
Merged

Conversation

ZehMatt
Copy link
Member

@ZehMatt ZehMatt commented Jun 10, 2017

Fixed peeps trying to watch ghost rides in multiplayer.
Fixed using the wrong tick number for commands, client was ahead one tick in reality.
Added some logging for scenario_rand when DEBUG_DESYNC is defined.

Fixed peeps trying to watch ghost rides in multiplayer.
Fixed using the wrong tick number for commands, client as ahead one tick in reality.
Added some logging scenario_rand when DEBUG_DESYNC is defined.
@ZehMatt ZehMatt changed the title Fixed ghost rides affecting grass. Fixed few multiplayer desync issues. Jun 10, 2017
@@ -181,7 +181,7 @@ extern "C"
else if (gClimateCurrentWeatherEffect == 2)
{
// Create new thunder and lightning
uint32 randomNumber = util_rand();
uint32 randomNumber = scenario_rand();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is thunder not completely client-side?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its still driven by a prng which is at least sync so every client should see the thunder at the same time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an option to disable thunders. This may cause a client UI layer not to call this function and it would desync this client, that's why it is client side.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More precisely: there is an option to disable lightning flashes. You'll still hear thunder.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to double check this, but the thunder and lightning effects should be purely client side and aesthetic.

Copy link
Member Author

@ZehMatt ZehMatt Jun 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After sleeping over it I just realized that, altho it should still use the same prng stream however not affect it so at least all clients will run the same effects.

@Margen67
Copy link
Contributor

Once this is merged https://github.com/OpenRCT2/OpenRCT2/wiki/Multiplayer-issues will have to be updated.

@janisozaur
Copy link
Member

@ZehM4tt thanks for this PR. While it looks like it indeed solves some desyncs, the map you provided for testing: aaa.sv6.txt still exhibits some.

It reproduces quite reliably for me under these conditions:

  • Arch Linux + GCC 7
  • No title sequence
  • server: ./openrct2 host aaa.sv6
  • client: ./openrct2 join 127.0.0.1
  • using rct1 theme
  • on client: spam the close/open button of the Autoskooter 1 ride.

if (!gInUpdateCode) {
log_warning("scenario_rand called from outside game update");
assert(false);
//assert(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ZehM4tt any particular reason this is commented out? I mentioned on gitter I hit this condition at times, but the PRNG looks fine regardless. Are there known good paths leading to this point?

Can you either provide justification and remove this line or leave the assert in?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its only active with DEBUG_DESYNC and it was triggering even tho its fine to be called at the given time. I would just leave it commented in case someone requires to stop there to investigate the stack or memory.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit nervous about this. I do not know enough about network to say why it got in, but an assertion is never put in for nothing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are false positives, its just annoying to have it there while investigating.

@@ -3659,7 +3659,8 @@ void map_update_tiles()
}

gGrassSceneryTileLoopPosition++;
gGrassSceneryTileLoopPosition &= 0xFFFF;
// Type is uint16, so why do we need this exactly?
//gGrassSceneryTileLoopPosition &= 0xFFFF;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed? Looks redundant, so perhaps should be part of another PR?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps leave ZehM4tt's changes intact and create an issue for it?

@@ -1124,7 +1131,7 @@ void Network::Server_Send_TICK()
// but debug version can check more often.
static sint32 checksum_counter = 0;
checksum_counter++;
if (checksum_counter >= 100) {
if (checksum_counter >= 5) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Back this out, such low value is only needed for testing

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ops

@@ -174,6 +174,12 @@ static void peep_update_ride_inspected(sint32 rideIndex);

bool loc_690FD0(rct_peep *peep, uint8 *rideToView, uint8 *rideSeatToView, rct_map_element *esi);

#ifdef DEBUG_DESYNC
#define peep_rand() scenario_rand_data(peep)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

peep may not be as useful as part of logging, as it's id: https://github.com/OpenRCT2/OpenRCT2/blob/develop/src/openrct2/peep/peep.h#L469

@Sweet-Tan
Copy link

Crash while on ed06a22
4a0b6f13-24a0-4d41-a80e-0992e4973316.zip

@janisozaur
Copy link
Member

@ZehM4tt it may not be related directly to your PR, as I don't recall any new places where it could crash, but perhaps I missed something. Can you please take a look at this dump?

@ZehMatt
Copy link
Member Author

ZehMatt commented Jun 11, 2017

Its a sound crash, where mixer is NULL.
Stack trace:

openrct2.dll!Mixer_Play_Music(int pathId=3, int loop=-1, int streaming=0) Line 150 C++
openrct2.dll!peep_update_crowd_noise(...) Line 6983 C
openrct2.dll!game_logic_update(...) Line 421 C
openrct2.dll!game_update(...) Line 318 C
devenv_2017-06-11_08-37-19

@janisozaur
Copy link
Member

@ZehM4tt can you please post the stack trace as text? Images are not searchable nor they add any value. It also looks like this is irrelevant to your PR and something that hasn't been reported yet, so can you please file a new issue with all the information there?

@ZehMatt
Copy link
Member Author

ZehMatt commented Jun 11, 2017

I'm not the one who found it to begin with and I have no idea how to trigger it, etc. The picture was merely some indication that it doesn't belong here.

Copy link
Member

@Gymnasiast Gymnasiast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a few line notes to address.

I'm not sure the debug stuff should be in this PR, but I'm not going to obstruct this if I'm the only one.

I do not know enough game_update() either to say anything about that, I'll leave that to IntelOrca, Janisozaur and Duncan.

@@ -11344,6 +11350,12 @@ static void peep_easter_egg_peep_interactions(rct_peep *peep)
*/
static bool peep_should_watch_ride(rct_map_element *mapElement) {
rct_ride *ride = get_ride(mapElement->properties.track.ride_index);

// In case of upcoming references we also have the check in here.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this comment a bit vague. It isn't clear what it's trying to prevent, nor does it say why (I know it's to prevents desyncs, but the comment should really say that).

@@ -11394,6 +11406,9 @@ static bool peep_find_ride_to_look_at(rct_peep *peep, uint8 edge, uint8 *rideToV

mapElement = surfaceElement;
do {
if (network_get_mode() != NETWORK_MODE_NONE) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put a comment explaining this is to prevent desyncs from interaction with ghost elements.

if (!gInUpdateCode) {
log_warning("scenario_rand called from outside game update");
assert(false);
//assert(false);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit nervous about this. I do not know enough about network to say why it got in, but an assertion is never put in for nothing.

@@ -3659,7 +3659,8 @@ void map_update_tiles()
}

gGrassSceneryTileLoopPosition++;
gGrassSceneryTileLoopPosition &= 0xFFFF;
// Type is uint16, so why do we need this exactly?
//gGrassSceneryTileLoopPosition &= 0xFFFF;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps leave ZehM4tt's changes intact and create an issue for it?

@@ -3719,6 +3720,9 @@ static void map_update_grass_length(sint32 x, sint32 y, rct_map_element *mapElem
mapElementAbove++;
if (map_element_get_type(mapElementAbove) == MAP_ELEMENT_TYPE_WALL)
continue;
// Grass should not be affected by ghost elements.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted.

@janisozaur
Copy link
Member

@Gymnasiast I addressed your comments. I'm not sure about the one that wants to have comment next to ghost checks, there are quite a few and having a comment next to each one would introduce a lot of clutter, so I'm not exactly for it.

@duncanspumpkin expressed concerns about passing the peep data to logging, but I concur. I think I could use such data and even if not, it's a good example of how to use the little debug features we have.

@janisozaur janisozaur added the network version Network version needs updating - double check before merging! label Jun 11, 2017
[ci skip]
@janisozaur
Copy link
Member

@Gymnasiast I addressed all your comment now.

@duncanspumpkin
Copy link
Contributor

My concern with the peep debug Rand was. does logging the Id/peep give any additional useful information? For debugging a desync it's rare that you would care about an individual sprite and if you did know which sprite caused the desync how would that help.

Copy link
Member

@Gymnasiast Gymnasiast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My notes are addressed. I'll leave the game_update() bits and related stuff to @janisozaur and @duncanspumpkin .

@ZehMatt
Copy link
Member Author

ZehMatt commented Jun 12, 2017

@duncanspumpkin It did help determine if the order is correct not necessarily the peep in question. If peep A comes before peep B on server then peep A must do all decision making on client before peep B as well. Since all allocation seems to be deterministic on my Windows 10 machine with debug heap this can be quite helpful, but you are right about the data its self, its quite useless. However this is only enabled if DEBUG_DESYNC is defined, its probably best to use their object id for logging.

@janisozaur janisozaur merged commit 60bf508 into OpenRCT2:develop Jun 12, 2017
ZehMatt added a commit to ZehMatt/OpenRCT2 that referenced this pull request Jul 14, 2017
This addresses some of the desync causes:

* `vehicle_create_car` was using `scenario_rand` when it shouldn't have
* ghost elements affected grass growth
* ghost elements affecting peep logic[1]

It also adds some desync debug facilities, enabled at compile time.

It also reverts part of change introduced in
OpenRCT2#5185,
namely reorder of desync check vs call to `ProcessGameCommandQueue();`

[1] It is not ideal to have this check in multiple locations, it is prone
to human error. We already have `map_remove_provisional_elements`,
but it is possible it does not work as well as it should. This needs
further investigation.
@ZehMatt ZehMatt deleted the issue-5058 branch July 19, 2017 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
network version Network version needs updating - double check before merging!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants