mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-23 13:05:54 +02:00
Music: skip the Mods shelf when no mod declares a playlist
Build the Mods shelf only when an enabled mod declares at least one playlist with songs, read from each mod's reskate-music.json. The shelf must be inserted before the native widgets bind, so it cannot wait for Featured rows to hydrate, and it should not publish an empty shelf when there is nothing to show. With no declared mod playlist the native three shelves are left as they are and a music_mods_shelf_skipped event is logged.
This commit is contained in:
1 parent
d4d3549799
commit
88e033b33f
2 files changed
+40
-16
No files matched your search
@@ -1,4 +1,5 @@
|
||||
#include "Extension/Music/local_music_shelf.h"
|
||||
#include "Extension/Music/local_music_assets.h"
|
||||
#include "Engine/Core/Log/logging.h"
|
||||
#include "Engine/Game/Abi/native_data.h"
|
||||
#include "Engine/Game/Build/addresses.h"
|
||||
@@ -198,22 +199,39 @@ std::uint64_t music_model_construct_hook(std::uintptr_t manager, std::uint8_t mo
|
||||
try {
|
||||
if (!handle || !type || md::read<std::uint32_t>(md::read<std::uintptr_t>(type)) != 0x48455d84U)
|
||||
return handle;
|
||||
game::ModelWriteLock lock(manager);
|
||||
md::Context context{local_runtime().base, manager};
|
||||
const auto items = context.field(md::Value{handle, type}, 0x67223da7U);
|
||||
unsigned count{}, stride{};
|
||||
const auto bytes = context.array(items, 1024, count, stride);
|
||||
if (count != 3 || stride != 16) return handle;
|
||||
constexpr const char* records[] = {
|
||||
"MusicPlaylistManager_Base_ContentResources/Featured_AnchoredContent_VM",
|
||||
"MusicPlaylistManager_Base_ContentResources/Liked_AnchoredContent_VM",
|
||||
"MusicPlaylistManager_Base_ContentResources/NewlyDiscovered_AnchoredContent_VM"};
|
||||
for (unsigned item = 0; item < 3; ++item) {
|
||||
std::uintptr_t item_record{};
|
||||
std::memcpy(&item_record, bytes.data() + item * stride, sizeof(item_record));
|
||||
// Named record header +0x28 is also used by the native UI dumper.
|
||||
if (!item_record || md::string(md::read<std::uintptr_t>(item_record + 0x28), 256) != records[item])
|
||||
return handle;
|
||||
bool is_music_shelf = false;
|
||||
{
|
||||
game::ModelWriteLock lock(manager);
|
||||
md::Context context{local_runtime().base, manager};
|
||||
const auto items = context.field(md::Value{handle, type}, 0x67223da7U);
|
||||
unsigned count{}, stride{};
|
||||
const auto bytes = context.array(items, 1024, count, stride);
|
||||
if (count != 3 || stride != 16) return handle;
|
||||
constexpr const char* records[] = {
|
||||
"MusicPlaylistManager_Base_ContentResources/Featured_AnchoredContent_VM",
|
||||
"MusicPlaylistManager_Base_ContentResources/Liked_AnchoredContent_VM",
|
||||
"MusicPlaylistManager_Base_ContentResources/NewlyDiscovered_AnchoredContent_VM"};
|
||||
is_music_shelf = true;
|
||||
for (unsigned item = 0; item < 3; ++item) {
|
||||
std::uintptr_t item_record{};
|
||||
std::memcpy(&item_record, bytes.data() + item * stride, sizeof(item_record));
|
||||
// Named record header +0x28 is also used by the native UI dumper.
|
||||
if (!item_record || md::string(md::read<std::uintptr_t>(item_record + 0x28), 256) != records[item]) {
|
||||
is_music_shelf = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!is_music_shelf) return handle;
|
||||
// Only add our shelf when an enabled mod actually declares a playlist with songs. Otherwise
|
||||
// leave the native three shelves untouched instead of publishing an empty Mods shelf.
|
||||
bool has_mod_playlists = false;
|
||||
for (const auto& playlist : mod_music_playlists())
|
||||
if (!playlist.songs.empty()) { has_mod_playlists = true; break; }
|
||||
if (!has_mod_playlists) {
|
||||
mods_shelf = {};
|
||||
dingosdk::logging::event(dingosdk::logging::Channel::music, "{\"event\":\"music_mods_shelf_skipped\"}");
|
||||
return handle;
|
||||
}
|
||||
const auto report = music_shelf_append_one(local_runtime().base, manager, handle);
|
||||
dingosdk::logging::event(dingosdk::logging::Channel::music,
|
||||
|
||||
@@ -198,6 +198,12 @@ The Mods implementation performs these steps under the native model write lock:
|
||||
**Mods, Featured, Liked, Newly Discovered**.
|
||||
7. Populate the owned tile list from mod playlist rows in Featured.
|
||||
|
||||
The shelf is only built when an enabled mod declares a playlist with songs, read from
|
||||
each mod's `reskate-music.json`. The insertion has to happen before the widgets bind,
|
||||
so its rows cannot be awaited; the enabled mods' declarations are the signal that does
|
||||
not depend on row hydration. With none, the native three shelves are left untouched
|
||||
rather than publishing an empty Mods shelf.
|
||||
|
||||
The native template supplies layout and presentation defaults. Creating both
|
||||
models separately supplies independent state. Changing the label on the original
|
||||
Liked tile list would rename the original shelf too.
|
||||
|
||||
Reference in new issue
Block a user