From d9865796c49b6bdce5df539ca2021670e126d89e Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Wed, 12 Nov 2025 20:01:44 +0100 Subject: [PATCH 01/18] first 1.40.8 fixes --- CMakeLists.txt | 5 + .../CustomTypes/Components/CellClicker.hpp | 51 ++++---- .../Components/GlobalLeaderboardTableCell.hpp | 14 +-- .../Components/GlobalLeaderboardTableData.hpp | 24 ++-- .../LeaderboardScoreInfoButtonHandler.hpp | 27 ++-- include/Data/Private/ScoreSaberUploadData.hpp | 2 +- include/MainInstaller.hpp | 7 +- .../Installers/ImberInstaller.hpp | 7 +- .../Installers/PlaybackInstaller.hpp | 9 +- .../Installers/RecordInstaller.hpp | 7 +- include/ReplaySystem/Playback/ComboPlayer.hpp | 6 +- .../ReplaySystem/Playback/EnergyPlayer.hpp | 6 +- .../ReplaySystem/Playback/HeightPlayer.hpp | 34 ++--- .../Playback/MultiplierPlayer.hpp | 6 +- include/ReplaySystem/Playback/NotePlayer.hpp | 52 ++++---- include/ReplaySystem/Playback/PosePlayer.hpp | 66 +++++----- .../Playback/ReplayTimeSyncController.hpp | 70 +++++------ include/ReplaySystem/Playback/ScorePlayer.hpp | 39 +++--- .../Recorders/EnergyEventRecorder.hpp | 38 +++--- .../Recorders/HeightEventRecorder.hpp | 38 +++--- .../ReplaySystem/Recorders/MainRecorder.hpp | 40 +++--- .../Recorders/MetadataRecorder.hpp | 46 ++++--- .../Recorders/NoteEventRecorder.hpp | 54 ++++---- .../ReplaySystem/Recorders/PoseRecorder.hpp | 36 +++--- .../Recorders/ScoreEventRecorder.hpp | 57 ++++----- include/ReplaySystem/UI/Components/AmeBar.hpp | 41 ++++--- .../ReplaySystem/UI/Components/AmeClicker.hpp | 26 ++-- .../ReplaySystem/UI/Components/AmeHandle.hpp | 35 +++--- .../ReplaySystem/UI/Components/AmeNode.hpp | 31 ++--- include/ReplaySystem/UI/GameReplayUI.hpp | 15 +-- include/ReplaySystem/UI/ImberManager.hpp | 101 ++++++++------- include/ReplaySystem/UI/ImberScrubber.hpp | 116 +++++++++--------- .../ReplaySystem/UI/ImberSpecsReporter.hpp | 34 +++-- .../UI/ImberUIPositionController.hpp | 94 +++++++------- .../ReplaySystem/UI/MainImberPanelView.hpp | 113 +++++++++-------- .../UI/ResultsViewReplayButtonController.hpp | 55 ++++----- .../UI/SpectateAreaController.hpp | 64 +++++----- .../ReplaySystem/UI/VRControllerAccessor.hpp | 9 +- .../ScoreSaberFlowCoordinator.hpp | 13 +- .../ScoreSaberSettingsFlowCoordinator.hpp | 9 +- .../ScoreSaberMultiplayerInitializer.hpp | 33 +++-- ...erLevelSelectionLeaderboardFlowManager.hpp | 61 ++++----- ...ltiplayerResultsLeaderboardFlowManager.hpp | 45 +++---- include/UI/Other/Banner.hpp | 15 +-- include/UI/Other/PlayerProfileModal.hpp | 74 +++++------ include/UI/Other/ScoreInfoModal.hpp | 98 ++++++++------- .../UI/ViewControllers/FAQViewController.hpp | 6 +- .../ViewControllers/GlobalViewController.hpp | 12 +- .../MainSettingsViewController.hpp | 4 +- .../UI/ViewControllers/TeamViewController.hpp | 13 +- include/Utils/MaxScoreCache.hpp | 8 +- include/logging.hpp | 2 +- mod.template.json | 2 +- qpm.json | 29 ++--- .../Components/GlobalLeaderboardTableData.cpp | 6 +- src/Data/Badge.cpp | 2 +- src/Data/LeaderboardInfo.cpp | 2 +- src/Data/LeaderboardPlayer.cpp | 2 +- src/Data/Player.cpp | 2 +- src/Data/Private/AuthResponse.cpp | 2 +- src/Data/Score.cpp | 2 +- src/ReplaySystem/Playback/NotePlayer.cpp | 2 +- src/ReplaySystem/Playback/PosePlayer.cpp | 12 +- .../Recorders/MetadataRecorder.cpp | 11 +- src/ReplaySystem/ReplayLoader.cpp | 3 +- src/ReplaySystem/UI/ImberSpecsReporter.cpp | 2 +- ...erLevelSelectionLeaderboardFlowManager.cpp | 1 + src/UI/Other/ProfilePictureView.cpp | 2 +- src/UI/Other/ScoreSaberLeaderboardView.cpp | 8 +- src/UI/ViewControllers/FAQViewController.cpp | 2 +- src/UI/ViewControllers/TeamViewController.cpp | 2 +- src/Utils/MaxScoreCache.cpp | 54 ++++---- src/Utils/StringUtils.cpp | 2 +- src/Utils/UIUtils.cpp | 2 +- 74 files changed, 983 insertions(+), 1037 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f94bbf7..5c966eb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,12 +37,17 @@ add_compile_definitions(MOD_ID=\"${MOD_ID}\") RECURSE_FILES(cpp_file_list ${SOURCE_DIR}/*.cpp) RECURSE_FILES(c_file_list ${SOURCE_DIR}/*.c) +RECURSE_FILES(inline_hook_c ${EXTERN_DIR}/includes/beatsaber-hook/shared/inline-hook/*.c) +RECURSE_FILES(inline_hook_cpp ${EXTERN_DIR}/includes/beatsaber-hook/shared/inline-hook/*.cpp) + # add all src files to compile add_library( ${COMPILE_ID} SHARED ${cpp_file_list} ${c_file_list} + ${inline_hook_c} + ${inline_hook_cpp} ) # add src dir as include dir diff --git a/include/CustomTypes/Components/CellClicker.hpp b/include/CustomTypes/Components/CellClicker.hpp index d95dac41..e76f9368 100644 --- a/include/CustomTypes/Components/CellClicker.hpp +++ b/include/CustomTypes/Components/CellClicker.hpp @@ -14,31 +14,28 @@ #include -#define INTERFACES \ - { \ - classof(UnityEngine::EventSystems::IPointerClickHandler*), \ - classof(UnityEngine::EventSystems::IPointerEnterHandler*), \ - classof(UnityEngine::EventSystems::IPointerExitHandler*), \ - classof(UnityEngine::EventSystems::IEventSystemHandler*) \ - } +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::CustomTypes::Components, + CellClicker, + UnityEngine::MonoBehaviour, + UnityEngine::EventSystems::IPointerClickHandler*, + UnityEngine::EventSystems::IPointerEnterHandler*, + UnityEngine::EventSystems::IPointerExitHandler*, + UnityEngine::EventSystems::IEventSystemHandler*) { + DECLARE_DEFAULT_CTOR(); + DECLARE_PRIVATE_METHOD(void, Start); + DECLARE_PRIVATE_METHOD(void, OnDestroy); + DECLARE_OVERRIDE_METHOD_MATCH(void, OnPointerClick, &UnityEngine::EventSystems::IPointerClickHandler::OnPointerClick, UnityEngine::EventSystems::PointerEventData* eventData); + DECLARE_OVERRIDE_METHOD_MATCH(void, OnPointerEnter, &UnityEngine::EventSystems::IPointerEnterHandler::OnPointerEnter, UnityEngine::EventSystems::PointerEventData* eventData); + DECLARE_OVERRIDE_METHOD_MATCH(void, OnPointerExit, &UnityEngine::EventSystems::IPointerExitHandler::OnPointerExit, UnityEngine::EventSystems::PointerEventData* eventData); + DECLARE_INSTANCE_FIELD(UnityW, seperator); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityEngine::Vector3, originalScale); + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, origColour, UnityEngine::Color(1, 1, 1, 1)); + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, origColour0, UnityEngine::Color(1, 1, 1, 0.2509804f)); + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, origColour1, UnityEngine::Color(1, 1, 1, 0)); -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::CustomTypes::Components, CellClicker, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, UnityEngine::MonoBehaviour, "ScoreSaber::CustomTypes::Components", INTERFACES, 0, nullptr, - DECLARE_DEFAULT_CTOR(); - DECLARE_PRIVATE_METHOD(void, Start); - DECLARE_PRIVATE_METHOD(void, OnDestroy); - DECLARE_OVERRIDE_METHOD_MATCH(void, OnPointerClick, &UnityEngine::EventSystems::IPointerClickHandler::OnPointerClick, UnityEngine::EventSystems::PointerEventData* eventData); - DECLARE_OVERRIDE_METHOD_MATCH(void, OnPointerEnter, &UnityEngine::EventSystems::IPointerEnterHandler::OnPointerEnter, UnityEngine::EventSystems::PointerEventData* eventData); - DECLARE_OVERRIDE_METHOD_MATCH(void, OnPointerExit, &UnityEngine::EventSystems::IPointerExitHandler::OnPointerExit, UnityEngine::EventSystems::PointerEventData* eventData); - DECLARE_INSTANCE_FIELD(UnityW, seperator); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityEngine::Vector3, originalScale); - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, origColour, UnityEngine::Color(1, 1, 1, 1)); - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, origColour0, UnityEngine::Color(1, 1, 1, 0.2509804f)); - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, origColour1, UnityEngine::Color(1, 1, 1, 0)); - - public: - int index; - std::function onClick; - bool isScaled = false; -) - -#undef INTERFACES \ No newline at end of file +public: + int index; + std::function onClick; + bool isScaled = false; +}; \ No newline at end of file diff --git a/include/CustomTypes/Components/GlobalLeaderboardTableCell.hpp b/include/CustomTypes/Components/GlobalLeaderboardTableCell.hpp index 1ffa5cea..64708c20 100644 --- a/include/CustomTypes/Components/GlobalLeaderboardTableCell.hpp +++ b/include/CustomTypes/Components/GlobalLeaderboardTableCell.hpp @@ -3,7 +3,6 @@ #include "CustomTypes/Components/GlobalLeaderboardTableData.hpp" #include "Data/Player.hpp" #include "UI/Other/PlayerProfileModal.hpp" - #include #include #include @@ -14,11 +13,7 @@ #include #include -#define GET_FIND_METHOD(mPtr) \ - il2cpp_utils::il2cpp_type_check::MetadataGetter::get() - -DECLARE_CLASS_CODEGEN( - ScoreSaber::CustomTypes::Components, GlobalLeaderboardTableCell, HMUI::TableCell, +DECLARE_CLASS_CODEGEN(ScoreSaber::CustomTypes::Components, GlobalLeaderboardTableCell, HMUI::TableCell) { DECLARE_INSTANCE_FIELD(UnityW, rank); DECLARE_INSTANCE_FIELD(UnityW, pp); DECLARE_INSTANCE_FIELD(UnityW, country); @@ -33,12 +28,11 @@ DECLARE_CLASS_CODEGEN( DECLARE_CTOR(ctor); - public - : std::string playerId; +public: + std::string playerId; static GlobalLeaderboardTableCell * CreateCell(); void Refresh(ScoreSaber::Data::Player& player, ScoreSaber::CustomTypes::Components::GlobalLeaderboardTableData::LeaderboardType leaderboardType); void stopProfileRoutine(); void stopFlagRoutine(); void OpenPlayerProfileModal(); - -) \ No newline at end of file +}; \ No newline at end of file diff --git a/include/CustomTypes/Components/GlobalLeaderboardTableData.hpp b/include/CustomTypes/Components/GlobalLeaderboardTableData.hpp index cf61fdd5..30329f06 100644 --- a/include/CustomTypes/Components/GlobalLeaderboardTableData.hpp +++ b/include/CustomTypes/Components/GlobalLeaderboardTableData.hpp @@ -9,18 +9,12 @@ #include #include -#define GET_FIND_METHOD(mPtr) \ - il2cpp_utils::il2cpp_type_check::MetadataGetter::get() - -static std::vector GetInterfaces() -{ - return {classof(HMUI::TableView::IDataSource*)}; -} - -___DECLARE_TYPE_WRAPPER_INHERITANCE( - ScoreSaber::CustomTypes::Components, GlobalLeaderboardTableData, - Il2CppTypeEnum::IL2CPP_TYPE_CLASS, UnityEngine::MonoBehaviour, "ScoreSaber", - GetInterfaces(), 0, nullptr, + +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::CustomTypes::Components, + GlobalLeaderboardTableData, + UnityEngine::MonoBehaviour, + HMUI::TableView::IDataSource*) { DECLARE_INSTANCE_FIELD(StringW, reuseIdentifier); DECLARE_INSTANCE_FIELD(float, cellSize); DECLARE_INSTANCE_FIELD(UnityW, tableView); @@ -47,8 +41,7 @@ ___DECLARE_TYPE_WRAPPER_INHERITANCE( int, NumberOfCells, &HMUI::TableView::IDataSource::NumberOfCells); - public - : +public: enum LeaderboardType{ Global, @@ -60,4 +53,5 @@ ___DECLARE_TYPE_WRAPPER_INHERITANCE( void set_LeaderboardType(LeaderboardType type); std::string get_LeaderboardURL(); void StartRefresh(); - custom_types::Helpers::Coroutine Refresh();) \ No newline at end of file + custom_types::Helpers::Coroutine Refresh(); +}; \ No newline at end of file diff --git a/include/CustomTypes/Components/LeaderboardScoreInfoButtonHandler.hpp b/include/CustomTypes/Components/LeaderboardScoreInfoButtonHandler.hpp index b4846ccf..c315a5b0 100644 --- a/include/CustomTypes/Components/LeaderboardScoreInfoButtonHandler.hpp +++ b/include/CustomTypes/Components/LeaderboardScoreInfoButtonHandler.hpp @@ -7,19 +7,18 @@ #include "Data/Score.hpp" #include -DECLARE_CLASS_CODEGEN(ScoreSaber::CustomTypes::Components, LeaderboardScoreInfoButtonHandler, UnityEngine::MonoBehaviour, - DECLARE_INSTANCE_FIELD(UnityW, scoreInfoModal); - DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapLevel*, beatmapLevel); - DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapKey, beatmapKey); +DECLARE_CLASS_CODEGEN(ScoreSaber::CustomTypes::Components, LeaderboardScoreInfoButtonHandler, UnityEngine::MonoBehaviour) { + DECLARE_INSTANCE_FIELD(UnityW, scoreInfoModal); + DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapLevel*, beatmapLevel); + DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapKey, beatmapKey); - public: - void Setup(); - void set_scoreCollection(std::vector scores, GlobalNamespace::BeatmapLevel* beatmapLevel, GlobalNamespace::BeatmapKey beatmapKey, int leaderboardId, int maxScore); - void ShowScoreInfoModal(int buttonIdx); + public: + void Setup(); + void set_scoreCollection(std::vector scores, GlobalNamespace::BeatmapLevel* beatmapLevel, GlobalNamespace::BeatmapKey beatmapKey, int leaderboardId, int maxScore); + void ShowScoreInfoModal(int buttonIdx); - private: - int leaderboardId; - int maxScore; - std::vector scores; - -) \ No newline at end of file + private: + int leaderboardId; + int maxScore; + std::vector scores; +}; \ No newline at end of file diff --git a/include/Data/Private/ScoreSaberUploadData.hpp b/include/Data/Private/ScoreSaberUploadData.hpp index 20d122da..e9fd9cbd 100644 --- a/include/Data/Private/ScoreSaberUploadData.hpp +++ b/include/Data/Private/ScoreSaberUploadData.hpp @@ -1,7 +1,7 @@ #pragma once #include "Utils/StringUtils.hpp" #include -#include "paper/shared/string_convert.hpp" +#include #include #include diff --git a/include/MainInstaller.hpp b/include/MainInstaller.hpp index 7c3e1188..90bf5a52 100644 --- a/include/MainInstaller.hpp +++ b/include/MainInstaller.hpp @@ -6,6 +6,7 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber, MainInstaller, ::Zenject::Installer, - DECLARE_OVERRIDE_METHOD_MATCH(void, InstallBindings, &::Zenject::Installer::InstallBindings); - DECLARE_DEFAULT_CTOR();) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber, MainInstaller, ::Zenject::Installer) { + DECLARE_OVERRIDE_METHOD_MATCH(void, InstallBindings, &::Zenject::Installer::InstallBindings); + DECLARE_DEFAULT_CTOR(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Installers/ImberInstaller.hpp b/include/ReplaySystem/Installers/ImberInstaller.hpp index 40beb09d..9df3a4cb 100644 --- a/include/ReplaySystem/Installers/ImberInstaller.hpp +++ b/include/ReplaySystem/Installers/ImberInstaller.hpp @@ -6,6 +6,7 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Installers, ImberInstaller, ::Zenject::Installer, - DECLARE_OVERRIDE_METHOD_MATCH(void, InstallBindings, &::Zenject::Installer::InstallBindings); - DECLARE_DEFAULT_CTOR();) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Installers, ImberInstaller, ::Zenject::Installer) { + DECLARE_OVERRIDE_METHOD_MATCH(void, InstallBindings, &::Zenject::Installer::InstallBindings); + DECLARE_DEFAULT_CTOR(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Installers/PlaybackInstaller.hpp b/include/ReplaySystem/Installers/PlaybackInstaller.hpp index 253045f6..de7d5d8c 100644 --- a/include/ReplaySystem/Installers/PlaybackInstaller.hpp +++ b/include/ReplaySystem/Installers/PlaybackInstaller.hpp @@ -7,7 +7,8 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Installers, PlaybackInstaller, ::Zenject::Installer, - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::GameplayCoreSceneSetupData*, _gameplayCoreSceneSetupData); - DECLARE_OVERRIDE_METHOD_MATCH(void, InstallBindings, &::Zenject::Installer::InstallBindings); - DECLARE_CTOR(ctor, GlobalNamespace::GameplayCoreSceneSetupData* gameplayCoreSceneSetupData);) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Installers, PlaybackInstaller, ::Zenject::Installer) { + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::GameplayCoreSceneSetupData*, _gameplayCoreSceneSetupData); + DECLARE_OVERRIDE_METHOD_MATCH(void, InstallBindings, &::Zenject::Installer::InstallBindings); + DECLARE_CTOR(ctor, GlobalNamespace::GameplayCoreSceneSetupData* gameplayCoreSceneSetupData); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Installers/RecordInstaller.hpp b/include/ReplaySystem/Installers/RecordInstaller.hpp index dbccfdc5..8eeeb44a 100644 --- a/include/ReplaySystem/Installers/RecordInstaller.hpp +++ b/include/ReplaySystem/Installers/RecordInstaller.hpp @@ -6,6 +6,7 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Installers, RecordInstaller, ::Zenject::Installer, - DECLARE_OVERRIDE_METHOD_MATCH(void, InstallBindings, &::Zenject::Installer::InstallBindings); - DECLARE_DEFAULT_CTOR();) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Installers, RecordInstaller, ::Zenject::Installer) { + DECLARE_OVERRIDE_METHOD_MATCH(void, InstallBindings, &::Zenject::Installer::InstallBindings); + DECLARE_DEFAULT_CTOR(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Playback/ComboPlayer.hpp b/include/ReplaySystem/Playback/ComboPlayer.hpp index 7162e23e..c4b33442 100644 --- a/include/ReplaySystem/Playback/ComboPlayer.hpp +++ b/include/ReplaySystem/Playback/ComboPlayer.hpp @@ -7,8 +7,7 @@ #include #include -DECLARE_CLASS_CODEGEN( - ScoreSaber::ReplaySystem::Playback, ComboPlayer, Il2CppObject, +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Playback, ComboPlayer, Il2CppObject) { DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _comboController); DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _comboUIController); @@ -16,4 +15,5 @@ DECLARE_CLASS_CODEGEN( DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); vector _sortedNoteEvents; vector _sortedComboEvents; - void UpdateCombo(float time, int combo);) + void UpdateCombo(float time, int combo); +}; diff --git a/include/ReplaySystem/Playback/EnergyPlayer.hpp b/include/ReplaySystem/Playback/EnergyPlayer.hpp index cc3b33d4..25b8fa7c 100644 --- a/include/ReplaySystem/Playback/EnergyPlayer.hpp +++ b/include/ReplaySystem/Playback/EnergyPlayer.hpp @@ -8,12 +8,12 @@ #include #include -DECLARE_CLASS_CODEGEN( - ScoreSaber::ReplaySystem::Playback, EnergyPlayer, Il2CppObject, +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Playback, EnergyPlayer, Il2CppObject) { DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyCounter); DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyUIPanel); DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::GameEnergyCounter* gameEnergyCounter, Zenject::DiContainer* container); DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); vector _sortedEnergyEvents; - void UpdateEnergy(float energy);) + void UpdateEnergy(float energy); +}; diff --git a/include/ReplaySystem/Playback/HeightPlayer.hpp b/include/ReplaySystem/Playback/HeightPlayer.hpp index 6002aab9..d4a8d34d 100644 --- a/include/ReplaySystem/Playback/HeightPlayer.hpp +++ b/include/ReplaySystem/Playback/HeightPlayer.hpp @@ -1,6 +1,7 @@ #pragma once #include "Data/Private/ReplayFile.hpp" +#include "System/zzzz__Object_def.hpp" #include #include #include @@ -10,20 +11,19 @@ #include #include -#define INTERFACES \ - { \ - classof(Zenject::ITickable*), classof(Zenject::IInitializable*), \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Playback, HeightPlayer, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Playback", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(int, _nextIndex); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _playerHeightDetector); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::GameplayCoreSceneSetupData*, _gameplayCoreSceneSetupData); - DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::PlayerHeightDetector* playerHeightDetector, GlobalNamespace::GameplayCoreSceneSetupData* gameplayCoreSceneSetupData); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); - vector _sortedHeightEvents;) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Playback, + HeightPlayer, + System::Object, + Zenject::ITickable*, + Zenject::IInitializable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(int, _nextIndex); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _playerHeightDetector); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::GameplayCoreSceneSetupData*, _gameplayCoreSceneSetupData); + DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::PlayerHeightDetector* playerHeightDetector, GlobalNamespace::GameplayCoreSceneSetupData* gameplayCoreSceneSetupData); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); + vector _sortedHeightEvents; +}; diff --git a/include/ReplaySystem/Playback/MultiplierPlayer.hpp b/include/ReplaySystem/Playback/MultiplierPlayer.hpp index cdb583da..13fead83 100644 --- a/include/ReplaySystem/Playback/MultiplierPlayer.hpp +++ b/include/ReplaySystem/Playback/MultiplierPlayer.hpp @@ -7,11 +7,11 @@ #include #include -DECLARE_CLASS_CODEGEN( - ScoreSaber::ReplaySystem::Playback, MultiplierPlayer, Il2CppObject, +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Playback, MultiplierPlayer, Il2CppObject) { DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _scoreController); DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::ScoreController* scoreController); DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); vector _sortedMultiplierEvents; - void UpdateMultiplier(int multiplier, float progress);) + void UpdateMultiplier(int multiplier, float progress); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Playback/NotePlayer.hpp b/include/ReplaySystem/Playback/NotePlayer.hpp index 406258d5..008e69ac 100644 --- a/include/ReplaySystem/Playback/NotePlayer.hpp +++ b/include/ReplaySystem/Playback/NotePlayer.hpp @@ -30,30 +30,28 @@ struct RecognizedNoteCutInfo ScoreSaber::Data::Private::NoteEvent event; }; -#define INTERFACES \ - { \ - classof(Zenject::ITickable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Playback, NotePlayer, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Playback", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(int, _nextIndex); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _saberManager); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BasicBeatmapObjectManager*, _basicBeatmapObjectManager); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::MemoryPoolContainer_1>*, _gameNotePool); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::MemoryPoolContainer_1>*, _burstSliderHeadNotePool); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::MemoryPoolContainer_1>*, _burstSliderNotePool); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::MemoryPoolContainer_1>*, _bombNotePool); - DECLARE_INSTANCE_METHOD(void, ForceCompleteGoodScoringElements, GlobalNamespace::GoodCutScoringElement* scoringElement, GlobalNamespace::NoteCutInfo noteCutInfo, GlobalNamespace::CutScoreBuffer* cutScoreBuffer); - DECLARE_CTOR(ctor, GlobalNamespace::SaberManager* saberManager, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::BasicBeatmapObjectManager* basicBeatmapObjectManager); - DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); - std::vector _sortedNoteEvents; - std::vector _recognizedNoteCutInfos; - // std::map _recognizedNoteCutInfos; - // System::Collections::Generic::Dictionary_2 * _recognizedNoteCutInfos; - void ProcessEvent(Data::Private::NoteEvent &activeEvent); - bool HandleEvent(Data::Private::NoteEvent &activeEvent, GlobalNamespace::NoteController* noteController); - bool DoesNoteMatchID(Data::Private::NoteID &id, GlobalNamespace::NoteData* noteData);) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Playback, + NotePlayer, + System::Object, + Zenject::ITickable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(int, _nextIndex); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _saberManager); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BasicBeatmapObjectManager*, _basicBeatmapObjectManager); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::MemoryPoolContainer_1>*, _gameNotePool); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::MemoryPoolContainer_1>*, _burstSliderHeadNotePool); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::MemoryPoolContainer_1>*, _burstSliderNotePool); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::MemoryPoolContainer_1>*, _bombNotePool); + DECLARE_INSTANCE_METHOD(void, ForceCompleteGoodScoringElements, GlobalNamespace::GoodCutScoringElement* scoringElement, GlobalNamespace::NoteCutInfo noteCutInfo, GlobalNamespace::CutScoreBuffer* cutScoreBuffer); + DECLARE_CTOR(ctor, GlobalNamespace::SaberManager* saberManager, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::BasicBeatmapObjectManager* basicBeatmapObjectManager); + DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); + std::vector _sortedNoteEvents; + std::vector _recognizedNoteCutInfos; + // std::map _recognizedNoteCutInfos; + // System::Collections::Generic::Dictionary_2 * _recognizedNoteCutInfos; + void ProcessEvent(Data::Private::NoteEvent &activeEvent); + bool HandleEvent(Data::Private::NoteEvent &activeEvent, GlobalNamespace::NoteController* noteController); + bool DoesNoteMatchID(Data::Private::NoteID &id, GlobalNamespace::NoteData* noteData); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Playback/PosePlayer.hpp b/include/ReplaySystem/Playback/PosePlayer.hpp index cc614a90..8f0f094d 100644 --- a/include/ReplaySystem/Playback/PosePlayer.hpp +++ b/include/ReplaySystem/Playback/PosePlayer.hpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -16,36 +16,34 @@ #include #include -#define INTERFACES \ - { \ - classof(Zenject::ITickable*), classof(Zenject::IInitializable*), classof(::System::IDisposable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Playback, PosePlayer, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Playback", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _mainCamera); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _saberManager); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::IReturnToMenuController*, _returnToMenuController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _playerTransforms); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(int, _nextIndex); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _spectatorCamera); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _desktopCamera); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityEngine::Vector3, _spectatorOffset); - DECLARE_INSTANCE_FIELD_PRIVATE(BeatSaber::GameSettings::MainSettingsHandler*, _mainSettingsHandler); - DECLARE_CTOR(ctor, GlobalNamespace::MainCamera* mainCamera, GlobalNamespace::SaberManager* saberManager, GlobalNamespace::IReturnToMenuController* returnToMenuController, GlobalNamespace::PlayerTransforms* playerTransforms, BeatSaber::GameSettings::MainSettingsHandler* mainSettingsHandler, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, TimeUpdate, float newTime); - vector _sortedPoses; - std::function DidUpdatePose; - void UpdatePoses(Data::Private::VRPoseGroup activePose, Data::Private::VRPoseGroup nextPose); - bool ReachedEnd(); - void SetupCameras(); - public: - void SetSpectatorOffset(UnityEngine::Vector3 value); - void AddCallback(std::function callback); - -); - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Playback, + PosePlayer, + System::Object, + Zenject::ITickable*, + Zenject::IInitializable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _mainCamera); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _saberManager); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::IReturnToMenuController*, _returnToMenuController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _playerTransforms); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(int, _nextIndex); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _spectatorCamera); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _desktopCamera); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityEngine::Vector3, _spectatorOffset); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::SettingsManager*, _settingsManager); + DECLARE_CTOR(ctor, GlobalNamespace::MainCamera* mainCamera, GlobalNamespace::SaberManager* saberManager, GlobalNamespace::IReturnToMenuController* returnToMenuController, GlobalNamespace::PlayerTransforms* playerTransforms, GlobalNamespace::SettingsManager* settingsManager, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, TimeUpdate, float newTime); + vector _sortedPoses; + std::function DidUpdatePose; + void UpdatePoses(Data::Private::VRPoseGroup activePose, Data::Private::VRPoseGroup nextPose); + bool ReachedEnd(); + void SetupCameras(); +public: + void SetSpectatorOffset(UnityEngine::Vector3 value); + void AddCallback(std::function callback); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp b/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp index a483f206..55fb420b 100644 --- a/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp +++ b/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp @@ -19,41 +19,39 @@ #include #include -#define INTERFACES \ - { \ - classof(Zenject::ITickable*) \ - } +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Playback, + ReplayTimeSyncController, + System::Object, + Zenject::ITickable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioManagerSO); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::AudioTimeSyncController::InitData*, _audioInitData); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BasicBeatmapObjectManager*, _basicBeatmapObjectManager); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _noteCutSoundEffectManager); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapCallbacksController::InitData*, _callbackInitData); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapCallbacksController*, _beatmapObjectCallbackController); + DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::ComboPlayer*, _comboPlayer); + DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::EnergyPlayer*, _energyPlayer); + DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::HeightPlayer*, _heightPlayer); + DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::MultiplierPlayer*, _multiplierPlayer); + DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::NotePlayer*, _notePlayer); + DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::PosePlayer*, _posePlayer); + DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::ScorePlayer*, _scorePlayer); + DECLARE_INSTANCE_FIELD_PRIVATE(bool, _paused); -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Playback, ReplayTimeSyncController, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Playback", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioManagerSO); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::AudioTimeSyncController::InitData*, _audioInitData); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BasicBeatmapObjectManager*, _basicBeatmapObjectManager); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _noteCutSoundEffectManager); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapCallbacksController::InitData*, _callbackInitData); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapCallbacksController*, _beatmapObjectCallbackController); - DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::ComboPlayer*, _comboPlayer); - DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::EnergyPlayer*, _energyPlayer); - DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::HeightPlayer*, _heightPlayer); - DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::MultiplierPlayer*, _multiplierPlayer); - DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::NotePlayer*, _notePlayer); - DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::PosePlayer*, _posePlayer); - DECLARE_INSTANCE_FIELD_PRIVATE(ScoreSaber::ReplaySystem::Playback::ScorePlayer*, _scorePlayer); - DECLARE_INSTANCE_FIELD_PRIVATE(bool, _paused); + DECLARE_CTOR(ctor, + GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, + GlobalNamespace::AudioTimeSyncController::InitData* audioInitData, + GlobalNamespace::BasicBeatmapObjectManager* basicBeatmapObjectManager, + GlobalNamespace::NoteCutSoundEffectManager* _noteCutSoundEffectManager, + GlobalNamespace::BeatmapCallbacksController::InitData* callbackInitData, + GlobalNamespace::BeatmapCallbacksController* beatmapObjectCallbackController, + Zenject::DiContainer* container); - DECLARE_CTOR(ctor, - GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, - GlobalNamespace::AudioTimeSyncController::InitData* audioInitData, - GlobalNamespace::BasicBeatmapObjectManager* basicBeatmapObjectManager, - GlobalNamespace::NoteCutSoundEffectManager* _noteCutSoundEffectManager, - GlobalNamespace::BeatmapCallbacksController::InitData* callbackInitData, - GlobalNamespace::BeatmapCallbacksController* beatmapObjectCallbackController, - Zenject::DiContainer* container); - - DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - DECLARE_INSTANCE_METHOD(void, UpdateTimes); - DECLARE_INSTANCE_METHOD(void, OverrideTime, float time); - DECLARE_INSTANCE_METHOD(void, OverrideTimeScale, float timeScale); - DECLARE_INSTANCE_METHOD(void, CancelAllHitSounds);) - -#undef INTERFACES + DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + DECLARE_INSTANCE_METHOD(void, UpdateTimes); + DECLARE_INSTANCE_METHOD(void, OverrideTime, float time); + DECLARE_INSTANCE_METHOD(void, OverrideTimeScale, float timeScale); + DECLARE_INSTANCE_METHOD(void, CancelAllHitSounds); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Playback/ScorePlayer.hpp b/include/ReplaySystem/Playback/ScorePlayer.hpp index fe5f9723..5fe177e7 100644 --- a/include/ReplaySystem/Playback/ScorePlayer.hpp +++ b/include/ReplaySystem/Playback/ScorePlayer.hpp @@ -1,6 +1,7 @@ #pragma once #include "Data/Private/ReplayFile.hpp" +#include "System/zzzz__Object_def.hpp" #include #include #include @@ -10,23 +11,21 @@ #include #include -#define INTERFACES \ - { \ - classof(Zenject::ITickable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Playback, ScorePlayer, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Playback", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(int, _nextIndex); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _scoreController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyCounter); - DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::ScoreController* scoreController, GlobalNamespace::GameEnergyCounter* gameEnergyCounter); - DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); - vector _sortedNoteEvents; - vector _sortedScoreEvents; - void UpdateScore(int newScore, std::optional immediateMaxPossibleScore, float time); - void UpdateMultiplier(); - int CalculatePostNoteCountForTime(float time);) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Playback, + ScorePlayer, + System::Object, + Zenject::ITickable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(int, _nextIndex); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _scoreController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyCounter); + DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::ScoreController* scoreController, GlobalNamespace::GameEnergyCounter* gameEnergyCounter); + DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); + vector _sortedNoteEvents; + vector _sortedScoreEvents; + void UpdateScore(int newScore, std::optional immediateMaxPossibleScore, float time); + void UpdateMultiplier(); + int CalculatePostNoteCountForTime(float time); +}; diff --git a/include/ReplaySystem/Recorders/EnergyEventRecorder.hpp b/include/ReplaySystem/Recorders/EnergyEventRecorder.hpp index 14de820b..d1ed10c5 100644 --- a/include/ReplaySystem/Recorders/EnergyEventRecorder.hpp +++ b/include/ReplaySystem/Recorders/EnergyEventRecorder.hpp @@ -11,24 +11,20 @@ #include #include "Utils/DelegateUtils.hpp" -using namespace GlobalNamespace; - -#define INTERFACES \ - { \ - classof(System::IDisposable*), classof(Zenject::IInitializable*), \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Recorders, EnergyEventRecorder, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Recorders", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyCounter); - DECLARE_CTOR(ctor, AudioTimeSyncController* audioTimeSyncController, GameEnergyCounter* gameEnergyCounter); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, GameEnergyCounter_gameEnergyDidChangeEvent, float energy); - std::vector _energyKeyframes; - DelegateUtils::DelegateW> gameEnergyDidChangeDelegate; - public: - std::vector Export(); - ) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Recorders, + EnergyEventRecorder, + System::Object, + System::IDisposable*, + Zenject::IInitializable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyCounter); + DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::GameEnergyCounter* gameEnergyCounter); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, GameEnergyCounter_gameEnergyDidChangeEvent, float energy); + std::vector _energyKeyframes; + DelegateUtils::DelegateW> gameEnergyDidChangeDelegate; +public: + std::vector Export(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Recorders/HeightEventRecorder.hpp b/include/ReplaySystem/Recorders/HeightEventRecorder.hpp index f98839e7..9284a6b9 100644 --- a/include/ReplaySystem/Recorders/HeightEventRecorder.hpp +++ b/include/ReplaySystem/Recorders/HeightEventRecorder.hpp @@ -11,24 +11,20 @@ #include #include -using namespace GlobalNamespace; - -#define INTERFACES \ - { \ - classof(System::IDisposable*), classof(Zenject::IInitializable*), \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Recorders, HeightEventRecorder, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Recorders", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _playerHeightDetector); - DECLARE_CTOR(ctor, AudioTimeSyncController* audioTimeSyncController, Zenject::DiContainer* container); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, PlayerHeightDetector_playerHeightDidChangeEvent, float newHeight); - std::vector _heightKeyframes; - DelegateUtils::DelegateW> playerHeightDidChangeDelegate; - public: - std::vector Export(); - ) - -#undef INTERFACES \ No newline at end of file +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Recorders, + HeightEventRecorder, + System::Object, + System::IDisposable*, + Zenject::IInitializable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _playerHeightDetector); + DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, Zenject::DiContainer* container); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, PlayerHeightDetector_playerHeightDidChangeEvent, float newHeight); + std::vector _heightKeyframes; + DelegateUtils::DelegateW> playerHeightDidChangeDelegate; +public: + std::vector Export(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Recorders/MainRecorder.hpp b/include/ReplaySystem/Recorders/MainRecorder.hpp index 0293043d..9460d350 100644 --- a/include/ReplaySystem/Recorders/MainRecorder.hpp +++ b/include/ReplaySystem/Recorders/MainRecorder.hpp @@ -13,24 +13,22 @@ #include #include -#define INTERFACES \ - { \ - classof(System::IDisposable*), classof(Zenject::IInitializable*), \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Recorders, MainRecorder, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Recorders", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(PoseRecorder*, _poseRecorder); - DECLARE_INSTANCE_FIELD_PRIVATE(MetadataRecorder*, _metadataRecorder); - DECLARE_INSTANCE_FIELD_PRIVATE(NoteEventRecorder*, _noteEventRecorder); - DECLARE_INSTANCE_FIELD_PRIVATE(ScoreEventRecorder*, _scoreEventRecorder); - DECLARE_INSTANCE_FIELD_PRIVATE(HeightEventRecorder*, _heightEventRecorder); - DECLARE_INSTANCE_FIELD_PRIVATE(EnergyEventRecorder*, _energyEventRecorder); - DECLARE_CTOR(ctor, PoseRecorder* poseRecorder, MetadataRecorder* metadataRecorder, NoteEventRecorder* noteEventRecorder, ScoreEventRecorder* scoreEventRecorder, HeightEventRecorder* heightEventRecorder, EnergyEventRecorder* energyEventRecorder); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - public: - std::shared_ptr ExportCurrentReplay(); - void StopRecording(); - ) - -#undef INTERFACES \ No newline at end of file +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Recorders, + MainRecorder, + System::Object, + System::IDisposable*, + Zenject::IInitializable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(PoseRecorder*, _poseRecorder); + DECLARE_INSTANCE_FIELD_PRIVATE(MetadataRecorder*, _metadataRecorder); + DECLARE_INSTANCE_FIELD_PRIVATE(NoteEventRecorder*, _noteEventRecorder); + DECLARE_INSTANCE_FIELD_PRIVATE(ScoreEventRecorder*, _scoreEventRecorder); + DECLARE_INSTANCE_FIELD_PRIVATE(HeightEventRecorder*, _heightEventRecorder); + DECLARE_INSTANCE_FIELD_PRIVATE(EnergyEventRecorder*, _energyEventRecorder); + DECLARE_CTOR(ctor, PoseRecorder* poseRecorder, MetadataRecorder* metadataRecorder, NoteEventRecorder* noteEventRecorder, ScoreEventRecorder* scoreEventRecorder, HeightEventRecorder* heightEventRecorder, EnergyEventRecorder* energyEventRecorder); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); +public: + std::shared_ptr ExportCurrentReplay(); + void StopRecording(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Recorders/MetadataRecorder.hpp b/include/ReplaySystem/Recorders/MetadataRecorder.hpp index 0778296f..34bf30de 100644 --- a/include/ReplaySystem/Recorders/MetadataRecorder.hpp +++ b/include/ReplaySystem/Recorders/MetadataRecorder.hpp @@ -2,7 +2,7 @@ #include "Data/Private/ReplayFile.hpp" #include "Utils/DelegateUtils.hpp" -#include +#include #include #include #include @@ -14,27 +14,23 @@ #include #include "Utils/DelegateUtils.hpp" -using namespace GlobalNamespace; - -#define INTERFACES \ - { \ - classof(System::IDisposable*), classof(Zenject::IInitializable*), \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Recorders, MetadataRecorder, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Recorders", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(BeatmapObjectSpawnController::InitData*, _beatmapObjectSpawnControllerInitData); - DECLARE_INSTANCE_FIELD_PRIVATE(GameplayCoreSceneSetupData*, _gameplayCoreSceneSetupData); - DECLARE_INSTANCE_FIELD_PRIVATE(BeatSaber::GameSettings::MainSettingsHandler*, _mainSettingsHandler); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyCounter); - DECLARE_CTOR(ctor, AudioTimeSyncController* audioTimeSyncController, GameplayCoreSceneSetupData* gameplayCoreSceneSetupData, BeatmapObjectSpawnController::InitData* beatmapObjectSpawnControllerInitData, GameEnergyCounter* gameEnergyCounter, BeatSaber::GameSettings::MainSettingsHandler* mainSettingsHandler); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, GameEnergyCounter_gameEnergyDidReach0Event); - float _failTime; - DelegateUtils::DelegateW gameEnergyDidReach0Delegate; - public: - std::shared_ptr Export(); - ) - -#undef INTERFACES \ No newline at end of file +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Recorders, + MetadataRecorder, + System::Object, + System::IDisposable*, + Zenject::IInitializable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapObjectSpawnController::InitData*, _beatmapObjectSpawnControllerInitData); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::GameplayCoreSceneSetupData*, _gameplayCoreSceneSetupData); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::SettingsManager*, _settingsManager); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyCounter); + DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::GameplayCoreSceneSetupData* gameplayCoreSceneSetupData, GlobalNamespace::BeatmapObjectSpawnController::InitData* beatmapObjectSpawnControllerInitData, GlobalNamespace::GameEnergyCounter* gameEnergyCounter, GlobalNamespace::SettingsManager* settingsManager); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, GameEnergyCounter_gameEnergyDidReach0Event); + float _failTime; + DelegateUtils::DelegateW gameEnergyDidReach0Delegate; +public: + std::shared_ptr Export(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Recorders/NoteEventRecorder.hpp b/include/ReplaySystem/Recorders/NoteEventRecorder.hpp index d09ef0a0..f5552c08 100644 --- a/include/ReplaySystem/Recorders/NoteEventRecorder.hpp +++ b/include/ReplaySystem/Recorders/NoteEventRecorder.hpp @@ -16,33 +16,27 @@ #include #include "Utils/DelegateUtils.hpp" -using namespace UnityEngine; -using namespace GlobalNamespace; - - -#define INTERFACES \ - { \ - classof(System::IDisposable*), classof(Zenject::IInitializable*), \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Recorders, NoteEventRecorder, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Recorders", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _scoreController); - DECLARE_INSTANCE_FIELD_PRIVATE(BeatmapObjectManager*, _beatmapObjectManager); - DECLARE_CTOR(ctor, AudioTimeSyncController* audioTimeSyncController, ScoreController* scoreController, BeatmapObjectManager* beatmapObjectManager); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, ScoreController_scoringForNoteStartedEvent, ScoringElement* element); - DECLARE_INSTANCE_METHOD(void, ScoreController_scoringForNoteFinishedEvent, ScoringElement* element); - DECLARE_INSTANCE_METHOD(void, BadCutInfoCollector, NoteController* noteController, ByRef noteCutInfo); - std::vector _noteKeyframes; - std::map _collectedBadCutInfos; - std::map _scoringStartInfo; - DelegateUtils::DelegateW> scoringForNoteStartedDelegate; - DelegateUtils::DelegateW> scoringForNoteFinishedDelegate; - DelegateUtils::DelegateW handleNoteWasCutDelegate; - public: - std::vector Export(); - ) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Recorders, + NoteEventRecorder, + System::Object, + System::IDisposable*, + Zenject::IInitializable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _scoreController); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapObjectManager*, _beatmapObjectManager); + DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::ScoreController* scoreController, GlobalNamespace::BeatmapObjectManager* beatmapObjectManager); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, ScoreController_scoringForNoteStartedEvent, GlobalNamespace::ScoringElement* element); + DECLARE_INSTANCE_METHOD(void, ScoreController_scoringForNoteFinishedEvent, GlobalNamespace::ScoringElement* element); + DECLARE_INSTANCE_METHOD(void, BadCutInfoCollector, GlobalNamespace::NoteController* noteController, ByRef noteCutInfo); + std::vector _noteKeyframes; + std::map _collectedBadCutInfos; + std::map _scoringStartInfo; + DelegateUtils::DelegateW> scoringForNoteStartedDelegate; + DelegateUtils::DelegateW> scoringForNoteFinishedDelegate; + DelegateUtils::DelegateW handleNoteWasCutDelegate; +public: + std::vector Export(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Recorders/PoseRecorder.hpp b/include/ReplaySystem/Recorders/PoseRecorder.hpp index 32070844..ff294351 100644 --- a/include/ReplaySystem/Recorders/PoseRecorder.hpp +++ b/include/ReplaySystem/Recorders/PoseRecorder.hpp @@ -11,24 +11,18 @@ #include #include -using namespace GlobalNamespace; -using namespace UnityEngine; - -#define INTERFACES \ - { \ - classof(Zenject::ITickable*), \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Recorders, PoseRecorder, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Recorders", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _playerTransforms); - DECLARE_CTOR(ctor, AudioTimeSyncController* audioTimeSyncController, PlayerTransforms* playerTransforms); - DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - std::vector _vrPoseGroup; - volatile bool _recording; - public: - std::vector Export(); - void StopRecording(); - ) - -#undef INTERFACES \ No newline at end of file +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Recorders, + PoseRecorder, + System::Object, + Zenject::ITickable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _playerTransforms); + DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::PlayerTransforms* playerTransforms); + DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + std::vector _vrPoseGroup; + volatile bool _recording; +public: + std::vector Export(); + void StopRecording(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/Recorders/ScoreEventRecorder.hpp b/include/ReplaySystem/Recorders/ScoreEventRecorder.hpp index 572ddcc6..5aca2b41 100644 --- a/include/ReplaySystem/Recorders/ScoreEventRecorder.hpp +++ b/include/ReplaySystem/Recorders/ScoreEventRecorder.hpp @@ -11,34 +11,29 @@ #include #include "Utils/DelegateUtils.hpp" -using namespace UnityEngine; -using namespace GlobalNamespace; - -#define INTERFACES \ - { \ - classof(System::IDisposable*), classof(Zenject::IInitializable*), \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::Recorders, ScoreEventRecorder, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::Recorders", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _scoreController); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _comboController); - DECLARE_CTOR(ctor, AudioTimeSyncController* audioTimeSyncController, ScoreController* scoreController, ComboController* comboController); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, ComboController_comboDidChangeEvent, int combo); - DECLARE_INSTANCE_METHOD(void, ScoreController_scoreDidChangeEvent, int rawScore, int score); - DECLARE_INSTANCE_METHOD(void, ScoreController_multiplierDidChangeEvent, int multiplier, float nextMultiplierProgress); - std::vector _scoreKeyFrames; - std::vector _comboKeyFrames; - std::vector _multiplierKeyFrames; - DelegateUtils::DelegateW> comboDidChangeDelegate; - DelegateUtils::DelegateW> scoreDidChangeDelegate; - DelegateUtils::DelegateW> multiplierDidChangeDelegate; - public: - std::vector ExportScoreKeyframes(); - std::vector ExportComboKeyframes(); - std::vector ExportMultiplierKeyframes(); - ) - -#undef INTERFACES \ No newline at end of file +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::Recorders, + ScoreEventRecorder, + System::Object, + System::IDisposable*, + Zenject::IInitializable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _scoreController); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _comboController); + DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::ScoreController* scoreController, GlobalNamespace::ComboController* comboController); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, ComboController_comboDidChangeEvent, int combo); + DECLARE_INSTANCE_METHOD(void, ScoreController_scoreDidChangeEvent, int rawScore, int score); + DECLARE_INSTANCE_METHOD(void, ScoreController_multiplierDidChangeEvent, int multiplier, float nextMultiplierProgress); + std::vector _scoreKeyFrames; + std::vector _comboKeyFrames; + std::vector _multiplierKeyFrames; + DelegateUtils::DelegateW> comboDidChangeDelegate; + DelegateUtils::DelegateW> scoreDidChangeDelegate; + DelegateUtils::DelegateW> multiplierDidChangeDelegate; +public: + std::vector ExportScoreKeyframes(); + std::vector ExportComboKeyframes(); + std::vector ExportMultiplierKeyframes(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/Components/AmeBar.hpp b/include/ReplaySystem/UI/Components/AmeBar.hpp index 03861fe6..609eddec 100644 --- a/include/ReplaySystem/UI/Components/AmeBar.hpp +++ b/include/ReplaySystem/UI/Components/AmeBar.hpp @@ -10,23 +10,24 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI::Components, AmeBar, UnityEngine::MonoBehaviour, - DECLARE_INSTANCE_FIELD(UnityW, _rectTransform); - DECLARE_INSTANCE_FIELD(UnityW, _fillBarTransform); - DECLARE_INSTANCE_FIELD(UnityW, _endTimeText); - DECLARE_INSTANCE_FIELD(UnityW, _currentTimeText); - DECLARE_INSTANCE_FIELD(UnityW, _otherTransform); - DECLARE_INSTANCE_METHOD(void, Setup, UnityEngine::RectTransform* fillBarTransform, UnityEngine::RectTransform* otherTransform); - DECLARE_INSTANCE_METHOD(void, RegisterNode, ScoreSaber::ReplaySystem::UI::Components::AmeNode* node); - DECLARE_INSTANCE_METHOD(void, UnregisterNode, ScoreSaber::ReplaySystem::UI::Components::AmeNode* node); - DECLARE_INSTANCE_METHOD(float, GetNodePercent, ScoreSaber::ReplaySystem::UI::Components::AmeNode* node); - DECLARE_INSTANCE_METHOD(void, AssignNodeToPercent, ScoreSaber::ReplaySystem::UI::Components::AmeNode* node, float percent); - DECLARE_INSTANCE_METHOD(void, set_currentTime, float value); - DECLARE_INSTANCE_METHOD(void, set_endTime, float value); - DECLARE_INSTANCE_METHOD(void, set_barFill, float value); - DECLARE_INSTANCE_METHOD(float, get_barFill); - DECLARE_INSTANCE_METHOD(float, XForPercent, float percent); - DECLARE_INSTANCE_METHOD(float, PercentForX, float x); - DECLARE_DEFAULT_CTOR(); - void DragCallback(ScoreSaber::ReplaySystem::UI::Components::AmeNode* node, UnityEngine::Vector2 x, UnityEngine::Camera* camera); - HMUI::CurvedTextMeshPro * CreateText();) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI::Components, AmeBar, UnityEngine::MonoBehaviour) { + DECLARE_INSTANCE_FIELD(UnityW, _rectTransform); + DECLARE_INSTANCE_FIELD(UnityW, _fillBarTransform); + DECLARE_INSTANCE_FIELD(UnityW, _endTimeText); + DECLARE_INSTANCE_FIELD(UnityW, _currentTimeText); + DECLARE_INSTANCE_FIELD(UnityW, _otherTransform); + DECLARE_INSTANCE_METHOD(void, Setup, UnityEngine::RectTransform* fillBarTransform, UnityEngine::RectTransform* otherTransform); + DECLARE_INSTANCE_METHOD(void, RegisterNode, ScoreSaber::ReplaySystem::UI::Components::AmeNode* node); + DECLARE_INSTANCE_METHOD(void, UnregisterNode, ScoreSaber::ReplaySystem::UI::Components::AmeNode* node); + DECLARE_INSTANCE_METHOD(float, GetNodePercent, ScoreSaber::ReplaySystem::UI::Components::AmeNode* node); + DECLARE_INSTANCE_METHOD(void, AssignNodeToPercent, ScoreSaber::ReplaySystem::UI::Components::AmeNode* node, float percent); + DECLARE_INSTANCE_METHOD(void, set_currentTime, float value); + DECLARE_INSTANCE_METHOD(void, set_endTime, float value); + DECLARE_INSTANCE_METHOD(void, set_barFill, float value); + DECLARE_INSTANCE_METHOD(float, get_barFill); + DECLARE_INSTANCE_METHOD(float, XForPercent, float percent); + DECLARE_INSTANCE_METHOD(float, PercentForX, float x); + DECLARE_DEFAULT_CTOR(); + void DragCallback(ScoreSaber::ReplaySystem::UI::Components::AmeNode* node, UnityEngine::Vector2 x, UnityEngine::Camera* camera); + HMUI::CurvedTextMeshPro * CreateText(); +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/Components/AmeClicker.hpp b/include/ReplaySystem/UI/Components/AmeClicker.hpp index 92b6a1a3..77d58dc0 100644 --- a/include/ReplaySystem/UI/Components/AmeClicker.hpp +++ b/include/ReplaySystem/UI/Components/AmeClicker.hpp @@ -7,17 +7,15 @@ #include #include -#define INTERFACES \ - { \ - classof(UnityEngine::EventSystems::IPointerClickHandler*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::UI::Components, AmeClicker, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, UnityEngine::MonoBehaviour, "ScoreSaber::ReplaySystem::UI::Components", INTERFACES, 0, nullptr, - DECLARE_DEFAULT_CTOR(); - DECLARE_INSTANCE_FIELD(UnityW, _rect); - DECLARE_OVERRIDE_METHOD_MATCH(void, OnPointerClick, &::UnityEngine::EventSystems::IPointerClickHandler::OnPointerClick, UnityEngine::EventSystems::PointerEventData* eventData); - std::function _clickCallback; - public - : void Setup(std::function callback);) - -#undef INTERFACES \ No newline at end of file +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::UI::Components, + AmeClicker, + UnityEngine::MonoBehaviour, + UnityEngine::EventSystems::IPointerClickHandler*) { + DECLARE_DEFAULT_CTOR(); + DECLARE_INSTANCE_FIELD(UnityW, _rect); + DECLARE_OVERRIDE_METHOD_MATCH(void, OnPointerClick, &UnityEngine::EventSystems::IPointerClickHandler::OnPointerClick, UnityEngine::EventSystems::PointerEventData* eventData); + std::function _clickCallback; +public: + void Setup(std::function callback); +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/Components/AmeHandle.hpp b/include/ReplaySystem/UI/Components/AmeHandle.hpp index a320434c..62097cc3 100644 --- a/include/ReplaySystem/UI/Components/AmeHandle.hpp +++ b/include/ReplaySystem/UI/Components/AmeHandle.hpp @@ -13,19 +13,22 @@ #include #include -#define INTERFACES \ - { \ - classof(UnityEngine::EventSystems::IBeginDragHandler*), classof(UnityEngine::EventSystems::IDragHandler*), classof(UnityEngine::EventSystems::IEventSystemHandler*), classof(UnityEngine::EventSystems::IInitializePotentialDragHandler*), classof(UnityEngine::EventSystems::IEndDragHandler*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::UI::Components, AmeHandle, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, UnityEngine::MonoBehaviour, "ScoreSaber::ReplaySystem::UI::Components", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD(bool, dragged); - DECLARE_OVERRIDE_METHOD_MATCH(void, OnBeginDrag, &::UnityEngine::EventSystems::IBeginDragHandler::OnBeginDrag, UnityEngine::EventSystems::PointerEventData* eventData); - DECLARE_OVERRIDE_METHOD_MATCH(void, OnInitializePotentialDrag, &::UnityEngine::EventSystems::IInitializePotentialDragHandler::OnInitializePotentialDrag, UnityEngine::EventSystems::PointerEventData* eventData); - DECLARE_OVERRIDE_METHOD_MATCH(void, OnDrag, &::UnityEngine::EventSystems::IDragHandler::OnDrag, UnityEngine::EventSystems::PointerEventData* eventData); - DECLARE_OVERRIDE_METHOD_MATCH(void, OnEndDrag, &::UnityEngine::EventSystems::IEndDragHandler::OnEndDrag, UnityEngine::EventSystems::PointerEventData* eventData); - DECLARE_DEFAULT_CTOR(); - public - : void AddCallback(std::function callback); - std::function _handleMoveCallback;) -#undef INTERFACES \ No newline at end of file +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::UI::Components, + AmeHandle, + UnityEngine::MonoBehaviour, + UnityEngine::EventSystems::IBeginDragHandler*, + UnityEngine::EventSystems::IDragHandler*, + UnityEngine::EventSystems::IEventSystemHandler*, + UnityEngine::EventSystems::IInitializePotentialDragHandler*, + UnityEngine::EventSystems::IEndDragHandler*) { + DECLARE_INSTANCE_FIELD(bool, dragged); + DECLARE_OVERRIDE_METHOD_MATCH(void, OnBeginDrag, &::UnityEngine::EventSystems::IBeginDragHandler::OnBeginDrag, UnityEngine::EventSystems::PointerEventData* eventData); + DECLARE_OVERRIDE_METHOD_MATCH(void, OnInitializePotentialDrag, &::UnityEngine::EventSystems::IInitializePotentialDragHandler::OnInitializePotentialDrag, UnityEngine::EventSystems::PointerEventData* eventData); + DECLARE_OVERRIDE_METHOD_MATCH(void, OnDrag, &::UnityEngine::EventSystems::IDragHandler::OnDrag, UnityEngine::EventSystems::PointerEventData* eventData); + DECLARE_OVERRIDE_METHOD_MATCH(void, OnEndDrag, &::UnityEngine::EventSystems::IEndDragHandler::OnEndDrag, UnityEngine::EventSystems::PointerEventData* eventData); + DECLARE_DEFAULT_CTOR(); +public: + void AddCallback(std::function callback); + std::function _handleMoveCallback; +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/Components/AmeNode.hpp b/include/ReplaySystem/UI/Components/AmeNode.hpp index bae96cb9..4e98a8bb 100644 --- a/include/ReplaySystem/UI/Components/AmeNode.hpp +++ b/include/ReplaySystem/UI/Components/AmeNode.hpp @@ -7,18 +7,19 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI::Components, AmeNode, UnityEngine::MonoBehaviour, - DECLARE_INSTANCE_FIELD(UnityW, _rectTransform); - DECLARE_INSTANCE_FIELD_DEFAULT(bool, moveable, true); - DECLARE_INSTANCE_FIELD_DEFAULT(float, min, 0.0f); - DECLARE_INSTANCE_FIELD_DEFAULT(float, max, 1.0f); - DECLARE_INSTANCE_FIELD(UnityW, _handle); - DECLARE_INSTANCE_METHOD(bool, get_isBeingDragged); - DECLARE_INSTANCE_METHOD(void, Init, ScoreSaber::ReplaySystem::UI::Components::AmeHandle* handle); - DECLARE_INSTANCE_METHOD(void, Callback, ScoreSaber::ReplaySystem::UI::Components::AmeHandle* handle, UnityEngine::Vector2 x, UnityEngine::Camera* camera); - DECLARE_INSTANCE_METHOD(void, SendUpdatePositionCall, float percentOnBar); - DECLARE_DEFAULT_CTOR(); - std::function _callback; - public - : void AddCallback(std::function callback); - std::function PositionDidChange;) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI::Components, AmeNode, UnityEngine::MonoBehaviour) { + DECLARE_INSTANCE_FIELD(UnityW, _rectTransform); + DECLARE_INSTANCE_FIELD_DEFAULT(bool, moveable, true); + DECLARE_INSTANCE_FIELD_DEFAULT(float, min, 0.0f); + DECLARE_INSTANCE_FIELD_DEFAULT(float, max, 1.0f); + DECLARE_INSTANCE_FIELD(UnityW, _handle); + DECLARE_INSTANCE_METHOD(bool, get_isBeingDragged); + DECLARE_INSTANCE_METHOD(void, Init, ScoreSaber::ReplaySystem::UI::Components::AmeHandle* handle); + DECLARE_INSTANCE_METHOD(void, Callback, ScoreSaber::ReplaySystem::UI::Components::AmeHandle* handle, UnityEngine::Vector2 x, UnityEngine::Camera* camera); + DECLARE_INSTANCE_METHOD(void, SendUpdatePositionCall, float percentOnBar); + DECLARE_DEFAULT_CTOR(); + std::function _callback; +public: + void AddCallback(std::function callback); + std::function PositionDidChange; +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/GameReplayUI.hpp b/include/ReplaySystem/UI/GameReplayUI.hpp index 4725f672..535777fc 100644 --- a/include/ReplaySystem/UI/GameReplayUI.hpp +++ b/include/ReplaySystem/UI/GameReplayUI.hpp @@ -9,10 +9,11 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI, GameReplayUI, UnityEngine::MonoBehaviour, - DECLARE_INSTANCE_FIELD(GlobalNamespace::GameplayCoreSceneSetupData*, _gameplayCoreSceneSetupData); - DECLARE_INSTANCE_METHOD(void, Start); - DECLARE_CTOR(ctor, GlobalNamespace::GameplayCoreSceneSetupData* gameplayCoreSceneSetupData); - void CreateReplayUI(); - TMPro::TextMeshProUGUI* CreateText(UnityEngine::RectTransform* parent, StringW text, UnityEngine::Vector2 anchoredPosition, UnityEngine::Vector2 sizeDelta, float fontSize); - std::string GetFriendlyDifficulty(GlobalNamespace::BeatmapDifficulty diff);) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI, GameReplayUI, UnityEngine::MonoBehaviour) { + DECLARE_INSTANCE_FIELD(GlobalNamespace::GameplayCoreSceneSetupData*, _gameplayCoreSceneSetupData); + DECLARE_INSTANCE_METHOD(void, Start); + DECLARE_CTOR(ctor, GlobalNamespace::GameplayCoreSceneSetupData* gameplayCoreSceneSetupData); + void CreateReplayUI(); + TMPro::TextMeshProUGUI* CreateText(UnityEngine::RectTransform* parent, StringW text, UnityEngine::Vector2 anchoredPosition, UnityEngine::Vector2 sizeDelta, float fontSize); + std::string GetFriendlyDifficulty(GlobalNamespace::BeatmapDifficulty diff); +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/ImberManager.hpp b/include/ReplaySystem/UI/ImberManager.hpp index 6f6d7a89..f242f8af 100644 --- a/include/ReplaySystem/UI/ImberManager.hpp +++ b/include/ReplaySystem/UI/ImberManager.hpp @@ -21,60 +21,57 @@ #include #include "Utils/DelegateUtils.hpp" -#define INTERFACES \ - { \ - classof(Zenject::IInitializable*), classof(::System::IDisposable*) \ - } +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::UI, + ImberManager, + System::Object, + Zenject::IInitializable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD(float, _initialTimeScale); + DECLARE_INSTANCE_FIELD(GlobalNamespace::GamePause*, _gamePause); + DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::UI::ImberScrubber*, _imberScrubber); + DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::UI::ImberSpecsReporter*, _imberSpecsReporter); + DECLARE_INSTANCE_FIELD(UnityW, _mainImberPanelView); + DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::UI::SpectateAreaController*, _spectateAreaController); + DECLARE_INSTANCE_FIELD(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::Playback::ReplayTimeSyncController*, _replayTimeSyncController); + DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::UI::ImberUIPositionController*, _imberUIPositionController); + DECLARE_INSTANCE_FIELD(GlobalNamespace::AudioTimeSyncController::InitData*, _initData); + DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::Playback::PosePlayer*, _posePlayer); -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::UI, ImberManager, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::UI", INTERFACES, 0, nullptr, + DECLARE_CTOR(ctor, + GlobalNamespace::IGamePause* gamePause, + ScoreSaber::ReplaySystem::UI::ImberScrubber* imberScrubber, + ScoreSaber::ReplaySystem::UI::ImberSpecsReporter* imberSpecsReporter, + ScoreSaber::ReplaySystem::UI::MainImberPanelView* mainImberPanelView, + ScoreSaber::ReplaySystem::UI::SpectateAreaController* spectateAreaController, + GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, + ScoreSaber::ReplaySystem::Playback::ReplayTimeSyncController* replayTimeSyncController, + ScoreSaber::ReplaySystem::UI::ImberUIPositionController* imberUIPositionController, + GlobalNamespace::AudioTimeSyncController::InitData* initData, + ScoreSaber::ReplaySystem::Playback::PosePlayer* posePlayer); - DECLARE_INSTANCE_FIELD(float, _initialTimeScale); - DECLARE_INSTANCE_FIELD(GlobalNamespace::GamePause*, _gamePause); - DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::UI::ImberScrubber*, _imberScrubber); - DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::UI::ImberSpecsReporter*, _imberSpecsReporter); - DECLARE_INSTANCE_FIELD(UnityW, _mainImberPanelView); - DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::UI::SpectateAreaController*, _spectateAreaController); - DECLARE_INSTANCE_FIELD(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::Playback::ReplayTimeSyncController*, _replayTimeSyncController); - DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::UI::ImberUIPositionController*, _imberUIPositionController); - DECLARE_INSTANCE_FIELD(GlobalNamespace::AudioTimeSyncController::InitData*, _initData); - DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::Playback::PosePlayer*, _posePlayer); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_CTOR(ctor, GlobalNamespace::IGamePause* gamePause, - ScoreSaber::ReplaySystem::UI::ImberScrubber* imberScrubber, - ScoreSaber::ReplaySystem::UI::ImberSpecsReporter* imberSpecsReporter, - ScoreSaber::ReplaySystem::UI::MainImberPanelView* mainImberPanelView, - ScoreSaber::ReplaySystem::UI::SpectateAreaController* spectateAreaController, - GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, - ScoreSaber::ReplaySystem::Playback::ReplayTimeSyncController* replayTimeSyncController, - ScoreSaber::ReplaySystem::UI::ImberUIPositionController* imberUIPositionController, - GlobalNamespace::AudioTimeSyncController::InitData* initData, - ScoreSaber::ReplaySystem::Playback::PosePlayer* posePlayer); + DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidHandSwitchEvent, UnityEngine::XR::XRNode hand); + DECLARE_INSTANCE_METHOD(void, GamePause_didResumeEvent); + DECLARE_INSTANCE_METHOD(void, ImberSpecsReporter_DidReport, int fps, float leftSaberSpeed, float rightSaberSpeed); + DECLARE_INSTANCE_METHOD(void, SpectateAreaController_DidUpdatePlayerSpectatorPose, UnityEngine::Vector3 position, UnityEngine::Quaternion rotation); + DECLARE_INSTANCE_METHOD(void, CreateWatermark); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + // UI Callbacks + DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidPositionTabVisibilityChange, bool value); + DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidPositionPreviewChange, StringW value); + DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidPositionJump); + DECLARE_INSTANCE_METHOD(void, ImberScrubber_DidCalculateNewTime, float time); + DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidClickLoop); + // DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidClickLogo); + DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidClickRestart); + DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidClickPausePlay); + DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidTimeSyncChange, float value); + DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidChangeVisibility, bool value); - DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidHandSwitchEvent, UnityEngine::XR::XRNode hand); - DECLARE_INSTANCE_METHOD(void, GamePause_didResumeEvent); - DECLARE_INSTANCE_METHOD(void, ImberSpecsReporter_DidReport, int fps, float leftSaberSpeed, float rightSaberSpeed); - DECLARE_INSTANCE_METHOD(void, SpectateAreaController_DidUpdatePlayerSpectatorPose, UnityEngine::Vector3 position, UnityEngine::Quaternion rotation); - DECLARE_INSTANCE_METHOD(void, CreateWatermark); - - // UI Callbacks - DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidPositionTabVisibilityChange, bool value); - DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidPositionPreviewChange, StringW value); - DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidPositionJump); - DECLARE_INSTANCE_METHOD(void, ImberScrubber_DidCalculateNewTime, float time); - DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidClickLoop); - // DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidClickLogo); - DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidClickRestart); - DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidClickPausePlay); - DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidTimeSyncChange, float value); - DECLARE_INSTANCE_METHOD(void, MainImberPanelView_DidChangeVisibility, bool value); - - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DelegateUtils::DelegateW _didResumeDelegate; - std::vector _positions; - -) - -#undef INTERFACES + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DelegateUtils::DelegateW _didResumeDelegate; + std::vector _positions; +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/ImberScrubber.hpp b/include/ReplaySystem/UI/ImberScrubber.hpp index 95795df7..a2efefed 100644 --- a/include/ReplaySystem/UI/ImberScrubber.hpp +++ b/include/ReplaySystem/UI/ImberScrubber.hpp @@ -6,9 +6,7 @@ #include #include "ReplaySystem/UI/Components/AmeBar.hpp" #include "ReplaySystem/UI/Components/AmeNode.hpp" - #include - #include #include #include @@ -18,62 +16,58 @@ #include #include -#define INTERFACES \ - { \ - classof(Zenject::ITickable*), classof(Zenject::IInitializable*), classof(::System::IDisposable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::UI, ImberScrubber, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::UI", INTERFACES, 0, nullptr, - // DidCalculateNewTime is at the eof - - DECLARE_INSTANCE_FIELD(UnityEngine::Color, _scoreSaberBlue); - DECLARE_INSTANCE_METHOD(UnityEngine::Transform*, get_transform); - - // loopMode - DECLARE_INSTANCE_FIELD(bool, _loopMode); - DECLARE_INSTANCE_METHOD(void, set_loopMode, bool value); - - DECLARE_INSTANCE_METHOD(void, set_visibility, bool value); - - // mainNodeValue - DECLARE_INSTANCE_METHOD(float, get_mainNodeValue); - DECLARE_INSTANCE_METHOD(void, set_mainNodeValue, float value); - - // "private" fields - - DECLARE_INSTANCE_FIELD(UnityW, _bar); - DECLARE_INSTANCE_FIELD(UnityW, _mainNode); - DECLARE_INSTANCE_FIELD(UnityW, _loopNode); - DECLARE_INSTANCE_FIELD(UnityW, _failNode); - DECLARE_INSTANCE_FIELD(UnityW, _parent); - DECLARE_INSTANCE_FIELD(UnityW, _mainCamera); - DECLARE_INSTANCE_FIELD(Zenject::DiContainer*, _container); - DECLARE_INSTANCE_FIELD_DEFAULT(float, _minNodeDistance, 0.01f); - DECLARE_INSTANCE_FIELD(UnityW, _audioTimeSyncController); - DECLARE_INSTANCE_FIELD_DEFAULT(float, _levelFailTime, 0.0f); - DECLARE_INSTANCE_FIELD_DEFAULT(float, _maxPercent, 1.0f); - DECLARE_INSTANCE_FIELD(bool, _allowPast); - - DECLARE_CTOR(ctor, GlobalNamespace::MainCamera* mainCamera, Zenject::DiContainer* container, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController); - - DECLARE_INSTANCE_METHOD(void, Setup, float levelFailTime, bool allowPast); - - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_INSTANCE_METHOD(void, MainNode_PositionDidChange, float value); - DECLARE_INSTANCE_METHOD(void, LoopNode_PositionDidChange, float value); - - DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - - DECLARE_INSTANCE_METHOD(ScoreSaber::ReplaySystem::UI::Components::AmeBar*, Create, UnityEngine::Camera* camera, UnityEngine::Vector2 size); - DECLARE_INSTANCE_METHOD(void, ClickedBackground, float value); - DECLARE_INSTANCE_METHOD(HMUI::ImageView*, CreateImage, UnityEngine::RectTransform* transform); - DECLARE_INSTANCE_METHOD(ScoreSaber::ReplaySystem::UI::Components::AmeNode*, CreateSlideNode, UnityEngine::RectTransform* transform); - DECLARE_INSTANCE_METHOD(ScoreSaber::ReplaySystem::UI::Components::AmeNode*, CreateTextNode, UnityEngine::RectTransform* transform, StringW initialText, UnityEngine::Color color); - - public: - std::function DidCalculateNewTime; - -) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::UI, + ImberScrubber, + System::Object, + Zenject::ITickable*, + Zenject::IInitializable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD(UnityEngine::Color, _scoreSaberBlue); + DECLARE_INSTANCE_METHOD(UnityEngine::Transform*, get_transform); + + // loopMode + DECLARE_INSTANCE_FIELD(bool, _loopMode); + DECLARE_INSTANCE_METHOD(void, set_loopMode, bool value); + + DECLARE_INSTANCE_METHOD(void, set_visibility, bool value); + + // mainNodeValue + DECLARE_INSTANCE_METHOD(float, get_mainNodeValue); + DECLARE_INSTANCE_METHOD(void, set_mainNodeValue, float value); + + // "private" fields + + DECLARE_INSTANCE_FIELD(UnityW, _bar); + DECLARE_INSTANCE_FIELD(UnityW, _mainNode); + DECLARE_INSTANCE_FIELD(UnityW, _loopNode); + DECLARE_INSTANCE_FIELD(UnityW, _failNode); + DECLARE_INSTANCE_FIELD(UnityW, _parent); + DECLARE_INSTANCE_FIELD(UnityW, _mainCamera); + DECLARE_INSTANCE_FIELD(Zenject::DiContainer*, _container); + DECLARE_INSTANCE_FIELD_DEFAULT(float, _minNodeDistance, 0.01f); + DECLARE_INSTANCE_FIELD(UnityW, _audioTimeSyncController); + DECLARE_INSTANCE_FIELD_DEFAULT(float, _levelFailTime, 0.0f); + DECLARE_INSTANCE_FIELD_DEFAULT(float, _maxPercent, 1.0f); + DECLARE_INSTANCE_FIELD(bool, _allowPast); + + DECLARE_CTOR(ctor, GlobalNamespace::MainCamera* mainCamera, Zenject::DiContainer* container, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController); + + DECLARE_INSTANCE_METHOD(void, Setup, float levelFailTime, bool allowPast); + + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_INSTANCE_METHOD(void, MainNode_PositionDidChange, float value); + DECLARE_INSTANCE_METHOD(void, LoopNode_PositionDidChange, float value); + + DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + + DECLARE_INSTANCE_METHOD(ScoreSaber::ReplaySystem::UI::Components::AmeBar*, Create, UnityEngine::Camera* camera, UnityEngine::Vector2 size); + DECLARE_INSTANCE_METHOD(void, ClickedBackground, float value); + DECLARE_INSTANCE_METHOD(HMUI::ImageView*, CreateImage, UnityEngine::RectTransform* transform); + DECLARE_INSTANCE_METHOD(ScoreSaber::ReplaySystem::UI::Components::AmeNode*, CreateSlideNode, UnityEngine::RectTransform* transform); + DECLARE_INSTANCE_METHOD(ScoreSaber::ReplaySystem::UI::Components::AmeNode*, CreateTextNode, UnityEngine::RectTransform* transform, StringW initialText, UnityEngine::Color color); + +public: + std::function DidCalculateNewTime; +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/ImberSpecsReporter.hpp b/include/ReplaySystem/UI/ImberSpecsReporter.hpp index 58e9216c..eee7a221 100644 --- a/include/ReplaySystem/UI/ImberSpecsReporter.hpp +++ b/include/ReplaySystem/UI/ImberSpecsReporter.hpp @@ -6,7 +6,6 @@ #include "ReplaySystem/UI/Components/AmeBar.hpp" #include "ReplaySystem/UI/Components/AmeNode.hpp" #include - #include #include "ReplaySystem/Playback/PosePlayer.hpp" #include @@ -15,21 +14,18 @@ #include #include -#define INTERFACES \ - { \ - classof(Zenject::IInitializable*), classof(::System::IDisposable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::UI, ImberSpecsReporter, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::UI", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::Playback::PosePlayer*, _posePlayer); - DECLARE_INSTANCE_FIELD(UnityW, _saberManager); - DECLARE_CTOR(ctor, ScoreSaber::ReplaySystem::Playback::PosePlayer* posePlayer, GlobalNamespace::SaberManager* _saberManager); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - public: - void PosePlayer_DidUpdatePose(ScoreSaber::Data::Private::VRPoseGroup pose); - std::function DidReport; - -) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::UI, + ImberSpecsReporter, + System::Object, + Zenject::IInitializable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD(ScoreSaber::ReplaySystem::Playback::PosePlayer*, _posePlayer); + DECLARE_INSTANCE_FIELD(UnityW, _saberManager); + DECLARE_CTOR(ctor, ScoreSaber::ReplaySystem::Playback::PosePlayer* posePlayer, GlobalNamespace::SaberManager* _saberManager); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); +public: + void PosePlayer_DidUpdatePose(ScoreSaber::Data::Private::VRPoseGroup pose); + std::function DidReport; +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/ImberUIPositionController.hpp b/include/ReplaySystem/UI/ImberUIPositionController.hpp index 497bf92a..26355ed2 100644 --- a/include/ReplaySystem/UI/ImberUIPositionController.hpp +++ b/include/ReplaySystem/UI/ImberUIPositionController.hpp @@ -2,13 +2,9 @@ #include "Data/Private/ReplayFile.hpp" #include - #include #include - #include - -#include #include #include #include @@ -30,53 +26,57 @@ #include #include "Utils/DelegateUtils.hpp" -#define INTERFACES \ - { \ - classof(Zenject::ITickable*), classof(Zenject::IInitializable*), classof(::System::IDisposable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::UI, ImberUIPositionController, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::UI", INTERFACES, 0, nullptr, - - DECLARE_INSTANCE_FIELD(bool, _isActive); - DECLARE_INSTANCE_FIELD(bool, _isClicking); - DECLARE_INSTANCE_FIELD(bool, _didClickOnce); - DECLARE_INSTANCE_FIELD(System::DateTime, _lastTriggerDownTime); - DECLARE_INSTANCE_FIELD_DEFAULT(UnityEngine::XR::XRNode, _handTrack, UnityEngine::XR::XRNode::LeftHand); - DECLARE_INSTANCE_FIELD_DEFAULT(float, _senstivityToClick, 0.5f); - DECLARE_INSTANCE_FIELD_DEFAULT(float, _timeBufferToDoubleClick, 0.75f); - DECLARE_INSTANCE_FIELD(GlobalNamespace::GamePause*, _gamePause); - DECLARE_INSTANCE_FIELD(ReplaySystem::UI::ImberScrubber*, _imberScrubber); - DECLARE_INSTANCE_FIELD(UnityW, _mainImberPanelView); - DECLARE_INSTANCE_FIELD(ReplaySystem::UI::VRControllerAccessor*, _vrControllerAccessor); - DECLARE_INSTANCE_FIELD(bool, _isPaused); - - DECLARE_INSTANCE_FIELD(UnityW, _vrGraphicRaycaster); - DECLARE_INSTANCE_FIELD(UnityW, _menuControllerTransform); - DECLARE_INSTANCE_FIELD(UnityW, _menuWrapperTransform); - DECLARE_INSTANCE_FIELD(UnityW, _pauseMenuManagerTransform); - DECLARE_INSTANCE_FIELD(UnityW, _curve); - DECLARE_INSTANCE_FIELD(UnityW, _canvas); - DECLARE_INSTANCE_FIELD(UnityEngine::Vector3, _controllerOffset); +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::UI, + ImberUIPositionController, + System::Object, + Zenject::ITickable*, + Zenject::IInitializable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD(bool, _isActive); + DECLARE_INSTANCE_FIELD(bool, _isClicking); + DECLARE_INSTANCE_FIELD(bool, _didClickOnce); + DECLARE_INSTANCE_FIELD(System::DateTime, _lastTriggerDownTime); + DECLARE_INSTANCE_FIELD_DEFAULT(UnityEngine::XR::XRNode, _handTrack, UnityEngine::XR::XRNode::LeftHand); + DECLARE_INSTANCE_FIELD_DEFAULT(float, _senstivityToClick, 0.5f); + DECLARE_INSTANCE_FIELD_DEFAULT(float, _timeBufferToDoubleClick, 0.75f); + DECLARE_INSTANCE_FIELD(GlobalNamespace::GamePause*, _gamePause); + DECLARE_INSTANCE_FIELD(ReplaySystem::UI::ImberScrubber*, _imberScrubber); + DECLARE_INSTANCE_FIELD(UnityW, _mainImberPanelView); + DECLARE_INSTANCE_FIELD(ReplaySystem::UI::VRControllerAccessor*, _vrControllerAccessor); + DECLARE_INSTANCE_FIELD(bool, _isPaused); - DECLARE_CTOR(ctor, GlobalNamespace::IGamePause* gamePause, ReplaySystem::UI::ImberScrubber* imberScrubber, GlobalNamespace::PauseMenuManager* pauseMenuManager, ReplaySystem::UI::MainImberPanelView* mainImberPanelView, ReplaySystem::UI::VRControllerAccessor* vrControllerAccessor); + DECLARE_INSTANCE_FIELD(UnityW, _vrGraphicRaycaster); + DECLARE_INSTANCE_FIELD(UnityW, _menuControllerTransform); + DECLARE_INSTANCE_FIELD(UnityW, _menuWrapperTransform); + DECLARE_INSTANCE_FIELD(UnityW, _pauseMenuManagerTransform); + DECLARE_INSTANCE_FIELD(UnityW, _curve); + DECLARE_INSTANCE_FIELD(UnityW, _canvas); + DECLARE_INSTANCE_FIELD(UnityEngine::Vector3, _controllerOffset); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_CTOR(ctor, + GlobalNamespace::IGamePause* gamePause, + ReplaySystem::UI::ImberScrubber* imberScrubber, + GlobalNamespace::PauseMenuManager* pauseMenuManager, + ReplaySystem::UI::MainImberPanelView* mainImberPanelView, + ReplaySystem::UI::VRControllerAccessor* vrControllerAccessor); - DECLARE_INSTANCE_METHOD(void, GamePause_didResumeEvent); - DECLARE_INSTANCE_METHOD(void, GamePause_didPauseEvent); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + DECLARE_INSTANCE_METHOD(void, GamePause_didResumeEvent); + DECLARE_INSTANCE_METHOD(void, GamePause_didPauseEvent); - DECLARE_INSTANCE_METHOD(void, SetUIPosition, GlobalNamespace::VRController* controller); - DECLARE_INSTANCE_METHOD(void, OpenedUI); - DECLARE_INSTANCE_METHOD(void, UpdateTrackingHand, UnityEngine::XR::XRNode node); - DECLARE_INSTANCE_METHOD(void, SetActiveState, bool state); - DECLARE_INSTANCE_METHOD(void, SetControllerOffset, UnityEngine::Vector3 offset); + DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DelegateUtils::DelegateW _didResumeDelegate; - DelegateUtils::DelegateW _didPauseDelegate; - public: - custom_types::Helpers::Coroutine KillMe(GlobalNamespace::VRController * controller);) + DECLARE_INSTANCE_METHOD(void, SetUIPosition, GlobalNamespace::VRController* controller); + DECLARE_INSTANCE_METHOD(void, OpenedUI); + DECLARE_INSTANCE_METHOD(void, UpdateTrackingHand, UnityEngine::XR::XRNode node); + DECLARE_INSTANCE_METHOD(void, SetActiveState, bool state); + DECLARE_INSTANCE_METHOD(void, SetControllerOffset, UnityEngine::Vector3 offset); -#undef INTERFACES + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DelegateUtils::DelegateW _didResumeDelegate; + DelegateUtils::DelegateW _didPauseDelegate; +public: + custom_types::Helpers::Coroutine KillMe(GlobalNamespace::VRController * controller); +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/MainImberPanelView.hpp b/include/ReplaySystem/UI/MainImberPanelView.hpp index d9058225..f8db5323 100644 --- a/include/ReplaySystem/UI/MainImberPanelView.hpp +++ b/include/ReplaySystem/UI/MainImberPanelView.hpp @@ -19,65 +19,64 @@ #include #include "Utils/DelegateUtils.hpp" -DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI, MainImberPanelView, HMUI::ViewController, - DECLARE_INSTANCE_FIELD(UnityEngine::Pose, defaultPosition); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _floatingScreen); +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI, MainImberPanelView, HMUI::ViewController) { + DECLARE_INSTANCE_FIELD(UnityEngine::Pose, defaultPosition); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _floatingScreen); - /* Default field values are only set if you INVOKE_CTOR() in your own ctor */ - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(int, _lastTab, 0); - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(int, _targetFPS, 90); - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(int, _initialTime, 1.0f); - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, _goodColor, UnityEngine::Color(0, 1, 0, 1.0f)); - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, _ehColor, UnityEngine::Color(1, 1, 0, 1.0f)); - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, _noColor, UnityEngine::Color(1, 0, 0, 1.0f)); + /* Default field values are only set if you INVOKE_CTOR() in your own ctor */ + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(int, _lastTab, 0); + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(int, _targetFPS, 90); + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(int, _initialTime, 1.0f); + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, _goodColor, UnityEngine::Color(0, 1, 0, 1.0f)); + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, _ehColor, UnityEngine::Color(1, 1, 0, 1.0f)); + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(UnityEngine::Color, _noColor, UnityEngine::Color(1, 0, 0, 1.0f)); - /* Declare BSML property already makes a type _propname; field for you! */ - DECLARE_INSTANCE_METHOD(UnityEngine::Transform*, get_Transform); - DECLARE_INSTANCE_METHOD(void, set_visibility, bool value); - DECLARE_INSTANCE_METHOD(void, set_fps, int value); - DECLARE_INSTANCE_METHOD(void, set_leftSaberSpeed, float value); - DECLARE_INSTANCE_METHOD(void, set_rightSaberSpeed, float value); - DECLARE_BSML_PROPERTY(bool, didParse); - DECLARE_BSML_PROPERTY(float, timeSync); - DECLARE_BSML_PROPERTY(StringW, loopText); - DECLARE_BSML_PROPERTY(StringW, playPauseText); - DECLARE_BSML_PROPERTY(StringW, location); + /* Declare BSML property already makes a type _propname; field for you! */ + DECLARE_INSTANCE_METHOD(UnityEngine::Transform*, get_Transform); + DECLARE_INSTANCE_METHOD(void, set_visibility, bool value); + DECLARE_INSTANCE_METHOD(void, set_fps, int value); + DECLARE_INSTANCE_METHOD(void, set_leftSaberSpeed, float value); + DECLARE_INSTANCE_METHOD(void, set_rightSaberSpeed, float value); + DECLARE_BSML_PROPERTY(bool, didParse); + DECLARE_BSML_PROPERTY(float, timeSync); + DECLARE_BSML_PROPERTY(StringW, loopText); + DECLARE_BSML_PROPERTY(StringW, playPauseText); + DECLARE_BSML_PROPERTY(StringW, location); - DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(ListW, locations, ListW::New()); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, tabSelector); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, fpsText); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, leftSpeedText); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, rightSpeedText); + DECLARE_INSTANCE_FIELD_PRIVATE_DEFAULT(ListW, locations, ListW::New()); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, tabSelector); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, fpsText); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, leftSpeedText); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, rightSpeedText); - /* In DidActivate is when you want to run BSML::parse_and_construct() usually*/ - DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::ViewController::DidActivate, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); - DECLARE_OVERRIDE_METHOD_MATCH(void, DidDeactivate, &HMUI::ViewController::DidDeactivate, bool removedFromHierarchy, bool screenSystemDisabling); - DECLARE_INSTANCE_METHOD(void, DidSelect, UnityW, int selected); - DECLARE_INSTANCE_METHOD(void, SwitchHand, UnityEngine::XR::XRNode xrNode); - DECLARE_INSTANCE_METHOD(void, PausePlay); - DECLARE_INSTANCE_METHOD(void, Restart); - DECLARE_INSTANCE_METHOD(void, Loop); - DECLARE_INSTANCE_METHOD(void, SwitchHandLeft); - DECLARE_INSTANCE_METHOD(void, SwitchHandRight); - DECLARE_INSTANCE_METHOD(void, RequestDismiss); - DECLARE_INSTANCE_METHOD(StringW, FormatTimePercent, float value); - DECLARE_INSTANCE_METHOD(void, Jump); + /* In DidActivate is when you want to run BSML::parse_and_construct() usually*/ + DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::ViewController::DidActivate, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); + DECLARE_OVERRIDE_METHOD_MATCH(void, DidDeactivate, &HMUI::ViewController::DidDeactivate, bool removedFromHierarchy, bool screenSystemDisabling); + DECLARE_INSTANCE_METHOD(void, DidSelect, UnityW, int selected); + DECLARE_INSTANCE_METHOD(void, SwitchHand, UnityEngine::XR::XRNode xrNode); + DECLARE_INSTANCE_METHOD(void, PausePlay); + DECLARE_INSTANCE_METHOD(void, Restart); + DECLARE_INSTANCE_METHOD(void, Loop); + DECLARE_INSTANCE_METHOD(void, SwitchHandLeft); + DECLARE_INSTANCE_METHOD(void, SwitchHandRight); + DECLARE_INSTANCE_METHOD(void, RequestDismiss); + DECLARE_INSTANCE_METHOD(StringW, FormatTimePercent, float value); + DECLARE_INSTANCE_METHOD(void, Jump); - DECLARE_INJECT_METHOD(void, Construct); - /* Use the ctor to set default values like _playPauseText = "PAUSE"; */ - DECLARE_CTOR(ctor); - private: - DelegateUtils::DelegateW, int>> didSelectDelegate; - public: - std::function DidPositionTabVisibilityChange; - std::function DidPositionPreviewChange; - std::function HandDidSwitchEvent; - std::function DidTimeSyncChange; - std::function DidChangeVisiblity; - std::function DidClickPausePlay; - std::function DidClickRestart; - std::function DidPositionJump; - std::function DidClickLoop; - void Setup(float initialSongTime, int targetFramerate, std::string defaultLocation, std::vector _locations); - -) + DECLARE_INJECT_METHOD(void, Construct); + /* Use the ctor to set default values like _playPauseText = "PAUSE"; */ + DECLARE_CTOR(ctor); +private: + DelegateUtils::DelegateW, int>> didSelectDelegate; +public: + std::function DidPositionTabVisibilityChange; + std::function DidPositionPreviewChange; + std::function HandDidSwitchEvent; + std::function DidTimeSyncChange; + std::function DidChangeVisiblity; + std::function DidClickPausePlay; + std::function DidClickRestart; + std::function DidPositionJump; + std::function DidClickLoop; + void Setup(float initialSongTime, int targetFramerate, std::string defaultLocation, std::vector _locations); +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/ResultsViewReplayButtonController.hpp b/include/ReplaySystem/UI/ResultsViewReplayButtonController.hpp index 0174989e..473c8125 100644 --- a/include/ReplaySystem/UI/ResultsViewReplayButtonController.hpp +++ b/include/ReplaySystem/UI/ResultsViewReplayButtonController.hpp @@ -14,32 +14,29 @@ #include #include "Utils/DelegateUtils.hpp" -#define INTERFACES \ - { \ - classof(Zenject::IInitializable*), classof(::System::IDisposable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::UI, ResultsViewReplayButtonController, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, System::Object, "ScoreSaber::ReplaySystem::UI::ResultsViewReplayButtonController", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _resultsViewController); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapLevel*, _beatmapLevel); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapKey, _beatmapKey); - DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::LevelCompletionResults*, _levelCompletionResults); - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, watchReplayButton); - DECLARE_CTOR(ctor, GlobalNamespace::ResultsViewController* resultsViewController); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, ResultsViewController_didActivateEvent, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); - DECLARE_INSTANCE_METHOD(void, ResultsViewController_restartButtonPressedEvent, UnityW obj); - DECLARE_INSTANCE_METHOD(void, ResultsViewController_continueButtonPressedEvent, UnityW obj); - DECLARE_INSTANCE_METHOD(void, WaitForReplay); - DECLARE_INSTANCE_METHOD(void, ClickedReplayButton); - std::vector _serializedReplay; - volatile bool _replayReady = false; - DelegateUtils::DelegateW didActivateDelegate; - DelegateUtils::DelegateW>> continueButtonPressedDelegate; - DelegateUtils::DelegateW>> restartButtonPressedDelegate; - void UploadDaemon_ReplaySerialized(const std::vector &serializedReplay); - -); - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::UI, + ResultsViewReplayButtonController, + System::Object, + Zenject::IInitializable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _resultsViewController); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapLevel*, _beatmapLevel); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapKey, _beatmapKey); + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::LevelCompletionResults*, _levelCompletionResults); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, watchReplayButton); + DECLARE_CTOR(ctor, GlobalNamespace::ResultsViewController* resultsViewController); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, ResultsViewController_didActivateEvent, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); + DECLARE_INSTANCE_METHOD(void, ResultsViewController_restartButtonPressedEvent, UnityW obj); + DECLARE_INSTANCE_METHOD(void, ResultsViewController_continueButtonPressedEvent, UnityW obj); + DECLARE_INSTANCE_METHOD(void, WaitForReplay); + DECLARE_INSTANCE_METHOD(void, ClickedReplayButton); + std::vector _serializedReplay; + volatile bool _replayReady = false; + DelegateUtils::DelegateW didActivateDelegate; + DelegateUtils::DelegateW>> continueButtonPressedDelegate; + DelegateUtils::DelegateW>> restartButtonPressedDelegate; + void UploadDaemon_ReplaySerialized(const std::vector &serializedReplay); +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/SpectateAreaController.hpp b/include/ReplaySystem/UI/SpectateAreaController.hpp index 5a41342e..4a7596f2 100644 --- a/include/ReplaySystem/UI/SpectateAreaController.hpp +++ b/include/ReplaySystem/UI/SpectateAreaController.hpp @@ -12,36 +12,34 @@ #include #include -#define INTERFACES \ - { \ - classof(Zenject::ITickable*), classof(::System::IDisposable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::ReplaySystem::UI, SpectateAreaController, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::ReplaySystem::UI", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD_DEFAULT(int, _colorID, UnityEngine::Shader::PropertyToID("Color")); - DECLARE_INSTANCE_FIELD(UnityW, _timeTweeningManager); - DECLARE_INSTANCE_FIELD(GlobalNamespace::GameNoteController::Pool*, _gameNoteControllerPool); - - DECLARE_INSTANCE_FIELD(UnityW, _activeNote); - DECLARE_INSTANCE_FIELD(UnityEngine::Quaternion, _initialQuaternion); - DECLARE_INSTANCE_FIELD(Tweening::Tween*, _movementTween); - DECLARE_INSTANCE_FIELD(Tweening::Tween*, _statusTween); - DECLARE_INSTANCE_FIELD(bool, _despawned); - DECLARE_CTOR(ctor, Zenject::DiContainer* diContainer, Tweening::TimeTweeningManager* timeTweeningManager); - - DECLARE_INSTANCE_METHOD(void, AnimateTo, StringW poseID); - DECLARE_INSTANCE_METHOD(void, JumpToCallback, StringW poseID); - DECLARE_INSTANCE_METHOD(void, Dismiss); - - DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - - DECLARE_INSTANCE_METHOD(void, UpdateNoteScale, UnityEngine::Vector3 scale); - DECLARE_INSTANCE_METHOD(void, DespawnActiveNote); - - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - std::optional TryGetPose(StringW poseID); - public: - std::function DidUpdatePlayerSpectatorPose; -) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::ReplaySystem::UI, + SpectateAreaController, + System::Object, + Zenject::ITickable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD_DEFAULT(int, _colorID, UnityEngine::Shader::PropertyToID("Color")); + DECLARE_INSTANCE_FIELD(UnityW, _timeTweeningManager); + DECLARE_INSTANCE_FIELD(GlobalNamespace::GameNoteController::Pool*, _gameNoteControllerPool); + + DECLARE_INSTANCE_FIELD(UnityW, _activeNote); + DECLARE_INSTANCE_FIELD(UnityEngine::Quaternion, _initialQuaternion); + DECLARE_INSTANCE_FIELD(Tweening::Tween*, _movementTween); + DECLARE_INSTANCE_FIELD(Tweening::Tween*, _statusTween); + DECLARE_INSTANCE_FIELD(bool, _despawned); + DECLARE_CTOR(ctor, Zenject::DiContainer* diContainer, Tweening::TimeTweeningManager* timeTweeningManager); + + DECLARE_INSTANCE_METHOD(void, AnimateTo, StringW poseID); + DECLARE_INSTANCE_METHOD(void, JumpToCallback, StringW poseID); + DECLARE_INSTANCE_METHOD(void, Dismiss); + + DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + + DECLARE_INSTANCE_METHOD(void, UpdateNoteScale, UnityEngine::Vector3 scale); + DECLARE_INSTANCE_METHOD(void, DespawnActiveNote); + + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + std::optional TryGetPose(StringW poseID); +public: + std::function DidUpdatePlayerSpectatorPose; +}; \ No newline at end of file diff --git a/include/ReplaySystem/UI/VRControllerAccessor.hpp b/include/ReplaySystem/UI/VRControllerAccessor.hpp index 28af3192..c02a6ca2 100644 --- a/include/ReplaySystem/UI/VRControllerAccessor.hpp +++ b/include/ReplaySystem/UI/VRControllerAccessor.hpp @@ -4,7 +4,8 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI, VRControllerAccessor, Il2CppObject, - DECLARE_INSTANCE_FIELD(UnityW, _leftController); - DECLARE_INSTANCE_FIELD(UnityW, _rightController); - DECLARE_CTOR(ctor, GlobalNamespace::PauseMenuManager*);) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::UI, VRControllerAccessor, Il2CppObject) { + DECLARE_INSTANCE_FIELD(UnityW, _leftController); + DECLARE_INSTANCE_FIELD(UnityW, _rightController); + DECLARE_CTOR(ctor, GlobalNamespace::PauseMenuManager*); +}; \ No newline at end of file diff --git a/include/UI/FlowCoordinators/ScoreSaberFlowCoordinator.hpp b/include/UI/FlowCoordinators/ScoreSaberFlowCoordinator.hpp index 976e082c..45b3d898 100644 --- a/include/UI/FlowCoordinators/ScoreSaberFlowCoordinator.hpp +++ b/include/UI/FlowCoordinators/ScoreSaberFlowCoordinator.hpp @@ -8,10 +8,11 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::UI::FlowCoordinators, ScoreSaberFlowCoordinator, HMUI::FlowCoordinator, - DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::FlowCoordinator::DidActivate, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); - DECLARE_OVERRIDE_METHOD_MATCH(void, BackButtonWasPressed, &HMUI::FlowCoordinator::BackButtonWasPressed, HMUI::ViewController* topViewController); +DECLARE_CLASS_CODEGEN(ScoreSaber::UI::FlowCoordinators, ScoreSaberFlowCoordinator, HMUI::FlowCoordinator) { + DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::FlowCoordinator::DidActivate, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); + DECLARE_OVERRIDE_METHOD_MATCH(void, BackButtonWasPressed, &HMUI::FlowCoordinator::BackButtonWasPressed, HMUI::ViewController* topViewController); - DECLARE_INSTANCE_FIELD_DEFAULT(UnityW, globalViewController, nullptr); - DECLARE_INSTANCE_FIELD_DEFAULT(UnityW, faqViewController, nullptr); - DECLARE_INSTANCE_FIELD_DEFAULT(UnityW, teamViewController, nullptr);) + DECLARE_INSTANCE_FIELD_DEFAULT(UnityW, globalViewController, nullptr); + DECLARE_INSTANCE_FIELD_DEFAULT(UnityW, faqViewController, nullptr); + DECLARE_INSTANCE_FIELD_DEFAULT(UnityW, teamViewController, nullptr); +}; diff --git a/include/UI/FlowCoordinators/ScoreSaberSettingsFlowCoordinator.hpp b/include/UI/FlowCoordinators/ScoreSaberSettingsFlowCoordinator.hpp index 6de8d3be..461a9d90 100644 --- a/include/UI/FlowCoordinators/ScoreSaberSettingsFlowCoordinator.hpp +++ b/include/UI/FlowCoordinators/ScoreSaberSettingsFlowCoordinator.hpp @@ -6,8 +6,9 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::UI::FlowCoordinators, ScoreSaberSettingsFlowCoordinator, HMUI::FlowCoordinator, - DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::FlowCoordinator::DidActivate, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); - DECLARE_OVERRIDE_METHOD_MATCH(void, BackButtonWasPressed, &HMUI::FlowCoordinator::BackButtonWasPressed, HMUI::ViewController* topViewController); +DECLARE_CLASS_CODEGEN(ScoreSaber::UI::FlowCoordinators, ScoreSaberSettingsFlowCoordinator, HMUI::FlowCoordinator) { + DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::FlowCoordinator::DidActivate, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); + DECLARE_OVERRIDE_METHOD_MATCH(void, BackButtonWasPressed, &HMUI::FlowCoordinator::BackButtonWasPressed, HMUI::ViewController* topViewController); - DECLARE_INSTANCE_FIELD_DEFAULT(UnityW, mainSettingsViewController, nullptr);) + DECLARE_INSTANCE_FIELD_DEFAULT(UnityW, mainSettingsViewController, nullptr); +}; diff --git a/include/UI/Multiplayer/ScoreSaberMultiplayerInitializer.hpp b/include/UI/Multiplayer/ScoreSaberMultiplayerInitializer.hpp index 420374a7..83969942 100644 --- a/include/UI/Multiplayer/ScoreSaberMultiplayerInitializer.hpp +++ b/include/UI/Multiplayer/ScoreSaberMultiplayerInitializer.hpp @@ -8,21 +8,18 @@ #include #include "Utils/DelegateUtils.hpp" -using namespace GlobalNamespace; - -#define INTERFACES \ - { \ - classof(Zenject::IInitializable*), classof(::System::IDisposable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::UI::Multiplayer, ScoreSaberMultiplayerInitializer, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::UI::Multiplayer", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD(UnityW, _gameServerLobbyFlowCoordinator); - DECLARE_CTOR(ctor, GameServerLobbyFlowCoordinator* gameServerLobbyFlowCoordinator); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, GameServerLobbyFlowCoordinator_didSetupEvent); - DECLARE_INSTANCE_METHOD(void, GameServerLobbyFlowCoordinator_didFinishEvent); - DelegateUtils::DelegateW didSetupDelegate; - DelegateUtils::DelegateW didFinishDelegate;) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::UI::Multiplayer, + ScoreSaberMultiplayerInitializer, + System::Object, + Zenject::IInitializable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD(UnityW, _gameServerLobbyFlowCoordinator); + DECLARE_CTOR(ctor, GlobalNamespace::GameServerLobbyFlowCoordinator* gameServerLobbyFlowCoordinator); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, GameServerLobbyFlowCoordinator_didSetupEvent); + DECLARE_INSTANCE_METHOD(void, GameServerLobbyFlowCoordinator_didFinishEvent); + DelegateUtils::DelegateW didSetupDelegate; + DelegateUtils::DelegateW didFinishDelegate; +}; diff --git a/include/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.hpp b/include/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.hpp index fe10aa75..f460904f 100644 --- a/include/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.hpp +++ b/include/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.hpp @@ -11,35 +11,38 @@ #include #include #include +#include "System/zzzz__Object_def.hpp" #include "Utils/DelegateUtils.hpp" -using namespace GlobalNamespace; -#define INTERFACES \ - { \ - classof(Zenject::IInitializable*), classof(::System::IDisposable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::UI::Multiplayer, ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::UI::Multiplayer", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD(UnityW, _mainFlowCoordinator); - DECLARE_INSTANCE_FIELD(UnityW, _serverPlayerListViewController); - DECLARE_INSTANCE_FIELD(UnityW, _platformLeaderboardViewController); - DECLARE_INSTANCE_FIELD(UnityW, _levelSelectionNavigationController); - DECLARE_CTOR(ctor, MainFlowCoordinator* mainFlowCoordinator, ServerPlayerListViewController* serverPlayerListViewController, PlatformLeaderboardViewController* platformLeaderboardViewController, LevelSelectionNavigationController* levelSelectionNavigationController); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, LevelSelectionNavigationController_didActivateEvent, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); - DECLARE_INSTANCE_METHOD(void, LevelSelectionNavigationController_didDeactivateEvent, bool removedFromHierarchy, bool screenSystemDisabling); - DECLARE_INSTANCE_METHOD(void, LevelSelectionNavigationController_didChangeDifficultyBeatmapEvent, UnityW controller); - DECLARE_INSTANCE_METHOD(void, LevelSelectionNavigationController_didChangeLevelDetailContentEvent, UnityW controller, StandardLevelDetailViewController::ContentType contentType); - DelegateUtils::DelegateW didActivateDelegate; - DelegateUtils::DelegateW didDeactivateDelegate; - DelegateUtils::DelegateW>> didChangeDifficultyBeatmapDelegate; - DelegateUtils::DelegateW, StandardLevelDetailViewController::ContentType>> didChangeLevelDetailContentDelegate; - bool InMulti(); - void HideLeaderboard(); - void ShowLeaderboard(); - bool _currentlyInMulti; - bool _performingFirstActivation;) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::UI::Multiplayer, + ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager, + System::Object, + Zenject::IInitializable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD(UnityW, _mainFlowCoordinator); + DECLARE_INSTANCE_FIELD(UnityW, _serverPlayerListViewController); + DECLARE_INSTANCE_FIELD(UnityW, _platformLeaderboardViewController); + DECLARE_INSTANCE_FIELD(UnityW, _levelSelectionNavigationController); + DECLARE_CTOR(ctor, + GlobalNamespace::MainFlowCoordinator* mainFlowCoordinator, + GlobalNamespace::ServerPlayerListViewController* serverPlayerListViewController, + GlobalNamespace::PlatformLeaderboardViewController* platformLeaderboardViewController, + GlobalNamespace::LevelSelectionNavigationController* levelSelectionNavigationController); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, LevelSelectionNavigationController_didActivateEvent, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); + DECLARE_INSTANCE_METHOD(void, LevelSelectionNavigationController_didDeactivateEvent, bool removedFromHierarchy, bool screenSystemDisabling); + DECLARE_INSTANCE_METHOD(void, LevelSelectionNavigationController_didChangeDifficultyBeatmapEvent, UnityW controller); + DECLARE_INSTANCE_METHOD(void, LevelSelectionNavigationController_didChangeLevelDetailContentEvent, UnityW controller, GlobalNamespace::StandardLevelDetailViewController::ContentType contentType); + DelegateUtils::DelegateW didActivateDelegate; + DelegateUtils::DelegateW didDeactivateDelegate; + DelegateUtils::DelegateW>> didChangeDifficultyBeatmapDelegate; + DelegateUtils::DelegateW, GlobalNamespace::StandardLevelDetailViewController::ContentType>> didChangeLevelDetailContentDelegate; + bool InMulti(); + void HideLeaderboard(); + void ShowLeaderboard(); + bool _currentlyInMulti; + bool _performingFirstActivation; +}; \ No newline at end of file diff --git a/include/UI/Multiplayer/ScoreSaberMultiplayerResultsLeaderboardFlowManager.hpp b/include/UI/Multiplayer/ScoreSaberMultiplayerResultsLeaderboardFlowManager.hpp index aa080154..7bc74f84 100644 --- a/include/UI/Multiplayer/ScoreSaberMultiplayerResultsLeaderboardFlowManager.hpp +++ b/include/UI/Multiplayer/ScoreSaberMultiplayerResultsLeaderboardFlowManager.hpp @@ -11,27 +11,28 @@ #include #include #include +#include "System/zzzz__Object_def.hpp" #include "Utils/DelegateUtils.hpp" -using namespace GlobalNamespace; - -#define INTERFACES \ - { \ - classof(Zenject::IInitializable*), classof(::System::IDisposable*) \ - } - -___DECLARE_TYPE_WRAPPER_INHERITANCE(ScoreSaber::UI::Multiplayer, ScoreSaberMultiplayerResultsLeaderboardFlowManager, Il2CppTypeEnum::IL2CPP_TYPE_CLASS, Il2CppObject, "ScoreSaber::UI::Multiplayer", INTERFACES, 0, nullptr, - DECLARE_INSTANCE_FIELD(UnityW, _mainFlowCoordinator); - DECLARE_INSTANCE_FIELD(UnityW, _multiplayerResultsViewController); - DECLARE_INSTANCE_FIELD(UnityW, _platformLeaderboardViewController); - DECLARE_INSTANCE_FIELD(BeatmapKey, _lastCompletedBeatmapKey); - DECLARE_CTOR(ctor, MainFlowCoordinator* mainFlowCoordinator, MultiplayerResultsViewController* multiplayerResultsViewController, PlatformLeaderboardViewController* platformLeaderboardViewController); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); - DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); - DECLARE_INSTANCE_METHOD(void, MultiplayerResultsViewController_didActivateEvent, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); - DECLARE_INSTANCE_METHOD(void, MultiplayerResultsViewController_didDeactivateEvent, bool removedFromHierarchy, bool screenSystemDisabling); - DECLARE_INSTANCE_METHOD(void, MultiplayerLevelDidFinish, MultiplayerLevelScenesTransitionSetupDataSO* transitionSetupData, MultiplayerResultsData* results); - DelegateUtils::DelegateW didActivateDelegate; - DelegateUtils::DelegateW didDeactivateDelegate;) - -#undef INTERFACES +DECLARE_CLASS_CODEGEN_INTERFACES( + ScoreSaber::UI::Multiplayer, + ScoreSaberMultiplayerResultsLeaderboardFlowManager, + System::Object, + Zenject::IInitializable*, + System::IDisposable*) { + DECLARE_INSTANCE_FIELD(UnityW, _mainFlowCoordinator); + DECLARE_INSTANCE_FIELD(UnityW, _multiplayerResultsViewController); + DECLARE_INSTANCE_FIELD(UnityW, _platformLeaderboardViewController); + DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapKey, _lastCompletedBeatmapKey); + DECLARE_CTOR(ctor, + GlobalNamespace::MainFlowCoordinator* mainFlowCoordinator, + GlobalNamespace::MultiplayerResultsViewController* multiplayerResultsViewController, + GlobalNamespace::PlatformLeaderboardViewController* platformLeaderboardViewController); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); + DECLARE_OVERRIDE_METHOD_MATCH(void, Dispose, &::System::IDisposable::Dispose); + DECLARE_INSTANCE_METHOD(void, MultiplayerResultsViewController_didActivateEvent, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); + DECLARE_INSTANCE_METHOD(void, MultiplayerResultsViewController_didDeactivateEvent, bool removedFromHierarchy, bool screenSystemDisabling); + DECLARE_INSTANCE_METHOD(void, MultiplayerLevelDidFinish, GlobalNamespace::MultiplayerLevelScenesTransitionSetupDataSO* transitionSetupData, GlobalNamespace::MultiplayerResultsData* results); + DelegateUtils::DelegateW didActivateDelegate; + DelegateUtils::DelegateW didDeactivateDelegate; +}; \ No newline at end of file diff --git a/include/UI/Other/Banner.hpp b/include/UI/Other/Banner.hpp index 3cf4220d..5d671098 100644 --- a/include/UI/Other/Banner.hpp +++ b/include/UI/Other/Banner.hpp @@ -11,13 +11,12 @@ #include #include #include -#include +#include #include #include #include -DECLARE_CLASS_CODEGEN( - ScoreSaber::UI::Other, Banner, UnityEngine::MonoBehaviour, +DECLARE_CLASS_CODEGEN(ScoreSaber::UI::Other, Banner, UnityEngine::MonoBehaviour) { DECLARE_INSTANCE_METHOD(void, Update); DECLARE_INSTANCE_FIELD(UnityW, bg); DECLARE_INSTANCE_FIELD(UnityW, bgImage); @@ -27,8 +26,7 @@ DECLARE_CLASS_CODEGEN( DECLARE_INSTANCE_FIELD(UnityW, loadingVertical); DECLARE_INSTANCE_FIELD(UnityW, promptText); - public - : +public: static ScoreSaber::UI::Other::Banner * Create(UnityEngine::Transform * parent); void Setup(); @@ -53,8 +51,8 @@ DECLARE_CLASS_CODEGEN( void set_bottomText(std::u16string_view newText); void set_bottomText(std::string_view newText) { set_bottomText(Paper::StringConvert::from_utf8(newText)); }; - private - : bool rainbow = false; +private: + bool rainbow = false; bool wasRainbow = false; float colorAngle = 0.0f; int scoreboardId; @@ -62,5 +60,4 @@ DECLARE_CLASS_CODEGEN( custom_types::Helpers::Coroutine SetPrompt( std::string status, bool loadingIndicator, float dismiss, std::function callback); - -) \ No newline at end of file +}; \ No newline at end of file diff --git a/include/UI/Other/PlayerProfileModal.hpp b/include/UI/Other/PlayerProfileModal.hpp index 934e08ec..b1a727fa 100644 --- a/include/UI/Other/PlayerProfileModal.hpp +++ b/include/UI/Other/PlayerProfileModal.hpp @@ -15,40 +15,40 @@ #include "Data/Badge.hpp" #include "Data/Player.hpp" -DECLARE_CLASS_CODEGEN(ScoreSaber::UI::Other, PlayerProfileModal, UnityEngine::MonoBehaviour, - DECLARE_INSTANCE_FIELD(UnityW, modal); - DECLARE_INSTANCE_FIELD(UnityW, pfpImage); - DECLARE_INSTANCE_FIELD(UnityW, badgeParent); - DECLARE_INSTANCE_FIELD(UnityW, headerText); - DECLARE_INSTANCE_FIELD(UnityW, globalRanking); - DECLARE_INSTANCE_FIELD(UnityW, performancePoints); - DECLARE_INSTANCE_FIELD(UnityW, averageRankedAccuracy); - DECLARE_INSTANCE_FIELD(UnityW, totalScore); - DECLARE_INSTANCE_FIELD(UnityEngine::Coroutine*, profileRoutine); - DECLARE_INSTANCE_FIELD(ListW, badgeRoutines); - - public - : - - std::string playerId; - static ScoreSaber::UI::Other::PlayerProfileModal * Create(UnityEngine::Transform * parent); - void Show(std::string playerId); - - void Hide(); - void Setup(); - void set_player(std::u16string_view playername); - void set_header(std::u16string_view header); - void set_globalRanking(int globalRanking); - void set_performancePoints(float performancePoints); - void set_averageRankedAccuracy(float averageRankedAccuracy); - void set_totalScore(long totalScore); - void set_pfp(UnityEngine::Sprite* pfp); - void ClearBadges(); - void AddBadge(ScoreSaber::Data::Badge& badge, int index); - - custom_types::Helpers::Coroutine FetchPlayerData(std::string playerId); - void SetPlayerData(ScoreSaber::Data::Player& player); - void stopProfileRoutine(); - void stopBadgeRoutines(); - - void OpenPlayerUrl();) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::UI::Other, PlayerProfileModal, UnityEngine::MonoBehaviour) { + DECLARE_INSTANCE_FIELD(UnityW, modal); + DECLARE_INSTANCE_FIELD(UnityW, pfpImage); + DECLARE_INSTANCE_FIELD(UnityW, badgeParent); + DECLARE_INSTANCE_FIELD(UnityW, headerText); + DECLARE_INSTANCE_FIELD(UnityW, globalRanking); + DECLARE_INSTANCE_FIELD(UnityW, performancePoints); + DECLARE_INSTANCE_FIELD(UnityW, averageRankedAccuracy); + DECLARE_INSTANCE_FIELD(UnityW, totalScore); + DECLARE_INSTANCE_FIELD(UnityEngine::Coroutine*, profileRoutine); + DECLARE_INSTANCE_FIELD(ListW, badgeRoutines); + +public: + + std::string playerId; + static ScoreSaber::UI::Other::PlayerProfileModal * Create(UnityEngine::Transform * parent); + void Show(std::string playerId); + + void Hide(); + void Setup(); + void set_player(std::u16string_view playername); + void set_header(std::u16string_view header); + void set_globalRanking(int globalRanking); + void set_performancePoints(float performancePoints); + void set_averageRankedAccuracy(float averageRankedAccuracy); + void set_totalScore(long totalScore); + void set_pfp(UnityEngine::Sprite* pfp); + void ClearBadges(); + void AddBadge(ScoreSaber::Data::Badge& badge, int index); + + custom_types::Helpers::Coroutine FetchPlayerData(std::string playerId); + void SetPlayerData(ScoreSaber::Data::Player& player); + void stopProfileRoutine(); + void stopBadgeRoutines(); + + void OpenPlayerUrl(); +}; \ No newline at end of file diff --git a/include/UI/Other/ScoreInfoModal.hpp b/include/UI/Other/ScoreInfoModal.hpp index 1c9fa548..37b230ae 100644 --- a/include/UI/Other/ScoreInfoModal.hpp +++ b/include/UI/Other/ScoreInfoModal.hpp @@ -10,53 +10,51 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::UI::Other, ScoreInfoModal, UnityEngine::MonoBehaviour, - DECLARE_INSTANCE_FIELD(UnityW, modal); - DECLARE_INSTANCE_FIELD(UnityW, playerProfileModal); - DECLARE_INSTANCE_FIELD(UnityW, player); - DECLARE_INSTANCE_FIELD(UnityW, deviceHmd); - DECLARE_INSTANCE_FIELD(UnityW, score); - DECLARE_INSTANCE_FIELD(UnityW, pp); - DECLARE_INSTANCE_FIELD(UnityW, combo); - DECLARE_INSTANCE_FIELD(UnityW, fullCombo); - DECLARE_INSTANCE_FIELD(UnityW, badCuts); - DECLARE_INSTANCE_FIELD(UnityW, missedNotes); - DECLARE_INSTANCE_FIELD(UnityW, modifiers); - DECLARE_INSTANCE_FIELD(UnityW, timeSet); - DECLARE_INSTANCE_FIELD(UnityW, replayImage); - DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapLevel*, currentBeatmapLevel); - DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapKey, currentBeatmapKey); - - public - : - - void Hide(); - void Show(ScoreSaber::Data::Score& score, GlobalNamespace::BeatmapLevel* beatmapLevel, GlobalNamespace::BeatmapKey beatmapKey, int leaderboardId, int maxScore); - - static ScoreSaber::UI::Other::ScoreInfoModal * Create(UnityEngine::Transform * parent); - - void Setup(); - - void set_player(std::u16string player); - void set_device_hmd(std::string_view device); - void set_score(long score, double percent); - void set_pp(double pp); - void set_combo(std::optional combo); - void set_fullCombo(std::optional value); - void set_badCuts(std::optional badCuts); - void set_missedNotes(std::optional missedNotes); - void set_modifiers(std::string_view modifiers); - void set_timeSet(std::string_view timeSet); - - private - : int leaderboardId; - ScoreSaber::Data::Score currentScore; - std::string playerId; - std::string replayFileName; - bool replayEnabled; - - void ShowPlayerProfileModal(); - void PlayReplay(); - void SetReplayButtonState(bool enabled); - -) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::UI::Other, ScoreInfoModal, UnityEngine::MonoBehaviour) { + DECLARE_INSTANCE_FIELD(UnityW, modal); + DECLARE_INSTANCE_FIELD(UnityW, playerProfileModal); + DECLARE_INSTANCE_FIELD(UnityW, player); + DECLARE_INSTANCE_FIELD(UnityW, deviceHmd); + DECLARE_INSTANCE_FIELD(UnityW, score); + DECLARE_INSTANCE_FIELD(UnityW, pp); + DECLARE_INSTANCE_FIELD(UnityW, combo); + DECLARE_INSTANCE_FIELD(UnityW, fullCombo); + DECLARE_INSTANCE_FIELD(UnityW, badCuts); + DECLARE_INSTANCE_FIELD(UnityW, missedNotes); + DECLARE_INSTANCE_FIELD(UnityW, modifiers); + DECLARE_INSTANCE_FIELD(UnityW, timeSet); + DECLARE_INSTANCE_FIELD(UnityW, replayImage); + DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapLevel*, currentBeatmapLevel); + DECLARE_INSTANCE_FIELD(GlobalNamespace::BeatmapKey, currentBeatmapKey); + +public: + + void Hide(); + void Show(ScoreSaber::Data::Score& score, GlobalNamespace::BeatmapLevel* beatmapLevel, GlobalNamespace::BeatmapKey beatmapKey, int leaderboardId, int maxScore); + + static ScoreSaber::UI::Other::ScoreInfoModal * Create(UnityEngine::Transform * parent); + + void Setup(); + + void set_player(std::u16string player); + void set_device_hmd(std::string_view device); + void set_score(long score, double percent); + void set_pp(double pp); + void set_combo(std::optional combo); + void set_fullCombo(std::optional value); + void set_badCuts(std::optional badCuts); + void set_missedNotes(std::optional missedNotes); + void set_modifiers(std::string_view modifiers); + void set_timeSet(std::string_view timeSet); + +private: + int leaderboardId; + ScoreSaber::Data::Score currentScore; + std::string playerId; + std::string replayFileName; + bool replayEnabled; + + void ShowPlayerProfileModal(); + void PlayReplay(); + void SetReplayButtonState(bool enabled); +}; \ No newline at end of file diff --git a/include/UI/ViewControllers/FAQViewController.hpp b/include/UI/ViewControllers/FAQViewController.hpp index fa751800..a0bd95cb 100644 --- a/include/UI/ViewControllers/FAQViewController.hpp +++ b/include/UI/ViewControllers/FAQViewController.hpp @@ -2,9 +2,9 @@ #include #include -DECLARE_CLASS_CODEGEN( - ScoreSaber::UI::ViewControllers, FAQViewController, HMUI::ViewController, +DECLARE_CLASS_CODEGEN(ScoreSaber::UI::ViewControllers, FAQViewController, HMUI::ViewController) { DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::ViewController::DidActivate, bool firstActivation, bool addedToHierarchy, - bool screenSystemEnabling);); \ No newline at end of file + bool screenSystemEnabling); +}; \ No newline at end of file diff --git a/include/UI/ViewControllers/GlobalViewController.hpp b/include/UI/ViewControllers/GlobalViewController.hpp index 5126905f..66734a92 100644 --- a/include/UI/ViewControllers/GlobalViewController.hpp +++ b/include/UI/ViewControllers/GlobalViewController.hpp @@ -1,15 +1,13 @@ #pragma once -#include "CustomTypes/Components/GlobalLeaderboardTableData.hpp" +#include "CustomTypes/Components/GlobalLeaderboardTableData.hpp" #include #include #include "UI/Other/PlayerProfileModal.hpp" #include #include -DECLARE_CLASS_CODEGEN( - ScoreSaber::UI::ViewControllers, GlobalViewController, - HMUI::ViewController, +DECLARE_CLASS_CODEGEN(ScoreSaber::UI::ViewControllers, GlobalViewController, HMUI::ViewController) { DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::ViewController::DidActivate, bool firstActivation, bool addedToHierarchy, @@ -19,12 +17,10 @@ DECLARE_CLASS_CODEGEN( DECLARE_INSTANCE_FIELD(UnityW, playerProfileModal); DECLARE_INSTANCE_FIELD(UnityW, loadingIndicator); void set_loading(bool value); - private - : +private: void OpenMoreInfoModal(); void UpButtonWasPressed(); void DownButtonWasPressed(); void FilterWasClicked(ScoreSaber::CustomTypes::Components::GlobalLeaderboardTableData::LeaderboardType type); - -); \ No newline at end of file +}; \ No newline at end of file diff --git a/include/UI/ViewControllers/MainSettingsViewController.hpp b/include/UI/ViewControllers/MainSettingsViewController.hpp index 123898bb..1c0da17a 100644 --- a/include/UI/ViewControllers/MainSettingsViewController.hpp +++ b/include/UI/ViewControllers/MainSettingsViewController.hpp @@ -6,7 +6,7 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::UI::ViewControllers, MainSettingsViewController, HMUI::ViewController, +DECLARE_CLASS_CODEGEN(ScoreSaber::UI::ViewControllers, MainSettingsViewController, HMUI::ViewController) { DECLARE_INSTANCE_METHOD(bool, get_showScorePP); DECLARE_INSTANCE_METHOD(void, set_showScorePP, bool value); DECLARE_INSTANCE_METHOD(bool, get_showLocalPlayerRank); @@ -25,4 +25,4 @@ DECLARE_CLASS_CODEGEN(ScoreSaber::UI::ViewControllers, MainSettingsViewControlle DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::ViewController::DidActivate, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); DECLARE_CTOR(ctor); -) +}; \ No newline at end of file diff --git a/include/UI/ViewControllers/TeamViewController.hpp b/include/UI/ViewControllers/TeamViewController.hpp index d1e6f795..4936bbee 100644 --- a/include/UI/ViewControllers/TeamViewController.hpp +++ b/include/UI/ViewControllers/TeamViewController.hpp @@ -5,9 +5,10 @@ #include #include -DECLARE_CLASS_CODEGEN(ScoreSaber::UI::ViewControllers, TeamViewController, HMUI::ViewController, - DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::ViewController::DidActivate, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); - DECLARE_INSTANCE_FIELD(Array>*, creditTabs); - public - : void Show(int idx); - UnityEngine::GameObject * CreateCreditTab(int idx);) \ No newline at end of file +DECLARE_CLASS_CODEGEN(ScoreSaber::UI::ViewControllers, TeamViewController, HMUI::ViewController) { + DECLARE_OVERRIDE_METHOD_MATCH(void, DidActivate, &HMUI::ViewController::DidActivate, bool firstActivation, bool addedToHierarchy, bool screenSystemEnabling); + DECLARE_INSTANCE_FIELD(Array>*, creditTabs); +public: + void Show(int idx); + UnityEngine::GameObject * CreateCreditTab(int idx); +}; \ No newline at end of file diff --git a/include/Utils/MaxScoreCache.hpp b/include/Utils/MaxScoreCache.hpp index f3ad8958..58aec915 100644 --- a/include/Utils/MaxScoreCache.hpp +++ b/include/Utils/MaxScoreCache.hpp @@ -39,15 +39,15 @@ namespace std { }; } -DECLARE_CLASS_CODEGEN( - ScoreSaber::Utils, MaxScoreCache, Il2CppObject, +DECLARE_CLASS_CODEGEN(ScoreSaber::Utils, MaxScoreCache, Il2CppObject) { DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapDataLoader*, _beatmapDataLoader); DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapLevelsModel*, _beatmapLevelsModel);; + DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::BeatmapLevelsEntitlementModel*, _beatmapLevelsEntitlementModel); - DECLARE_CTOR(ctor, GlobalNamespace::BeatmapDataLoader* beatmapDataLoader, GlobalNamespace::BeatmapLevelsModel* beatmapLevelsModel); + DECLARE_CTOR(ctor, GlobalNamespace::BeatmapDataLoader* beatmapDataLoader, GlobalNamespace::BeatmapLevelsModel* beatmapLevelsModel, GlobalNamespace::BeatmapLevelsEntitlementModel* beatmapLevelsEntitlementModel); // the cache needs to store BeatmapKeys as FixedSafeValueType so GC cannot collect any of its members. std::unordered_map, int> cache; public: void GetMaxScore(GlobalNamespace::BeatmapLevel* beatmapLevel, GlobalNamespace::BeatmapKey beatmapKey, const std::function &callback); -) +}; \ No newline at end of file diff --git a/include/logging.hpp b/include/logging.hpp index 67b7861d..2119cc0f 100644 --- a/include/logging.hpp +++ b/include/logging.hpp @@ -1,5 +1,5 @@ #pragma once -#include "paper/shared/logger.hpp" +#include namespace ScoreSaber { diff --git a/mod.template.json b/mod.template.json index 56481d43..6e44630d 100644 --- a/mod.template.json +++ b/mod.template.json @@ -7,7 +7,7 @@ "version": "${version}", "coverImage": "logo.jpg", "packageId": "com.beatgames.beatsaber", - "packageVersion": "1.37.0_9064817954", + "packageVersion": "1.40.8_7379", "description": "Allows you to upload scores to an online leaderboard at https://scoresaber.com. Earn PP from ranked maps and compare scores with others.", "modFiles": [], "lateModFiles": [ diff --git a/qpm.json b/qpm.json index 324d1ccb..53d381c8 100644 --- a/qpm.json +++ b/qpm.json @@ -48,33 +48,29 @@ "dependencies": [ { "id": "beatsaber-hook", - "versionRange": "^5.1.9", - "additionalData": { - "extraFiles": [ - "src/inline-hook" - ] - } + "versionRange": "^6.4.2", + "additionalData": {} }, { "id": "scotland2", - "versionRange": "^0.1.4", + "versionRange": "^0.1.6", "additionalData": { "includeQmod": false } }, { "id": "bs-cordl", - "versionRange": "^3700.0.0", + "versionRange": "^4008.0.0", "additionalData": {} }, { "id": "custom-types", - "versionRange": "^0.17.10", + "versionRange": "^0.18.3", "additionalData": {} }, { "id": "config-utils", - "versionRange": "^1.4.2", + "versionRange": "^2.0.3", "additionalData": {} }, { @@ -89,12 +85,12 @@ }, { "id": "lapiz", - "versionRange": "^0.2.12", + "versionRange": "^0.2.23", "additionalData": {} }, { "id": "bsml", - "versionRange": "^0.4.43", + "versionRange": "^0.4.55", "additionalData": {} }, { @@ -103,8 +99,13 @@ "additionalData": {} }, { - "id": "paper", - "versionRange": "^3.6.4", + "id": "paper2_scotland2", + "versionRange": "^4.6.4", + "additionalData": {} + }, + { + "id": "metacore", + "versionRange": "^1.4.0", "additionalData": {} } ], diff --git a/src/CustomTypes/Components/GlobalLeaderboardTableData.cpp b/src/CustomTypes/Components/GlobalLeaderboardTableData.cpp index 58472dde..371d7447 100644 --- a/src/CustomTypes/Components/GlobalLeaderboardTableData.cpp +++ b/src/CustomTypes/Components/GlobalLeaderboardTableData.cpp @@ -157,8 +157,8 @@ namespace ScoreSaber::CustomTypes::Components self->_visibleCells->Clear(); if (self->dataSource != nullptr) { - self->_numberOfCells = self->dataSource->NumberOfCells(); - self->_cellSize = self->dataSource->CellSize(); + self->UpdateCachedData(); + self->_cellSize = self->dataSource->CellSize(-1); } else { @@ -166,7 +166,7 @@ namespace ScoreSaber::CustomTypes::Components self->_cellSize = 1.0f; } - self->scrollView->_fixedCellSize = self->cellSize; + self->scrollView->_fixedCellSize = self->cellSize + self->spacing; self->RefreshContentSize(); if (!self->gameObject->activeInHierarchy) { diff --git a/src/Data/Badge.cpp b/src/Data/Badge.cpp index 9c2c0099..6719a776 100644 --- a/src/Data/Badge.cpp +++ b/src/Data/Badge.cpp @@ -1,6 +1,6 @@ #include "Data/Badge.hpp" #include -#include "paper/shared/string_convert.hpp" +#include namespace ScoreSaber::Data { diff --git a/src/Data/LeaderboardInfo.cpp b/src/Data/LeaderboardInfo.cpp index 9254c54f..3b8cdc39 100644 --- a/src/Data/LeaderboardInfo.cpp +++ b/src/Data/LeaderboardInfo.cpp @@ -1,7 +1,7 @@ #include "Data/LeaderboardInfo.hpp" #include #include -#include "paper/shared/string_convert.hpp" +#include inline rapidjson::GenericDocument> getdoc(std::u16string_view string) { diff --git a/src/Data/LeaderboardPlayer.cpp b/src/Data/LeaderboardPlayer.cpp index ec6bd55c..c4cbec3c 100644 --- a/src/Data/LeaderboardPlayer.cpp +++ b/src/Data/LeaderboardPlayer.cpp @@ -1,6 +1,6 @@ #include "Data/LeaderboardPlayer.hpp" #include -#include "paper/shared/string_convert.hpp" +#include namespace ScoreSaber::Data { diff --git a/src/Data/Player.cpp b/src/Data/Player.cpp index 3b65b5a0..a791610c 100644 --- a/src/Data/Player.cpp +++ b/src/Data/Player.cpp @@ -1,6 +1,6 @@ #include "Data/Player.hpp" #include -#include "paper/shared/string_convert.hpp" +#include #include namespace ScoreSaber::Data { diff --git a/src/Data/Private/AuthResponse.cpp b/src/Data/Private/AuthResponse.cpp index 72ce9ca6..fc63d075 100644 --- a/src/Data/Private/AuthResponse.cpp +++ b/src/Data/Private/AuthResponse.cpp @@ -1,6 +1,6 @@ #include "Data/Private/AuthResponse.hpp" #include -#include "paper/shared/string_convert.hpp" +#include namespace ScoreSaber::Data::Private { diff --git a/src/Data/Score.cpp b/src/Data/Score.cpp index 476db323..94c5f353 100644 --- a/src/Data/Score.cpp +++ b/src/Data/Score.cpp @@ -1,7 +1,7 @@ #include "Data/Score.hpp" #include "Utils/StringUtils.hpp" #include -#include "paper/shared/string_convert.hpp" +#include namespace ScoreSaber::Data { diff --git a/src/ReplaySystem/Playback/NotePlayer.cpp b/src/ReplaySystem/Playback/NotePlayer.cpp index 24b1447b..6e89bcd2 100644 --- a/src/ReplaySystem/Playback/NotePlayer.cpp +++ b/src/ReplaySystem/Playback/NotePlayer.cpp @@ -105,7 +105,7 @@ namespace ScoreSaber::ReplaySystem::Playback noteController->inverseWorldRotation, noteTransform->rotation, noteTransform->position, - il2cpp_utils::try_cast(correctSaber->movementData).value_or(nullptr)); + il2cpp_utils::try_cast(correctSaber->movementDataForLogic).value_or(nullptr)); _recognizedNoteCutInfos.emplace_back(noteCutInfo, activeEvent); noteController->SendNoteWasCutEvent(byref(noteCutInfo)); return true; diff --git a/src/ReplaySystem/Playback/PosePlayer.cpp b/src/ReplaySystem/Playback/PosePlayer.cpp index 159c594a..4751ab18 100644 --- a/src/ReplaySystem/Playback/PosePlayer.cpp +++ b/src/ReplaySystem/Playback/PosePlayer.cpp @@ -1,7 +1,7 @@ #include "ReplaySystem/Playback/PosePlayer.hpp" #include +#include #include -#include #include "ReplaySystem/ReplayLoader.hpp" #include #include @@ -27,7 +27,7 @@ DEFINE_TYPE(ScoreSaber::ReplaySystem::Playback, PosePlayer); namespace ScoreSaber::ReplaySystem::Playback { - void PosePlayer::ctor(GlobalNamespace::MainCamera* mainCamera, GlobalNamespace::SaberManager* saberManager, GlobalNamespace::IReturnToMenuController* returnToMenuController, GlobalNamespace::PlayerTransforms* playerTransforms, BeatSaber::GameSettings::MainSettingsHandler* mainSettingsHandler, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController) + void PosePlayer::ctor(GlobalNamespace::MainCamera* mainCamera, GlobalNamespace::SaberManager* saberManager, GlobalNamespace::IReturnToMenuController* returnToMenuController, GlobalNamespace::PlayerTransforms* playerTransforms, GlobalNamespace::SettingsManager* settingsManager, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController) { INVOKE_CTOR(); _mainCamera = mainCamera; @@ -36,7 +36,7 @@ namespace ScoreSaber::ReplaySystem::Playback _returnToMenuController = returnToMenuController; _spectatorOffset = Vector3(0, 0, -2); _playerTransforms = playerTransforms; - _mainSettingsHandler = mainSettingsHandler; + _settingsManager = settingsManager; _audioTimeSyncController = audioTimeSyncController; } void PosePlayer::Initialize() @@ -64,8 +64,8 @@ namespace ScoreSaber::ReplaySystem::Playback GameObject* spectatorObject = GameObject::New_ctor("SpectatorParent"); _spectatorCamera = UnityEngine::Object::Instantiate(_desktopCamera); - spectatorObject->transform->position = Vector3(_mainSettingsHandler->instance->roomCenter.x + _spectatorOffset.x, _mainSettingsHandler->instance->roomCenter.y + _spectatorOffset.y, _mainSettingsHandler->instance->roomCenter.z + _spectatorOffset.z); - Quaternion rotation = Quaternion::Euler(0.0f, _mainSettingsHandler->instance->roomRotation, 0.0f); + spectatorObject->transform->position = Vector3(_settingsManager->settings.room.center.x + _spectatorOffset.x, _settingsManager->settings.room.center.y + _spectatorOffset.y, _settingsManager->settings.room.center.z + _spectatorOffset.z); + Quaternion rotation = Quaternion::Euler(0.0f, _settingsManager->settings.room.rotation, 0.0f); spectatorObject->transform->rotation = rotation; _spectatorCamera->stereoTargetEye = StereoTargetEyeMask::Both; @@ -167,7 +167,7 @@ namespace ScoreSaber::ReplaySystem::Playback } void PosePlayer::SetSpectatorOffset(Vector3 value) { - _spectatorCamera->transform->parent->position = Vector3(_mainSettingsHandler->instance->roomCenter.x + value.x, _mainSettingsHandler->instance->roomCenter.y + value.y, _mainSettingsHandler->instance->roomCenter.z + value.z); + _spectatorCamera->transform->parent->position = Vector3(_settingsManager->settings.room.center.x + value.x, _settingsManager->settings.room.center.y + value.y, _settingsManager->settings.room.center.z + value.z); _spectatorOffset = value; } diff --git a/src/ReplaySystem/Recorders/MetadataRecorder.cpp b/src/ReplaySystem/Recorders/MetadataRecorder.cpp index 71fcd27e..159bbe03 100644 --- a/src/ReplaySystem/Recorders/MetadataRecorder.cpp +++ b/src/ReplaySystem/Recorders/MetadataRecorder.cpp @@ -1,7 +1,6 @@ #include "ReplaySystem/Recorders/MetadataRecorder.hpp" #include "Data/Private/ReplayFile.hpp" #include "Services/UploadService.hpp" -#include #include #include #include @@ -25,14 +24,14 @@ DEFINE_TYPE(ScoreSaber::ReplaySystem::Recorders, MetadataRecorder); namespace ScoreSaber::ReplaySystem::Recorders { - void MetadataRecorder::ctor(AudioTimeSyncController* audioTimeSyncController, GameplayCoreSceneSetupData* gameplayCoreSceneSetupData, BeatmapObjectSpawnController::InitData* beatmapObjectSpawnControllerInitData, GameEnergyCounter* gameEnergyCounter, BeatSaber::GameSettings::MainSettingsHandler* mainSettingsHandler) + void MetadataRecorder::ctor(AudioTimeSyncController* audioTimeSyncController, GameplayCoreSceneSetupData* gameplayCoreSceneSetupData, BeatmapObjectSpawnController::InitData* beatmapObjectSpawnControllerInitData, GameEnergyCounter* gameEnergyCounter, GlobalNamespace::SettingsManager* settingsManager) { INVOKE_CTOR(); _audioTimeSyncController = audioTimeSyncController; _beatmapObjectSpawnControllerInitData = beatmapObjectSpawnControllerInitData; _gameEnergyCounter = gameEnergyCounter; _gameplayCoreSceneSetupData = gameplayCoreSceneSetupData; - _mainSettingsHandler = mainSettingsHandler; + _settingsManager = settingsManager; } void MetadataRecorder::Initialize() @@ -60,13 +59,13 @@ namespace ScoreSaber::ReplaySystem::Recorders metadata->LevelID = (string)_gameplayCoreSceneSetupData->beatmapLevel->levelID; metadata->Difficulty = BeatmapDifficultyMethods::DefaultRating(_gameplayCoreSceneSetupData->beatmapKey.difficulty); metadata->Characteristic = (string)_gameplayCoreSceneSetupData->beatmapKey.beatmapCharacteristic->serializedName; - metadata->Environment = (string)_gameplayCoreSceneSetupData->environmentInfo->serializedName; + metadata->Environment = (string)_gameplayCoreSceneSetupData->targetEnvironmentInfo->serializedName; metadata->Modifiers = ScoreSaber::Services::UploadService::GetModifierList(_gameplayCoreSceneSetupData->gameplayModifiers, -1); metadata->NoteSpawnOffset = _beatmapObjectSpawnControllerInitData->noteJumpValue; metadata->LeftHanded = _gameplayCoreSceneSetupData->playerSpecificSettings->leftHanded; metadata->InitialHeight = _gameplayCoreSceneSetupData->playerSpecificSettings->playerHeight; - metadata->RoomRotation = _mainSettingsHandler->instance->roomRotation; - metadata->RoomCenter = VRPosition(_mainSettingsHandler->instance->roomCenter.x, _mainSettingsHandler->instance->roomCenter.y, _mainSettingsHandler->instance->roomCenter.z); + metadata->RoomRotation = _settingsManager->settings.room.rotation; + metadata->RoomCenter = VRPosition(_settingsManager->settings.room.center.x, _settingsManager->settings.room.center.y, _settingsManager->settings.room.center.z); metadata->FailTime = _failTime; return metadata; } diff --git a/src/ReplaySystem/ReplayLoader.cpp b/src/ReplaySystem/ReplayLoader.cpp index 8b052fa2..0cae3d6f 100644 --- a/src/ReplaySystem/ReplayLoader.cpp +++ b/src/ReplaySystem/ReplayLoader.cpp @@ -94,7 +94,8 @@ namespace ScoreSaber::ReplaySystem::ReplayLoader byref(beatmapKey), // beatmapKey beatmapLevel, // beatmapLevel playerData->overrideEnvironmentSettings, // overrideEnvironmentSettings - playerData->colorSchemesSettings->GetOverrideColorScheme(), // overrideColorScheme + playerData->colorSchemesSettings->GetOverrideColorScheme(), // playerOverrideColorScheme + playerData->colorSchemesSettings->ShouldOverrideLightshowColors(), // playerOverrideLightshowColors beatmapLevel->GetColorScheme(beatmapKey.beatmapCharacteristic, beatmapKey.difficulty), // beatmapOverrideColorScheme BeatmapUtils::GetModifiersFromStrings(LoadedReplay->metadata->Modifiers), // gameplayModifiers playerSettings, // playerSpecificSettings diff --git a/src/ReplaySystem/UI/ImberSpecsReporter.cpp b/src/ReplaySystem/UI/ImberSpecsReporter.cpp index ba65fadf..2ed67b50 100644 --- a/src/ReplaySystem/UI/ImberSpecsReporter.cpp +++ b/src/ReplaySystem/UI/ImberSpecsReporter.cpp @@ -31,7 +31,7 @@ namespace ScoreSaber::ReplaySystem::UI { if (DidReport != nullptr) { - DidReport(pose.FPS, _saberManager->leftSaber->movementData->bladeSpeed, _saberManager->rightSaber->movementData->bladeSpeed); + DidReport(pose.FPS, _saberManager->leftSaber->movementDataForLogic->bladeSpeed, _saberManager->rightSaber->movementDataForLogic->bladeSpeed); } } void ImberSpecsReporter::Dispose() diff --git a/src/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.cpp b/src/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.cpp index 5dc43a7e..973fb5c7 100644 --- a/src/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.cpp +++ b/src/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.cpp @@ -11,6 +11,7 @@ #include using namespace BSML; +using namespace GlobalNamespace; DEFINE_TYPE(ScoreSaber::UI::Multiplayer, ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager); diff --git a/src/UI/Other/ProfilePictureView.cpp b/src/UI/Other/ProfilePictureView.cpp index 1df59586..d3ce8e0c 100644 --- a/src/UI/Other/ProfilePictureView.cpp +++ b/src/UI/Other/ProfilePictureView.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include "questui/ArrayUtil.hpp" #include "Utils/OperatorOverloads.hpp" diff --git a/src/UI/Other/ScoreSaberLeaderboardView.cpp b/src/UI/Other/ScoreSaberLeaderboardView.cpp index 4d7ef4a9..f1778f50 100644 --- a/src/UI/Other/ScoreSaberLeaderboardView.cpp +++ b/src/UI/Other/ScoreSaberLeaderboardView.cpp @@ -270,10 +270,10 @@ namespace ScoreSaber::UI::Other::ScoreSaberLeaderboardView } ::Array* array = ::Array::New({ - IconSegmentedControl::DataItem::New_ctor(globalLeaderboardIcon, "Global"), - IconSegmentedControl::DataItem::New_ctor(aroundPlayerLeaderboardIcon, "Around You"), - IconSegmentedControl::DataItem::New_ctor(friendsLeaderboardIcon, "Friends"), - IconSegmentedControl::DataItem::New_ctor(countryLeaderboardIcon, mode == "region" ? "Region" : "Country"), + IconSegmentedControl::DataItem::New_ctor(globalLeaderboardIcon, "Global", true), + IconSegmentedControl::DataItem::New_ctor(aroundPlayerLeaderboardIcon, "Around You", true), + IconSegmentedControl::DataItem::New_ctor(friendsLeaderboardIcon, "Friends", true), + IconSegmentedControl::DataItem::New_ctor(countryLeaderboardIcon, mode == "region" ? "Region" : "Country", true), }); scopeSegmentedControl->SetData(array); diff --git a/src/UI/ViewControllers/FAQViewController.cpp b/src/UI/ViewControllers/FAQViewController.cpp index 7abe857b..bc2bacb2 100644 --- a/src/UI/ViewControllers/FAQViewController.cpp +++ b/src/UI/ViewControllers/FAQViewController.cpp @@ -10,7 +10,7 @@ #include "Utils/UIUtils.hpp" #include #include -#include +#include #include "Utils/StrippedMethods.hpp" #include "Sprites.hpp" diff --git a/src/UI/ViewControllers/TeamViewController.cpp b/src/UI/ViewControllers/TeamViewController.cpp index 056a9900..b799b89d 100644 --- a/src/UI/ViewControllers/TeamViewController.cpp +++ b/src/UI/ViewControllers/TeamViewController.cpp @@ -88,7 +88,7 @@ namespace ScoreSaber::UI::ViewControllers teamAndContributorsNames.push_back("CAT"); teamAndContributorsNames.push_back("CCT"); - segmentedController->SetTexts(teamAndContributorsNames.getPtr()->i___System__Collections__Generic__IReadOnlyList_1_T_()); + segmentedController->SetTexts(teamAndContributorsNames.getPtr()->i___System__Collections__Generic__IReadOnlyList_1_T_(), nullptr); creditTabs = Array>::NewLength(teamAndContributorsNames.size()); diff --git a/src/Utils/MaxScoreCache.cpp b/src/Utils/MaxScoreCache.cpp index 067dd4f1..9c1df755 100644 --- a/src/Utils/MaxScoreCache.cpp +++ b/src/Utils/MaxScoreCache.cpp @@ -3,6 +3,9 @@ #include #include #include +#include "GlobalNamespace/zzzz__BeatmapLevelDataVersion_def.hpp" +#include "GlobalNamespace/zzzz__BeatmapLevelsEntitlementModel_def.hpp" +#include "System/Threading/zzzz__CancellationToken_def.hpp" #include "Utils/DelegateUtils.hpp" #include "Utils/SafePtr.hpp" #include "Utils/GCUtil.hpp" @@ -17,11 +20,12 @@ using namespace BSML; DEFINE_TYPE(ScoreSaber::Utils, MaxScoreCache); namespace ScoreSaber::Utils { - void MaxScoreCache::ctor(BeatmapDataLoader* beatmapDataLoader, BeatmapLevelsModel* beatmapLevelsModel) { + void MaxScoreCache::ctor(BeatmapDataLoader* beatmapDataLoader, BeatmapLevelsModel* beatmapLevelsModel, BeatmapLevelsEntitlementModel* beatmapLevelsEntitlementModel) { INVOKE_CTOR(); _beatmapDataLoader = beatmapDataLoader; _beatmapLevelsModel = beatmapLevelsModel; + _beatmapLevelsEntitlementModel = beatmapLevelsEntitlementModel; } void MaxScoreCache::GetMaxScore(BeatmapLevel* beatmapLevel, BeatmapKey beatmapKey, const function &callback) { @@ -35,28 +39,32 @@ namespace ScoreSaber::Utils { FixedSafePtr beatmapLevelSafe(beatmapLevel); MainThreadScheduler::Schedule(gc_aware_function([self, beatmapLevelSafe, beatmapKeySafe, callback] { - DelegateHelper::ContinueWith(self->_beatmapLevelsModel->LoadBeatmapLevelDataAsync(beatmapKeySafe->levelId, CancellationToken::get_None()), std::function(gc_aware_function( - [self, beatmapLevelSafe, beatmapKeySafe, callback](LoadBeatmapLevelDataResult beatmapLevelDataResult) { - MainThreadScheduler::Schedule(gc_aware_function([self, beatmapLevelSafe, beatmapKeySafe, callback, beatmapLevelDataResult]() { - DelegateHelper::ContinueWith(self->_beatmapDataLoader->LoadBeatmapDataAsync( - beatmapLevelDataResult.beatmapLevelData, // ::GlobalNamespace::IBeatmapLevelData *beatmapLevelData, - *beatmapKeySafe, // ::GlobalNamespace::BeatmapKey beatmapKey, - beatmapLevelSafe->beatsPerMinute, // float_t startBpm, - false, // bool loadingForDesignatedEnvironment, - nullptr, // ::GlobalNamespace::IEnvironmentInfo *environmentInfo, - nullptr, // ::GlobalNamespace::GameplayModifiers *gameplayModifiers, - nullptr, // ::GlobalNamespace::PlayerSpecificSettings *playerSpecificSettings, - false// bool enableBeatmapDataCaching - ), std::function(gc_aware_function( - [self, beatmapKeySafe, callback](IReadonlyBeatmapData *beatmapData) { - INFO("step D"); - int maxScore = ScoreModel::ComputeMaxMultipliedScoreForBeatmap(beatmapData); - INFO("step E"); - self->cache[beatmapKeySafe] = maxScore; - callback(maxScore); - } - ))); - })); + DelegateHelper::ContinueWith(self->_beatmapLevelsEntitlementModel->GetLevelDataVersionAsync(beatmapKeySafe->levelId, CancellationToken::get_None()), std::function(gc_aware_function( + [self, beatmapLevelSafe, beatmapKeySafe, callback](BeatmapLevelDataVersion beatmapLevelDataVersion) { + DelegateHelper::ContinueWith(self->_beatmapLevelsModel->LoadBeatmapLevelDataAsync(beatmapKeySafe->levelId, beatmapLevelDataVersion, CancellationToken::get_None()), std::function(gc_aware_function( + [self, beatmapLevelSafe, beatmapKeySafe, callback, beatmapLevelDataVersion](LoadBeatmapLevelDataResult beatmapLevelDataResult) { + MainThreadScheduler::Schedule(gc_aware_function([self, beatmapLevelSafe, beatmapKeySafe, callback, beatmapLevelDataVersion, beatmapLevelDataResult]() { + DelegateHelper::ContinueWith(self->_beatmapDataLoader->LoadBeatmapDataAsync( + beatmapLevelDataResult.beatmapLevelData, // ::GlobalNamespace::IBeatmapLevelData *beatmapLevelData, + *beatmapKeySafe, // ::GlobalNamespace::BeatmapKey beatmapKey, + beatmapLevelSafe->beatsPerMinute, // float_t startBpm, + false, // bool loadingForDesignatedEnvironment, + nullptr, // ::GlobalNamespace::IEnvironmentInfo *targetEnvironmentInfo + nullptr, // ::GlobalNamespace::IEnvironmentInfo *originalEnvironmentInfo + beatmapLevelDataVersion,// ::GlobalNamespace::BeatmapLevelDataVersion beatmapLevelDataVersion + nullptr, // ::GlobalNamespace::GameplayModifiers *gameplayModifiers, + nullptr, // ::GlobalNamespace::PlayerSpecificSettings *playerSpecificSettings, + false// bool enableBeatmapDataCaching + ), std::function(gc_aware_function( + [self, beatmapKeySafe, callback](IReadonlyBeatmapData *beatmapData) { + int maxScore = ScoreModel::ComputeMaxMultipliedScoreForBeatmap(beatmapData); + self->cache[beatmapKeySafe] = maxScore; + callback(maxScore); + } + ))); + })); + } + ))); } ))); })); diff --git a/src/Utils/StringUtils.cpp b/src/Utils/StringUtils.cpp index c7f93543..0cb9c96b 100644 --- a/src/Utils/StringUtils.cpp +++ b/src/Utils/StringUtils.cpp @@ -11,7 +11,7 @@ #include #include #include "logging.hpp" -#include +#include #include "Utils/StrippedMethods.hpp" static std::string color_prefix = " #include #include -#include +#include #include "questui/ArrayUtil.hpp" #include "Utils/StrippedMethods.hpp" #include "Utils/SafePtr.hpp" From 9b3ee6818382463fb69a2e25703683b3fac57c7d Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Wed, 12 Nov 2025 23:29:58 +0100 Subject: [PATCH 02/18] 1.40 replays --- include/Data/Private/ReplayFile.hpp | 23 +- include/ReplaySystem/Playback/NotePlayer.hpp | 1 + include/Utils/semver.hpp | 417 ++++++++++++++++++ src/Data/Private/ReplayFile.cpp | 46 +- src/Data/Private/ReplayReader.cpp | 24 +- src/Data/Private/ReplayWriter.cpp | 5 +- src/ReplaySystem/Playback/NotePlayer.cpp | 3 +- .../Recorders/MetadataRecorder.cpp | 11 +- 8 files changed, 514 insertions(+), 16 deletions(-) create mode 100644 include/Utils/semver.hpp diff --git a/include/Data/Private/ReplayFile.hpp b/include/Data/Private/ReplayFile.hpp index be4e2829..7d2f69f4 100644 --- a/include/Data/Private/ReplayFile.hpp +++ b/include/Data/Private/ReplayFile.hpp @@ -9,6 +9,8 @@ #include #include +#include "Utils/semver.hpp" + using namespace std; namespace ScoreSaber::Data::Private @@ -84,6 +86,16 @@ namespace ScoreSaber::Data::Private Bomb }; + enum ScoringType_pre1_40 { + Ignore = -1, + NoScore, + Normal, + SliderHead, + SliderTail, + BurstSliderHead, + BurstSliderElement + }; + struct NoteID { NoteID(); @@ -97,6 +109,8 @@ namespace ScoreSaber::Data::Private std::optional GameplayType; std::optional ScoringType; std::optional CutDirectionAngleOffset; + + bool MatchesScoringType(GlobalNamespace::NoteData_ScoringType comparedScoringType, optional gameVersion) const; }; struct EnergyEvent @@ -138,9 +152,9 @@ namespace ScoreSaber::Data::Private struct Metadata { Metadata(); - Metadata(string Version, string LevelID, int Difficulty, string Characteristic, string Environment, vector Modifiers, float NoteSpawnOffset, - bool LeftHanded, float InitialHeight, float RoomRotation, VRPosition RoomCenter, float FailTime); - string Version; + Metadata(semver::version Version, string LevelID, int Difficulty, string Characteristic, string Environment, vector Modifiers, float NoteSpawnOffset, + bool LeftHanded, float InitialHeight, float RoomRotation, VRPosition RoomCenter, float FailTime, optional GameVersion, optional PluginVersion, optional Platform); + semver::version Version; string LevelID; int Difficulty; string Characteristic; @@ -152,6 +166,9 @@ namespace ScoreSaber::Data::Private float RoomRotation; VRPosition RoomCenter; float FailTime; + optional GameVersion; + optional PluginVersion; + optional Platform; }; struct NoteEvent diff --git a/include/ReplaySystem/Playback/NotePlayer.hpp b/include/ReplaySystem/Playback/NotePlayer.hpp index 008e69ac..04665607 100644 --- a/include/ReplaySystem/Playback/NotePlayer.hpp +++ b/include/ReplaySystem/Playback/NotePlayer.hpp @@ -49,6 +49,7 @@ DECLARE_CLASS_CODEGEN_INTERFACES( DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); std::vector _sortedNoteEvents; std::vector _recognizedNoteCutInfos; + std::shared_ptr _replayFile; // std::map _recognizedNoteCutInfos; // System::Collections::Generic::Dictionary_2 * _recognizedNoteCutInfos; void ProcessEvent(Data::Private::NoteEvent &activeEvent); diff --git a/include/Utils/semver.hpp b/include/Utils/semver.hpp new file mode 100644 index 00000000..58dab77c --- /dev/null +++ b/include/Utils/semver.hpp @@ -0,0 +1,417 @@ +/* +License: MIT (http://opensource.org/licenses/MIT). + +Copyright (c) 2024 Peter Csajtai + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef Z4KN4FEIN_SEMVER_H +#define Z4KN4FEIN_SEMVER_H + +#ifndef SEMVER_MODULE +#include +#include +#include +#include +#include + +// conditionally include and its dependency for C++20 +#ifdef __cpp_lib_format +#if __cpp_lib_format >= 201907L +#include +#include +#endif +#endif +#endif + +#ifdef SEMVER_MODULE +#define SEMVER_EXPORT export +#else +#define SEMVER_EXPORT +#endif + +namespace semver +{ + const std::string default_prerelease_part = "0"; + const std::string numbers = "0123456789"; + const std::string prerelease_allowed_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"; + const std::string version_pattern = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)" + "(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))" + "?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"; + const std::string loose_version_pattern = "^v?(0|[1-9]\\d*)(?:\\.(0|[1-9]\\d*))?(?:\\.(0|[1-9]\\d*))" + "?(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))" + "?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"; + + SEMVER_EXPORT struct semver_exception : public std::runtime_error { + explicit semver_exception(const std::string& message) : std::runtime_error(message) { } + }; + + inline uint64_t parse_numeric_part(const std::string& version_part) + { + return static_cast(std::stoull(version_part)); + } + + inline std::vector split(const std::string& text, const char& delimiter) { + std::size_t pos_start = 0, pos_end, delim_len = 1; + std::string current; + std::vector result; + + while ((pos_end = text.find(delimiter, pos_start)) != std::string::npos) { + current = text.substr(pos_start, pos_end - pos_start); + pos_start = pos_end + delim_len; + result.push_back(current); + } + + result.push_back(text.substr(pos_start)); + return result; + } + + inline bool is_numeric(const std::string& text) { + return text.find_first_not_of(numbers) == std::string::npos; + } + + inline bool is_valid_prerelease(const std::string& text) { + return text.find_first_not_of(numbers + prerelease_allowed_chars) == std::string::npos; + } + + class prerelease_part { + private: + bool m_numeric = false; + std::string m_value; + uint64_t m_numeric_value; + public: + explicit prerelease_part(const std::string& part) { + if (part.empty()) { + throw semver_exception("Pre-release identity contains an empty part."); + } + + if (is_numeric(part)) { + if (part.size() > 1 && part[0] == '0') { + throw semver_exception( + "Pre-release part '" + part + "' is numeric but contains a leading zero."); + } + m_numeric_value = parse_numeric_part(part); + m_numeric = true; + } + if (!is_valid_prerelease(part)) { + throw semver_exception( + "Pre-release part '" + part + "' contains an invalid character."); + } + m_value = part; + } + + [[nodiscard]] bool numeric() const { return m_numeric; } + [[nodiscard]] std::string value() const { return m_value; } + [[nodiscard]] uint64_t numeric_value() const { return m_numeric_value; } + + [[nodiscard]] int compare(const prerelease_part& other) const { + if (m_numeric && !other.m_numeric) return -1; + if (!m_numeric && other.m_numeric) return 1; + if (m_numeric) { + return (m_numeric_value < other.m_numeric_value) ? -1 : (m_numeric_value > other.m_numeric_value); + } + return (m_value < other.m_value) ? -1 : (m_value > other.m_value); + } + }; + + SEMVER_EXPORT class prerelease_descriptor { + private: + std::vector m_parts; + std::string prerelease_str; + + explicit prerelease_descriptor(const std::vector& parts) + : m_parts(parts) { + if (parts.empty()) prerelease_str = ""; + for (const auto &part : parts) { + if (!prerelease_str.empty()) prerelease_str += "."; + prerelease_str += part.value(); + } + } + public: + [[nodiscard]] std::string str() const { return prerelease_str; } + [[nodiscard]] bool is_empty() const { return m_parts.empty(); } + + [[nodiscard]] std::string identity() const { + if (is_empty()) return ""; + return m_parts.front().value(); + } + + [[nodiscard]] prerelease_descriptor increment() const { + std::vector new_parts = (m_parts); + size_t last_numeric_index = 0; + bool last_numeric_index_found = false; + for (size_t i = 0; i < new_parts.size(); ++i) { + if (new_parts[i].numeric()){ + last_numeric_index = i; + last_numeric_index_found = true; + } + } + if (last_numeric_index_found) { + prerelease_part last = new_parts[last_numeric_index]; + new_parts[last_numeric_index] = prerelease_part(std::to_string(last.numeric_value() + 1)); + } else { + new_parts.emplace_back(default_prerelease_part); + } + return prerelease_descriptor(new_parts); + } + + [[nodiscard]] int compare(const prerelease_descriptor& other) const { + auto this_size = m_parts.size(); + auto other_size = other.m_parts.size(); + + auto count = std::min(this_size, other_size); + for (size_t i = 0; i < count; ++i) { + int cmp = m_parts[i].compare(other.m_parts[i]); + if (cmp != 0) return cmp; + } + return (this_size < other_size) ? -1 : (this_size > other_size); + } + + bool operator<(const prerelease_descriptor& other) const { + return compare(other) == -1; + } + + bool operator>(const prerelease_descriptor& other) const { + return (other < *this); + } + + bool operator==(const prerelease_descriptor& other) const { + return prerelease_str == other.prerelease_str; + } + + bool operator!=(const prerelease_descriptor& other) const { + return prerelease_str != other.prerelease_str; + } + + static prerelease_descriptor parse(const std::string& prerelease_part_str) { + if (prerelease_part_str.empty()) return empty(); + std::vector prerelease_parts; + std::vector parts = split(prerelease_part_str, '.'); + for(auto& part : parts) { + prerelease_parts.emplace_back(part); + } + return prerelease_descriptor(prerelease_parts); + } + + static prerelease_descriptor empty() { + return prerelease_descriptor({}); + } + + static prerelease_descriptor initial() { + return prerelease_descriptor::parse(default_prerelease_part); + } + }; + + SEMVER_EXPORT enum inc { major, minor, patch, prerelease }; + + SEMVER_EXPORT class version { + private: + uint64_t m_major; + uint64_t m_minor; + uint64_t m_patch; + prerelease_descriptor m_prerelease; + std::string m_build_meta; + + [[nodiscard]] int compare(const version& other) const { + if (m_major > other.m_major) return 1; + if (m_major < other.m_major) return -1; + if (m_minor > other.m_minor) return 1; + if (m_minor < other.m_minor) return -1; + if (m_patch > other.m_patch) return 1; + if (m_patch < other.m_patch) return -1; + if (!m_prerelease.is_empty() && other.m_prerelease.is_empty()) return -1; + if (m_prerelease.is_empty() && !other.m_prerelease.is_empty()) return 1; + if (!m_prerelease.is_empty() && !other.m_prerelease.is_empty()) return m_prerelease.compare(other.m_prerelease); + return 0; + } + public: + explicit version(uint64_t major = 0, + uint64_t minor = 0, + uint64_t patch = 0, + const std::string& prerelease = "", + std::string build_meta = "") + : m_major{major}, + m_minor{minor}, + m_patch{patch}, + m_prerelease{prerelease_descriptor::parse(prerelease)}, + m_build_meta{std::move(build_meta)} { } + + [[nodiscard]] uint64_t major() const { return m_major; } + [[nodiscard]] uint64_t minor() const { return m_minor; } + [[nodiscard]] uint64_t patch() const { return m_patch; } + [[nodiscard]] std::string prerelease() const { return m_prerelease.str(); } + [[nodiscard]] std::string build_meta() const { return m_build_meta; } + + [[nodiscard]] bool is_prerelease() const { return !m_prerelease.is_empty(); } + [[nodiscard]] bool is_stable() const { return m_major > 0 && m_prerelease.is_empty(); } + + [[nodiscard]] std::string str() const { + std::string result = std::to_string(m_major) + "." + std::to_string(m_minor) + "." + std::to_string(m_patch); + if (!m_prerelease.is_empty()) result += "-" + m_prerelease.str(); + if (!m_build_meta.empty()) result += "+" + m_build_meta; + return result; + } + + [[nodiscard]] version without_suffixes() const { + return version(m_major, m_minor, m_patch); + } + + [[nodiscard]] version next_major(const std::string& prerelease = "") const { + return version(m_major + 1, 0, 0, prerelease); + } + + [[nodiscard]] version next_minor(const std::string& prerelease = "") const { + return version(m_major, m_minor + 1, 0, prerelease); + } + + [[nodiscard]] version next_patch(const std::string& prerelease = "") const { + return version(m_major, m_minor, (!is_prerelease() || !prerelease.empty() ? m_patch + 1 : m_patch), prerelease); + } + + [[nodiscard]] version next_prerelease(const std::string& prerelease = "") const { + std::string pre = default_prerelease_part; + if (!prerelease.empty()) { + pre = is_prerelease() && m_prerelease.identity() == prerelease ? m_prerelease.increment().str() : prerelease; + } else if (prerelease.empty() && is_prerelease()) { + pre = m_prerelease.increment().str(); + } + return version(m_major, m_minor, is_prerelease() ? m_patch : m_patch + 1, pre); + } + + [[nodiscard]] version increment(inc by, const std::string& prerelease = "") const { + switch (by) { + case semver::major: return next_major(prerelease); + case semver::minor: return next_minor(prerelease); + case semver::patch: return next_patch(prerelease); + case semver::prerelease: return next_prerelease(prerelease); + default: throw semver_exception("Invalid 'by' parameter in 'increment()' function."); + } + } + + bool operator<(const version& other) const { + return compare(other) == -1; + } + + bool operator<=(const version& other) const { + return compare(other) <= 0; + } + + bool operator>(const version& other) const { + return compare(other) == 1; + } + + bool operator>=(const version& other) const { + return compare(other) >= 0; + } + + bool operator==(const version& other) const { + return compare(other) == 0; + } + + bool operator!=(const version& other) const { + return compare(other) != 0; + } + + // conditionally provide three-way operator for C++20 + #ifdef __cpp_impl_three_way_comparison + #if __cpp_impl_three_way_comparison >= 201907L + + auto operator<=>(const version& other) const { + return compare(other); + } + + #endif + #endif + + static version parse(const std::string& version_str, bool strict = true) { + std::regex regex(strict ? version_pattern : loose_version_pattern); + std::cmatch match; + uint64_t major; + uint64_t minor; + uint64_t patch; + std::string prerelease; + std::string build_meta; + + if (!std::regex_match(version_str.c_str(), match, regex)) { + throw semver_exception("Invalid version: " + version_str); + } + + auto major_m = match[1]; + auto minor_m = match[2]; + auto patch_m = match[3]; + auto prerelease_m = match[4]; + auto build_meta_m = match[5]; + + if (prerelease_m.matched) prerelease = prerelease_m.str(); + if (build_meta_m.matched) build_meta = build_meta_m.str(); + + try { + if (strict && major_m.matched && minor_m.matched && patch_m.matched) { + major = parse_numeric_part(major_m); + minor = parse_numeric_part(minor_m); + patch = parse_numeric_part(patch_m); + } else if (!strict && major_m.matched) { + major = parse_numeric_part(major_m); + minor = minor_m.matched ? parse_numeric_part(minor_m) : 0; + patch = patch_m.matched ? parse_numeric_part(patch_m) : 0; + } else { + throw semver_exception("Invalid version: " + version_str); + } + + return version(major, minor, patch, prerelease, build_meta); + } catch (std::exception& exception) { + throw semver_exception("Version parse error: " + std::string(exception.what())); + } + } + }; + + SEMVER_EXPORT inline std::ostream & operator<<(std::ostream& str, const version& version) { + for (const auto s : version.str()) str.put(s); + return str; + } + + namespace literals + { + SEMVER_EXPORT inline version operator""_v(const char* text, std::size_t length) { + return version::parse(std::string(text, length)); + } + + SEMVER_EXPORT inline version operator""_lv(const char* text, std::size_t length) { + return version::parse(std::string(text, length), false); + } + } +} + +// conditionally provide formatter for C++20 +#ifdef __cpp_lib_format +#if __cpp_lib_format >= 201907L + +template +struct std::formatter : std::formatter { + template + auto format(const semver::version& version, FormatContext& ctx) const { + return std::formatter::format(version.str(), ctx); + } +}; + +#endif +#endif + +#endif // Z4KN4FEIN_SEMVER_H \ No newline at end of file diff --git a/src/Data/Private/ReplayFile.cpp b/src/Data/Private/ReplayFile.cpp index b6664112..d3369683 100644 --- a/src/Data/Private/ReplayFile.cpp +++ b/src/Data/Private/ReplayFile.cpp @@ -3,8 +3,16 @@ #include #include +#include "Utils/semver.hpp" + +using namespace GlobalNamespace; + namespace ScoreSaber::Data::Private { + namespace RelevantGameVersions { + const auto Version_1_40 = semver::version::parse("1.40.0"); + }; + UnityEngine::Vector3 VRVector3(Data::Private::VRPosition pose) { @@ -119,6 +127,37 @@ namespace ScoreSaber::Data::Private NoteID::NoteID(){}; + bool NoteID::MatchesScoringType(GlobalNamespace::NoteData_ScoringType comparedScoringType, optional gameVersion) const + { + if (ScoringType) { + if(!gameVersion || gameVersion < RelevantGameVersions::Version_1_40) { + switch(ScoringType.value()) { + case ScoringType_pre1_40::Ignore: return comparedScoringType == NoteData_ScoringType::Ignore; + case ScoringType_pre1_40::NoScore: return comparedScoringType == NoteData_ScoringType::NoScore; + case ScoringType_pre1_40::Normal: return comparedScoringType == NoteData_ScoringType::Normal; + case ScoringType_pre1_40::SliderHead: + if (comparedScoringType == NoteData_ScoringType::ArcHeadArcTail) return true; + if (comparedScoringType == NoteData_ScoringType::ChainLinkArcHead) return true; + return comparedScoringType == NoteData_ScoringType::ArcHead; + case ScoringType_pre1_40::SliderTail: + if (comparedScoringType == NoteData_ScoringType::ArcHeadArcTail) return true; + if (comparedScoringType == NoteData_ScoringType::ChainHeadArcTail) return true; + return comparedScoringType == NoteData_ScoringType::ArcTail; + case ScoringType_pre1_40::BurstSliderHead: + if (comparedScoringType == NoteData_ScoringType::ChainHeadArcTail) return true; + return comparedScoringType == NoteData_ScoringType::ChainHead; + case ScoringType_pre1_40::BurstSliderElement: + if (comparedScoringType == NoteData_ScoringType::ChainLinkArcHead) return true; + return comparedScoringType == NoteData_ScoringType::ChainLink; + } + } + + // if it's none of the special versions handled above the scoring types should be compatible to our current scoring type. + return ScoringType.value() == (int)comparedScoringType; + } + return true; + } + EnergyEvent::EnergyEvent(float _Energy, float _Time) { Energy = _Energy; @@ -155,8 +194,8 @@ namespace ScoreSaber::Data::Private VRPoseGroup::VRPoseGroup(){}; - Metadata::Metadata(string _Version, string _LevelID, int _Difficulty, string _Characteristic, string _Environment, vector _Modifiers, - float _NoteSpawnOffset, bool _LeftHanded, float _InitialHeight, float _RoomRotation, VRPosition _RoomCenter, float _FailTime) + Metadata::Metadata(semver::version _Version, string _LevelID, int _Difficulty, string _Characteristic, string _Environment, vector _Modifiers, + float _NoteSpawnOffset, bool _LeftHanded, float _InitialHeight, float _RoomRotation, VRPosition _RoomCenter, float _FailTime, optional _GameVersion, optional _PluginVersion, optional _Platform) { Version = _Version; LevelID = _LevelID; @@ -170,6 +209,9 @@ namespace ScoreSaber::Data::Private RoomRotation = _RoomRotation; RoomCenter = _RoomCenter; FailTime = _FailTime; + GameVersion = _GameVersion; + PluginVersion = _PluginVersion; + Platform = _Platform; } Metadata::Metadata(){}; diff --git a/src/Data/Private/ReplayReader.cpp b/src/Data/Private/ReplayReader.cpp index ffa2dbea..8357bd4b 100644 --- a/src/Data/Private/ReplayReader.cpp +++ b/src/Data/Private/ReplayReader.cpp @@ -2,13 +2,10 @@ #include "Utils/lzma/lzma.hpp" -#include -#include #include #include -#include "Services/PlayerService.hpp" - +#include "Utils/semver.hpp" #include "logging.hpp" #include "static.hpp" @@ -28,8 +25,8 @@ namespace ScoreSaber::Data::Private::ReplayReader shared_ptr metadata = ReadMetadata(inputStream, pointers.metadata); - INFO("Found replay with version {:s}", metadata->Version.c_str()); - if (metadata->Version == "2.0.0") { + INFO("Found replay with version {:s}", metadata->Version.str()); + if (metadata->Version == semver::version::parse("2.0.0")) { return make_shared(metadata, ReadPoseKeyframes(inputStream, pointers.poseKeyframes), ReadHeightKeyframes(inputStream, pointers.heightKeyframes), @@ -38,7 +35,7 @@ namespace ScoreSaber::Data::Private::ReplayReader ReadComboKeyframes(inputStream, pointers.comboKeyframes), ReadMultiplierKeyframes(inputStream, pointers.multiplierKeyframes), ReadEnergyKeyframes(inputStream, pointers.energyKeyframes)); - } else if (metadata->Version == "3.0.0") { + } else if (metadata->Version <= semver::version::parse("3.1.0")) { return make_shared(metadata, ReadPoseKeyframes(inputStream, pointers.poseKeyframes), ReadHeightKeyframes(inputStream, pointers.heightKeyframes), @@ -66,9 +63,20 @@ namespace ScoreSaber::Data::Private::ReplayReader shared_ptr ReadMetadata(stringstream& inputStream, int offset) { inputStream.seekg(offset); - return make_shared(ReadString(inputStream), ReadString(inputStream), ReadInt(inputStream), ReadString(inputStream), + + semver::version version = semver::version::parse(ReadString(inputStream)); + + if(version < semver::version::parse("3.1.0")) { + return make_shared(version, ReadString(inputStream), ReadInt(inputStream), ReadString(inputStream), ReadString(inputStream), ReadStringArray(inputStream), ReadFloat(inputStream), ReadBool(inputStream), ReadFloat(inputStream), ReadFloat(inputStream), ReadVRPosition(inputStream), ReadFloat(inputStream)); + } else { + return make_shared(version, ReadString(inputStream), ReadInt(inputStream), ReadString(inputStream), + ReadString(inputStream), ReadStringArray(inputStream), ReadFloat(inputStream), ReadBool(inputStream), + ReadFloat(inputStream), ReadFloat(inputStream), ReadVRPosition(inputStream), ReadFloat(inputStream), + semver::version::parse(ReadString(inputStream)), + semver::version::parse(ReadString(inputStream)), ReadString(inputStream)); + } } vector ReadPoseKeyframes(stringstream& inputStream, int offset) diff --git a/src/Data/Private/ReplayWriter.cpp b/src/Data/Private/ReplayWriter.cpp index de43297c..420af7fa 100644 --- a/src/Data/Private/ReplayWriter.cpp +++ b/src/Data/Private/ReplayWriter.cpp @@ -71,7 +71,7 @@ namespace ScoreSaber::Data::Private::ReplayWriter int WriteMetadata(std::shared_ptr metadata, stringstream& outputStream) { int bytesWritten = 0; - bytesWritten += WriteString(metadata->Version, outputStream); + bytesWritten += WriteString(metadata->Version.str(), outputStream); bytesWritten += WriteString(metadata->LevelID, outputStream); bytesWritten += WriteInt(metadata->Difficulty, outputStream); bytesWritten += WriteString(metadata->Characteristic, outputStream); @@ -83,6 +83,9 @@ namespace ScoreSaber::Data::Private::ReplayWriter bytesWritten += WriteFloat(metadata->RoomRotation, outputStream); bytesWritten += WriteVRPosition(metadata->RoomCenter, outputStream); bytesWritten += WriteFloat(metadata->FailTime, outputStream); + bytesWritten += WriteString(metadata->GameVersion.value().str(), outputStream); + bytesWritten += WriteString(metadata->PluginVersion.value().str(), outputStream); + bytesWritten += WriteString(metadata->Platform.value(), outputStream); return bytesWritten; } diff --git a/src/ReplaySystem/Playback/NotePlayer.cpp b/src/ReplaySystem/Playback/NotePlayer.cpp index 6e89bcd2..0c27f15f 100644 --- a/src/ReplaySystem/Playback/NotePlayer.cpp +++ b/src/ReplaySystem/Playback/NotePlayer.cpp @@ -37,6 +37,7 @@ namespace ScoreSaber::ReplaySystem::Playback std::sort(_sortedNoteEvents.begin(), _sortedNoteEvents.end(), [](const auto& lhs, const auto& rhs) { return lhs.Time < rhs.Time; }); + _replayFile = ReplayLoader::LoadedReplay; } void NotePlayer::Tick() { @@ -126,7 +127,7 @@ namespace ScoreSaber::ReplaySystem::Playback return false; } - if (id.ScoringType.has_value() && id.ScoringType.value() != (int)noteData->scoringType) { + if (!id.MatchesScoringType(noteData->scoringType, _replayFile->metadata->GameVersion)) { return false; } diff --git a/src/ReplaySystem/Recorders/MetadataRecorder.cpp b/src/ReplaySystem/Recorders/MetadataRecorder.cpp index 159bbe03..713b0a98 100644 --- a/src/ReplaySystem/Recorders/MetadataRecorder.cpp +++ b/src/ReplaySystem/Recorders/MetadataRecorder.cpp @@ -12,8 +12,10 @@ #include #include #include +#include #include #include +#include "Utils/semver.hpp" #include "logging.hpp" using namespace UnityEngine; @@ -55,7 +57,7 @@ namespace ScoreSaber::ReplaySystem::Recorders { StringW csc; auto metadata = make_shared(); - metadata->Version = "3.0.0"; + metadata->Version = semver::version::parse("3.1.0"); metadata->LevelID = (string)_gameplayCoreSceneSetupData->beatmapLevel->levelID; metadata->Difficulty = BeatmapDifficultyMethods::DefaultRating(_gameplayCoreSceneSetupData->beatmapKey.difficulty); metadata->Characteristic = (string)_gameplayCoreSceneSetupData->beatmapKey.beatmapCharacteristic->serializedName; @@ -67,6 +69,13 @@ namespace ScoreSaber::ReplaySystem::Recorders metadata->RoomRotation = _settingsManager->settings.room.rotation; metadata->RoomCenter = VRPosition(_settingsManager->settings.room.center.x, _settingsManager->settings.room.center.y, _settingsManager->settings.room.center.z); metadata->FailTime = _failTime; + string gameVersion = (string)Application::get_version(); + if(gameVersion.find_first_of('_') != string::npos) { + gameVersion = gameVersion.substr(0, gameVersion.find_first_of('_')); + } + metadata->GameVersion = semver::version::parse(gameVersion); + metadata->PluginVersion = semver::version::parse(VERSION); + metadata->Platform = "Quest"; return metadata; } } // namespace ScoreSaber::ReplaySystem::Recorders \ No newline at end of file From 1b570e81e7b594c8bb790b2d5fc63144576873ba Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Wed, 12 Nov 2025 23:43:07 +0100 Subject: [PATCH 03/18] fixed missing parameters --- src/Data/Private/ReplayReader.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Data/Private/ReplayReader.cpp b/src/Data/Private/ReplayReader.cpp index 8357bd4b..4e7b9594 100644 --- a/src/Data/Private/ReplayReader.cpp +++ b/src/Data/Private/ReplayReader.cpp @@ -2,6 +2,7 @@ #include "Utils/lzma/lzma.hpp" +#include #include #include @@ -69,7 +70,8 @@ namespace ScoreSaber::Data::Private::ReplayReader if(version < semver::version::parse("3.1.0")) { return make_shared(version, ReadString(inputStream), ReadInt(inputStream), ReadString(inputStream), ReadString(inputStream), ReadStringArray(inputStream), ReadFloat(inputStream), ReadBool(inputStream), - ReadFloat(inputStream), ReadFloat(inputStream), ReadVRPosition(inputStream), ReadFloat(inputStream)); + ReadFloat(inputStream), ReadFloat(inputStream), ReadVRPosition(inputStream), ReadFloat(inputStream), + nullopt, nullopt, nullopt); } else { return make_shared(version, ReadString(inputStream), ReadInt(inputStream), ReadString(inputStream), ReadString(inputStream), ReadStringArray(inputStream), ReadFloat(inputStream), ReadBool(inputStream), From 12a8b8d28d098ca6efcfddf10fbfc91452a9a71d Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Wed, 12 Nov 2025 23:51:15 +0100 Subject: [PATCH 04/18] fix scrubbing with hud off --- include/ReplaySystem/Playback/EnergyPlayer.hpp | 6 +++--- src/ReplaySystem/Playback/EnergyPlayer.cpp | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/ReplaySystem/Playback/EnergyPlayer.hpp b/include/ReplaySystem/Playback/EnergyPlayer.hpp index 25b8fa7c..bfaeb763 100644 --- a/include/ReplaySystem/Playback/EnergyPlayer.hpp +++ b/include/ReplaySystem/Playback/EnergyPlayer.hpp @@ -1,18 +1,18 @@ #pragma once #include "Data/Private/ReplayFile.hpp" -#include #include #include +#include #include #include #include DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Playback, EnergyPlayer, Il2CppObject) { - DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyCounter); DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _gameEnergyUIPanel); - DECLARE_CTOR(ctor, GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::GameEnergyCounter* gameEnergyCounter, Zenject::DiContainer* container); + DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _playerDataModel); + DECLARE_CTOR(ctor, GlobalNamespace::GameEnergyCounter* gameEnergyCounter, GlobalNamespace::PlayerDataModel* playerDataModel, Zenject::DiContainer* container); DECLARE_INSTANCE_METHOD(void, TimeUpdate, float songTime); vector _sortedEnergyEvents; void UpdateEnergy(float energy); diff --git a/src/ReplaySystem/Playback/EnergyPlayer.cpp b/src/ReplaySystem/Playback/EnergyPlayer.cpp index 4c10f8f5..dd89c8e1 100644 --- a/src/ReplaySystem/Playback/EnergyPlayer.cpp +++ b/src/ReplaySystem/Playback/EnergyPlayer.cpp @@ -1,5 +1,7 @@ #include "ReplaySystem/Playback/EnergyPlayer.hpp" #include "ReplaySystem/ReplayLoader.hpp" +#include +#include #include #include #include @@ -16,11 +18,11 @@ DEFINE_TYPE(ScoreSaber::ReplaySystem::Playback, EnergyPlayer); namespace ScoreSaber::ReplaySystem::Playback { - void EnergyPlayer::ctor(GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::GameEnergyCounter* gameEnergyCounter, Zenject::DiContainer* container) + void EnergyPlayer::ctor(GlobalNamespace::GameEnergyCounter* gameEnergyCounter, GlobalNamespace::PlayerDataModel* playerDataModel, Zenject::DiContainer* container) { INVOKE_CTOR(); - _audioTimeSyncController = audioTimeSyncController; _gameEnergyCounter = gameEnergyCounter; + _playerDataModel = playerDataModel; _gameEnergyUIPanel = container->TryResolve(); _sortedEnergyEvents = ReplayLoader::LoadedReplay->energyKeyframes; } @@ -56,7 +58,7 @@ namespace ScoreSaber::ReplaySystem::Playback _gameEnergyCounter->energy = energy; _gameEnergyCounter->noFail = noFail; - if (_gameEnergyUIPanel != nullptr) { + if (_gameEnergyUIPanel != nullptr && !_playerDataModel->playerData->playerSpecificSettings->noTextsAndHuds) { _gameEnergyUIPanel->Init(); auto director = _gameEnergyUIPanel->_playableDirector; director->Stop(); From 5fc4756703af08b166de504b2f697cc48d1a7fee Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Thu, 13 Nov 2025 00:04:03 +0100 Subject: [PATCH 05/18] implement metacore score submissions --- src/Hooks/LeaderboardHooks.cpp | 9 +++++++-- src/ReplaySystem/ReplayLoader.cpp | 4 +++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Hooks/LeaderboardHooks.cpp b/src/Hooks/LeaderboardHooks.cpp index 0e01a912..f1246e1f 100644 --- a/src/Hooks/LeaderboardHooks.cpp +++ b/src/Hooks/LeaderboardHooks.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "hooks.hpp" #include "UI/Other/ScoreSaberLeaderboardView.hpp" @@ -108,7 +109,9 @@ MAKE_AUTO_HOOK_MATCH(StandardLevelScenesTransitionSetupDataSO_Finish, &GlobalNam GlobalNamespace::StandardLevelScenesTransitionSetupDataSO* self, GlobalNamespace::LevelCompletionResults* levelCompletionResults) { - ScoreSaber::Services::UploadService::Three(self, levelCompletionResults); + if(!MetaCore::Game::IsScoreSubmissionDisabled()) { + ScoreSaber::Services::UploadService::Three(self, levelCompletionResults); + } StandardLevelScenesTransitionSetupDataSO_Finish(self, levelCompletionResults); } @@ -116,6 +119,8 @@ MAKE_AUTO_HOOK_MATCH(MultiplayerLevelScenesTransitionSetupDataSO_Finish, &Global GlobalNamespace::MultiplayerLevelScenesTransitionSetupDataSO* self, GlobalNamespace::MultiplayerResultsData* multiplayerResultsData) { - ScoreSaber::Services::UploadService::Four(self, multiplayerResultsData); + if(!MetaCore::Game::IsScoreSubmissionDisabled()) { + ScoreSaber::Services::UploadService::Four(self, multiplayerResultsData); + } MultiplayerLevelScenesTransitionSetupDataSO_Finish(self, multiplayerResultsData); } \ No newline at end of file diff --git a/src/ReplaySystem/ReplayLoader.cpp b/src/ReplaySystem/ReplayLoader.cpp index 0cae3d6f..97a4470c 100644 --- a/src/ReplaySystem/ReplayLoader.cpp +++ b/src/ReplaySystem/ReplayLoader.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "Utils/BeatmapUtils.hpp" #include "Utils/SafePtr.hpp" #include "Utils/WebUtils.hpp" @@ -109,7 +110,8 @@ namespace ScoreSaber::ReplaySystem::ReplayLoader replayEndDelegate, // levelFinishedCallback nullptr, // levelRestartedCallback {false, {}} // recordingToolData (set to null) - ); + ); + MetaCore::Game::DisableScoreSubmissionOnce(MOD_ID); IsPlaying = true; } From 583d3987136687a66280e314ca7008d0e02e9b3f Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Thu, 13 Nov 2025 00:27:21 +0100 Subject: [PATCH 06/18] revert back to bshook SafePtrs --- include/ReplaySystem/ReplayLoader.hpp | 6 +- include/UI/Other/ProfilePictureView.hpp | 5 +- .../UI/Other/ScoreSaberLeaderboardView.hpp | 7 +- include/Utils/DelegateUtils.hpp | 7 +- include/Utils/MaxScoreCache.hpp | 12 +- include/Utils/SafePtr.hpp | 609 +----------------- src/CustomTypes/Components/CellClicker.cpp | 3 +- src/ReplaySystem/ReplayLoader.cpp | 10 +- src/ReplaySystem/UI/ImberManager.cpp | 3 +- src/ReplaySystem/UI/ImberScrubber.cpp | 5 +- src/ReplaySystem/UI/ImberSpecsReporter.cpp | 3 +- .../UI/ResultsViewReplayButtonController.cpp | 7 +- src/Services/LeaderboardService.cpp | 3 +- src/Services/ReplayService.cpp | 2 +- src/Services/UploadService.cpp | 3 +- ...erLevelSelectionLeaderboardFlowManager.cpp | 3 +- ...ltiplayerResultsLeaderboardFlowManager.cpp | 3 +- src/UI/Other/Banner.cpp | 5 +- src/UI/Other/ProfilePictureView.cpp | 8 +- src/UI/Other/ScoreSaberLeaderboardView.cpp | 21 +- .../ViewControllers/GlobalViewController.cpp | 3 +- src/Utils/MaxScoreCache.cpp | 6 +- src/Utils/SafePtr.cpp | 33 - src/Utils/UIUtils.cpp | 3 +- src/main.cpp | 2 - 25 files changed, 66 insertions(+), 706 deletions(-) delete mode 100644 src/Utils/SafePtr.cpp diff --git a/include/ReplaySystem/ReplayLoader.hpp b/include/ReplaySystem/ReplayLoader.hpp index 5bef82a4..db52b800 100644 --- a/include/ReplaySystem/ReplayLoader.hpp +++ b/include/ReplaySystem/ReplayLoader.hpp @@ -12,11 +12,11 @@ namespace ScoreSaber::ReplaySystem::ReplayLoader { extern std::shared_ptr LoadedReplay; - extern FixedSafeValueType CurrentBeatmapKey; - extern FixedSafePtr CurrentBeatmapLevel; + extern SafeValueType CurrentBeatmapKey; + extern SafePtr CurrentBeatmapLevel; extern std::u16string CurrentPlayerName; extern std::string CurrentModifiers; - extern FixedSafePtr NotePlayerInstance; + extern SafePtr NotePlayerInstance; extern bool IsPlaying; void StartReplay(GlobalNamespace::BeatmapLevel* beatmapLevel, GlobalNamespace::BeatmapKey beatmapKey); diff --git a/include/UI/Other/ProfilePictureView.hpp b/include/UI/Other/ProfilePictureView.hpp index 11915d32..e1b5c4dd 100644 --- a/include/UI/Other/ProfilePictureView.hpp +++ b/include/UI/Other/ProfilePictureView.hpp @@ -5,13 +5,12 @@ #include #include #include -#include "Utils/SafePtr.hpp" namespace ScoreSaber::UI::Other { // shouldn't need to be a C# class until we switch over to BSML class ProfilePictureView { - FixedSafePtrUnity profileImage; - FixedSafePtrUnity loadingIndicator; + SafePtrUnity profileImage; + SafePtrUnity loadingIndicator; void OnAvatarDownloadSuccess(UnityEngine::Sprite* a, int pos, std::string url, System::Threading::CancellationToken cancellationToken); void OnAvatarDownloadFailure(std::string error, int pos, System::Threading::CancellationToken cancellationToken); public: diff --git a/include/UI/Other/ScoreSaberLeaderboardView.hpp b/include/UI/Other/ScoreSaberLeaderboardView.hpp index 4a456bf2..7c2d4c81 100644 --- a/include/UI/Other/ScoreSaberLeaderboardView.hpp +++ b/include/UI/Other/ScoreSaberLeaderboardView.hpp @@ -9,7 +9,6 @@ #include "Data/LeaderboardInfo.hpp" #include "Data/Score.hpp" #include "UI/Other/Banner.hpp" -#include "Utils/SafePtr.hpp" using namespace GlobalNamespace; @@ -21,9 +20,9 @@ namespace ScoreSaber::UI::Other::ScoreSaberLeaderboardView Down, }; - extern FixedSafePtrUnity ScoreSaberBanner; - extern FixedSafePtrUnity leaderboardScoreInfoButtonHandler; - extern std::vector> _cellClickingImages; + extern SafePtrUnity ScoreSaberBanner; + extern SafePtrUnity leaderboardScoreInfoButtonHandler; + extern std::vector> _cellClickingImages; void OnSoftRestart(); diff --git a/include/Utils/DelegateUtils.hpp b/include/Utils/DelegateUtils.hpp index ca56dae3..17692bf2 100644 --- a/include/Utils/DelegateUtils.hpp +++ b/include/Utils/DelegateUtils.hpp @@ -3,7 +3,6 @@ #include #include #include -#include "Utils/SafePtr.hpp" // Credits to https://github.com/kodenamekrak/Cinema/blob/7cab615b4a0fa3e35c6ee3076334d25823718bd4/include/Util/DelegateHelper.hpp @@ -83,12 +82,12 @@ namespace DelegateUtils this->internalCSharpDelegate = custom_types::MakeDelegate(function); return *this; } - constexpr FixedSafePtr* operator->() noexcept { return &internalCSharpDelegate; } - constexpr FixedSafePtr const* operator->() const noexcept { return &internalCSharpDelegate; } + constexpr SafePtr* operator->() noexcept { return &internalCSharpDelegate; } + constexpr SafePtr const* operator->() const noexcept { return &internalCSharpDelegate; } constexpr operator bool() const noexcept { return internalCSharpDelegate; } private: - FixedSafePtr internalCSharpDelegate; + SafePtr internalCSharpDelegate; }; template diff --git a/include/Utils/MaxScoreCache.hpp b/include/Utils/MaxScoreCache.hpp index 58aec915..da0f6e8c 100644 --- a/include/Utils/MaxScoreCache.hpp +++ b/include/Utils/MaxScoreCache.hpp @@ -17,8 +17,8 @@ // create std::hash and std::equal_to for BeatmapKey so we can use it as a key in std::unordered_map namespace std { template<> - struct hash> { - size_t operator()(const FixedSafeValueType &key) const { + struct hash> { + size_t operator()(const SafeValueType &key) const { auto hashA = key->beatmapCharacteristic->serializedName->GetHashCode(); auto hashB = (int)key->difficulty; auto hashC = key->levelId->GetHashCode(); @@ -32,8 +32,8 @@ namespace std { }; template<> - struct equal_to> { - bool operator()(const FixedSafeValueType &lhs, const FixedSafeValueType &rhs) const { + struct equal_to> { + bool operator()(const SafeValueType &lhs, const SafeValueType &rhs) const { return GlobalNamespace::BeatmapKey::op_Equality(*lhs, *rhs); } }; @@ -46,8 +46,8 @@ DECLARE_CLASS_CODEGEN(ScoreSaber::Utils, MaxScoreCache, Il2CppObject) { DECLARE_CTOR(ctor, GlobalNamespace::BeatmapDataLoader* beatmapDataLoader, GlobalNamespace::BeatmapLevelsModel* beatmapLevelsModel, GlobalNamespace::BeatmapLevelsEntitlementModel* beatmapLevelsEntitlementModel); - // the cache needs to store BeatmapKeys as FixedSafeValueType so GC cannot collect any of its members. - std::unordered_map, int> cache; + // the cache needs to store BeatmapKeys as SafeValueType so GC cannot collect any of its members. + std::unordered_map, int> cache; public: void GetMaxScore(GlobalNamespace::BeatmapLevel* beatmapLevel, GlobalNamespace::BeatmapKey beatmapKey, const std::function &callback); }; \ No newline at end of file diff --git a/include/Utils/SafePtr.hpp b/include/Utils/SafePtr.hpp index 7f493b82..eeb72075 100644 --- a/include/Utils/SafePtr.hpp +++ b/include/Utils/SafePtr.hpp @@ -3,9 +3,6 @@ #include #include "logging.hpp" -// This file is a copy of the SafePtr classes from typedefs-wrapper.hpp with the changes from https://github.com/QuestPackageManager/beatsaber-hook/pull/33 -// TODO: delete this and use the original versions if the changes are (a) backported or (b) we move on to 1.40 - #if __has_feature(cxx_exceptions) #define __SAFE_PTR_NULL_HANDLE_CHECK(handle, ...) \ @@ -19,510 +16,28 @@ CRASH_UNLESS(false) #endif -extern std::unordered_map safePtrCache; - -/// @brief A thread-safe, static type that holds a mapping from addresses to reference counts. -struct FixedCounter { - /// @brief Adds to the reference count of an address. If the address does not exist, initializes a new entry for it to 1. - /// @param addr The address to add. - static void add(void* addr) { - std::unique_lock lock(mutex); - auto itr = addrRefCount.find(addr); - if (itr != addrRefCount.end()) { - ++itr->second; - } else { - addrRefCount.emplace(addr, 1); - } - } - /// @brief Decreases the reference count of an address. If the address has 1 or fewer references, erases it. - /// @param addr The address to decrease. - static void remove(void* addr) { - std::unique_lock lock(mutex); - auto itr = addrRefCount.find(addr); - if (itr != addrRefCount.end() && itr->second > 1) { - --itr->second; - } else if (itr != addrRefCount.end()) { - addrRefCount.erase(itr); - } else { - SAFE_ABORT_MSG("Tried to remove a non-existent address from FixedCounter!"); - } - } - /// @brief Gets the reference count of an address, or 0 if no such address exists. - /// @param addr The address to get the count of. - /// @return The reference count of the provided address. - static size_t get(void* addr) { - std::shared_lock lock(mutex); - auto itr = addrRefCount.find(addr); - if (itr != addrRefCount.end()) { - return itr->second; - } else { - return 0; - } - } - - private: - static std::unordered_map addrRefCount; - static std::shared_mutex mutex; -}; - -/// @brief Represents a smart pointer that has a reference count, which does NOT destroy the held instance on refcount reaching 0. -/// @tparam T The type to wrap as a pointer. -template -struct FixedCountPointer { - /// @brief Default constructor for Count Pointer, defaults to a nullptr, with 0 references. - explicit FixedCountPointer() : ptr(nullptr) {} - /// @brief Construct a count pointer from the provided pointer, adding to the reference count (if non-null) for the provided pointer. - /// @param p The pointer to provide. May be null, which does nothing. - explicit FixedCountPointer(T* p) : ptr(p) { - if (p) { - FixedCounter::add(p); - } - } - /// @brief Copy constructor, copies and adds to the reference count for the held non-null pointer. - FixedCountPointer(const FixedCountPointer& other) : ptr(other.ptr) { - if (ptr) { - FixedCounter::add(ptr); - } - } - /// @brief Move constructor moves the pointer and keeps the reference count the same. - FixedCountPointer(FixedCountPointer&& other) { - ptr = other.ptr; - other.ptr = nullptr; - } - /// @brief Destructor, decreases the ref count for the held non-null pointer. - ~FixedCountPointer() { - if (ptr) { - FixedCounter::remove(ptr); - } - } - /// @brief Gets the reference count held by this pointer. - /// @return The reference count for this pointer, or 0 if the held pointer is null. - size_t count() const { - if (ptr) { - return FixedCounter::get(ptr); - } - return 0; - } - /// @brief Emplaces a new pointer into the shared pointer, decreasing the existing ref count as necessary. - /// @param val The new pointer to replace the currently held one with. - inline void emplace(T* val) { - if (val != ptr) { - if (ptr) { - FixedCounter::remove(ptr); - } - ptr = val; - if (ptr) { - FixedCounter::add(ptr); - } - } - } - /// Assignment operator. - FixedCountPointer& operator=(T* val) { - emplace(val); - return *this; - } - /// Dereference operator. - T& operator*() noexcept { - if (ptr) { - return *ptr; - } - SAFE_ABORT(); - return *ptr; - } - const T& operator*() const noexcept { - if (ptr) { - return *ptr; - } - SAFE_ABORT(); - return *ptr; - } - T* operator->() noexcept { - if (ptr) { - return ptr; - } - SAFE_ABORT(); - return nullptr; - } - T* const operator->() const noexcept { - if (ptr) { - return ptr; - } - SAFE_ABORT(); - return nullptr; - } - constexpr operator bool() const noexcept { - return ptr != nullptr; - } - /// @brief Performs an il2cpp type checked cast from T to U. - /// This should only be done if both T and U are reference types - /// Currently assumes the `klass` field is the first pointer in T. - /// This function may throw TypeCastException or crash. - /// See try_cast for a version that does not. - /// @tparam U The type to cast to. - /// @return A new CountPointer of the cast value. - template - [[nodiscard]] inline FixedCountPointer cast() const { - // TODO: We currently assume that the first sizeof(void*) bytes of ptr is the klass field. - // This should hold true for everything except value types. - auto* k1 = CRASH_UNLESS(classof(U*)); - auto* k2 = *CRASH_UNLESS(reinterpret_cast(ptr)); - CRASH_UNLESS(k2); - il2cpp_functions::Init(); - if (il2cpp_functions::class_is_assignable_from(k1, k2)) { - return FixedCountPointer(reinterpret_cast(ptr)); - } -#if __has_feature(cxx_exceptions) - throw TypeCastException(); -#else - SAFE_ABORT(); - return CountPointer(); -#endif - } - /// @brief Performs an il2cpp type checked cast from T to U. - /// This should only be done if both T and U are reference types - /// Currently assumes the `klass` field is the first pointer in T. - /// @tparam U The type to cast to. - /// @return A new CountPointer of the cast value, if successful. - template - [[nodiscard]] inline std::optional> try_cast() const noexcept { - auto* k1 = classof(U*); - if (!ptr || !k1) { - return std::nullopt; - } - auto* k2 = *reinterpret_cast(ptr); - if (!k2) { - return std::nullopt; - } - il2cpp_functions::Init(); - if (il2cpp_functions::class_is_assignable_from(k1, k2)) { - return CountPointer(reinterpret_cast(ptr)); - } - return std::nullopt; - } - - /// @brief Get the raw pointer. Should ALMOST NEVER BE USED, UNLESS SCOPE GUARANTEES IT DIES BEFORE THIS INSTANCE DOES! - /// @return The raw pointer saved by this instance. - constexpr T* const __internal_get() const noexcept { - return ptr; - } - - private: - T* ptr; -}; - -// TODO: Make an overall Ptr interface type, virtual destructor and *, -> operators -// TODO: Remove all conversion operators? (Basically force people to guarantee lifetime of held instance?) - -// Fd UnityEngine.Object -#ifdef HAS_CODEGEN -namespace UnityEngine { -class Object; -} -#endif - -template -struct FixedSafePtrUnity; - -// Until we are sure everyone uses the fixed counting, cache enough elements and never actually ask the GC for new objects later on -// This is a temporary solution until we can ensure that all SafePtrs are FixedSafePtrs - -void reserve_safe_ptrs(size_t count); -void* alloc_safe_ptr(size_t sz); -void free_safe_ptr(void* ptr); - - -/// @brief Represents a C++ type that wraps a C# pointer that will be valid for the entire lifetime of this instance. -/// This instance must be created at a time such that il2cpp_functions::Init is valid, or else it will throw a CreatedTooEarlyException -/// @tparam T The type of the instance to wrap. -/// @tparam AllowUnity Whether to permit convertible Unity Object types to be wrapped. -template -struct FixedSafePtr { -#ifdef HAS_CODEGEN - static_assert(!std::is_assignable_v || AllowUnity, "Don't use Unity types with SafePtr. Ignore this warning by specifying SafePtr"); -#endif - /// @brief Default constructor. Should be paired with emplace or = to ensure validity. - FixedSafePtr() {} - /// @brief Construct a SafePtr with the provided instance pointer (which may be nullptr). - /// If you wish to wrap a non-existent pointer (ex, use as a default constructor) see the 0 arg constructor instead. - FixedSafePtr(T* wrappableInstance) : internalHandle(SafePointerWrapper::New(wrappableInstance)) {} - /// @brief Construct a SafePtr with the provided wrapper - FixedSafePtr(T& wrappableInstance) - requires(il2cpp_utils::has_il2cpp_conversion) - : internalHandle(SafePointerWrapper::New(wrappableInstance.convert())) {} - /// @brief Construct a SafePtr with the provided wrapper - FixedSafePtr(T&& wrappableInstance) - requires(il2cpp_utils::has_il2cpp_conversion) - : internalHandle(SafePointerWrapper::New(wrappableInstance.convert())) {} - /// @brief Construct a SafePtr with the provided reference - FixedSafePtr(T& wrappableInstance) - requires(!il2cpp_utils::has_il2cpp_conversion) - : internalHandle(SafePointerWrapper::New(std::addressof(wrappableInstance))) {} - /// @brief Move constructor is default, moves the internal handle and keeps reference count the same. - FixedSafePtr(FixedSafePtr&& other) = default; - /// @brief Copy constructor copies the HANDLE, that is, the held pointer remains the same. - /// Note that this means if you modify one SafePtr's held instance, all others that point to the same location will also reflect this change. - /// In order to avoid a (small) performance overhead, consider using a reference type instead of a value type, or the move constructor instead. - FixedSafePtr(const FixedSafePtr& other) : internalHandle(other.internalHandle) {} - /// @brief Destructor. Destroys the internal wrapper type, if necessary. - /// Aborts if a wrapper type exists and must be freed, yet GC_free does not exist. - ~FixedSafePtr() { - clear(); - } - - /// @brief Destroys the internal wrapper type, if necessary. - /// Aborts if a wrapper type exists and must be freed, yet GC_free does not exist. - inline void clear() { - if (!internalHandle) { - // Clearing up without an internal handle is trivial - return; - } - // If our internal handle has 1 instance, we need to clean up the instance it points to. - // Otherwise, some other SafePtr is currently holding a reference to this instance, so keep it around. - if (internalHandle.count() <= 1) { - if(!safePtrCache.contains(internalHandle.__internal_get())) { - SAFE_ABORT_MSG("The object is not cached!"); - } - if(safePtrCache[internalHandle.__internal_get()] != internalHandle->instancePointer) { - SAFE_ABORT_MSG("The object has been changed externally! (is {}, expected {})", fmt::ptr(safePtrCache[internalHandle.__internal_get()]), fmt::ptr(internalHandle->instancePointer)); - } - safePtrCache.erase(internalHandle.__internal_get()); - internalHandle->instancePointer = nullptr; - free_safe_ptr(internalHandle.__internal_get()); - - /*il2cpp_functions::Init(); - #ifdef UNITY_2021 - il2cpp_functions::gc_free_fixed(internalHandle.__internal_get()); - #else - if (!il2cpp_functions::hasGCFuncs) { - SAFE_ABORT_MSG("Cannot use SafePtr without GC functions!"); - } - il2cpp_functions::GC_free(internalHandle.__internal_get()); - #endif*/ - } - - // ensure we don't try to clear the same handle twice - internalHandle = nullptr; - } - - /// @brief Emplace a new value into this SafePtr, freeing an existing one, if it exists. - /// @param other The instance to emplace. - inline void emplace(T& other) { - clear(); - internalHandle = SafePointerWrapper::New(std::addressof(other)); - } - - /// @brief Emplace a new value into this SafePtr, freeing an existing one, if it exists. - /// @param other The instance to emplace. - inline void emplace(T* other) { - clear(); - internalHandle = SafePointerWrapper::New(other); - } - - /// @brief Emplace a new pointer into this SafePtr, managing the existing one, if it exists. - /// @param other The CountPointer to copy during the emplace. - inline void emplace(FixedCountPointer& other) { - // Clear existing instance as necessary - clear(); - // Copy other into handle - internalHandle = other; - } - - /// @brief Move an existing CountPointer into this SafePtr, deleting the existing one, if necessary. - /// @param other The CountPointer to move during this call. - inline void move(FixedCountPointer& other) { - // Clear existing instance as necessary - clear(); - // Move into handle - internalHandle = std::move(other); - } - - inline FixedSafePtr& operator=(T* other) { - emplace(other); - return *this; - } - - inline FixedSafePtr& operator=(T& other) { - emplace(other); - return *this; - } - /// @brief Performs an il2cpp type checked cast from T to U. - /// This should only be done if both T and U are reference types - /// Currently assumes the `klass` field is the first pointer in T. - /// This function may throw TypeCastException or NullHandleException or otherwise abort. - /// See try_cast for a version that does not. - /// @tparam U The type to cast to. - /// @tparam AllowUnityPrime Whether the casted SafePtr should allow unity conversions. - /// @return A new SafePtr of the cast value. - template - [[nodiscard]] inline FixedSafePtr cast() const { - // TODO: We currently assume that the first sizeof(void*) bytes of ptr is the klass field. - // This should hold true for everything except value types. - if (!internalHandle) { -#if __has_feature(cxx_exceptions) - throw NullHandleException(); -#else - SAFE_ABORT(); - return SafePtr(); -#endif - } - auto* k1 = CRASH_UNLESS(classof(U*)); - auto* k2 = *CRASH_UNLESS(reinterpret_cast(internalHandle->instancePointer)); - il2cpp_functions::Init(); - if (il2cpp_functions::class_is_assignable_from(k1, k2)) { - return FixedSafePtr(reinterpret_cast(internalHandle->instancePointer)); - } -#if __has_feature(cxx_exceptions) - throw TypeCastException(); -#else - SAFE_ABORT(); - return FixedSafePtr(); -#endif - } - /// @brief Performs an il2cpp type checked cast from T to U. - /// This should only be done if both T and U are reference types - /// Currently assumes the `klass` field is the first pointer in T. - /// @tparam U The type to cast to. - /// @tparam AllowUnityPrime Whether the casted SafePtr should allow unity conversions. - /// @return A new SafePtr of the cast value, if successful. - template - [[nodiscard]] inline std::optional> try_cast() const noexcept { - auto* k1 = classof(U*); - if (!internalHandle || !internalHandle->instancePointer || k1) { - return std::nullopt; - } - auto* k2 = *reinterpret_cast(internalHandle->instancePointer); - if (!k2) { - return std::nullopt; - } - il2cpp_functions::Init(); - if (il2cpp_functions::class_is_assignable_from(k1, k2)) { - return FixedSafePtr(reinterpret_cast(internalHandle->instancePointer)); - } - return std::nullopt; - } - - /// @brief Returns false if this is a defaultly constructed SafePtr, true otherwise. - /// Note that this means that it will return true if it holds a nullptr value explicitly! - /// This means that you should check yourself before calling anything using the held T*. - inline bool isHandleValid() const noexcept { - return static_cast(internalHandle); - } - - T* ptr() { - if(!internalHandle) throw NullHandleException(); - if(!safePtrCache.contains(internalHandle.__internal_get())) { - SAFE_ABORT_MSG("The object is not cached!"); - } - if(safePtrCache[internalHandle.__internal_get()] != internalHandle->instancePointer) { - SAFE_ABORT_MSG("The object has been changed externally! (is {}, expected {})", fmt::ptr(safePtrCache[internalHandle.__internal_get()]), fmt::ptr(internalHandle->instancePointer)); - } - return internalHandle->instancePointer; - } - - T* const ptr() const { - if(!internalHandle) throw NullHandleException(); - if(!safePtrCache.contains(internalHandle.__internal_get())) { - SAFE_ABORT_MSG("The object is not cached!"); - } - if(safePtrCache[internalHandle.__internal_get()] != internalHandle->instancePointer) { - SAFE_ABORT_MSG("The object has been changed externally! (is {}, expected {})", fmt::ptr(safePtrCache[internalHandle.__internal_get()]), fmt::ptr(internalHandle->instancePointer)); - } - return internalHandle->instancePointer; - } - - /// @brief Returns false if this is a defaultly constructed SafePtr, - /// or if the held pointer evaluates to false. - operator bool() const noexcept { - return isHandleValid() && ptr(); - } - - /// @brief Dereferences the instance pointer to a reference type of the held instance. - /// Throws a NullHandleException if there is no internal handle. - [[nodiscard]] T& operator*() { - return *ptr(); - } - - [[nodiscard]] const T& operator*() const { - return *ptr(); - } - - [[nodiscard]] T* const operator->() const { - return const_cast(ptr()); - } - - /// @brief Explicitly cast this instance to a T*. - /// Note, however, that the lifetime of this returned T* is not longer than the lifetime of this instance. - /// Consider passing a SafePtr reference or copy instead. - [[nodiscard]] explicit operator T* const() const { - return const_cast(ptr()); - } - - private: - friend struct FixedSafePtrUnity; - - struct SafePointerWrapper { - static SafePointerWrapper* New(T* instance) { - static constexpr auto sz = sizeof(SafePointerWrapper); - auto* wrapper = reinterpret_cast(alloc_safe_ptr(sz)); - - /*il2cpp_functions::Init(); - // It should be safe to assume that gc_alloc_fixed returns a non-null pointer. If it does return null, we have a pretty big issue. - static constexpr auto sz = sizeof(SafePointerWrapper); - - #ifdef UNITY_2021 - auto* wrapper = reinterpret_cast(il2cpp_functions::gc_alloc_fixed(sz)); - - #else - - if (!il2cpp_functions::hasGCFuncs) { - #if __has_feature(cxx_exceptions) - throw CreatedTooEarlyException(); - #else - SAFE_ABORT_MSG("Cannot use a SafePtr this early/without GC functions!"); - #endif - } - auto* wrapper = reinterpret_cast(il2cpp_functions::GarbageCollector_AllocateFixed(sz, nullptr)); - #endif*/ - - CRASH_UNLESS(wrapper); - wrapper->instancePointer = instance; - - CRASH_UNLESS(!safePtrCache.contains(wrapper)); - safePtrCache[wrapper] = instance; - INFO("Caching SafePtr {} to {}", fmt::ptr(wrapper), fmt::ptr(instance)); - - return wrapper; - } - // Must be explicitly GC freed and allocated - SafePointerWrapper() = delete; - ~SafePointerWrapper() = delete; - T* instancePointer; - }; - FixedCountPointer internalHandle; -}; - /// @brief Represents a C++ type that wraps a C# value type. Makes sure all members of the value type are kept valid. /// This instance must be created at a time such that il2cpp_functions::Init is valid, or else it will throw a CreatedTooEarlyException /// @tparam T The type of the instance to wrap. template -struct FixedSafeValueType { +struct SafeValueType { #ifdef HAS_CODEGEN - static_assert(T::__IL2CPP_IS_VALUE_TYPE, "Only use FixedSafeValueType with value types!"); + static_assert(T::__IL2CPP_IS_VALUE_TYPE, "Only use SafeValueType with value types!"); #endif /// @brief Default constructor. Should be paired with emplace or = to ensure validity. - FixedSafeValueType() {} - /// @brief Construct a FixedSafeValueType with the provided value type. - FixedSafeValueType(const T& wrappableInstance) : internalHandle(SafePointerWrapper::New(wrappableInstance)) {} + SafeValueType() {} + /// @brief Construct a SafeValueType with the provided value type. + SafeValueType(const T& wrappableInstance) : internalHandle(SafePointerWrapper::New(wrappableInstance)) {} /// @brief Move constructor is default, moves the internal handle and keeps reference count the same. - FixedSafeValueType(FixedSafeValueType&& other) = default; + SafeValueType(SafeValueType&& other) = default; /// @brief Copy constructor copies the HANDLE, that is, the held pointer remains the same. /// Note that this means if you modify one SafePtr's held instance, all others that point to the same location will also reflect this change. /// In order to avoid a (small) performance overhead, consider using a reference type instead of a value type, or the move constructor instead. - FixedSafeValueType(const FixedSafeValueType& other) : internalHandle(other.internalHandle) {} + SafeValueType(const SafeValueType& other) : internalHandle(other.internalHandle) {} /// @brief Destructor. Destroys the internal wrapper type, if necessary. /// Aborts if a wrapper type exists and must be freed, yet GC_free does not exist. - ~FixedSafeValueType() { + ~SafeValueType() { clear(); } @@ -558,7 +73,7 @@ struct FixedSafeValueType { internalHandle = SafePointerWrapper::New(other); } - inline FixedSafeValueType& operator=(const T& other) { + inline SafeValueType& operator=(const T& other) { emplace(other); return *this; } @@ -628,111 +143,7 @@ struct FixedSafeValueType { ~SafePointerWrapper() = delete; T instance; }; - FixedCountPointer internalHandle; -}; - -#if __has_feature(cxx_exceptions) -#define __SAFE_PTR_UNITY_NULL_HANDLE_CHECK(...) \ - if (isAlive()) return __VA_ARGS__; \ - throw NullHandleException() - -#else -#include "utils.h" -#define __SAFE_PTR_UNITY_NULL_HANDLE_CHECK(...) \ - if (isAlive()) return __VA_ARGS__; \ - CRASH_UNLESS(false) -#endif - -template -struct FixedSafePtrUnity : public FixedSafePtr { - private: - using Parent = FixedSafePtr; - - public: - FixedSafePtrUnity() = default; - - FixedSafePtrUnity(T* wrappableInstance) : Parent(wrappableInstance) {} - FixedSafePtrUnity(T& wrappableInstance) : Parent(wrappableInstance) {} - FixedSafePtrUnity(Parent&& p) : Parent(p) {} - FixedSafePtrUnity(Parent const& p) : Parent(p) {} - - FixedSafePtrUnity(FixedSafePtrUnity&& p) : Parent(p) {} - FixedSafePtrUnity(FixedSafePtrUnity const& p) : Parent(p) {} - - T* ptr() { - __SAFE_PTR_UNITY_NULL_HANDLE_CHECK(Parent::internalHandle->instancePointer); - } - - T* const ptr() const { - __SAFE_PTR_UNITY_NULL_HANDLE_CHECK(Parent::internalHandle->instancePointer); - } - - inline FixedSafePtrUnity& operator=(T* other) { - Parent::emplace(other); - return *this; - } - - inline FixedSafePtrUnity& operator=(T& other) { - Parent::emplace(other); - return *this; - } - - /// @brief Explicitly cast this instance to a T*. - /// Note, however, that the lifetime of this returned T* is not longer than the lifetime of this instance. - /// Consider passing a SafePtrUnity reference or copy instead. - explicit operator T* const() const { - return const_cast(ptr()); - } - - T* const operator->() { - return const_cast(ptr()); - } - - T* const operator->() const { - return ptr(); - } - - T& operator*() { - return *ptr(); - } - - T const& operator*() const { - return *ptr(); - } - - operator bool() const { - return isAlive(); - } - - template - requires(std::is_assignable_v || std::is_same_v) bool - operator==(FixedSafePtrUnity const& other) const { - if (!other.isAlive() || !isAlive()) { - return other.isAlive() == isAlive(); - } - - return static_cast(other.internalHandle) == static_cast(Parent::ptr()); - } - - template - bool operator==(U const* other) const { - if (!other || !isAlive()) { - return static_cast(other) == isAlive(); - } - - return static_cast(other) == static_cast(Parent::ptr()); - } - - inline bool isAlive() const { -#ifdef HAS_CODEGEN - return static_cast(Parent::internalHandle) && (Parent::ptr()) && Parent::ptr()->m_CachedPtr.m_value.convert(); -#else - // offset yay - // the offset as specified in the codegen header of [m_CachedPtr] is 0x10 - // which is also the first field of the instance UnityEngine.Object - return static_cast(Parent::internalHandle) && (Parent::ptr()) && *reinterpret_cast(reinterpret_cast(Parent::ptr()) + 0x10); -#endif - } + CountPointer internalHandle; }; #undef __SAFE_PTR_NULL_HANDLE_CHECK \ No newline at end of file diff --git a/src/CustomTypes/Components/CellClicker.cpp b/src/CustomTypes/Components/CellClicker.cpp index 53be6010..fc8341d6 100644 --- a/src/CustomTypes/Components/CellClicker.cpp +++ b/src/CustomTypes/Components/CellClicker.cpp @@ -10,7 +10,6 @@ #include #include #include "Utils/OperatorOverloads.hpp" -#include "Utils/SafePtr.hpp" using namespace HMUI; using namespace UnityEngine; @@ -22,7 +21,7 @@ DEFINE_TYPE(ScoreSaber::CustomTypes::Components, CellClicker); namespace ScoreSaber::CustomTypes::Components { // copied from BSML to get the button click sound GlobalNamespace::Signal* getImageClickedSignal() { - static FixedSafePtrUnity imageClickedSignal; + static SafePtrUnity imageClickedSignal; if (!imageClickedSignal) { auto menuShockWave = Resources::FindObjectsOfTypeAll().front_or_default(); imageClickedSignal = menuShockWave ? menuShockWave->_buttonClickEvents.back_or_default() : nullptr; diff --git a/src/ReplaySystem/ReplayLoader.cpp b/src/ReplaySystem/ReplayLoader.cpp index 97a4470c..fcb6a25a 100644 --- a/src/ReplaySystem/ReplayLoader.cpp +++ b/src/ReplaySystem/ReplayLoader.cpp @@ -33,15 +33,15 @@ using namespace BSML::Helpers; namespace ScoreSaber::ReplaySystem::ReplayLoader { - FixedSafePtrUnity playerDataModel; - FixedSafePtrUnity menuTransitionsHelper; + SafePtrUnity playerDataModel; + SafePtrUnity menuTransitionsHelper; std::shared_ptr LoadedReplay; - FixedSafeValueType CurrentBeatmapKey; - FixedSafePtr CurrentBeatmapLevel; + SafeValueType CurrentBeatmapKey; + SafePtr CurrentBeatmapLevel; std::u16string CurrentPlayerName; std::string CurrentModifiers; - FixedSafePtr NotePlayerInstance; + SafePtr NotePlayerInstance; bool IsPlaying; diff --git a/src/ReplaySystem/UI/ImberManager.cpp b/src/ReplaySystem/UI/ImberManager.cpp index 2b4e8b51..2e6140bb 100644 --- a/src/ReplaySystem/UI/ImberManager.cpp +++ b/src/ReplaySystem/UI/ImberManager.cpp @@ -7,7 +7,6 @@ #include #include #include -#include "Utils/SafePtr.hpp" #include "Utils/StringUtils.hpp" #include "logging.hpp" @@ -67,7 +66,7 @@ namespace ScoreSaber::ReplaySystem::UI void ImberManager::Initialize() { - FixedSafePtr self(this); + SafePtr self(this); _mainImberPanelView->DidClickLoop = [self]() { self->MainImberPanelView_DidClickLoop(); diff --git a/src/ReplaySystem/UI/ImberScrubber.cpp b/src/ReplaySystem/UI/ImberScrubber.cpp index 632ceae6..cda1c915 100644 --- a/src/ReplaySystem/UI/ImberScrubber.cpp +++ b/src/ReplaySystem/UI/ImberScrubber.cpp @@ -12,7 +12,6 @@ #include #include #include -#include "Utils/SafePtr.hpp" #include "logging.hpp" #include "questui/ArrayUtil.hpp" #include "Utils/OperatorOverloads.hpp" @@ -84,7 +83,7 @@ namespace ScoreSaber::ReplaySystem::UI _bar->set_endTime(_audioTimeSyncController->songEndTime); set_loopMode(_loopMode); - FixedSafePtr self(this); + SafePtr self(this); _mainNode->PositionDidChange = [self](float value) { self->MainNode_PositionDidChange(value); }; @@ -218,7 +217,7 @@ namespace ScoreSaber::ReplaySystem::UI clickScrubRectTransform->anchorMax = Vector2(1.0f, 0.5f); clickScrubImage->color = Color::get_clear(); auto clicker = clickScrubImage->gameObject->AddComponent(); - FixedSafePtr self(this); + SafePtr self(this); clicker->Setup([self](float value) { self->ClickedBackground(value); }); diff --git a/src/ReplaySystem/UI/ImberSpecsReporter.cpp b/src/ReplaySystem/UI/ImberSpecsReporter.cpp index 2ed67b50..7afc33c2 100644 --- a/src/ReplaySystem/UI/ImberSpecsReporter.cpp +++ b/src/ReplaySystem/UI/ImberSpecsReporter.cpp @@ -4,7 +4,6 @@ #include #include #include -#include "Utils/SafePtr.hpp" #include "logging.hpp" using namespace UnityEngine; @@ -22,7 +21,7 @@ namespace ScoreSaber::ReplaySystem::UI } void ImberSpecsReporter::Initialize() { - FixedSafePtr self(this); + SafePtr self(this); _posePlayer->AddCallback([self](ScoreSaber::Data::Private::VRPoseGroup pose) { self->PosePlayer_DidUpdatePose(pose); }); diff --git a/src/ReplaySystem/UI/ResultsViewReplayButtonController.cpp b/src/ReplaySystem/UI/ResultsViewReplayButtonController.cpp index 2620f71a..79538f1e 100644 --- a/src/ReplaySystem/UI/ResultsViewReplayButtonController.cpp +++ b/src/ReplaySystem/UI/ResultsViewReplayButtonController.cpp @@ -8,7 +8,6 @@ #include #include #include "Utils/OperatorOverloads.hpp" -#include "Utils/SafePtr.hpp" #include "logging.hpp" using namespace BSML; @@ -33,7 +32,7 @@ namespace ScoreSaber::ReplaySystem::UI _resultsViewController->___continueButtonPressedEvent += continueButtonPressedDelegate; _resultsViewController->___restartButtonPressedEvent += restartButtonPressedDelegate; - FixedSafePtr self(this); + SafePtr self(this); Services::ReplayService::ReplaySerialized = [self](const std::vector &v) { self->UploadDaemon_ReplaySerialized(v); }; } @@ -76,7 +75,7 @@ namespace ScoreSaber::ReplaySystem::UI void ResultsViewReplayButtonController::WaitForReplay() { - FixedSafePtr self(this); + SafePtr self(this); il2cpp_utils::il2cpp_aware_thread([self](){ while(!self->_replayReady) { @@ -100,7 +99,7 @@ namespace ScoreSaber::ReplaySystem::UI void ResultsViewReplayButtonController::ClickedReplayButton() { - FixedSafePtr self(this); + SafePtr self(this); il2cpp_utils::il2cpp_aware_thread([self](){ std::vector modifiersVec = Services::UploadService::GetModifierList(self->_levelCompletionResults->gameplayModifiers, self->_levelCompletionResults->energy); std::string modifiers; diff --git a/src/Services/LeaderboardService.cpp b/src/Services/LeaderboardService.cpp index 770c31f2..067eabb0 100644 --- a/src/Services/LeaderboardService.cpp +++ b/src/Services/LeaderboardService.cpp @@ -1,4 +1,3 @@ -#include "Utils/SafePtr.hpp" #include "Utils/StringUtils.hpp" #include "Data/InternalLeaderboard.hpp" @@ -92,7 +91,7 @@ namespace ScoreSaber::Services::LeaderboardService return; } - FixedSafePtr beatmapLevelSafe(beatmapLevel); + SafePtr beatmapLevelSafe(beatmapLevel); int * const a = nullptr; int *b = a; diff --git a/src/Services/ReplayService.cpp b/src/Services/ReplayService.cpp index dcd8d459..491163a5 100644 --- a/src/Services/ReplayService.cpp +++ b/src/Services/ReplayService.cpp @@ -10,7 +10,7 @@ namespace ScoreSaber::Services::ReplayService { vector CurrentSerializedReplay; function&)> ReplaySerialized; - FixedSafePtr recorder; + SafePtr recorder; void OnSoftRestart() { CurrentSerializedReplay.clear(); diff --git a/src/Services/UploadService.cpp b/src/Services/UploadService.cpp index de365902..23caabef 100644 --- a/src/Services/UploadService.cpp +++ b/src/Services/UploadService.cpp @@ -23,7 +23,6 @@ #include #include #include "Utils/BeatmapUtils.hpp" -#include "Utils/SafePtr.hpp" #include "Utils/StringUtils.hpp" #include "Utils/WebUtils.hpp" #include "Utils/md5.h" @@ -136,7 +135,7 @@ namespace ScoreSaber::Services::UploadService void Seven(BeatmapLevel* beatmapLevel, BeatmapKey beatmapKey, int modifiedScore, int multipliedScore, std::string uploadPacket, std::string replayFileName) { - FixedSafePtr beatmapLevelSafe(beatmapLevel); + SafePtr beatmapLevelSafe(beatmapLevel); il2cpp_utils::il2cpp_aware_thread(gc_aware_function([beatmapLevelSafe, beatmapKey, modifiedScore, multipliedScore, uploadPacket, replayFileName] { ScoreSaber::UI::Other::ScoreSaberLeaderboardView::SetUploadState(true, false); diff --git a/src/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.cpp b/src/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.cpp index e9bfeb08..4500bdc3 100644 --- a/src/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.cpp +++ b/src/UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.cpp @@ -1,5 +1,4 @@ #include "UI/Multiplayer/ScoreSaberMultiplayerLevelSelectionLeaderboardFlowManager.hpp" -#include "Utils/SafePtr.hpp" #include #include @@ -114,7 +113,7 @@ namespace ScoreSaber::UI::Multiplayer { _performingFirstActivation = false; - FixedSafePtr self(this); + SafePtr self(this); il2cpp_utils::il2cpp_aware_thread([self] { std::this_thread::sleep_for(std::chrono::milliseconds(250)); diff --git a/src/UI/Multiplayer/ScoreSaberMultiplayerResultsLeaderboardFlowManager.cpp b/src/UI/Multiplayer/ScoreSaberMultiplayerResultsLeaderboardFlowManager.cpp index 0a95ae1c..78b77b40 100644 --- a/src/UI/Multiplayer/ScoreSaberMultiplayerResultsLeaderboardFlowManager.cpp +++ b/src/UI/Multiplayer/ScoreSaberMultiplayerResultsLeaderboardFlowManager.cpp @@ -6,7 +6,6 @@ #include "Services/PlayerService.hpp" #include "UI/Other/ScoreSaberLeaderboardView.hpp" #include -#include "Utils/SafePtr.hpp" #include "hooks.hpp" #include @@ -31,7 +30,7 @@ namespace ScoreSaber::UI::Multiplayer _multiplayerResultsViewController->___didActivateEvent += didActivateDelegate; _multiplayerResultsViewController->___didDeactivateEvent += didDeactivateDelegate; - FixedSafePtr self(this); + SafePtr self(this); HandleMultiplayerLevelDidFinish = [self](MultiplayerLevelScenesTransitionSetupDataSO * transitionSetupData, MultiplayerResultsData * results) { self->MultiplayerLevelDidFinish(transitionSetupData, results); diff --git a/src/UI/Other/Banner.cpp b/src/UI/Other/Banner.cpp index 729bcd64..01f95a44 100644 --- a/src/UI/Other/Banner.cpp +++ b/src/UI/Other/Banner.cpp @@ -21,7 +21,6 @@ #include #include #include -#include "Utils/SafePtr.hpp" #include "Utils/UIUtils.hpp" #include "logging.hpp" #include @@ -142,7 +141,7 @@ namespace ScoreSaber::UI::Other topText = CreateClickableText(infoVertical->transform, ""); bottomText = CreateClickableText(infoVertical->transform, ""); - FixedSafePtrUnity self(this); + SafePtrUnity self(this); topText->onClick += [self]() { self->OpenPlayerInfoModal(); }; bottomText->onClick += [self]() { self->OpenSongInBrowser(); }; @@ -317,7 +316,7 @@ namespace ScoreSaber::UI::Other promptText->text = text; if (dismissTime != -1) { - FixedSafePtrUnity self(this); + SafePtrUnity self(this); il2cpp_utils::il2cpp_aware_thread([dismissTime, self] { std::this_thread::sleep_for(std::chrono::seconds(dismissTime)); MainThreadScheduler::Schedule([self]() { diff --git a/src/UI/Other/ProfilePictureView.cpp b/src/UI/Other/ProfilePictureView.cpp index d3ce8e0c..d4bf74e9 100644 --- a/src/UI/Other/ProfilePictureView.cpp +++ b/src/UI/Other/ProfilePictureView.cpp @@ -31,7 +31,7 @@ using namespace std; namespace ScoreSaber::UI::Other { namespace SpriteCache { - map> cachedSprites; + map> cachedSprites; const int MaxSpriteCacheSize = 150; queue spriteCacheQueue; @@ -43,7 +43,7 @@ namespace ScoreSaber::UI::Other { cachedSprites.erase(oldestUrl); } - // somehow the objects can be GCed, even when behind a FixedSafePtrUnity + // somehow the objects can be GCed, even when behind a SafePtrUnity vector badSprites; for (auto &[key, value] : cachedSprites) { if (!value.isAlive()) { @@ -65,8 +65,8 @@ namespace ScoreSaber::UI::Other { } bool initializedGlobals = false; - FixedSafePtrUnity nullSprite; - FixedSafePtrUnity mat_UINoGlowRoundEdge; + SafePtrUnity nullSprite; + SafePtrUnity mat_UINoGlowRoundEdge; void ProfilePictureView::OnSoftRestart() { SpriteCache::cachedSprites.clear(); diff --git a/src/UI/Other/ScoreSaberLeaderboardView.cpp b/src/UI/Other/ScoreSaberLeaderboardView.cpp index f1778f50..d2016118 100644 --- a/src/UI/Other/ScoreSaberLeaderboardView.cpp +++ b/src/UI/Other/ScoreSaberLeaderboardView.cpp @@ -45,7 +45,6 @@ #include "Sprites.hpp" #include "UI/Other/ProfilePictureView.hpp" #include "Utils/MaxScoreCache.hpp" -#include "Utils/SafePtr.hpp" #include "Utils/UIUtils.hpp" #include "Utils/GCUtil.hpp" #include "logging.hpp" @@ -65,20 +64,20 @@ using namespace ScoreSaber::Data::Private; namespace ScoreSaber::UI::Other::ScoreSaberLeaderboardView { - FixedSafePtrUnity ScoreSaberBanner; + SafePtrUnity ScoreSaberBanner; - FixedSafePtrUnity leaderboardScoreInfoButtonHandler; + SafePtrUnity leaderboardScoreInfoButtonHandler; - FixedSafePtrUnity _platformLeaderboardViewController; + SafePtrUnity _platformLeaderboardViewController; - FixedSafePtrUnity _pageUpButton; - FixedSafePtrUnity _pageDownButton; + SafePtrUnity _pageUpButton; + SafePtrUnity _pageDownButton; std::vector _ImageHolders; - std::vector> _cellClickingImages; + std::vector> _cellClickingImages; - FixedSafePtr cancellationToken; + SafePtr cancellationToken; bool _activated = false; @@ -333,9 +332,9 @@ namespace ScoreSaber::UI::Other::ScoreSaberLeaderboardView _currentLeaderboardRefreshId = refreshId; - FixedSafePtr beatmapLevelSafe(beatmapLevel); - FixedSafePtrUnity loadingControlSafe(loadingControl); - FixedSafePtrUnity tableViewSafe(tableView); + SafePtr beatmapLevelSafe(beatmapLevel); + SafePtrUnity loadingControlSafe(loadingControl); + SafePtrUnity tableViewSafe(tableView); il2cpp_utils::il2cpp_aware_thread(gc_aware_function([beatmapLevelSafe, beatmapKey, scope, loadingControlSafe, tableViewSafe, refreshId]() { std::this_thread::sleep_for(std::chrono::milliseconds(500)); diff --git a/src/UI/ViewControllers/GlobalViewController.cpp b/src/UI/ViewControllers/GlobalViewController.cpp index 85bd75f3..22375d82 100644 --- a/src/UI/ViewControllers/GlobalViewController.cpp +++ b/src/UI/ViewControllers/GlobalViewController.cpp @@ -17,7 +17,6 @@ #include #include "Utils/UIUtils.hpp" #include "Utils/StrippedMethods.hpp" -#include "Utils/SafePtr.hpp" DEFINE_TYPE(ScoreSaber::UI::ViewControllers, GlobalViewController); @@ -29,7 +28,7 @@ using namespace BSML; using namespace BSML::Lite; custom_types::Helpers::Coroutine WaitForInit( - FixedSafePtrUnity + SafePtrUnity leaderboard, std::function callback) { diff --git a/src/Utils/MaxScoreCache.cpp b/src/Utils/MaxScoreCache.cpp index 9c1df755..ca3cdc62 100644 --- a/src/Utils/MaxScoreCache.cpp +++ b/src/Utils/MaxScoreCache.cpp @@ -29,14 +29,14 @@ namespace ScoreSaber::Utils { } void MaxScoreCache::GetMaxScore(BeatmapLevel* beatmapLevel, BeatmapKey beatmapKey, const function &callback) { - FixedSafeValueType beatmapKeySafe(beatmapKey); + SafeValueType beatmapKeySafe(beatmapKey); if(cache.contains(beatmapKeySafe)) { callback(cache[beatmapKeySafe]); return; } - FixedSafePtr self(this); - FixedSafePtr beatmapLevelSafe(beatmapLevel); + SafePtr self(this); + SafePtr beatmapLevelSafe(beatmapLevel); MainThreadScheduler::Schedule(gc_aware_function([self, beatmapLevelSafe, beatmapKeySafe, callback] { DelegateHelper::ContinueWith(self->_beatmapLevelsEntitlementModel->GetLevelDataVersionAsync(beatmapKeySafe->levelId, CancellationToken::get_None()), std::function(gc_aware_function( diff --git a/src/Utils/SafePtr.cpp b/src/Utils/SafePtr.cpp deleted file mode 100644 index 8b145935..00000000 --- a/src/Utils/SafePtr.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "Utils/SafePtr.hpp" -#include "logging.hpp" - -std::unordered_map safePtrCache; - -std::unordered_map FixedCounter::addrRefCount; -std::shared_mutex FixedCounter::mutex; - -std::vector cached_safe_ptr_wrappers; - -void reserve_safe_ptrs(size_t count) { - il2cpp_functions::Init(); - for(int i = 0; i < count; ++i) { - cached_safe_ptr_wrappers.push_back(il2cpp_functions::gc_alloc_fixed(sizeof(void*))); - } -} -void* alloc_safe_ptr(size_t sz) { - if(cached_safe_ptr_wrappers.empty()) { - SAFE_ABORT_MSG("No more SafePtrs available! Please increase the cache size."); - } - if(sz != sizeof(void*)) { - SAFE_ABORT_MSG("SafePtr size mismatch! Expected %zu, got %zu", sizeof(void*), sz); - } - - void* wrapper = cached_safe_ptr_wrappers.back(); - cached_safe_ptr_wrappers.pop_back(); - INFO("Allocated SafePtr at {}", fmt::ptr(wrapper)); - return wrapper; -} -void free_safe_ptr(void* ptr) { - cached_safe_ptr_wrappers.push_back(ptr); - INFO("Freed SafePtr at {}", fmt::ptr(ptr)); -} \ No newline at end of file diff --git a/src/Utils/UIUtils.cpp b/src/Utils/UIUtils.cpp index 6794f4b8..01c9ef25 100644 --- a/src/Utils/UIUtils.cpp +++ b/src/Utils/UIUtils.cpp @@ -28,7 +28,6 @@ #include #include "questui/ArrayUtil.hpp" #include "Utils/StrippedMethods.hpp" -#include "Utils/SafePtr.hpp" #include "Sprites.hpp" #include "logging.hpp" @@ -60,7 +59,7 @@ using namespace BSML::Lite; #define BeginCoroutine(method) BSML::SharedCoroutineStarter::StartCoroutine(custom_types::Helpers::CoroutineHelper::New(method)) using HapticPresetSO = Libraries::HM::HMLib::VR::HapticPresetSO; -static FixedSafePtrUnity hapticFeedbackPresetSO; +static SafePtrUnity hapticFeedbackPresetSO; namespace UIUtils { diff --git a/src/main.cpp b/src/main.cpp index 272aaf1a..bc4a9880 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,4 @@ #include "main.hpp" -#include "Utils/SafePtr.hpp" #include "hooks.hpp" #include "logging.hpp" @@ -60,7 +59,6 @@ void soft_restart() extern "C" __attribute((visibility("default"))) void late_load() noexcept { il2cpp_functions::Init(); - reserve_safe_ptrs(5000); BSML::Init(); custom_types::Register::AutoRegister(); Hooks::InstallHooks(); From c7837facde6a86a8fc5cc491b6038c31c3ecb1bf Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Tue, 18 Nov 2025 22:05:53 +0100 Subject: [PATCH 07/18] switch from semver to custom built simple version class. Fixes compatibility with System.Version which is not semver compliant :( --- include/Data/Private/ReplayFile.hpp | 14 +- include/Utils/Versions.hpp | 65 +++ include/Utils/semver.hpp | 417 ------------------ src/Data/Private/ReplayFile.cpp | 10 +- src/Data/Private/ReplayReader.cpp | 20 +- .../Recorders/MetadataRecorder.cpp | 12 +- 6 files changed, 92 insertions(+), 446 deletions(-) create mode 100644 include/Utils/Versions.hpp delete mode 100644 include/Utils/semver.hpp diff --git a/include/Data/Private/ReplayFile.hpp b/include/Data/Private/ReplayFile.hpp index 7d2f69f4..f1c66621 100644 --- a/include/Data/Private/ReplayFile.hpp +++ b/include/Data/Private/ReplayFile.hpp @@ -9,7 +9,7 @@ #include #include -#include "Utils/semver.hpp" +#include "Utils/Versions.hpp" using namespace std; @@ -110,7 +110,7 @@ namespace ScoreSaber::Data::Private std::optional ScoringType; std::optional CutDirectionAngleOffset; - bool MatchesScoringType(GlobalNamespace::NoteData_ScoringType comparedScoringType, optional gameVersion) const; + bool MatchesScoringType(GlobalNamespace::NoteData_ScoringType comparedScoringType, optional gameVersion) const; }; struct EnergyEvent @@ -152,9 +152,9 @@ namespace ScoreSaber::Data::Private struct Metadata { Metadata(); - Metadata(semver::version Version, string LevelID, int Difficulty, string Characteristic, string Environment, vector Modifiers, float NoteSpawnOffset, - bool LeftHanded, float InitialHeight, float RoomRotation, VRPosition RoomCenter, float FailTime, optional GameVersion, optional PluginVersion, optional Platform); - semver::version Version; + Metadata(version Version, string LevelID, int Difficulty, string Characteristic, string Environment, vector Modifiers, float NoteSpawnOffset, + bool LeftHanded, float InitialHeight, float RoomRotation, VRPosition RoomCenter, float FailTime, optional GameVersion, optional PluginVersion, optional Platform); + version Version; string LevelID; int Difficulty; string Characteristic; @@ -166,8 +166,8 @@ namespace ScoreSaber::Data::Private float RoomRotation; VRPosition RoomCenter; float FailTime; - optional GameVersion; - optional PluginVersion; + optional GameVersion; + optional PluginVersion; optional Platform; }; diff --git a/include/Utils/Versions.hpp b/include/Utils/Versions.hpp new file mode 100644 index 00000000..d6ab7852 --- /dev/null +++ b/include/Utils/Versions.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include +#include + +// Simple class to represent all kinds of versions and allow comparison between them. Does not respect semver rules beyond basic numeric comparison of parts. +class version { + std::vector parts; +public: + version() = default; + + version(const std::string& versionStr) { + // strip weird beatgames suffixes and semver prerelease/build metadata + std::string cleanedVersionStr = versionStr; + size_t suffixPos = cleanedVersionStr.find_first_of("_-+"); + if (suffixPos != std::string::npos) { + cleanedVersionStr = cleanedVersionStr.substr(0, suffixPos); + } + + size_t start = 0; + size_t end = cleanedVersionStr.find('.'); + while (end != std::string::npos) { + parts.push_back(std::stoi(cleanedVersionStr.substr(start, end - start))); + start = end + 1; + end = cleanedVersionStr.find('.', start); + } + parts.push_back(std::stoi(cleanedVersionStr.substr(start))); + } + + bool operator<(const version& other) const { + size_t maxLength = std::max(parts.size(), other.parts.size()); + for (size_t i = 0; i < maxLength; ++i) { + int thisPart = (i < parts.size()) ? parts[i] : 0; + int otherPart = (i < other.parts.size()) ? other.parts[i] : 0; + if (thisPart < otherPart) return true; + if (thisPart > otherPart) return false; + } + return false; + } + + bool operator==(const version& other) const { + size_t maxLength = std::max(parts.size(), other.parts.size()); + for (size_t i = 0; i < maxLength; ++i) { + int thisPart = (i < parts.size()) ? parts[i] : 0; + int otherPart = (i < other.parts.size()) ? other.parts[i] : 0; + if (thisPart != otherPart) return false; + } + return true; + } + + bool operator<=(const version& other) const { + return *this < other || *this == other; + } + + std::string str() const { + std::string result; + for (size_t i = 0; i < parts.size(); ++i) { + result += std::to_string(parts[i]); + if (i < parts.size() - 1) { + result += "."; + } + } + return result; + } +}; \ No newline at end of file diff --git a/include/Utils/semver.hpp b/include/Utils/semver.hpp deleted file mode 100644 index 58dab77c..00000000 --- a/include/Utils/semver.hpp +++ /dev/null @@ -1,417 +0,0 @@ -/* -License: MIT (http://opensource.org/licenses/MIT). - -Copyright (c) 2024 Peter Csajtai - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#ifndef Z4KN4FEIN_SEMVER_H -#define Z4KN4FEIN_SEMVER_H - -#ifndef SEMVER_MODULE -#include -#include -#include -#include -#include - -// conditionally include and its dependency for C++20 -#ifdef __cpp_lib_format -#if __cpp_lib_format >= 201907L -#include -#include -#endif -#endif -#endif - -#ifdef SEMVER_MODULE -#define SEMVER_EXPORT export -#else -#define SEMVER_EXPORT -#endif - -namespace semver -{ - const std::string default_prerelease_part = "0"; - const std::string numbers = "0123456789"; - const std::string prerelease_allowed_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-"; - const std::string version_pattern = "^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)" - "(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))" - "?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"; - const std::string loose_version_pattern = "^v?(0|[1-9]\\d*)(?:\\.(0|[1-9]\\d*))?(?:\\.(0|[1-9]\\d*))" - "?(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))" - "?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"; - - SEMVER_EXPORT struct semver_exception : public std::runtime_error { - explicit semver_exception(const std::string& message) : std::runtime_error(message) { } - }; - - inline uint64_t parse_numeric_part(const std::string& version_part) - { - return static_cast(std::stoull(version_part)); - } - - inline std::vector split(const std::string& text, const char& delimiter) { - std::size_t pos_start = 0, pos_end, delim_len = 1; - std::string current; - std::vector result; - - while ((pos_end = text.find(delimiter, pos_start)) != std::string::npos) { - current = text.substr(pos_start, pos_end - pos_start); - pos_start = pos_end + delim_len; - result.push_back(current); - } - - result.push_back(text.substr(pos_start)); - return result; - } - - inline bool is_numeric(const std::string& text) { - return text.find_first_not_of(numbers) == std::string::npos; - } - - inline bool is_valid_prerelease(const std::string& text) { - return text.find_first_not_of(numbers + prerelease_allowed_chars) == std::string::npos; - } - - class prerelease_part { - private: - bool m_numeric = false; - std::string m_value; - uint64_t m_numeric_value; - public: - explicit prerelease_part(const std::string& part) { - if (part.empty()) { - throw semver_exception("Pre-release identity contains an empty part."); - } - - if (is_numeric(part)) { - if (part.size() > 1 && part[0] == '0') { - throw semver_exception( - "Pre-release part '" + part + "' is numeric but contains a leading zero."); - } - m_numeric_value = parse_numeric_part(part); - m_numeric = true; - } - if (!is_valid_prerelease(part)) { - throw semver_exception( - "Pre-release part '" + part + "' contains an invalid character."); - } - m_value = part; - } - - [[nodiscard]] bool numeric() const { return m_numeric; } - [[nodiscard]] std::string value() const { return m_value; } - [[nodiscard]] uint64_t numeric_value() const { return m_numeric_value; } - - [[nodiscard]] int compare(const prerelease_part& other) const { - if (m_numeric && !other.m_numeric) return -1; - if (!m_numeric && other.m_numeric) return 1; - if (m_numeric) { - return (m_numeric_value < other.m_numeric_value) ? -1 : (m_numeric_value > other.m_numeric_value); - } - return (m_value < other.m_value) ? -1 : (m_value > other.m_value); - } - }; - - SEMVER_EXPORT class prerelease_descriptor { - private: - std::vector m_parts; - std::string prerelease_str; - - explicit prerelease_descriptor(const std::vector& parts) - : m_parts(parts) { - if (parts.empty()) prerelease_str = ""; - for (const auto &part : parts) { - if (!prerelease_str.empty()) prerelease_str += "."; - prerelease_str += part.value(); - } - } - public: - [[nodiscard]] std::string str() const { return prerelease_str; } - [[nodiscard]] bool is_empty() const { return m_parts.empty(); } - - [[nodiscard]] std::string identity() const { - if (is_empty()) return ""; - return m_parts.front().value(); - } - - [[nodiscard]] prerelease_descriptor increment() const { - std::vector new_parts = (m_parts); - size_t last_numeric_index = 0; - bool last_numeric_index_found = false; - for (size_t i = 0; i < new_parts.size(); ++i) { - if (new_parts[i].numeric()){ - last_numeric_index = i; - last_numeric_index_found = true; - } - } - if (last_numeric_index_found) { - prerelease_part last = new_parts[last_numeric_index]; - new_parts[last_numeric_index] = prerelease_part(std::to_string(last.numeric_value() + 1)); - } else { - new_parts.emplace_back(default_prerelease_part); - } - return prerelease_descriptor(new_parts); - } - - [[nodiscard]] int compare(const prerelease_descriptor& other) const { - auto this_size = m_parts.size(); - auto other_size = other.m_parts.size(); - - auto count = std::min(this_size, other_size); - for (size_t i = 0; i < count; ++i) { - int cmp = m_parts[i].compare(other.m_parts[i]); - if (cmp != 0) return cmp; - } - return (this_size < other_size) ? -1 : (this_size > other_size); - } - - bool operator<(const prerelease_descriptor& other) const { - return compare(other) == -1; - } - - bool operator>(const prerelease_descriptor& other) const { - return (other < *this); - } - - bool operator==(const prerelease_descriptor& other) const { - return prerelease_str == other.prerelease_str; - } - - bool operator!=(const prerelease_descriptor& other) const { - return prerelease_str != other.prerelease_str; - } - - static prerelease_descriptor parse(const std::string& prerelease_part_str) { - if (prerelease_part_str.empty()) return empty(); - std::vector prerelease_parts; - std::vector parts = split(prerelease_part_str, '.'); - for(auto& part : parts) { - prerelease_parts.emplace_back(part); - } - return prerelease_descriptor(prerelease_parts); - } - - static prerelease_descriptor empty() { - return prerelease_descriptor({}); - } - - static prerelease_descriptor initial() { - return prerelease_descriptor::parse(default_prerelease_part); - } - }; - - SEMVER_EXPORT enum inc { major, minor, patch, prerelease }; - - SEMVER_EXPORT class version { - private: - uint64_t m_major; - uint64_t m_minor; - uint64_t m_patch; - prerelease_descriptor m_prerelease; - std::string m_build_meta; - - [[nodiscard]] int compare(const version& other) const { - if (m_major > other.m_major) return 1; - if (m_major < other.m_major) return -1; - if (m_minor > other.m_minor) return 1; - if (m_minor < other.m_minor) return -1; - if (m_patch > other.m_patch) return 1; - if (m_patch < other.m_patch) return -1; - if (!m_prerelease.is_empty() && other.m_prerelease.is_empty()) return -1; - if (m_prerelease.is_empty() && !other.m_prerelease.is_empty()) return 1; - if (!m_prerelease.is_empty() && !other.m_prerelease.is_empty()) return m_prerelease.compare(other.m_prerelease); - return 0; - } - public: - explicit version(uint64_t major = 0, - uint64_t minor = 0, - uint64_t patch = 0, - const std::string& prerelease = "", - std::string build_meta = "") - : m_major{major}, - m_minor{minor}, - m_patch{patch}, - m_prerelease{prerelease_descriptor::parse(prerelease)}, - m_build_meta{std::move(build_meta)} { } - - [[nodiscard]] uint64_t major() const { return m_major; } - [[nodiscard]] uint64_t minor() const { return m_minor; } - [[nodiscard]] uint64_t patch() const { return m_patch; } - [[nodiscard]] std::string prerelease() const { return m_prerelease.str(); } - [[nodiscard]] std::string build_meta() const { return m_build_meta; } - - [[nodiscard]] bool is_prerelease() const { return !m_prerelease.is_empty(); } - [[nodiscard]] bool is_stable() const { return m_major > 0 && m_prerelease.is_empty(); } - - [[nodiscard]] std::string str() const { - std::string result = std::to_string(m_major) + "." + std::to_string(m_minor) + "." + std::to_string(m_patch); - if (!m_prerelease.is_empty()) result += "-" + m_prerelease.str(); - if (!m_build_meta.empty()) result += "+" + m_build_meta; - return result; - } - - [[nodiscard]] version without_suffixes() const { - return version(m_major, m_minor, m_patch); - } - - [[nodiscard]] version next_major(const std::string& prerelease = "") const { - return version(m_major + 1, 0, 0, prerelease); - } - - [[nodiscard]] version next_minor(const std::string& prerelease = "") const { - return version(m_major, m_minor + 1, 0, prerelease); - } - - [[nodiscard]] version next_patch(const std::string& prerelease = "") const { - return version(m_major, m_minor, (!is_prerelease() || !prerelease.empty() ? m_patch + 1 : m_patch), prerelease); - } - - [[nodiscard]] version next_prerelease(const std::string& prerelease = "") const { - std::string pre = default_prerelease_part; - if (!prerelease.empty()) { - pre = is_prerelease() && m_prerelease.identity() == prerelease ? m_prerelease.increment().str() : prerelease; - } else if (prerelease.empty() && is_prerelease()) { - pre = m_prerelease.increment().str(); - } - return version(m_major, m_minor, is_prerelease() ? m_patch : m_patch + 1, pre); - } - - [[nodiscard]] version increment(inc by, const std::string& prerelease = "") const { - switch (by) { - case semver::major: return next_major(prerelease); - case semver::minor: return next_minor(prerelease); - case semver::patch: return next_patch(prerelease); - case semver::prerelease: return next_prerelease(prerelease); - default: throw semver_exception("Invalid 'by' parameter in 'increment()' function."); - } - } - - bool operator<(const version& other) const { - return compare(other) == -1; - } - - bool operator<=(const version& other) const { - return compare(other) <= 0; - } - - bool operator>(const version& other) const { - return compare(other) == 1; - } - - bool operator>=(const version& other) const { - return compare(other) >= 0; - } - - bool operator==(const version& other) const { - return compare(other) == 0; - } - - bool operator!=(const version& other) const { - return compare(other) != 0; - } - - // conditionally provide three-way operator for C++20 - #ifdef __cpp_impl_three_way_comparison - #if __cpp_impl_three_way_comparison >= 201907L - - auto operator<=>(const version& other) const { - return compare(other); - } - - #endif - #endif - - static version parse(const std::string& version_str, bool strict = true) { - std::regex regex(strict ? version_pattern : loose_version_pattern); - std::cmatch match; - uint64_t major; - uint64_t minor; - uint64_t patch; - std::string prerelease; - std::string build_meta; - - if (!std::regex_match(version_str.c_str(), match, regex)) { - throw semver_exception("Invalid version: " + version_str); - } - - auto major_m = match[1]; - auto minor_m = match[2]; - auto patch_m = match[3]; - auto prerelease_m = match[4]; - auto build_meta_m = match[5]; - - if (prerelease_m.matched) prerelease = prerelease_m.str(); - if (build_meta_m.matched) build_meta = build_meta_m.str(); - - try { - if (strict && major_m.matched && minor_m.matched && patch_m.matched) { - major = parse_numeric_part(major_m); - minor = parse_numeric_part(minor_m); - patch = parse_numeric_part(patch_m); - } else if (!strict && major_m.matched) { - major = parse_numeric_part(major_m); - minor = minor_m.matched ? parse_numeric_part(minor_m) : 0; - patch = patch_m.matched ? parse_numeric_part(patch_m) : 0; - } else { - throw semver_exception("Invalid version: " + version_str); - } - - return version(major, minor, patch, prerelease, build_meta); - } catch (std::exception& exception) { - throw semver_exception("Version parse error: " + std::string(exception.what())); - } - } - }; - - SEMVER_EXPORT inline std::ostream & operator<<(std::ostream& str, const version& version) { - for (const auto s : version.str()) str.put(s); - return str; - } - - namespace literals - { - SEMVER_EXPORT inline version operator""_v(const char* text, std::size_t length) { - return version::parse(std::string(text, length)); - } - - SEMVER_EXPORT inline version operator""_lv(const char* text, std::size_t length) { - return version::parse(std::string(text, length), false); - } - } -} - -// conditionally provide formatter for C++20 -#ifdef __cpp_lib_format -#if __cpp_lib_format >= 201907L - -template -struct std::formatter : std::formatter { - template - auto format(const semver::version& version, FormatContext& ctx) const { - return std::formatter::format(version.str(), ctx); - } -}; - -#endif -#endif - -#endif // Z4KN4FEIN_SEMVER_H \ No newline at end of file diff --git a/src/Data/Private/ReplayFile.cpp b/src/Data/Private/ReplayFile.cpp index d3369683..7e7ab9df 100644 --- a/src/Data/Private/ReplayFile.cpp +++ b/src/Data/Private/ReplayFile.cpp @@ -3,14 +3,14 @@ #include #include -#include "Utils/semver.hpp" +#include "Utils/Versions.hpp" using namespace GlobalNamespace; namespace ScoreSaber::Data::Private { namespace RelevantGameVersions { - const auto Version_1_40 = semver::version::parse("1.40.0"); + const auto Version_1_40 = version("1.40.0"); }; @@ -127,7 +127,7 @@ namespace ScoreSaber::Data::Private NoteID::NoteID(){}; - bool NoteID::MatchesScoringType(GlobalNamespace::NoteData_ScoringType comparedScoringType, optional gameVersion) const + bool NoteID::MatchesScoringType(GlobalNamespace::NoteData_ScoringType comparedScoringType, optional gameVersion) const { if (ScoringType) { if(!gameVersion || gameVersion < RelevantGameVersions::Version_1_40) { @@ -194,8 +194,8 @@ namespace ScoreSaber::Data::Private VRPoseGroup::VRPoseGroup(){}; - Metadata::Metadata(semver::version _Version, string _LevelID, int _Difficulty, string _Characteristic, string _Environment, vector _Modifiers, - float _NoteSpawnOffset, bool _LeftHanded, float _InitialHeight, float _RoomRotation, VRPosition _RoomCenter, float _FailTime, optional _GameVersion, optional _PluginVersion, optional _Platform) + Metadata::Metadata(version _Version, string _LevelID, int _Difficulty, string _Characteristic, string _Environment, vector _Modifiers, + float _NoteSpawnOffset, bool _LeftHanded, float _InitialHeight, float _RoomRotation, VRPosition _RoomCenter, float _FailTime, optional _GameVersion, optional _PluginVersion, optional _Platform) { Version = _Version; LevelID = _LevelID; diff --git a/src/Data/Private/ReplayReader.cpp b/src/Data/Private/ReplayReader.cpp index 4e7b9594..cf6a40b2 100644 --- a/src/Data/Private/ReplayReader.cpp +++ b/src/Data/Private/ReplayReader.cpp @@ -6,7 +6,7 @@ #include #include -#include "Utils/semver.hpp" +#include "Utils/Versions.hpp" #include "logging.hpp" #include "static.hpp" @@ -27,7 +27,7 @@ namespace ScoreSaber::Data::Private::ReplayReader shared_ptr metadata = ReadMetadata(inputStream, pointers.metadata); INFO("Found replay with version {:s}", metadata->Version.str()); - if (metadata->Version == semver::version::parse("2.0.0")) { + if (metadata->Version == version("2.0.0")) { return make_shared(metadata, ReadPoseKeyframes(inputStream, pointers.poseKeyframes), ReadHeightKeyframes(inputStream, pointers.heightKeyframes), @@ -36,7 +36,7 @@ namespace ScoreSaber::Data::Private::ReplayReader ReadComboKeyframes(inputStream, pointers.comboKeyframes), ReadMultiplierKeyframes(inputStream, pointers.multiplierKeyframes), ReadEnergyKeyframes(inputStream, pointers.energyKeyframes)); - } else if (metadata->Version <= semver::version::parse("3.1.0")) { + } else if (metadata->Version <= version("3.1.0")) { return make_shared(metadata, ReadPoseKeyframes(inputStream, pointers.poseKeyframes), ReadHeightKeyframes(inputStream, pointers.heightKeyframes), @@ -65,19 +65,21 @@ namespace ScoreSaber::Data::Private::ReplayReader { inputStream.seekg(offset); - semver::version version = semver::version::parse(ReadString(inputStream)); + version ver = version(ReadString(inputStream)); - if(version < semver::version::parse("3.1.0")) { - return make_shared(version, ReadString(inputStream), ReadInt(inputStream), ReadString(inputStream), + INFO("found version {:s}", ver.str()); + + if(ver < version("3.1.0")) { + return make_shared(ver, ReadString(inputStream), ReadInt(inputStream), ReadString(inputStream), ReadString(inputStream), ReadStringArray(inputStream), ReadFloat(inputStream), ReadBool(inputStream), ReadFloat(inputStream), ReadFloat(inputStream), ReadVRPosition(inputStream), ReadFloat(inputStream), nullopt, nullopt, nullopt); } else { - return make_shared(version, ReadString(inputStream), ReadInt(inputStream), ReadString(inputStream), + return make_shared(ver, ReadString(inputStream), ReadInt(inputStream), ReadString(inputStream), ReadString(inputStream), ReadStringArray(inputStream), ReadFloat(inputStream), ReadBool(inputStream), ReadFloat(inputStream), ReadFloat(inputStream), ReadVRPosition(inputStream), ReadFloat(inputStream), - semver::version::parse(ReadString(inputStream)), - semver::version::parse(ReadString(inputStream)), ReadString(inputStream)); + version(ReadString(inputStream)), + version(ReadString(inputStream)), ReadString(inputStream)); } } diff --git a/src/ReplaySystem/Recorders/MetadataRecorder.cpp b/src/ReplaySystem/Recorders/MetadataRecorder.cpp index 713b0a98..49d1af1e 100644 --- a/src/ReplaySystem/Recorders/MetadataRecorder.cpp +++ b/src/ReplaySystem/Recorders/MetadataRecorder.cpp @@ -15,7 +15,7 @@ #include #include #include -#include "Utils/semver.hpp" +#include "Utils/Versions.hpp" #include "logging.hpp" using namespace UnityEngine; @@ -57,7 +57,7 @@ namespace ScoreSaber::ReplaySystem::Recorders { StringW csc; auto metadata = make_shared(); - metadata->Version = semver::version::parse("3.1.0"); + metadata->Version = version("3.1.0"); metadata->LevelID = (string)_gameplayCoreSceneSetupData->beatmapLevel->levelID; metadata->Difficulty = BeatmapDifficultyMethods::DefaultRating(_gameplayCoreSceneSetupData->beatmapKey.difficulty); metadata->Characteristic = (string)_gameplayCoreSceneSetupData->beatmapKey.beatmapCharacteristic->serializedName; @@ -69,12 +69,8 @@ namespace ScoreSaber::ReplaySystem::Recorders metadata->RoomRotation = _settingsManager->settings.room.rotation; metadata->RoomCenter = VRPosition(_settingsManager->settings.room.center.x, _settingsManager->settings.room.center.y, _settingsManager->settings.room.center.z); metadata->FailTime = _failTime; - string gameVersion = (string)Application::get_version(); - if(gameVersion.find_first_of('_') != string::npos) { - gameVersion = gameVersion.substr(0, gameVersion.find_first_of('_')); - } - metadata->GameVersion = semver::version::parse(gameVersion); - metadata->PluginVersion = semver::version::parse(VERSION); + metadata->GameVersion = version((string)Application::get_version()); + metadata->PluginVersion = version(VERSION); metadata->Platform = "Quest"; return metadata; } From 9d9551169647d87c3c9cc7aa071ac0cbf36a37f0 Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Tue, 16 Dec 2025 14:23:22 +0100 Subject: [PATCH 08/18] pass logging params --- qpm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qpm.json b/qpm.json index 53d381c8..8e93ab45 100644 --- a/qpm.json +++ b/qpm.json @@ -23,7 +23,7 @@ "pwsh ./scripts/copy.ps1 $0:?" ], "logcat": [ - "pwsh ./scripts/start-logging.ps1" + "pwsh ./scripts/start-logging.ps1 $0:?" ], "qmod": [ "pwsh ./scripts/build.ps1", From 9628e506b45132e2e564ab72b70f3c0c3336edd7 Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Tue, 16 Dec 2025 14:27:56 +0100 Subject: [PATCH 09/18] prevent BL from thinking our replays are actual plays --- src/ReplaySystem/ReplayLoader.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ReplaySystem/ReplayLoader.cpp b/src/ReplaySystem/ReplayLoader.cpp index fcb6a25a..841fef4c 100644 --- a/src/ReplaySystem/ReplayLoader.cpp +++ b/src/ReplaySystem/ReplayLoader.cpp @@ -91,6 +91,9 @@ namespace ScoreSaber::ReplaySystem::ReplayLoader auto _environmentsListModel = Helpers::GetDiContainer()->Resolve(); + MetaCore::Game::DisableScoreSubmissionOnce(MOD_ID); + MetaCore::Game::DisableScoreSubmissionOnce("Replay"); // hacky way to prevent BL from submitting scores during replay + menuTransitionsHelper->StartStandardLevel("Replay", // gameMode byref(beatmapKey), // beatmapKey beatmapLevel, // beatmapLevel @@ -111,7 +114,6 @@ namespace ScoreSaber::ReplaySystem::ReplayLoader nullptr, // levelRestartedCallback {false, {}} // recordingToolData (set to null) ); - MetaCore::Game::DisableScoreSubmissionOnce(MOD_ID); IsPlaying = true; } From cf96bb5d4bdc51ae96e4af899731b3b8996f53b2 Mon Sep 17 00:00:00 2001 From: Riley <105916526@student.swin.edu.au> Date: Wed, 17 Dec 2025 00:29:01 +1100 Subject: [PATCH 10/18] Replay Fixes for 1.40 --- .../Playback/ReplayTimeSyncController.hpp | 3 +- .../ReplaySystem/Playback/TimeUpdateUtils.hpp | 41 ++++++ src/Hooks/ReplayHooks.cpp | 14 ++ src/ReplaySystem/Playback/ComboPlayer.cpp | 81 ++++++++++-- src/ReplaySystem/Playback/EnergyPlayer.cpp | 47 +++++-- .../Playback/MultiplierPlayer.cpp | 36 +++-- src/ReplaySystem/Playback/NotePlayer.cpp | 48 ++++++- src/ReplaySystem/Playback/PosePlayer.cpp | 10 +- .../Playback/ReplayTimeSyncController.cpp | 124 +++++++----------- src/ReplaySystem/Playback/ScorePlayer.cpp | 46 +++++-- 10 files changed, 309 insertions(+), 141 deletions(-) create mode 100644 include/ReplaySystem/Playback/TimeUpdateUtils.hpp diff --git a/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp b/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp index 55fb420b..1e7ba477 100644 --- a/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp +++ b/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp @@ -23,7 +23,7 @@ DECLARE_CLASS_CODEGEN_INTERFACES( ScoreSaber::ReplaySystem::Playback, ReplayTimeSyncController, System::Object, - Zenject::ITickable*) { + Zenject::ITickable*, Zenject::IInitializable*) { DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioManagerSO); DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::AudioTimeSyncController::InitData*, _audioInitData); @@ -50,6 +50,7 @@ DECLARE_CLASS_CODEGEN_INTERFACES( Zenject::DiContainer* container); DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); + DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); DECLARE_INSTANCE_METHOD(void, UpdateTimes); DECLARE_INSTANCE_METHOD(void, OverrideTime, float time); DECLARE_INSTANCE_METHOD(void, OverrideTimeScale, float timeScale); diff --git a/include/ReplaySystem/Playback/TimeUpdateUtils.hpp b/include/ReplaySystem/Playback/TimeUpdateUtils.hpp new file mode 100644 index 00000000..cefe7d66 --- /dev/null +++ b/include/ReplaySystem/Playback/TimeUpdateUtils.hpp @@ -0,0 +1,41 @@ +#pragma once +#include +#include + +// i think i understand templates now :D +template +TValue FindLastEventBeforeOrAt( + float newTime, + const std::vector& events, + TValue defaultValue, + Accessor valueAccessor) +{ + if (events.empty()) + return defaultValue; + + auto it = std::upper_bound( + events.begin(), + events.end(), + newTime, + [](float t, const TEvent& e) { return t < e.Time; } + ); + + if (it == events.begin()) + return defaultValue; + + --it; + return valueAccessor(*it); +} + +template +int FindNextEventIndex(float newTime, const std::vector& events) +{ + auto it = std::upper_bound( + events.begin(), + events.end(), + newTime, + [](float t, const TEvent& e) { return t < e.Time; } + ); + + return static_cast(it - events.begin()); +} diff --git a/src/Hooks/ReplayHooks.cpp b/src/Hooks/ReplayHooks.cpp index 768dd01b..6964e1cf 100644 --- a/src/Hooks/ReplayHooks.cpp +++ b/src/Hooks/ReplayHooks.cpp @@ -34,6 +34,7 @@ #include #include #include +#include "GlobalNamespace/FlyingScoreSpawner.hpp" #include "logging.hpp" using namespace UnityEngine; @@ -185,3 +186,16 @@ MAKE_AUTO_HOOK_ORIG_MATCH(ScoreController_LateUpdate, &ScoreController::LateUpda } } } + + +// fixes scores doubling up in one position when note cuts are done on the same frame (time) +MAKE_AUTO_HOOK_MATCH(FlyingScoreSpawner_SpawnFlyingScoreNextFrame, &GlobalNamespace::FlyingScoreSpawner::SpawnFlyingScoreNextFrame, void, GlobalNamespace::FlyingScoreSpawner* self, GlobalNamespace::IReadonlyCutScoreBuffer* cutScoreBuffer, UnityEngine::Color color) +{ + if (!ScoreSaber::ReplaySystem::ReplayLoader::IsPlaying) + { + FlyingScoreSpawner_SpawnFlyingScoreNextFrame(self, cutScoreBuffer, color); + return; + } + self->SpawnFlyingScore(cutScoreBuffer, color); + return; +} \ No newline at end of file diff --git a/src/ReplaySystem/Playback/ComboPlayer.cpp b/src/ReplaySystem/Playback/ComboPlayer.cpp index b647083a..98081022 100644 --- a/src/ReplaySystem/Playback/ComboPlayer.cpp +++ b/src/ReplaySystem/Playback/ComboPlayer.cpp @@ -1,8 +1,11 @@ #include "ReplaySystem/Playback/ComboPlayer.hpp" +#include "Data/Private/ReplayFile.hpp" #include "ReplaySystem/ReplayLoader.hpp" #include #include #include +#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" +#include "metacore/shared/internals.hpp" using namespace UnityEngine; using namespace ScoreSaber::Data::Private; @@ -21,19 +24,22 @@ namespace ScoreSaber::ReplaySystem::Playback _sortedNoteEvents = ReplayLoader::LoadedReplay->noteKeyframes; _sortedComboEvents = ReplayLoader::LoadedReplay->comboKeyframes; } + void ComboPlayer::TimeUpdate(float newTime) { - for (int c = 0; c < _sortedComboEvents.size(); c++) - { - // TODO: this has potential to have problems if _sortedComboEvents[c].Time is within an epsilon of newTime, potentially applying combo twice or not at all - if (_sortedComboEvents[c].Time > newTime) - { - UpdateCombo(newTime, c != 0 ? _sortedComboEvents[c - 1].Combo : 0); - return; - } - } - UpdateCombo(newTime, _sortedComboEvents[_sortedComboEvents.size() - 1].Combo); + INFO("ComboPlayer::TimeUpdate newTime: {}", newTime); + + int combo = FindLastEventBeforeOrAt( + newTime, + _sortedComboEvents, + 0, + [](const ComboEvent& e) { return e.Combo; } + ); + + UpdateCombo(newTime, combo); } + + void ComboPlayer::UpdateCombo(float time, int combo) { auto previousComboEvents = std::vector(); @@ -45,12 +51,57 @@ namespace ScoreSaber::ReplaySystem::Playback } } int cutOrMissRecorded = 0; + int bombsHitL = 0; + int bombsHitR = 0; + + int leftCombo = 0; + int rightCombo = 0; + + int leftHighest = 0; + int rightHighest = 0; + for (int c = 0; c < previousComboEvents.size(); c++) { if (previousComboEvents[c].EventType == NoteEventType::BadCut || previousComboEvents[c].EventType == NoteEventType::GoodCut || previousComboEvents[c].EventType == NoteEventType::Miss) { cutOrMissRecorded++; } + else if (previousComboEvents[c].EventType == NoteEventType::Bomb) + { + if (previousComboEvents[c].SaberType == 0) { + bombsHitL++; + } + else { + bombsHitR++; + } + } + + + if (previousComboEvents[c].EventType == NoteEventType::GoodCut) + { + if (previousComboEvents[c].SaberType == 0) + { + leftCombo++; + if (leftHighest < leftCombo) { + leftHighest = leftCombo; + } + } + else + { + rightCombo++; + if (rightHighest < rightCombo) { + rightHighest = rightCombo; + } + } + } + else{ + if (previousComboEvents[c].SaberType == 0) { + leftCombo = 0; + } + else { + rightCombo = 0; + } + } } _comboController->_combo = combo; _comboController->_maxCombo = cutOrMissRecorded; @@ -78,5 +129,15 @@ namespace ScoreSaber::ReplaySystem::Playback _comboUIController->_animator->SetTrigger(_comboUIController->_comboLostId); _comboUIController->_fullComboLost = true; } + + + MetaCore::Internals::combo = combo; + MetaCore::Internals::highestCombo = cutOrMissRecorded == 0 ? 0 : std::max(combo, cutOrMissRecorded); + MetaCore::Internals::leftCombo = leftCombo; + MetaCore::Internals::rightCombo = rightCombo; + MetaCore::Internals::highestLeftCombo = leftHighest; + MetaCore::Internals::highestRightCombo = rightHighest; + MetaCore::Internals::bombsLeftHit = bombsHitL; + MetaCore::Internals::bombsRightHit = bombsHitR; } } // namespace ScoreSaber::ReplaySystem::Playback \ No newline at end of file diff --git a/src/ReplaySystem/Playback/EnergyPlayer.cpp b/src/ReplaySystem/Playback/EnergyPlayer.cpp index dd89c8e1..00116262 100644 --- a/src/ReplaySystem/Playback/EnergyPlayer.cpp +++ b/src/ReplaySystem/Playback/EnergyPlayer.cpp @@ -9,7 +9,8 @@ #include #include #include "logging.hpp" -#include +#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" +#include "metacore/shared/internals.hpp" using namespace UnityEngine; using namespace ScoreSaber::Data::Private; @@ -29,22 +30,22 @@ namespace ScoreSaber::ReplaySystem::Playback void EnergyPlayer::TimeUpdate(float newTime) { - for (int c = 0; c < _sortedEnergyEvents.size(); c++) - { - // TODO: this has potential to have problems if _sortedEnergyEvents[c].Time is within an epsilon of newTime, potentially applying energy changes twice or not at all - if (_sortedEnergyEvents[c].Time > newTime) - { - float energy = c != 0 ? _sortedEnergyEvents[c - 1].Energy : 0.5f; - UpdateEnergy(energy); - return; - } - } - UpdateEnergy(0.5f); - auto lastEvent = _sortedEnergyEvents[_sortedEnergyEvents.size() - 1]; - if (newTime >= lastEvent.Time && lastEvent.Energy <= Mathf::getStaticF_Epsilon()) + INFO("EnergyPlayer::TimeUpdate newTime: {}", newTime); + + const auto& last = _sortedEnergyEvents.back(); + if (newTime >= last.Time && last.Energy <= Mathf::getStaticF_Epsilon()) { UpdateEnergy(0.0f); + return; } + + float energy = FindLastEventBeforeOrAt( + newTime, + _sortedEnergyEvents, + 0.5f, + [](const auto& e) { return e.Energy; }); + + UpdateEnergy(energy); } void EnergyPlayer::UpdateEnergy(float energy) @@ -69,6 +70,24 @@ namespace ScoreSaber::ReplaySystem::Playback { _gameEnergyCounter->gameEnergyDidChangeEvent->Invoke(energy); } + + // forgive me + MetaCore::Internals::health = energy; + + MetaCore::Internals::wallsHit = 0; + + float lastEnergy = 0.5f; + for (const auto& ev : _sortedEnergyEvents) + { + if (ev.Time > MetaCore::Internals::audioTimeSyncController->_songTime) + { + break; + } + if (ev.Energy < lastEnergy) // weve lost energy by any means so just set wallhit for ui to be correct + { + MetaCore::Internals::wallsHit = 1; // just needs to be > 0 for ui to be correct (will implement precalculation later) + } + } return; } diff --git a/src/ReplaySystem/Playback/MultiplierPlayer.cpp b/src/ReplaySystem/Playback/MultiplierPlayer.cpp index dba0000b..b9eb6d18 100644 --- a/src/ReplaySystem/Playback/MultiplierPlayer.cpp +++ b/src/ReplaySystem/Playback/MultiplierPlayer.cpp @@ -2,7 +2,8 @@ #include "ReplaySystem/ReplayLoader.hpp" #include #include "logging.hpp" -#include +#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" +#include "metacore/shared/internals.hpp" using namespace UnityEngine; using namespace ScoreSaber::Data::Private; @@ -18,24 +19,31 @@ namespace ScoreSaber::ReplaySystem::Playback _scoreController = scoreController; _sortedMultiplierEvents = ReplayLoader::LoadedReplay->multiplierKeyframes; } + void MultiplierPlayer::TimeUpdate(float newTime) { - for (int c = 0; c < _sortedMultiplierEvents.size(); c++) + INFO("MultiplierPlayer::TimeUpdate newTime: {}", newTime); + + int index = FindNextEventIndex(newTime, _sortedMultiplierEvents); + + if (index == 0) + { + UpdateMultiplier(1, 0.0f); + return; + } + + if (index < _sortedMultiplierEvents.size()) { - // TODO: this has potential to have problems if _sortedMultiplierEvents[c].Time is within an epsilon of newTime, potentially applying combo changes twice or not at all - if (_sortedMultiplierEvents[c].Time > newTime) - { - int multiplier = c != 0 ? _sortedMultiplierEvents[c - 1].Multiplier : 1; - float progress = c != 0 ? _sortedMultiplierEvents[c - 1].NextMultiplierProgress : 0.0f; - UpdateMultiplier(multiplier, progress); - return; - } + const auto& ev = _sortedMultiplierEvents[index - 1]; + UpdateMultiplier(ev.Multiplier, ev.NextMultiplierProgress); } - if (_sortedMultiplierEvents.size() > 0) { - auto lastEvent = _sortedMultiplierEvents[_sortedMultiplierEvents.size() - 1]; - UpdateMultiplier(lastEvent.Multiplier, lastEvent.NextMultiplierProgress); + else + { + const auto& last = _sortedMultiplierEvents.back(); + UpdateMultiplier(last.Multiplier, last.NextMultiplierProgress); } } + void MultiplierPlayer::UpdateMultiplier(int multiplier, float progress) { auto counter = _scoreController->_scoreMultiplierCounter; @@ -46,5 +54,7 @@ namespace ScoreSaber::ReplaySystem::Playback { _scoreController->multiplierDidChangeEvent->Invoke(multiplier, progress); } + MetaCore::Internals::multiplier = multiplier; + MetaCore::Internals::multiplierProgress = progress; } } // namespace ScoreSaber::ReplaySystem::Playback \ No newline at end of file diff --git a/src/ReplaySystem/Playback/NotePlayer.cpp b/src/ReplaySystem/Playback/NotePlayer.cpp index 0c27f15f..a429b73a 100644 --- a/src/ReplaySystem/Playback/NotePlayer.cpp +++ b/src/ReplaySystem/Playback/NotePlayer.cpp @@ -14,6 +14,8 @@ #include #include "logging.hpp" #include +#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" +#include "metacore/shared/internals.hpp" using namespace UnityEngine; using namespace ScoreSaber::Data::Private; @@ -136,18 +138,50 @@ namespace ScoreSaber::ReplaySystem::Playback } return true; } + void NotePlayer::TimeUpdate(float newTime) { - for (int c = 0; c < _sortedNoteEvents.size(); c++) - { - if (_sortedNoteEvents[c].Time > newTime) - { - _nextIndex = c; - return; + INFO("NotePlayer::TimeUpdate newTime: {}", newTime); + _nextIndex = FindNextEventIndex(newTime, _sortedNoteEvents); + + MetaCore::Internals::notesLeftBadCut = 0; + MetaCore::Internals::notesRightBadCut = 0; + MetaCore::Internals::notesLeftMissed = 0; + MetaCore::Internals::notesRightMissed = 0; + MetaCore::Internals::notesLeftCut = 0; + MetaCore::Internals::notesRightCut = 0; + MetaCore::Internals::remainingNotesLeft = 0; + MetaCore::Internals::remainingNotesRight = 0; + // MetaCore::Internals::leftMissedFixedScore = 0; // chains or something but not important rn + // MetaCore::Internals::rightMissedFixedScore = 0; + MetaCore::Internals::leftMissedMaxScore = 0; + MetaCore::Internals::rightMissedMaxScore = 0; + + for (int i = 0; i < _sortedNoteEvents.size(); i++) { + auto& noteEvent = _sortedNoteEvents[i]; + if (noteEvent.Time > newTime) { + if (noteEvent.EventType == NoteEventType::BadCut) { + if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) { + MetaCore::Internals::notesLeftBadCut++; + } else if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorB) { + MetaCore::Internals::notesRightBadCut++; + } + } else if (noteEvent.EventType == NoteEventType::Miss) { + if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) { + MetaCore::Internals::notesLeftMissed++; + } else if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorB) { + MetaCore::Internals::notesRightMissed++; + } + } + if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) { + MetaCore::Internals::remainingNotesLeft++; + } else if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorB) { + MetaCore::Internals::remainingNotesRight++; + } } } - _nextIndex = _sortedNoteEvents.size(); } + static bool operator==(const GlobalNamespace::NoteCutInfo& lhs, const GlobalNamespace::NoteCutInfo& rhs) { return lhs.noteData == rhs.noteData; diff --git a/src/ReplaySystem/Playback/PosePlayer.cpp b/src/ReplaySystem/Playback/PosePlayer.cpp index 4751ab18..1b667aa1 100644 --- a/src/ReplaySystem/Playback/PosePlayer.cpp +++ b/src/ReplaySystem/Playback/PosePlayer.cpp @@ -18,6 +18,7 @@ #include #include #include "logging.hpp" +#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" using namespace UnityEngine; using namespace UnityEngine::SpatialTracking; @@ -157,13 +158,8 @@ namespace ScoreSaber::ReplaySystem::Playback void PosePlayer::TimeUpdate(float newTime) { - for (int c = 0; c < _sortedPoses.size(); c++) { - if (_sortedPoses[c].Time > newTime) { - _nextIndex = c; - return; - } - } - _nextIndex = _sortedPoses.size(); + INFO("PosePlayer::TimeUpdate newTime: {}", newTime); + _nextIndex = FindNextEventIndex(newTime, _sortedPoses); } void PosePlayer::SetSpectatorOffset(Vector3 value) { diff --git a/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp b/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp index 1630faf8..84005e23 100644 --- a/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp +++ b/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp @@ -1,4 +1,3 @@ - #include "ReplaySystem/Playback/ReplayTimeSyncController.hpp" #include #include @@ -9,7 +8,8 @@ #include #include #include - +#include "GlobalNamespace/NoteCutSoundEffect.hpp" +#include "GlobalNamespace/NoteCutSoundEffectManager.hpp" #include "logging.hpp" using namespace UnityEngine; @@ -51,16 +51,25 @@ namespace ScoreSaber::ReplaySystem::Playback // Potential input? } + void ReplayTimeSyncController::Initialize() + { + if(!_noteCutSoundEffectManager){ + INFO("Finding NoteCutSoundEffectManager via Resources"); + _noteCutSoundEffectManager = UnityEngine::Object::FindObjectsOfType()->FirstOrDefault(); // weird that this fixes it, why isnt it being injected? + } + } + void ReplayTimeSyncController::UpdateTimes() { - _comboPlayer->TimeUpdate(_audioTimeSyncController->songTime); - _energyPlayer->TimeUpdate(_audioTimeSyncController->songTime); // needs to be run before the ScorePlayer - if(_heightPlayer) + if(_heightPlayer){ _heightPlayer->TimeUpdate(_audioTimeSyncController->songTime); + } + _energyPlayer->TimeUpdate(_audioTimeSyncController->songTime); // needs to be run before the ScorePlayer + _comboPlayer->TimeUpdate(_audioTimeSyncController->songTime); _multiplierPlayer->TimeUpdate(_audioTimeSyncController->songTime); - _notePlayer->TimeUpdate(_audioTimeSyncController->songTime); - _posePlayer->TimeUpdate(_audioTimeSyncController->songTime); _scorePlayer->TimeUpdate(_audioTimeSyncController->songTime); + _posePlayer->TimeUpdate(_audioTimeSyncController->songTime); + _notePlayer->TimeUpdate(_audioTimeSyncController->songTime); } void ReplayTimeSyncController::OverrideTime(float time) @@ -69,70 +78,22 @@ namespace ScoreSaber::ReplaySystem::Playback { return; } - // TODO: Cancel hitsounds CancelAllHitSounds(); - - auto gameNotePoolItems = _basicBeatmapObjectManager->_basicGameNotePoolContainer->activeItems; - for (int i = 0; i < gameNotePoolItems->Count; i++) - { - auto item = gameNotePoolItems->get_Item(i); - item->Hide(false); - item->Pause(false); - item->enabled = true; - item->gameObject->SetActive(true); - item->Dissolve(0.0f); - } - auto sliderHeadPoolItems = _basicBeatmapObjectManager->_burstSliderHeadGameNotePoolContainer->activeItems; - for (int i = 0; i < sliderHeadPoolItems->Count; i++) - { - auto item = sliderHeadPoolItems->get_Item(i); - item->Hide(false); - item->Pause(false); - item->enabled = true; - item->gameObject->SetActive(true); - item->Dissolve(0.0f); - } - auto sliderNotePoolItems = _basicBeatmapObjectManager->_burstSliderGameNotePoolContainer->activeItems; - for (int i = 0; i < sliderNotePoolItems->Count; i++) - { - auto item = sliderNotePoolItems->get_Item(i); - item->Hide(false); - item->Pause(false); - item->enabled = true; - item->gameObject->SetActive(true); - item->Dissolve(0.0f); - } - auto bombNotePoolItems = _basicBeatmapObjectManager->_bombNotePoolContainer->activeItems; - for (int i = 0; i < bombNotePoolItems->Count; i++) - { - auto item = bombNotePoolItems->get_Item(i); - item->Hide(false); - item->Pause(false); - item->enabled = true; - item->gameObject->SetActive(true); - item->Dissolve(0.0f); - } - - auto obstacleNotePool = _basicBeatmapObjectManager->activeObstacleControllers; - for (int i = 0; i < obstacleNotePool->Count; i++) - { - auto item = obstacleNotePool->get_Item(i); - item->Hide(false); - item->Pause(false); - item->enabled = true; - item->gameObject->SetActive(true); - item->Dissolve(0.0f); - } auto previousState = _audioTimeSyncController->state; + _audioTimeSyncController->Pause(); - _audioTimeSyncController->SeekTo(time / _audioTimeSyncController->timeScale); - if (previousState == GlobalNamespace::AudioTimeSyncController::State::Playing) - { - _audioTimeSyncController->Resume(); + + ListW allBmObj = _basicBeatmapObjectManager->_allBeatmapObjects; + + for (auto bmObj : allBmObj) { + bmObj->Pause(false); + bmObj->Hide(false); + ((UnityEngine::Component*) bmObj)->gameObject->active = true; + bmObj->Dissolve(0.0f); } + _callbackInitData->startFilterTime = time; - _beatmapObjectCallbackController->_startFilterTime = time; auto callbacks = _beatmapObjectCallbackController->_callbacksInTimes; auto itr = callbacks->GetEnumerator(); @@ -145,8 +106,17 @@ namespace ScoreSaber::ReplaySystem::Playback } } + _beatmapObjectCallbackController->_prevSongTime = time - 0.01; + _beatmapObjectCallbackController->_songTime = time; + _beatmapObjectCallbackController->_startFilterTime = time; + _audioTimeSyncController->SeekTo(time / _audioTimeSyncController->timeScale); _audioTimeSyncController->_songTime = time; _audioTimeSyncController->Update(); + + if (previousState == GlobalNamespace::AudioTimeSyncController::State::Playing) + { + _audioTimeSyncController->Resume(); + } UpdateTimes(); } @@ -163,17 +133,17 @@ namespace ScoreSaber::ReplaySystem::Playback void ReplayTimeSyncController::CancelAllHitSounds() { - // auto noteCutPool = _noteCutSoundEffectManager->noteCutSoundEffectPoolContainer; - // auto noteCutPoolItems = noteCutPool->activeItems; - // for (int i = 0; i < noteCutPoolItems->Count; i++) - // { - // auto effect = noteCutPoolItems->get_Item(i); - // if (effect->isActiveAndEnabled) - // { - // effect->StopPlayingAndFinish(); - // } - // } - // _noteCutSoundEffectManager->prevNoteATime = -1.0f; - // _noteCutSoundEffectManager->prevNoteBTime = -1.0f; + auto noteCutPool = _noteCutSoundEffectManager->_noteCutSoundEffectPoolContainer; + auto noteCutPoolItems = noteCutPool->activeItems; + for (int i = 0; i < noteCutPoolItems->Count; i++) + { + auto effect = noteCutPoolItems->get_Item(i); + if (effect->isActiveAndEnabled) + { + effect->StopPlayingAndFinish(); + } + } + _noteCutSoundEffectManager->_prevNoteATime = -1.0f; + _noteCutSoundEffectManager->_prevNoteBTime = -1.0f; } } // namespace ScoreSaber::ReplaySystem::Playback \ No newline at end of file diff --git a/src/ReplaySystem/Playback/ScorePlayer.cpp b/src/ReplaySystem/Playback/ScorePlayer.cpp index 7f993781..849a62cb 100644 --- a/src/ReplaySystem/Playback/ScorePlayer.cpp +++ b/src/ReplaySystem/Playback/ScorePlayer.cpp @@ -5,8 +5,10 @@ #include "ReplaySystem/ReplayLoader.hpp" #include #include "Utils/BeatmapUtils.hpp" - +#include "System/Collections/Generic/HashSet_1.hpp" #include "logging.hpp" +#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" +#include "metacore/shared/internals.hpp" using namespace UnityEngine; using namespace ScoreSaber::Data::Private; @@ -27,6 +29,7 @@ namespace ScoreSaber::ReplaySystem::Playback return lhs.Time < rhs.Time; }); } + void ScorePlayer::Tick() { optional recentMultipliedScore; @@ -44,28 +47,28 @@ namespace ScoreSaber::ReplaySystem::Playback void ScorePlayer::TimeUpdate(float newTime) { + INFO("ScorePlayer::TimeUpdate newTime: {}", newTime); ScorePlayer::UpdateMultiplier(); - _nextIndex = _sortedScoreEvents.size(); - for (int c = 0; c < _sortedScoreEvents.size(); c++) { - if (_sortedScoreEvents[c].Time > newTime) { - _nextIndex = c; - break; - } - } + _nextIndex = FindNextEventIndex(newTime, _sortedScoreEvents); - if (_nextIndex > 0) { - auto scoreEvent = _sortedScoreEvents[_nextIndex - 1]; - UpdateScore(scoreEvent.Score, scoreEvent.ImmediateMaxPossibleScore, newTime); - } else { + if (_nextIndex > 0) + { + const auto& ev = _sortedScoreEvents[_nextIndex - 1]; + UpdateScore(ev.Score, ev.ImmediateMaxPossibleScore, newTime); + } + else + { UpdateScore(0, 0, newTime); } } + void ScorePlayer::UpdateMultiplier() { float totalMultiplier = _scoreController->_gameplayModifiersModel->GetTotalMultiplier(_scoreController->_gameplayModifierParams, _gameEnergyCounter->energy); _scoreController->_prevMultiplierFromModifiers = totalMultiplier; + MetaCore::Internals::multiplier = totalMultiplier; } void ScorePlayer::UpdateScore(int newScore, optional immediateMaxPossibleScore, float time) @@ -88,7 +91,26 @@ namespace ScoreSaber::ReplaySystem::Playback if (_scoreController->scoreDidChangeEvent != nullptr) { _scoreController->scoreDidChangeEvent->Invoke(newScore, newModifiedScore); } + + _scoreController->____playerHeadAndObstacleInteraction->____intersectingObstacles->Clear(); + + // this sucks but metacore expects left/right scores separately + // will figure out proper calculations, and probably make a full util for updating metacore values later + MetaCore::Internals::songMaxScore = immediate; + + auto splitScore = [](int total) -> std::pair { + return {total / 2, total - total / 2}; + }; + + auto [leftScore, rightScore] = splitScore(newModifiedScore); + MetaCore::Internals::leftScore = leftScore; + MetaCore::Internals::rightScore = rightScore; + + auto [leftMaxScore, rightMaxScore] = splitScore(immediate); + MetaCore::Internals::leftMaxScore = leftMaxScore; + MetaCore::Internals::rightMaxScore = rightMaxScore; } + int ScorePlayer::CalculatePostNoteCountForTime(float time) { int count = 0; From c3aedd8f8f2fa8ccf92e753b8823ac50bad52750 Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Tue, 16 Dec 2025 14:35:57 +0100 Subject: [PATCH 11/18] fix instant replay with disabled score submission --- src/Hooks/LeaderboardHooks.cpp | 8 ++------ src/Services/UploadService.cpp | 7 +++++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Hooks/LeaderboardHooks.cpp b/src/Hooks/LeaderboardHooks.cpp index f1246e1f..e173be91 100644 --- a/src/Hooks/LeaderboardHooks.cpp +++ b/src/Hooks/LeaderboardHooks.cpp @@ -109,9 +109,7 @@ MAKE_AUTO_HOOK_MATCH(StandardLevelScenesTransitionSetupDataSO_Finish, &GlobalNam GlobalNamespace::StandardLevelScenesTransitionSetupDataSO* self, GlobalNamespace::LevelCompletionResults* levelCompletionResults) { - if(!MetaCore::Game::IsScoreSubmissionDisabled()) { - ScoreSaber::Services::UploadService::Three(self, levelCompletionResults); - } + ScoreSaber::Services::UploadService::Three(self, levelCompletionResults); StandardLevelScenesTransitionSetupDataSO_Finish(self, levelCompletionResults); } @@ -119,8 +117,6 @@ MAKE_AUTO_HOOK_MATCH(MultiplayerLevelScenesTransitionSetupDataSO_Finish, &Global GlobalNamespace::MultiplayerLevelScenesTransitionSetupDataSO* self, GlobalNamespace::MultiplayerResultsData* multiplayerResultsData) { - if(!MetaCore::Game::IsScoreSubmissionDisabled()) { - ScoreSaber::Services::UploadService::Four(self, multiplayerResultsData); - } + ScoreSaber::Services::UploadService::Four(self, multiplayerResultsData); MultiplayerLevelScenesTransitionSetupDataSO_Finish(self, multiplayerResultsData); } \ No newline at end of file diff --git a/src/Services/UploadService.cpp b/src/Services/UploadService.cpp index 23caabef..43965c95 100644 --- a/src/Services/UploadService.cpp +++ b/src/Services/UploadService.cpp @@ -29,6 +29,7 @@ #include "logging.hpp" #include #include +#include #include "static.hpp" #include "Utils/MaxScoreCache.hpp" #include "Utils/GCUtil.hpp" @@ -110,6 +111,12 @@ namespace ScoreSaber::Services::UploadService } ReplayService::WriteSerializedReplay(); + + if(MetaCore::Game::IsScoreSubmissionDisabled()) { + INFO("Score submission is disabled, not uploading score"); + return; + } + // Continue to upload phase Six(beatmapLevel, beatmapKey, levelCompletionResults); } From e6801dd90f00e51ddc69a644649ab868585eb5f3 Mon Sep 17 00:00:00 2001 From: Riley <105916526@student.swin.edu.au> Date: Wed, 17 Dec 2025 01:07:05 +1100 Subject: [PATCH 12/18] Orig behaviour w fixes --- .../ReplaySystem/Playback/TimeUpdateUtils.hpp | 41 ------------------- src/ReplaySystem/Playback/ComboPlayer.cpp | 23 +++++------ src/ReplaySystem/Playback/EnergyPlayer.cpp | 30 +++++++------- .../Playback/MultiplierPlayer.cpp | 32 ++++++--------- src/ReplaySystem/Playback/NotePlayer.cpp | 20 ++++----- src/ReplaySystem/Playback/PosePlayer.cpp | 10 +++-- src/ReplaySystem/Playback/ScorePlayer.cpp | 2 +- 7 files changed, 57 insertions(+), 101 deletions(-) delete mode 100644 include/ReplaySystem/Playback/TimeUpdateUtils.hpp diff --git a/include/ReplaySystem/Playback/TimeUpdateUtils.hpp b/include/ReplaySystem/Playback/TimeUpdateUtils.hpp deleted file mode 100644 index cefe7d66..00000000 --- a/include/ReplaySystem/Playback/TimeUpdateUtils.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once -#include -#include - -// i think i understand templates now :D -template -TValue FindLastEventBeforeOrAt( - float newTime, - const std::vector& events, - TValue defaultValue, - Accessor valueAccessor) -{ - if (events.empty()) - return defaultValue; - - auto it = std::upper_bound( - events.begin(), - events.end(), - newTime, - [](float t, const TEvent& e) { return t < e.Time; } - ); - - if (it == events.begin()) - return defaultValue; - - --it; - return valueAccessor(*it); -} - -template -int FindNextEventIndex(float newTime, const std::vector& events) -{ - auto it = std::upper_bound( - events.begin(), - events.end(), - newTime, - [](float t, const TEvent& e) { return t < e.Time; } - ); - - return static_cast(it - events.begin()); -} diff --git a/src/ReplaySystem/Playback/ComboPlayer.cpp b/src/ReplaySystem/Playback/ComboPlayer.cpp index 98081022..776e5e8a 100644 --- a/src/ReplaySystem/Playback/ComboPlayer.cpp +++ b/src/ReplaySystem/Playback/ComboPlayer.cpp @@ -4,8 +4,7 @@ #include #include #include -#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" -#include "metacore/shared/internals.hpp" +#include using namespace UnityEngine; using namespace ScoreSaber::Data::Private; @@ -27,16 +26,16 @@ namespace ScoreSaber::ReplaySystem::Playback void ComboPlayer::TimeUpdate(float newTime) { - INFO("ComboPlayer::TimeUpdate newTime: {}", newTime); - - int combo = FindLastEventBeforeOrAt( - newTime, - _sortedComboEvents, - 0, - [](const ComboEvent& e) { return e.Combo; } - ); - - UpdateCombo(newTime, combo); + for (int c = 0; c < _sortedComboEvents.size(); c++) + { + // TODO: this has potential to have problems if _sortedComboEvents[c].Time is within an epsilon of newTime, potentially applying combo twice or not at all + if (_sortedComboEvents[c].Time > newTime) + { + UpdateCombo(newTime, c != 0 ? _sortedComboEvents[c - 1].Combo : 0); + return; + } + } + UpdateCombo(newTime, _sortedComboEvents[_sortedComboEvents.size() - 1].Combo); } diff --git a/src/ReplaySystem/Playback/EnergyPlayer.cpp b/src/ReplaySystem/Playback/EnergyPlayer.cpp index 00116262..2e3089ac 100644 --- a/src/ReplaySystem/Playback/EnergyPlayer.cpp +++ b/src/ReplaySystem/Playback/EnergyPlayer.cpp @@ -9,8 +9,7 @@ #include #include #include "logging.hpp" -#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" -#include "metacore/shared/internals.hpp" +#include using namespace UnityEngine; using namespace ScoreSaber::Data::Private; @@ -30,22 +29,23 @@ namespace ScoreSaber::ReplaySystem::Playback void EnergyPlayer::TimeUpdate(float newTime) { - INFO("EnergyPlayer::TimeUpdate newTime: {}", newTime); - - const auto& last = _sortedEnergyEvents.back(); - if (newTime >= last.Time && last.Energy <= Mathf::getStaticF_Epsilon()) + for (int c = 0; c < _sortedEnergyEvents.size(); c++) { - UpdateEnergy(0.0f); - return; + // TODO: this has potential to have problems if _sortedEnergyEvents[c].Time is within an epsilon of newTime, potentially applying energy changes twice or not at all + if (_sortedEnergyEvents[c].Time > newTime) + { + float energy = c != 0 ? _sortedEnergyEvents[c - 1].Energy : 0.5f; + UpdateEnergy(energy); + return; + } } + UpdateEnergy(0.5f); + auto lastEvent = _sortedEnergyEvents[_sortedEnergyEvents.size() - 1]; + if (newTime >= lastEvent.Time && lastEvent.Energy <= Mathf::getStaticF_Epsilon()) + { + UpdateEnergy(0.0f); - float energy = FindLastEventBeforeOrAt( - newTime, - _sortedEnergyEvents, - 0.5f, - [](const auto& e) { return e.Energy; }); - - UpdateEnergy(energy); + } } void EnergyPlayer::UpdateEnergy(float energy) diff --git a/src/ReplaySystem/Playback/MultiplierPlayer.cpp b/src/ReplaySystem/Playback/MultiplierPlayer.cpp index b9eb6d18..51db7bff 100644 --- a/src/ReplaySystem/Playback/MultiplierPlayer.cpp +++ b/src/ReplaySystem/Playback/MultiplierPlayer.cpp @@ -2,8 +2,7 @@ #include "ReplaySystem/ReplayLoader.hpp" #include #include "logging.hpp" -#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" -#include "metacore/shared/internals.hpp" +#include using namespace UnityEngine; using namespace ScoreSaber::Data::Private; @@ -22,25 +21,20 @@ namespace ScoreSaber::ReplaySystem::Playback void MultiplierPlayer::TimeUpdate(float newTime) { - INFO("MultiplierPlayer::TimeUpdate newTime: {}", newTime); - - int index = FindNextEventIndex(newTime, _sortedMultiplierEvents); - - if (index == 0) - { - UpdateMultiplier(1, 0.0f); - return; - } - - if (index < _sortedMultiplierEvents.size()) + for (int c = 0; c < _sortedMultiplierEvents.size(); c++) { - const auto& ev = _sortedMultiplierEvents[index - 1]; - UpdateMultiplier(ev.Multiplier, ev.NextMultiplierProgress); + // TODO: this has potential to have problems if _sortedMultiplierEvents[c].Time is within an epsilon of newTime, potentially applying combo changes twice or not at all + if (_sortedMultiplierEvents[c].Time > newTime) + { + int multiplier = c != 0 ? _sortedMultiplierEvents[c - 1].Multiplier : 1; + float progress = c != 0 ? _sortedMultiplierEvents[c - 1].NextMultiplierProgress : 0.0f; + UpdateMultiplier(multiplier, progress); + return; + } } - else - { - const auto& last = _sortedMultiplierEvents.back(); - UpdateMultiplier(last.Multiplier, last.NextMultiplierProgress); + if (_sortedMultiplierEvents.size() > 0) { + auto lastEvent = _sortedMultiplierEvents[_sortedMultiplierEvents.size() - 1]; + UpdateMultiplier(lastEvent.Multiplier, lastEvent.NextMultiplierProgress); } } diff --git a/src/ReplaySystem/Playback/NotePlayer.cpp b/src/ReplaySystem/Playback/NotePlayer.cpp index a429b73a..01ac7715 100644 --- a/src/ReplaySystem/Playback/NotePlayer.cpp +++ b/src/ReplaySystem/Playback/NotePlayer.cpp @@ -14,8 +14,7 @@ #include #include "logging.hpp" #include -#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" -#include "metacore/shared/internals.hpp" +#include using namespace UnityEngine; using namespace ScoreSaber::Data::Private; @@ -138,12 +137,8 @@ namespace ScoreSaber::ReplaySystem::Playback } return true; } - void NotePlayer::TimeUpdate(float newTime) { - INFO("NotePlayer::TimeUpdate newTime: {}", newTime); - _nextIndex = FindNextEventIndex(newTime, _sortedNoteEvents); - MetaCore::Internals::notesLeftBadCut = 0; MetaCore::Internals::notesRightBadCut = 0; MetaCore::Internals::notesLeftMissed = 0; @@ -156,9 +151,9 @@ namespace ScoreSaber::ReplaySystem::Playback // MetaCore::Internals::rightMissedFixedScore = 0; MetaCore::Internals::leftMissedMaxScore = 0; MetaCore::Internals::rightMissedMaxScore = 0; - - for (int i = 0; i < _sortedNoteEvents.size(); i++) { - auto& noteEvent = _sortedNoteEvents[i]; + for (int c = 0; c < _sortedNoteEvents.size(); c++) + { + auto& noteEvent = _sortedNoteEvents[c]; if (noteEvent.Time > newTime) { if (noteEvent.EventType == NoteEventType::BadCut) { if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) { @@ -179,9 +174,14 @@ namespace ScoreSaber::ReplaySystem::Playback MetaCore::Internals::remainingNotesRight++; } } + if (_sortedNoteEvents[c].Time > newTime) + { + _nextIndex = c; + return; + } } + _nextIndex = _sortedNoteEvents.size(); } - static bool operator==(const GlobalNamespace::NoteCutInfo& lhs, const GlobalNamespace::NoteCutInfo& rhs) { return lhs.noteData == rhs.noteData; diff --git a/src/ReplaySystem/Playback/PosePlayer.cpp b/src/ReplaySystem/Playback/PosePlayer.cpp index 1b667aa1..4751ab18 100644 --- a/src/ReplaySystem/Playback/PosePlayer.cpp +++ b/src/ReplaySystem/Playback/PosePlayer.cpp @@ -18,7 +18,6 @@ #include #include #include "logging.hpp" -#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" using namespace UnityEngine; using namespace UnityEngine::SpatialTracking; @@ -158,8 +157,13 @@ namespace ScoreSaber::ReplaySystem::Playback void PosePlayer::TimeUpdate(float newTime) { - INFO("PosePlayer::TimeUpdate newTime: {}", newTime); - _nextIndex = FindNextEventIndex(newTime, _sortedPoses); + for (int c = 0; c < _sortedPoses.size(); c++) { + if (_sortedPoses[c].Time > newTime) { + _nextIndex = c; + return; + } + } + _nextIndex = _sortedPoses.size(); } void PosePlayer::SetSpectatorOffset(Vector3 value) { diff --git a/src/ReplaySystem/Playback/ScorePlayer.cpp b/src/ReplaySystem/Playback/ScorePlayer.cpp index 849a62cb..b01bed9d 100644 --- a/src/ReplaySystem/Playback/ScorePlayer.cpp +++ b/src/ReplaySystem/Playback/ScorePlayer.cpp @@ -8,7 +8,7 @@ #include "System/Collections/Generic/HashSet_1.hpp" #include "logging.hpp" #include "ReplaySystem/Playback/TimeUpdateUtils.hpp" -#include "metacore/shared/internals.hpp" +#include using namespace UnityEngine; using namespace ScoreSaber::Data::Private; From 7e83a8055afa65ac458557605e56a6e7d5ff25d5 Mon Sep 17 00:00:00 2001 From: Riley <105916526@student.swin.edu.au> Date: Wed, 17 Dec 2025 01:13:21 +1100 Subject: [PATCH 13/18] fix includes and scoreplayer --- src/Hooks/ReplayHooks.cpp | 2 +- .../Playback/ReplayTimeSyncController.cpp | 4 ++-- src/ReplaySystem/Playback/ScorePlayer.cpp | 22 +++++++++---------- src/Utils/MaxScoreCache.cpp | 8 +++---- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Hooks/ReplayHooks.cpp b/src/Hooks/ReplayHooks.cpp index 6964e1cf..871c65bd 100644 --- a/src/Hooks/ReplayHooks.cpp +++ b/src/Hooks/ReplayHooks.cpp @@ -34,7 +34,7 @@ #include #include #include -#include "GlobalNamespace/FlyingScoreSpawner.hpp" +#include #include "logging.hpp" using namespace UnityEngine; diff --git a/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp b/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp index 84005e23..abc73f29 100644 --- a/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp +++ b/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp @@ -8,8 +8,8 @@ #include #include #include -#include "GlobalNamespace/NoteCutSoundEffect.hpp" -#include "GlobalNamespace/NoteCutSoundEffectManager.hpp" +#include +#include #include "logging.hpp" using namespace UnityEngine; diff --git a/src/ReplaySystem/Playback/ScorePlayer.cpp b/src/ReplaySystem/Playback/ScorePlayer.cpp index b01bed9d..15abd846 100644 --- a/src/ReplaySystem/Playback/ScorePlayer.cpp +++ b/src/ReplaySystem/Playback/ScorePlayer.cpp @@ -7,7 +7,6 @@ #include "Utils/BeatmapUtils.hpp" #include "System/Collections/Generic/HashSet_1.hpp" #include "logging.hpp" -#include "ReplaySystem/Playback/TimeUpdateUtils.hpp" #include using namespace UnityEngine; @@ -47,23 +46,24 @@ namespace ScoreSaber::ReplaySystem::Playback void ScorePlayer::TimeUpdate(float newTime) { - INFO("ScorePlayer::TimeUpdate newTime: {}", newTime); ScorePlayer::UpdateMultiplier(); - _nextIndex = FindNextEventIndex(newTime, _sortedScoreEvents); - - if (_nextIndex > 0) - { - const auto& ev = _sortedScoreEvents[_nextIndex - 1]; - UpdateScore(ev.Score, ev.ImmediateMaxPossibleScore, newTime); + _nextIndex = _sortedScoreEvents.size(); + for (int c = 0; c < _sortedScoreEvents.size(); c++) { + if (_sortedScoreEvents[c].Time > newTime) { + _nextIndex = c; + break; + } } - else - { + + if (_nextIndex > 0) { + auto scoreEvent = _sortedScoreEvents[_nextIndex - 1]; + UpdateScore(scoreEvent.Score, scoreEvent.ImmediateMaxPossibleScore, newTime); + } else { UpdateScore(0, 0, newTime); } } - void ScorePlayer::UpdateMultiplier() { float totalMultiplier = _scoreController->_gameplayModifiersModel->GetTotalMultiplier(_scoreController->_gameplayModifierParams, _gameEnergyCounter->energy); diff --git a/src/Utils/MaxScoreCache.cpp b/src/Utils/MaxScoreCache.cpp index ca3cdc62..a698c425 100644 --- a/src/Utils/MaxScoreCache.cpp +++ b/src/Utils/MaxScoreCache.cpp @@ -3,13 +3,13 @@ #include #include #include -#include "GlobalNamespace/zzzz__BeatmapLevelDataVersion_def.hpp" -#include "GlobalNamespace/zzzz__BeatmapLevelsEntitlementModel_def.hpp" -#include "System/Threading/zzzz__CancellationToken_def.hpp" +#include +#include +#include #include "Utils/DelegateUtils.hpp" #include "Utils/SafePtr.hpp" #include "Utils/GCUtil.hpp" -#include "bsml/shared/BSML/MainThreadScheduler.hpp" +#include #include "logging.hpp" using namespace GlobalNamespace; From cd6ca1913ee395cfc7e926aa4c12ec919028f6dc Mon Sep 17 00:00:00 2001 From: Riley <105916526@student.swin.edu.au> Date: Wed, 17 Dec 2025 02:17:25 +1100 Subject: [PATCH 14/18] fix combo checks and cutsound ctor --- include/ReplaySystem/Playback/ComboPlayer.hpp | 3 ++ .../Playback/ReplayTimeSyncController.hpp | 5 ++-- src/ReplaySystem/Playback/ComboPlayer.cpp | 29 ++++++++++--------- .../Playback/ReplayTimeSyncController.cpp | 12 ++------ 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/include/ReplaySystem/Playback/ComboPlayer.hpp b/include/ReplaySystem/Playback/ComboPlayer.hpp index c4b33442..9eaa79b7 100644 --- a/include/ReplaySystem/Playback/ComboPlayer.hpp +++ b/include/ReplaySystem/Playback/ComboPlayer.hpp @@ -16,4 +16,7 @@ DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Playback, ComboPlayer, Il2CppObj vector _sortedNoteEvents; vector _sortedComboEvents; void UpdateCombo(float time, int combo); + + private: + int highestCombo = 0; }; diff --git a/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp b/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp index 1e7ba477..5069e088 100644 --- a/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp +++ b/include/ReplaySystem/Playback/ReplayTimeSyncController.hpp @@ -23,7 +23,7 @@ DECLARE_CLASS_CODEGEN_INTERFACES( ScoreSaber::ReplaySystem::Playback, ReplayTimeSyncController, System::Object, - Zenject::ITickable*, Zenject::IInitializable*) { + Zenject::ITickable*) { DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioTimeSyncController); DECLARE_INSTANCE_FIELD_PRIVATE(UnityW, _audioManagerSO); DECLARE_INSTANCE_FIELD_PRIVATE(GlobalNamespace::AudioTimeSyncController::InitData*, _audioInitData); @@ -44,13 +44,12 @@ DECLARE_CLASS_CODEGEN_INTERFACES( GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::AudioTimeSyncController::InitData* audioInitData, GlobalNamespace::BasicBeatmapObjectManager* basicBeatmapObjectManager, - GlobalNamespace::NoteCutSoundEffectManager* _noteCutSoundEffectManager, + GlobalNamespace::NoteCutSoundEffectManager* noteCutSoundEffectManager, GlobalNamespace::BeatmapCallbacksController::InitData* callbackInitData, GlobalNamespace::BeatmapCallbacksController* beatmapObjectCallbackController, Zenject::DiContainer* container); DECLARE_OVERRIDE_METHOD_MATCH(void, Tick, &::Zenject::ITickable::Tick); - DECLARE_OVERRIDE_METHOD_MATCH(void, Initialize, &::Zenject::IInitializable::Initialize); DECLARE_INSTANCE_METHOD(void, UpdateTimes); DECLARE_INSTANCE_METHOD(void, OverrideTime, float time); DECLARE_INSTANCE_METHOD(void, OverrideTimeScale, float timeScale); diff --git a/src/ReplaySystem/Playback/ComboPlayer.cpp b/src/ReplaySystem/Playback/ComboPlayer.cpp index 776e5e8a..7e9ea61e 100644 --- a/src/ReplaySystem/Playback/ComboPlayer.cpp +++ b/src/ReplaySystem/Playback/ComboPlayer.cpp @@ -22,6 +22,7 @@ namespace ScoreSaber::ReplaySystem::Playback _comboUIController = UnityEngine::Resources::FindObjectsOfTypeAll()->First(); _sortedNoteEvents = ReplayLoader::LoadedReplay->noteKeyframes; _sortedComboEvents = ReplayLoader::LoadedReplay->comboKeyframes; + highestCombo = 0; } void ComboPlayer::TimeUpdate(float newTime) @@ -75,35 +76,35 @@ namespace ScoreSaber::ReplaySystem::Playback } } - if (previousComboEvents[c].EventType == NoteEventType::GoodCut) { if (previousComboEvents[c].SaberType == 0) { leftCombo++; - if (leftHighest < leftCombo) { - leftHighest = leftCombo; - } + leftHighest = std::max(leftHighest, leftCombo); } else { rightCombo++; - if (rightHighest < rightCombo) { - rightHighest = rightCombo; - } + rightHighest = std::max(rightHighest, rightCombo); } } - else{ - if (previousComboEvents[c].SaberType == 0) { + else if ( + previousComboEvents[c].EventType == NoteEventType::BadCut || + previousComboEvents[c].EventType == NoteEventType::Miss + ) + { + if (previousComboEvents[c].SaberType == 0) leftCombo = 0; - } - else { + else rightCombo = 0; - } } } + _comboController->_combo = combo; - _comboController->_maxCombo = cutOrMissRecorded; + highestCombo = std::max(highestCombo, combo); + _comboController->_maxCombo = highestCombo; + if (_comboController->comboDidChangeEvent != nullptr) { _comboController->comboDidChangeEvent->Invoke(combo); @@ -131,7 +132,7 @@ namespace ScoreSaber::ReplaySystem::Playback MetaCore::Internals::combo = combo; - MetaCore::Internals::highestCombo = cutOrMissRecorded == 0 ? 0 : std::max(combo, cutOrMissRecorded); + MetaCore::Internals::highestCombo = highestCombo; MetaCore::Internals::leftCombo = leftCombo; MetaCore::Internals::rightCombo = rightCombo; MetaCore::Internals::highestLeftCombo = leftHighest; diff --git a/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp b/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp index abc73f29..a4b8548a 100644 --- a/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp +++ b/src/ReplaySystem/Playback/ReplayTimeSyncController.cpp @@ -22,7 +22,7 @@ namespace ScoreSaber::ReplaySystem::Playback void ReplayTimeSyncController::ctor(GlobalNamespace::AudioTimeSyncController* audioTimeSyncController, GlobalNamespace::AudioTimeSyncController::InitData* audioInitData, GlobalNamespace::BasicBeatmapObjectManager* basicBeatmapObjectManager, - GlobalNamespace::NoteCutSoundEffectManager* _noteCutSoundEffectManager, + GlobalNamespace::NoteCutSoundEffectManager* noteCutSoundEffectManager, GlobalNamespace::BeatmapCallbacksController::InitData* callbackInitData, GlobalNamespace::BeatmapCallbacksController* beatmapObjectCallbackController, Zenject::DiContainer* container) @@ -31,7 +31,7 @@ namespace ScoreSaber::ReplaySystem::Playback _audioTimeSyncController = audioTimeSyncController; _audioInitData = audioInitData; _basicBeatmapObjectManager = basicBeatmapObjectManager; - _noteCutSoundEffectManager = _noteCutSoundEffectManager; + _noteCutSoundEffectManager = noteCutSoundEffectManager; _callbackInitData = callbackInitData; _beatmapObjectCallbackController = beatmapObjectCallbackController; @@ -51,14 +51,6 @@ namespace ScoreSaber::ReplaySystem::Playback // Potential input? } - void ReplayTimeSyncController::Initialize() - { - if(!_noteCutSoundEffectManager){ - INFO("Finding NoteCutSoundEffectManager via Resources"); - _noteCutSoundEffectManager = UnityEngine::Object::FindObjectsOfType()->FirstOrDefault(); // weird that this fixes it, why isnt it being injected? - } - } - void ReplayTimeSyncController::UpdateTimes() { if(_heightPlayer){ From 098d8cb2ccbd2222b695a5d508a3e0ed995ca4f1 Mon Sep 17 00:00:00 2001 From: Riley <105916526@student.swin.edu.au> Date: Wed, 17 Dec 2025 02:34:10 +1100 Subject: [PATCH 15/18] fix metacore note calculations --- src/ReplaySystem/Playback/NotePlayer.cpp | 60 ++++++++++++++++-------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/src/ReplaySystem/Playback/NotePlayer.cpp b/src/ReplaySystem/Playback/NotePlayer.cpp index 01ac7715..5d4253b9 100644 --- a/src/ReplaySystem/Playback/NotePlayer.cpp +++ b/src/ReplaySystem/Playback/NotePlayer.cpp @@ -9,6 +9,7 @@ #include #include #include +#include "Data/Private/ReplayFile.hpp" #include "ReplaySystem/ReplayLoader.hpp" #include #include @@ -137,8 +138,10 @@ namespace ScoreSaber::ReplaySystem::Playback } return true; } + void NotePlayer::TimeUpdate(float newTime) { + // reset MetaCore::Internals::notesLeftBadCut = 0; MetaCore::Internals::notesRightBadCut = 0; MetaCore::Internals::notesLeftMissed = 0; @@ -147,41 +150,58 @@ namespace ScoreSaber::ReplaySystem::Playback MetaCore::Internals::notesRightCut = 0; MetaCore::Internals::remainingNotesLeft = 0; MetaCore::Internals::remainingNotesRight = 0; - // MetaCore::Internals::leftMissedFixedScore = 0; // chains or something but not important rn - // MetaCore::Internals::rightMissedFixedScore = 0; - MetaCore::Internals::leftMissedMaxScore = 0; - MetaCore::Internals::rightMissedMaxScore = 0; + + bool checkedNextIndex = false; + for (int c = 0; c < _sortedNoteEvents.size(); c++) { - auto& noteEvent = _sortedNoteEvents[c]; - if (noteEvent.Time > newTime) { - if (noteEvent.EventType == NoteEventType::BadCut) { - if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) { + auto& e = _sortedNoteEvents[c]; + if(e.EventType == NoteEventType::Bomb || e.EventType == NoteEventType::None) continue; + if (e.Time <= newTime) + { + if (e.EventType == NoteEventType::BadCut) + { + if (e.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) + { MetaCore::Internals::notesLeftBadCut++; - } else if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorB) { + } + else + { MetaCore::Internals::notesRightBadCut++; } - } else if (noteEvent.EventType == NoteEventType::Miss) { - if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) { + } + else if (e.EventType == NoteEventType::Miss) + { + if (e.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) + { MetaCore::Internals::notesLeftMissed++; - } else if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorB) { + } + else + { MetaCore::Internals::notesRightMissed++; } } - if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) { + } + else + { + if (!checkedNextIndex) + { + _nextIndex = c; + checkedNextIndex = true; + } + + if (e.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorA) + { MetaCore::Internals::remainingNotesLeft++; - } else if (noteEvent.TheNoteID.ColorType == (int)GlobalNamespace::ColorType::ColorB) { + } + else + { MetaCore::Internals::remainingNotesRight++; } } - if (_sortedNoteEvents[c].Time > newTime) - { - _nextIndex = c; - return; - } } - _nextIndex = _sortedNoteEvents.size(); } + static bool operator==(const GlobalNamespace::NoteCutInfo& lhs, const GlobalNamespace::NoteCutInfo& rhs) { return lhs.noteData == rhs.noteData; From 2332c27c67a61032de32c3e6159423c31fb705fb Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Tue, 16 Dec 2025 18:07:59 +0100 Subject: [PATCH 16/18] fix energy after last energy event --- src/ReplaySystem/Playback/EnergyPlayer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ReplaySystem/Playback/EnergyPlayer.cpp b/src/ReplaySystem/Playback/EnergyPlayer.cpp index 2e3089ac..ebdff40b 100644 --- a/src/ReplaySystem/Playback/EnergyPlayer.cpp +++ b/src/ReplaySystem/Playback/EnergyPlayer.cpp @@ -41,9 +41,9 @@ namespace ScoreSaber::ReplaySystem::Playback } UpdateEnergy(0.5f); auto lastEvent = _sortedEnergyEvents[_sortedEnergyEvents.size() - 1]; - if (newTime >= lastEvent.Time && lastEvent.Energy <= Mathf::getStaticF_Epsilon()) + if (newTime >= lastEvent.Time) { - UpdateEnergy(0.0f); + UpdateEnergy(lastEvent.Energy); } } From fd7ffbbc02b97607eaa9795c22f9cadaf95d9f9c Mon Sep 17 00:00:00 2001 From: Riley <105916526@student.swin.edu.au> Date: Wed, 17 Dec 2025 12:23:54 +1100 Subject: [PATCH 17/18] fix combo calculation once more --- include/ReplaySystem/Playback/ComboPlayer.hpp | 3 --- src/ReplaySystem/Playback/ComboPlayer.cpp | 12 ++++++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/ReplaySystem/Playback/ComboPlayer.hpp b/include/ReplaySystem/Playback/ComboPlayer.hpp index 9eaa79b7..c4b33442 100644 --- a/include/ReplaySystem/Playback/ComboPlayer.hpp +++ b/include/ReplaySystem/Playback/ComboPlayer.hpp @@ -16,7 +16,4 @@ DECLARE_CLASS_CODEGEN(ScoreSaber::ReplaySystem::Playback, ComboPlayer, Il2CppObj vector _sortedNoteEvents; vector _sortedComboEvents; void UpdateCombo(float time, int combo); - - private: - int highestCombo = 0; }; diff --git a/src/ReplaySystem/Playback/ComboPlayer.cpp b/src/ReplaySystem/Playback/ComboPlayer.cpp index 7e9ea61e..0a924582 100644 --- a/src/ReplaySystem/Playback/ComboPlayer.cpp +++ b/src/ReplaySystem/Playback/ComboPlayer.cpp @@ -22,7 +22,6 @@ namespace ScoreSaber::ReplaySystem::Playback _comboUIController = UnityEngine::Resources::FindObjectsOfTypeAll()->First(); _sortedNoteEvents = ReplayLoader::LoadedReplay->noteKeyframes; _sortedComboEvents = ReplayLoader::LoadedReplay->comboKeyframes; - highestCombo = 0; } void ComboPlayer::TimeUpdate(float newTime) @@ -59,6 +58,9 @@ namespace ScoreSaber::ReplaySystem::Playback int leftHighest = 0; int rightHighest = 0; + int highestCombo = 0; + + int comboCounter = 0; for (int c = 0; c < previousComboEvents.size(); c++) { @@ -78,6 +80,7 @@ namespace ScoreSaber::ReplaySystem::Playback if (previousComboEvents[c].EventType == NoteEventType::GoodCut) { + comboCounter++; if (previousComboEvents[c].SaberType == 0) { leftCombo++; @@ -91,18 +94,20 @@ namespace ScoreSaber::ReplaySystem::Playback } else if ( previousComboEvents[c].EventType == NoteEventType::BadCut || - previousComboEvents[c].EventType == NoteEventType::Miss + previousComboEvents[c].EventType == NoteEventType::Miss || + previousComboEvents[c].EventType == NoteEventType::Bomb ) { + comboCounter = 0; if (previousComboEvents[c].SaberType == 0) leftCombo = 0; else rightCombo = 0; } + highestCombo = std::max(highestCombo, comboCounter); } _comboController->_combo = combo; - highestCombo = std::max(highestCombo, combo); _comboController->_maxCombo = highestCombo; if (_comboController->comboDidChangeEvent != nullptr) @@ -130,7 +135,6 @@ namespace ScoreSaber::ReplaySystem::Playback _comboUIController->_fullComboLost = true; } - MetaCore::Internals::combo = combo; MetaCore::Internals::highestCombo = highestCombo; MetaCore::Internals::leftCombo = leftCombo; From 0fb5d31babc29238e4304f58ca2e820d9847bf8f Mon Sep 17 00:00:00 2001 From: Qwasyx Date: Thu, 18 Dec 2025 19:58:51 +0100 Subject: [PATCH 18/18] pin versions of everything to hopefully make CI/CD build again --- .gitignore | 1 - qpm.json | 221 ++++++++++++++-------------- qpm.shared.json | 374 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 486 insertions(+), 110 deletions(-) create mode 100644 qpm.shared.json diff --git a/.gitignore b/.gitignore index 914a7eaf..a6aadc37 100644 --- a/.gitignore +++ b/.gitignore @@ -46,7 +46,6 @@ ndkpath.txt *.txt extern/ Android.mk.backup -qpm.shared.json qpm_defines.cmake extern.cmake build/ diff --git a/qpm.json b/qpm.json index 8e93ab45..c3804cdc 100644 --- a/qpm.json +++ b/qpm.json @@ -1,113 +1,116 @@ { - "sharedDir": "shared", - "dependenciesDir": "extern", - "info": { - "name": "ScoreSaber", - "id": "scoresaber", - "version": "1.0.0", - "url": null, - "additionalData": { - "overrideSoName": "libscoresaber.so", - "cmake": true - } - }, - "workspace": { - "scripts": { - "build": [ - "pwsh ./scripts/build.ps1" - ], - "clean": [ - "pwsh ./scripts/build.ps1 -clean" - ], - "copy": [ - "pwsh ./scripts/copy.ps1 $0:?" - ], - "logcat": [ - "pwsh ./scripts/start-logging.ps1 $0:?" - ], - "qmod": [ - "pwsh ./scripts/build.ps1", - "pwsh ./scripts/createqmod.ps1" - ], - "restart": [ - "pwsh ./scripts/restart-game.ps1" - ], - "stack": [ - "pwsh ./scripts/ndk-stack.ps1" - ], - "tomb": [ - "pwsh ./scripts/pull-tombstone.ps1" - ] - }, - "qmodIncludeDirs": [ - "./build", - "./extern/libs" + "$schema": "https://raw.githubusercontent.com/QuestPackageManager/QPM.Package/refs/heads/main/qpm.schema.json", + "version": "0.4.0", + "sharedDir": "shared", + "dependenciesDir": "extern", + "info": { + "name": "ScoreSaber", + "id": "scoresaber", + "version": "1.0.0", + "url": null, + "additionalData": { + "overrideSoName": "libscoresaber.so", + "cmake": true + } + }, + "workspace": { + "scripts": { + "build": [ + "pwsh ./scripts/build.ps1" + ], + "clean": [ + "pwsh ./scripts/build.ps1 -clean" + ], + "copy": [ + "pwsh ./scripts/copy.ps1 $0:?" + ], + "logcat": [ + "pwsh ./scripts/start-logging.ps1 $0:?" ], - "qmodOutput": "./ScoreSaber.qmod" - }, - "dependencies": [ - { - "id": "beatsaber-hook", - "versionRange": "^6.4.2", - "additionalData": {} - }, - { - "id": "scotland2", - "versionRange": "^0.1.6", - "additionalData": { - "includeQmod": false - } - }, - { - "id": "bs-cordl", - "versionRange": "^4008.0.0", - "additionalData": {} - }, - { - "id": "custom-types", - "versionRange": "^0.18.3", - "additionalData": {} - }, - { - "id": "config-utils", - "versionRange": "^2.0.3", - "additionalData": {} - }, - { - "id": "libcurl", - "versionRange": "=8.5.0", - "additionalData": {} - }, - { - "id": "gif-lib", - "versionRange": "^5.2.2", - "additionalData": {} - }, - { - "id": "lapiz", - "versionRange": "^0.2.23", - "additionalData": {} - }, - { - "id": "bsml", - "versionRange": "^0.4.55", - "additionalData": {} - }, - { - "id": "tinyxml2", - "versionRange": "^10.0.0", - "additionalData": {} - }, - { - "id": "paper2_scotland2", - "versionRange": "^4.6.4", - "additionalData": {} - }, - { - "id": "metacore", - "versionRange": "^1.4.0", - "additionalData": {} + "qmod": [ + "pwsh ./scripts/build.ps1", + "pwsh ./scripts/createqmod.ps1" + ], + "restart": [ + "pwsh ./scripts/restart-game.ps1" + ], + "stack": [ + "pwsh ./scripts/ndk-stack.ps1" + ], + "tomb": [ + "pwsh ./scripts/pull-tombstone.ps1" + ] + }, + "ndk": "^27.2.12479018", + "qmodIncludeDirs": [ + "./build", + "./extern/libs" + ], + "qmodIncludeFiles": [], + "qmodOutput": "./ScoreSaber.qmod" + }, + "dependencies": [ + { + "id": "beatsaber-hook", + "versionRange": "^6.4.2", + "additionalData": {} + }, + { + "id": "scotland2", + "versionRange": "^0.1.6", + "additionalData": { + "includeQmod": false } - ], - "additionalData": {} + }, + { + "id": "bs-cordl", + "versionRange": "^4008.0.0", + "additionalData": {} + }, + { + "id": "custom-types", + "versionRange": "^0.18.3", + "additionalData": {} + }, + { + "id": "config-utils", + "versionRange": "^2.0.3", + "additionalData": {} + }, + { + "id": "libcurl", + "versionRange": "=8.5.0", + "additionalData": {} + }, + { + "id": "gif-lib", + "versionRange": "^5.2.2", + "additionalData": {} + }, + { + "id": "lapiz", + "versionRange": "^0.2.23", + "additionalData": {} + }, + { + "id": "bsml", + "versionRange": "^0.4.55", + "additionalData": {} + }, + { + "id": "tinyxml2", + "versionRange": "^10.0.0", + "additionalData": {} + }, + { + "id": "paper2_scotland2", + "versionRange": "^4.6.4", + "additionalData": {} + }, + { + "id": "metacore", + "versionRange": "^1.4.0", + "additionalData": {} + } + ] } \ No newline at end of file diff --git a/qpm.shared.json b/qpm.shared.json new file mode 100644 index 00000000..a10c820e --- /dev/null +++ b/qpm.shared.json @@ -0,0 +1,374 @@ +{ + "$schema": "https://raw.githubusercontent.com/QuestPackageManager/QPM.Package/refs/heads/main/qpm.shared.schema.json", + "config": { + "version": "0.4.0", + "sharedDir": "shared", + "dependenciesDir": "extern", + "info": { + "name": "ScoreSaber", + "id": "scoresaber", + "version": "1.0.0", + "url": null, + "additionalData": { + "overrideSoName": "libscoresaber.so", + "cmake": true + } + }, + "workspace": { + "scripts": { + "build": [ + "pwsh ./scripts/build.ps1" + ], + "clean": [ + "pwsh ./scripts/build.ps1 -clean" + ], + "copy": [ + "pwsh ./scripts/copy.ps1 $0:?" + ], + "logcat": [ + "pwsh ./scripts/start-logging.ps1 $0:?" + ], + "qmod": [ + "pwsh ./scripts/build.ps1", + "pwsh ./scripts/createqmod.ps1" + ], + "restart": [ + "pwsh ./scripts/restart-game.ps1" + ], + "stack": [ + "pwsh ./scripts/ndk-stack.ps1" + ], + "tomb": [ + "pwsh ./scripts/pull-tombstone.ps1" + ] + }, + "ndk": "^27.2.12479018", + "qmodIncludeDirs": [ + "./build", + "./extern/libs" + ], + "qmodIncludeFiles": [], + "qmodOutput": "./ScoreSaber.qmod" + }, + "dependencies": [ + { + "id": "beatsaber-hook", + "versionRange": "^6.4.2", + "additionalData": {} + }, + { + "id": "scotland2", + "versionRange": "^0.1.6", + "additionalData": { + "includeQmod": false + } + }, + { + "id": "bs-cordl", + "versionRange": "^4008.0.0", + "additionalData": {} + }, + { + "id": "custom-types", + "versionRange": "^0.18.3", + "additionalData": {} + }, + { + "id": "config-utils", + "versionRange": "^2.0.3", + "additionalData": {} + }, + { + "id": "libcurl", + "versionRange": "=8.5.0", + "additionalData": {} + }, + { + "id": "gif-lib", + "versionRange": "^5.2.2", + "additionalData": {} + }, + { + "id": "lapiz", + "versionRange": "^0.2.23", + "additionalData": {} + }, + { + "id": "bsml", + "versionRange": "^0.4.55", + "additionalData": {} + }, + { + "id": "tinyxml2", + "versionRange": "^10.0.0", + "additionalData": {} + }, + { + "id": "paper2_scotland2", + "versionRange": "^4.6.4", + "additionalData": {} + }, + { + "id": "metacore", + "versionRange": "^1.4.0", + "additionalData": {} + } + ] + }, + "restoredDependencies": [ + { + "dependency": { + "id": "sombrero", + "versionRange": "=0.1.43", + "additionalData": { + "headersOnly": true, + "branchName": "version/v0_1_43" + } + }, + "version": "0.1.43" + }, + { + "dependency": { + "id": "bs-cordl", + "versionRange": "=4008.0.0", + "additionalData": { + "headersOnly": true, + "branchName": "version/v4008_0_0", + "compileOptions": { + "includePaths": [ + "include" + ], + "cppFeatures": [], + "cppFlags": [ + "-DNEED_UNSAFE_CSHARP", + "-fdeclspec", + "-DUNITY_2021", + "-DHAS_CODEGEN", + "-Wno-invalid-offsetof" + ] + } + } + }, + "version": "4008.0.0" + }, + { + "dependency": { + "id": "lapiz", + "versionRange": "=0.2.23", + "additionalData": { + "soLink": "https://github.com/raineaeternal/Lapiz/releases/download/v0.2.23/liblapiz.so", + "debugSoLink": "https://github.com/raineaeternal/Lapiz/releases/download/v0.2.23/debug_liblapiz.so", + "overrideSoName": "liblapiz.so", + "modLink": "https://github.com/raineaeternal/Lapiz/releases/download/v0.2.23/Lapiz.qmod", + "branchName": "version/v0_2_23", + "cmake": true + } + }, + "version": "0.2.23" + }, + { + "dependency": { + "id": "tinyxml2", + "versionRange": "=10.0.0", + "additionalData": { + "soLink": "https://github.com/MillzyDev/NDK-tinyxml2/releases/download/v10.0.0/libtinyxml2.so", + "debugSoLink": "https://github.com/MillzyDev/NDK-tinyxml2/releases/download/v10.0.0/debug_libtinyxml2.so", + "overrideSoName": "libtinyxml2.so", + "modLink": "https://github.com/MillzyDev/NDK-tinyxml2/releases/download/v10.0.0/tinyxml2.qmod", + "branchName": "version/v10_0_0", + "cmake": true + } + }, + "version": "10.0.0" + }, + { + "dependency": { + "id": "metacore", + "versionRange": "=1.6.2", + "additionalData": { + "soLink": "https://github.com/Metalit/MetaCore/releases/download/v1.6.2/libmetacore.so", + "overrideSoName": "libmetacore.so", + "modLink": "https://github.com/Metalit/MetaCore/releases/download/v1.6.2/MetaCore.qmod", + "branchName": "version/v1_6_2", + "cmake": true + } + }, + "version": "1.6.2" + }, + { + "dependency": { + "id": "gif-lib", + "versionRange": "=5.2.2", + "additionalData": { + "staticLinking": true, + "soLink": "https://github.com/RedBrumbler/gif-lib-QPM/releases/download/v5.2.2/libgif-lib.a", + "debugSoLink": "https://github.com/RedBrumbler/gif-lib-QPM/releases/download/v5.2.2/debug_libgif-lib.a", + "overrideSoName": "libgif-lib.a", + "branchName": "version-v5.2.2" + } + }, + "version": "5.2.2" + }, + { + "dependency": { + "id": "fmt", + "versionRange": "=11.0.2", + "additionalData": { + "headersOnly": true, + "branchName": "version/v11_0_2", + "compileOptions": { + "systemIncludes": [ + "fmt/include/" + ], + "cppFlags": [ + "-DFMT_HEADER_ONLY" + ] + } + } + }, + "version": "11.0.2" + }, + { + "dependency": { + "id": "scotland2", + "versionRange": "=0.1.6", + "additionalData": { + "soLink": "https://github.com/sc2ad/scotland2/releases/download/v0.1.6/libsl2.so", + "debugSoLink": "https://github.com/sc2ad/scotland2/releases/download/v0.1.6/debug_libsl2.so", + "overrideSoName": "libsl2.so", + "branchName": "version/v0_1_6" + } + }, + "version": "0.1.6" + }, + { + "dependency": { + "id": "libil2cpp", + "versionRange": "=0.4.0", + "additionalData": { + "headersOnly": true, + "compileOptions": { + "systemIncludes": [ + "il2cpp/external/baselib/Include", + "il2cpp/external/baselib/Platforms/Android/Include" + ] + } + } + }, + "version": "0.4.0" + }, + { + "dependency": { + "id": "custom-types", + "versionRange": "=0.18.4", + "additionalData": { + "soLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.4/libcustom-types.so", + "debugSoLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.4/debug_libcustom-types.so", + "overrideSoName": "libcustom-types.so", + "modLink": "https://github.com/QuestPackageManager/Il2CppQuestTypePatching/releases/download/v0.18.4/CustomTypes.qmod", + "branchName": "version/v0_18_4", + "compileOptions": { + "cppFlags": [ + "-Wno-invalid-offsetof" + ] + }, + "cmake": true + } + }, + "version": "0.18.4" + }, + { + "dependency": { + "id": "rapidjson-macros", + "versionRange": "=2.1.0", + "additionalData": { + "headersOnly": true, + "branchName": "version/v2_1_0", + "cmake": false + } + }, + "version": "2.1.0" + }, + { + "dependency": { + "id": "paper2_scotland2", + "versionRange": "=4.7.0", + "additionalData": { + "soLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.7.0/libpaper2_scotland2.so", + "overrideSoName": "libpaper2_scotland2.so", + "modLink": "https://github.com/Fernthedev/paperlog/releases/download/v4.7.0/paper2_scotland2.qmod", + "branchName": "version/v4_7_0", + "compileOptions": { + "systemIncludes": [ + "shared/utfcpp/source" + ] + }, + "cmake": false + } + }, + "version": "4.7.0" + }, + { + "dependency": { + "id": "config-utils", + "versionRange": "=2.0.3", + "additionalData": { + "headersOnly": true, + "soLink": "https://github.com/darknight1050/config-utils/releases/download/v2.0.3/libconfig-utils_test.so", + "overrideSoName": "libconfig-utils_test.so", + "branchName": "version/v2_0_3", + "cmake": true + } + }, + "version": "2.0.3" + }, + { + "dependency": { + "id": "libcurl", + "versionRange": "=8.5.0", + "additionalData": { + "staticLinking": true, + "soLink": "https://github.com/darknight1050/openssl-curl-android/releases/download/v8.5.0/libcurl.a", + "overrideSoName": "libcurl.a", + "branchName": "version-v8.5.0" + } + }, + "version": "8.5.0" + }, + { + "dependency": { + "id": "beatsaber-hook", + "versionRange": "=6.4.2", + "additionalData": { + "soLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/libbeatsaber-hook.so", + "debugSoLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/debug_libbeatsaber-hook.so", + "overrideSoName": "libbeatsaber-hook.so", + "modLink": "https://github.com/QuestPackageManager/beatsaber-hook/releases/download/v6.4.2/beatsaber-hook.qmod", + "branchName": "version/v6_4_2", + "compileOptions": { + "cppFlags": [ + "-Wno-extra-qualification" + ] + }, + "cmake": true + } + }, + "version": "6.4.2" + }, + { + "dependency": { + "id": "bsml", + "versionRange": "=0.4.55", + "additionalData": { + "soLink": "https://github.com/bsq-ports/Quest-BSML/releases/download/v0.4.55/libbsml.so", + "debugSoLink": "https://github.com/bsq-ports/Quest-BSML/releases/download/v0.4.55/debug_libbsml.so", + "overrideSoName": "libbsml.so", + "modLink": "https://github.com/bsq-ports/Quest-BSML/releases/download/v0.4.55/BSML.qmod", + "branchName": "version/v0_4_55", + "cmake": true + } + }, + "version": "0.4.55" + } + ] +} \ No newline at end of file