Skip to content

Commit 0c5cdcb

Browse files
committed
SA-MP plugin loader overhaul
* Store plugins in a struct to store additional data alongside them. * Add missing types * Only require Load, Supports and Unload from plugins * Store function pointers in a struct instead of repeatedly using getProcAddr * Use Supports() from plugins to know exactly what the plugin exports * Call Unload on plugins when unloading them * Implement ProcessTick (stored separately to minimize overhead when calling in DoPulse)
1 parent e083c26 commit 0c5cdcb

File tree

3 files changed

+76
-15
lines changed

3 files changed

+76
-15
lines changed

amx-deps/src/CFunctions.cpp

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,47 @@ extern ILuaModuleManager10 *pModuleManager;
2626

2727
int amx_SAMPInit(AMX *amx);
2828

29-
typedef int (STDCALL AmxLoad_t) (AMX *);
30-
typedef int (STDCALL AmxUnload_t) (AMX *);
31-
typedef bool (STDCALL Load_t) (void**);
29+
typedef unsigned int (STDCALL Supports_t) ();
30+
typedef int (STDCALL AmxLoad_t) (AMX *);
31+
typedef int (STDCALL AmxUnload_t) (AMX *);
32+
typedef bool (STDCALL Load_t) (void**);
33+
typedef void (STDCALL Unload_t) ();
34+
35+
#define SAMP_PLUGIN_VERSION 0x0200
36+
37+
enum SUPPORTS_FLAGS
38+
{
39+
SUPPORTS_VERSION = SAMP_PLUGIN_VERSION,
40+
SUPPORTS_VERSION_MASK = 0xffff,
41+
SUPPORTS_AMX_NATIVES = 0x10000,
42+
SUPPORTS_PROCESS_TICK = 0x20000
43+
};
44+
45+
struct SampPlugin
46+
{
47+
HMODULE pPluginPointer = nullptr;
48+
49+
SUPPORTS_FLAGS dwSupportFlags = (SUPPORTS_FLAGS)0;
50+
51+
Unload_t *Unload = nullptr;
52+
53+
AmxLoad_t *AmxLoad = nullptr;
54+
AmxUnload_t *AmxUnload = nullptr;
55+
};
3256

3357
extern void *pluginInitData[];
3458
extern lua_State *mainVM;
3559

3660
map< AMX *, AMXPROPS > loadedAMXs;
3761
map< AMX *, map< int, sqlite3 * > > loadedDBs; // amx => (dbID => db)
38-
map< string, HMODULE > loadedPlugins;
62+
map< string, SampPlugin* > loadedPlugins;
63+
vector<ProcessTick_t*> vecPfnProcessTick;
3964

4065
AMX *suspendedAMX = NULL;
4166

4267
// amxLoadPlugin(pluginName)
4368
int CFunctions::amxLoadPlugin(lua_State *luaVM) {
44-
static const char *requiredExports[] = { "Load", "AmxLoad", "AmxUnload", "Unload", 0 };
69+
static const char *requiredExports[] = { "Load", "Unload", "Supports", 0 };
4570

4671
const char *pluginName = luaL_checkstring(luaVM, 1);
4772
if(!pluginName || loadedPlugins.find(pluginName) != loadedPlugins.end() || !isSafePath(pluginName)) {
@@ -58,6 +83,7 @@ int CFunctions::amxLoadPlugin(lua_State *luaVM) {
5883
#endif
5984

6085
HMODULE hPlugin = loadLib(pluginPath.c_str());
86+
6187
if(!hPlugin) {
6288
lua_pushboolean(luaVM, 0);
6389
return 1;
@@ -77,10 +103,29 @@ int CFunctions::amxLoadPlugin(lua_State *luaVM) {
77103
}
78104

79105
printf("Loading plugin %s\n", pluginName);
80-
Load_t *pfnLoad = (Load_t *)getProcAddr(hPlugin, "Load");
106+
107+
Load_t* pfnLoad = (Load_t *)getProcAddr(hPlugin, "Load");
108+
Supports_t* pfnSupports = (Supports_t *)getProcAddr(hPlugin, "Supports");
109+
110+
SampPlugin* pSampPlugin = new SampPlugin;
111+
pSampPlugin->pPluginPointer = hPlugin;
112+
pSampPlugin->Unload = (Unload_t*)getProcAddr(hPlugin, "Unload");
113+
pSampPlugin->dwSupportFlags = (SUPPORTS_FLAGS)pfnSupports();
114+
115+
if ((pSampPlugin->dwSupportFlags & SUPPORTS_AMX_NATIVES) != 0)
116+
{
117+
pSampPlugin->AmxLoad = (AmxLoad_t *)getProcAddr(hPlugin, "AmxLoad");
118+
pSampPlugin->AmxUnload = (AmxUnload_t *)getProcAddr(hPlugin, "AmxUnload");
119+
}
120+
121+
if ((pSampPlugin->dwSupportFlags & SUPPORTS_PROCESS_TICK) != 0)
122+
{
123+
vecPfnProcessTick.push_back((ProcessTick_t *)getProcAddr(hPlugin, "ProcessTick"));
124+
}
125+
81126
pfnLoad(pluginInitData);
82127

83-
loadedPlugins[pluginName] = hPlugin;
128+
loadedPlugins[pluginName] = pSampPlugin;
84129

85130
lua_pushboolean(luaVM, 1);
86131
return 1;
@@ -127,9 +172,11 @@ int CFunctions::amxLoad(lua_State *luaVM) {
127172
amx_TimeInit(amx);
128173
amx_FileInit(amx);
129174
err = amx_SAMPInit(amx);
130-
for(map< string, HMODULE >::iterator it = loadedPlugins.begin(); it != loadedPlugins.end(); it++) {
131-
AmxLoad_t* pfnAmxLoad = (AmxLoad_t*)getProcAddr(it->second, "AmxLoad");
132-
err = pfnAmxLoad(amx);
175+
for(map< string, SampPlugin* >::iterator it = loadedPlugins.begin(); it != loadedPlugins.end(); it++) {
176+
AmxLoad_t* pfnAmxLoad = it->second->AmxLoad;
177+
if (pfnAmxLoad) {
178+
err = pfnAmxLoad(amx);
179+
}
133180
}
134181

135182
if(err != AMX_ERR_NONE) {
@@ -318,9 +365,11 @@ int CFunctions::amxUnload(lua_State *luaVM) {
318365
return 1;
319366
}
320367
// Call all plugins' AmxUnload function
321-
for(map< string, HMODULE >::iterator piIt = loadedPlugins.begin(); piIt != loadedPlugins.end(); piIt++) {
322-
AmxUnload_t *pfnAmxUnload = (AmxUnload_t*)getProcAddr(piIt->second, "AmxUnload");
323-
pfnAmxUnload(amx);
368+
for(map< string, SampPlugin* >::iterator piIt = loadedPlugins.begin(); piIt != loadedPlugins.end(); piIt++) {
369+
AmxUnload_t *pfnAmxUnload = piIt->second->AmxUnload;
370+
if (pfnAmxUnload) {
371+
pfnAmxUnload(amx);
372+
}
324373
}
325374
// Close any open databases
326375
if(loadedDBs.find(amx) != loadedDBs.end()) {
@@ -341,9 +390,13 @@ int CFunctions::amxUnload(lua_State *luaVM) {
341390

342391
// amxUnloadAllPlugins()
343392
int CFunctions::amxUnloadAllPlugins(lua_State *luaVM) {
344-
for(map< string, HMODULE >::iterator it = loadedPlugins.begin(); it != loadedPlugins.end(); it++)
345-
freeLib(it->second);
393+
for (map< string, SampPlugin* >::iterator it = loadedPlugins.begin(); it != loadedPlugins.end(); it++) {
394+
it->second->Unload();
395+
freeLib(it->second->pPluginPointer);
396+
delete it->second;
397+
}
346398
loadedPlugins.clear();
399+
vecPfnProcessTick.clear();
347400

348401
lua_pushboolean(luaVM, 1);
349402
return 1;

amx-deps/src/CFunctions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
#ifndef __CFUNCTIONS_H
2020
#define __CFUNCTIONS_H
2121

22+
typedef void (STDCALL ProcessTick_t)();
23+
24+
extern vector<ProcessTick_t*> vecPfnProcessTick;
25+
2226
class CFunctions
2327
{
2428
public:

amx-deps/src/ml_base.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,10 @@ MTAEXPORT void RegisterFunctions ( lua_State * luaVM )
180180

181181
MTAEXPORT bool DoPulse ( void )
182182
{
183+
for (const auto& ProcessTick : vecPfnProcessTick)
184+
{
185+
ProcessTick();
186+
}
183187
return true;
184188
}
185189

0 commit comments

Comments
 (0)