[server] Implement a few CPlugins member functions

This commit is contained in:
RD42 2024-04-18 22:41:01 +08:00
parent 9dfb9f748e
commit 32f2bc4e94
4 changed files with 388 additions and 3 deletions

View File

@ -59,6 +59,7 @@
// Std
#include <map>
#include <string>
#include <vector>
// Raknet
#include "../raknet/RakServer.h"

View File

@ -4,6 +4,49 @@
//----------------------------------------------------------
#define SAMP_PLUGIN_VERSION 0x0220
//----------------------------------------------------------
#ifdef __cplusplus
#define PLUGIN_EXTERN_C extern "C"
#else
#define PLUGIN_EXTERN_C
#endif
#if defined(LINUX) || defined(FREEBSD) || defined(__FreeBSD__) || defined(__OpenBSD__)
#ifndef __GNUC__
#pragma message "Warning: Not using a GNU compiler."
#endif
#define PLUGIN_CALL
#ifndef SAMPSVR
// Compile code with -fvisibility=hidden to hide non-exported functions.
#define PLUGIN_EXPORT PLUGIN_EXTERN_C __attribute__((visibility("default")))
#else
#define PLUGIN_EXPORT PLUGIN_EXTERN_C
#endif
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
#ifndef _MSC_VER
#pragma message "Warning: Not using a VC++ compiler."
#endif
#define PLUGIN_CALL __stdcall
#define PLUGIN_EXPORT PLUGIN_EXTERN_C
#else
#error "You must define one of WIN32, LINUX or FREEBSD"
#endif
//----------------------------------------------------------
enum SUPPORTS_FLAGS
{
SUPPORTS_VERSION = SAMP_PLUGIN_VERSION,
SUPPORTS_VERSION_MASK = 0xffff,
SUPPORTS_AMX_NATIVES = 0x10000,
SUPPORTS_PROCESS_TICK = 0x20000,
};
//----------------------------------------------------------
enum PLUGIN_DATA_TYPE
{
// For some debugging
@ -65,4 +108,9 @@ enum PLUGIN_AMX_EXPORT
PLUGIN_AMX_EXPORT_UTF8Put = 43,
};
//----------------------------------------------------------
#endif // _PLUGINCOMMON_H_INCLUDED
//----------------------------------------------------------
// EOF

View File

@ -127,10 +127,290 @@ CPlugins::CPlugins()
CPlugins::~CPlugins()
{
// TODO: CPlugins::~CPlugins W: 00469DB0 L: 080D20E0
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)
{
// TODO: CPlugins::LoadPlugins W: 0046A570 L: 080D29E0
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);
}
}
//---------------------------------------

View File

@ -5,18 +5,74 @@
#include "plugincommon.h"
#include "plugininternal.h"
class CPlugins // size: W: 1216 L: 1212
#ifdef LINUX
#include <dlfcn.h>
#define PLUGIN_LOAD(p) dlopen(p, RTLD_LAZY)
#define PLUGIN_UNLOAD dlclose
#define PLUGIN_GETFUNCTION dlsym
#else
#define PLUGIN_LOAD LoadLibrary
#define PLUGIN_UNLOAD FreeLibrary
#define PLUGIN_GETFUNCTION GetProcAddress
#endif
typedef bool (PLUGIN_CALL *ServerPluginLoad_t)(void **data);
typedef void (PLUGIN_CALL *ServerPluginUnload_t)();
typedef unsigned int (PLUGIN_CALL *ServerPluginSupports_t)();
typedef void (PLUGIN_CALL *ServerPluginProcessTick_t)();
typedef int (PLUGIN_CALL *ServerPluginAmxLoad_t)(AMX *amx);
typedef int (PLUGIN_CALL *ServerPluginAmxUnload_t)(AMX *amx);
struct ServerPlugin_s
{
#ifdef LINUX
void *hModule;
#else
HMODULE hModule;
#endif
SUPPORTS_FLAGS dwSupportFlags;
// Core Plugin Interface
ServerPluginLoad_t Load;
ServerPluginUnload_t Unload;
ServerPluginSupports_t Supports;
ServerPluginProcessTick_t ProcessTick;
// AMX Plugin Interface
ServerPluginAmxLoad_t AmxLoad;
ServerPluginAmxUnload_t AmxUnload;
};
typedef std::vector<ServerPlugin_s*> ServerPluginVector;
//---------------------------------------
class CPlugins
{
private:
void* m_PluginData[MAX_PLUGIN_DATA];
void* m_AMXExports[MAX_PLUGIN_AMX_EXPORT];
ServerPluginVector m_Plugins;
BOOL LoadSinglePlugin(char *szPluginPath);
public:
CPlugins();
~CPlugins();
void LoadPlugins(char *szSearchPath);
void LoadPluginsSearch(char *szSearchPath);
DWORD GetPluginCount();
ServerPlugin_s* GetPlugin(DWORD index);
void DoProcessTick();
void DoAmxLoad(AMX *amx);
void DoAmxUnload(AMX *amx);
};
#endif