From 0cea5d3b8b8b7ce2e316f175f80ce4d2d7fcf5e7 Mon Sep 17 00:00:00 2001 From: HalloTheEngineer <83722147+HalloTheEngineer@users.noreply.github.com> Date: Fri, 13 Feb 2026 00:33:45 +0100 Subject: [PATCH 1/3] migrated code to 1.42.2; added dependency: BS_Utils --- .gitignore | 2 + ScoreSaber/Core/Daemons/MockUploadDaemon.cs | 18 +++---- ScoreSaber/Core/ReplaySystem/ReplayLoader.cs | 28 ++++++---- ScoreSaber/Core/Services/PlayerService.cs | 57 ++++++++++++++++---- ScoreSaber/ScoreSaber.csproj | 25 +++++++++ ScoreSaber/manifest.json | 4 +- 6 files changed, 100 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index 140ae3e..acfe076 100644 --- a/.gitignore +++ b/.gitignore @@ -354,3 +354,5 @@ MigrationBackup/ ScoreSaber/ObfuscationSettings.cs ScoreSaber/Core/ReplaySystem/Legacy/LegacyRecorder.cs ScoreSaber/Core/ReplaySystem/Legacy/OldLegacyReplayPlayer.cs + +.idea diff --git a/ScoreSaber/Core/Daemons/MockUploadDaemon.cs b/ScoreSaber/Core/Daemons/MockUploadDaemon.cs index 708c61d..5c80245 100644 --- a/ScoreSaber/Core/Daemons/MockUploadDaemon.cs +++ b/ScoreSaber/Core/Daemons/MockUploadDaemon.cs @@ -45,17 +45,14 @@ public MockUploadDaemon(LeaderboardService leaderboardService, PlayerService pla } public void FakeUpload(StandardLevelScenesTransitionSetupDataSO standardLevelScenesTransitionSetupDataSO, LevelCompletionResults levelCompletionResults) { - - ProcessUpload(standardLevelScenesTransitionSetupDataSO.gameMode, standardLevelScenesTransitionSetupDataSO.difficultyBeatmap, levelCompletionResults, standardLevelScenesTransitionSetupDataSO.practiceSettings != null); + ProcessUpload(standardLevelScenesTransitionSetupDataSO.gameMode, standardLevelScenesTransitionSetupDataSO.beatmapLevel, standardLevelScenesTransitionSetupDataSO.beatmapKey, levelCompletionResults, standardLevelScenesTransitionSetupDataSO.practiceSettings != null); } - private void FakeMultiUpload(MultiplayerLevelScenesTransitionSetupDataSO multiplayerLevelScenesTransitionSetupDataSO, MultiplayerResultsData multiplayerResultsData) { - - ProcessUpload(multiplayerLevelScenesTransitionSetupDataSO.gameMode, multiplayerLevelScenesTransitionSetupDataSO.difficultyBeatmap, multiplayerResultsData.localPlayerResultData.multiplayerLevelCompletionResults.levelCompletionResults, false); + ProcessUpload(multiplayerLevelScenesTransitionSetupDataSO.gameMode, multiplayerLevelScenesTransitionSetupDataSO.beatmapLevel, multiplayerLevelScenesTransitionSetupDataSO.beatmapKey, multiplayerResultsData.localPlayerResultData.multiplayerLevelCompletionResults.levelCompletionResults, false); } - private async void ProcessUpload(string gameMode, IDifficultyBeatmap difficultyBeatmap, LevelCompletionResults levelCompletionResults, bool practicing) { + private async void ProcessUpload(string gameMode, BeatmapLevel beatmapLevel, BeatmapKey beatmapKey, LevelCompletionResults levelCompletionResults, bool practicing) { var practiceViewController = Resources.FindObjectsOfTypeAll().FirstOrDefault(); if (!practiceViewController.isInViewControllerHierarchy) { @@ -77,9 +74,8 @@ private async void ProcessUpload(string gameMode, IDifficultyBeatmap difficultyB return; } - bool ranked = true; - Leaderboard currentLeaderboard = await _leaderboardService.GetCurrentLeaderboard(difficultyBeatmap); + Leaderboard currentLeaderboard = await _leaderboardService.GetCurrentLeaderboard(beatmapKey); if (currentLeaderboard != null) { ranked = currentLeaderboard.leaderboardInfo.ranked; @@ -96,7 +92,7 @@ private async void ProcessUpload(string gameMode, IDifficultyBeatmap difficultyB } // We good, "upload" the score - WriteReplay(difficultyBeatmap).RunTask(); + WriteReplay(beatmapLevel, beatmapKey).RunTask(); } } else { // We still want to write a replay to memory if in practice mode @@ -104,7 +100,7 @@ private async void ProcessUpload(string gameMode, IDifficultyBeatmap difficultyB } } - public async Task WriteReplay(IDifficultyBeatmap beatmap) { + public async Task WriteReplay(BeatmapLevel beatmapLevel, BeatmapKey beatmapKey) { uploading = true; UploadStatusChanged?.Invoke(UploadStatus.Uploading, "Packaging replay..."); @@ -112,7 +108,7 @@ public async Task WriteReplay(IDifficultyBeatmap beatmap) { byte[] serializedReplay = await _replayService.WriteSerializedReplay(); if (Plugin.Settings.saveLocalReplays) { - string replayPath = $@"{Settings.replayPath}\{_playerService.localPlayerInfo.playerId}-{beatmap.level.songName.ReplaceInvalidChars().Truncate(155)}-{beatmap.difficulty.SerializedName()}-{beatmap.parentDifficultyBeatmapSet.beatmapCharacteristic.serializedName}-{beatmap.level.levelID}.dat"; + string replayPath = $@"{Settings.replayPath}\{_playerService.localPlayerInfo.playerId}-{beatmapLevel.songName.ReplaceInvalidChars().Truncate(155)}-{beatmapKey.difficulty.SerializedName()}-{beatmapKey.beatmapCharacteristic.serializedName}-{beatmapLevel.levelID}.dat"; File.WriteAllBytes(replayPath, serializedReplay); } uploading = false; diff --git a/ScoreSaber/Core/ReplaySystem/ReplayLoader.cs b/ScoreSaber/Core/ReplaySystem/ReplayLoader.cs index 63ad8c3..6582930 100644 --- a/ScoreSaber/Core/ReplaySystem/ReplayLoader.cs +++ b/ScoreSaber/Core/ReplaySystem/ReplayLoader.cs @@ -75,18 +75,22 @@ await Task.Run(async () => { overrideEnvironmentSettings: playerData.overrideEnvironmentSettings, playerOverrideColorScheme: playerData.colorSchemesSettings.GetOverrideColorScheme(), playerOverrideLightshowColors: playerData.colorSchemesSettings.ShouldOverrideLightshowColors(), - beatmapOverrideColorScheme: beatmapLevel.GetColorScheme(beatmapKey.beatmapCharacteristic, beatmapKey.difficulty), gameplayModifiers: gameplayModifiers, playerSpecificSettings: playerSettings, practiceSettings: null, environmentsListModel: _environmentsListModel, - backButtonText: "Exit Replay", - useTestNoteCutSoundEffects: false, - startPaused: false, + gameplayAdditionalInformation: new GameplayAdditionalInformation( + backButtonText: "Exit Replay", + useTestNoteCutSoundEffects: false, + startPaused: false, + playmodeOptions: PlaymodeOptions.Default, + recordingRelativePath: null + ), beforeSceneSwitchToGameplayCallback: null, afterSceneSwitchToGameplayCallback: null, levelFinishedCallback: ReplayEnd, - levelRestartedCallback: null + levelRestartedCallback: null, + beatmapLevelData: null ); }); } @@ -151,18 +155,22 @@ await Task.Run(async () => { overrideEnvironmentSettings: playerData.overrideEnvironmentSettings, playerOverrideColorScheme: playerData.colorSchemesSettings.GetOverrideColorScheme(), playerOverrideLightshowColors: playerData.colorSchemesSettings.ShouldOverrideLightshowColors(), - beatmapOverrideColorScheme: beatmapLevel.GetColorScheme(beatmapKey.beatmapCharacteristic, beatmapKey.difficulty), gameplayModifiers: LeaderboardUtils.GetModifierFromStrings(replay.metadata.Modifiers.ToArray(), false).gameplayModifiers, playerSpecificSettings: playerSettings, practiceSettings: null, environmentsListModel: _environmentsListModel, - backButtonText: "Exit Replay", - useTestNoteCutSoundEffects: false, - startPaused: false, + gameplayAdditionalInformation: new GameplayAdditionalInformation( + backButtonText: "Exit Replay", + useTestNoteCutSoundEffects: false, + startPaused: false, + playmodeOptions: PlaymodeOptions.Default, + recordingRelativePath: null + ), beforeSceneSwitchToGameplayCallback: null, afterSceneSwitchToGameplayCallback: null, levelFinishedCallback: ReplayEnd, - levelRestartedCallback: null + levelRestartedCallback: null, + beatmapLevelData: null ); }); } diff --git a/ScoreSaber/Core/Services/PlayerService.cs b/ScoreSaber/Core/Services/PlayerService.cs index 8522b1c..718e607 100644 --- a/ScoreSaber/Core/Services/PlayerService.cs +++ b/ScoreSaber/Core/Services/PlayerService.cs @@ -8,6 +8,9 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.Collections.Generic; +using Steamworks; +using System.Reflection; using UnityEngine; namespace ScoreSaber.Core.Services { @@ -47,30 +50,62 @@ private async Task SignIn() { ChangeLoginStatus(LoginStatus.InProgress, "Signing into ScoreSaber..."); - var platformUserModel = Plugin.Container.TryResolve(); - var authToken = await platformUserModel.GetUserAuthToken(); - var userInfo = await platformUserModel.GetUserInfo(CancellationToken.None); + var userInfo = await BS_Utils.Gameplay.GetUserInfo.GetUserAsync(); + var platform = BS_Utils.Gameplay.GetUserInfo.GetPlatformUserModel(); var nonce = string.Empty; - var platform = string.Empty; + var platformString = string.Empty; switch (userInfo.platform) { case UserInfo.Platform.Steam: - nonce = authToken.token; - platform = "0"; + nonce = await platform.user.GetAccessTokenAsync(); + platformString = "0"; break; case UserInfo.Platform.Oculus: - nonce = authToken.token + "," + (await platformUserModel.RequestXPlatformAccessToken(CancellationToken.None)).token; - platform = "1"; + var accessToken = await platform.user.GetAccessTokenAsync(); + var xplatformToken = await platform.user.GetXPlatformAccessTokenAsync(); + nonce = accessToken + "," + xplatformToken; + platformString = "1"; break; } var playerId = userInfo.platformUserId; var playerName = userInfo.userName; - var friendIds = await platformUserModel.GetUserFriendsUserIds(false); - var friends = string.Join(",", friendIds.Where(x => x != "0")); + - var playerInfo = new LocalPlayerInfo(playerId, playerName, friends, platform, nonce); + + // Get friends list + var friends = string.Empty; + if (userInfo.platform == UserInfo.Platform.Steam) { + var friendDetailList = new List(); + int friendCount = SteamFriends.GetFriendCount(EFriendFlags.k_EFriendFlagAll); + for (int i = 0; i < friendCount; i++) { + CSteamID friendSteamId = SteamFriends.GetFriendByIndex(i, EFriendFlags.k_EFriendFlagAll); + friendDetailList.Add(friendSteamId.ToString()); + } + friends = string.Join(",", friendDetailList); + } + else { + // Fallback for non-Steam platforms (e.g., Oculus) + var platformNetworkPlayerModel = Resources.FindObjectsOfTypeAll().FirstOrDefault(); + if (platformNetworkPlayerModel != null) { + var friendIds = new List(); + foreach (var friend in platformNetworkPlayerModel.friends) { + var idProperty = friend.GetType().GetProperty("id"); + if (idProperty != null) { + var idValue = idProperty.GetValue(friend); + if (idValue != null) { + friendIds.Add(idValue.ToString()); + continue; + } + } + friendIds.Add(friend.userId); + } + friends = string.Join(",", friendIds); + } + } + + var playerInfo = new LocalPlayerInfo(playerId, playerName, friends, platformString, nonce); int attempts = 1; diff --git a/ScoreSaber/ScoreSaber.csproj b/ScoreSaber/ScoreSaber.csproj index c5a5eac..deee918 100644 --- a/ScoreSaber/ScoreSaber.csproj +++ b/ScoreSaber/ScoreSaber.csproj @@ -46,6 +46,11 @@ False False + + $(BeatSaberDir)\Beat Saber_Data\Managed\BeatSaber.Destinations.dll + False + False + $(BeatSaberDir)\Beat Saber_Data\Managed\BeatSaber.ViewSystem.dll @@ -90,6 +95,21 @@ False False + + $(BeatSaberDir)\Beat Saber_Data\Managed\BeatSaber.Multiplayer.Core.dll + False + False + + + $(BeatSaberDir)\Beat Saber_Data\Managed\OculusStudios.Platform.Core.dll + False + False + + + $(BeatSaberDir)\Beat Saber_Data\Managed\com.rlabrecque.steamworks.net.dll + False + False + $(BeatSaberDir)\Beat Saber_Data\Managed\SegmentedControl.dll @@ -101,6 +121,11 @@ $(BeatSaberDir)\Plugins\SiraUtil.dll + + $(BeatSaberDir)\Plugins\BS_Utils.dll + False + False + $(BeatSaberDir)\Libs\0Harmony.dll diff --git a/ScoreSaber/manifest.json b/ScoreSaber/manifest.json index 11b396e..2fe1080 100644 --- a/ScoreSaber/manifest.json +++ b/ScoreSaber/manifest.json @@ -2,11 +2,11 @@ "$schema": "https://raw.githubusercontent.com/nike4613/ModSaber-MetadataFileSchema/master/Schema.json", "author": "Umbranox", "description": "Allows you to upload scores to an online leaderboard, earn PP from ranked maps and compare scores with others.", - "gameVersion": "1.40.9", + "gameVersion": "1.42.2", "icon": "ScoreSaber.logo.png", "id": "ScoreSaber", "name": "ScoreSaber", - "version": "3.3.17", + "version": "3.3.18", "dependsOn": { "BSIPA": "^4.3.6", "BeatSaberMarkupLanguage": "^1.12.0", From 8212b2e5e92fa43db9e15dd1b8c35c9de5591d7b Mon Sep 17 00:00:00 2001 From: HalloTheEngineer <83722147+HalloTheEngineer@users.noreply.github.com> Date: Fri, 13 Feb 2026 10:52:35 +0100 Subject: [PATCH 2/3] Add BS_Utils dependency to manifest.json --- ScoreSaber/manifest.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ScoreSaber/manifest.json b/ScoreSaber/manifest.json index 2fe1080..30e1c9b 100644 --- a/ScoreSaber/manifest.json +++ b/ScoreSaber/manifest.json @@ -11,7 +11,8 @@ "BSIPA": "^4.3.6", "BeatSaberMarkupLanguage": "^1.12.0", "SiraUtil": "^3.1.11", - "SongCore": "^3.16.0" + "SongCore": "^3.16.0", + "BS_Utils": "^1.14.3" }, "links": { "website": "https://scoresaber.com" From fa7e7fd66e2c48045877e4596c7311e2c668cc0b Mon Sep 17 00:00:00 2001 From: HalloTheEngineer <83722147+HalloTheEngineer@users.noreply.github.com> Date: Sun, 3 May 2026 15:17:11 +0200 Subject: [PATCH 3/3] Fix typo in BS_Utils key in manifest.json --- ScoreSaber/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ScoreSaber/manifest.json b/ScoreSaber/manifest.json index 30e1c9b..3639f80 100644 --- a/ScoreSaber/manifest.json +++ b/ScoreSaber/manifest.json @@ -12,7 +12,7 @@ "BeatSaberMarkupLanguage": "^1.12.0", "SiraUtil": "^3.1.11", "SongCore": "^3.16.0", - "BS_Utils": "^1.14.3" + "BS Utils": "^1.14.3" }, "links": { "website": "https://scoresaber.com"