2022-08-20 01:59:36 +02:00
//=============================================================================//
//
2022-08-21 00:59:55 +02:00
// Purpose: plugin system that manages plugins!
2022-08-20 01:59:36 +02:00
//
//-----------------------------------------------------------------------------
//
//=============================================================================//
# include "core/stdafx.h"
# include "pluginsystem.h"
//-----------------------------------------------------------------------------
// Purpose: initialize the plugin system
// Input :
//-----------------------------------------------------------------------------
void CPluginSystem : : PluginSystem_Init ( )
{
2022-11-08 21:17:40 +01:00
CreateDirectories ( " bin \\ x64_retail \\ plugins " ) ;
2022-08-20 01:59:36 +02:00
2022-11-08 21:17:40 +01:00
for ( auto & it : fs : : directory_iterator ( " bin \\ x64_retail \\ plugins " ) )
2022-08-20 11:28:28 +02:00
{
2023-03-20 00:19:17 +01:00
if ( ! fs : : is_regular_file ( it ) )
2022-08-20 11:28:28 +02:00
continue ;
if ( auto path = it . path ( ) ; path . has_filename ( ) & & path . has_extension ( ) & & path . extension ( ) . compare ( " .dll " ) = = 0 )
{
bool addInstance = true ;
for ( auto & inst : pluginInstances )
{
if ( inst . m_svPluginFullPath . compare ( path . u8string ( ) ) = = 0 )
addInstance = false ;
}
if ( addInstance )
2022-08-20 12:42:19 +02:00
pluginInstances . push_back ( PluginInstance_t ( path . filename ( ) . u8string ( ) , path . u8string ( ) ) ) ;
2022-08-20 11:28:28 +02:00
}
}
2022-08-20 01:59:36 +02:00
}
//-----------------------------------------------------------------------------
// Purpose: load a plugin instance
// Input : pluginInst* -
// Output : bool
//-----------------------------------------------------------------------------
2022-08-20 12:42:19 +02:00
bool CPluginSystem : : LoadPluginInstance ( PluginInstance_t & pluginInst )
2022-08-20 01:59:36 +02:00
{
2022-08-20 11:28:28 +02:00
if ( pluginInst . m_bIsLoaded )
2022-08-20 01:59:36 +02:00
return false ;
HMODULE loadedPlugin = LoadLibraryA ( pluginInst . m_svPluginFullPath . c_str ( ) ) ;
2022-08-21 00:59:55 +02:00
if ( loadedPlugin = = INVALID_HANDLE_VALUE | | loadedPlugin = = 0 )
2022-08-20 01:59:36 +02:00
return false ;
2022-08-21 00:59:55 +02:00
CModule pluginModule = CModule ( pluginInst . m_svPluginName ) ;
2022-08-20 01:59:36 +02:00
2022-12-25 14:49:24 +01:00
// Pass selfModule here on load function, we have to do this because local listen/dedi/client dll's are called different, refer to a comment on the pluginsdk.
2022-08-21 00:59:55 +02:00
auto onLoadFn = pluginModule . GetExportedFunction ( " PluginInstance_OnLoad " ) . RCast < PluginInstance_t : : OnLoad > ( ) ;
2022-08-20 11:28:28 +02:00
Assert ( onLoadFn ) ;
2022-08-20 01:59:36 +02:00
2022-08-21 00:59:55 +02:00
if ( ! onLoadFn ( pluginInst . m_svPluginName . c_str ( ) ) )
{
FreeLibrary ( loadedPlugin ) ;
return false ;
}
2022-08-20 01:59:36 +02:00
2022-08-21 00:59:55 +02:00
pluginInst . m_hModule = pluginModule ;
2022-08-20 01:59:36 +02:00
2022-08-20 11:28:28 +02:00
return pluginInst . m_bIsLoaded = true ;
2022-08-20 01:59:36 +02:00
}
//-----------------------------------------------------------------------------
// Purpose: unload a plugin instance
// Input : pluginInst* -
// Output : bool
//-----------------------------------------------------------------------------
2022-08-20 12:42:19 +02:00
bool CPluginSystem : : UnloadPluginInstance ( PluginInstance_t & pluginInst )
2022-08-20 01:59:36 +02:00
{
if ( ! pluginInst . m_bIsLoaded )
return false ;
2022-08-20 12:42:19 +02:00
auto onUnloadFn = pluginInst . m_hModule . GetExportedFunction ( " PluginInstance_OnUnload " ) . RCast < PluginInstance_t : : OnUnload > ( ) ;
2022-08-21 00:59:55 +02:00
Assert ( onUnloadFn ) ;
2022-08-20 01:59:36 +02:00
if ( onUnloadFn )
2022-08-21 00:59:55 +02:00
onUnloadFn ( ) ;
2022-08-20 01:59:36 +02:00
bool unloadOk = FreeLibrary ( ( HMODULE ) pluginInst . m_hModule . GetModuleBase ( ) ) ;
2022-08-20 11:28:28 +02:00
Assert ( unloadOk ) ;
pluginInst . m_bIsLoaded = false ;
2022-08-20 01:59:36 +02:00
return unloadOk ;
}
//-----------------------------------------------------------------------------
// Purpose: reload a plugin instance
// Input : pluginInst* -
// Output : bool
//-----------------------------------------------------------------------------
2022-08-20 12:42:19 +02:00
bool CPluginSystem : : ReloadPluginInstance ( PluginInstance_t & pluginInst )
2022-08-20 01:59:36 +02:00
{
return UnloadPluginInstance ( pluginInst ) ? LoadPluginInstance ( pluginInst ) : false ;
}
//-----------------------------------------------------------------------------
// Purpose: get all plugin instances
// Input :
// Output : vector<CPluginSystem::PluginInstance>&
//-----------------------------------------------------------------------------
2022-08-20 12:42:19 +02:00
vector < CPluginSystem : : PluginInstance_t > & CPluginSystem : : GetPluginInstances ( )
2022-08-20 01:59:36 +02:00
{
return pluginInstances ;
2022-08-20 11:42:22 +02:00
}
2022-08-20 12:42:19 +02:00
//-----------------------------------------------------------------------------
2022-12-12 17:16:39 +01:00
// Purpose: add plugin callback for function
// Input : *help
// Output : void
//-----------------------------------------------------------------------------
void CPluginSystem : : AddPluginCallback ( PluginHelpWithAnything_t * help )
{
# define ADD_PLUGIN_CALLBACK(fn, callback, function) callback += reinterpret_cast<fn>(function)
switch ( help - > m_nCallbackID )
{
case PluginHelpWithAnything_t : : ePluginCallback : : CModAppSystemGroup_Create :
{
ADD_PLUGIN_CALLBACK ( CreateFn , GetCreateCallbacks ( ) , help - > m_pFunction ) ;
break ;
}
default :
break ;
}
# undef ADD_PLUGIN_CALLBACK
}
//-----------------------------------------------------------------------------
// Purpose: remove plugin callback for function
// Input : *help
// Output : void
2022-08-20 12:42:19 +02:00
//-----------------------------------------------------------------------------
2022-12-12 17:16:39 +01:00
void CPluginSystem : : RemovePluginCallback ( PluginHelpWithAnything_t * help )
2022-08-20 12:42:19 +02:00
{
2022-12-12 17:16:39 +01:00
# define REMOVE_PLUGIN_CALLBACK(fn, callback, function) callback -= reinterpret_cast<fn>(function)
switch ( help - > m_nCallbackID )
{
case PluginHelpWithAnything_t : : ePluginCallback : : CModAppSystemGroup_Create :
{
REMOVE_PLUGIN_CALLBACK ( CreateFn , GetCreateCallbacks ( ) , help - > m_pFunction ) ;
break ;
}
default :
break ;
}
# undef REMOVE_PLUGIN_CALLBACK
2022-08-20 12:42:19 +02:00
}
//-----------------------------------------------------------------------------
// Purpose: help plugins with anything
// Input : *help
// Output : void*
//-----------------------------------------------------------------------------
void * CPluginSystem : : HelpWithAnything ( PluginHelpWithAnything_t * help )
{
switch ( help - > m_nHelpID )
{
case PluginHelpWithAnything_t : : ePluginHelp : : PLUGIN_GET_FUNCTION :
{
break ;
}
case PluginHelpWithAnything_t : : ePluginHelp : : PLUGIN_REGISTER_CALLBACK :
{
2022-12-12 17:16:39 +01:00
AddPluginCallback ( help ) ;
2022-08-20 12:42:19 +02:00
break ;
}
case PluginHelpWithAnything_t : : ePluginHelp : : PLUGIN_UNREGISTER_CALLBACK :
{
2022-12-12 17:16:39 +01:00
RemovePluginCallback ( help ) ;
2022-08-20 12:42:19 +02:00
break ;
}
default :
break ;
}
return nullptr ;
}
2022-08-20 11:42:22 +02:00
CPluginSystem * g_pPluginSystem = new CPluginSystem ( ) ;