diff options
-rw-r--r-- | NorthstarDLL/mods/modmanager.cpp | 121 | ||||
-rw-r--r-- | NorthstarDLL/mods/modmanager.h | 45 | ||||
-rw-r--r-- | NorthstarDLL/mods/reload/reloadmodweapons.cpp | 24 |
3 files changed, 92 insertions, 98 deletions
diff --git a/NorthstarDLL/mods/modmanager.cpp b/NorthstarDLL/mods/modmanager.cpp index 0203a66e..ab1ef791 100644 --- a/NorthstarDLL/mods/modmanager.cpp +++ b/NorthstarDLL/mods/modmanager.cpp @@ -828,7 +828,7 @@ void ModManager::InstallModFileOverrides(Mod& mod) } #pragma endregion -void ModManager::CheckModFilesForChanges() +void ModManager::CheckModFilesForChanges(ModAssetsToReload* pAssetsToReload) { // normal mod files { @@ -860,21 +860,21 @@ void ModManager::CheckModFilesForChanges() if (!IsDedicatedServer()) { // could check localisation here? but what's the point, localisation shouldn't be in mod fs - // if (m_AssetTypesToReload.bLocalisation) + // if (pAssetsToReload->bLocalisation) - if (!m_AssetTypesToReload.bAimAssistSettings && pChangedFile->m_Path.parent_path().string().starts_with("cfg/aimassist/")) + if (!pAssetsToReload->bAimAssistSettings && pChangedFile->m_Path.parent_path().string().starts_with("cfg/aimassist/")) { - m_AssetTypesToReload.bAimAssistSettings = true; + pAssetsToReload->bAimAssistSettings = true; continue; } - if (!m_AssetTypesToReload.bMaterials && pChangedFile->m_Path.parent_path().string().starts_with("materials/")) + if (!pAssetsToReload->bMaterials && pChangedFile->m_Path.parent_path().string().starts_with("materials/")) { - m_AssetTypesToReload.bMaterials = true; + pAssetsToReload->bMaterials = true; continue; } - if (!m_AssetTypesToReload.bUiScript) + if (!pAssetsToReload->bUiScript) { // TODO: need to check whether any ui scripts have changed @@ -882,42 +882,40 @@ void ModManager::CheckModFilesForChanges() if (pChangedFile->m_Path.parent_path().string().starts_with("resource/ui/")) { - m_AssetTypesToReload.bUiScript = true; + pAssetsToReload->bUiScript = true; continue; } } } - if (!m_AssetTypesToReload.bModels && pChangedFile->m_Path.parent_path().string().starts_with("models/")) + if (!pAssetsToReload->bModels && pChangedFile->m_Path.parent_path().string().starts_with("models/")) { - m_AssetTypesToReload.bModels = true; + pAssetsToReload->bModels = true; continue; } - // could also check this but no point as it should only be changed from mod keyvalues - - if (!m_AssetTypesToReload.bPlayerSettings && pChangedFile->m_Path.parent_path().string().starts_with("scripts/players/")) + if (!pAssetsToReload->bPlayerSettings && pChangedFile->m_Path.parent_path().string().starts_with("scripts/players/")) { - m_AssetTypesToReload.bPlayerSettings = true; + pAssetsToReload->bPlayerSettings = true; continue; } // maybe also aibehaviour? - if (!m_AssetTypesToReload.bAiSettings && pChangedFile->m_Path.parent_path().string().starts_with("scripts/aisettings/")) + if (!pAssetsToReload->bAiSettings && pChangedFile->m_Path.parent_path().string().starts_with("scripts/aisettings/")) { - m_AssetTypesToReload.bAiSettings = true; + pAssetsToReload->bAiSettings = true; continue; } - if (!m_AssetTypesToReload.bDamageDefs && pChangedFile->m_Path.parent_path().string().starts_with("scripts/damage/")) + if (!pAssetsToReload->bDamageDefs && pChangedFile->m_Path.parent_path().string().starts_with("scripts/damage/")) { - m_AssetTypesToReload.bDamageDefs = true; + pAssetsToReload->bDamageDefs = true; continue; } - if (m_AssetTypesToReload.bDatatables && pChangedFile->m_Path.parent_path().string().starts_with("scripts/datatable/")) + if (pAssetsToReload->bDatatables && pChangedFile->m_Path.parent_path().string().starts_with("scripts/datatable/")) { - m_AssetTypesToReload.bDatatables = true; + pAssetsToReload->bDatatables = true; continue; } } @@ -962,38 +960,38 @@ void ModManager::CheckModFilesForChanges() { fs::path fChangedPath(sChangedPath); - if (!m_AssetTypesToReload.bPlaylists && fChangedPath == "playlists_v2.txt") + if (!pAssetsToReload->bPlaylists && fChangedPath == "playlists_v2.txt") { - m_AssetTypesToReload.bPlaylists = true; + pAssetsToReload->bPlaylists = true; continue; } - if (!m_AssetTypesToReload.bPlayerSettings && fChangedPath.parent_path().string().starts_with("scripts/players/")) + if (!pAssetsToReload->bPlayerSettings && fChangedPath.parent_path().string().starts_with("scripts/players/")) { - m_AssetTypesToReload.bPlayerSettings = true; + pAssetsToReload->bPlayerSettings = true; continue; } - if (!m_AssetTypesToReload.bAiSettings && fChangedPath.parent_path().string().starts_with("scripts/aisettings/")) + if (!pAssetsToReload->bAiSettings && fChangedPath.parent_path().string().starts_with("scripts/aisettings/")) { - m_AssetTypesToReload.bAiSettings = true; + pAssetsToReload->bAiSettings = true; continue; } - if (!m_AssetTypesToReload.bDamageDefs && fChangedPath.parent_path().string().starts_with("scripts/damage/")) + if (!pAssetsToReload->bDamageDefs && fChangedPath.parent_path().string().starts_with("scripts/damage/")) { - m_AssetTypesToReload.bDamageDefs = true; + pAssetsToReload->bDamageDefs = true; continue; } if (!fChangedPath.parent_path().string().starts_with("scripts/weapons/")) { if (fChangedPath.filename() == "ammo_suck_behaviours.txt") - m_AssetTypesToReload.bAmmoSuckBehaviours = true; + pAssetsToReload->bAmmoSuckBehaviours = true; else if (fChangedPath.filename() == "springs.txt") - m_AssetTypesToReload.bWeaponSprings = true; + pAssetsToReload->bWeaponSprings = true; else - m_AssetTypesToReload.setsWeaponSettings.insert(fChangedPath.replace_extension().string()); + pAssetsToReload->setsWeaponSettings.insert(fChangedPath.replace_extension().string()); continue; } @@ -1001,27 +999,27 @@ void ModManager::CheckModFilesForChanges() } } -void ModManager::ReloadNecessaryModAssets(bool bDeferred) +void ModManager::ReloadNecessaryModAssets(bool bDeferred, const ModAssetsToReload* pAssetsToReload) { std::vector<std::string> vReloadCommands; - if (m_AssetTypesToReload.bLocalisation) + if (pAssetsToReload->bLocalisation) vReloadCommands.push_back("reload_localization"); // after we reload_localization, we need to loadPlaylists, to keep playlist localisation - if (m_AssetTypesToReload.bPlaylists || m_AssetTypesToReload.bLocalisation) + if (pAssetsToReload->bPlaylists || pAssetsToReload->bLocalisation) vReloadCommands.push_back("loadPlaylists"); - if (m_AssetTypesToReload.bUiScript) + if (pAssetsToReload->bUiScript) vReloadCommands.push_back("uiscript_reset"); - if (m_AssetTypesToReload.bAimAssistSettings) + if (pAssetsToReload->bAimAssistSettings) vReloadCommands.push_back("ReloadAimAssistSettings"); - if (m_AssetTypesToReload.bModels) + if (pAssetsToReload->bModels) spdlog::warn("Need to reload models but can't without a restart!"); - if (m_AssetTypesToReload.bDatatables) + if (pAssetsToReload->bDatatables) { // TODO: clear disk datatable cache in scriptdatatables.cpp } @@ -1029,27 +1027,27 @@ void ModManager::ReloadNecessaryModAssets(bool bDeferred) // deferred - load files using engine functions where possible, on level load if (bDeferred) { - if (m_AssetTypesToReload.bAimAssistSettings) + if (pAssetsToReload->bAimAssistSettings) DeferredReloadADSPulls(); - if (m_AssetTypesToReload.bAmmoSuckBehaviours) + if (pAssetsToReload->bAmmoSuckBehaviours) DeferredReloadAmmoSuckBehaviours(); - if (m_AssetTypesToReload.bDamageDefs) + if (pAssetsToReload->bDamageDefs) DeferredReloadDamageFlags(); - if (m_AssetTypesToReload.bWeaponSprings) + if (pAssetsToReload->bWeaponSprings) DeferredReloadWeaponSprings(); + + DeferredReloadWeapons(pAssetsToReload->setsWeaponSettings); } else { - + // need to reimplement mat_reloadmaterials for this + // if (m_AssetTypesToReload.bMaterials) + // R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "mat_reloadmaterials", R2::cmd_source_t::kCommandSrcCode); } - // need to reimplement mat_reloadmaterials for this - //if (m_AssetTypesToReload.bMaterials) - // R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "mat_reloadmaterials", R2::cmd_source_t::kCommandSrcCode); - for (std::string& sReloadCommand : vReloadCommands) { spdlog::info("Executing command {} for asset reload", sReloadCommand); @@ -1057,17 +1055,6 @@ void ModManager::ReloadNecessaryModAssets(bool bDeferred) } R2::Cbuf_Execute(); - - // reset everything we've already reloaded at this point - m_AssetTypesToReload.bUiScript = false; - m_AssetTypesToReload.bLocalisation = false; - m_AssetTypesToReload.bPlaylists = false; - m_AssetTypesToReload.bAimAssistSettings = false; - m_AssetTypesToReload.bDatatables = false; - m_AssetTypesToReload.bModels = false; - m_AssetTypesToReload.bAmmoSuckBehaviours = false; - m_AssetTypesToReload.bDamageDefs = false; - m_AssetTypesToReload.bWeaponSprings = false; } void ModManager::InstallMods(bool bDeferredAssetReload) @@ -1090,8 +1077,10 @@ void ModManager::InstallMods(bool bDeferredAssetReload) if (m_bHasLoadedMods) // only reload assets after initial load { - CheckModFilesForChanges(); - ReloadNecessaryModAssets(bDeferredAssetReload); + ModAssetsToReload assetsToReload; + + CheckModFilesForChanges(&assetsToReload); + ReloadNecessaryModAssets(bDeferredAssetReload, &assetsToReload); } } @@ -1147,18 +1136,6 @@ void ModManager::UnloadMods() m_LastModLoadState = m_ModLoadState; m_ModLoadState = new ModLoadState; - // reset assets to reload - m_AssetTypesToReload.bUiScript = false; - m_AssetTypesToReload.bLocalisation = false; - m_AssetTypesToReload.bPlaylists = false; - m_AssetTypesToReload.bAimAssistSettings = false; - m_AssetTypesToReload.bMaterials = false; - m_AssetTypesToReload.bRPaks = false; - m_AssetTypesToReload.bPlayerSettings = false; - m_AssetTypesToReload.bAiSettings = false; - m_AssetTypesToReload.bDamageDefs = false; - m_AssetTypesToReload.bModels = false; - // clean up stuff from mods before we unload fs::remove_all(GetCompiledAssetsPath()); diff --git a/NorthstarDLL/mods/modmanager.h b/NorthstarDLL/mods/modmanager.h index 73d6cb3c..9b194ea9 100644 --- a/NorthstarDLL/mods/modmanager.h +++ b/NorthstarDLL/mods/modmanager.h @@ -132,7 +132,6 @@ class ModManager { private: bool m_bHasLoadedMods = false; - bool m_bHasEnabledModsCfg; // precalculated hashes size_t m_hScriptsRsonHash; @@ -144,23 +143,7 @@ class ModManager void BuildPublicModList(); void InstallMods(bool bDeferredAssetReload); - // mod installation funcs - void InstallModCvars(Mod& mod); - void InstallModVpks(Mod& mod); - void InstallModRpaks(Mod& mod); - void InstallModKeyValues(Mod& mod); - void InstallModBinks(Mod& mod); - void InstallModAudioOverrides(Mod& mod); - - void InstallModFileOverrides(Mod& mod); - - void UnloadMods(); - - std::unordered_set<ConVar*> m_RegisteredModConVars; - std::unordered_set<ConCommand*> m_RegisteredModConCommands; - - - struct + struct ModAssetsToReload { // assets types we need to reload completely after mods are reloaded (can't reload individually) bool bUiScript = false; // also includes .menu files @@ -181,12 +164,27 @@ class ModManager bool bRPaks = false; // assets that we can reload individually - std::unordered_set<std::string> setsWeaponSettings; - //std::vector<ModAudioOverride> vAudioOverrides - } m_AssetTypesToReload; + std::unordered_set<std::string> setsWeaponSettings = {}; + // std::vector<ModAudioOverride> vAudioOverrides + }; + + // mod installation funcs + void InstallModCvars(Mod& mod); + void InstallModVpks(Mod& mod); + void InstallModRpaks(Mod& mod); + void InstallModKeyValues(Mod& mod); + void InstallModBinks(Mod& mod); + void InstallModAudioOverrides(Mod& mod); + void InstallModFileOverrides(Mod& mod); + + void UnloadMods(); + + std::unordered_set<ConVar*> m_RegisteredModConVars; + std::unordered_set<ConCommand*> m_RegisteredModConCommands; + - void CheckModFilesForChanges(); - void ReloadNecessaryModAssets(bool bDeferred); + void CheckModFilesForChanges(ModAssetsToReload* pAssetsToReload); + void ReloadNecessaryModAssets(bool bDeferred, const ModAssetsToReload* pAssetsToReload); struct ModLoadState @@ -235,6 +233,7 @@ class ModManager void DeferredReloadWeaponSprings(); void DeferredReloadAmmoSuckBehaviours(); void DeferredReloadADSPulls(); + void DeferredReloadWeapons(const std::unordered_set<std::string> setsWeapons); // asset reloading funcs bool TryReloadWeapon(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers); diff --git a/NorthstarDLL/mods/reload/reloadmodweapons.cpp b/NorthstarDLL/mods/reload/reloadmodweapons.cpp index 1384621a..4619fb31 100644 --- a/NorthstarDLL/mods/reload/reloadmodweapons.cpp +++ b/NorthstarDLL/mods/reload/reloadmodweapons.cpp @@ -27,6 +27,9 @@ VAR_AT(client.dll + 0xB339E8, GlobalWeaponDefs**, g_ppClientWeaponDefs); FUNCTION_AT(client.dll + 0x3D2FB0, void,, ClientReparseWeapon, (WeaponDefinition* pWeapon)); FUNCTION_AT(client.dll + 0x3CE270, void,, ClientReloadWeaponCallbacks, (int nWeaponIndex)); +std::unordered_set<std::string> setsClientWeaponsToReload; +std::unordered_set<std::string> setsServerWeaponsToReload; + // used for passing client/server funcs/data/pointers to TryReloadWeapon struct SidedWeaponReloadPointers { @@ -34,6 +37,8 @@ struct SidedWeaponReloadPointers uint16_t* m_pnWeaponsLoaded; GlobalWeaponDefs** m_ppWeaponDefs; + std::unordered_set<std::string>* m_psetsWeaponsToReload; + // funcs void (*m_fnReparseWeapon)(WeaponDefinition* pWeapon); void (*m_fnReloadWeaponCallbacks)(int nWeaponIndex); @@ -41,16 +46,19 @@ struct SidedWeaponReloadPointers SidedWeaponReloadPointers( uint16_t* pnWeaponsLoaded, GlobalWeaponDefs** ppWeaponDefs, + std::unordered_set<std::string>* psetsWeaponsToReload, void (*fnReparseWeapon)(WeaponDefinition*), void (*fnReloadWeaponCallbacks)(int)) { m_pnWeaponsLoaded = pnWeaponsLoaded; m_ppWeaponDefs = ppWeaponDefs; + m_psetsWeaponsToReload = psetsWeaponsToReload; m_fnReparseWeapon = fnReparseWeapon; m_fnReloadWeaponCallbacks = fnReloadWeaponCallbacks; } }; + int WeaponIndexByName(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers) { for (int i = 0; i < *pReloadPointers->m_pnWeaponsLoaded; i++) @@ -63,9 +71,19 @@ int WeaponIndexByName(const char* pWeaponName, const SidedWeaponReloadPointers* return -1; } +void ModManager::DeferredReloadWeapons(const std::unordered_set<std::string> setsWeapons) +{ + // if there's still weapons that need reloading, then keep them, just reload the new stuff + for (const std::string& sWeapon : setsWeapons) + { + setsClientWeaponsToReload.insert(sWeapon); + setsServerWeaponsToReload.insert(sWeapon); + } +} + bool ModManager::TryReloadWeapon(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers) { - if (!m_AssetTypesToReload.setsWeaponSettings.contains(pWeaponName)) + if (!pReloadPointers->m_psetsWeaponsToReload->contains(pWeaponName)) return false; // don't reload int nWeaponIndex = WeaponIndexByName(pWeaponName, pReloadPointers); @@ -80,7 +98,7 @@ bool ModManager::TryReloadWeapon(const char* pWeaponName, const SidedWeaponReloa if (bReloadScriptFuncs) pReloadPointers->m_fnReloadWeaponCallbacks(nWeaponIndex); - m_AssetTypesToReload.setsWeaponSettings.erase(pWeaponName); + pReloadPointers->m_psetsWeaponsToReload->erase(pWeaponName); return true; } @@ -91,7 +109,7 @@ bool, __fastcall, (void* a1, void* a2, void* a3, const char* pWeaponName)) // clang-format on { static SidedWeaponReloadPointers clientReloadPointers( - g_pnClientWeaponsLoaded, g_ppClientWeaponDefs, ClientReparseWeapon, ClientReloadWeaponCallbacks); + g_pnClientWeaponsLoaded, g_ppClientWeaponDefs, &setsClientWeaponsToReload, ClientReparseWeapon, ClientReloadWeaponCallbacks); if (g_pModManager->TryReloadWeapon(pWeaponName, &clientReloadPointers)) return true; |