Skip to content

Commit

Permalink
Fix multiple audio file overrides (#677)
Browse files Browse the repository at this point in the history
This basically prevents audio files from being loaded into memory if matching audio event has already been overriden by a previous mod, preventing a crash from occurring.

This means that audio mods now respect the load priority, i.e. mods with higher priority (= lower int value) will have priority over other mods on audio overrides.
  • Loading branch information
Alystrasz authored Jul 6, 2024
1 parent 3edcc91 commit 497945b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
31 changes: 28 additions & 3 deletions primedev/client/audio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <iostream>
#include <sstream>
#include <random>
#include <ranges>

AUTOHOOK_INIT()

Expand All @@ -28,7 +29,7 @@ unsigned char EMPTY_WAVE[45] = {0x52, 0x49, 0x46, 0x46, 0x25, 0x00, 0x00, 0x00,
0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x44, 0xAC, 0x00, 0x00, 0x88, 0x58,
0x01, 0x00, 0x02, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x74, 0x00, 0x00, 0x00, 0x00};

EventOverrideData::EventOverrideData(const std::string& data, const fs::path& path)
EventOverrideData::EventOverrideData(const std::string& data, const fs::path& path, const std::vector<std::string>& registeredEvents)
{
if (data.length() <= 0)
{
Expand Down Expand Up @@ -191,6 +192,14 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
{
std::string pathString = file.path().string();

// Retrieve event id from path (standard?)
std::string eventId = file.path().parent_path().filename().string();
if (std::find(registeredEvents.begin(), registeredEvents.end(), eventId) != registeredEvents.end())
{
spdlog::warn("{} couldn't be loaded because {} event has already been overrided, skipping.", pathString, eventId);
continue;
}

// Open the file.
std::ifstream wavStream(pathString, std::ios::binary);

Expand Down Expand Up @@ -259,7 +268,7 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
LoadedSuccessfully = true;
}

bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)
bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath, std::string modName)
{
if (IsDedicatedServer())
return true; // silently fail
Expand All @@ -279,19 +288,35 @@ bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)

jsonStream.close();

std::shared_ptr<EventOverrideData> data = std::make_shared<EventOverrideData>(jsonStringStream.str(), defPath);
// Pass the list of overriden events to avoid multiple event registrations crash
auto kv = std::views::keys(m_loadedAudioOverrides);
std::vector<std::string> keys {kv.begin(), kv.end()};
std::shared_ptr<EventOverrideData> data = std::make_shared<EventOverrideData>(jsonStringStream.str(), defPath, keys);

if (!data->LoadedSuccessfully)
return false; // no logging, the constructor has probably already logged

for (const std::string& eventId : data->EventIds)
{
if (m_loadedAudioOverrides.contains(eventId))
{
spdlog::warn("\"{}\" mod tried to override sound event \"{}\" but it is already overriden, skipping.", modName, eventId);
continue;
}
spdlog::info("Registering sound event {}", eventId);
m_loadedAudioOverrides.insert({eventId, data});
}

for (const auto& eventIdRegexData : data->EventIdsRegex)
{
if (m_loadedAudioOverridesRegex.contains(eventIdRegexData.first))
{
spdlog::warn(
"\"{}\" mod tried to override sound event regex \"{}\" but it is already overriden, skipping.",
modName,
eventIdRegexData.first);
continue;
}
spdlog::info("Registering sound event regex {}", eventIdRegexData.first);
m_loadedAudioOverridesRegex.insert({eventIdRegexData.first, data});
}
Expand Down
4 changes: 2 additions & 2 deletions primedev/client/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ enum class AudioSelectionStrategy
class EventOverrideData
{
public:
EventOverrideData(const std::string&, const fs::path&);
EventOverrideData(const std::string&, const fs::path&, const std::vector<std::string>& registeredEvents);
EventOverrideData();

public:
Expand All @@ -35,7 +35,7 @@ class EventOverrideData
class CustomAudioManager
{
public:
bool TryLoadAudioOverride(const fs::path&);
bool TryLoadAudioOverride(const fs::path&, std::string modName);
void ClearAudioOverrides();

std::shared_mutex m_loadingMutex;
Expand Down
2 changes: 1 addition & 1 deletion primedev/mods/modmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,7 @@ void ModManager::LoadMods()
{
if (fs::is_regular_file(file) && file.path().extension().string() == ".json")
{
if (!g_CustomAudioManager.TryLoadAudioOverride(file.path()))
if (!g_CustomAudioManager.TryLoadAudioOverride(file.path(), mod.Name))
{
spdlog::warn("Mod {} has an invalid audio def {}", mod.Name, file.path().filename().string());
continue;
Expand Down

0 comments on commit 497945b

Please sign in to comment.