2023-10-29 00:00:36 +08:00
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
2024-04-12 22:09:26 +08:00
|
|
|
//---------------------------------------
|
|
|
|
// Some Helpers
|
|
|
|
|
|
|
|
extern "C" RakServerInterface* PluginGetRakServer()
|
|
|
|
{
|
|
|
|
if (pNetGame != NULL)
|
|
|
|
return pNetGame->GetRakServer();
|
|
|
|
else
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" CNetGame* PluginGetNetGame()
|
|
|
|
{
|
|
|
|
return pNetGame;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" CConsole* PluginGetConsole()
|
|
|
|
{
|
|
|
|
return pConsole;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" bool PluginUnloadFilterScript(char* pFileName)
|
|
|
|
{
|
|
|
|
if (pNetGame != NULL)
|
|
|
|
return pNetGame->GetFilterScripts()->UnloadOneFilterScript(pFileName);
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" bool PluginLoadFilterScriptFromMemory(char* pFileName, char* pFileData)
|
|
|
|
{
|
|
|
|
if (pNetGame != NULL)
|
|
|
|
return pNetGame->GetFilterScripts()->LoadFilterScriptFromMemory(pFileName, pFileData);
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int PluginCallPublicFS(char *szFunctionName)
|
|
|
|
{
|
|
|
|
if (pNetGame != NULL)
|
|
|
|
return pNetGame->GetFilterScripts()->CallPublic(szFunctionName);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int PluginCallPublicGM(char *szFunctionName)
|
|
|
|
{
|
|
|
|
if (pNetGame != NULL && pNetGame->GetGameMode())
|
|
|
|
return pNetGame->GetGameMode()->CallPublic(szFunctionName);
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
|
|
|
2023-10-29 00:00:36 +08:00
|
|
|
CPlugins::CPlugins()
|
|
|
|
{
|
2023-11-23 23:34:47 +08:00
|
|
|
// Set up the table of AMX functions to be exported
|
|
|
|
#if defined AMX_ALIGN || defined AMX_INIT
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Align16] = (void*)&amx_Align16;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Align32] = (void*)&amx_Align32;
|
|
|
|
#if defined _I64_MAX || defined HAVE_I64
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Align64] = (void*)&amx_Align64;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Allot] = (void*)&amx_Allot;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Callback] = (void*)&amx_Callback;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Cleanup] = (void*)&amx_Cleanup;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Clone] = (void*)&amx_Clone;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Exec] = (void*)&amx_Exec;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_FindNative] = (void*)&amx_FindNative;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_FindPublic] = (void*)&amx_FindPublic;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_FindPubVar] = (void*)&amx_FindPubVar;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_FindTagId] = (void*)&amx_FindTagId;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Flags] = (void*)&amx_Flags;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_GetAddr] = (void*)&amx_GetAddr;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_GetNative] = (void*)&amx_GetNative;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_GetPublic] = (void*)&amx_GetPublic;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_GetPubVar] = (void*)&amx_GetPubVar;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_GetString] = (void*)&amx_GetString;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_GetTag] = (void*)&amx_GetTag;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_GetUserData] = (void*)&amx_GetUserData;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Init] = (void*)&amx_Init;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_InitJIT] = (void*)&amx_InitJIT;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_MemInfo] = (void*)&amx_MemInfo;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_NameLength] = (void*)&amx_NameLength;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_NativeInfo] = (void*)&amx_NativeInfo;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_NumNatives] = (void*)&amx_NumNatives;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_NumPublics] = (void*)&amx_NumPublics;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_NumPubVars] = (void*)&amx_NumPubVars;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_NumTags] = (void*)&amx_NumTags;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Push] = (void*)&amx_Push;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_PushArray] = (void*)&amx_PushArray;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_PushString] = (void*)&amx_PushString;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_RaiseError] = (void*)&amx_RaiseError;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Register] = (void*)&amx_Register;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_Release] = (void*)&amx_Release;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_SetCallback] = (void*)&amx_SetCallback;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_SetDebugHook] = (void*)&amx_SetDebugHook;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_SetString] = (void*)&amx_SetString;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_SetUserData] = (void*)&amx_SetUserData;
|
|
|
|
m_AMXExports[PLUGIN_AMX_EXPORT_StrLen] = (void*)&amx_StrLen;
|
|
|
|
//m_AMXExports[PLUGIN_AMX_EXPORT_UTF8Check] = (void*)&amx_UTF8Check;
|
|
|
|
//m_AMXExports[PLUGIN_AMX_EXPORT_UTF8Get] = (void*)&amx_UTF8Get;
|
|
|
|
//m_AMXExports[PLUGIN_AMX_EXPORT_UTF8Len] = (void*)&amx_UTF8Len;
|
|
|
|
//m_AMXExports[PLUGIN_AMX_EXPORT_UTF8Put] = (void*)&amx_UTF8Put;
|
|
|
|
|
|
|
|
// Set up table of Plugin exports
|
|
|
|
m_PluginData[PLUGIN_DATA_LOGPRINTF] = (void*)&logprintf;
|
|
|
|
|
|
|
|
m_PluginData[PLUGIN_DATA_AMX_EXPORTS] = m_AMXExports;
|
2024-04-12 22:09:26 +08:00
|
|
|
m_PluginData[PLUGIN_DATA_CALLPUBLIC_FS] = (void*)&PluginCallPublicFS;
|
|
|
|
m_PluginData[PLUGIN_DATA_CALLPUBLIC_GM] = (void*)&PluginCallPublicGM;
|
2023-11-23 23:34:47 +08:00
|
|
|
|
2024-04-12 22:09:26 +08:00
|
|
|
// Internals
|
|
|
|
m_PluginData[PLUGIN_DATA_NETGAME] = (void*)&PluginGetNetGame;
|
|
|
|
m_PluginData[PLUGIN_DATA_CONSOLE] = (void*)&PluginGetConsole;
|
|
|
|
m_PluginData[PLUGIN_DATA_RAKSERVER] = (void*)&PluginGetRakServer;
|
|
|
|
m_PluginData[PLUGIN_DATA_LOADFSCRIPT] = (void*)&PluginLoadFilterScriptFromMemory;
|
|
|
|
m_PluginData[PLUGIN_DATA_UNLOADFSCRIPT] = (void*)&PluginUnloadFilterScript;
|
2023-10-29 00:00:36 +08:00
|
|
|
}
|
|
|
|
|
2024-04-12 22:09:26 +08:00
|
|
|
//---------------------------------------
|
|
|
|
|
2023-10-29 00:00:36 +08:00
|
|
|
CPlugins::~CPlugins()
|
|
|
|
{
|
2024-04-18 22:41:01 +08:00
|
|
|
ServerPluginVector::iterator itor;
|
|
|
|
|
|
|
|
for(itor=m_Plugins.begin(); itor!=m_Plugins.end(); itor++)
|
|
|
|
{
|
|
|
|
ServerPlugin_s* pSPlugin = *itor;
|
|
|
|
if (pSPlugin->Unload)
|
|
|
|
pSPlugin->Unload();
|
|
|
|
PLUGIN_UNLOAD(pSPlugin->hModule);
|
|
|
|
delete pSPlugin;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
|
|
|
|
|
|
BOOL CPlugins::LoadSinglePlugin(char *szPluginPath)
|
|
|
|
{
|
|
|
|
// Load it
|
|
|
|
ServerPlugin_s* pSPlugin;
|
|
|
|
pSPlugin = new ServerPlugin_s();
|
|
|
|
|
|
|
|
pSPlugin->hModule = PLUGIN_LOAD(szPluginPath);
|
|
|
|
if (pSPlugin->hModule == NULL)
|
|
|
|
{
|
|
|
|
// Failed to load
|
|
|
|
delete pSPlugin;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pSPlugin->Load = (ServerPluginLoad_t)PLUGIN_GETFUNCTION(pSPlugin->hModule, "Load");
|
|
|
|
pSPlugin->Unload = (ServerPluginUnload_t)PLUGIN_GETFUNCTION(pSPlugin->hModule, "Unload");
|
|
|
|
pSPlugin->Supports = (ServerPluginSupports_t)PLUGIN_GETFUNCTION(pSPlugin->hModule, "Supports");
|
|
|
|
|
|
|
|
if (pSPlugin->Load == NULL || pSPlugin->Supports == NULL)
|
|
|
|
{
|
|
|
|
// Not proper architecture!
|
|
|
|
logprintf(" Plugin does not conform to architecture.");
|
|
|
|
PLUGIN_UNLOAD(pSPlugin->hModule);
|
|
|
|
delete pSPlugin;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pSPlugin->dwSupportFlags = (SUPPORTS_FLAGS)pSPlugin->Supports();
|
|
|
|
|
|
|
|
if ((pSPlugin->dwSupportFlags & SUPPORTS_VERSION_MASK) > SUPPORTS_VERSION)
|
|
|
|
{
|
|
|
|
// Unsupported version, sorry!
|
|
|
|
logprintf(" Unsupported version - This plugin requires version %x.", (pSPlugin->dwSupportFlags & SUPPORTS_VERSION_MASK));
|
|
|
|
PLUGIN_UNLOAD(pSPlugin->hModule);
|
|
|
|
delete pSPlugin;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((pSPlugin->dwSupportFlags & SUPPORTS_AMX_NATIVES) != 0)
|
|
|
|
{
|
|
|
|
pSPlugin->AmxLoad = (ServerPluginAmxLoad_t)PLUGIN_GETFUNCTION(pSPlugin->hModule, "AmxLoad");
|
|
|
|
pSPlugin->AmxUnload = (ServerPluginAmxUnload_t)PLUGIN_GETFUNCTION(pSPlugin->hModule, "AmxUnload");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pSPlugin->AmxLoad = NULL;
|
|
|
|
pSPlugin->AmxUnload = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((pSPlugin->dwSupportFlags & SUPPORTS_PROCESS_TICK) != 0)
|
|
|
|
{
|
|
|
|
pSPlugin->ProcessTick = (ServerPluginProcessTick_t)PLUGIN_GETFUNCTION(pSPlugin->hModule, "ProcessTick");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pSPlugin->ProcessTick = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pSPlugin->Load(m_PluginData))
|
|
|
|
{
|
|
|
|
// Initialize failed!
|
|
|
|
PLUGIN_UNLOAD(pSPlugin->hModule);
|
|
|
|
delete pSPlugin;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_Plugins.push_back(pSPlugin);
|
|
|
|
|
|
|
|
return TRUE;
|
2023-10-29 00:00:36 +08:00
|
|
|
}
|
|
|
|
|
2024-04-18 22:41:01 +08:00
|
|
|
//---------------------------------------
|
|
|
|
|
2023-10-29 00:00:36 +08:00
|
|
|
void CPlugins::LoadPlugins(char *szSearchPath)
|
|
|
|
{
|
2024-04-18 22:41:01 +08:00
|
|
|
char szPath[MAX_PATH];
|
|
|
|
char szFullPath[MAX_PATH];
|
|
|
|
char *szDlerror = NULL;
|
|
|
|
strcpy(szPath, szSearchPath);
|
|
|
|
|
|
|
|
#ifdef LINUX
|
|
|
|
if (szPath[strlen(szPath)-1] != '/')
|
|
|
|
strcat(szPath, "/");
|
|
|
|
#else
|
|
|
|
if (szPath[strlen(szPath)-1] != '\\')
|
|
|
|
strcat(szPath, "\\");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
logprintf("");
|
|
|
|
logprintf("Server Plugins");
|
|
|
|
logprintf("--------------");
|
|
|
|
|
|
|
|
char* szFilename = strtok(pConsole->GetStringVariable("plugins"), " ");
|
|
|
|
while (szFilename)
|
|
|
|
{
|
|
|
|
logprintf(" Loading plugin: %s", szFilename);
|
|
|
|
|
|
|
|
strcpy(szFullPath, szPath);
|
|
|
|
strcat(szFullPath, szFilename);
|
|
|
|
|
|
|
|
if (LoadSinglePlugin(szFullPath))
|
|
|
|
{
|
|
|
|
logprintf(" Loaded.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
#ifdef LINUX
|
|
|
|
szDlerror = PLUGIN_GETERROR();
|
|
|
|
if (szDlerror)
|
|
|
|
logprintf(" Failed (%s)", szDlerror);
|
|
|
|
else
|
|
|
|
logprintf(" Failed.");
|
|
|
|
#else
|
|
|
|
logprintf(" Failed.");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
szFilename = strtok(NULL, " ");
|
|
|
|
}
|
|
|
|
logprintf(" Loaded %d plugins.\n", GetPluginCount());
|
2023-10-29 00:00:36 +08:00
|
|
|
}
|
2024-04-18 22:41:01 +08:00
|
|
|
|
|
|
|
// [OBSOLETE: Using the non search defined method]
|
|
|
|
void CPlugins::LoadPluginsSearch(char *szSearchPath)
|
|
|
|
{
|
|
|
|
#ifdef LINUX
|
|
|
|
DIR *dir = opendir(szSearchPath);
|
|
|
|
struct dirent *file;
|
|
|
|
char *szFilename = NULL;
|
|
|
|
char *szExt = NULL;
|
|
|
|
int iStrLen;
|
|
|
|
char szPath[255];
|
|
|
|
strcpy(szPath, szSearchPath);
|
|
|
|
if (szPath[strlen(szPath)-1] != '/') strcat(szPath, "/");
|
|
|
|
char szFullPath[255];
|
|
|
|
char *szDlerror = NULL;
|
|
|
|
if (dir)
|
|
|
|
{
|
|
|
|
logprintf("");
|
|
|
|
logprintf("Server Plugins");
|
|
|
|
logprintf("--------------");
|
|
|
|
|
|
|
|
// Load the plugins
|
|
|
|
while (dir)
|
|
|
|
{
|
|
|
|
strcpy(szFullPath, szPath);
|
|
|
|
if ((file = readdir(dir)) != NULL)
|
|
|
|
{
|
|
|
|
szFilename = (char*)file->d_name;
|
|
|
|
iStrLen = strlen(szFilename);
|
|
|
|
if (iStrLen > 3)
|
|
|
|
{
|
|
|
|
szExt = szFilename+iStrLen-3;
|
|
|
|
if (strcmp(".so", szExt) == 0)
|
|
|
|
{
|
|
|
|
logprintf(" Loading plugin: %s", szFilename);
|
|
|
|
strcat(szFullPath, szFilename);
|
|
|
|
bool bSuccess = LoadSinglePlugin(szFullPath);
|
|
|
|
if (!bSuccess)
|
|
|
|
{
|
|
|
|
szDlerror = PLUGIN_GETERROR();
|
|
|
|
if (szDlerror)
|
|
|
|
logprintf(" Failed (%s)", szDlerror);
|
|
|
|
else
|
|
|
|
logprintf((" Failed.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
closedir(dir);
|
|
|
|
dir = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
logprintf("");
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
char szPath[MAX_PATH];
|
|
|
|
char szSearch[MAX_PATH];
|
|
|
|
|
|
|
|
strcpy(szPath, szSearchPath);
|
|
|
|
|
|
|
|
char cLastChar = szPath[strlen(szPath)-1];
|
|
|
|
if (cLastChar != '\\' && cLastChar != '/')
|
|
|
|
strcat(szPath, "\\");
|
|
|
|
|
|
|
|
DWORD szPathLen = strlen(szPath);
|
|
|
|
|
|
|
|
strcpy(szSearch, szPath);
|
|
|
|
strcat(szSearch, "*.dll");
|
|
|
|
|
|
|
|
WIN32_FIND_DATA fdFindData;
|
|
|
|
HANDLE hFindFile = FindFirstFile(szSearch, &fdFindData);
|
|
|
|
if (hFindFile != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
logprintf("");
|
|
|
|
logprintf("Server Plugins");
|
|
|
|
logprintf("--------------");
|
|
|
|
|
|
|
|
// Load the plugins
|
|
|
|
while(true) {
|
|
|
|
logprintf(" Loading plugin: %s", fdFindData.cFileName);
|
|
|
|
strcpy(szPath+szPathLen, fdFindData.cFileName);
|
|
|
|
BOOL bSuccess = LoadSinglePlugin(szPath);
|
|
|
|
if (!bSuccess)
|
|
|
|
logprintf(" Failed.");
|
|
|
|
if(!FindNextFile(hFindFile, &fdFindData))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
logprintf("");
|
|
|
|
}
|
|
|
|
FindClose(hFindFile);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
|
|
|
|
|
|
DWORD CPlugins::GetPluginCount()
|
|
|
|
{
|
|
|
|
return (DWORD)m_Plugins.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
|
|
|
|
|
|
ServerPlugin_s* CPlugins::GetPlugin(DWORD index)
|
|
|
|
{
|
|
|
|
return m_Plugins[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
|
|
|
|
|
|
void CPlugins::DoProcessTick()
|
|
|
|
{
|
|
|
|
ServerPluginVector::iterator itor;
|
|
|
|
|
|
|
|
for(itor=m_Plugins.begin(); itor!=m_Plugins.end(); itor++) {
|
|
|
|
ServerPlugin_s* pSPlugin = *itor;
|
|
|
|
if ((pSPlugin->dwSupportFlags & SUPPORTS_PROCESS_TICK) != 0)
|
|
|
|
if (pSPlugin->ProcessTick != NULL)
|
|
|
|
pSPlugin->ProcessTick();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
|
|
|
|
|
|
void CPlugins::DoAmxLoad(AMX *amx)
|
|
|
|
{
|
|
|
|
ServerPluginVector::iterator itor;
|
|
|
|
|
|
|
|
for(itor=m_Plugins.begin(); itor!=m_Plugins.end(); itor++) {
|
|
|
|
ServerPlugin_s* pSPlugin = *itor;
|
|
|
|
if ((pSPlugin->dwSupportFlags & SUPPORTS_AMX_NATIVES) != 0)
|
|
|
|
if (pSPlugin->AmxLoad != NULL)
|
|
|
|
pSPlugin->AmxLoad(amx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
|
|
|
|
|
|
void CPlugins::DoAmxUnload(AMX *amx)
|
|
|
|
{
|
|
|
|
ServerPluginVector::iterator itor;
|
|
|
|
|
|
|
|
for(itor=m_Plugins.begin(); itor!=m_Plugins.end(); itor++) {
|
|
|
|
ServerPlugin_s* pSPlugin = *itor;
|
|
|
|
if ((pSPlugin->dwSupportFlags & SUPPORTS_AMX_NATIVES) != 0)
|
|
|
|
if (pSPlugin->AmxUnload != NULL)
|
|
|
|
pSPlugin->AmxUnload(amx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|