From 070d77c64478bbddaeeafe8c15f1c7e87ca51751 Mon Sep 17 00:00:00 2001 From: rcelyte Date: Fri, 28 Apr 2023 22:06:47 +0000 Subject: [PATCH] =?UTF-8?q?Clean=20up=20reordering=20logic=20no=20longer?= =?UTF-8?q?=20reallocates=20BPM=20data=206=20times=20=F0=9F=91=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- makefile | 4 +- qpm.json | 2 +- src/conversions.hpp | 272 +++++++++++++++++++++++--------------------- src/main.cpp | 21 ++-- 4 files changed, 159 insertions(+), 140 deletions(-) diff --git a/makefile b/makefile index 016f7f4..cfad64f 100644 --- a/makefile +++ b/makefile @@ -36,7 +36,7 @@ $(OBJDIR)/%.cpp.o: %.cpp extern makefile | ndk \"name\": \"Mapping Extensions\",\n\ \"id\": \"MappingExtensions\",\n\ \"author\": \"StackDoubleFlow, rxzz0, rcelyte\",\n\ - \"version\": \"0.22.3\",\n\ + \"version\": \"0.22.4\",\n\ \"packageId\": \"com.beatgames.beatsaber\",\n\ \"packageVersion\": \"1.28.0_4124311467\",\n\ \"description\": \"This adds a host of new things you can do with your maps as a mapper, and allows you to play said maps as a player. An update of the port of the PC original mod by Kyle 1413. Previously maintained by zoller27osu.\",\n\ @@ -47,7 +47,7 @@ $(OBJDIR)/%.cpp.o: %.cpp extern makefile | ndk \"id\": \"codegen\",\n\ \"downloadIfMissing\": \"https://github.com/sc2ad/BeatSaber-Quest-Codegen/releases/download/v0.33.0/Codegen.qmod\"\n\ }, {\n\ - \"version\": \"1.8.9\",\n\ + \"version\": \"^1.8.9\",\n\ \"id\": \"pinkcore\",\n\ \"downloadIfMissing\": \"https://github.com/BSMGPink/PinkCore/releases/download/v1.8.9/PinkCore.qmod\"\n\ }\n\ diff --git a/qpm.json b/qpm.json index 140fdea..0f8e271 100644 --- a/qpm.json +++ b/qpm.json @@ -4,7 +4,7 @@ "info": { "name": "MappingExtensions", "id": "MappingExtensions", - "version": "0.22.3", + "version": "0.22.4", "url": null, "additionalData": {} }, diff --git a/src/conversions.hpp b/src/conversions.hpp index 58213c8..0f7d9ca 100644 --- a/src/conversions.hpp +++ b/src/conversions.hpp @@ -1,27 +1,30 @@ #pragma once #include -template struct Linematch; +struct BpmChangeData { + float time, beat, bpm; +}; -struct BpmState { - struct BpmChangeData { - float time, beat, bpm; - }; +static inline std::vector ConvertBpmChanges(float startBpm, System::Collections::Generic::List_1 *events) { + const uint32_t count = events->get_Count(); + bool skipFirst = (count > 0 && events->get_Item(0)->get_beat() == 0); std::vector changes; - uint32_t current = 0; - BpmState(float startBpm, System::Collections::Generic::List_1 *events) { - const uint32_t count = events->get_Count(); - bool skipFirst = (count > 0 && events->get_Item(0)->get_beat() == 0); - changes.reserve(count + !skipFirst); - BpmChangeData lastEntry = {0, 0, skipFirst ? events->get_Item(0)->get_bpm() : startBpm}; + changes.reserve(count + !skipFirst); + BpmChangeData lastEntry = {0, 0, skipFirst ? events->get_Item(0)->get_bpm() : startBpm}; + changes.push_back(lastEntry); + for(uint32_t i = skipFirst; i < count; i++) { + BeatmapSaveDataVersion3::BeatmapSaveData::BpmChangeEventData *event = events->get_Item(i); + const float beat = event->get_beat(); + lastEntry = {lastEntry.time + (beat - lastEntry.beat) / lastEntry.bpm * 60, beat, event->get_bpm()}; changes.push_back(lastEntry); - for(uint32_t i = skipFirst; i < count; i++) { - BeatmapSaveDataVersion3::BeatmapSaveData::BpmChangeEventData *event = events->get_Item(i); - const float beat = event->get_beat(); - lastEntry = {lastEntry.time + (beat - lastEntry.beat) / lastEntry.bpm * 60, beat, event->get_bpm()}; - changes.push_back(lastEntry); - } } + return changes; +} + +struct BpmState { + std::basic_string_view changes; + uint32_t current = 0; + BpmState(std::basic_string_view changes) : changes(changes) {} float GetTime(float beat) { while(current > 0 && changes[current].beat >= beat) --current; @@ -39,56 +42,70 @@ static inline GlobalNamespace::ColorType ConvertColorType(BeatmapSaveDataVersion } } -template<> struct Linematch { - float time; - int32_t lineIndex; - GlobalNamespace::ColorType colorType; - GlobalNamespace::NoteCutDirection cutDirection; - float cutDirectionAngleOffset; - Linematch(GlobalNamespace::NoteData *from) : - time(from->get_time()), - lineIndex(from->get_lineIndex()), - colorType(from->get_colorType()), - cutDirection(from->get_cutDirection()), - cutDirectionAngleOffset(from->get_cutDirectionAngleOffset()) {} - Linematch(BeatmapSaveDataVersion3::BeatmapSaveData::ColorNoteData *from, BpmState *bpmState) : - time(bpmState->GetTime(from->get_beat())), - lineIndex(from->get_line()), - colorType(ConvertColorType(from->get_color())), - cutDirection(from->get_cutDirection()), - cutDirectionAngleOffset(from->get_angleOffset()) {} +template struct RestoreBlob; + +template<> struct RestoreBlob { + struct Ident { + float time; + int32_t lineIndex; + GlobalNamespace::ColorType colorType; + GlobalNamespace::NoteCutDirection cutDirection; + float cutDirectionAngleOffset; + Ident(GlobalNamespace::NoteData *from) : + time(from->get_time()), + lineIndex(from->get_lineIndex()), + colorType(from->get_colorType()), + cutDirection(from->get_cutDirection()), + cutDirectionAngleOffset(from->get_cutDirectionAngleOffset()) {} + Ident(BeatmapSaveDataVersion3::BeatmapSaveData::ColorNoteData *from, BpmState *bpmState) : + time(bpmState->GetTime(from->get_beat())), + lineIndex(from->get_line()), + colorType(ConvertColorType(from->get_color())), + cutDirection(from->get_cutDirection()), + cutDirectionAngleOffset(from->get_angleOffset()) {} + } ident; + int32_t layer; + RestoreBlob(BeatmapSaveDataVersion3::BeatmapSaveData::ColorNoteData *from, BpmState *bpmState) : ident(from, bpmState), layer(from->get_layer()) {} }; -template<> struct Linematch { - float time; - int32_t lineIndex; - Linematch(GlobalNamespace::NoteData *from) : - time(from->get_time()), - lineIndex(from->get_lineIndex()) {} - Linematch(BeatmapSaveDataVersion3::BeatmapSaveData::BombNoteData *from, BpmState *bpmState) : - time(bpmState->GetTime(from->get_beat())), - lineIndex(from->get_line()) {} +template<> struct RestoreBlob { + struct Ident { + float time; + int32_t lineIndex; + Ident(GlobalNamespace::NoteData *from) : + time(from->get_time()), + lineIndex(from->get_lineIndex()) {} + Ident(BeatmapSaveDataVersion3::BeatmapSaveData::BombNoteData *from, BpmState *bpmState) : + time(bpmState->GetTime(from->get_beat())), + lineIndex(from->get_line()) {} + } ident; + int32_t layer; + RestoreBlob(BeatmapSaveDataVersion3::BeatmapSaveData::BombNoteData *from, BpmState *bpmState) : ident(from, bpmState), layer(from->get_layer()) {} }; -template<> struct Linematch { - float time; - int32_t lineIndex; - float duration; - int32_t width; - int32_t height; - Linematch(GlobalNamespace::ObstacleData *from) : - time(from->get_time()), - lineIndex(from->get_lineIndex()), - duration(from->get_duration()), - width(from->get_width()), - height(from->get_height()) {} - Linematch(BeatmapSaveDataVersion3::BeatmapSaveData::ObstacleData *from, BpmState *bpmState) : - time(bpmState->GetTime(from->get_beat())), - lineIndex(from->get_line()), - duration(bpmState->GetTime(from->get_beat() + from->get_duration()) - time), - width(from->get_width()), - height(from->get_height()) {} +template<> struct RestoreBlob { + struct Ident { + float time; + int32_t lineIndex; + float duration; + int32_t width; + int32_t height; + Ident(GlobalNamespace::ObstacleData *from) : + time(from->get_time()), + lineIndex(from->get_lineIndex()), + duration(from->get_duration()), + width(from->get_width()), + height(from->get_height()) {} + Ident(BeatmapSaveDataVersion3::BeatmapSaveData::ObstacleData *from, BpmState *bpmState) : + time(bpmState->GetTime(from->get_beat())), + lineIndex(from->get_line()), + duration(bpmState->GetTime(from->get_beat() + from->get_duration()) - time), + width(from->get_width()), + height(from->get_height()) {} + } ident; + int32_t layer; + RestoreBlob(BeatmapSaveDataVersion3::BeatmapSaveData::ObstacleData *from, BpmState *bpmState) : ident(from, bpmState), layer(from->get_layer()) {} }; struct SliderLinematch { @@ -114,87 +131,88 @@ struct SliderLinematch { tailLineIndex(from->get_tailLine()) {} }; -template<> struct Linematch { - SliderLinematch base; - GlobalNamespace::NoteCutDirection tailCutDirection; - GlobalNamespace::SliderMidAnchorMode midAnchorMode; - float headControlPointLengthMultiplier; - float tailControlPointLengthMultiplier; - Linematch(GlobalNamespace::SliderData *from) : - base(from), - tailCutDirection(from->get_tailCutDirection()), - midAnchorMode(from->get_midAnchorMode()), - headControlPointLengthMultiplier(from->get_headControlPointLengthMultiplier()), - tailControlPointLengthMultiplier(from->get_tailControlPointLengthMultiplier()) {} - Linematch(BeatmapSaveDataVersion3::BeatmapSaveData::SliderData *from, BpmState *bpmState) : - base(from, bpmState), - tailCutDirection(from->get_tailCutDirection()), - midAnchorMode(from->get_sliderMidAnchorMode()), - headControlPointLengthMultiplier(from->get_headControlPointLengthMultiplier()), - tailControlPointLengthMultiplier(from->get_tailControlPointLengthMultiplier()) {} +template<> struct RestoreBlob { + struct Ident { + SliderLinematch base; + GlobalNamespace::NoteCutDirection tailCutDirection; + GlobalNamespace::SliderMidAnchorMode midAnchorMode; + float headControlPointLengthMultiplier; + float tailControlPointLengthMultiplier; + Ident(GlobalNamespace::SliderData *from) : + base(from), + tailCutDirection(from->get_tailCutDirection()), + midAnchorMode(from->get_midAnchorMode()), + headControlPointLengthMultiplier(from->get_headControlPointLengthMultiplier()), + tailControlPointLengthMultiplier(from->get_tailControlPointLengthMultiplier()) {} + Ident(BeatmapSaveDataVersion3::BeatmapSaveData::SliderData *from, BpmState *bpmState) : + base(from, bpmState), + tailCutDirection(from->get_tailCutDirection()), + midAnchorMode(from->get_sliderMidAnchorMode()), + headControlPointLengthMultiplier(from->get_headControlPointLengthMultiplier()), + tailControlPointLengthMultiplier(from->get_tailControlPointLengthMultiplier()) {} + } ident; + std::array layer; + RestoreBlob(BeatmapSaveDataVersion3::BeatmapSaveData::SliderData *from, BpmState *bpmState) : ident(from, bpmState), layer({from->get_headLayer(), from->get_tailLayer()}) {} }; -template<> struct Linematch { - SliderLinematch base; - int32_t sliceCount; - float squishAmount; - Linematch(GlobalNamespace::SliderData *from) : - base(from), - sliceCount(from->get_sliceCount()), - squishAmount(from->get_squishAmount()) {} - Linematch(BeatmapSaveDataVersion3::BeatmapSaveData::BurstSliderData *from, BpmState *bpmState) : - base(from, bpmState), - sliceCount(from->get_sliceCount()), - squishAmount(from->get_squishAmount()) {} +template<> struct RestoreBlob { + struct Ident { + SliderLinematch base; + int32_t sliceCount; + float squishAmount; + Ident(GlobalNamespace::SliderData *from) : + base(from), + sliceCount(from->get_sliceCount()), + squishAmount(from->get_squishAmount()) {} + Ident(BeatmapSaveDataVersion3::BeatmapSaveData::BurstSliderData *from, BpmState *bpmState) : + base(from, bpmState), + sliceCount(from->get_sliceCount()), + squishAmount(from->get_squishAmount()) {} + } ident; + std::array layer; + RestoreBlob(BeatmapSaveDataVersion3::BeatmapSaveData::BurstSliderData *from, BpmState *bpmState) : ident(from, bpmState), layer({from->get_headLayer(), from->get_tailLayer()}) {} }; -template<> struct Linematch { - float time; - int32_t lineIndex; - GlobalNamespace::OffsetDirection offsetDirection; - Linematch(GlobalNamespace::WaypointData *from) : - time(from->get_time()), - lineIndex(from->get_lineIndex()), - offsetDirection(from->get_offsetDirection()) {} - Linematch(BeatmapSaveDataVersion3::BeatmapSaveData::WaypointData *from, BpmState *bpmState) : - time(bpmState->GetTime(from->get_beat())), - lineIndex(from->get_line()), - offsetDirection(from->get_offsetDirection()) {} +template<> struct RestoreBlob { + struct Ident { + float time; + int32_t lineIndex; + GlobalNamespace::OffsetDirection offsetDirection; + Ident(GlobalNamespace::WaypointData *from) : + time(from->get_time()), + lineIndex(from->get_lineIndex()), + offsetDirection(from->get_offsetDirection()) {} + Ident(BeatmapSaveDataVersion3::BeatmapSaveData::WaypointData *from, BpmState *bpmState) : + time(bpmState->GetTime(from->get_beat())), + lineIndex(from->get_line()), + offsetDirection(from->get_offsetDirection()) {} + } ident; + int32_t layer; + RestoreBlob(BeatmapSaveDataVersion3::BeatmapSaveData::WaypointData *from, BpmState *bpmState) : ident(from, bpmState), layer(from->get_layer()) {} }; -std::array GetLineLayers(BeatmapSaveDataVersion3::BeatmapSaveData::BombNoteData *saveData) {return {saveData->get_layer()};} -std::array GetLineLayers(BeatmapSaveDataVersion3::BeatmapSaveData::ColorNoteData *saveData) {return {saveData->get_layer()};} -std::array GetLineLayers(BeatmapSaveDataVersion3::BeatmapSaveData::ObstacleData *saveData) {return {saveData->get_layer()};} -std::array GetLineLayers(BeatmapSaveDataVersion3::BeatmapSaveData::WaypointData *saveData) {return {saveData->get_layer()};} -std::array GetLineLayers(BeatmapSaveDataVersion3::BeatmapSaveData::BaseSliderData *saveData) {return {saveData->get_headLayer(), saveData->get_tailLayer()};} - -template +template struct LayerCache { - struct Entry { - Linematch match; - std::array layers; - }; - std::vector cache; + std::vector> cache; std::vector matched; size_t head = 0, failCount = 0; - LayerCache(System::Collections::Generic::List_1 *list, float startBpm, System::Collections::Generic::List_1 *bpmEvents) : matched(list->get_Count()) { - BpmState bpmState(startBpm, bpmEvents); + LayerCache(System::Collections::Generic::List_1 *list, const std::vector *changes) : matched(list->get_Count()) { + BpmState bpmState(std::basic_string_view(&(*changes)[0], changes->size())); cache.reserve(matched.size()); - for(size_t i = 0; i < matched.size(); ++i) { - SaveData *entry = list->get_Item(i); - cache.push_back({Linematch(entry, &bpmState), GetLineLayers(entry)}); - } + for(size_t i = 0; i < matched.size(); ++i) + cache.emplace_back(list->get_Item(i), &bpmState); } - template std::array restore(BeatmapData *data) { - const Linematch match(data); - std::array res = {}; + using LayerType = decltype(RestoreBlob::layer); + template LayerType restore(BeatmapData *data) { + const typename RestoreBlob::Ident match(data); + LayerType res = {}; size_t i = head; for(; i < cache.size(); ++i) { if(matched[i]) continue; - if(memcmp(&match, &cache[i].match, sizeof(match))) + if(memcmp(&match, &cache[i].ident, sizeof(match))) continue; - res = cache[i].layers; + res = cache[i].layer; matched[i] = true; break; } diff --git a/src/main.cpp b/src/main.cpp index 5fa981d..87c657c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -146,27 +146,28 @@ MAKE_HOOK_MATCH(GameplayCoreSceneSetupData_GetTransformedBeatmapDataAsync, &Glob MAKE_HOOK_MATCH(BeatmapDataLoader_GetBeatmapDataFromBeatmapSaveData, &GlobalNamespace::BeatmapDataLoader::GetBeatmapDataFromBeatmapSaveData, GlobalNamespace::BeatmapData*, ::BeatmapSaveDataVersion3::BeatmapSaveData* beatmapSaveData, ::GlobalNamespace::BeatmapDifficulty beatmapDifficulty, float startBpm, bool loadingForDesignatedEnvironment, ::GlobalNamespace::EnvironmentKeywords* environmentKeywords, ::GlobalNamespace::EnvironmentLightGroups* environmentLightGroups, ::GlobalNamespace::DefaultEnvironmentEvents* defaultEnvironmentEvents, ::GlobalNamespace::PlayerSpecificSettings* playerSpecificSettings) { if(!active) return BeatmapDataLoader_GetBeatmapDataFromBeatmapSaveData(beatmapSaveData, beatmapDifficulty, startBpm, loadingForDesignatedEnvironment, environmentKeywords, environmentLightGroups, defaultEnvironmentEvents, playerSpecificSettings); - LayerCache bombCache(beatmapSaveData->bombNotes, startBpm, beatmapSaveData->bpmEvents); - LayerCache noteCache(beatmapSaveData->colorNotes, startBpm, beatmapSaveData->bpmEvents); - LayerCache obstacleCache(beatmapSaveData->obstacles, startBpm, beatmapSaveData->bpmEvents); - LayerCache burstCache(beatmapSaveData->burstSliders, startBpm, beatmapSaveData->bpmEvents); - LayerCache sliderCache(beatmapSaveData->sliders, startBpm, beatmapSaveData->bpmEvents); - LayerCache waypointCache(beatmapSaveData->waypoints, startBpm, beatmapSaveData->bpmEvents); + const std::vector bpmChanges = ConvertBpmChanges(startBpm, beatmapSaveData->bpmEvents); + LayerCache bombCache(beatmapSaveData->bombNotes, &bpmChanges); + LayerCache noteCache(beatmapSaveData->colorNotes, &bpmChanges); + LayerCache obstacleCache(beatmapSaveData->obstacles, &bpmChanges); + LayerCache burstCache(beatmapSaveData->burstSliders, &bpmChanges); + LayerCache sliderCache(beatmapSaveData->sliders, &bpmChanges); + LayerCache waypointCache(beatmapSaveData->waypoints, &bpmChanges); logger->info("Restoring %zu notes, %zu bombs, %zu obstacles, %zu sliders, %zu burst sliders, and %zu waypoints", noteCache.cache.size(), bombCache.cache.size(), obstacleCache.cache.size(), sliderCache.cache.size(), burstCache.cache.size(), waypointCache.cache.size()); GlobalNamespace::BeatmapData *result = BeatmapDataLoader_GetBeatmapDataFromBeatmapSaveData(beatmapSaveData, beatmapDifficulty, startBpm, loadingForDesignatedEnvironment, environmentKeywords, environmentLightGroups, defaultEnvironmentEvents, playerSpecificSettings); for(System::Collections::Generic::LinkedListNode_1 *iter = result->get_allBeatmapDataItems()->head, *end = iter ? iter->prev : NULL; iter; iter = iter->next) { GlobalNamespace::BeatmapDataItem *item = iter->item; if(GlobalNamespace::NoteData *data = il2cpp_utils::try_cast(item).value_or(nullptr); data) { - data->noteLineLayer = (data->gameplayType == GlobalNamespace::NoteData::GameplayType::Bomb) ? bombCache.restore(data)[0] : noteCache.restore(data)[0]; + data->noteLineLayer = (data->gameplayType == GlobalNamespace::NoteData::GameplayType::Bomb) ? bombCache.restore(data) : noteCache.restore(data); } else if(GlobalNamespace::ObstacleData *data = il2cpp_utils::try_cast(item).value_or(nullptr); data) { - data->lineLayer = obstacleCache.restore(data)[0]; + data->lineLayer = obstacleCache.restore(data); } else if(GlobalNamespace::SliderData *data = il2cpp_utils::try_cast(item).value_or(nullptr); data) { std::array layers = (data->sliderType == GlobalNamespace::SliderData::Type::Burst) ? burstCache.restore(data) : sliderCache.restore(data); data->headBeforeJumpLineLayer = data->headLineLayer = layers[0]; data->tailBeforeJumpLineLayer = data->tailLineLayer = layers[1]; } else if(GlobalNamespace::WaypointData *data = il2cpp_utils::try_cast(item).value_or(nullptr); data) { - data->lineLayer = waypointCache.restore(data)[0]; + data->lineLayer = waypointCache.restore(data); } if(iter == end) break; @@ -513,7 +514,7 @@ MAKE_HOOK_MATCH(StaticBeatmapObjectSpawnMovementData_LineYPosForLineLayer, &Glob extern "C" DL_EXPORT void setup(ModInfo& info) { info.id = "MappingExtensions"; - info.version = "0.22.3"; + info.version = "0.22.4"; modInfo = info; logger = new Logger(modInfo, LoggerOptions(false, true)); logger->info("Leaving setup!");