From 2309f87348f8ae1a4c45d2cf0afb801a5471a44e Mon Sep 17 00:00:00 2001 From: Fernthedev <15272073+Fernthedev@users.noreply.github.com> Date: Sun, 1 Feb 2026 11:19:00 -0400 Subject: [PATCH 1/9] Move to using associated data for tracking custom data --- include/Chroma.hpp | 1 + include/ChromaEvents.hpp | 25 ++++++--- include/ChromaObjectData.hpp | 28 +++++++--- include/lighting/ChromaEventData.hpp | 21 +++++--- src/ChromaEvents.cpp | 52 ++++++++----------- src/ChromaObjectData.cpp | 18 +++++-- src/api/BombAPI.cpp | 6 +-- src/api/NoteAPI.cpp | 8 +-- src/hooks/BeatEffectSpawner.cpp | 6 +-- .../Events/LightPairRotationEventEffect.cpp | 13 ++--- src/hooks/Events/LightRotationEventEffect.cpp | 11 ++-- ...rackLaneRingsPositionStepEffectSpawner.cpp | 18 +++---- .../TrackLaneRingsRotationEffectSpawner.cpp | 38 ++++++-------- src/hooks/colorizer/BombNoteController.cpp | 6 +-- src/hooks/colorizer/BurstSliderController.cpp | 6 +-- src/hooks/colorizer/ColorNoteVisuals.cpp | 6 +-- .../colorizer/Note/NoteCutEffectSpawner.cpp | 6 +-- src/hooks/colorizer/NoteController.cpp | 14 ++--- src/hooks/colorizer/ObstacleController.cpp | 15 +++--- src/hooks/colorizer/SliderController.cpp | 14 ++--- src/lighting/ChromaEventData.cpp | 19 +++---- src/lighting/ChromaGradientController.cpp | 3 +- src/lighting/ChromaLightSwitchEventEffect.cpp | 18 ++++--- 23 files changed, 190 insertions(+), 162 deletions(-) diff --git a/include/Chroma.hpp b/include/Chroma.hpp index 63cbaa2e..1aa77ebf 100644 --- a/include/Chroma.hpp +++ b/include/Chroma.hpp @@ -76,6 +76,7 @@ inline static constexpr const std::string_view STEP = "step"; inline static constexpr const std::string_view RING_ROTATION = "rotation"; inline static constexpr const std::string_view ENVIRONMENT = "environment"; + inline static constexpr const std::string_view GAMEOBJECT_ID = "id"; inline static constexpr const std::string_view GEOMETRY = "geometry"; inline static constexpr const std::string_view MATERIAL = "material"; diff --git a/include/ChromaEvents.hpp b/include/ChromaEvents.hpp index 695721d9..2a3075f0 100644 --- a/include/ChromaEvents.hpp +++ b/include/ChromaEvents.hpp @@ -28,7 +28,9 @@ struct AnimateComponentEventData { }; AnimateComponentEventData(AnimateComponentEventData&&) = default; - AnimateComponentEventData(AnimateComponentEventData const&) = delete; + + [[deprecated("Copy invoked")]] + AnimateComponentEventData(AnimateComponentEventData const&) = default; ~AnimateComponentEventData() = default; AnimateComponentEventData() = default; AnimateComponentEventData(float duration, Functions easing, TracksAD::TracksVector track, @@ -48,18 +50,27 @@ struct CustomEventAssociatedData { bool parsed = false; CustomEventAssociatedData() : data(nullptr) {}; -}; -static std::unordered_map eventDataMap; + AssignBloomFogTrack* getAssignBloomFogTrack() { + return std::get_if(&data); + } + + AnimateComponentEventData* getAnimateComponentEventData() { + return std::get_if(&data); + } +}; -static CustomEventAssociatedData& getEventAD(CustomJSONData::CustomEventData const* customData) { - return eventDataMap[customData]; +static CustomEventAssociatedData& getEventAD(CustomJSONData::CustomEventData const* customEvent) { + auto& ad = customEvent->customData->associatedData['C']; + if (!ad.has_value()) { + ad = std::make_any(); + } + return std::any_cast(ad); } void deserialize(CustomJSONData::CustomBeatmapData* readOnlyBeatmap); -void parseEventData(TracksAD::BeatmapAssociatedData& beatmapAD, CustomJSONData::CustomEventData const* customEventData, - bool v2); +void parseEventData(TracksAD::BeatmapAssociatedData& beatmapAD, CustomJSONData::CustomEventData const* customEventData, bool v2); void AddEventCallbacks(); } // namespace ChromaEvents diff --git a/include/ChromaObjectData.hpp b/include/ChromaObjectData.hpp index 686fb87c..c46f3af2 100644 --- a/include/ChromaObjectData.hpp +++ b/include/ChromaObjectData.hpp @@ -11,6 +11,9 @@ class BeatmapObjectData; namespace CustomJSONData { class CustomBeatmapData; +class CustomNoteData; +class CustomObstacleData; +class CustomSliderData; } // Third-party includes @@ -18,14 +21,11 @@ class CustomBeatmapData; #include "tracks/shared/Animation/PointDefinition.h" #include "sombrero/shared/ColorUtils.hpp" +#include "custom-json-data/shared/JSONWrapper.h" + namespace Chroma { class ChromaObjectData { -private: - ChromaObjectData(ChromaObjectData const&) = default; - friend class std::unordered_map; - friend class std::pair; - public: std::optional Color; std::span Tracks; // probably a bad idea, this could be freed. @@ -37,14 +37,26 @@ class ChromaObjectData { ChromaObjectData() = default; ChromaObjectData(ChromaObjectData&&) = default; + + [[deprecated("Copy invoked")]] + ChromaObjectData(ChromaObjectData const&) = default; + + ChromaObjectData& operator=(ChromaObjectData&&) noexcept = default; + ChromaObjectData& operator=(ChromaObjectData const&) = default; }; class ChromaObjectDataManager { public: - using ChromaObjectDataType = std::unordered_map; - inline static ChromaObjectDataType ChromaObjectDatas; - static void deserialize(CustomJSONData::CustomBeatmapData* beatmapData); }; +static ChromaObjectData& getObjectAD(CustomJSONData::JSONWrapper* customData) { + auto& ad = customData->associatedData['C']; + if (!ad.has_value()) ad = std::make_any(); + return std::any_cast(ad); +} + +// defined in ChromaObjectData.cpp to avoid include bloat +ChromaObjectData* getObjectAD(GlobalNamespace::BeatmapObjectData* obj); + } // namespace Chroma \ No newline at end of file diff --git a/include/lighting/ChromaEventData.hpp b/include/lighting/ChromaEventData.hpp index 0ff3718c..8c438192 100644 --- a/include/lighting/ChromaEventData.hpp +++ b/include/lighting/ChromaEventData.hpp @@ -18,14 +18,16 @@ class BeatmapObjectSpawnController; namespace Chroma { class ChromaEventData { -private: - ChromaEventData(ChromaEventData const&) = default; - friend class std::unordered_map; - friend class std::pair; - public: ChromaEventData() = default; + [[deprecated("Copy invoked")]] + ChromaEventData(ChromaEventData const&) = default; + ChromaEventData(ChromaEventData&&) = default; + + ChromaEventData& operator=(ChromaEventData&&) noexcept = default; + ChromaEventData& operator=(ChromaEventData const&) = default; + std::optional Easing; std::optional LerpType; @@ -81,10 +83,13 @@ class ChromaEventData { class ChromaEventDataManager { public: - using EventMapType = std::unordered_map; - inline static EventMapType ChromaEventDatas; - static void deserialize(CustomJSONData::CustomBeatmapData* beatmapData); }; +static ChromaEventData& getLightAD(CustomJSONData::JSONWrapper* customData) { + auto& ad = customData->associatedData['C']; + if (!ad.has_value()) ad = std::make_any(); + return std::any_cast(ad); +} + } // namespace Chroma \ No newline at end of file diff --git a/src/ChromaEvents.cpp b/src/ChromaEvents.cpp index c5d3b777..45fe4c40 100644 --- a/src/ChromaEvents.cpp +++ b/src/ChromaEvents.cpp @@ -1,37 +1,32 @@ #include #include - #include "ChromaEvents.hpp" #include "Chroma.hpp" #include "ChromaLogger.hpp" #include "lighting/ChromaFogController.hpp" #include "ChromaComponentManager.hpp" - #include "GlobalNamespace/BeatmapData.hpp" #include "GlobalNamespace/BeatmapCallbacksController.hpp" - #include "custom-json-data/shared/CustomBeatmapData.h" #include "custom-json-data/shared/CustomEventData.h" #include "tracks/shared/TimeSourceHelper.h" #include "tracks/shared/Vector.h" #include "tracks/shared/Json.h" - - using namespace GlobalNamespace; using namespace NEVector; -void ChromaEvents::parseEventData(TracksAD::BeatmapAssociatedData& beatmapAD, - CustomJSONData::CustomEventData const* customEventData, bool v2) { +void ChromaEvents::parseEventData(TracksAD::BeatmapAssociatedData& beatmapAD, CustomJSONData::CustomEventData const* customEventData, + bool v2) { bool isType = false; auto typeHash = customEventData->typeHash; -#define TYPE_GET(jsonName, varName) \ - static auto jsonNameHash_##varName = std::hash()(jsonName); \ +#define TYPE_GET(jsonName, varName) \ + static auto jsonNameHash_##varName = std::hash()(jsonName); \ if (!isType && typeHash == (jsonNameHash_##varName)) isType = true; TYPE_GET(Chroma::OldConstants::ASSIGNFOGTRACK, ASSIGNFOGTRACK) @@ -41,21 +36,22 @@ void ChromaEvents::parseEventData(TracksAD::BeatmapAssociatedData& beatmapAD, return; } - rapidjson::Value const& eventData = *customEventData->data; auto& eventAD = getEventAD(customEventData); - + eventAD.parsed = true; if (eventAD.parsed) { return; } + if (!customEventData->customData->value) { + return; + } - eventAD.parsed = true; + rapidjson::Value const& eventData = *customEventData->customData->value; if (typeHash == jsonNameHash_ASSIGNFOGTRACK) { auto trackIt = eventData.FindMember((v2 ? Chroma::NewConstants::V2_TRACK : Chroma::NewConstants::TRACK).data()); if (trackIt == eventData.MemberEnd() || trackIt->value.IsNull() || !trackIt->value.IsString()) { - ChromaLogger::Logger.debug("Track data is missing for Chroma custom event {}", - customEventData->____time_k__BackingField); + ChromaLogger::Logger.debug("Track data is missing for Chroma custom event {}", customEventData->____time_k__BackingField); return; } @@ -69,20 +65,18 @@ void ChromaEvents::parseEventData(TracksAD::BeatmapAssociatedData& beatmapAD, auto trackIt = eventData.FindMember((v2 ? Chroma::NewConstants::V2_TRACK : Chroma::NewConstants::TRACK).data()); if (trackIt == eventData.MemberEnd() || trackIt->value.IsNull() || !trackIt->value.IsString()) { - ChromaLogger::Logger.debug("Track data is missing for Chroma custom event {}", - customEventData->____time_k__BackingField); + ChromaLogger::Logger.debug("Track data is missing for Chroma custom event {}", customEventData->____time_k__BackingField); return; } float const duration = NEJSON::ReadOptionalFloat(eventData, Chroma::NewConstants::DURATION.data()).value_or(0); - auto easing = static_cast(NEJSON::ReadOptionalInt(eventData, Chroma::NewConstants::EASING.data()) - .value_or(static_cast(Functions::EaseLinear))); + auto easing = static_cast( + NEJSON::ReadOptionalInt(eventData, Chroma::NewConstants::EASING.data()).value_or(static_cast(Functions::EaseLinear))); auto tracks = NEJSON::ReadOptionalTracks(eventData, Chroma::NewConstants::TRACK, beatmapAD).value(); - auto const availableNames = { Chroma::NewConstants::BLOOM_FOG_ENVIRONMENT, - Chroma::NewConstants::TUBE_BLOOM_PRE_PASS_LIGHT }; + auto const availableNames = { Chroma::NewConstants::BLOOM_FOG_ENVIRONMENT, Chroma::NewConstants::TUBE_BLOOM_PRE_PASS_LIGHT }; std::unordered_map> coroutineInfos; // eventData -> { @@ -146,21 +140,19 @@ void ChromaEvents::deserialize(CustomJSONData::CustomBeatmapData* readOnlyBeatma } } -void CustomEventCallback(BeatmapCallbacksController* callbackController, - CustomJSONData::CustomEventData* customEventData) { +void CustomEventCallback(BeatmapCallbacksController* callbackController, CustomJSONData::CustomEventData* customEventData) { PAPER_IL2CPP_CATCH_HANDLER( bool isType = false; auto typeHash = customEventData->typeHash; -#define TYPE_GET(jsonName, varName) \ - static auto jsonNameHash_##varName = std::hash()(jsonName); \ +#define TYPE_GET(jsonName, varName) \ + static auto jsonNameHash_##varName = std::hash()(jsonName); \ if (!isType && typeHash == (jsonNameHash_##varName)) isType = true; - TYPE_GET(Chroma::OldConstants::ASSIGNFOGTRACK, ASSIGNFOGTRACK) - TYPE_GET(Chroma::NewConstants::ANIMATE_COMPONENT, ANIMATE_COMPONENT) + TYPE_GET(Chroma::OldConstants::ASSIGNFOGTRACK, ASSIGNFOGTRACK) TYPE_GET(Chroma::NewConstants::ANIMATE_COMPONENT, ANIMATE_COMPONENT) - if (!isType) { return; } + if (!isType) { return; } auto const& ad = ChromaEvents::getEventAD(customEventData); @@ -173,13 +165,11 @@ void CustomEventCallback(BeatmapCallbacksController* callbackController, } if (typeHash == jsonNameHash_ASSIGNFOGTRACK) { - Chroma::ChromaFogController::getInstance()->AssignTrack( - std::get(ad.data).track); + Chroma::ChromaFogController::getInstance()->AssignTrack(std::get(ad.data).track); CJDLogger::Logger.fmtLog("Assigned fog controller to track"); } if (typeHash == jsonNameHash_ANIMATE_COMPONENT && !customBeatmapData->v2orEarlier) { CJDLogger::Logger.fmtLog("Animated component"); - Chroma::Component::StartEvent(callbackController, customEventData, - std::get(ad.data)); + Chroma::Component::StartEvent(callbackController, customEventData, std::get(ad.data)); } ) diff --git a/src/ChromaObjectData.cpp b/src/ChromaObjectData.cpp index cb6dc69d..d85e24b3 100644 --- a/src/ChromaObjectData.cpp +++ b/src/ChromaObjectData.cpp @@ -24,8 +24,6 @@ using namespace ChromaUtils; using namespace GlobalNamespace; void Chroma::ChromaObjectDataManager::deserialize(CustomJSONData::CustomBeatmapData* beatmapData) { - ChromaObjectDatas.clear(); - auto* beatmapDataCast = beatmapData; bool v2 = beatmapDataCast->v2orEarlier; @@ -116,6 +114,20 @@ void Chroma::ChromaObjectDataManager::deserialize(CustomJSONData::CustomBeatmapD auto const& tracks = TracksAD::getAD(objectDynData).tracks; chromaObjectData.Tracks = tracks; - ChromaObjectDatas.try_emplace(beatmapObjectData, chromaObjectData); + getObjectAD(objectDynData) = std::move(chromaObjectData); } } + +Chroma::ChromaObjectData* Chroma::getObjectAD(GlobalNamespace::BeatmapObjectData* obj) { + if (auto note = il2cpp_utils::try_cast(obj)) { + return &getObjectAD(note.value()->customData); + } + if (auto obstacle = il2cpp_utils::try_cast(obj)) { + return &getObjectAD(obstacle.value()->customData); + } + if (auto slider = il2cpp_utils::try_cast(obj)) { + return &getObjectAD(slider.value()->customData); + } + + return nullptr; +} \ No newline at end of file diff --git a/src/api/BombAPI.cpp b/src/api/BombAPI.cpp index 19e08dec..3c2e3342 100644 --- a/src/api/BombAPI.cpp +++ b/src/api/BombAPI.cpp @@ -42,13 +42,13 @@ EXPOSE_API(getBombNoteControllerOverrideColorSafe, OptColor, BombNoteController* } EXPOSE_API(getBombNoteControllerColorSafe, OptColor, BombNoteController* BombNoteController) { - auto it = ChromaObjectDataManager::ChromaObjectDatas.find(BombNoteController->noteData); + auto ad = getObjectAD(BombNoteController->_noteData); - if (it == ChromaObjectDataManager::ChromaObjectDatas.end()) { + if (!ad) { return OptColorNull; } - auto color = it->second.Color; + auto color = ad->Color; if (!color) { return OptColorNull; diff --git a/src/api/NoteAPI.cpp b/src/api/NoteAPI.cpp index 16edc5e7..ee18e83a 100644 --- a/src/api/NoteAPI.cpp +++ b/src/api/NoteAPI.cpp @@ -1,3 +1,4 @@ +#include "ChromaObjectData.hpp" #include "main.hpp" #include "NoteAPI.hpp" #include "colorizer/NoteColorizer.hpp" @@ -34,13 +35,14 @@ EXPOSE_API(getNoteControllerOverrideColorSafe, OptColor, NoteController* noteCon } EXPOSE_API(getNoteControllerColorSafe, OptColor, NoteController* noteController) { - auto it = ChromaObjectDataManager::ChromaObjectDatas.find(noteController->noteData); - if (it == ChromaObjectDataManager::ChromaObjectDatas.end()) { + auto *ad = getObjectAD(noteController->_noteData); + + if (!ad) { return OptColorNull; } - auto const& color = it->second.Color; + auto const& color = ad->Color; if (!color) { return OptColorNull; diff --git a/src/hooks/BeatEffectSpawner.cpp b/src/hooks/BeatEffectSpawner.cpp index 60591344..7acabd2b 100644 --- a/src/hooks/BeatEffectSpawner.cpp +++ b/src/hooks/BeatEffectSpawner.cpp @@ -26,10 +26,10 @@ using namespace Chroma; using namespace GlobalNamespace; static bool BeatEffectHide(bool original, NoteController* noteController) { - auto it = ChromaObjectDataManager::ChromaObjectDatas.find(noteController->noteData); + auto it = getObjectAD(noteController->noteData); - if (it != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& chromaData = it->second; + if (it) { + auto const& chromaData = *it; std::optional force = chromaData.SpawnEffect; if (force.has_value()) { diff --git a/src/hooks/Events/LightPairRotationEventEffect.cpp b/src/hooks/Events/LightPairRotationEventEffect.cpp index 0819346a..b0b07bbc 100644 --- a/src/hooks/Events/LightPairRotationEventEffect.cpp +++ b/src/hooks/Events/LightPairRotationEventEffect.cpp @@ -53,18 +53,15 @@ MAKE_HOOK_MATCH(LightPairRotationEventEffect_UpdateRotationData, &LightPairRotat return; } - auto* beatmapEventData = LastLightPairRotationEventEffectData; - - auto chromaIt = ChromaEventDataManager::ChromaEventDatas.find(beatmapEventData); - - // Not found - if (chromaIt == ChromaEventDataManager::ChromaEventDatas.end()) { + auto beatmapEventDataOpt = il2cpp_utils::try_cast(LastLightPairRotationEventEffectData); + if (!beatmapEventDataOpt) { LightPairRotationEventEffect_UpdateRotationData(self, beatmapEventDataValue, rotationData, startRotationOffset, - direction); + direction); return; } - auto const& chromaData = chromaIt->second; + auto beatmapEventData = *beatmapEventDataOpt; + auto const& chromaData = getLightAD(beatmapEventData->customData); bool isLeftEvent = beatmapEventData->basicBeatmapEventType == self->_eventL; // rotationData diff --git a/src/hooks/Events/LightRotationEventEffect.cpp b/src/hooks/Events/LightRotationEventEffect.cpp index 13245a5a..34ce36a5 100644 --- a/src/hooks/Events/LightRotationEventEffect.cpp +++ b/src/hooks/Events/LightRotationEventEffect.cpp @@ -33,15 +33,18 @@ MAKE_HOOK_MATCH(LightRotationEventEffect_HandleBeatmapObjectCallbackControllerBe return; } - auto chromaIt = ChromaEventDataManager::ChromaEventDatas.find(beatmapEventData); + - // Not found - if (chromaIt == ChromaEventDataManager::ChromaEventDatas.end()) { + auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); + if (!beatmapEventDataOpt) { LightRotationEventEffect_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger(self, beatmapEventData); return; } - auto const& chromaData = chromaIt->second; + // Not found + + + auto const& chromaData = getLightAD(beatmapEventDataOpt.value()->customData); bool isLeftEvent = self->_event == BasicBeatmapEventType::Event12; diff --git a/src/hooks/Events/TrackLaneRingsPositionStepEffectSpawner.cpp b/src/hooks/Events/TrackLaneRingsPositionStepEffectSpawner.cpp index 4fd06cd9..18a3a20c 100644 --- a/src/hooks/Events/TrackLaneRingsPositionStepEffectSpawner.cpp +++ b/src/hooks/Events/TrackLaneRingsPositionStepEffectSpawner.cpp @@ -13,11 +13,10 @@ using namespace Chroma; using namespace GlobalNamespace; static float GetPrecisionStep(float const defaultF, GlobalNamespace::BasicBeatmapEventData* beatmapEventData) { - auto const& map = ChromaEventDataManager::ChromaEventDatas; - auto it = map.find(beatmapEventData); - - if (it != map.end()) { - auto const& chromaData = it->second; + auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); + + if (beatmapEventDataOpt.has_value()) { + auto const& chromaData = getLightAD(beatmapEventDataOpt.value()->customData); if (chromaData.Step) { return chromaData.Step.value(); @@ -28,11 +27,10 @@ static float GetPrecisionStep(float const defaultF, GlobalNamespace::BasicBeatma } static float GetPrecisionSpeed(float const defaultF, GlobalNamespace::BasicBeatmapEventData* beatmapEventData) { - auto const& map = ChromaEventDataManager::ChromaEventDatas; - auto it = map.find(beatmapEventData); - - if (it != map.end()) { - auto const& chromaData = it->second; + auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); + + if (beatmapEventDataOpt.has_value()) { + auto const& chromaData = getLightAD(beatmapEventDataOpt.value()->customData); if (chromaData.Speed) { return chromaData.Speed.value(); diff --git a/src/hooks/Events/TrackLaneRingsRotationEffectSpawner.cpp b/src/hooks/Events/TrackLaneRingsRotationEffectSpawner.cpp index d44b492c..a384a034 100644 --- a/src/hooks/Events/TrackLaneRingsRotationEffectSpawner.cpp +++ b/src/hooks/Events/TrackLaneRingsRotationEffectSpawner.cpp @@ -46,8 +46,8 @@ template T getValueOrDefault(rapidjson::Value* val, std::string con return v != val->MemberEnd() ? v->value.Get() : def; } -void TriggerRotation(TrackLaneRingsRotationEffect* trackLaneRingsRotationEffect, bool rotRight, float rotation, - float rotationStep, float rotationPropagationSpeed, float rotationFlexySpeed) { +void TriggerRotation(TrackLaneRingsRotationEffect* trackLaneRingsRotationEffect, bool rotRight, float rotation, float rotationStep, + float rotationPropagationSpeed, float rotationFlexySpeed) { debugSpamLog("DOING TRIGGER ROTATION {}", trackLaneRingsRotationEffect->klass->name); auto* chromaRingRotation = static_cast(trackLaneRingsRotationEffect); @@ -61,8 +61,8 @@ void TriggerRotation(TrackLaneRingsRotationEffect* trackLaneRingsRotationEffect, // This method is directly ported from TrackLaneRingsRotationEffectSpawner. It is required to be ported since for some // inexplicable reason using the original method causes CJD or something else to stop loading the map and it just stays // as limbo. Hopefully with time we can fix that and use that instead -void origHandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger( - GlobalNamespace::TrackLaneRingsRotationEffectSpawner* self, BasicBeatmapEventData* beatmapEventData) { +void origHandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger(GlobalNamespace::TrackLaneRingsRotationEffectSpawner* self, + BasicBeatmapEventData* beatmapEventData) { if (beatmapEventData->basicBeatmapEventType != self->_beatmapEventType) { return; } @@ -87,24 +87,21 @@ void origHandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger( auto* chromaRotation = reinterpret_cast(rotationEffect.ptr()); - chromaRotation->AddRingRotationEffectF( - chromaRotation->GetFirstRingDestinationRotationAngleCpp() + - (self->_rotation * static_cast((ChromaController::randomXoshiro() < 0.5F) ? 1 : -1)), - step, static_cast(self->_rotationPropagationSpeed), self->_rotationFlexySpeed); + chromaRotation->AddRingRotationEffectF(chromaRotation->GetFirstRingDestinationRotationAngleCpp() + + (self->_rotation * static_cast((ChromaController::randomXoshiro() < 0.5F) ? 1 : -1)), + step, static_cast(self->_rotationPropagationSpeed), self->_rotationFlexySpeed); } else { - rotationEffect->AddRingRotationEffect( - rotationEffect->GetFirstRingDestinationRotationAngle() + - (self->_rotation * static_cast((ChromaController::randomXoshiro() < 0.5F) ? 1 : -1)), - step, self->_rotationPropagationSpeed, self->_rotationFlexySpeed); + rotationEffect->AddRingRotationEffect(rotationEffect->GetFirstRingDestinationRotationAngle() + + (self->_rotation * static_cast((ChromaController::randomXoshiro() < 0.5F) ? 1 : -1)), + step, self->_rotationPropagationSpeed, self->_rotationFlexySpeed); } } MAKE_HOOK_MATCH(TrackLaneRingsRotationEffectSpawner_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger, - &TrackLaneRingsRotationEffectSpawner::HandleBeatmapEvent, void, - GlobalNamespace::TrackLaneRingsRotationEffectSpawner* self, BasicBeatmapEventData* beatmapEventData) { + &TrackLaneRingsRotationEffectSpawner::HandleBeatmapEvent, void, GlobalNamespace::TrackLaneRingsRotationEffectSpawner* self, + BasicBeatmapEventData* beatmapEventData) { if (!ChromaController::DoChromaHooks()) { - TrackLaneRingsRotationEffectSpawner_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger(self, - beatmapEventData); + TrackLaneRingsRotationEffectSpawner_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger(self, beatmapEventData); return; } @@ -115,15 +112,15 @@ MAKE_HOOK_MATCH(TrackLaneRingsRotationEffectSpawner_HandleBeatmapObjectCallbackC // : 1); if (beatmapEventData->basicBeatmapEventType == self->_beatmapEventType) { - auto chromaIt = ChromaEventDataManager::ChromaEventDatas.find(beatmapEventData); + auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); // Not found - if (chromaIt == ChromaEventDataManager::ChromaEventDatas.end()) { + if (!beatmapEventDataOpt) { origHandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger(self, beatmapEventData); return; } - auto const& chromaData = chromaIt->second; + auto const& chromaData = getLightAD(beatmapEventDataOpt.value()->customData); debugSpamLog("Doing stuff with custom Data ring"); @@ -188,8 +185,7 @@ MAKE_HOOK_MATCH(TrackLaneRingsRotationEffectSpawner_HandleBeatmapObjectCallbackC float propMult = chromaData.PropMult; float speedMult = chromaData.SpeedMult; - TriggerRotation(self->_trackLaneRingsRotationEffect, rotRight, rotation, step * stepMult, prop * propMult, - speed * speedMult); + TriggerRotation(self->_trackLaneRingsRotationEffect, rotRight, rotation, step * stepMult, prop * propMult, speed * speedMult); debugSpamLog("Finished spawn, returning"); return; } diff --git a/src/hooks/colorizer/BombNoteController.cpp b/src/hooks/colorizer/BombNoteController.cpp index 7ff415a4..1b5a0caa 100644 --- a/src/hooks/colorizer/BombNoteController.cpp +++ b/src/hooks/colorizer/BombNoteController.cpp @@ -22,9 +22,9 @@ MAKE_HOOK_MATCH(BombNoteController_Init, &BombNoteController::Init, void, BombNo return; } - auto chromaData = ChromaObjectDataManager::ChromaObjectDatas.find(noteData); - if (chromaData != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& color = chromaData->second.Color; + auto const& chromaData = getObjectAD(noteData); + if (chromaData) { + auto const& color = chromaData->Color; BombColorizer::ColorizeBomb(self, color); } diff --git a/src/hooks/colorizer/BurstSliderController.cpp b/src/hooks/colorizer/BurstSliderController.cpp index 98d57ae3..32c36254 100644 --- a/src/hooks/colorizer/BurstSliderController.cpp +++ b/src/hooks/colorizer/BurstSliderController.cpp @@ -57,9 +57,9 @@ MAKE_HOOK_MATCH(BurstSliderGameNoteController_Init, &BurstSliderGameNoteControll return; } - auto chromaData = ChromaObjectDataManager::ChromaObjectDatas.find(self->noteData); - if (chromaData != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& color = chromaData->second.Color; + auto const& chromaData = getObjectAD(self->noteData); + if (chromaData) { + auto const& color = chromaData->Color; NoteColorizer::ColorizeNote(self, color); } diff --git a/src/hooks/colorizer/ColorNoteVisuals.cpp b/src/hooks/colorizer/ColorNoteVisuals.cpp index f5d8db60..693cfb8c 100644 --- a/src/hooks/colorizer/ColorNoteVisuals.cpp +++ b/src/hooks/colorizer/ColorNoteVisuals.cpp @@ -25,10 +25,10 @@ MAKE_HOOK_MATCH(ColorNoteVisuals_HandleNoteControllerDidInit, &ColorNoteVisuals: auto NoteControllerCast = il2cpp_utils::try_cast(noteController); if (NoteControllerCast) { - auto it = ChromaObjectDataManager::ChromaObjectDatas.find(NoteControllerCast.value()->noteData); + auto it = getObjectAD(NoteControllerCast.value()->noteData); - if (it != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& chromaData = it->second; + if (it) { + auto const& chromaData = *it; std::optional const& color = chromaData.Color; diff --git a/src/hooks/colorizer/Note/NoteCutEffectSpawner.cpp b/src/hooks/colorizer/Note/NoteCutEffectSpawner.cpp index 75c2c525..25d4a078 100644 --- a/src/hooks/colorizer/Note/NoteCutEffectSpawner.cpp +++ b/src/hooks/colorizer/Note/NoteCutEffectSpawner.cpp @@ -24,9 +24,9 @@ using namespace Chroma; // If this is true, we disable debris spawning in hooks static bool global_DisableDebris_Disable = false; static bool DisableDebrisOpt(NoteController* noteController) { - auto it = ChromaObjectDataManager::ChromaObjectDatas.find(noteController->noteData); - if (it != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& chromaData = it->second; + auto it = getObjectAD(noteController->noteData); + if (it) { + auto const& chromaData = *it; std::optional disableDebris = chromaData.DisableDebris; return disableDebris.has_value() && disableDebris.value(); } diff --git a/src/hooks/colorizer/NoteController.cpp b/src/hooks/colorizer/NoteController.cpp index 19a2ca10..860bab8a 100644 --- a/src/hooks/colorizer/NoteController.cpp +++ b/src/hooks/colorizer/NoteController.cpp @@ -37,9 +37,9 @@ MAKE_HOOK_MATCH(NoteController_Init, &NoteController::Init, void, NoteController return; } - auto chromaData = ChromaObjectDataManager::ChromaObjectDatas.find(self->noteData); - if (chromaData != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& color = chromaData->second.Color; + auto const& chromaData = getObjectAD(self->noteData); + if (chromaData) { + auto const& color = chromaData->Color; NoteColorizer::ColorizeNote(self, color); } @@ -55,12 +55,12 @@ MAKE_HOOK_MATCH(NoteController_Update, &NoteController::ManualUpdate, void, Note - auto chromaData = ChromaObjectDataManager::ChromaObjectDatas.find(self->noteData); - if (chromaData != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& tracks = chromaData->second.Tracks; + auto const& chromaData = getObjectAD(self->noteData); + if (chromaData) { + auto const& tracks = chromaData->Tracks; - auto pathPointDefinition = chromaData->second.LocalPathColor; + auto pathPointDefinition = chromaData->LocalPathColor; if (!tracks.empty() || pathPointDefinition) { NoteJump* noteJump = self->_noteMovement->_jump; VariableMovementW movement(noteJump->_variableMovementDataProvider); diff --git a/src/hooks/colorizer/ObstacleController.cpp b/src/hooks/colorizer/ObstacleController.cpp index 13259130..6cc1e130 100644 --- a/src/hooks/colorizer/ObstacleController.cpp +++ b/src/hooks/colorizer/ObstacleController.cpp @@ -35,9 +35,9 @@ MAKE_HOOK_MATCH(ObstacleController_Init, &ObstacleController::Init, void, Obstac return; } - auto chromaData = ChromaObjectDataManager::ChromaObjectDatas.find(obstacleData); - if (chromaData != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& color = chromaData->second.Color; + auto const& chromaData = getObjectAD(obstacleData); + if (chromaData) { + auto const& color = chromaData->Color; ObstacleColorizer::ColorizeObstacle(self, color); } @@ -55,12 +55,13 @@ MAKE_HOOK_MATCH(ObstacleController_ManualUpdate, &ObstacleController::ManualUpda return; } - auto chromaData = ChromaObjectDataManager::ChromaObjectDatas.find(self->obstacleData); - if (chromaData != ChromaObjectDataManager::ChromaObjectDatas.end()) { + auto const& chromaData = getObjectAD(self->_obstacleData); + if (chromaData) { + auto const& color = chromaData->Color; - auto const& tracks = chromaData->second.Tracks; + auto const& tracks = chromaData->Tracks; - auto const& pathPointDefinition = chromaData->second.LocalPathColor; + auto const& pathPointDefinition = chromaData->LocalPathColor; if (!tracks.empty() || pathPointDefinition) { VariableMovementW movement(self->_variableMovementDataProvider); diff --git a/src/hooks/colorizer/SliderController.cpp b/src/hooks/colorizer/SliderController.cpp index ed7cecc5..7c524fe7 100644 --- a/src/hooks/colorizer/SliderController.cpp +++ b/src/hooks/colorizer/SliderController.cpp @@ -31,9 +31,9 @@ MAKE_HOOK_MATCH(SliderController_Init, &SliderController::Init, void, SliderCont return; } - auto chromaData = ChromaObjectDataManager::ChromaObjectDatas.find(self->sliderData); - if (chromaData != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& color = chromaData->second.Color; + auto const& chromaData = getObjectAD(self->_sliderData); + if (chromaData) { + auto const& color = chromaData->Color; if (color) { SliderColorizer::ColorizeSlider(self, color); @@ -49,11 +49,11 @@ MAKE_HOOK_MATCH(SliderController_Update, &SliderController::ManualUpdate, void, return; } - auto chromaData = ChromaObjectDataManager::ChromaObjectDatas.find(self->sliderData); - if (chromaData != ChromaObjectDataManager::ChromaObjectDatas.end()) { - auto const& tracks = chromaData->second.Tracks; + auto const& chromaData = getObjectAD(self->sliderData); + if (chromaData) { + auto const& tracks = chromaData->Tracks; - auto pathPointDefinition = chromaData->second.LocalPathColor; + auto pathPointDefinition = chromaData->LocalPathColor; if (!tracks.empty() || pathPointDefinition) { VariableMovementW movement(self->_sliderMovement->_variableMovementDataProvider); float jumpDuration = movement.jumpDuration; diff --git a/src/lighting/ChromaEventData.cpp b/src/lighting/ChromaEventData.cpp index acf9e87a..b891c1fc 100644 --- a/src/lighting/ChromaEventData.cpp +++ b/src/lighting/ChromaEventData.cpp @@ -10,8 +10,6 @@ using namespace ChromaUtils; void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapData* beatmapData) { - ChromaEventDatas.clear(); - auto* beatmapDataCast = beatmapData; static auto* CustomBasicBeatmapEventDataKlass = classof(CustomJSONData::CustomBeatmapEventData*); @@ -199,33 +197,30 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa chromaEventData.LockPosition = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_LOCK_POSITION : NewConstants::LOCK_POSITION, false); - ChromaEventDatas.try_emplace(customBeatmapEvent, std::move(chromaEventData)); + getLightAD(customBeatmapEvent->customData) = std::move(chromaEventData); } // Horrible stupid logic to get next same type event per light id // what am i even doing anymore - std::unordered_map> allNextSameTypes; - for (int i = beatmapEventDatas.size() - 1; i >= 0; i--) { + std::unordered_map> allNextSameTypes; + for (auto i = beatmapEventDatas.size() - 1; i >= 0; i--) { auto const& beatmapEventData = beatmapEventDatas[i]; auto const& basicBeatmapEventDataOpt = - il2cpp_utils::try_cast(beatmapEventData); + il2cpp_utils::try_cast(beatmapEventData); if (!basicBeatmapEventDataOpt) { continue; } auto const& basicBeatmapEventData = *basicBeatmapEventDataOpt; - auto eventDataIt = ChromaEventDatas.find(beatmapEventData); - if (eventDataIt == ChromaEventDatas.end()) { - continue; - } - auto& currentEventData = eventDataIt->second; + + auto& currentEventData = getLightAD(basicBeatmapEventData->customData); int type = (int)basicBeatmapEventData->basicBeatmapEventType.value__; auto& nextSameTypes = allNextSameTypes[type]; if (currentEventData.NextSameTypeEvent.empty()) { for (auto const& [k, v] : nextSameTypes) { - currentEventData.NextSameTypeEvent[k] = std::pair(v, &ChromaEventDatas.at(v)); + currentEventData.NextSameTypeEvent[k] = std::pair(v, &getLightAD(v->customData)); } } diff --git a/src/lighting/ChromaGradientController.cpp b/src/lighting/ChromaGradientController.cpp index ffcb335a..6fb36fa6 100644 --- a/src/lighting/ChromaGradientController.cpp +++ b/src/lighting/ChromaGradientController.cpp @@ -2,6 +2,7 @@ #include "lighting/ChromaGradientController.hpp" #include "GlobalNamespace/BeatmapObjectSpawnController.hpp" +#include "GlobalNamespace/BeatmapCallbacksController.hpp" #include "ChromaController.hpp" #include "UnityEngine/Color.hpp" @@ -74,7 +75,7 @@ Sombrero::FastColor ChromaGradientController::AddGradient(ChromaEventData::Gradi auto const& newGradientEvent = it.first->second; bool erased = false; - auto r = newGradientEvent.Interpolate(erased, ChromaController::CallbacksController->songTime); + auto r = newGradientEvent.Interpolate(erased, ChromaController::CallbacksController->_songTime); if (erased) { getInstance()->Gradients.erase(it.first); diff --git a/src/lighting/ChromaLightSwitchEventEffect.cpp b/src/lighting/ChromaLightSwitchEventEffect.cpp index 256631fa..4a937d55 100644 --- a/src/lighting/ChromaLightSwitchEventEffect.cpp +++ b/src/lighting/ChromaLightSwitchEventEffect.cpp @@ -113,17 +113,18 @@ void Chroma::ChromaLightSwitchEventEffect::HandleEvent(GlobalNamespace::BasicBea // fun fun chroma stuff - auto chromaIt = ChromaEventDataManager::ChromaEventDatas.find(beatmapEventData); + auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); // Aero thinks legacy was a mistake. I think a Quest port was a bigger mistake. std::optional color; - if (chromaIt == ChromaEventDataManager::ChromaEventDatas.end()) { + if (!beatmapEventDataOpt) { color = LegacyLightHelper::GetLegacyColor(beatmapEventData); } else { debugSpamLog("Color is legacy? {}", color ? "true" : "false"); - auto const& chromaData = chromaIt->second; + auto const& chromaData = getLightAD(beatmapEventDataOpt.value()->customData); + auto const& lightMember = chromaData.LightID; auto const& propMember = chromaData.PropID; @@ -228,8 +229,9 @@ void ChromaLightSwitchEventEffect::Refresh(bool hard, std::optionalfloatValue; auto CheckNextEventForFadeBetter = [&, this, hard, easing, lerpType]() { - auto eventDataIt = ChromaEventDataManager::ChromaEventDatas.find(previousEvent); - auto const* eventData = eventDataIt != ChromaEventDataManager::ChromaEventDatas.end() ? &eventDataIt->second : nullptr; + auto previousEventOpt = il2cpp_utils::try_cast(previousEvent); + + auto const* eventData = previousEventOpt.has_value() ? &getLightAD(previousEventOpt.value()->customData) : nullptr; auto const& nextSameTypesDict = eventData != nullptr ? &eventData->NextSameTypeEvent : nullptr; @@ -261,9 +263,11 @@ void ChromaLightSwitchEventEffect::Refresh(bool hard, std::optionalvalue); Sombrero::FastColor nextColor; - eventDataIt = ChromaEventDataManager::ChromaEventDatas.find(nextSameTypeEvent); + previousEventOpt = il2cpp_utils::try_cast(nextSameTypeEvent); + + if (nextEventData == nullptr) { - nextEventData = eventDataIt != ChromaEventDataManager::ChromaEventDatas.end() ? &eventDataIt->second : nullptr; + nextEventData = previousEventOpt.has_value() ? &getLightAD(previousEventOpt.value()->customData) : nullptr; } std::optional nextColorData = nextEventData != nullptr ? nextEventData->ColorData : std::nullopt; From 1bb9df10fd7e871e1333d7cce7b71ee24437d622 Mon Sep 17 00:00:00 2001 From: Fernthedev <15272073+Fernthedev@users.noreply.github.com> Date: Sun, 1 Feb 2026 11:22:15 -0400 Subject: [PATCH 2/9] Optimize calls to data using fields instead of properties --- src/colorizer/NoteColorizer.cpp | 2 +- src/colorizer/SliderColorizer.cpp | 4 ++-- src/hooks/BeatEffectSpawner.cpp | 2 +- src/hooks/MovementBeatmapEventEffect.cpp | 6 +++--- src/hooks/colorizer/BurstSliderController.cpp | 2 +- src/hooks/colorizer/ColorNoteVisuals.cpp | 2 +- src/hooks/colorizer/Note/NoteCutEffectSpawner.cpp | 2 +- src/hooks/colorizer/NoteController.cpp | 6 +++--- src/hooks/colorizer/ObstacleController.cpp | 2 +- src/hooks/colorizer/SliderController.cpp | 4 ++-- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/colorizer/NoteColorizer.cpp b/src/colorizer/NoteColorizer.cpp index 7bceb918..985e4c07 100644 --- a/src/colorizer/NoteColorizer.cpp +++ b/src/colorizer/NoteColorizer.cpp @@ -87,7 +87,7 @@ void NoteColorizer::Reset() { void NoteColorizer::ColorizeSaber(GlobalNamespace::NoteController* noteController, NoteCutInfo const& noteCutInfo) { if (ChromaController::DoColorizerSabers()) { - auto* noteData = noteController->noteData; + auto* noteData = noteController->_noteData; SaberType saberType = noteCutInfo.saberType; if (noteData->colorType.value__ == saberType.value__) { SaberColorizer::ColorizeSaber(saberType, GetNoteColorizer(noteController)->getColor()); diff --git a/src/colorizer/SliderColorizer.cpp b/src/colorizer/SliderColorizer.cpp index 0a17bb60..db1bc1ba 100644 --- a/src/colorizer/SliderColorizer.cpp +++ b/src/colorizer/SliderColorizer.cpp @@ -32,8 +32,8 @@ SliderColorizer* SliderColorizer::New(GlobalNamespace::SliderController* sliderC } GlobalNamespace::ColorType SliderColorizer::getColorType() const { - if ((_sliderController != nullptr) && (_sliderController->sliderData != nullptr)) { - auto* sliderData = _sliderController->sliderData; + if ((_sliderController != nullptr) && (_sliderController->_sliderData != nullptr)) { + auto* sliderData = _sliderController->_sliderData; return sliderData->colorType; } diff --git a/src/hooks/BeatEffectSpawner.cpp b/src/hooks/BeatEffectSpawner.cpp index 7acabd2b..fbf7d0a1 100644 --- a/src/hooks/BeatEffectSpawner.cpp +++ b/src/hooks/BeatEffectSpawner.cpp @@ -26,7 +26,7 @@ using namespace Chroma; using namespace GlobalNamespace; static bool BeatEffectHide(bool original, NoteController* noteController) { - auto it = getObjectAD(noteController->noteData); + auto it = getObjectAD(noteController->_noteData); if (it) { auto const& chromaData = *it; diff --git a/src/hooks/MovementBeatmapEventEffect.cpp b/src/hooks/MovementBeatmapEventEffect.cpp index dc8b4127..9e32c58d 100644 --- a/src/hooks/MovementBeatmapEventEffect.cpp +++ b/src/hooks/MovementBeatmapEventEffect.cpp @@ -27,7 +27,7 @@ using namespace GlobalNamespace; // // inline bool BeatEffectForce(bool hideNoteSpawnEffect, NoteController* noteController) //{ -// auto it = ChromaObjectDataManager::ChromaObjectDatas.find(noteController->noteData); +// auto it = ChromaObjectDataManager::ChromaObjectDatas.find(noteController->_noteData); // // if (it != ChromaObjectDataManager::ChromaObjectDatas.end()) { // auto const& chromaData = it->second; @@ -59,11 +59,11 @@ using namespace GlobalNamespace; // { // return; // } -// if (noteController->noteData->time + 0.1f < self->audioTimeSyncController->songTime) +// if (noteController->_noteData->time + 0.1f < self->audioTimeSyncController->songTime) // { // return; // } -// ColorType colorType = noteController->noteData->colorType; +// ColorType colorType = noteController->_noteData->colorType; // Sombrero::FastColor a = (colorType != ColorType::None) ? self->colorManager->ColorForType(colorType) : // self->bombColorEffect; auto beatEffect = self->beatEffectPoolContainer->Spawn(); // beatEffect->didFinishEvent->Add(self->i_IBeatEffectDidFinishEvent()); diff --git a/src/hooks/colorizer/BurstSliderController.cpp b/src/hooks/colorizer/BurstSliderController.cpp index 32c36254..a859cf2e 100644 --- a/src/hooks/colorizer/BurstSliderController.cpp +++ b/src/hooks/colorizer/BurstSliderController.cpp @@ -57,7 +57,7 @@ MAKE_HOOK_MATCH(BurstSliderGameNoteController_Init, &BurstSliderGameNoteControll return; } - auto const& chromaData = getObjectAD(self->noteData); + auto const& chromaData = getObjectAD(self->_noteData); if (chromaData) { auto const& color = chromaData->Color; diff --git a/src/hooks/colorizer/ColorNoteVisuals.cpp b/src/hooks/colorizer/ColorNoteVisuals.cpp index 693cfb8c..8d330bd5 100644 --- a/src/hooks/colorizer/ColorNoteVisuals.cpp +++ b/src/hooks/colorizer/ColorNoteVisuals.cpp @@ -25,7 +25,7 @@ MAKE_HOOK_MATCH(ColorNoteVisuals_HandleNoteControllerDidInit, &ColorNoteVisuals: auto NoteControllerCast = il2cpp_utils::try_cast(noteController); if (NoteControllerCast) { - auto it = getObjectAD(NoteControllerCast.value()->noteData); + auto it = getObjectAD(NoteControllerCast.value()->_noteData); if (it) { auto const& chromaData = *it; diff --git a/src/hooks/colorizer/Note/NoteCutEffectSpawner.cpp b/src/hooks/colorizer/Note/NoteCutEffectSpawner.cpp index 25d4a078..c90b59ca 100644 --- a/src/hooks/colorizer/Note/NoteCutEffectSpawner.cpp +++ b/src/hooks/colorizer/Note/NoteCutEffectSpawner.cpp @@ -24,7 +24,7 @@ using namespace Chroma; // If this is true, we disable debris spawning in hooks static bool global_DisableDebris_Disable = false; static bool DisableDebrisOpt(NoteController* noteController) { - auto it = getObjectAD(noteController->noteData); + auto it = getObjectAD(noteController->_noteData); if (it) { auto const& chromaData = *it; std::optional disableDebris = chromaData.DisableDebris; diff --git a/src/hooks/colorizer/NoteController.cpp b/src/hooks/colorizer/NoteController.cpp index 860bab8a..bbc4e337 100644 --- a/src/hooks/colorizer/NoteController.cpp +++ b/src/hooks/colorizer/NoteController.cpp @@ -37,7 +37,7 @@ MAKE_HOOK_MATCH(NoteController_Init, &NoteController::Init, void, NoteController return; } - auto const& chromaData = getObjectAD(self->noteData); + auto const& chromaData = getObjectAD(self->_noteData); if (chromaData) { auto const& color = chromaData->Color; @@ -55,7 +55,7 @@ MAKE_HOOK_MATCH(NoteController_Update, &NoteController::ManualUpdate, void, Note - auto const& chromaData = getObjectAD(self->noteData); + auto const& chromaData = getObjectAD(self->_noteData); if (chromaData) { auto const& tracks = chromaData->Tracks; @@ -66,7 +66,7 @@ MAKE_HOOK_MATCH(NoteController_Update, &NoteController::ManualUpdate, void, Note VariableMovementW movement(noteJump->_variableMovementDataProvider); float jumpDuration = movement.jumpDuration; float elapsedTime = ChromaTimeSourceHelper::getSongTimeChroma(noteJump->_audioTimeSyncController) - - (self->noteData->time - (jumpDuration * 0.5F)); + (self->_noteData->time - (jumpDuration * 0.5F)); float normalTime = elapsedTime / jumpDuration; [[maybe_unused]] bool updated = false; diff --git a/src/hooks/colorizer/ObstacleController.cpp b/src/hooks/colorizer/ObstacleController.cpp index 6cc1e130..28845e9f 100644 --- a/src/hooks/colorizer/ObstacleController.cpp +++ b/src/hooks/colorizer/ObstacleController.cpp @@ -69,7 +69,7 @@ MAKE_HOOK_MATCH(ObstacleController_ManualUpdate, &ObstacleController::ManualUpda float elapsedTime = ChromaTimeSourceHelper::getSongTimeChroma(self->_audioTimeSyncController) - self->_startTimeOffset; float normalTime = - (elapsedTime - movement.moveDuration) / (jumpDuration + self->obstacleData->duration); + (elapsedTime - movement.moveDuration) / (jumpDuration + self->_obstacleData->duration); [[maybe_unused]] bool updated = false; std::optional colorOffset = diff --git a/src/hooks/colorizer/SliderController.cpp b/src/hooks/colorizer/SliderController.cpp index 7c524fe7..10b405ad 100644 --- a/src/hooks/colorizer/SliderController.cpp +++ b/src/hooks/colorizer/SliderController.cpp @@ -49,7 +49,7 @@ MAKE_HOOK_MATCH(SliderController_Update, &SliderController::ManualUpdate, void, return; } - auto const& chromaData = getObjectAD(self->sliderData); + auto const& chromaData = getObjectAD(self->_sliderData); if (chromaData) { auto const& tracks = chromaData->Tracks; @@ -58,7 +58,7 @@ MAKE_HOOK_MATCH(SliderController_Update, &SliderController::ManualUpdate, void, VariableMovementW movement(self->_sliderMovement->_variableMovementDataProvider); float jumpDuration = movement.jumpDuration; - float duration = (jumpDuration * 0.75F) + (self->sliderData->tailTime - self->sliderData->time); + float duration = (jumpDuration * 0.75F) + (self->_sliderData->tailTime - self->_sliderData->time); float normalTime = self->sliderMovement->timeSinceHeadNoteJump / (jumpDuration + duration); [[maybe_unused]] bool updated = false; From cad046f63984308af3272ed9e8485eed4c74542c Mon Sep 17 00:00:00 2001 From: CatsaCode Date: Tue, 3 Feb 2026 00:09:02 -0500 Subject: [PATCH 3/9] Fix underflow crash --- src/lighting/ChromaEventData.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lighting/ChromaEventData.cpp b/src/lighting/ChromaEventData.cpp index b891c1fc..fec43111 100644 --- a/src/lighting/ChromaEventData.cpp +++ b/src/lighting/ChromaEventData.cpp @@ -7,6 +7,8 @@ #include "utils/ChromaUtils.hpp" +#include + using namespace ChromaUtils; void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapData* beatmapData) { @@ -203,7 +205,7 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa // Horrible stupid logic to get next same type event per light id // what am i even doing anymore std::unordered_map> allNextSameTypes; - for (auto i = beatmapEventDatas.size() - 1; i >= 0; i--) { + for (auto i = beatmapEventDatas.size() - 1; i >= 0 && i != std::numeric_limits::max(); i--) { auto const& beatmapEventData = beatmapEventDatas[i]; auto const& basicBeatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); From 5e5ce400bacf695800b17ea2d15f44eed9642cee Mon Sep 17 00:00:00 2001 From: CatsaCode <155121307+CatsaCode@users.noreply.github.com> Date: Tue, 3 Feb 2026 06:30:42 -0500 Subject: [PATCH 4/9] Reduce underflow check `i >= 0` is always true for an `unsigned long`. --- src/lighting/ChromaEventData.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lighting/ChromaEventData.cpp b/src/lighting/ChromaEventData.cpp index fec43111..26634ed3 100644 --- a/src/lighting/ChromaEventData.cpp +++ b/src/lighting/ChromaEventData.cpp @@ -205,7 +205,7 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa // Horrible stupid logic to get next same type event per light id // what am i even doing anymore std::unordered_map> allNextSameTypes; - for (auto i = beatmapEventDatas.size() - 1; i >= 0 && i != std::numeric_limits::max(); i--) { + for (auto i = beatmapEventDatas.size() - 1; i != std::numeric_limits::max(); i--) { auto const& beatmapEventData = beatmapEventDatas[i]; auto const& basicBeatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); From 445a0ec3c42c77f75c2a164366bd6c0f17d6d851 Mon Sep 17 00:00:00 2001 From: Fernthedev <15272073+Fernthedev@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:22:10 -0400 Subject: [PATCH 5/9] Refactor ChromaEventData assignment to use reference for efficiency --- src/lighting/ChromaEventData.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/lighting/ChromaEventData.cpp b/src/lighting/ChromaEventData.cpp index 3f8d6fbc..4452110c 100644 --- a/src/lighting/ChromaEventData.cpp +++ b/src/lighting/ChromaEventData.cpp @@ -35,10 +35,10 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa debugSpamLog("Light gradient"); // ASSIGN - ChromaEventData chromaEventData; if (!optionalDynData.has_value()) { continue; } + ChromaEventData& chromaEventData = getLightAD(customBeatmapEvent->customData); if (optionalDynData) { rapidjson::Value const& unwrappedData = *optionalDynData; @@ -199,7 +199,6 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa chromaEventData.LockPosition = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_LOCK_POSITION : NewConstants::LOCK_POSITION, false); - getLightAD(customBeatmapEvent->customData) = std::move(chromaEventData); } // Horrible stupid logic to get next same type event per light id From 317bde4bf6307fcf0a5080fd1c89dcfc04249dd6 Mon Sep 17 00:00:00 2001 From: Fernthedev <15272073+Fernthedev@users.noreply.github.com> Date: Tue, 3 Feb 2026 20:27:55 -0400 Subject: [PATCH 6/9] Minor cleaning --- include/lighting/ChromaEventData.hpp | 16 +++++++++++++--- src/ChromaObjectData.cpp | 18 ------------------ 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/include/lighting/ChromaEventData.hpp b/include/lighting/ChromaEventData.hpp index 8c438192..fde533d0 100644 --- a/include/lighting/ChromaEventData.hpp +++ b/include/lighting/ChromaEventData.hpp @@ -14,7 +14,7 @@ namespace GlobalNamespace { class BasicBeatmapEventData; class BeatmapObjectSpawnController; -}; +}; // namespace GlobalNamespace namespace Chroma { class ChromaEventData { @@ -86,10 +86,20 @@ class ChromaEventDataManager { static void deserialize(CustomJSONData::CustomBeatmapData* beatmapData); }; -static ChromaEventData& getLightAD(CustomJSONData::JSONWrapper* customData) { +constexpr ChromaEventData& getLightAD(CustomJSONData::JSONWrapper* customData) { auto& ad = customData->associatedData['C']; - if (!ad.has_value()) ad = std::make_any(); + if (!ad.has_value()) { + ad = std::make_any(); + } return std::any_cast(ad); } +constexpr ChromaEventData* getLightAD(GlobalNamespace::BeatmapEventData* beatmap) { + auto const& customBeatmapEvent = il2cpp_utils::try_cast(beatmap); + if (!customBeatmapEvent) { + return nullptr; + } + return &getLightAD(customBeatmapEvent.value()->customData); +} + } // namespace Chroma \ No newline at end of file diff --git a/src/ChromaObjectData.cpp b/src/ChromaObjectData.cpp index d85e24b3..37a51c8c 100644 --- a/src/ChromaObjectData.cpp +++ b/src/ChromaObjectData.cpp @@ -77,24 +77,6 @@ void Chroma::ChromaObjectDataManager::deserialize(CustomJSONData::CustomBeatmapD objectDynData = customObstacleData->customData; chromaObjectData.Color = ChromaUtilities::GetColorFromData(objectDynData->value, v2); } - // else if (false && ASSIGNMENT_CHECK(CustomWaypointDataKlass,beatmapObjectData->klass)) { - // debugSpamLog("Custom waypoint"); - // auto *customBeatmapEvent = - // il2cpp_utils::cast(beatmapObjectData); - // - // // TODO: uncomment when CJD adds customData - // // bool isCustomData = customBeatmapEvent->customData && customBeatmapEvent->customData->value - // && - // // customBeatmapEvent->customData->value->IsObject(); - // // dynData = isCustomData ? customBeatmapEvent->customData->value : nullptr; - // - // auto data = std::make_shared(); - // - // data->Color = std::nullopt; - // - // - // chromaObjectData = data; - // } else { continue; } From b4b91b942b9a46311600be50124b092801799bac Mon Sep 17 00:00:00 2001 From: Fernthedev <15272073+Fernthedev@users.noreply.github.com> Date: Sat, 14 Feb 2026 20:18:41 -0400 Subject: [PATCH 7/9] Fix event parsing returning early --- src/ChromaEvents.cpp | 50 +++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/ChromaEvents.cpp b/src/ChromaEvents.cpp index 45fe4c40..3fb657ec 100644 --- a/src/ChromaEvents.cpp +++ b/src/ChromaEvents.cpp @@ -37,13 +37,13 @@ void ChromaEvents::parseEventData(TracksAD::BeatmapAssociatedData& beatmapAD, Cu } auto& eventAD = getEventAD(customEventData); - eventAD.parsed = true; if (eventAD.parsed) { return; } - if (!customEventData->customData->value) { + if (!customEventData->customData || !customEventData->customData->value) { return; } + eventAD.parsed = true; rapidjson::Value const& eventData = *customEventData->customData->value; @@ -141,38 +141,40 @@ void ChromaEvents::deserialize(CustomJSONData::CustomBeatmapData* readOnlyBeatma } void CustomEventCallback(BeatmapCallbacksController* callbackController, CustomJSONData::CustomEventData* customEventData) { - PAPER_IL2CPP_CATCH_HANDLER( - bool isType = false; - auto typeHash = customEventData->typeHash; + bool isType = false; + + auto typeHash = customEventData->typeHash; #define TYPE_GET(jsonName, varName) \ static auto jsonNameHash_##varName = std::hash()(jsonName); \ if (!isType && typeHash == (jsonNameHash_##varName)) isType = true; - TYPE_GET(Chroma::OldConstants::ASSIGNFOGTRACK, ASSIGNFOGTRACK) TYPE_GET(Chroma::NewConstants::ANIMATE_COMPONENT, ANIMATE_COMPONENT) - - if (!isType) { return; } + TYPE_GET(Chroma::OldConstants::ASSIGNFOGTRACK, ASSIGNFOGTRACK) + TYPE_GET(Chroma::NewConstants::ANIMATE_COMPONENT, ANIMATE_COMPONENT) - auto const& ad = ChromaEvents::getEventAD(customEventData); + if (!isType) { + return; + } - // fail safe, idek why this needs to be done smh - // CJD you bugger - auto* customBeatmapData = il2cpp_utils::cast(callbackController->_beatmapData); - if (!ad.parsed) { - TracksAD::BeatmapAssociatedData& beatmapAD = TracksAD::getBeatmapAD(customBeatmapData->customData); - ChromaEvents::parseEventData(beatmapAD, customEventData, customBeatmapData->v2orEarlier); - } + auto const& ad = ChromaEvents::getEventAD(customEventData); - if (typeHash == jsonNameHash_ASSIGNFOGTRACK) { - Chroma::ChromaFogController::getInstance()->AssignTrack(std::get(ad.data).track); - CJDLogger::Logger.fmtLog("Assigned fog controller to track"); - } if (typeHash == jsonNameHash_ANIMATE_COMPONENT && !customBeatmapData->v2orEarlier) { - CJDLogger::Logger.fmtLog("Animated component"); - Chroma::Component::StartEvent(callbackController, customEventData, std::get(ad.data)); - } + // fail safe, idek why this needs to be done smh + // CJD you bugger + auto* customBeatmapData = il2cpp_utils::cast(callbackController->_beatmapData); + if (!ad.parsed) { + TracksAD::BeatmapAssociatedData& beatmapAD = TracksAD::getBeatmapAD(customBeatmapData->customData); + ChromaEvents::parseEventData(beatmapAD, customEventData, customBeatmapData->v2orEarlier); + } - ) + if (typeHash == jsonNameHash_ASSIGNFOGTRACK) { + Chroma::ChromaFogController::getInstance()->AssignTrack(std::get(ad.data).track); + CJDLogger::Logger.fmtLog("Assigned fog controller to track"); + } + if (typeHash == jsonNameHash_ANIMATE_COMPONENT && !customBeatmapData->v2orEarlier) { + CJDLogger::Logger.fmtLog("Animated component"); + Chroma::Component::StartEvent(callbackController, customEventData, std::get(ad.data)); + } } void ChromaEvents::AddEventCallbacks() { From 8a1db90be429ce36999258c863a646410414b539 Mon Sep 17 00:00:00 2001 From: Fernthedev <15272073+Fernthedev@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:20:34 -0400 Subject: [PATCH 8/9] Fix regressions causing lights not to work --- src/lighting/ChromaEventData.cpp | 61 +++++++------------ src/lighting/ChromaLightSwitchEventEffect.cpp | 6 +- 2 files changed, 25 insertions(+), 42 deletions(-) diff --git a/src/lighting/ChromaEventData.cpp b/src/lighting/ChromaEventData.cpp index d8f9ddba..212493ee 100644 --- a/src/lighting/ChromaEventData.cpp +++ b/src/lighting/ChromaEventData.cpp @@ -14,40 +14,34 @@ using namespace ChromaUtils; void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapData* beatmapData) { auto* beatmapDataCast = beatmapData; - static auto* CustomBasicBeatmapEventDataKlass = classof(CustomJSONData::CustomBeatmapEventData*); bool v2 = beatmapDataCast->v2orEarlier; auto const& beatmapEventDatas = beatmapDataCast->beatmapEventDatas; + ChromaLogger::Logger.debug("Deserializing Chroma events, count: {}", beatmapEventDatas.size()); for (auto* beatmapEvent : beatmapEventDatas) { - if (beatmapEvent->klass != CustomBasicBeatmapEventDataKlass) { + auto customBeatmapEvent = il2cpp_utils::try_cast(beatmapEvent); + + if (!customBeatmapEvent) { continue; } - auto* customBeatmapEvent = reinterpret_cast(beatmapEvent); - if (!customBeatmapEvent->customData) { + + if (!customBeatmapEvent.value()->customData) { continue; } - auto const& optionalDynData = customBeatmapEvent->customData->value; - - std::optional gradientObject = std::nullopt; + auto const& optionalDynData = customBeatmapEvent.value()->customData->value; - debugSpamLog("Light gradient"); // ASSIGN - if (!optionalDynData.has_value()) { - continue; - } - ChromaEventData& chromaEventData = getLightAD(customBeatmapEvent->customData); + ChromaEventData& chromaEventData = getLightAD(customBeatmapEvent.value()->customData); if (optionalDynData) { rapidjson::Value const& unwrappedData = *optionalDynData; -#pragma region V2 Gradients and prop if (v2) { auto gradientJSON = unwrappedData.FindMember(NewConstants::V2_LIGHT_GRADIENT.data()); - if (gradientJSON != unwrappedData.MemberEnd() && !gradientJSON->value.IsNull() && - gradientJSON->value.IsObject()) { + if (gradientJSON != unwrappedData.MemberEnd() && !gradientJSON->value.IsNull() && gradientJSON->value.IsObject()) { auto const& gValue = gradientJSON->value; float duration = ChromaUtils::getIfExists(gValue, Chroma::NewConstants::V2_DURATION).value_or(0); @@ -55,8 +49,7 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa Sombrero::FastColor initcolor = ChromaUtils::ChromaUtilities::GetColorFromData(gValue, Chroma::NewConstants::V2_START_COLOR).value(); - Sombrero::FastColor endcolor = - ChromaUtils::ChromaUtilities::GetColorFromData(gValue, Chroma::NewConstants::V2_END_COLOR).value(); + Sombrero::FastColor endcolor = ChromaUtils::ChromaUtilities::GetColorFromData(gValue, Chroma::NewConstants::V2_END_COLOR).value(); std::string_view easingString = gValue.FindMember(Chroma::NewConstants::V2_EASING.data())->value.GetString(); @@ -68,8 +61,8 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa easing = FunctionFromStr(easingString); } - gradientObject = std::make_optional(ChromaEventData::GradientObjectData{ - .Duration = duration, .StartColor = initcolor, .EndColor = endcolor, .Easing = easing }); + chromaEventData.GradientObject = std::make_optional( + ChromaEventData::GradientObjectData{ .Duration = duration, .StartColor = initcolor, .EndColor = endcolor, .Easing = easing }); } auto propId = unwrappedData.FindMember(Chroma::NewConstants::V2_PROPAGATION_ID.data()); @@ -109,9 +102,8 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa chromaEventData.PropID = propIds; } } -#pragma endregion - auto easingString = - getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_EASING : NewConstants::EASING); + + auto easingString = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_EASING : NewConstants::EASING); if (easingString) { Functions easing; @@ -125,8 +117,7 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa chromaEventData.Easing = easing; } - auto lerpTypeStr = - getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_LERP_TYPE : NewConstants::LERP_TYPE); + auto lerpTypeStr = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_LERP_TYPE : NewConstants::LERP_TYPE); if (lerpTypeStr) { LerpType lerpType; @@ -140,7 +131,6 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa chromaEventData.LerpType = lerpType; } - debugSpamLog("Light ID"); auto lightId = unwrappedData.FindMember(v2 ? NewConstants::V2_LIGHT_ID.data() : NewConstants::LIGHT_ID.data()); if (lightId != unwrappedData.MemberEnd()) { @@ -167,19 +157,16 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa // Light stuff chromaEventData.ColorData = ChromaUtilities::GetColorFromData(optionalDynData, v2); - chromaEventData.GradientObject = gradientObject; + // RING STUFF chromaEventData.NameFilter = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_NAME_FILTER : NewConstants::NAME_FILTER); - chromaEventData.Direction = - getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_DIRECTION : NewConstants::DIRECTION); - chromaEventData.CounterSpin = - v2 ? getIfExistsOpt(optionalDynData, NewConstants::V2_COUNTER_SPIN) : std::nullopt; + chromaEventData.Direction = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_DIRECTION : NewConstants::DIRECTION); + chromaEventData.CounterSpin = v2 ? getIfExistsOpt(optionalDynData, NewConstants::V2_COUNTER_SPIN) : std::nullopt; chromaEventData.Reset = v2 ? getIfExistsOpt(optionalDynData, NewConstants::V2_RESET) : std::nullopt; - std::optional speed = - getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_SPEED : NewConstants::SPEED); + std::optional speed = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_SPEED : NewConstants::SPEED); if (!speed && v2) { speed = getIfExistsOpt(optionalDynData, NewConstants::V2_PRECISE_SPEED); @@ -188,8 +175,7 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa chromaEventData.Prop = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_PROP : NewConstants::PROP); chromaEventData.Step = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_STEP : NewConstants::STEP); chromaEventData.Speed = speed; - chromaEventData.Rotation = - getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_ROTATION : NewConstants::ROTATION); + chromaEventData.Rotation = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_ROTATION : NewConstants::ROTATION); } chromaEventData.StepMult = v2 ? getIfExistsOpt(optionalDynData, NewConstants::V2_STEP_MULT, 1.0F) : 1; @@ -199,7 +185,6 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa // Light stuff again chromaEventData.LockPosition = getIfExistsOpt(optionalDynData, v2 ? NewConstants::V2_LOCK_POSITION : NewConstants::LOCK_POSITION, false); - } // Horrible stupid logic to get next same type event per light id @@ -208,15 +193,13 @@ void Chroma::ChromaEventDataManager::deserialize(CustomJSONData::CustomBeatmapDa if (beatmapEventDatas.size() == 0) { return; } - for (auto *beatmapEventData : std::ranges::reverse_view(beatmapEventDatas)) { - auto const& basicBeatmapEventDataOpt = - il2cpp_utils::try_cast(beatmapEventData); + for (auto* beatmapEventData : std::ranges::reverse_view(beatmapEventDatas)) { + auto basicBeatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); if (!basicBeatmapEventDataOpt) { continue; } auto const& basicBeatmapEventData = *basicBeatmapEventDataOpt; - auto& currentEventData = getLightAD(basicBeatmapEventData->customData); int type = (int)basicBeatmapEventData->basicBeatmapEventType.value__; diff --git a/src/lighting/ChromaLightSwitchEventEffect.cpp b/src/lighting/ChromaLightSwitchEventEffect.cpp index 71c727e5..7591b911 100644 --- a/src/lighting/ChromaLightSwitchEventEffect.cpp +++ b/src/lighting/ChromaLightSwitchEventEffect.cpp @@ -112,7 +112,7 @@ void Chroma::ChromaLightSwitchEventEffect::HandleEvent(GlobalNamespace::BasicBea // fun fun chroma stuff - auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); + auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); // Aero thinks legacy was a mistake. I think a Quest port was a bigger mistake. std::optional color; @@ -229,7 +229,7 @@ void ChromaLightSwitchEventEffect::Refresh(bool hard, std::optional(previousEvent); - auto const* eventData = previousEventOpt.has_value() ? &getLightAD(previousEventOpt.value()->customData) : nullptr; + auto const* eventData = getLightAD(previousEvent); auto const& nextSameTypesDict = eventData != nullptr ? &eventData->NextSameTypeEvent : nullptr; @@ -265,7 +265,7 @@ void ChromaLightSwitchEventEffect::Refresh(bool hard, std::optionalcustomData) : nullptr; + nextEventData = getLightAD(nextSameTypeEvent); } std::optional nextColorData = nextEventData != nullptr ? nextEventData->ColorData : std::nullopt; From e1dccaca659f6fce7255764badec5f65fdd00722 Mon Sep 17 00:00:00 2001 From: Fernthedev <15272073+Fernthedev@users.noreply.github.com> Date: Sat, 14 Feb 2026 21:20:49 -0400 Subject: [PATCH 9/9] Nitpicks --- include/lighting/ChromaEventData.hpp | 4 +-- .../Events/LightPairRotationEventEffect.cpp | 6 ++-- src/hooks/Events/LightRotationEventEffect.cpp | 9 ++--- ...rackLaneRingsPositionStepEffectSpawner.cpp | 33 +++++++------------ 4 files changed, 19 insertions(+), 33 deletions(-) diff --git a/include/lighting/ChromaEventData.hpp b/include/lighting/ChromaEventData.hpp index fde533d0..d902028b 100644 --- a/include/lighting/ChromaEventData.hpp +++ b/include/lighting/ChromaEventData.hpp @@ -4,6 +4,7 @@ #include "tracks/shared/Animation/Easings.h" +#include #include #include "sombrero/shared/ColorUtils.hpp" @@ -20,7 +21,6 @@ namespace Chroma { class ChromaEventData { public: ChromaEventData() = default; - [[deprecated("Copy invoked")]] ChromaEventData(ChromaEventData const&) = default; ChromaEventData(ChromaEventData&&) = default; @@ -95,7 +95,7 @@ constexpr ChromaEventData& getLightAD(CustomJSONData::JSONWrapper* customData) { } constexpr ChromaEventData* getLightAD(GlobalNamespace::BeatmapEventData* beatmap) { - auto const& customBeatmapEvent = il2cpp_utils::try_cast(beatmap); + auto customBeatmapEvent = il2cpp_utils::try_cast(beatmap); if (!customBeatmapEvent) { return nullptr; } diff --git a/src/hooks/Events/LightPairRotationEventEffect.cpp b/src/hooks/Events/LightPairRotationEventEffect.cpp index 7497d8d0..efd2481a 100644 --- a/src/hooks/Events/LightPairRotationEventEffect.cpp +++ b/src/hooks/Events/LightPairRotationEventEffect.cpp @@ -50,15 +50,15 @@ MAKE_HOOK_MATCH(LightPairRotationEventEffect_UpdateRotationData, &LightPairRotat return; } - auto beatmapEventDataOpt = il2cpp_utils::try_cast(LastLightPairRotationEventEffectData); + auto beatmapEventDataOpt = getLightAD(LastLightPairRotationEventEffectData); if (!beatmapEventDataOpt) { LightPairRotationEventEffect_UpdateRotationData(self, beatmapEventDataValue, rotationData, startRotationOffset, direction); return; } - auto beatmapEventData = *beatmapEventDataOpt; - auto const& chromaData = getLightAD(beatmapEventData->customData); + auto beatmapEventData = LastLightPairRotationEventEffectData; + auto const& chromaData = *beatmapEventDataOpt; bool isLeftEvent = beatmapEventData->basicBeatmapEventType == self->_eventL; // rotationData diff --git a/src/hooks/Events/LightRotationEventEffect.cpp b/src/hooks/Events/LightRotationEventEffect.cpp index 34ce36a5..80b34955 100644 --- a/src/hooks/Events/LightRotationEventEffect.cpp +++ b/src/hooks/Events/LightRotationEventEffect.cpp @@ -33,18 +33,15 @@ MAKE_HOOK_MATCH(LightRotationEventEffect_HandleBeatmapObjectCallbackControllerBe return; } - - - auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); - if (!beatmapEventDataOpt) { + auto *chromaDataOpt = getLightAD(beatmapEventData); + if (!chromaDataOpt) { LightRotationEventEffect_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger(self, beatmapEventData); return; } // Not found - - auto const& chromaData = getLightAD(beatmapEventDataOpt.value()->customData); + auto const& chromaData = *chromaDataOpt; bool isLeftEvent = self->_event == BasicBeatmapEventType::Event12; diff --git a/src/hooks/Events/TrackLaneRingsPositionStepEffectSpawner.cpp b/src/hooks/Events/TrackLaneRingsPositionStepEffectSpawner.cpp index 18a3a20c..4a2140aa 100644 --- a/src/hooks/Events/TrackLaneRingsPositionStepEffectSpawner.cpp +++ b/src/hooks/Events/TrackLaneRingsPositionStepEffectSpawner.cpp @@ -13,28 +13,20 @@ using namespace Chroma; using namespace GlobalNamespace; static float GetPrecisionStep(float const defaultF, GlobalNamespace::BasicBeatmapEventData* beatmapEventData) { - auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); - - if (beatmapEventDataOpt.has_value()) { - auto const& chromaData = getLightAD(beatmapEventDataOpt.value()->customData); - - if (chromaData.Step) { - return chromaData.Step.value(); - } + auto const& chromaData = getLightAD(beatmapEventData); + if (chromaData && chromaData->Step) { + + return chromaData->Step.value(); } return defaultF; } static float GetPrecisionSpeed(float const defaultF, GlobalNamespace::BasicBeatmapEventData* beatmapEventData) { - auto beatmapEventDataOpt = il2cpp_utils::try_cast(beatmapEventData); - - if (beatmapEventDataOpt.has_value()) { - auto const& chromaData = getLightAD(beatmapEventDataOpt.value()->customData); - - if (chromaData.Speed) { - return chromaData.Speed.value(); - } + auto chromaData = getLightAD(beatmapEventData); + + if (chromaData && chromaData->Speed) { + return chromaData->Speed.value(); } return defaultF; @@ -43,12 +35,10 @@ static float GetPrecisionSpeed(float const defaultF, GlobalNamespace::BasicBeatm // Aero why do you have to use transpilers for everything damn it? Just rewrite the method MAKE_HOOK_MATCH(TrackLaneRingsPositionStepEffectSpawner_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger, &TrackLaneRingsPositionStepEffectSpawner::HandleBeatmapEvent, void, - GlobalNamespace::TrackLaneRingsPositionStepEffectSpawner* self, - GlobalNamespace::BasicBeatmapEventData* beatmapEventData) { + GlobalNamespace::TrackLaneRingsPositionStepEffectSpawner* self, GlobalNamespace::BasicBeatmapEventData* beatmapEventData) { // Essentially, here we cancel the original method. DO NOT call it IF it's a Chroma map if (!ChromaController::DoChromaHooks()) { - TrackLaneRingsPositionStepEffectSpawner_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger( - self, beatmapEventData); + TrackLaneRingsPositionStepEffectSpawner_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger(self, beatmapEventData); return; } @@ -67,8 +57,7 @@ MAKE_HOOK_MATCH(TrackLaneRingsPositionStepEffectSpawner_HandleBeatmapObjectCallb } void TrackLaneRingsPositionStepEffectSpawnerHook() { - INSTALL_HOOK(ChromaLogger::Logger, - TrackLaneRingsPositionStepEffectSpawner_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger); + INSTALL_HOOK(ChromaLogger::Logger, TrackLaneRingsPositionStepEffectSpawner_HandleBeatmapObjectCallbackControllerBeatmapEventDidTrigger); // INSTALL_HOOK_OFFSETLESS(ChromaLogger::Logger, SaberManager_Finalize, il2cpp_utils::FindMethodUnsafe("System", "Object", // "Finalize", 0)); }