Skip to content

Commit 497945b

Browse files
authored
Fix multiple audio file overrides (#677)
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.
1 parent 3edcc91 commit 497945b

File tree

3 files changed

+31
-6
lines changed

3 files changed

+31
-6
lines changed

primedev/client/audio.cpp

+28-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <iostream>
88
#include <sstream>
99
#include <random>
10+
#include <ranges>
1011

1112
AUTOHOOK_INIT()
1213

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

31-
EventOverrideData::EventOverrideData(const std::string& data, const fs::path& path)
32+
EventOverrideData::EventOverrideData(const std::string& data, const fs::path& path, const std::vector<std::string>& registeredEvents)
3233
{
3334
if (data.length() <= 0)
3435
{
@@ -191,6 +192,14 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
191192
{
192193
std::string pathString = file.path().string();
193194

195+
// Retrieve event id from path (standard?)
196+
std::string eventId = file.path().parent_path().filename().string();
197+
if (std::find(registeredEvents.begin(), registeredEvents.end(), eventId) != registeredEvents.end())
198+
{
199+
spdlog::warn("{} couldn't be loaded because {} event has already been overrided, skipping.", pathString, eventId);
200+
continue;
201+
}
202+
194203
// Open the file.
195204
std::ifstream wavStream(pathString, std::ios::binary);
196205

@@ -259,7 +268,7 @@ EventOverrideData::EventOverrideData(const std::string& data, const fs::path& pa
259268
LoadedSuccessfully = true;
260269
}
261270

262-
bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)
271+
bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath, std::string modName)
263272
{
264273
if (IsDedicatedServer())
265274
return true; // silently fail
@@ -279,19 +288,35 @@ bool CustomAudioManager::TryLoadAudioOverride(const fs::path& defPath)
279288

280289
jsonStream.close();
281290

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

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

287299
for (const std::string& eventId : data->EventIds)
288300
{
301+
if (m_loadedAudioOverrides.contains(eventId))
302+
{
303+
spdlog::warn("\"{}\" mod tried to override sound event \"{}\" but it is already overriden, skipping.", modName, eventId);
304+
continue;
305+
}
289306
spdlog::info("Registering sound event {}", eventId);
290307
m_loadedAudioOverrides.insert({eventId, data});
291308
}
292309

293310
for (const auto& eventIdRegexData : data->EventIdsRegex)
294311
{
312+
if (m_loadedAudioOverridesRegex.contains(eventIdRegexData.first))
313+
{
314+
spdlog::warn(
315+
"\"{}\" mod tried to override sound event regex \"{}\" but it is already overriden, skipping.",
316+
modName,
317+
eventIdRegexData.first);
318+
continue;
319+
}
295320
spdlog::info("Registering sound event regex {}", eventIdRegexData.first);
296321
m_loadedAudioOverridesRegex.insert({eventIdRegexData.first, data});
297322
}

primedev/client/audio.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ enum class AudioSelectionStrategy
1515
class EventOverrideData
1616
{
1717
public:
18-
EventOverrideData(const std::string&, const fs::path&);
18+
EventOverrideData(const std::string&, const fs::path&, const std::vector<std::string>& registeredEvents);
1919
EventOverrideData();
2020

2121
public:
@@ -35,7 +35,7 @@ class EventOverrideData
3535
class CustomAudioManager
3636
{
3737
public:
38-
bool TryLoadAudioOverride(const fs::path&);
38+
bool TryLoadAudioOverride(const fs::path&, std::string modName);
3939
void ClearAudioOverrides();
4040

4141
std::shared_mutex m_loadingMutex;

primedev/mods/modmanager.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,7 @@ void ModManager::LoadMods()
972972
{
973973
if (fs::is_regular_file(file) && file.path().extension().string() == ".json")
974974
{
975-
if (!g_CustomAudioManager.TryLoadAudioOverride(file.path()))
975+
if (!g_CustomAudioManager.TryLoadAudioOverride(file.path(), mod.Name))
976976
{
977977
spdlog::warn("Mod {} has an invalid audio def {}", mod.Name, file.path().filename().string());
978978
continue;

0 commit comments

Comments
 (0)