Skip to content

Commit b3da7d8

Browse files
committed
Handle loading and unloading modules at runtime
1 parent e862789 commit b3da7d8

File tree

3 files changed

+47
-2
lines changed

3 files changed

+47
-2
lines changed

Managers/ModuleMan.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ namespace RTE {
1818

1919
void ModuleMan::Clear() {
2020
m_LoadedDataModules.clear();
21+
m_UnloadedDataModules.clear();
2122
m_DisabledDataModuleNames.clear();
2223
}
2324

@@ -27,6 +28,9 @@ namespace RTE {
2728
for (const auto &[moduleID, dataModule] : m_LoadedDataModules) {
2829
delete dataModule;
2930
}
31+
for (const auto &[moduleID, dataModule] : m_UnloadedDataModules) {
32+
delete dataModule;
33+
}
3034
Clear();
3135
}
3236

@@ -147,8 +151,20 @@ namespace RTE {
147151
return false;
148152
}
149153

154+
// First check that we aren't trying to load another module with the same name. If not, check the unloaded map and load from there if it exists.
150155
if (const DataModule *dataModule = GetDataModule(GetModuleID(moduleName)); dataModule) {
151156
return true;
157+
} else if (moduleType == DataModule::DataModuleType::Unofficial) {
158+
auto unloadedModulesItr = std::find_if(m_UnloadedDataModules.begin(), m_UnloadedDataModules.end(),
159+
[&moduleName](const auto &unloadedModuleEntry) {
160+
return unloadedModuleEntry.second->GetFileName() == moduleName;
161+
}
162+
);
163+
if (unloadedModulesItr != m_UnloadedDataModules.end()) {
164+
m_LoadedDataModules.emplace(*unloadedModulesItr);
165+
m_UnloadedDataModules.erase(unloadedModulesItr);
166+
return true;
167+
}
152168
}
153169

154170
// Only instantiate it here, because it needs to be in the lists of this before being created.
@@ -165,6 +181,27 @@ namespace RTE {
165181
return true;
166182
}
167183

184+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
185+
186+
bool ModuleMan::UnloadDataModule(const std::string &moduleName) {
187+
if (!IsModuleOfficial(moduleName) && !IsModuleUserdata(moduleName)) {
188+
auto loadedModulesItr = std::find_if(m_LoadedDataModules.begin(), m_LoadedDataModules.end(),
189+
[&moduleName](const auto &loadedModuleEntry) {
190+
return loadedModuleEntry.second->GetFileName() == moduleName;
191+
}
192+
);
193+
194+
if (loadedModulesItr != m_LoadedDataModules.end()) {
195+
m_UnloadedDataModules.emplace(*loadedModulesItr);
196+
m_LoadedDataModules.erase(loadedModulesItr);
197+
return true;
198+
}
199+
} else {
200+
g_ConsoleMan.PrintString("Official and Userdata modules cannot be unloaded!");
201+
}
202+
return false;
203+
}
204+
168205
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
169206

170207
bool ModuleMan::LoadAllDataModules() {

Managers/ModuleMan.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,20 +141,26 @@ namespace RTE {
141141
/// <returns>Whether the DataModule was read and added correctly.</returns>
142142
bool LoadDataModule(const std::string &moduleName, DataModule::DataModuleType moduleType, const ProgressCallback &progressCallback = nullptr);
143143

144+
/// <summary>
145+
/// Unloads a DataModule by removing it from the loaded modules list. Does not actually erase it from memory.
146+
/// </summary>
147+
/// <param name="moduleName">The DataModule name to unload.</param>
148+
/// <returns>Whether the DataModule was successfully unloaded.</returns>
149+
bool UnloadDataModule(const std::string &moduleName);
150+
144151
/// <summary>
145152
/// Loads all the official data modules individually with LoadDataModule, then proceeds to look for any non-official modules and loads them as well.
146153
/// </summary>
147154
bool LoadAllDataModules();
148155
#pragma endregion
149156

150-
151-
152157
private:
153158

154159
static const std::array<std::string, 10> c_OfficialModules; //!< Array storing the names of all the official modules.
155160
static const std::array<std::pair<std::string, std::string>, 3> c_UserdataModules; //!< Array storing the names of all the userdata modules.
156161

157162
std::unordered_map<int, DataModule *> m_LoadedDataModules; //!< Map of all loaded DataModules by their ID. Owned by this.
163+
std::unordered_map<int, DataModule *> m_UnloadedDataModules; //!< Map of DataModules that are loaded but disabled through the Mod Manager GUI. Treated as not loaded at all.
158164

159165
std::unordered_set<std::string> m_DisabledDataModuleNames; //!< The DataModule names that are disabled and should not be loaded at startup.
160166
std::string m_SingleModuleToLoad; //!< Name of the single module to load after the official modules.

Menus/ModManagerGUI.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,11 @@ namespace RTE {
117117
if (modRecord.Enabled) {
118118
m_ToggleModButton->SetText("Disable Mod");
119119
disabledModsList.erase(disabledModsList.find(modRecord.ModulePath));
120+
g_ModuleMan.LoadDataModule(modRecord.ModulePath, DataModule::DataModuleType::Unofficial, nullptr);
120121
} else {
121122
m_ToggleModButton->SetText("Enable Mod");
122123
disabledModsList.emplace(modRecord.ModulePath);
124+
g_ModuleMan.UnloadDataModule(modRecord.ModulePath);
123125
}
124126
selectedItem->m_Name = modRecord.GetDisplayString();
125127
m_ModsListBox->SetSelectedIndex(index);

0 commit comments

Comments
 (0)