Skip to content

Commit

Permalink
Fix for 1.36.0
Browse files Browse the repository at this point in the history
  • Loading branch information
qe201020335 committed Apr 25, 2024
1 parent 718733b commit 6e5debb
Show file tree
Hide file tree
Showing 14 changed files with 114 additions and 59 deletions.
4 changes: 2 additions & 2 deletions SongPlayHistory/Model/LevelMapKey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ internal LevelMapKey(string levelId, string characteristicName, BeatmapDifficult
Difficulty = difficulty;
}

public LevelMapKey(IDifficultyBeatmap beatmap)
: this(beatmap.level.levelID, beatmap.parentDifficultyBeatmapSet.beatmapCharacteristic.serializedName, beatmap.difficulty)
public LevelMapKey(BeatmapKey beatmap)
: this(beatmap.levelId, beatmap.beatmapCharacteristic.serializedName, beatmap.difficulty)
{
}

Expand Down
6 changes: 3 additions & 3 deletions SongPlayHistory/Patches/DiTailsVotePatch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ private static bool Prepare()
}

[HarmonyPrefix]
public static void Prefix(bool upvote, IDifficultyBeatmap? ____activeBeatmap)
public static void Prefix(bool upvote, BeatmapLevel? ____activeBeatmap) //TODO: update when DiTails Update
{
if (____activeBeatmap == null) return;
var vote = upvote ? VoteType.Upvote : VoteType.Downvote;
Plugin.Log.Debug($"DiTails voted {vote} to {____activeBeatmap.level.levelID}");
InMenuVoteTrackingHelper.Instance?.Vote(____activeBeatmap.level, vote);
Plugin.Log.Debug($"DiTails voted {vote} to {____activeBeatmap.levelID}");
InMenuVoteTrackingHelper.Instance?.Vote(____activeBeatmap, vote);
}
}
}
2 changes: 1 addition & 1 deletion SongPlayHistory/Patches/HarmonyPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static bool Prepare()
}

[HarmonyAfter("com.kyle1413.BeatSaber.SongCore")]
public static void Postfix(LevelListTableCell __instance, IPreviewBeatmapLevel? level, bool isFavorite,
public static void Postfix(LevelListTableCell __instance, BeatmapLevel? level, bool isFavorite,
Image ____favoritesBadgeImage, TextMeshProUGUI? ____songBpmText)
{
if (!PluginConfig.Instance.ShowVotes) return;
Expand Down
2 changes: 1 addition & 1 deletion SongPlayHistory/SongPlayData/IRecordManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace SongPlayHistory.SongPlayData;

public interface IRecordManager
{
public IList<ISongPlayRecord> GetRecords(IDifficultyBeatmap beatmap);
public IList<ISongPlayRecord> GetRecords(BeatmapKey beatmap);

public IList<ISongPlayRecord> GetRecords(LevelMapKey key);

Expand Down
2 changes: 1 addition & 1 deletion SongPlayHistory/SongPlayData/IScoringCacheManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ namespace SongPlayHistory.SongPlayData;

public interface IScoringCacheManager
{
public Task<LevelScoringCache> GetScoringInfo(IDifficultyBeatmap beatmap, CancellationToken cancellationToken = new());
public Task<LevelScoringCache> GetScoringInfo(BeatmapKey beatmapKey, BeatmapLevel? beatmapLevel = null, CancellationToken cancellationToken = new());
}
10 changes: 5 additions & 5 deletions SongPlayHistory/SongPlayData/RecordsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private void OnLevelFinished(object scene, LevelFinishedEventArgs eventArgs)

if (eventArgs.LevelType == LevelType.Multiplayer)
{
var beatmap = ((MultiplayerLevelScenesTransitionSetupDataSO)scene).difficultyBeatmap;
var beatmap = ((MultiplayerLevelScenesTransitionSetupDataSO)scene).beatmapKey;
SaveRecord(beatmap, result, true, energyDidReach0, failRecord);
}
else
Expand All @@ -136,12 +136,12 @@ private void OnLevelFinished(object scene, LevelFinishedEventArgs eventArgs)
_logger.Info("It was in practice or party mode, ignored.");
return;
}
var beatmap = ((StandardLevelScenesTransitionSetupDataSO)scene).difficultyBeatmap;
var beatmap = ((StandardLevelScenesTransitionSetupDataSO)scene).beatmapKey;
SaveRecord(beatmap, result, false, energyDidReach0, failRecord);
}
}

public IList<ISongPlayRecord> GetRecords(IDifficultyBeatmap beatmap)
public IList<ISongPlayRecord> GetRecords(BeatmapKey beatmap)
{
var key = new LevelMapKey(beatmap);
return GetRecords(key);
Expand All @@ -160,7 +160,7 @@ public IList<ISongPlayRecord> GetRecords(LevelMapKey key)
return new List<ISongPlayRecord>();
}

private void SaveRecord(IDifficultyBeatmap? beatmap, LevelCompletionResults? result, bool isMultiplayer, bool energyDidReach0, ScoreRecord? failRecord)
private void SaveRecord(BeatmapKey? beatmap, LevelCompletionResults? result, bool isMultiplayer, bool energyDidReach0, ScoreRecord? failRecord)
{
if (beatmap == null || result == null)
{
Expand Down Expand Up @@ -235,7 +235,7 @@ private void SaveRecord(IDifficultyBeatmap? beatmap, LevelCompletionResults? res

_logger.Info($"Saving result. Record: {record}");

var key = new LevelMapKey(beatmap).ToOldKey();
var key = new LevelMapKey(beatmap.Value).ToOldKey();

if (!Records.ContainsKey(key))
{
Expand Down
56 changes: 50 additions & 6 deletions SongPlayHistory/SongPlayData/ScoringCacheManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,25 @@ internal class ScoringCacheManager: IScoringCacheManager
[Inject]
private readonly PlayerDataModel _playerDataModel = null!;

[Inject]
private readonly BeatmapLevelsModel _beatmapLevelsModel = null!;

[Inject]
private readonly BeatmapDataLoader _beatmapDataLoader = null!;

[Inject]
private readonly EnvironmentsListModel _environmentListModel = null!;

[Inject]
private readonly SiraLog _logger = null!;

//TODO use persistent storage cache if needed
private readonly Dictionary<LevelMapKey, LevelScoringCache> _cache = new Dictionary<LevelMapKey, LevelScoringCache>();

public async Task<LevelScoringCache> GetScoringInfo(IDifficultyBeatmap beatmap, CancellationToken cancellationToken = new())
public async Task<LevelScoringCache> GetScoringInfo(BeatmapKey beatmapKey, BeatmapLevel? beatmapLevel = null, CancellationToken cancellationToken = new())
{
_logger.Debug($"Get scoring cache from Thread {Environment.CurrentManagedThreadId}");
var cacheKey = new LevelMapKey(beatmap);
var cacheKey = new LevelMapKey(beatmapKey);

lock (_cache)
{
Expand All @@ -34,14 +43,49 @@ internal class ScoringCacheManager: IScoringCacheManager
}

cancellationToken.ThrowIfCancellationRequested();
// await Task.Delay(15000, cancellationToken); // simulate am extreme loading time
// await Task.Delay(15000, cancellationToken); // simulate an extreme loading time

if (beatmapLevel == null)
{
_logger.Warn("BeatmapLevel is null, getting from BeatmapLevelsModel.");
beatmapLevel = _beatmapLevelsModel.GetBeatmapLevel(beatmapKey.levelId);
if (beatmapLevel == null)
{
_logger.Error("Failed to get BeatmapLevel.");
throw new Exception("Failed to get BeatmapLevel.");
}
}

_logger.Debug("Loading beat map level data from BeatmapLevelsModel.");
var loadResult = await _beatmapLevelsModel.LoadBeatmapLevelDataAsync(beatmapKey.levelId, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
if (loadResult.isError)
{
_logger.Error("Failed to get BeatmapLevelData.");
throw new Exception("Failed to load beat map level data.");
}

var beatmapLevelData = loadResult.beatmapLevelData!;

var beatmapData = await beatmap.GetBeatmapDataAsync(beatmap.GetEnvironmentInfo(), _playerDataModel.playerData.playerSpecificSettings);
var basicBeatmapData = beatmapLevel.GetDifficultyBeatmapData(beatmapKey.beatmapCharacteristic, beatmapKey.difficulty);
var envName = basicBeatmapData.environmentName;
var envInfo = _environmentListModel.GetEnvironmentInfoBySerializedNameSafe(envName);
var beatmapData = await _beatmapDataLoader.LoadBeatmapDataAsync(
beatmapLevelData,
beatmapKey,
beatmapLevel.beatsPerMinute,
false, //environmentName == this.environmentInfo.serializedName,
envInfo, // do we need to consider player env override?
_playerDataModel.playerData.gameplayModifiers,
_playerDataModel.playerData.playerSpecificSettings,
true);

cancellationToken.ThrowIfCancellationRequested();
var notesCount = beatmapData.cuttableNotesCount;

var notesCount = basicBeatmapData.notesCount;
var fullMaxScore = ScoreModel.ComputeMaxMultipliedScoreForBeatmap(beatmapData);
// we can use the original v2 scoring method to calculate the adjusted max score if there is no slider or burst
var isV2Score = !beatmapData.GetBeatmapDataItems<SliderData>(0).Any();
var isV2Score = !beatmapData!.GetBeatmapDataItems<SliderData>(0).Any();
cancellationToken.ThrowIfCancellationRequested();

var newCache = new LevelScoringCache
Expand Down
5 changes: 4 additions & 1 deletion SongPlayHistory/SongPlayHistory.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
<Reference Include="0Harmony" HintPath="$(BeatSaberDir)\Libs\0Harmony.dll" />
<Reference Include="BeatmapCore" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\BeatmapCore.dll" />
<Reference Include="BeatSaverVoting" HintPath="$(BeatSaberDir)\Plugins\BeatSaverVoting.dll" Publicize="true" />
<Reference Include="BGLib.AppFlow" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\BGLib.AppFlow.dll" />
<Reference Include="BGLib.Polyglot" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\BGLib.Polyglot.dll" />
<Reference Include="BGLib.UnityExtension" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\BGLib.UnityExtension.dll" />
<Reference Include="DataModels" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\DataModels.dll" />
<Reference Include="Hive.Versioning" HintPath="$(BeatSaberDir)\Libs\Hive.Versioning.dll" />
<Reference Include="Main" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\Main.dll" />
<Reference Include="Newtonsoft.Json" HintPath="$(BeatSaberDir)\Libs\Newtonsoft.Json.dll" />
Expand All @@ -26,7 +30,6 @@
<Reference Include="HMUI" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\HMUI.dll" />
<Reference Include="HMLib" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\HMLib.dll" />
<Reference Include="IPA.Loader" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\IPA.Loader.dll" />
<Reference Include="Polyglot" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\Polyglot.dll" />
<Reference Include="SiraUtil" HintPath="$(BeatSaberDir)\Plugins\SiraUtil.dll" />
<Reference Include="SongCore" HintPath="$(BeatSaberDir)\Plugins\SongCore.dll" />
<Reference Include="Unity.TextMeshPro" HintPath="$(BeatSaberDir)\Beat Saber_Data\Managed\Unity.TextMeshPro.dll" />
Expand Down
36 changes: 19 additions & 17 deletions SongPlayHistory/UI/SPHUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using System.Threading.Tasks;
using HMUI;
using IPA.Utilities;
using Polyglot;
using BGLib.Polyglot;
using SiraUtil.Logging;
using SongPlayHistory.Configuration;
using SongPlayHistory.Model;
Expand Down Expand Up @@ -136,31 +136,31 @@ public void Dispose()
_cts = null;
}

private void OnDifficultyChanged(StandardLevelDetailViewController _, IDifficultyBeatmap beatmap)
private void OnDifficultyChanged(StandardLevelDetailViewController controller)
{
UpdateUI(beatmap);
UpdateUI(controller.beatmapKey, controller.beatmapLevel);
}

private void OnContentChanged(StandardLevelDetailViewController _, StandardLevelDetailViewController.ContentType contentType)
private void OnContentChanged(StandardLevelDetailViewController controller, StandardLevelDetailViewController.ContentType contentType)
{
if (contentType == StandardLevelDetailViewController.ContentType.OwnedAndReady)
{
UpdateUI(_levelDetailViewController.selectedDifficultyBeatmap);
UpdateUI(controller.beatmapKey, controller.beatmapLevel);
}
}

private void OnPlayResultDismiss(ResultsViewController _)
{
UpdateUI(_levelDetailViewController.selectedDifficultyBeatmap);
UpdateUI(_levelDetailViewController.beatmapKey, _levelDetailViewController.beatmapLevel);
}

private void UpdateUI(IDifficultyBeatmap? beatmap)
private void UpdateUI(BeatmapKey beatmapKey, BeatmapLevel? beatmap)
{
if (beatmap == null) return;
_logger.Info("Updating SPH UI");
_logger.Debug($"{beatmap.level.songName} {beatmap.parentDifficultyBeatmapSet.beatmapCharacteristic.serializedName} {beatmap.difficulty}");
_logger.Debug($"{beatmap.songName} {beatmapKey.beatmapCharacteristic.serializedName} {beatmapKey.difficulty}");

SetStats(beatmap);
SetStats(beatmapKey);

_cts?.Cancel();
_cts?.Dispose();
Expand All @@ -170,11 +170,11 @@ private void UpdateUI(IDifficultyBeatmap? beatmap)
{
try
{
await SetRecords(beatmap, token);
await SetRecords(beatmapKey, beatmap, token);
}
catch (OperationCanceledException e) when (e.CancellationToken == token)
{
_logger.Debug($"Update cancelled: {beatmap.level.songName}");
_logger.Debug($"Update cancelled: {beatmap.songName}");
}
catch (Exception ex)
{
Expand All @@ -184,14 +184,14 @@ private void UpdateUI(IDifficultyBeatmap? beatmap)
}, token);
}

private async Task SetRecords(IDifficultyBeatmap beatmap, CancellationToken cancellationToken)
private async Task SetRecords(BeatmapKey beatmapKey, BeatmapLevel beatmap, CancellationToken cancellationToken)
{
_logger.Debug($"Setting records from Thread {Environment.CurrentManagedThreadId}");

var task = _scoringCacheManager.GetScoringInfo(beatmap, cancellationToken); // let it run in the background first
var task = _scoringCacheManager.GetScoringInfo(beatmapKey, beatmap, cancellationToken); // let it run in the background first

var config = PluginConfig.Instance;
var key = new LevelMapKey(beatmap);
var key = new LevelMapKey(beatmapKey);
var records =
from record in _recordsManager.GetRecords(key)
where config.ShowFailed || record.LevelEnd == LevelEndType.Cleared
Expand Down Expand Up @@ -295,10 +295,12 @@ from record in _recordsManager.GetRecords(key)
_hoverHint.text = builder.ToString();
}

private void SetStats(IDifficultyBeatmap beatmap)
private void SetStats(BeatmapKey beatmap)
{
var stats = _playerDataModel.playerData.GetPlayerLevelStatsData(beatmap.level.levelID, beatmap.difficulty, beatmap.parentDifficultyBeatmapSet.beatmapCharacteristic);
_playCount.text = stats.playCount.ToString();
var playCount = _playerDataModel.playerData.levelsStatsData.TryGetValue(beatmap, out var data)
? data.playCount
: 0;
_playCount.text = playCount.ToString();
}
}
}
4 changes: 2 additions & 2 deletions SongPlayHistory/Utils/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ internal static bool IsInReplay()
}
#endregion

internal static string GetLowerCaseCustomLevelHash(CustomPreviewBeatmapLevel level)
internal static string? GetLowerCaseCustomLevelHash(BeatmapLevel level)
{
return Hashing.GetCustomLevelHash(level).ToLower();
return level.levelID.StartsWith("custom_level_") ? Hashing.GetCustomLevelHash(level).ToLower() : null;
}

internal static IList<ISongPlayRecord> Copy(this IEnumerable<Record> records)
Expand Down
23 changes: 16 additions & 7 deletions SongPlayHistory/VoteTracker/BeatSaverVotingTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,25 @@ internal class BeatSaverVotingTracker: IVoteTracker

[Inject]
private readonly SiraLog _logger = null!;
public void Vote(IPreviewBeatmapLevel level, VoteType voteType)

public void Vote(BeatmapLevel level, VoteType voteType)
{
if (!(level is CustomPreviewBeatmapLevel customLevel)) return;
try
{
_logger.Debug($"Voting for {level.songName}, {level.levelID}, {voteType}");
var hash = Utils.Utils.GetLowerCaseCustomLevelHash(level);
if (hash == null)
{
_logger.Debug("Not custom level");
return;
}

if (BSVPlugin.votedSongs == null)
{
_logger.Debug("BeatSaverVoting dictionary is null");
return;
}

var hash = Utils.Utils.GetLowerCaseCustomLevelHash(customLevel);
var bsvType = voteType == VoteType.Upvote ? BSVType.Upvote : BSVType.Downvote;
if (BSVPlugin.votedSongs.TryGetValue(hash, out var songVote) && songVote.voteType == bsvType) return;

Expand All @@ -39,14 +44,18 @@ public void Vote(IPreviewBeatmapLevel level, VoteType voteType)
}
}

public bool TryGetVote(IPreviewBeatmapLevel level, out VoteType voteType)
public bool TryGetVote(BeatmapLevel level, out VoteType voteType)
{
voteType = VoteType.Downvote;
if (!(level is CustomPreviewBeatmapLevel customLevel)) return false;
try
{
_logger.Debug($"Getting vote data for {level.songName}, {level.levelID}");
var hash = Utils.Utils.GetLowerCaseCustomLevelHash(customLevel);
var hash = Utils.Utils.GetLowerCaseCustomLevelHash(level);
if (hash == null)
{
_logger.Debug("Not custom level");
return false;
}

var voteStatus = BSVPlugin.CurrentVoteStatus(hash);
if (voteStatus == null)
Expand Down
4 changes: 2 additions & 2 deletions SongPlayHistory/VoteTracker/IVoteTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ namespace SongPlayHistory.VoteTracker
{
public interface IVoteTracker
{
public bool TryGetVote(IPreviewBeatmapLevel level, out VoteType voteType);
public bool TryGetVote(BeatmapLevel level, out VoteType voteType);

public void Vote(IPreviewBeatmapLevel level, VoteType voteType);
public void Vote(BeatmapLevel level, VoteType voteType);

}
}
4 changes: 2 additions & 2 deletions SongPlayHistory/VoteTracker/InMenuVoteTrackingHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,14 @@ private void OnPlayResultDismiss(ResultsViewController _)
_tableView.RefreshCellsContent();
}

internal void Vote(IPreviewBeatmapLevel level, VoteType voteType)
internal void Vote(BeatmapLevel level, VoteType voteType)
{
_voteTracker.Vote(level, voteType);
_logger.Debug("Refreshing cells content");
_tableView.RefreshCellsContent();
}

internal bool TryGetVote(IPreviewBeatmapLevel level, out VoteType voteType)
internal bool TryGetVote(BeatmapLevel level, out VoteType voteType)
{
return _voteTracker.TryGetVote(level, out voteType);
}
Expand Down
Loading

0 comments on commit 6e5debb

Please sign in to comment.