Skip to content

Conversation

@Arctice
Copy link
Contributor

@Arctice Arctice commented Dec 6, 2025

Fix for the 0.4 issue of disappearing scores (#178),
Alleviates an issue where scoring on a chart that was added to the database using the old parser that allowed #LNMODE would cause the score cache to write and read from different cache blocks

I've provided a more detailed explanation of the score cache behaviour and the mechanics of this fix in internal dev channel, reproduced here:

Despite looking a lot like a stale cache issue, it's kind of not.

  • each chart's SongData has a feature bit field describing, among other things, their long note type, where 0b1 is undefined, 0b1000 (8) is LN, 16 is CN, and 32 HCN
  • ScoreDataCache.java uses hasUndefinedLongNote on the SongData to determine which of the four caches to use for loading the visible scores - caches 0, 1 and 2 correspond to the different PLAYER (not chart) long note modes, while cache 3 (or so I believe) contains scores for both charts that: either don't have any long notes at all, or have a #LNMODE setting (this suggests that scores of #LNMODE charts previously always displayed in the song wheel regardless of currently set player LN mode? I'm not completely sure)
  • when loading scores, a #LNMODE 1 chart has feature = 8 (LN). This is probably the case when the song DB was built on 0.3 or earlier; and so, when loading scores from db, ScoreDataCache puts it in cache index 3.
  • after playing the song, (presumably due to re-parsing the chart for play and using the new parsing code that always sets LNMODE to 0) ScoreDataCache.update sees a feature of 1, an "undefined" long note type, and stuffs it in the cache for current play LN mode (at cache index 0)
  • again, returning from song select, the folders' song bars update their song data from the song db, getting 8 for a #LNMODE 1 chart, and show the score from cache 3, which isn't the one that was just played.

for clarity:
feature = 0 has no long notes, and goes in cache 3.
feature = 1 is a FEATURE_UNDEFINED that corresponds to a missing #LNMODE and goes in cache config.getLnmode(), typically 0.
feature = 8 is a FEATURE_LONGNOTE that corresponds to #LNMODE 1 and goes in cache 3. We see this when loading chart data from a disk DB built in 0.3 or earlier. There are corresponding variants for other LNMODE settings.

Incidentally, the new score could still be seen by opening the context menu, because that song bar was created using a different song data object - one that was reloaded by the render function in MusicSelector - which, since it needs to generate the note graph, would re-parse the chart and load the score with the right feature.

original cache organization:

int cacheindex = song.hasUndefinedLongNote() ? lnmode : 3;
scorecache[cacheindex].put(song.getSha256(), score);

cacheindex=0,1,2 contains scores of LN charts that don't have #LNMODE so they can have 3 different scores per chart. cacheindex=3 contains scores with #LNMODE 1-3 charts, and scores of charts with no LNs at all, which can only have one score. this makes optimal use of space but interacts with a feature we disabled in a way that makes it update improperly.
possible fixes I considered:

int cacheindex = lnmode;

this would stuff all scores into the current LN mode (I'm operating under the assumption that one day we might provide some in-game way to switch again), which probably works, but loses the clever optimization where all non-LN charts go into a separate cache and save space when switching modes.

int cacheindex = 0;

just one cache that rebuilds when switching modes. tempting, but I'm not sure I can make sure it always update correctly.

int cacheindex = song.hasAnyLongNote() ? lnmode : 3;

I think this should make it so that songs that formerly had #LNMODE definitions go into the selected mode's scores instead of the special 4th cache.

This last fix is the one provided by this PR.

alleviates an issue where scoring on a chart that was added to the
database using the old parser that allowed #LNMODE would cause
the score cache to write and read from different cache blocks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants