SA-MP/server/plugins.cpp

417 lines
11 KiB
C++

#include "main.h"
//---------------------------------------
// 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;
}
//---------------------------------------
CPlugins::CPlugins()
{
// 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;
m_PluginData[PLUGIN_DATA_CALLPUBLIC_FS] = (void*)&PluginCallPublicFS;
m_PluginData[PLUGIN_DATA_CALLPUBLIC_GM] = (void*)&PluginCallPublicGM;
// 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;
}
//---------------------------------------
CPlugins::~CPlugins()
{
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;
}
//---------------------------------------
void CPlugins::LoadPlugins(char *szSearchPath)
{
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());
}
// [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);
}
}
//---------------------------------------