From 41831249fe92ecd3e860e1d5e02192fbed633a19 Mon Sep 17 00:00:00 2001 From: Guffawaffle Date: Wed, 23 Sep 2026 21:25:48 -0500 Subject: [PATCH] Support All wildcard in the existing named audio event filter --- example_community_patch_settings_da.toml | 2 +- example_community_patch_settings_de.toml | 2 +- ...munity_patch_settings_en-GB-x-cockney.toml | 2 +- ...mmunity_patch_settings_en-x-minionese.toml | 2 +- example_community_patch_settings_en.toml | 2 +- example_community_patch_settings_es.toml | 2 +- example_community_patch_settings_fr.toml | 2 +- example_community_patch_settings_nl.toml | 2 +- example_community_patch_settings_ru.toml | 2 +- example_community_patch_settings_tlh.toml | 2 +- mods/src/config.cc | 21 ++++++- mods/src/config.h | 1 + mods/src/patches/parts/audio_events.cc | 55 +++++++++++++++++-- 13 files changed, 80 insertions(+), 17 deletions(-) diff --git a/example_community_patch_settings_da.toml b/example_community_patch_settings_da.toml index bd067d2a8..4c848e469 100644 --- a/example_community_patch_settings_da.toml +++ b/example_community_patch_settings_da.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/example_community_patch_settings_de.toml b/example_community_patch_settings_de.toml index faa367211..ecf3dd6b2 100644 --- a/example_community_patch_settings_de.toml +++ b/example_community_patch_settings_de.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/example_community_patch_settings_en-GB-x-cockney.toml b/example_community_patch_settings_en-GB-x-cockney.toml index 72b77cb88..a90334eba 100644 --- a/example_community_patch_settings_en-GB-x-cockney.toml +++ b/example_community_patch_settings_en-GB-x-cockney.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/example_community_patch_settings_en-x-minionese.toml b/example_community_patch_settings_en-x-minionese.toml index ca5a5850f..eafb62ebf 100644 --- a/example_community_patch_settings_en-x-minionese.toml +++ b/example_community_patch_settings_en-x-minionese.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/example_community_patch_settings_en.toml b/example_community_patch_settings_en.toml index eec640425..53ea677aa 100644 --- a/example_community_patch_settings_en.toml +++ b/example_community_patch_settings_en.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/example_community_patch_settings_es.toml b/example_community_patch_settings_es.toml index cd1fb5c77..f7c88508c 100644 --- a/example_community_patch_settings_es.toml +++ b/example_community_patch_settings_es.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/example_community_patch_settings_fr.toml b/example_community_patch_settings_fr.toml index f6f9541cd..682eb8562 100644 --- a/example_community_patch_settings_fr.toml +++ b/example_community_patch_settings_fr.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/example_community_patch_settings_nl.toml b/example_community_patch_settings_nl.toml index e3980b218..b70bcc2a2 100644 --- a/example_community_patch_settings_nl.toml +++ b/example_community_patch_settings_nl.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/example_community_patch_settings_ru.toml b/example_community_patch_settings_ru.toml index eaf83d806..a41a1e8d3 100644 --- a/example_community_patch_settings_ru.toml +++ b/example_community_patch_settings_ru.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/example_community_patch_settings_tlh.toml b/example_community_patch_settings_tlh.toml index 0ebcbb1b5..4ca9c6e89 100644 --- a/example_community_patch_settings_tlh.toml +++ b/example_community_patch_settings_tlh.toml @@ -31,7 +31,7 @@ # <[=======================================]> [audio] -# Comma-separated audio event names to suppress; leave blank to allow all audio events +# Comma-separated audio event names to suppress; use "All" as a wildcard for named events handled by this filter disabled_events = "" # Write audio event names to the trace log for troubleshooting diff --git a/mods/src/config.cc b/mods/src/config.cc index 2efae99ae..3864d9636 100644 --- a/mods/src/config.cc +++ b/mods/src/config.cc @@ -32,6 +32,19 @@ namespace DCS = DefaultConfig::Sync; namespace DCSC = DefaultConfig::SystemConfig; namespace DCSH = DefaultConfig::Shortcuts; +namespace +{ +constexpr bool is_all_audio_wildcard(std::string_view value) +{ + return value.size() == 3 && (value[0] == 'a' || value[0] == 'A') && (value[1] == 'l' || value[1] == 'L') + && (value[2] == 'l' || value[2] == 'L'); +} + +static_assert(is_all_audio_wildcard("aLl")); +static_assert(!is_all_audio_wildcard(std::string_view{"All\0suffix", 10})); +static_assert(!is_all_audio_wildcard(std::string_view{"\xffll", 3})); +} // namespace + static const eastl::tuple bannerTypes[] = { {"All", ToastState::All}, {"Standard", ToastState::Standard}, @@ -1023,14 +1036,18 @@ void Config::Load() get_config_or_default(config, parsed, "audio", "trace_events", DCA::trace_events, write_config); auto disabled_audio_events = get_config_or_default( config, parsed, "audio", "disabled_events", DCA::disabled_events, write_config); + this->disable_all_audio_events = false; this->disabled_audio_events.clear(); for (const auto& event : StrSplit(disabled_audio_events, ',')) { auto stripped = StripAsciiWhitespace(event); - if (!stripped.empty()) { + if (is_all_audio_wildcard(stripped)) { + this->disable_all_audio_events = true; + } else if (!stripped.empty()) { this->disabled_audio_events.emplace_back(stripped); } } - this->installAudioEventHooks = this->trace_audio_events || !this->disabled_audio_events.empty(); + this->installAudioEventHooks = + this->trace_audio_events || this->disable_all_audio_events || !this->disabled_audio_events.empty(); this->auto_open_bulk_claim_flyout = get_config_or_default(config, parsed, "ui", "auto_open_bulk_claim_flyout", DCU::auto_open_bulk_claim_flyout, write_config); diff --git a/mods/src/config.h b/mods/src/config.h index 37e73e307..f37095d8a 100644 --- a/mods/src/config.h +++ b/mods/src/config.h @@ -213,6 +213,7 @@ class Config final bool disable_first_popup; bool disable_toast_banners; bool trace_audio_events; + bool disable_all_audio_events; std::vector disabled_audio_events; bool auto_open_bulk_claim_flyout; bool auto_confirm_ft_upgrade; diff --git a/mods/src/patches/parts/audio_events.cc b/mods/src/patches/parts/audio_events.cc index 1d2c2c0e2..7e276d1cf 100644 --- a/mods/src/patches/parts/audio_events.cc +++ b/mods/src/patches/parts/audio_events.cc @@ -13,6 +13,40 @@ struct FabricEventManager { }; +namespace +{ +enum class FabricEventAction : int { + PlaySound = 0, + StopSound = 1, + UnpauseSound = 3, + AdvanceSequence = 16, + StopAll = 21, + UnloadAudio = 23, + PlayScheduled = 33, +}; + +constexpr bool can_start_audio(int event_action) +{ + switch (static_cast(event_action)) { + case FabricEventAction::PlaySound: + case FabricEventAction::UnpauseSound: + case FabricEventAction::AdvanceSequence: + case FabricEventAction::PlayScheduled: + return true; + default: + return false; + } +} + +constexpr bool should_suppress_audio_event(bool disable_all, bool event_is_disabled, int event_action) +{ return disable_all ? can_start_audio(event_action) : event_is_disabled; } + +static_assert(should_suppress_audio_event(true, false, static_cast(FabricEventAction::PlaySound))); +static_assert(!should_suppress_audio_event(true, false, static_cast(FabricEventAction::StopSound))); +static_assert(should_suppress_audio_event(false, true, static_cast(FabricEventAction::StopAll))); +static_assert(!should_suppress_audio_event(true, true, static_cast(FabricEventAction::UnloadAudio))); +} // namespace + // Fabric.EventManager.PostEvent(string, EventAction, object, GameObject, // InitialiseParameters, bool, OnEventNotify) bool FabricEventManager_PostEvent_Hook(auto original, FabricEventManager* _this, Il2CppString* event_name, @@ -25,14 +59,16 @@ bool FabricEventManager_PostEvent_Hook(auto original, FabricEventManager* _this, add_to_queue, on_event_notify); } - const auto event = to_string(event_name); + const auto event = to_string(event_name); auto& config = Config::Get(); if (config.trace_audio_events) { spdlog::info("Audio event: {}", event); } - if (std::ranges::find(config.disabled_audio_events, event) != config.disabled_audio_events.end()) { + const bool event_is_disabled = + std::ranges::find(config.disabled_audio_events, event) != config.disabled_audio_events.end(); + if (should_suppress_audio_event(config.disable_all_audio_events, event_is_disabled, event_action)) { spdlog::debug("Suppressed audio event: {}", event); return false; } @@ -49,10 +85,19 @@ void InstallAudioEventHooks() return; } - // The shorter PostEvent overloads funnel into this seven-argument overload. - const auto method = helper.GetMethodInfo("PostEvent", 7); + // The shorter string PostEvent overloads funnel into this seven-argument overload. Select it by type because + // Fabric also has a seven-argument integer-ID overload with an incompatible native signature. + auto string_event_filter = [](int count, const Il2CppType** params) { + return count == 7 && params != nullptr && params[0] != nullptr && params[5] != nullptr + && params[0]->type == IL2CPP_TYPE_STRING && params[5]->type == IL2CPP_TYPE_BOOLEAN; + }; + const auto method = helper.GetMethodInfoSpecial("PostEvent", string_event_filter); if (method == nullptr || method->methodPointer == nullptr) { - ErrorMsg::MissingMethod("EventManager", "PostEvent"); + ErrorMsg::MissingMethod("EventManager", "PostEvent(string, ..., bool, ...)"); + return; + } + if (method->return_type == nullptr || method->return_type->type != IL2CPP_TYPE_BOOLEAN) { + spdlog::error("Fabric EventManager string PostEvent route has an unexpected return type"); return; }