From a39dbdbefc08b061d92761b030b570ca5a905584 Mon Sep 17 00:00:00 2001 From: ck <21735205+cyperdark@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:52:18 +0300 Subject: [PATCH] fix: Fix incorrect realtime pp from previous update --- .../tosu/src/entities/GamePlayData/index.ts | 101 ++++++++++++------ 1 file changed, 69 insertions(+), 32 deletions(-) diff --git a/packages/tosu/src/entities/GamePlayData/index.ts b/packages/tosu/src/entities/GamePlayData/index.ts index e3fd1bab..28dd153d 100644 --- a/packages/tosu/src/entities/GamePlayData/index.ts +++ b/packages/tosu/src/entities/GamePlayData/index.ts @@ -24,7 +24,8 @@ export class GamePlayData extends AbstractEntity { isDefaultState: boolean = true; isKeyOverlayDefaultState: boolean = true; - PerformanceAttributes?: rosu.PerformanceAttributes | rosu.Beatmap; + PerformanceAttributes: rosu.PerformanceAttributes; + GradualPerformance: rosu.GradualPerformance | null; Retries: number; PlayerName: string; @@ -58,6 +59,7 @@ export class GamePlayData extends AbstractEntity { private cachedkeys: string = ''; previousState: string = ''; + previousPassedObjects = 0; constructor(osuInstance: OsuInstance) { super(osuInstance); @@ -112,6 +114,9 @@ export class GamePlayData extends AbstractEntity { }; this.isReplayUiHidden = false; + this.previousPassedObjects = 0; + this.GradualPerformance = null; + // below is gata that shouldn't be reseted on retry if (isRetry === true) { return; @@ -548,6 +553,7 @@ export class GamePlayData extends AbstractEntity { } private updateStarsAndPerformance() { + const t1 = performance.now(); if (!config.calculatePP) { wLogger.debug( 'GD(updateStarsAndPerformance) pp calculation disabled' @@ -577,52 +583,83 @@ export class GamePlayData extends AbstractEntity { return; } - const scoreParams = { - passedObjects: calculatePassedObjects( - this.Mode, - this.Hit300, - this.Hit100, - this.Hit50, - this.HitMiss, - this.HitKatu, - this.HitGeki - ), - combo: this.MaxCombo, - mods: this.Mods, - misses: this.HitMiss, - n50: this.Hit50, - n100: this.Hit100, - n300: this.Hit300 - }; - const currentState = `${menuData.MD5}:${menuData.MenuGameMode}:${this.Mods}:${menuData.MP3Length}`; - const isUpdate = this.previousState !== currentState; - if (isUpdate) { - this.previousState = currentState; + + // update precalculated attributes + if ( + isUpdate || + !this.GradualPerformance || + !this.PerformanceAttributes + ) { + if (this.GradualPerformance) this.GradualPerformance.free(); if (this.PerformanceAttributes) this.PerformanceAttributes.free(); - const calculate = new rosu.Performance(scoreParams).calculate( + const difficulty = new rosu.Difficulty({ mods: this.Mods }); + this.GradualPerformance = new rosu.GradualPerformance( + difficulty, currentBeatmap ); - this.PerformanceAttributes = calculate; + + this.PerformanceAttributes = new rosu.Performance({ + mods: this.Mods + }).calculate(currentBeatmap); + + this.previousState = currentState; } - const curPerformance = new rosu.Performance(scoreParams).calculate( - this.PerformanceAttributes! + if (!this.GradualPerformance && !this.PerformanceAttributes) return; + + const passedObjects = calculatePassedObjects( + this.Mode, + this.Hit300, + this.Hit100, + this.Hit50, + this.HitMiss, + this.HitKatu, + this.HitGeki ); + + const offset = passedObjects - this.previousPassedObjects; + if (offset <= 0) return; + + const scoreParams: rosu.ScoreState = { + maxCombo: this.MaxCombo, + misses: this.HitMiss, + n50: this.Hit50, + n100: this.Hit100, + n300: this.Hit300, + nKatu: this.HitKatu, + nGeki: this.HitGeki + }; + + const curPerformance = this.GradualPerformance.nth( + scoreParams, + offset - 1 + )!; + const fcPerformance = new rosu.Performance({ mods: this.Mods, misses: 0, accuracy: this.Accuracy - }).calculate(this.PerformanceAttributes!); + }).calculate(this.PerformanceAttributes); + const t2 = performance.now(); + + if (curPerformance) { + beatmapPpData.updateCurrentAttributes( + curPerformance.difficulty.stars, + curPerformance.pp + ); + } + + if (fcPerformance) { + beatmapPpData.updateFcPP(fcPerformance.pp); + } - this.PerformanceAttributes = curPerformance; + this.previousPassedObjects = passedObjects; - beatmapPpData.updateCurrentAttributes( - curPerformance.difficulty.stars, - curPerformance.pp + wLogger.debug( + `GD(updateStarsAndPerformance) [${(t2 - t1).toFixed(2)}ms] elapsed time` ); - beatmapPpData.updateFcPP(fcPerformance.pp); } }