2008-03-30 09:00:22 +02:00
/**
2009-08-30 09:03:58 +02:00
* vim : set ts = 4 sw = 4 tw = 99 noet :
2008-03-30 09:00:22 +02:00
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* SourceMod
2010-07-28 00:32:32 +02:00
* Copyright ( C ) 2004 - 2010 AlliedModders LLC . All rights reserved .
2008-03-30 09:00:22 +02:00
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* This program is free software ; you can redistribute it and / or modify it under
* the terms of the GNU General Public License , version 3.0 , as published by the
* Free Software Foundation .
*
* This program is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE . See the GNU General Public License for more
* details .
*
* You should have received a copy of the GNU General Public License along with
* this program . If not , see < http : //www.gnu.org/licenses/>.
*
* As a special exception , AlliedModders LLC gives you permission to link the
* code of this program ( as well as its derivative works ) to " Half-Life 2, " the
* " Source Engine, " the " SourcePawn JIT, " and any Game MODs that run on software
* by the Valve Corporation . You must obey the GNU General Public License in
* all respects for all other code used . Additionally , AlliedModders LLC grants
* this exception to all derivative works . AlliedModders LLC defines further
* exceptions , found in LICENSE . txt ( as of this writing , version JULY - 31 - 2007 ) ,
* or < http : //www.sourcemod.net/license.php>.
*
* Version : $ Id $
*/
# include <stdlib.h>
2020-05-17 08:15:32 +02:00
# include <memory>
2008-03-30 09:00:22 +02:00
# include "ExtensionSys.h"
2013-03-29 19:37:29 +01:00
# include <ILibrarySys.h>
# include <ISourceMod.h>
# include "common_logic.h"
# include "PluginSys.h"
2013-10-29 23:58:34 +01:00
# include <am-utility.h>
2015-08-26 05:58:43 +02:00
# include <am-string.h>
2015-08-31 06:27:32 +02:00
# include <bridge/include/CoreProvider.h>
# include <bridge/include/ILogger.h>
2008-03-30 09:00:22 +02:00
CExtensionManager g_Extensions ;
IdentityType_t g_ExtType ;
2017-11-30 18:57:12 +01:00
void CExtension : : Initialize ( const char * filename , const char * path , bool bRequired )
2008-03-30 09:00:22 +02:00
{
2017-11-30 18:57:12 +01:00
m_bRequired = bRequired ;
2008-03-30 09:00:22 +02:00
m_pAPI = NULL ;
m_pIdentToken = NULL ;
unload_code = 0 ;
m_bFullyLoaded = false ;
m_File . assign ( filename ) ;
m_Path . assign ( path ) ;
2009-08-30 09:03:58 +02:00
char real_name [ PLATFORM_MAX_PATH ] ;
2013-03-29 19:37:29 +01:00
libsys - > GetFileFromPath ( real_name , sizeof ( real_name ) , m_Path . c_str ( ) ) ;
2009-08-30 09:03:58 +02:00
m_RealFile . assign ( real_name ) ;
2008-03-30 09:00:22 +02:00
}
CRemoteExtension : : CRemoteExtension ( IExtensionInterface * pAPI , const char * filename , const char * path )
{
Initialize ( filename , path ) ;
m_pAPI = pAPI ;
}
2017-11-30 18:57:12 +01:00
CLocalExtension : : CLocalExtension ( const char * filename , bool bRequired )
2008-03-30 09:00:22 +02:00
{
m_PlId = 0 ;
m_pLib = NULL ;
char path [ PLATFORM_MAX_PATH ] ;
2010-08-01 21:57:54 +02:00
/* Special case for new bintools binary */
if ( strcmp ( filename , " bintools.ext " ) = = 0 )
2013-07-21 17:53:56 +02:00
{
g_pSM - > BuildPath ( Path_SM ,
path ,
PLATFORM_MAX_PATH ,
2018-05-25 15:49:10 +02:00
" extensions/%s. " PLATFORM_LIB_EXT ,
2013-07-21 17:53:56 +02:00
filename ) ;
2013-08-14 17:56:34 +02:00
}
2018-05-25 15:49:10 +02:00
else
2013-08-14 17:56:34 +02:00
{
2018-05-25 15:49:10 +02:00
/* Zeroth, see if there is an engine specific build in the new place. */
2013-08-14 17:56:34 +02:00
g_pSM - > BuildPath ( Path_SM ,
path ,
PLATFORM_MAX_PATH ,
2018-05-25 15:49:10 +02:00
" extensions/%s.%s. " PLATFORM_LIB_EXT ,
filename ,
bridge - > gamesuffix ) ;
2013-08-14 17:56:34 +02:00
2018-05-25 15:49:10 +02:00
if ( ! libsys - > IsPathFile ( path ) )
2013-07-21 17:53:56 +02:00
{
2018-05-25 15:49:10 +02:00
/* COMPAT HACK: One-halfth, if ep2v, see if there is an engine specific build in the new place with old naming */
if ( strcmp ( bridge - > gamesuffix , " 2.tf2 " ) = = 0
| | strcmp ( bridge - > gamesuffix , " 2.dods " ) = = 0
| | strcmp ( bridge - > gamesuffix , " 2.hl2dm " ) = = 0
)
{
g_pSM - > BuildPath ( Path_SM ,
path ,
PLATFORM_MAX_PATH ,
" extensions/%s.2.ep2v. " PLATFORM_LIB_EXT ,
filename ) ;
}
else if ( strcmp ( bridge - > gamesuffix , " 2.nd " ) = = 0 )
{
g_pSM - > BuildPath ( Path_SM ,
path ,
PLATFORM_MAX_PATH ,
" extensions/%s.2.l4d2. " PLATFORM_LIB_EXT ,
filename ) ;
}
//Try further
if ( ! libsys - > IsPathFile ( path ) )
{
/* First see if there is an engine specific build! */
g_pSM - > BuildPath ( Path_SM ,
path ,
PLATFORM_MAX_PATH ,
" extensions/auto.%s/%s. " PLATFORM_LIB_EXT ,
filename ,
bridge - > gamesuffix ) ;
/* Try the "normal" version */
if ( ! libsys - > IsPathFile ( path ) )
{
g_pSM - > BuildPath ( Path_SM ,
path ,
PLATFORM_MAX_PATH ,
" extensions/%s. " PLATFORM_LIB_EXT ,
filename ) ;
}
}
2013-07-21 17:53:56 +02:00
}
}
2017-11-30 18:57:12 +01:00
Initialize ( filename , path , bRequired ) ;
2008-03-30 09:00:22 +02:00
}
bool CRemoteExtension : : Load ( char * error , size_t maxlength )
{
if ( ! PerformAPICheck ( error , maxlength ) )
{
m_pAPI = NULL ;
return false ;
}
if ( ! CExtension : : Load ( error , maxlength ) )
{
m_pAPI = NULL ;
return false ;
}
return true ;
}
bool CLocalExtension : : Load ( char * error , size_t maxlength )
{
2013-03-29 19:37:29 +01:00
m_pLib = libsys - > OpenLibrary ( m_Path . c_str ( ) , error , maxlength ) ;
2008-03-30 09:00:22 +02:00
if ( m_pLib = = NULL )
{
return false ;
}
typedef IExtensionInterface * ( * GETAPI ) ( ) ;
GETAPI pfnGetAPI = NULL ;
if ( ( pfnGetAPI = ( GETAPI ) m_pLib - > GetSymbolAddress ( " GetSMExtAPI " ) ) = = NULL )
{
m_pLib - > CloseLibrary ( ) ;
m_pLib = NULL ;
2018-03-25 22:00:53 +02:00
ke : : SafeStrcpy ( error , maxlength , " Unable to find extension entry point " ) ;
2008-03-30 09:00:22 +02:00
return false ;
}
m_pAPI = pfnGetAPI ( ) ;
/* Check pointer and version */
if ( ! PerformAPICheck ( error , maxlength ) )
{
m_pLib - > CloseLibrary ( ) ;
m_pLib = NULL ;
m_pAPI = NULL ;
return false ;
}
/* Load as MM:S */
if ( m_pAPI - > IsMetamodExtension ( ) )
{
2013-03-29 19:37:29 +01:00
bool ok ;
2015-08-30 01:23:50 +02:00
m_PlId = bridge - > LoadMMSPlugin ( m_Path . c_str ( ) , & ok , error , maxlength ) ;
2011-08-15 21:19:07 +02:00
2013-03-29 19:37:29 +01:00
if ( ! m_PlId | | ! ok )
2011-08-15 21:19:07 +02:00
{
m_pLib - > CloseLibrary ( ) ;
m_pLib = NULL ;
m_pAPI = NULL ;
return false ;
}
2008-03-30 09:00:22 +02:00
}
if ( ! CExtension : : Load ( error , maxlength ) )
{
if ( m_pAPI - > IsMetamodExtension ( ) )
{
if ( m_PlId )
{
2015-08-30 01:23:50 +02:00
bridge - > UnloadMMSPlugin ( m_PlId ) ;
2008-03-30 09:00:22 +02:00
m_PlId = 0 ;
}
}
m_pLib - > CloseLibrary ( ) ;
m_pLib = NULL ;
m_pAPI = NULL ;
return false ;
}
return true ;
}
void CRemoteExtension : : Unload ( )
{
}
void CLocalExtension : : Unload ( )
{
if ( m_pAPI ! = NULL & & m_PlId )
{
2015-08-30 01:23:50 +02:00
bridge - > UnloadMMSPlugin ( m_PlId ) ;
2008-03-30 09:00:22 +02:00
m_PlId = 0 ;
}
if ( m_pLib ! = NULL )
{
m_pLib - > CloseLibrary ( ) ;
m_pLib = NULL ;
}
}
2009-08-23 23:11:42 +02:00
bool CRemoteExtension : : Reload ( char * error , size_t maxlength )
{
2018-03-25 22:00:53 +02:00
ke : : SafeStrcpy ( error , maxlength , " Remote extensions do not support reloading " ) ;
2009-08-23 23:11:42 +02:00
return false ;
}
bool CLocalExtension : : Reload ( char * error , size_t maxlength )
{
if ( m_pLib = = NULL ) // FIXME: just load it instead?
return false ;
m_pAPI - > OnExtensionUnload ( ) ;
Unload ( ) ;
return Load ( error , maxlength ) ;
}
2008-03-30 09:00:22 +02:00
bool CRemoteExtension : : IsExternal ( )
{
return true ;
}
bool CLocalExtension : : IsExternal ( )
{
return false ;
}
CExtension : : ~ CExtension ( )
{
DestroyIdentity ( ) ;
}
bool CExtension : : PerformAPICheck ( char * error , size_t maxlength )
{
if ( ! m_pAPI )
{
2018-03-25 22:00:53 +02:00
ke : : SafeStrcpy ( error , maxlength , " No IExtensionInterface instance provided " ) ;
2008-03-30 09:00:22 +02:00
return false ;
}
if ( m_pAPI - > GetExtensionVersion ( ) > SMINTERFACE_EXTENSIONAPI_VERSION )
{
2018-03-25 22:00:53 +02:00
ke : : SafeSprintf ( error , maxlength , " Extension version is too new to load (%d, max is %d) " , m_pAPI - > GetExtensionVersion ( ) , SMINTERFACE_EXTENSIONAPI_VERSION ) ;
2008-03-30 09:00:22 +02:00
return false ;
}
return true ;
}
bool CExtension : : Load ( char * error , size_t maxlength )
{
CreateIdentity ( ) ;
2015-08-30 01:23:50 +02:00
if ( ! m_pAPI - > OnExtensionLoad ( this , & g_ShareSys , error , maxlength , ! bridge - > IsMapLoading ( ) ) )
2008-03-30 09:00:22 +02:00
{
2015-11-09 15:56:42 +01:00
g_ShareSys . RemoveInterfaces ( this ) ;
2008-03-30 09:00:22 +02:00
DestroyIdentity ( ) ;
return false ;
}
2015-11-09 15:56:42 +01:00
/* Check if we're past load time */
if ( ! bridge - > IsMapLoading ( ) )
2008-03-30 09:00:22 +02:00
{
2020-06-22 08:32:11 +02:00
MarkAllLoaded ( ) ;
2008-03-30 09:00:22 +02:00
}
return true ;
}
void CExtension : : CreateIdentity ( )
{
if ( m_pIdentToken ! = NULL )
{
return ;
}
m_pIdentToken = g_ShareSys . CreateIdentity ( g_ExtType , this ) ;
}
void CExtension : : DestroyIdentity ( )
{
if ( m_pIdentToken = = NULL )
{
return ;
}
g_ShareSys . DestroyIdentity ( m_pIdentToken ) ;
m_pIdentToken = NULL ;
}
void CExtension : : MarkAllLoaded ( )
{
assert ( m_bFullyLoaded = = false ) ;
if ( ! m_bFullyLoaded )
{
m_bFullyLoaded = true ;
m_pAPI - > OnExtensionsAllLoaded ( ) ;
}
}
2008-05-26 09:51:11 +02:00
void CExtension : : AddPlugin ( CPlugin * pPlugin )
2008-03-30 09:00:22 +02:00
{
/* Unfortunately we have to do this :( */
2013-09-30 18:26:45 +02:00
if ( m_Dependents . find ( pPlugin ) = = m_Dependents . end ( ) )
2008-03-30 09:00:22 +02:00
{
2008-05-26 09:51:11 +02:00
m_Dependents . push_back ( pPlugin ) ;
2008-03-30 09:00:22 +02:00
}
}
void CExtension : : SetError ( const char * error )
{
m_Error . assign ( error ) ;
}
IExtensionInterface * CExtension : : GetAPI ( )
{
return m_pAPI ;
}
const char * CExtension : : GetFilename ( )
{
2009-08-30 09:03:58 +02:00
return m_RealFile . c_str ( ) ;
2008-03-30 09:00:22 +02:00
}
2011-10-12 04:51:24 +02:00
const char * CExtension : : GetPath ( ) const
{
return m_Path . c_str ( ) ;
}
2008-03-30 09:00:22 +02:00
IdentityToken_t * CExtension : : GetIdentity ( )
{
return m_pIdentToken ;
}
bool CRemoteExtension : : IsLoaded ( )
{
return ( m_pAPI ! = NULL ) ;
}
bool CLocalExtension : : IsLoaded ( )
{
return ( m_pLib ! = NULL ) ;
}
2008-07-01 08:12:16 +02:00
void CExtension : : AddDependency ( const IfaceInfo * pInfo )
2008-03-30 09:00:22 +02:00
{
if ( m_Deps . find ( * pInfo ) = = m_Deps . end ( ) )
{
m_Deps . push_back ( * pInfo ) ;
}
}
bool operator = = ( const IfaceInfo & i1 , const IfaceInfo & i2 )
{
return ( i1 . iface = = i2 . iface ) & & ( i1 . owner = = i2 . owner ) ;
}
void CExtension : : AddChildDependent ( CExtension * pOther , SMInterface * iface )
{
IfaceInfo info ;
info . iface = iface ;
info . owner = pOther ;
List < IfaceInfo > : : iterator iter ;
for ( iter = m_ChildDeps . begin ( ) ;
iter ! = m_ChildDeps . end ( ) ;
iter + + )
{
IfaceInfo & other = ( * iter ) ;
if ( other = = info )
{
return ;
}
}
m_ChildDeps . push_back ( info ) ;
}
2019-05-29 03:04:08 +02:00
// note: dependency iteration deprecated since 1.10
2008-03-30 09:00:22 +02:00
ITERATOR * CExtension : : FindFirstDependency ( IExtension * * pOwner , SMInterface * * pInterface )
{
2019-05-29 03:04:08 +02:00
return nullptr ;
2008-03-30 09:00:22 +02:00
}
bool CExtension : : FindNextDependency ( ITERATOR * iter , IExtension * * pOwner , SMInterface * * pInterface )
{
2019-05-29 03:04:08 +02:00
return false ;
2008-03-30 09:00:22 +02:00
}
void CExtension : : FreeDependencyIterator ( ITERATOR * iter )
{
}
void CExtension : : AddInterface ( SMInterface * pInterface )
{
m_Interfaces . push_back ( pInterface ) ;
}
bool CExtension : : IsRunning ( char * error , size_t maxlength )
{
if ( ! IsLoaded ( ) )
{
if ( error )
{
2018-03-25 22:00:53 +02:00
ke : : SafeStrcpy ( error , maxlength , m_Error . c_str ( ) ) ;
2008-03-30 09:00:22 +02:00
}
return false ;
}
return m_pAPI - > QueryRunning ( error , maxlength ) ;
}
void CExtension : : AddLibrary ( const char * library )
{
m_Libraries . push_back ( library ) ;
}
2017-11-30 18:57:12 +01:00
bool CExtension : : IsRequired ( )
{
return m_bRequired ;
}
2008-03-30 09:00:22 +02:00
/*********************
* EXTENSION MANAGER *
* * * * * * * * * * * * * * * * * * * * */
void CExtensionManager : : OnSourceModAllInitialized ( )
{
g_ExtType = g_ShareSys . CreateIdentType ( " EXTENSION " ) ;
2013-03-29 19:37:29 +01:00
pluginsys - > AddPluginsListener ( this ) ;
2015-08-28 04:59:04 +02:00
rootmenu - > AddRootConsoleCommand3 ( " exts " , " Manage extensions " , this ) ;
2008-03-30 09:00:22 +02:00
g_ShareSys . AddInterface ( NULL , this ) ;
}
void CExtensionManager : : OnSourceModShutdown ( )
{
2013-04-01 07:03:57 +02:00
rootmenu - > RemoveRootConsoleCommand ( " exts " , this ) ;
2013-03-29 19:37:29 +01:00
pluginsys - > RemovePluginsListener ( this ) ;
2008-03-30 09:00:22 +02:00
g_ShareSys . DestroyIdentType ( g_ExtType ) ;
}
void CExtensionManager : : Shutdown ( )
{
List < CExtension * > : : iterator iter ;
while ( ( iter = m_Libs . begin ( ) ) ! = m_Libs . end ( ) )
{
UnloadExtension ( ( * iter ) ) ;
}
}
void CExtensionManager : : TryAutoload ( )
{
char path [ PLATFORM_MAX_PATH ] ;
2013-03-29 19:37:29 +01:00
g_pSM - > BuildPath ( Path_SM , path , sizeof ( path ) , " extensions " ) ;
2008-03-30 09:00:22 +02:00
2020-05-17 08:15:32 +02:00
std : : unique_ptr < IDirectory > pDir ( libsys - > OpenDirectory ( path ) ) ;
2008-03-30 09:00:22 +02:00
if ( ! pDir )
return ;
const char * lfile ;
size_t len ;
while ( pDir - > MoreFiles ( ) )
{
if ( pDir - > IsEntryDirectory ( ) )
{
pDir - > NextEntry ( ) ;
continue ;
}
lfile = pDir - > GetEntryName ( ) ;
len = strlen ( lfile ) ;
if ( len < = 9 ) /* size of ".autoload" */
{
pDir - > NextEntry ( ) ;
continue ;
}
if ( strcmp ( & lfile [ len - 9 ] , " .autoload " ) ! = 0 )
{
pDir - > NextEntry ( ) ;
continue ;
}
char file [ PLATFORM_MAX_PATH ] ;
2018-03-19 21:12:51 +01:00
len = ke : : SafeStrcpy ( file , sizeof ( file ) , lfile ) ;
2009-08-30 09:03:58 +02:00
strcpy ( & file [ len - 9 ] , " .ext " ) ;
2008-03-30 09:00:22 +02:00
LoadAutoExtension ( file ) ;
pDir - > NextEntry ( ) ;
}
}
2013-08-24 06:12:21 +02:00
IExtension * CExtensionManager : : LoadAutoExtension ( const char * path , bool bErrorOnMissing )
2008-03-30 09:00:22 +02:00
{
2009-08-30 09:03:58 +02:00
/* Remove platform extension if it's there. Compat hack. */
2013-03-29 19:37:29 +01:00
const char * ext = libsys - > GetFileExtension ( path ) ;
2009-08-30 09:03:58 +02:00
if ( strcmp ( ext , PLATFORM_LIB_EXT ) = = 0 )
2008-03-30 09:00:22 +02:00
{
2009-08-30 09:03:58 +02:00
char path2 [ PLATFORM_MAX_PATH ] ;
2018-03-19 21:12:51 +01:00
ke : : SafeStrcpy ( path2 , sizeof ( path2 ) , path ) ;
2009-08-30 09:03:58 +02:00
path2 [ strlen ( path ) - strlen ( PLATFORM_LIB_EXT ) - 1 ] = ' \0 ' ;
2013-08-24 06:12:21 +02:00
return LoadAutoExtension ( path2 , bErrorOnMissing ) ;
2008-03-30 09:00:22 +02:00
}
IExtension * pAlready ;
if ( ( pAlready = FindExtensionByFile ( path ) ) ! = NULL )
{
return pAlready ;
}
char error [ 256 ] ;
2017-11-30 18:57:12 +01:00
CExtension * p = new CLocalExtension ( path , bErrorOnMissing ) ;
2008-03-30 09:00:22 +02:00
/* We put us in the list beforehand so extensions that check for each other
* won ' t recursively load each other .
*/
m_Libs . push_back ( p ) ;
if ( ! p - > Load ( error , sizeof ( error ) ) | | ! p - > IsLoaded ( ) )
{
2013-08-24 06:12:21 +02:00
if ( bErrorOnMissing | | libsys - > IsPathFile ( p - > GetPath ( ) ) )
{
2014-08-13 23:24:35 +02:00
logger - > LogError ( " [SM] Unable to load extension \" %s \" : %s " , path , error ) ;
2013-08-24 06:12:21 +02:00
}
2008-03-30 09:00:22 +02:00
p - > SetError ( error ) ;
}
return p ;
}
IExtension * CExtensionManager : : FindExtensionByFile ( const char * file )
{
List < CExtension * > : : iterator iter ;
CExtension * pExt ;
/* Chomp off the path */
char lookup [ PLATFORM_MAX_PATH ] ;
2013-03-29 19:37:29 +01:00
libsys - > GetFileFromPath ( lookup , sizeof ( lookup ) , file ) ;
2008-03-30 09:00:22 +02:00
for ( iter = m_Libs . begin ( ) ; iter ! = m_Libs . end ( ) ; iter + + )
{
pExt = ( * iter ) ;
2009-08-30 09:03:58 +02:00
if ( pExt - > IsSameFile ( lookup ) )
2008-03-30 09:00:22 +02:00
{
return pExt ;
}
}
return NULL ;
}
IExtension * CExtensionManager : : FindExtensionByName ( const char * ext )
{
List < CExtension * > : : iterator iter ;
CExtension * pExt ;
IExtensionInterface * pAPI ;
const char * name ;
for ( iter = m_Libs . begin ( ) ; iter ! = m_Libs . end ( ) ; iter + + )
{
pExt = ( * iter ) ;
if ( ! pExt - > IsLoaded ( ) )
{
continue ;
}
if ( ( pAPI = pExt - > GetAPI ( ) ) = = NULL )
{
continue ;
}
name = pAPI - > GetExtensionName ( ) ;
if ( ! name )
{
continue ;
}
if ( strcmp ( name , ext ) = = 0 )
{
return pExt ;
}
}
return NULL ;
}
IExtension * CExtensionManager : : LoadExtension ( const char * file , char * error , size_t maxlength )
{
2009-08-30 09:03:58 +02:00
/* Remove platform extension if it's there. Compat hack. */
2013-03-29 19:37:29 +01:00
const char * ext = libsys - > GetFileExtension ( file ) ;
2009-08-30 09:03:58 +02:00
if ( strcmp ( ext , PLATFORM_LIB_EXT ) = = 0 )
{
char path2 [ PLATFORM_MAX_PATH ] ;
2018-03-19 21:12:51 +01:00
ke : : SafeStrcpy ( path2 , sizeof ( path2 ) , file ) ;
2009-08-30 09:03:58 +02:00
path2 [ strlen ( file ) - strlen ( PLATFORM_LIB_EXT ) - 1 ] = ' \0 ' ;
return LoadExtension ( path2 , error , maxlength ) ;
}
2008-03-30 09:00:22 +02:00
IExtension * pAlready ;
if ( ( pAlready = FindExtensionByFile ( file ) ) ! = NULL )
{
return pAlready ;
}
CExtension * pExt = new CLocalExtension ( file ) ;
if ( ! pExt - > Load ( error , maxlength ) | | ! pExt - > IsLoaded ( ) )
{
pExt - > Unload ( ) ;
delete pExt ;
return NULL ;
}
/* :TODO: do QueryRunning check if the map is loaded */
m_Libs . push_back ( pExt ) ;
return pExt ;
}
void CExtensionManager : : BindDependency ( IExtension * pRequester , IfaceInfo * pInfo )
{
CExtension * pExt = ( CExtension * ) pRequester ;
CExtension * pOwner = ( CExtension * ) pInfo - > owner ;
pExt - > AddDependency ( pInfo ) ;
IExtensionInterface * pAPI = pExt - > GetAPI ( ) ;
if ( pAPI & & ! pAPI - > QueryInterfaceDrop ( pInfo - > iface ) )
{
pOwner - > AddChildDependent ( pExt , pInfo - > iface ) ;
}
}
2008-07-01 08:12:16 +02:00
void CExtensionManager : : AddRawDependency ( IExtension * ext , IdentityToken_t * other , void * iface )
{
CExtension * pExt = ( CExtension * ) ext ;
CExtension * pOwner = GetExtensionFromIdent ( other ) ;
IfaceInfo info ;
info . iface = ( SMInterface * ) iface ;
info . owner = pOwner ;
pExt - > AddDependency ( & info ) ;
pOwner - > AddChildDependent ( pExt , ( SMInterface * ) iface ) ;
}
2008-03-30 09:00:22 +02:00
void CExtensionManager : : AddInterface ( IExtension * pOwner , SMInterface * pInterface )
{
CExtension * pExt = ( CExtension * ) pOwner ;
pExt - > AddInterface ( pInterface ) ;
}
2013-03-29 19:37:29 +01:00
void CExtensionManager : : BindChildPlugin ( IExtension * pParent , SMPlugin * pPlugin )
2008-03-30 09:00:22 +02:00
{
CExtension * pExt = ( CExtension * ) pParent ;
2013-03-29 19:37:29 +01:00
pExt - > AddPlugin ( static_cast < CPlugin * > ( pPlugin ) ) ;
2008-03-30 09:00:22 +02:00
}
void CExtensionManager : : OnPluginDestroyed ( IPlugin * plugin )
{
List < CExtension * > : : iterator iter ;
for ( iter = m_Libs . begin ( ) ; iter ! = m_Libs . end ( ) ; iter + + )
{
2013-03-29 19:37:29 +01:00
( * iter ) - > DropRefsTo ( static_cast < CPlugin * > ( plugin ) ) ;
2008-03-30 09:00:22 +02:00
}
}
CExtension * CExtensionManager : : FindByOrder ( unsigned int num )
{
if ( num < 1 | | num > m_Libs . size ( ) )
{
return NULL ;
}
List < CExtension * > : : iterator iter = m_Libs . begin ( ) ;
while ( iter ! = m_Libs . end ( ) )
{
if ( - - num = = 0 )
{
return ( * iter ) ;
}
iter + + ;
}
return NULL ;
}
bool CExtensionManager : : UnloadExtension ( IExtension * _pExt )
{
if ( ! _pExt )
return false ;
CExtension * pExt = ( CExtension * ) _pExt ;
if ( m_Libs . find ( pExt ) = = m_Libs . end ( ) )
return false ;
2013-02-28 23:04:28 +01:00
/* Tell it to unload */
if ( pExt - > IsLoaded ( ) )
2013-08-22 23:05:44 +02:00
pExt - > GetAPI ( ) - > OnExtensionUnload ( ) ;
2013-02-28 23:04:28 +01:00
2013-08-22 23:05:44 +02:00
// Remove us from internal lists. Note that because we do this, it's
// possible that our extension could be added back if another plugin
// tries to load during this process. If we ever find this to happen,
// we can just block plugin loading.
2008-03-30 09:00:22 +02:00
g_ShareSys . RemoveInterfaces ( _pExt ) ;
m_Libs . remove ( pExt ) ;
List < CExtension * > UnloadQueue ;
/* Handle dependencies */
if ( pExt - > IsLoaded ( ) )
{
/* Unload any dependent plugins */
2008-05-26 09:51:11 +02:00
List < CPlugin * > : : iterator p_iter = pExt - > m_Dependents . begin ( ) ;
while ( p_iter ! = pExt - > m_Dependents . end ( ) )
2008-03-30 09:00:22 +02:00
{
/* We have to manually unlink ourselves here, since we're no longer being managed */
2013-03-29 19:37:29 +01:00
scripts - > UnloadPlugin ( ( * p_iter ) ) ;
2008-05-26 09:51:11 +02:00
p_iter = pExt - > m_Dependents . erase ( p_iter ) ;
2008-03-30 09:00:22 +02:00
}
List < String > : : iterator s_iter ;
for ( s_iter = pExt - > m_Libraries . begin ( ) ;
s_iter ! = pExt - > m_Libraries . end ( ) ;
s_iter + + )
{
2013-03-29 19:37:29 +01:00
scripts - > OnLibraryAction ( ( * s_iter ) . c_str ( ) , LibraryAction_Removed ) ;
2008-03-30 09:00:22 +02:00
}
/* Notify and/or unload all dependencies */
List < CExtension * > : : iterator c_iter ;
CExtension * pDep ;
IExtensionInterface * pAPI ;
for ( c_iter = m_Libs . begin ( ) ; c_iter ! = m_Libs . end ( ) ; c_iter + + )
{
pDep = ( * c_iter ) ;
if ( ( pAPI = pDep - > GetAPI ( ) ) = = NULL )
continue ;
if ( pDep = = pExt )
continue ;
/* Now, get its dependency list */
bool dropped = false ;
List < IfaceInfo > : : iterator i_iter = pDep - > m_Deps . begin ( ) ;
while ( i_iter ! = pDep - > m_Deps . end ( ) )
{
if ( ( * i_iter ) . owner = = _pExt )
{
if ( ! pAPI - > QueryInterfaceDrop ( ( * i_iter ) . iface ) )
{
if ( ! dropped )
{
dropped = true ;
UnloadQueue . push_back ( pDep ) ;
}
}
pAPI - > NotifyInterfaceDrop ( ( * i_iter ) . iface ) ;
i_iter = pDep - > m_Deps . erase ( i_iter ) ;
}
else
{
i_iter + + ;
}
}
/* Flush out any back references to this plugin */
i_iter = pDep - > m_ChildDeps . begin ( ) ;
while ( i_iter ! = pDep - > m_ChildDeps . end ( ) )
{
if ( ( * i_iter ) . owner = = pExt )
i_iter = pDep - > m_ChildDeps . erase ( i_iter ) ;
else
i_iter + + ;
}
}
/* Unbind our natives from Core */
2008-05-26 09:51:11 +02:00
pExt - > DropEverything ( ) ;
2008-03-30 09:00:22 +02:00
}
IdentityToken_t * pIdentity ;
if ( ( pIdentity = pExt - > GetIdentity ( ) ) ! = NULL )
{
SMGlobalClass * glob = SMGlobalClass : : head ;
while ( glob )
{
glob - > OnSourceModIdentityDropped ( pIdentity ) ;
glob = glob - > m_pGlobalClassNext ;
}
}
2013-08-22 23:05:44 +02:00
// Everything has been informed that we're unloading, so give the
// extension one last notification.
if ( pExt - > IsLoaded ( ) & & pExt - > GetAPI ( ) - > GetExtensionVersion ( ) > = 7 )
pExt - > GetAPI ( ) - > OnDependenciesDropped ( ) ;
2008-03-30 09:00:22 +02:00
pExt - > Unload ( ) ;
delete pExt ;
List < CExtension * > : : iterator iter ;
for ( iter = UnloadQueue . begin ( ) ; iter ! = UnloadQueue . end ( ) ; iter + + )
{
/* NOTE: This is safe because the unload function backs out of anything not present */
UnloadExtension ( ( * iter ) ) ;
}
return true ;
}
void CExtensionManager : : MarkAllLoaded ( )
{
List < CExtension * > : : iterator iter ;
CExtension * pExt ;
for ( iter = m_Libs . begin ( ) ; iter ! = m_Libs . end ( ) ; iter + + )
{
pExt = ( * iter ) ;
if ( ! pExt - > IsLoaded ( ) )
{
continue ;
}
if ( pExt - > m_bFullyLoaded )
{
continue ;
}
pExt - > MarkAllLoaded ( ) ;
}
}
void CExtensionManager : : AddDependency ( IExtension * pSource , const char * file , bool required , bool autoload )
{
/* This function doesn't really need to do anything now. We make sure the
* other extension is loaded , but handling of dependencies is really done
* by the interface fetcher .
*/
if ( required | | autoload )
{
LoadAutoExtension ( file ) ;
}
}
2015-08-28 04:59:04 +02:00
void CExtensionManager : : OnRootConsoleCommand ( const char * cmdname , const ICommandArgs * command )
2008-03-30 09:00:22 +02:00
{
2015-08-28 04:59:04 +02:00
int argcount = command - > ArgC ( ) ;
2008-03-30 09:00:22 +02:00
if ( argcount > = 3 )
{
2015-08-28 04:59:04 +02:00
const char * cmd = command - > Arg ( 2 ) ;
2008-03-30 09:00:22 +02:00
if ( strcmp ( cmd , " list " ) = = 0 )
{
List < CExtension * > : : iterator iter ;
CExtension * pExt ;
unsigned int num = 1 ;
2017-11-30 20:21:19 +01:00
2017-12-30 20:08:56 +01:00
switch ( m_Libs . size ( ) )
2008-03-30 09:00:22 +02:00
{
case 1 :
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Displaying 1 extension: " ) ;
2008-03-30 09:00:22 +02:00
break ;
}
case 0 :
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] No extensions are loaded. " ) ;
2008-03-30 09:00:22 +02:00
break ;
}
default :
{
2017-12-30 20:08:56 +01:00
rootmenu - > ConsolePrint ( " [SM] Displaying %d extensions: " , m_Libs . size ( ) ) ;
2008-03-30 09:00:22 +02:00
break ;
}
}
2017-12-30 20:08:56 +01:00
for ( iter = m_Libs . begin ( ) ; iter ! = m_Libs . end ( ) ; iter + + , num + + )
2008-03-30 09:00:22 +02:00
{
pExt = ( * iter ) ;
if ( pExt - > IsLoaded ( ) )
{
char error [ 255 ] ;
if ( ! pExt - > IsRunning ( error , sizeof ( error ) ) )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [%02d] <FAILED> file \" %s \" : %s " , num , pExt - > GetFilename ( ) , error ) ;
2008-03-30 09:00:22 +02:00
}
else
{
IExtensionInterface * pAPI = pExt - > GetAPI ( ) ;
const char * name = pAPI - > GetExtensionName ( ) ;
const char * version = pAPI - > GetExtensionVerString ( ) ;
const char * descr = pAPI - > GetExtensionDescription ( ) ;
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [%02d] %s (%s): %s " , num , name , version , descr ) ;
2008-03-30 09:00:22 +02:00
}
2017-11-30 18:57:12 +01:00
}
2017-12-30 20:08:56 +01:00
else if ( pExt - > IsRequired ( ) | | libsys - > PathExists ( pExt - > GetPath ( ) ) )
2017-11-30 18:57:12 +01:00
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [%02d] <FAILED> file \" %s \" : %s " , num , pExt - > GetFilename ( ) , pExt - > m_Error . c_str ( ) ) ;
2008-03-30 09:00:22 +02:00
}
2017-12-30 20:08:56 +01:00
else
2017-11-30 18:57:12 +01:00
{
2017-12-30 20:08:56 +01:00
rootmenu - > ConsolePrint ( " [%02d] <OPTIONAL> file \" %s \" : %s " , num , pExt - > GetFilename ( ) , pExt - > m_Error . c_str ( ) ) ;
2017-11-30 18:57:12 +01:00
}
2008-03-30 09:00:22 +02:00
}
return ;
}
2009-08-23 23:11:42 +02:00
else if ( strcmp ( cmd , " load " ) = = 0 )
{
if ( argcount < 4 )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Usage: sm exts load <file> " ) ;
2009-08-23 23:11:42 +02:00
return ;
}
2015-08-28 04:59:04 +02:00
const char * filename = command - > Arg ( 3 ) ;
2009-08-23 23:11:42 +02:00
char path [ PLATFORM_MAX_PATH ] ;
char error [ 256 ] ;
2015-08-26 05:58:43 +02:00
ke : : SafeSprintf ( path , sizeof ( path ) , " %s%s%s " , filename , ! strstr ( filename , " .ext " ) ? " .ext " : " " ,
2009-08-23 23:11:42 +02:00
! strstr ( filename , " . " PLATFORM_LIB_EXT ) ? " . " PLATFORM_LIB_EXT : " " ) ;
if ( FindExtensionByFile ( path ) ! = NULL )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Extension %s is already loaded. " , path ) ;
2009-08-23 23:11:42 +02:00
return ;
}
if ( LoadExtension ( path , error , sizeof ( error ) ) )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Loaded extension %s successfully. " , path ) ;
2009-08-23 23:11:42 +02:00
} else
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Extension %s failed to load: %s " , path , error ) ;
2009-08-23 23:11:42 +02:00
}
return ;
}
2008-03-30 09:00:22 +02:00
else if ( strcmp ( cmd , " info " ) = = 0 )
{
if ( argcount < 4 )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Usage: sm exts info <#> " ) ;
2008-03-30 09:00:22 +02:00
return ;
}
2015-08-28 04:59:04 +02:00
const char * sId = command - > Arg ( 3 ) ;
2008-03-30 09:00:22 +02:00
unsigned int id = atoi ( sId ) ;
if ( id < = 0 )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Usage: sm exts info <#> " ) ;
2008-03-30 09:00:22 +02:00
return ;
}
if ( m_Libs . size ( ) = = 0 )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] No extensions are loaded. " ) ;
2008-03-30 09:00:22 +02:00
return ;
}
if ( id > m_Libs . size ( ) )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] No extension was found with id %d. " , id ) ;
2008-03-30 09:00:22 +02:00
return ;
}
List < CExtension * > : : iterator iter = m_Libs . begin ( ) ;
CExtension * pExt = NULL ;
while ( iter ! = m_Libs . end ( ) )
{
if ( - - id = = 0 )
{
pExt = ( * iter ) ;
break ;
}
iter + + ;
}
/* This should never happen */
if ( ! pExt )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] No extension was found with id %d. " , id ) ;
2008-03-30 09:00:22 +02:00
return ;
}
if ( ! pExt - > IsLoaded ( ) )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " File: %s " , pExt - > GetFilename ( ) ) ;
rootmenu - > ConsolePrint ( " Loaded: No (%s) " , pExt - > m_Error . c_str ( ) ) ;
2008-03-30 09:00:22 +02:00
}
else
{
char error [ 255 ] ;
if ( ! pExt - > IsRunning ( error , sizeof ( error ) ) )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " File: %s " , pExt - > GetFilename ( ) ) ;
rootmenu - > ConsolePrint ( " Loaded: Yes " ) ;
rootmenu - > ConsolePrint ( " Running: No (%s) " , error ) ;
2008-03-30 09:00:22 +02:00
}
else
{
IExtensionInterface * pAPI = pExt - > GetAPI ( ) ;
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " File: %s " , pExt - > GetFilename ( ) ) ;
rootmenu - > ConsolePrint ( " Loaded: Yes (version %s) " , pAPI - > GetExtensionVerString ( ) ) ;
rootmenu - > ConsolePrint ( " Name: %s (%s) " , pAPI - > GetExtensionName ( ) , pAPI - > GetExtensionDescription ( ) ) ;
rootmenu - > ConsolePrint ( " Author: %s (%s) " , pAPI - > GetExtensionAuthor ( ) , pAPI - > GetExtensionURL ( ) ) ;
rootmenu - > ConsolePrint ( " Binary info: API version %d (compiled %s) " , pAPI - > GetExtensionVersion ( ) , pAPI - > GetExtensionDateString ( ) ) ;
2008-03-30 09:00:22 +02:00
if ( pExt - > IsExternal ( ) )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " Method: Loaded by Metamod:Source, attached to SourceMod " ) ;
2008-03-30 09:00:22 +02:00
}
else if ( pAPI - > IsMetamodExtension ( ) )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " Method: Loaded by SourceMod, attached to Metamod:Source " ) ;
2008-03-30 09:00:22 +02:00
}
else
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " Method: Loaded by SourceMod " ) ;
2008-03-30 09:00:22 +02:00
}
}
}
return ;
}
else if ( strcmp ( cmd , " unload " ) = = 0 )
{
if ( argcount < 4 )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Usage: sm exts unload <#> [code] " ) ;
2008-03-30 09:00:22 +02:00
return ;
}
2015-08-28 04:59:04 +02:00
const char * arg = command - > Arg ( 3 ) ;
2008-03-30 09:00:22 +02:00
unsigned int num = atoi ( arg ) ;
CExtension * pExt = FindByOrder ( num ) ;
if ( ! pExt )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Extension number %d was not found. " , num ) ;
2008-03-30 09:00:22 +02:00
return ;
}
if ( argcount > 4 & & pExt - > unload_code )
{
2015-08-28 04:59:04 +02:00
const char * unload = command - > Arg ( 4 ) ;
2008-03-30 09:00:22 +02:00
if ( pExt - > unload_code = = ( unsigned ) atoi ( unload ) )
{
char filename [ PLATFORM_MAX_PATH ] ;
2018-03-25 22:00:53 +02:00
ke : : SafeStrcpy ( filename , PLATFORM_MAX_PATH , pExt - > GetFilename ( ) ) ;
2008-03-30 09:00:22 +02:00
UnloadExtension ( pExt ) ;
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Extension %s is now unloaded. " , filename ) ;
2008-03-30 09:00:22 +02:00
}
else
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Please try again, the correct unload code is \" %d \" " , pExt - > unload_code ) ;
2008-03-30 09:00:22 +02:00
}
return ;
}
if ( ! pExt - > IsLoaded ( )
2008-05-26 09:51:11 +02:00
| | ( ! pExt - > m_ChildDeps . size ( ) & & ! pExt - > m_Dependents . size ( ) ) )
2008-03-30 09:00:22 +02:00
{
char filename [ PLATFORM_MAX_PATH ] ;
2018-03-25 22:00:53 +02:00
ke : : SafeStrcpy ( filename , PLATFORM_MAX_PATH , pExt - > GetFilename ( ) ) ;
2008-03-30 09:00:22 +02:00
UnloadExtension ( pExt ) ;
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Extension %s is now unloaded. " , filename ) ;
2008-03-30 09:00:22 +02:00
return ;
}
else
{
2008-05-26 09:51:11 +02:00
List < CPlugin * > plugins ;
2008-03-30 09:00:22 +02:00
if ( pExt - > m_ChildDeps . size ( ) )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Unloading %s will unload the following extensions: " , pExt - > GetFilename ( ) ) ;
2008-03-30 09:00:22 +02:00
List < CExtension * > : : iterator iter ;
CExtension * pOther ;
/* Get list of all extensions */
for ( iter = m_Libs . begin ( ) ; iter ! = m_Libs . end ( ) ; iter + + )
{
List < IfaceInfo > : : iterator i_iter ;
pOther = ( * iter ) ;
if ( ! pOther - > IsLoaded ( ) | | pOther = = pExt )
{
continue ;
}
/* Get their dependencies */
for ( i_iter = pOther - > m_Deps . begin ( ) ;
i_iter ! = pOther - > m_Deps . end ( ) ;
i_iter + + )
{
/* Is this dependency to us? */
if ( ( * i_iter ) . owner ! = pExt )
{
continue ;
}
/* Will our dependent care? */
if ( ! pExt - > GetAPI ( ) - > QueryInterfaceDrop ( ( * i_iter ) . iface ) )
{
2016-02-27 21:22:09 +01:00
rootmenu - > ConsolePrint ( " -> %s " , pOther - > GetFilename ( ) ) ;
2008-03-30 09:00:22 +02:00
/* Add to plugin unload list */
2008-05-26 09:51:11 +02:00
List < CPlugin * > : : iterator p_iter ;
for ( p_iter = pOther - > m_Dependents . begin ( ) ;
p_iter ! = pOther - > m_Dependents . end ( ) ;
2008-03-30 09:00:22 +02:00
p_iter + + )
{
if ( plugins . find ( ( * p_iter ) ) = = plugins . end ( ) )
{
plugins . push_back ( ( * p_iter ) ) ;
}
}
}
}
}
}
2008-05-26 09:51:11 +02:00
if ( pExt - > m_Dependents . size ( ) )
2008-03-30 09:00:22 +02:00
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Unloading %s will unload the following plugins: " , pExt - > GetFilename ( ) ) ;
2008-05-26 09:51:11 +02:00
List < CPlugin * > : : iterator iter ;
CPlugin * pPlugin ;
for ( iter = pExt - > m_Dependents . begin ( ) ; iter ! = pExt - > m_Dependents . end ( ) ; iter + + )
2008-03-30 09:00:22 +02:00
{
pPlugin = ( * iter ) ;
if ( plugins . find ( pPlugin ) = = plugins . end ( ) )
{
plugins . push_back ( pPlugin ) ;
}
}
for ( iter = plugins . begin ( ) ; iter ! = plugins . end ( ) ; iter + + )
{
pPlugin = ( * iter ) ;
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " -> %s " , pPlugin - > GetFilename ( ) ) ;
2008-03-30 09:00:22 +02:00
}
}
srand ( static_cast < int > ( time ( NULL ) ) ) ;
pExt - > unload_code = ( rand ( ) % 877 ) + 123 ; //123 to 999
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] To verify unloading %s, please use the following: " , pExt - > GetFilename ( ) ) ;
rootmenu - > ConsolePrint ( " [SM] sm exts unload %d %d " , num , pExt - > unload_code ) ;
2008-03-30 09:00:22 +02:00
return ;
}
}
2009-08-23 23:11:42 +02:00
else if ( strcmp ( cmd , " reload " ) = = 0 )
{
if ( argcount < 4 )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Usage: sm exts reload <#> " ) ;
2009-08-23 23:11:42 +02:00
return ;
}
2015-08-28 04:59:04 +02:00
const char * arg = command - > Arg ( 3 ) ;
2009-08-23 23:11:42 +02:00
unsigned int num = atoi ( arg ) ;
CExtension * pExt = FindByOrder ( num ) ;
if ( ! pExt )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Extension number %d was not found. " , num ) ;
2009-08-23 23:11:42 +02:00
return ;
}
if ( pExt - > IsLoaded ( ) )
{
char filename [ PLATFORM_MAX_PATH ] ;
char error [ 255 ] ;
2018-03-25 22:00:53 +02:00
ke : : SafeStrcpy ( filename , PLATFORM_MAX_PATH , pExt - > GetFilename ( ) ) ;
2009-08-23 23:11:42 +02:00
if ( pExt - > Reload ( error , sizeof ( error ) ) )
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Extension %s is now reloaded. " , filename ) ;
2009-08-23 23:11:42 +02:00
}
else
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Extension %s failed to reload: %s " , filename , error ) ;
2009-08-23 23:11:42 +02:00
}
return ;
2009-08-30 09:03:58 +02:00
}
2009-08-23 23:11:42 +02:00
else
{
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " [SM] Extension %s is not loaded. " , pExt - > GetFilename ( ) ) ;
2009-08-23 23:11:42 +02:00
return ;
}
}
2008-03-30 09:00:22 +02:00
}
2013-03-29 19:37:29 +01:00
rootmenu - > ConsolePrint ( " SourceMod Extensions Menu: " ) ;
rootmenu - > DrawGenericOption ( " info " , " Extra extension information " ) ;
rootmenu - > DrawGenericOption ( " list " , " List extensions " ) ;
rootmenu - > DrawGenericOption ( " load " , " Load an extension " ) ;
rootmenu - > DrawGenericOption ( " reload " , " Reload an extension " ) ;
rootmenu - > DrawGenericOption ( " unload " , " Unload an extension " ) ;
2012-05-27 02:51:08 +02:00
}
2008-03-30 09:00:22 +02:00
CExtension * CExtensionManager : : GetExtensionFromIdent ( IdentityToken_t * ptr )
{
if ( ptr - > type = = g_ExtType )
{
return ( CExtension * ) ( ptr - > ptr ) ;
}
return NULL ;
}
CExtensionManager : : CExtensionManager ( )
{
}
CExtensionManager : : ~ CExtensionManager ( )
{
}
void CExtensionManager : : AddLibrary ( IExtension * pSource , const char * library )
{
CExtension * pExt = ( CExtension * ) pSource ;
pExt - > AddLibrary ( library ) ;
2013-03-29 19:37:29 +01:00
scripts - > OnLibraryAction ( library , LibraryAction_Added ) ;
2008-03-30 09:00:22 +02:00
}
bool CExtensionManager : : LibraryExists ( const char * library )
{
CExtension * pExt ;
for ( List < CExtension * > : : iterator iter = m_Libs . begin ( ) ;
iter ! = m_Libs . end ( ) ;
iter + + )
{
pExt = ( * iter ) ;
for ( List < String > : : iterator s_iter = pExt - > m_Libraries . begin ( ) ;
s_iter ! = pExt - > m_Libraries . end ( ) ;
s_iter + + )
{
if ( ( * s_iter ) . compare ( library ) = = 0 )
{
return true ;
}
}
}
return false ;
}
IExtension * CExtensionManager : : LoadExternal ( IExtensionInterface * pInterface ,
const char * filepath ,
const char * filename ,
char * error ,
size_t maxlength )
{
IExtension * pAlready ;
if ( ( pAlready = FindExtensionByFile ( filename ) ) ! = NULL )
{
return pAlready ;
}
CExtension * pExt = new CRemoteExtension ( pInterface , filename , filepath ) ;
if ( ! pExt - > Load ( error , maxlength ) | | ! pExt - > IsLoaded ( ) )
{
pExt - > Unload ( ) ;
delete pExt ;
return NULL ;
}
m_Libs . push_back ( pExt ) ;
return pExt ;
}
2008-04-12 03:35:45 +02:00
void CExtensionManager : : CallOnCoreMapStart ( edict_t * pEdictList , int edictCount , int clientMax )
{
2008-04-13 06:00:44 +02:00
IExtensionInterface * pAPI ;
2008-04-12 03:35:45 +02:00
List < CExtension * > : : iterator iter ;
for ( iter = m_Libs . begin ( ) ; iter ! = m_Libs . end ( ) ; iter + + )
{
2008-04-13 06:00:44 +02:00
if ( ( pAPI = ( * iter ) - > GetAPI ( ) ) = = NULL )
{
continue ;
}
if ( pAPI - > GetExtensionVersion ( ) > 3 )
2008-04-12 03:35:45 +02:00
{
2008-04-13 06:00:44 +02:00
pAPI - > OnCoreMapStart ( pEdictList , edictCount , clientMax ) ;
2008-04-12 03:35:45 +02:00
}
}
}
2009-08-30 09:03:58 +02:00
2014-08-08 07:01:47 +02:00
void CExtensionManager : : CallOnCoreMapEnd ( )
{
IExtensionInterface * pAPI ;
List < CExtension * > : : iterator iter ;
for ( iter = m_Libs . begin ( ) ; iter ! = m_Libs . end ( ) ; iter + + )
{
if ( ( pAPI = ( * iter ) - > GetAPI ( ) ) = = NULL )
{
continue ;
}
if ( pAPI - > GetExtensionVersion ( ) > 7 )
{
pAPI - > OnCoreMapEnd ( ) ;
}
}
}
2013-03-31 22:30:22 +02:00
const CVector < IExtension * > * CExtensionManager : : ListExtensions ( )
2013-03-29 19:37:29 +01:00
{
2013-03-31 22:30:22 +02:00
CVector < IExtension * > * list = new CVector < IExtension * > ( ) ;
2013-03-29 19:37:29 +01:00
for ( List < CExtension * > : : iterator iter = m_Libs . begin ( ) ; iter ! = m_Libs . end ( ) ; iter + + )
list - > push_back ( * iter ) ;
2013-03-31 22:30:22 +02:00
return list ;
}
void CExtensionManager : : FreeExtensionList ( const CVector < IExtension * > * list )
{
delete const_cast < CVector < IExtension * > * > ( list ) ;
2013-03-29 19:37:29 +01:00
}
2009-08-30 09:03:58 +02:00
bool CLocalExtension : : IsSameFile ( const char * file )
{
/* Only care about the shortened name. */
return strcmp ( file , m_File . c_str ( ) ) = = 0 ;
}
bool CRemoteExtension : : IsSameFile ( const char * file )
{
2019-07-29 12:41:29 +02:00
/* Check full path and name passed in from LoadExternal */
return strcmp ( file , m_Path . c_str ( ) ) = = 0 | | strcmp ( file , m_File . c_str ( ) ) = = 0 ;
2009-08-30 09:03:58 +02:00
}