ppy / osu

rhythm is just a *click* away!
https://osu.ppy.sh
MIT License
15.3k stars 2.27k forks source link

Importing Failed Replay from Stable does not do same as Lazer #20857

Open TRRESTGHGYTCFTGBCXSZD opened 2 years ago

TRRESTGHGYTCFTGBCXSZD commented 2 years ago

Type

Game behaviour

Bug description

failed replay on stable version exported and imported into lazer but for some reason, in stable version it fails but lazer version does not and does not give f rank

Screenshots or videos

image upper one is failed replay on stable version exported and imported into lazer (does show d) lower one is in game score importer (does show f) HAEAHAEA - de tesu - de tesu [fruits] (2022-05-14) CatchTheBeat-1.zip https://osu.ppy.sh/beatmapsets/1753657#fruits/3588777

Version

2022.1008.2-lazer

Logs

database.log legacy-ipc.log network.log performance.log runtime.log updater.log

Haspamelodica commented 1 year ago

This seems to happen every time a failed replay is imported into lazer, not just when importing a replay from stable. Steps to reproduce on a "fresh" lazer install:

  1. Download any map
  2. Play it, fail, save replay
  3. Export replay to file
  4. Delete replay from lazer
  5. Import replay again. Rank shows as D instead of F.

Demonstration:

https://user-images.githubusercontent.com/46954095/227949912-a194fe27-8aae-4072-b30d-c402463615c0.mp4

Resulting logs and client.realm: logs_and_client_realm.zip Replay file: Guest playing Kenji Ninuma - DISCO_PRINCE (peppy) [Normal] (2023-03-27_15-14).zip

Haspamelodica commented 1 year ago

(This is the first time I'm looking at lazer's source code (or any C# code for that matter), so be patient with me if I'm stating the obvious or if I use weird / incorrect terminology.)

After a bit of debugging, the problem seems to lie in PopulateAccuracy from class LegacyScoreDecoder. This method considers the amount of misses, 50s, etc. to compute a rank between SS and D, but does not consider health during play, which would be needed to determine if a given replay failed or not. However, information about health isn't stored in the replay file, and can only be reconstructed by simulating the entire replay AFAIK. Digging further reveals that during normal gameplay, the class HealthProcessor (including its subclasses) is responsible for tracking health, together with judgement-related classes like JudgementResult and Judgement.

One problem with simulating the entire replay is that it will take time. Importing many replays is slow enough as it is.

Am I correct in these deductions, especially the fact that we would need to simulate the entire replay to find out if it failed or not? Did I miss something?

peppy commented 1 year ago

In stable, replays are "allowed" to fail when all replay frames are exhausted and they haven't reached the end of the beatmap. Until that point, replays will never fail (to cover cases where replay playback is not accurate, as was historically the case).

If we want failed replays to have a correct grade, something will either need to change in stable or as part of the import process in lazer. I'm not sure if this is worth it, depends on how many users depend on this functionality.

But either way, we probably need similar logic to stable to allow gameplay to fail if there are no frames left and the beatmap has not finished.

t1meshift commented 8 months ago

Faced the same problem described in the issue and made a little research.

Could we use "life bar graph" string in osr file? I made a bunch of failed replays from various game versions, and there is always a pair <time>|0 at the end of their life bar graph. I'm not sure about corner cases like passing a map with almost empty health bar, though.