2
0
mirror of https://github.com/rehlds/metamod-r.git synced 2025-02-04 17:50:52 +03:00

Gracefully shutdown metamod and plugins when game is closing (for a proper reload using _restart command)

This commit is contained in:
s1lentq 2023-11-28 16:28:55 +07:00
parent adc94141a4
commit ec926a611f
8 changed files with 46 additions and 14 deletions

View File

@ -12,8 +12,11 @@ NEW_DLL_FUNCTIONS sNewFunctionTable;
NEW_DLL_FUNCTIONS sNewFunctionTable_jit;
NEW_DLL_FUNCTIONS *pHookedNewDllFunctions = &sNewFunctionTable;
void MM_PRE_HOOK EXT_FUNC mm_GameShutdown()
// Unload game DLL and meta plugins
void MM_POST_HOOK EXT_FUNC mm_GameShutdown()
{
g_metamod_active = false;
if (g_plugins) g_plugins->unload_all();
g_meta_extdll.unload();
g_GameDLL.sys_module.unload();
g_engine.sys_module.unload();
@ -130,7 +133,7 @@ compile_data_t g_dllfunc_cdata[] =
compile_data_t g_newdllfunc_cdata[] =
{
CDATA_NEWDLL(pfnOnFreeEntPrivateData), // Called right before the object's memory is freed. Calls its destructor.
CDATA_NEWDLL_H(pfnGameShutdown, P_PRE, mm_GameShutdown), //
CDATA_NEWDLL_H(pfnGameShutdown, P_POST, mm_GameShutdown), //
CDATA_NEWDLL(pfnShouldCollide), //
CDATA_NEWDLL(pfnCvarValue), // (fz) Use mm_CvarValue2 instead

View File

@ -32,6 +32,8 @@ unsigned int g_CALL_API_count = 0;
int g_requestid_counter = 0;
bool g_metamod_active = false;
// Very first metamod function that's run.
// Do startup operations...
void metamod_startup()
@ -61,6 +63,8 @@ void metamod_startup()
Sys_Error("Failure to init game DLL; exiting...");
}
g_metamod_active = true;
// Register various console commands and cvars.
// Can I do these here, rather than waiting for GameDLLInit() ?
// Looks like it works okay..
@ -509,6 +513,8 @@ static void meta_apply_fix_data(std::vector<fixdata_t>& data)
void meta_rebuild_callbacks()
{
if (!g_metamod_active) return;
std::vector<fixdata_t> fixdata;
if (g_metaGlobals.esp_save) {
META_LOG("dll: Begin scan to collect callback fix data...");

View File

@ -74,6 +74,8 @@ extern unsigned int g_CALL_API_count;
// stores previous requestid counter
extern int g_requestid_counter;
extern bool g_metamod_active;
// (patch by BAILOPAN)
// Holds cached player info, right now only things for querying cvars
// Max players is always 32, small enough that we can use a static array

View File

@ -573,6 +573,15 @@ void MPluginList::unpause_all()
}
}
// Unload all plugins currently loaded
void MPluginList::unload_all()
{
bool delayed;
for (auto p : m_plugins) {
p->unload(PT_ANYTIME, PNL_CMD_FORCED, delayed);
}
}
// Retry any pending actions on plugins, for instance load/unload delayed
// until changelevel.
void MPluginList::retry_all(PLUG_LOADTIME now)

View File

@ -35,6 +35,7 @@ public:
bool load(); // load the list, at startup
bool refresh(PLUG_LOADTIME now); // update from re-read inifile
void unpause_all(); // unpause any paused plugins
void unload_all(); // unload all plugins
void retry_all(PLUG_LOADTIME now); // retry any pending plugin actions
void show(int source_index = 0); // list plugins to console use dynamic alignment
void show_static(int source_index = 0); // list plugins to console use static alignment

View File

@ -471,7 +471,7 @@ bool MPlugin::unload(PLUG_LOADTIME now, PL_UNLOAD_REASON reason, bool& delayed)
return false;
}
}
if (m_action != PA_UNLOAD && m_action != PA_RELOAD) {
if (m_action != PA_UNLOAD && m_action != PA_RELOAD && reason != PNL_CMD_FORCED) {
META_WARNING("dll: Not unloading plugin '%s'; not marked for unload (action=%s)", m_desc, str_action());
return false;
}

View File

@ -64,17 +64,21 @@ MRegCmd* MRegCmdList::add(const char* addname, REG_CMD_FN cmd_handler, MPlugin*
void MRegCmdList::remove(char* cmd_name)
{
for (auto it = m_list.begin(), end = m_list.end(); it != end; ++it) {
for (auto it = m_list.begin(); it != m_list.end(); ) {
auto reg = *it;
if (!Q_stricmp(reg->m_name, cmd_name)) {
if (g_RehldsFuncs) {
g_RehldsFuncs->Cmd_RemoveCmd(cmd_name);
m_list.erase(it);
delete reg;
it = m_list.erase(it);
}
else {
reg->disable();
it++;
}
} else {
it++;
}
}
}
@ -82,17 +86,22 @@ void MRegCmdList::remove(char* cmd_name)
// Disable any functions belonging to the given plugin (by index id).
void MRegCmdList::remove(int owner_plugin_id)
{
for (auto it = m_list.begin(), end = m_list.end(); it != end; ++it) {
for (auto it = m_list.begin(); it != m_list.end(); ) {
auto reg = *it;
if (reg->m_plugid == owner_plugin_id) {
if (reg->m_plugid != owner_plugin_id) {
it++;
continue;
}
if (g_RehldsFuncs) {
g_RehldsFuncs->Cmd_RemoveCmd(reg->m_name);
m_list.erase(it);
delete reg;
it = m_list.erase(it);
}
else {
reg->disable();
}
it++;
}
}
}

View File

@ -68,6 +68,7 @@ module_handle_t CSysModule::load(const char *filepath)
{
if (!m_handle) {
m_handle = LoadLibrary(filepath);
if (m_handle) m_free = true;
MODULEINFO module_info;
if (GetModuleInformation(GetCurrentProcess(), m_handle, &module_info, sizeof(module_info))) {
@ -157,6 +158,7 @@ module_handle_t CSysModule::load(const char *filepath)
{
if (!m_handle) {
m_handle = dlopen(filepath, RTLD_NOW | RTLD_LOCAL | RTLD_DEEPBIND);
if (m_handle) m_free = true;
char buf[1024], dummy[1024], path[260];
Q_sprintf(buf, "/proc/%i/maps", getpid());