plugins get updated on map change

maponly plugins get unloaded on map change

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40338
This commit is contained in:
Borja Ferrer 2007-01-20 02:12:53 +00:00
parent d351566b25
commit ba1daf3142
5 changed files with 100 additions and 2 deletions

View File

@ -10,6 +10,7 @@
#include "ExtensionSys.h" #include "ExtensionSys.h"
SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool); SH_DECL_HOOK6(IServerGameDLL, LevelInit, SH_NOATTRIB, false, bool, const char *, const char *, const char *, const char *, bool, bool);
SH_DECL_HOOK0_void(IServerGameDLL, LevelShutdown, SH_NOATTRIB, false);
SourcePawnEngine g_SourcePawn; SourcePawnEngine g_SourcePawn;
SourceModBase g_SourceMod; SourceModBase g_SourceMod;
@ -39,6 +40,7 @@ void ShutdownJIT()
SourceModBase::SourceModBase() SourceModBase::SourceModBase()
{ {
m_IsMapLoading = false; m_IsMapLoading = false;
m_ExecPluginReload = false;
} }
bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late) bool SourceModBase::InitializeSourceMod(char *error, size_t err_max, bool late)
@ -131,6 +133,7 @@ void SourceModBase::StartSourceMod(bool late)
{ {
/* First initialize the global hooks we need */ /* First initialize the global hooks we need */
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false); SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false);
SH_ADD_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &SourceModBase::LevelShutdown, false);
/* Notify! */ /* Notify! */
SMGlobalClass *pBase = SMGlobalClass::head; SMGlobalClass *pBase = SMGlobalClass::head;
@ -158,6 +161,7 @@ void SourceModBase::StartSourceMod(bool late)
bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background) bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background)
{ {
m_IsMapLoading = true; m_IsMapLoading = true;
m_ExecPluginReload = true;
g_Logger.MapChange(pMapName); g_Logger.MapChange(pMapName);
@ -168,6 +172,15 @@ bool SourceModBase::LevelInit(char const *pMapName, char const *pMapEntities, ch
RETURN_META_VALUE(MRES_IGNORED, true); RETURN_META_VALUE(MRES_IGNORED, true);
} }
void SourceModBase::LevelShutdown()
{
if (m_ExecPluginReload)
{
g_PluginSys.ReloadOrUnloadPlugins();
m_ExecPluginReload = false;
}
}
bool SourceModBase::IsMapLoading() bool SourceModBase::IsMapLoading()
{ {
return m_IsMapLoading; return m_IsMapLoading;
@ -241,6 +254,9 @@ void SourceModBase::CloseSourceMod()
pBase = pBase->m_pGlobalClassNext; pBase = pBase->m_pGlobalClassNext;
} }
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelInit, gamedll, this, &SourceModBase::LevelInit, false);
SH_REMOVE_HOOK_MEMFUNC(IServerGameDLL, LevelShutdown, gamedll, this, &SourceModBase::LevelShutdown, false);
/* Rest In Peace */ /* Rest In Peace */
ShutdownJIT(); ShutdownJIT();
} }

View File

@ -33,6 +33,11 @@ public:
*/ */
bool LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background); bool LevelInit(char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background);
/**
* @brief Level shutdown hook
*/
void LevelShutdown();
/** /**
* @brief Returns whether or not a mapload is in progress * @brief Returns whether or not a mapload is in progress
*/ */
@ -52,6 +57,7 @@ private:
private: private:
char m_SMBaseDir[PLATFORM_MAX_PATH+1]; char m_SMBaseDir[PLATFORM_MAX_PATH+1];
bool m_IsMapLoading; bool m_IsMapLoading;
bool m_ExecPluginReload;
}; };
extern SourceModBase g_SourceMod; extern SourceModBase g_SourceMod;

View File

@ -449,6 +449,35 @@ bool CPlugin::IsRunnable() const
return (m_status <= Plugin_Paused) ? true : false; return (m_status <= Plugin_Paused) ? true : false;
} }
time_t CPlugin::GetFileTimeStamp()
{
char path[PLATFORM_MAX_PATH+1];
g_SourceMod.BuildPath(Path_SM, path, sizeof(path), "plugins/%s", m_filename);
#ifdef PLATFORM_WINDOWS
struct _stat s;
if (_stat(path, &s) != 0)
#else if defined PLATFORM_POSIX
struct stat s;
if (stat(path, &s) != 0)
#endif
{
g_Logger.LogError("Could not obtain plugin time stamp, error: %d", errno);
return 0;
} else {
return s.st_mtime;
}
}
time_t CPlugin::GetTimeStamp() const
{
return m_LastAccess;
}
void CPlugin::SetTimeStamp(time_t t)
{
m_LastAccess = t;
}
/******************* /*******************
* PLUGIN ITERATOR * * PLUGIN ITERATOR *
*******************/ *******************/
@ -681,6 +710,10 @@ bool CPluginManager::_LoadPlugin(CPlugin **_plugin, const char *path, bool debug
} }
} }
/* Save the time stamp */
time_t t = pPlugin->GetFileTimeStamp();
pPlugin->SetTimeStamp(t);
if (_plugin) if (_plugin)
{ {
*_plugin = pPlugin; *_plugin = pPlugin;
@ -1522,3 +1555,31 @@ void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argc
g_RootMenu.DrawGenericOption("info", "Information about a plugin"); g_RootMenu.DrawGenericOption("info", "Information about a plugin");
g_RootMenu.DrawGenericOption("debug", "Toggle debug mode on a plugin"); g_RootMenu.DrawGenericOption("debug", "Toggle debug mode on a plugin");
} }
void CPluginManager::ReloadOrUnloadPlugins()
{
List<CPlugin *>::iterator iter;
List<CPlugin *> tmp_list = m_plugins;
CPlugin *pl;
time_t t;
for (iter=tmp_list.begin(); iter!=tmp_list.end(); iter++)
{
pl = (*iter);
if (pl->GetType() == PluginType_MapOnly)
{
UnloadPlugin((IPlugin *)pl);
} else if (pl->GetType() == PluginType_MapUpdated) {
t=pl->GetFileTimeStamp();
if (!t)
{
continue;
}
if (t > pl->GetTimeStamp())
{
pl->SetTimeStamp(t);
UnloadPlugin((IPlugin *)pl);
}
}
}
}

View File

@ -2,6 +2,8 @@
#define _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_ #define _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
#include <time.h> #include <time.h>
#include <errno.h>
#include <sys/stat.h>
#include <IPluginSys.h> #include <IPluginSys.h>
#include <IHandleSys.h> #include <IHandleSys.h>
#include <sh_list.h> #include <sh_list.h>
@ -155,7 +157,15 @@ public:
*/ */
bool IsRunnable() const; bool IsRunnable() const;
public: public:
time_t HasUpdatedFile(); /**
* Returns the modification time during last plugin load.
*/
time_t GetTimeStamp() const;
/**
* Returns the current modification time of the plugin file.
*/
time_t GetFileTimeStamp();
/** /**
* Returns true if the plugin was running, but is now invalid. * Returns true if the plugin was running, but is now invalid.
@ -163,6 +173,7 @@ public:
bool WasRunning(); bool WasRunning();
protected: protected:
void UpdateInfo(); void UpdateInfo();
void SetTimeStamp(time_t t);
private: private:
ContextPair m_ctx; ContextPair m_ctx;
PluginType m_type; PluginType m_type;
@ -272,6 +283,11 @@ public:
*/ */
const char *GetStatusText(PluginStatus status); const char *GetStatusText(PluginStatus status);
/**
* Reload or update plugins on level shutdown.
*/
void ReloadOrUnloadPlugins();
private: private:
bool _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t err_max); bool _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t err_max);

View File

@ -17,7 +17,6 @@ namespace SourceMod
typedef unsigned int HandleType_t; typedef unsigned int HandleType_t;
typedef unsigned int Handle_t; typedef unsigned int Handle_t;
class SourcePawn::IPluginContext;
/** /**
* About type checking: * About type checking: