From 2a20e0088ee4c05edd0b52d213272504e7d4c94e Mon Sep 17 00:00:00 2001 From: BobTheBob Date: Tue, 7 Mar 2023 13:03:25 +0000 Subject: add non-deferred reload --- NorthstarDLL/mods/modmanager.cpp | 38 +++++++++--- NorthstarDLL/mods/modmanager.h | 13 +++- NorthstarDLL/mods/reload/reloadmodweapons.cpp | 42 +++++++++++-- NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp | 72 ++++++++++++++++++++++ 4 files changed, 150 insertions(+), 15 deletions(-) (limited to 'NorthstarDLL/mods') diff --git a/NorthstarDLL/mods/modmanager.cpp b/NorthstarDLL/mods/modmanager.cpp index ab1ef791..6d36a975 100644 --- a/NorthstarDLL/mods/modmanager.cpp +++ b/NorthstarDLL/mods/modmanager.cpp @@ -294,7 +294,7 @@ ModManager::ModManager() m_LastModLoadState = nullptr; m_ModLoadState = new ModLoadState; - LoadMods(false); + LoadMods(false, false); } template auto ModConCommandCallback_Internal(std::string name, const CCommand& command) @@ -352,7 +352,7 @@ auto ModConCommandCallback(const CCommand& command) -void ModManager::LoadMods(bool bDeferredAssetReload) +void ModManager::LoadMods(bool bReloadAssets, bool bDeferredAssetReload) { // reset state of all currently loaded mods, if we've loaded once already if (m_bHasLoadedMods) @@ -366,7 +366,7 @@ void ModManager::LoadMods(bool bDeferredAssetReload) LoadModDefinitions(); // install mods (load all files) - InstallMods(bDeferredAssetReload); + InstallMods(bReloadAssets, bDeferredAssetReload); // write json storing currently enabled mods SaveEnabledMods(); @@ -1043,6 +1043,21 @@ void ModManager::ReloadNecessaryModAssets(bool bDeferred, const ModAssetsToReloa } else { + if (pAssetsToReload->bAimAssistSettings) + TryImmediateReloadADSPulls(); + + if (pAssetsToReload->bAmmoSuckBehaviours) + TryImmediateReloadAmmoSuckBehaviours(); + + if (pAssetsToReload->bDamageDefs) + TryImmediateReloadDamageFlags(); + + if (pAssetsToReload->bWeaponSprings) + TryImmediateReloadWeaponSprings(); + + TryImmediateReloadWeapons(pAssetsToReload->setsWeaponSettings); + + // need to reimplement mat_reloadmaterials for this // if (m_AssetTypesToReload.bMaterials) // R2::Cbuf_AddText(R2::Cbuf_GetCurrentPlayer(), "mat_reloadmaterials", R2::cmd_source_t::kCommandSrcCode); @@ -1057,7 +1072,7 @@ void ModManager::ReloadNecessaryModAssets(bool bDeferred, const ModAssetsToReloa R2::Cbuf_Execute(); } -void ModManager::InstallMods(bool bDeferredAssetReload) +void ModManager::InstallMods(bool bReloadAssets, bool bDeferredAssetReload) { for (Mod& mod : GetMods() | FilterEnabled) { @@ -1075,7 +1090,7 @@ void ModManager::InstallMods(bool bDeferredAssetReload) InstallModFileOverrides(mod); } - if (m_bHasLoadedMods) // only reload assets after initial load + if (m_bHasLoadedMods && bReloadAssets) // only reload assets after initial load { ModAssetsToReload assetsToReload; @@ -1183,12 +1198,20 @@ void ModManager::CompileAssetsForFile(const char* filename) void ConCommand_mods_reload(const CCommand& args) { - g_pModManager->LoadMods(false); + // reload assets now + g_pModManager->LoadMods(true, false); } void ConCommand_mods_reload_deferred(const CCommand& args) { - g_pModManager->LoadMods(true); + // reload assets later + g_pModManager->LoadMods(true, true); +} + +void ConCommand_mods_no_asset_reload(const CCommand& args) +{ + // reload assets never + g_pModManager->LoadMods(false, false); } void ConCommand_mods_getfileowner(const CCommand& args) @@ -1232,5 +1255,6 @@ ON_DLL_LOAD_RELIESON("engine.dll", ModManager, (ConCommand, MasterServer), (CMod RegisterConCommand("reload_mods", ConCommand_mods_reload, "reloads mods", FCVAR_NONE); RegisterConCommand("mods_reload", ConCommand_mods_reload, "reloads mods", FCVAR_NONE); RegisterConCommand("mods_reload_deferred", ConCommand_mods_reload_deferred, "reloads mods, prefers reloading assets on level load rather than now", FCVAR_NONE); + RegisterConCommand("mods_reload_no_asset_reload", ConCommand_mods_no_asset_reload, "reloads mods without trying to reload assets", FCVAR_NONE); RegisterConCommand("mods_getfileowner", ConCommand_mods_getfileowner, "find the mod that owns a given file", FCVAR_NONE); } diff --git a/NorthstarDLL/mods/modmanager.h b/NorthstarDLL/mods/modmanager.h index 9b194ea9..9eccffc5 100644 --- a/NorthstarDLL/mods/modmanager.h +++ b/NorthstarDLL/mods/modmanager.h @@ -141,7 +141,7 @@ class ModManager void LoadModDefinitions(); void SaveEnabledMods(); void BuildPublicModList(); - void InstallMods(bool bDeferredAssetReload); + void InstallMods(bool bReloadAssets, bool bDeferredAssetReload); struct ModAssetsToReload { @@ -203,7 +203,7 @@ class ModManager public: ModManager(); - void LoadMods(bool bDeferredAssetReload); + void LoadMods(bool bReloadAssets, bool bDeferredAssetReload); std::string NormaliseModFilePath(const fs::path path); void CompileAssetsForFile(const char* filename); @@ -235,7 +235,14 @@ class ModManager void DeferredReloadADSPulls(); void DeferredReloadWeapons(const std::unordered_set setsWeapons); - // asset reloading funcs + // hybrid asset reloading funcs (i.e. try reload on both client and server immediately, defer sides that aren't currently possible) + void TryImmediateReloadDamageFlags(); + void TryImmediateReloadWeaponSprings(); + void TryImmediateReloadAmmoSuckBehaviours(); + void TryImmediateReloadADSPulls(); + void TryImmediateReloadWeapons(const std::unordered_set setsWeapons); + + // individual asset reloading funcs bool TryReloadWeapon(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers); // for std::views::filter, e.g. for (Mod& mod : g_pModManager::GetMods() | ModManager::FilterEnabled) diff --git a/NorthstarDLL/mods/reload/reloadmodweapons.cpp b/NorthstarDLL/mods/reload/reloadmodweapons.cpp index 4619fb31..077c2835 100644 --- a/NorthstarDLL/mods/reload/reloadmodweapons.cpp +++ b/NorthstarDLL/mods/reload/reloadmodweapons.cpp @@ -1,4 +1,6 @@ #include "mods/modmanager.h" +#include "dedicated/dedicated.h" +#include "engine/r2engine.h" AUTOHOOK_INIT() @@ -23,9 +25,13 @@ OFFSET_STRUCT(GlobalWeaponDefs) VAR_AT(client.dll + 0xB33A02, uint16_t*, g_pnClientWeaponsLoaded); VAR_AT(client.dll + 0xB339E8, GlobalWeaponDefs**, g_ppClientWeaponDefs); +VAR_AT(server.dll + 0xBB57C2, uint16_t*, g_pnServerWeaponsLoaded); +VAR_AT(server.dll + 0xBB57A8, GlobalWeaponDefs**, g_ppServerWeaponDefs); FUNCTION_AT(client.dll + 0x3D2FB0, void,, ClientReparseWeapon, (WeaponDefinition* pWeapon)); FUNCTION_AT(client.dll + 0x3CE270, void,, ClientReloadWeaponCallbacks, (int nWeaponIndex)); +FUNCTION_AT(client.dll + 0x6D1170, void,, ServerReparseWeapon, (WeaponDefinition * pWeapon)); +FUNCTION_AT(client.dll + 0x6CCE80, void, , ServerReloadWeaponCallbacks, (int nWeaponIndex)); std::unordered_set setsClientWeaponsToReload; std::unordered_set setsServerWeaponsToReload; @@ -43,6 +49,7 @@ struct SidedWeaponReloadPointers void (*m_fnReparseWeapon)(WeaponDefinition* pWeapon); void (*m_fnReloadWeaponCallbacks)(int nWeaponIndex); + SidedWeaponReloadPointers() {} // don't use SidedWeaponReloadPointers( uint16_t* pnWeaponsLoaded, GlobalWeaponDefs** ppWeaponDefs, @@ -56,8 +63,7 @@ struct SidedWeaponReloadPointers m_fnReparseWeapon = fnReparseWeapon; m_fnReloadWeaponCallbacks = fnReloadWeaponCallbacks; } -}; - +} clientReloadPointers, serverReloadPointers; int WeaponIndexByName(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers) { @@ -81,6 +87,24 @@ void ModManager::DeferredReloadWeapons(const std::unordered_set set } } +void ModManager::TryImmediateReloadWeapons(const std::unordered_set setsWeapons) +{ + // try to reload all weapons on client and server, if we can't reload for any reason + // (either due to either side being inactive, or just failure to reload) + for (const std::string& sWeapon : setsWeapons) + { + if (!IsDedicatedServer()) + { + setsClientWeaponsToReload.insert(sWeapon); + // if this fails, the weapon will still be there for deferred reload + TryReloadWeapon(sWeapon.c_str(), &clientReloadPointers); + } + + setsServerWeaponsToReload.insert(sWeapon); + TryReloadWeapon(sWeapon.c_str(), &serverReloadPointers); + } +} + bool ModManager::TryReloadWeapon(const char* pWeaponName, const SidedWeaponReloadPointers* pReloadPointers) { if (!pReloadPointers->m_psetsWeaponsToReload->contains(pWeaponName)) @@ -108,9 +132,6 @@ AUTOHOOK(ClientPrecacheWeaponFromStringtable, client.dll + 0x195A60, bool, __fastcall, (void* a1, void* a2, void* a3, const char* pWeaponName)) // clang-format on { - static SidedWeaponReloadPointers clientReloadPointers( - g_pnClientWeaponsLoaded, g_ppClientWeaponDefs, &setsClientWeaponsToReload, ClientReparseWeapon, ClientReloadWeaponCallbacks); - if (g_pModManager->TryReloadWeapon(pWeaponName, &clientReloadPointers)) return true; @@ -119,6 +140,17 @@ bool, __fastcall, (void* a1, void* a2, void* a3, const char* pWeaponName)) } ON_DLL_LOAD_CLIENT("client.dll", ModReloadWeaponsClient, (CModule module)) +{ + AUTOHOOK_DISPATCH_MODULE(client.dll) + + clientReloadPointers = SidedWeaponReloadPointers( + g_pnClientWeaponsLoaded, g_ppClientWeaponDefs, &setsClientWeaponsToReload, ClientReparseWeapon, ClientReloadWeaponCallbacks); +} + +ON_DLL_LOAD_CLIENT("server.dll", ModReloadWeaponsServer, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(server.dll) + + serverReloadPointers = SidedWeaponReloadPointers( + g_pnServerWeaponsLoaded, g_ppServerWeaponDefs, &setsServerWeaponsToReload, ServerReparseWeapon, ServerReloadWeaponCallbacks); } diff --git a/NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp b/NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp index 5f43b11f..75503382 100644 --- a/NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp +++ b/NorthstarDLL/mods/reload/reloadmodweapons_misc.cpp @@ -1,4 +1,6 @@ #include "mods/modmanager.h" +#include "dedicated/dedicated.h" +#include "engine/r2engine.h" AUTOHOOK_INIT() @@ -9,11 +11,21 @@ VAR_AT(client.dll + 0x23EF0C6, bool*, g_pbClientHasLoadedWeaponSprings); VAR_AT(client.dll + 0x23EF0C7, bool*, g_pbClientHasLoadedWeaponAmmoSuckBehaviours); VAR_AT(client.dll + 0x23EF0C4, bool*, g_pbClientHasLoadedWeaponADSPulls); +FUNCTION_AT(client.dll + 0x3CDDF0, void,, ClientReparseDamageFlags, ()); // requires g_pbClientHasLoadedDamageFlags to be false +FUNCTION_AT(client.dll + 0x3CE5B0, void,, ClientReparseWeaponSprings, ()); +FUNCTION_AT(client.dll + 0x3CE060, void,, ClientReparseWeaponAmmoSuckBehaviours, ()); +FUNCTION_AT(client.dll + 0x3CD700, void,, ClientReparseWeaponADSPulls, ()); + VAR_AT(server.dll + 0x160B474, bool*, g_pbServerHasLoadedDamageFlags); VAR_AT(server.dll + 0x160B475, bool*, g_pbServerHasLoadedWeaponSprings); VAR_AT(server.dll + 0x160B476, bool*, g_pbServerHasLoadedWeaponAmmoSuckBehaviours); VAR_AT(server.dll + 0x160B477, bool*, g_pbServerHasLoadedWeaponADSPulls); +FUNCTION_AT(client.dll + 0x6CC9F0, void,, ServerReparseDamageFlags, ()); // requires g_pbClientHasLoadedDamageFlags to be false +FUNCTION_AT(client.dll + 0x6CD1C0, void,, ServerReparseWeaponSprings, ()); +FUNCTION_AT(client.dll + 0x6CCC70, void,, ServerReparseWeaponAmmoSuckBehaviours, ()); +FUNCTION_AT(client.dll + 0x6CC300, void,, ServerReparseWeaponADSPulls, ()); + void ModManager::DeferredReloadDamageFlags() { *g_pbClientHasLoadedDamageFlags = false; @@ -38,8 +50,68 @@ void ModManager::DeferredReloadADSPulls() *g_pbServerHasLoadedWeaponADSPulls = false; } +void ModManager::TryImmediateReloadDamageFlags() +{ + if (!IsDedicatedServer()) + { + *g_pbClientHasLoadedDamageFlags = false; + if (g_pSquirrel->m_pSQVM) + ClientReparseDamageFlags(); + } + + *g_pbServerHasLoadedDamageFlags = false; + if (*R2::g_pServerState == R2::ss_active) + ServerReparseDamageFlags(); +} + +void ModManager::TryImmediateReloadWeaponSprings() +{ + if (!IsDedicatedServer()) + { + *g_pbClientHasLoadedWeaponSprings = false; + if (g_pSquirrel->m_pSQVM) + ClientReparseWeaponSprings(); + } + + *g_pbServerHasLoadedWeaponSprings = false; + if (*R2::g_pServerState == R2::ss_active) + ServerReparseWeaponSprings(); +} + +void ModManager::TryImmediateReloadAmmoSuckBehaviours() +{ + if (!IsDedicatedServer()) + { + *g_pbClientHasLoadedWeaponAmmoSuckBehaviours = false; + if (g_pSquirrel->m_pSQVM) + ClientReparseWeaponAmmoSuckBehaviours(); + } + + *g_pbServerHasLoadedWeaponAmmoSuckBehaviours = false; + if (*R2::g_pServerState == R2::ss_active) + ServerReparseWeaponAmmoSuckBehaviours(); +} + +void ModManager::TryImmediateReloadADSPulls() +{ + if (!IsDedicatedServer()) + { + *g_pbClientHasLoadedWeaponADSPulls = false; + if (g_pSquirrel->m_pSQVM) + ClientReparseWeaponADSPulls(); + } + + *g_pbServerHasLoadedWeaponADSPulls = false; + if (*R2::g_pServerState == R2::ss_active) + ServerReparseWeaponADSPulls(); +} ON_DLL_LOAD_CLIENT("client.dll", ClientModReloadWeaponsMisc, (CModule module)) { AUTOHOOK_DISPATCH_MODULE(client.dll) } + +ON_DLL_LOAD_CLIENT("server.dll", ServerModReloadWeaponsMisc, (CModule module)) +{ + AUTOHOOK_DISPATCH_MODULE(server.dll) +} -- cgit v1.2.3