diff --git a/amxmodx/CModule.cpp b/amxmodx/CModule.cpp index fb348800..4d9658ee 100755 --- a/amxmodx/CModule.cpp +++ b/amxmodx/CModule.cpp @@ -30,6 +30,7 @@ */ #include "amxmodx.h" +#include "libraries.h" #ifndef FAR #define FAR @@ -41,6 +42,8 @@ typedef int (FAR *QUERYMOD_NEW)(int * /*ifvers*/, amxx_module_info_s * /*modInfo typedef int (FAR *ATTACHMOD_NEW)(PFN_REQ_FNPTR /*reqFnptrFunc*/); typedef int (FAR *DETACHMOD_NEW)(void); typedef void (FAR *PLUGINSLOADED_NEW)(void); +typedef void (*PLUGINSUNLOADED_NEW)(void); +typedef void (*PLUGINSUNLOADING_NEW)(void); // ***************************************************** // class CModule @@ -126,7 +129,7 @@ bool CModule::attachModule() { case AMXX_OK: m_Status = MODULE_LOADED; - return true; + break; case AMXX_PARAM: AMXXLOG_Log("[AMXX] Internal Error: Module \"%s\" (version \"%s\") retured \"Invalid parameter\" from Attach func.", m_Filename.c_str(), getVersion()); m_Status = MODULE_INTERROR; @@ -144,6 +147,13 @@ bool CModule::attachModule() m_Status = MODULE_BADLOAD; } + if (m_Status == MODULE_LOADED) + { + AddLibrariesFromString(m_InfoNew.library, LibType_Library, LibSource_Module, this); + AddLibrariesFromString(m_InfoNew.libclass, LibType_Class, LibSource_Module, this); + return true; + } + return false; } @@ -184,10 +194,36 @@ bool CModule::queryModule() return false; case AMXX_IFVERS: if (ifVers < AMXX_INTERFACE_VERSION) - m_Status = MODULE_OLD; - else + { + //backwards compat for new defs + if (ifVers == 3) + { + g_ModuleCallReason = ModuleCall_Query; + g_CurrentlyCalledModule = this; + retVal = (*queryFunc_New)(&ifVers, &m_InfoNew); + g_CurrentlyCalledModule = NULL; + g_ModuleCallReason = ModuleCall_NotCalled; + if (retVal == AMXX_OK) + { + m_InfoNew.library = m_InfoNew.logtag; + if (StrCaseStr(m_InfoNew.library, "sql") + || StrCaseStr(m_InfoNew.library, "dbi")) + { + m_InfoNew.libclass = "DBI"; + } else { + m_InfoNew.libclass = ""; + } + break; + } + return false; + } else { + m_Status = MODULE_OLD; + return false; + } + } else { m_Status = MODULE_NEWER; - return false; + return false; + } case AMXX_OK: break; default: @@ -217,6 +253,8 @@ bool CModule::detachModule() if (m_Status != MODULE_LOADED) return false; + RemoveLibraries(this); + if (m_Amxx) { DETACHMOD_NEW detachFunc_New = (DETACHMOD_NEW)DLPROC(m_Handle, "AMXX_Detach"); @@ -244,6 +282,38 @@ bool CModule::detachModule() return true; } +void CModule::CallPluginsUnloaded() +{ + if (m_Status != MODULE_LOADED) + return; + + if (!m_Handle) + return; + + PLUGINSUNLOADED_NEW func = (PLUGINSUNLOADED_NEW)DLPROC(m_Handle, "AMXX_PluginsUnloaded"); + + if (!func) + return; + + func(); +} + +void CModule::CallPluginsUnloading() +{ + if (m_Status != MODULE_LOADED) + return; + + if (!m_Handle) + return; + + PLUGINSUNLOADING_NEW func = (PLUGINSUNLOADING_NEW)DLPROC(m_Handle, "AMXX_PluginsUnloading"); + + if (!func) + return; + + func(); +} + void CModule::CallPluginsLoaded() { if (m_Status != MODULE_LOADED) diff --git a/amxmodx/CModule.h b/amxmodx/CModule.h index 12dbbc82..f67ce408 100755 --- a/amxmodx/CModule.h +++ b/amxmodx/CModule.h @@ -59,6 +59,8 @@ struct amxx_module_info_s const char *version; int reload; // reload on mapchange when nonzero const char *logtag; //added in version 2 + const char *library; // added in version 4 + const char *libclass; // added in version 4 }; #define AMXX_OK 0 /* no error */ @@ -66,7 +68,7 @@ struct amxx_module_info_s #define AMXX_PARAM 2 /* Invalid parameter */ #define AMXX_FUNC_NOT_PRESENT 3 /* Function not present */ -#define AMXX_INTERFACE_VERSION 3 +#define AMXX_INTERFACE_VERSION 4 class CModule { @@ -110,6 +112,8 @@ public: inline bool IsMetamod() { return m_Metamod; } void CallPluginsLoaded(); + void CallPluginsUnloaded(); + void CallPluginsUnloading(); CList m_Natives; }; diff --git a/amxmodx/amxmodx.cpp b/amxmodx/amxmodx.cpp index 71b98599..23c01e05 100755 --- a/amxmodx/amxmodx.cpp +++ b/amxmodx/amxmodx.cpp @@ -34,6 +34,7 @@ #include "natives.h" #include "debugger.h" #include "binlog.h" +#include "libraries.h" static cell AMX_NATIVE_CALL get_xvar_id(AMX *amx, cell *params) { @@ -3716,43 +3717,18 @@ static cell AMX_NATIVE_CALL module_exists(AMX *amx, cell *params) int len; char *module = get_amxstring(amx, params[1], 0, len); - CList::iterator a; + if (!FindLibrary(module, LibType_Library)) + return FindLibrary(module, LibType_Class); - bool isdbi = false, found = false; - const amxx_module_info_s *info; - - if (stricmp(module, "dbi") == 0) - isdbi = true; + return true; +} - for (a = g_modules.begin(); a; ++a) - { - if ((*a).getStatusValue() == MODULE_LOADED) - { - info = (*a).getInfoNew(); - if (info) - { - if (isdbi) - { - if (info->logtag && (StrCaseStr(info->logtag, "sql") || StrCaseStr(info->logtag, "dbi"))) - { - found = true; - break; - } - } else { - if (info->logtag && (stricmp(info->logtag, module) == 0)) - { - found = true; - break; - } - } - } - } - } - - if (!found) - found = LibraryExists(module); +static cell AMX_NATIVE_CALL LibraryExists(AMX *amx, cell *params) +{ + int len; + char *library = get_amxstring(amx, params[1], 0, len); - return (found ? 1 : 0); + return FindLibrary(library, static_cast(params[2])); } static cell AMX_NATIVE_CALL set_fail_state(AMX *amx, cell *params) @@ -4242,5 +4218,6 @@ AMX_NATIVE_INFO amxmodx_Natives[] = {"ExecuteForward", ExecuteForward}, {"PrepareArray", PrepareArray}, {"ShowSyncHudMsg", ShowSyncHudMsg}, + {"LibraryExists", LibraryExists}, {NULL, NULL} }; diff --git a/amxmodx/amxmodx.h b/amxmodx/amxmodx.h index 835cdc1a..88196c4b 100755 --- a/amxmodx/amxmodx.h +++ b/amxmodx/amxmodx.h @@ -263,6 +263,8 @@ enum CountModulesMode int countModules(CountModulesMode mode); void modules_callPluginsLoaded(); +void modules_callPluginsUnloaded(); +void modules_callPluginsUnloading(); cell* get_amxaddr(AMX *amx, cell amx_addr); char* build_pathname(char *fmt, ...); diff --git a/amxmodx/meta_api.cpp b/amxmodx/meta_api.cpp index 03bc7032..0e93339a 100755 --- a/amxmodx/meta_api.cpp +++ b/amxmodx/meta_api.cpp @@ -506,6 +506,7 @@ void C_ServerDeactivate_Post() g_xvars.clear(); g_plugins.clear(); ClearPluginLibraries(); + modules_callPluginsUnloaded(); for (unsigned int i=0; i g_modules; CList g_loadedscripts; @@ -427,68 +428,61 @@ const char *StrCaseStr(const char *as, const char *bs) int CheckModules(AMX *amx, char error[128]) { int numLibraries = amx_GetLibraries(amx); - char buffer[32]; - - bool found = false; - bool isdbi = false; - - CList::iterator a; - - const amxx_module_info_s *info; + char buffer[64]; Handler *pHandler = (Handler *)amx->userdata[UD_HANDLER]; for (int i = 0; i < numLibraries; i++) { amx_GetLibrary(amx, i, buffer, sizeof(buffer) - 1); - found = false; if (stricmp(buffer, "float") == 0) continue; - - isdbi = false; - - if (stricmp(buffer, "dbi") == 0) - isdbi = true; - - for (a = g_modules.begin(); a; ++a) + + LibDecoder dcd; + LibType expect; + bool found = false; + const char *search = NULL; + + DecodeLibCmdString(buffer, dcd); + + switch (dcd.cmd) { - if ((*a).getStatusValue() == MODULE_LOADED) - { - info = (*a).getInfoNew(); - - if (info) - { - if (isdbi) - { - if (info->logtag && (StrCaseStr(info->logtag, "sql") || StrCaseStr(info->logtag, "dbi"))) - { - found = true; - break; - } - } else { - if (info->logtag && (stricmp(info->logtag, buffer) == 0)) - { - found = true; - break; - } - } - } - } + case LibCmd_ReqLib: + search = dcd.param1; + expect = LibType_Library; + break; + case LibCmd_ExpectLib: + search = dcd.param2; + expect = LibType_Library; + break; + case LibCmd_ReqClass: + search = dcd.param1; + expect = LibType_Class; + break; + case LibCmd_ExpectClass: + search = dcd.param2; + expect = LibType_Class; + break; } - - if (!found) - found = LibraryExists(buffer); + + if (!search) + continue; + + found = FindLibrary(search, expect); if (!found) { - if (pHandler->HandleModule(buffer)) + if (pHandler->HandleModule(search)) found = true; } if (!found) { - sprintf(error, "Module \"%s\" required for plugin. Check modules.ini.", buffer); + const char *type = "Module/Library"; + if (expect == LibType_Class) + type = "Module/Library Class"; + sprintf(error, "%s \"%s\" required for plugin. Check modules.ini.", type, search); return 0; } } @@ -735,130 +729,202 @@ char* build_pathname_addons(char *fmt, ...) return string; } -bool validFile(const char* file) -{ - const char* a = 0; - - while (*file) - if (*file++ == '.') - a = file; -#ifndef __linux__ - return (a && !strcmp(a, "dll")); -#else - return (a && !strcmp(a, "so")); +#if defined WIN32 +#define SEPCHAR '\\' +#elif defined __linux__ +#define SEPCHAR '/' #endif + +bool ConvertModuleName(const char *pathString, String &path) +{ + String local; + + local.assign(pathString); + char *tmpname = const_cast(local.c_str()); + char *orig_path = tmpname; + + path.clear(); + + size_t len = local.size(); + if (!len) + return false; + + /* run to filename instead of dir */ + char *ptr = tmpname; + ptr = tmpname + len - 1; + while (ptr >= tmpname && *ptr != SEPCHAR) + ptr--; + if (ptr >= tmpname) + { + *ptr++ = '\0'; + tmpname = ptr; + } + + bool foundAmxx = false; + int iDigit = '3'; + ptr = tmpname; + while (*ptr) + { + while (*ptr && *ptr != '_') + ptr++; + if (strncmp(ptr, "_amxx", 5) == 0) + { + char *p = ptr + 5; + if (strncmp(p, ".dll", 4) == 0) + { + foundAmxx = true; + break; + } else if (p[0] == '_') { + p++; + if (strncmp(p, "amd64.so", 8) == 0) + { + foundAmxx = true; + break; + } else if (p[0] == 'i') { + p++; + if (isdigit(p[0]) && p[1] == '8' && p[2] == '6') + { + iDigit = p[0]; + foundAmxx = true; + break; + } + } + } else if (p[0] == '\0') { + foundAmxx = true; + break; + } + } else { + while (*ptr && *ptr == '_') + ptr++; + } + } + + if (!foundAmxx) + { + ptr = tmpname + strlen(tmpname); - 1; + while (ptr >= tmpname && *ptr != '.') + ptr--; + if (ptr > tmpname && *ptr == '.') + { + *ptr = '\0'; + } + } else { + *ptr = '\0'; + } + + path.assign(orig_path); + path.append(SEPCHAR); + path.append(tmpname); + path.append("_amxx"); +#if defined __linux__ + #if defined AMD64 || PAWN_CELL_SIZE==64 + path.append("amd64"); + #else + path.append("i"); + path.append(iDigit); + path.append("86"); + #endif +#endif +#if defined WIN32 + path.append(".dll"); +#elif defined __linux__ + path.append(".so"); +#endif + + FILE *fp = fopen(path.c_str(), "rb"); + if (!fp) + return false; + fclose(fp); + + return true; } -void ConvertModuleName(const char *pathString, String &path) +bool LoadModule(const char *shortname, PLUG_LOADTIME now) { -#if PAWN_CELL_SIZE==64 - char *ptr = strstr(pathString, "i386"); - - if (ptr) - { - //attempt to fix the binary name - *ptr = 0; - path.assign(pathString); - path.append("amd64.so"); - } else { - ptr = strstr(pathString, ".dll"); - - if (ptr) - { - *ptr = 0; - path.assign(pathString); - path.append("_amd64.so"); - } else { - ptr = strstr(pathString, ".so"); - - if (ptr) - { - path.assign(pathString); - } else { - //no extension at all - path.assign(pathString); - path.append("_amd64.so"); - } - } - } -#else + char pathString[512]; + String path; -#ifdef __linux__ - char *ptr = strstr(pathString, "amd64"); - - if (ptr) + build_pathname_r( + pathString, + sizeof(pathString)-1, + "%s/%s", + get_localinfo("amxx_modulesdir", "addons/amxmodx/modules"), + shortname); + + if (!ConvertModuleName(pathString, path)) + return false; + + CList::iterator a = g_modules.find(path.c_str()); + + if (a) + return false; + + CModule* cc = new CModule(path.c_str()); + + cc->queryModule(); + + switch (cc->getStatusValue()) { - //attempt to fix the binary name - *ptr = 0; - path.assign(pathString); - path.append("i386.so"); - } else { - ptr = strstr(pathString, ".dll"); - - if (ptr) - { - *ptr = 0; - path.assign(pathString); - path.append("_i386.so"); - } else { - //check to see if this file even has an extension - ptr = strstr(pathString, ".so"); - - if (ptr) - { - path.assign(pathString); - } else { - path.assign(pathString); - path.append("_i386.so"); - } - } + case MODULE_BADLOAD: + report_error(1, "[AMXX] Module is not a valid library (file \"%s\")", path.c_str()); + break; + case MODULE_NOINFO: + report_error(1, "[AMXX] Couldn't find info about module (file \"%s\")", path.c_str()); + break; + case MODULE_NOQUERY: + report_error(1, "[AMXX] Couldn't find \"AMX_Query\" or \"AMXX_Query\" (file \"%s\")", path.c_str()); + break; + case MODULE_NOATTACH: + report_error(1, "[AMXX] Couldn't find \"%s\" (file \"%s\")", cc->isAmxx() ? "AMXX_Attach" : "AMX_Attach", path.c_str()); + break; + case MODULE_OLD: + report_error(1, "[AMXX] Module has a different interface version (file \"%s\")", path.c_str()); + break; + case MODULE_NEWER: + report_error(1, "[AMXX] Module has a newer interface version (file \"%s\"). Please download a new amxmodx.", path.c_str()); + break; + case MODULE_INTERROR: + report_error(1, "[AMXX] Internal error during module load (file \"%s\")", path.c_str()); + break; + case MODULE_NOT64BIT: + report_error(1, "[AMXX] Module \"%s\" is not 64 bit compatible.", path.c_str()); + break; } -#else - char *ptr = const_cast(strstr(pathString, ".dll")); - - if (ptr) + + g_modules.put(cc); + + if (cc->IsMetamod()) { - path.assign(pathString); - } else { - //prevent this from loading .so too - ptr = const_cast(strstr(pathString, ".so")); - - if (ptr) - { - int i = 0, len = strlen(pathString), c = -1; - - for (i = len - 1; i >= 0; i--) - { - //cut off at first _ - if (pathString[i] == '_') - { - //make sure this is a valid _ - if (i == len - 1 || strncmp(&(pathString[i + 1]), "amxx", 4) == 0) - break; - - c = i; - break; - } - } - *ptr = 0; - - if (c == -1) - { - path.assign(pathString); - path.append(".dll"); - } else { - ptr = (char *)&(pathString[c]); - *ptr = 0; - path.assign(pathString); - path.append(".dll"); - } - } else { - path.assign(pathString); - path.append(".dll"); - } + char *mmpathname = build_pathname_addons( + "%s/%s", + get_localinfo("amxx_modulesdir", "addons/amxmodx/modules"), + shortname); + ConvertModuleName(mmpathname, path); + cc->attachMetamod(path.c_str(), now); } -#endif //__linux__ -#endif //PAWN_CELL_SIZE==64 + + bool retVal = cc->attachModule(); + + if (cc->isAmxx() && !retVal) + { + switch (cc->getStatusValue()) + { + case MODULE_FUNCNOTPRESENT: + report_error(1, "[AMXX] Module requested a not exisitng function (file \"%s\")%s%s%s", cc->getFilename(), cc->getMissingFunc() ? " (func \"" : "", + cc->getMissingFunc() ? cc->getMissingFunc() : "", cc->getMissingFunc() ? "\")" : ""); + break; + case MODULE_INTERROR: + report_error(1, "[AMXX] Internal error during module load (file \"%s\")", cc->getFilename()); + break; + case MODULE_BADLOAD: + report_error(1, "[AMXX] Module is not a valid library (file \"%s\")", cc->getFilename()); + break; + } + + return false; + } + + return true; } int loadModules(const char* filename, PLUG_LOADTIME now) @@ -872,7 +938,6 @@ int loadModules(const char* filename, PLUG_LOADTIME now) } char moduleName[256]; - char pathString[512]; String line; int loaded = 0; @@ -892,91 +957,8 @@ int loadModules(const char* filename, PLUG_LOADTIME now) if (moduleName[0] == ';') continue; - char* pathname = build_pathname("%s/%s", get_localinfo("amxx_modulesdir", "addons/amxmodx/modules"), moduleName); - strcpy(pathString, pathname); - - path.assign(""); - - ConvertModuleName(pathString, path); - - if (!validFile(path.c_str())) - continue; - - CList::iterator a = g_modules.find(path.c_str()); - - if (a) - continue; // already loaded - - CModule* cc = new CModule(path.c_str()); - - if (cc == 0) - { - fclose(fp); - return loaded; - } - - cc->queryModule(); - - switch (cc->getStatusValue()) - { - case MODULE_BADLOAD: - report_error(1, "[AMXX] Module is not a valid library (file \"%s\")", path.c_str()); - break; - case MODULE_NOINFO: - report_error(1, "[AMXX] Couldn't find info. about module (file \"%s\")", path.c_str()); - break; - case MODULE_NOQUERY: - report_error(1, "[AMXX] Couldn't find \"AMX_Query\" or \"AMXX_Query\" (file \"%s\")", path.c_str()); - break; - case MODULE_NOATTACH: - report_error(1, "[AMXX] Couldn't find \"%s\" (file \"%s\")", cc->isAmxx() ? "AMXX_Attach" : "AMX_Attach", path.c_str()); - break; - case MODULE_OLD: - report_error(1, "[AMXX] Module has a different interface version (file \"%s\")", path.c_str()); - break; - case MODULE_NEWER: - report_error(1, "[AMXX] Module has a newer interface version (file \"%s\"). Please download a new amxmodx.", path.c_str()); - break; - case MODULE_INTERROR: - report_error(1, "[AMXX] Internal error during module load (file \"%s\")", path.c_str()); - break; - case MODULE_NOT64BIT: - report_error(1, "[AMXX] Module \"%s\" is not 64 bit compatible.", path.c_str()); - break; - default: - ++loaded; - } - - g_modules.put(cc); - - if (cc->IsMetamod()) - { - char* mmpathname = build_pathname_addons("%s/%s", get_localinfo("amxx_modulesdir", "addons/amxmodx/modules"), line.c_str()); - - ConvertModuleName(mmpathname, path); - cc->attachMetamod(path.c_str(), now); - } - - bool retVal = cc->attachModule(); - - if (cc->isAmxx() && !retVal) - { - switch (cc->getStatusValue()) - { - case MODULE_FUNCNOTPRESENT: - report_error(1, "[AMXX] Module requested a not exisitng function (file \"%s\")%s%s%s", cc->getFilename(), cc->getMissingFunc() ? " (func \"" : "", - cc->getMissingFunc() ? cc->getMissingFunc() : "", cc->getMissingFunc() ? "\")" : ""); - break; - case MODULE_INTERROR: - report_error(1, "[AMXX] Internal error during module load (file \"%s\")", cc->getFilename()); - break; - case MODULE_BADLOAD: - report_error(1, "[AMXX] Module is not a valid library (file \"%s\")", cc->getFilename()); - break; - default: - break; - } - } + if (LoadModule(moduleName, now)) + loaded++; } fclose(fp); @@ -1080,6 +1062,29 @@ void modules_callPluginsLoaded() } } +//same for unloaded +void modules_callPluginsUnloaded() +{ + CList::iterator iter = g_modules.begin(); + + while (iter) + { + (*iter).CallPluginsUnloaded(); + ++iter; + } +} + +void modules_callPluginsUnloading() +{ + CList::iterator iter = g_modules.begin(); + + while (iter) + { + (*iter).CallPluginsUnloading(); + ++iter; + } +} + // new functions int MNF_AddNatives(AMX_NATIVE_INFO* natives) { @@ -1493,6 +1498,21 @@ void MNF_MergeDefinitionFile(const char *file) g_langMngr.MergeDefinitionFile(file); } +int MNF_FindLibrary(const char *name, LibType type) +{ + return FindLibrary(name, type) ? 1 : 0; +} + +size_t MFN_AddLibraries(const char *name, LibType type, void *parent) +{ + return AddLibrariesFromString(name, type, LibSource_Module, parent) ? 1 : 0; +} + +size_t MNF_RemoveLibraries(void *parent) +{ + return RemoveLibraries(parent); +} + edict_t* MNF_GetPlayerEdict(int id) { if (id < 1 || id > gpGlobals->maxClients) @@ -1732,6 +1752,10 @@ void Module_CacheFunctions() REGISTER_FUNC("RegAuthFunc", MNF_RegAuthorizeFunc); REGISTER_FUNC("UnregAuthFunc", MNF_UnregAuthorizeFunc); + REGISTER_FUNC("FindLibrary", MNF_FindLibrary); + REGISTER_FUNC("AddLibraries", MFN_AddLibraries); + REGISTER_FUNC("RemoveLibraries", MNF_RemoveLibraries); + #ifdef MEMORY_TEST REGISTER_FUNC("Allocator", m_allocator) REGISTER_FUNC("Deallocator", m_deallocator) diff --git a/amxmodx/modules.h b/amxmodx/modules.h index 42596d96..63d13490 100755 --- a/amxmodx/modules.h +++ b/amxmodx/modules.h @@ -72,6 +72,7 @@ typedef enum } PlayerProp; int CheckModules(AMX *amx, char error[128]); +bool LoadModule(const char *shortname, PLUG_LOADTIME now); const char *StrCaseStr(const char *as, const char *bs); class Debugger; @@ -79,7 +80,6 @@ Debugger *DisableDebugHandler(AMX *amx); void EnableDebugHandler(AMX *amx, Debugger *pd); bool DirExists(const char *dir); - const char* GetFileName(AMX *amx); #endif // __MODULES_H__ diff --git a/amxmodx/msvc/amxmodx_mm.vcproj b/amxmodx/msvc/amxmodx_mm.vcproj index c0abf4c7..cde93f3e 100755 --- a/amxmodx/msvc/amxmodx_mm.vcproj +++ b/amxmodx/msvc/amxmodx_mm.vcproj @@ -415,6 +415,9 @@ AssemblerOutput="4"/> + + @@ -542,6 +545,9 @@ + + diff --git a/amxmodx/natives.cpp b/amxmodx/natives.cpp index 287ce6a4..dfd16b7f 100755 --- a/amxmodx/natives.cpp +++ b/amxmodx/natives.cpp @@ -32,6 +32,7 @@ #include "sh_stack.h" #include "natives.h" #include "debugger.h" +#include "libraries.h" #ifdef __linux__ #include @@ -47,7 +48,6 @@ CStack g_ErrorStk; CVector g_RegNatives; CStack g_NativeStack; -CVector g_Libraries; static char g_errorStr[512] = {0}; bool g_Initialized = false; @@ -343,7 +343,7 @@ static cell AMX_NATIVE_CALL register_library(AMX *amx, cell *params) int len; char *lib = get_amxstring(amx, params[1], 0, len); - AddPluginLibrary(lib); + AddLibrary(lib, LibType_Library, LibSource_Plugin, g_plugins.findPluginFast(amx)); return 1; } @@ -396,27 +396,9 @@ static cell AMX_NATIVE_CALL register_native(AMX *amx, cell *params) return 1; } -bool LibraryExists(const char *name) -{ - for (size_t i=0; ipfn; diff --git a/amxmodx/natives.h b/amxmodx/natives.h index 995844e1..16c0cadc 100755 --- a/amxmodx/natives.h +++ b/amxmodx/natives.h @@ -61,9 +61,7 @@ extern "C" int amxx_DynaFunc(AMX *amx, cell *params); extern "C" int amxx_DynaCodesize(); AMX_NATIVE_INFO *BuildNativeTable(); -void AddPluginLibrary(const char *name); void ClearPluginLibraries(); -bool LibraryExists(const char *name); //I couldn't resist :) extern AMX_NATIVE_INFO g_NativeNatives[]; diff --git a/amxmodx/sdk/amxxmodule.cpp b/amxmodx/sdk/amxxmodule.cpp index 9d92f6f5..194da0b1 100755 --- a/amxmodx/sdk/amxxmodule.cpp +++ b/amxmodx/sdk/amxxmodule.cpp @@ -2430,7 +2430,9 @@ static amxx_module_info_s g_ModuleInfo = #else // MODULE_RELOAD_ON_MAPCHANGE 0, #endif // MODULE_RELOAD_ON_MAPCHANGE - MODULE_LOGTAG + MODULE_LOGTAG, + MODULE_LIBRARY, + MODULE_LIBCLASS }; // Storage for the requested functions @@ -2506,6 +2508,9 @@ PFN_SET_TEAM_INFO g_fn_SetTeamInfo; PFN_PLAYER_PROP_ADDR g_fn_PlayerPropAddr; PFN_REG_AUTH_FUNC g_fn_RegAuthFunc; PFN_UNREG_AUTH_FUNC g_fn_UnregAuthFunc; +PFN_FINDLIBRARY g_fn_FindLibrary; +PFN_ADDLIBRARIES g_fn_AddLibraries; +PFN_REMOVELIBRARIES g_fn_RemoveLibraries; // *** Exports *** C_DLLEXPORT int AMXX_Query(int *interfaceVersion, amxx_module_info_s *moduleInfo) @@ -2620,6 +2625,10 @@ C_DLLEXPORT int AMXX_Attach(PFN_REQ_FNPTR reqFnptrFunc) REQFUNC("RegAuthFunc", g_fn_RegAuthFunc, PFN_REG_AUTH_FUNC); REQFUNC("UnregAuthFunc", g_fn_UnregAuthFunc, PFN_UNREG_AUTH_FUNC); + REQFUNC("FindLibrary", g_fn_FindLibrary, PFN_FINDLIBRARY); + REQFUNC("AddLibraries", g_fn_AddLibraries, PFN_ADDLIBRARIES); + REQFUNC("RemoveLibraries", g_fn_RemoveLibraries, PFN_REMOVELIBRARIES); + #ifdef MEMORY_TEST // Memory REQFUNC_OPT("Allocator", g_fn_Allocator, PFN_ALLOCATOR); @@ -2654,6 +2663,20 @@ C_DLLEXPORT int AMXX_PluginsLoaded() return AMXX_OK; } +C_DLLEXPORT void AMXX_PluginsUnloaded() +{ +#ifdef FN_AMXX_PLUGINSUNLOADED + FN_AMXX_PLUGINSUNLOADED(); +#endif // FN_AMXX_PLUGINSUNLOADED +} + +C_DLLEXPORT void AMXX_PluginsUnloading() +{ +#ifdef FN_AMXX_PLUGINSUNLOADING + FN_AMXX_PLUGINSUNLOADING(); +#endif // FN_AMXX_PLUGINSUNLOADING +} + // Advanced MF functions void MF_Log(const char *fmt, ...) { @@ -2743,6 +2766,9 @@ void ValidateMacros_DontCallThis_Smiley() MF_PlayerPropAddr(0, 0); MF_RegAuthFunc(NULL); MF_UnregAuthFunc(NULL); + MF_FindLibrary(NULL, LibType_Class); + MF_AddLibraries(NULL, LibType_Class, NULL); + MF_RemoveLibraries(NULL); } #endif diff --git a/amxmodx/sdk/amxxmodule.h b/amxmodx/sdk/amxxmodule.h index 71077bdd..975c3c7c 100755 --- a/amxmodx/sdk/amxxmodule.h +++ b/amxmodx/sdk/amxxmodule.h @@ -34,7 +34,8 @@ // module interface version was 1 // 2 - added logtag to struct (amxx1.1-rc1) // 3 - added new tagAMX structure (amxx1.5) -#define AMXX_INTERFACE_VERSION 3 +// 4 - added new 'library' setting for direct loading +#define AMXX_INTERFACE_VERSION 4 // amxx module info struct amxx_module_info_s @@ -44,6 +45,8 @@ struct amxx_module_info_s const char *version; int reload; // reload on mapchange when nonzero const char *logtag; // added in version 2 + const char *library; // added in version 4 + const char *libclass; // added in version 4 }; // return values from functions called by amxx @@ -2032,6 +2035,14 @@ void FN_AMXX_DETACH(void); void FN_AMXX_PLUGINSLOADED(void); #endif // FN_AMXX_PLUGINSLOADED +#ifdef FN_AMXX_PLUGINSUNLOADING +void FN_AMXX_PLUGINSUNLOADING(void); +#endif // FN_AMXX_PLUGINSUNLOADING + +#ifdef FN_AMXX_PLUGINSUNLOADED +void FN_AMXX_PLUGINSUNLOADED(void); +#endif // FN_AMXX_PLUGINSUNLOADED + // *** Types *** typedef void* (*PFN_REQ_FNPTR)(const char * /*name*/); @@ -2078,6 +2089,12 @@ enum PlayerProp Player_NewmenuPage, //int }; +enum LibType +{ + LibType_Library, + LibType_Class +}; + typedef void (*AUTHORIZEFUNC)(int player, const char *authstring); typedef int (*PFN_ADD_NATIVES) (const AMX_NATIVE_INFO * /*list*/); @@ -2159,6 +2176,9 @@ typedef int (*PFN_AMX_PUSH) (AMX * /*amx*/, cell /*value*/); typedef int (*PFN_SET_TEAM_INFO) (int /*player */, int /*teamid */, const char * /*name */); typedef void (*PFN_REG_AUTH_FUNC) (AUTHORIZEFUNC); typedef void (*PFN_UNREG_AUTH_FUNC) (AUTHORIZEFUNC); +typedef int (*PFN_FINDLIBRARY) (const char * /*name*/, LibType /*type*/); +typedef size_t (*PFN_ADDLIBRARIES) (const char * /*name*/, LibType /*type*/, void * /*parent*/); +typedef size_t (*PFN_REMOVELIBRARIES) (void * /*parent*/); extern PFN_ADD_NATIVES g_fn_AddNatives; extern PFN_BUILD_PATHNAME g_fn_BuildPathname; @@ -2226,6 +2246,9 @@ extern PFN_SET_TEAM_INFO g_fn_SetTeamInfo; extern PFN_PLAYER_PROP_ADDR g_fn_PlayerPropAddr; extern PFN_REG_AUTH_FUNC g_fn_RegAuthFunc; extern PFN_UNREG_AUTH_FUNC g_fn_UnregAuthFunc; +extern PFN_FINDLIBRARY g_fn_FindLibrary; +extern PFN_ADDLIBRARIES g_fn_AddLibraries; +extern PFN_REMOVELIBRARIES g_fn_RemoveLibraries; #ifdef MAY_NEVER_BE_DEFINED // Function prototypes for intellisense and similar systems @@ -2290,6 +2313,9 @@ int MF_SetPlayerTeamInfo (int id, int teamid, const char *teamname) { } void * MF_PlayerPropAddr (int id, int prop) { } void MF_RegAuthFunc (AUTHORIZEFUNC fn) { } void MF_UnregAuthFunc (AUTHORIZEFUNC fn) { } +int MF_FindLibrary (const char *name, LibType type) { } +size_t MF_AddLibraries (const char *name, LibType type, void *parent) { } +size_t MF_RemoveLibraries (void *parent) { } #endif // MAY_NEVER_BE_DEFINED #define MF_AddNatives g_fn_AddNatives @@ -2359,6 +2385,9 @@ void MF_LogError(AMX *amx, int err, const char *fmt, ...); #define MF_PlayerPropAddr g_fn_PlayerPropAddr #define MF_RegAuthFunc g_fn_RegAuthFunc #define MF_UnregAuthFunc g_fn_UnregAuthFunc +#define MF_FindLibrary g_fn_FindLibrary; +#define MF_AddLibraries g_fn_AddLibraries; +#define MF_RemoveLibraries g_fn_RemoveLibraries; #ifdef MEMORY_TEST /*** Memory ***/ diff --git a/amxmodx/sdk/moduleconfig.h b/amxmodx/sdk/moduleconfig.h index 543bb5f9..6afd743d 100755 --- a/amxmodx/sdk/moduleconfig.h +++ b/amxmodx/sdk/moduleconfig.h @@ -3,12 +3,24 @@ #ifndef __MODULECONFIG_H__ #define __MODULECONFIG_H__ -// Module info +/** Module info + * -The logtag is the tag that the module's log messages will be + * prepended with. + * -The library is the name that the #pragma library + * message will have prepended. + * -The library class is the class of libraries that + * a module belongs to (like DBI). Keep it "" to + * ignore. + * -For both library and library class, you can use a comma + * to add multiple entries. + */ #define MODULE_NAME "--ENTER NAME HERE--" #define MODULE_VERSION "--ENTER VERSION HERE--" #define MODULE_AUTHOR "--ENTER AUTHOR HERE--" #define MODULE_URL "--ENTER URL HERE--" #define MODULE_LOGTAG "--ENTER LOGTAG HERE--" +#define MODULE_LIBRARY "--ENTER LIBRARY HERE--" +#define MODULE_LIBCLASS "" // If you want the module not to be reloaded on mapchange, remove / comment out the next line #define MODULE_RELOAD_ON_MAPCHANGE @@ -34,18 +46,32 @@ // Uncomment this if you are using MSVC8 or greater and want to fix some of the compatibility issues yourself // #define NO_MSVC8_AUTO_COMPAT -// - AMXX Init functions -// Also consider using FN_META_* -// AMXX query +/** + * AMXX Init functions + * Also consider using FN_META_* + */ + +/** AMXX query */ //#define FN_AMXX_QUERY OnAmxxQuery -// AMXX attach -// Do native functions init here (MF_AddNatives) + +/** AMXX attach + * Do native functions init here (MF_AddNatives) + */ //#define FN_AMXX_ATTACH OnAmxxAttach -// AMXX detach + +/** AMXX Detach (unload) */ //#define FN_AMXX_DETACH OnAmxxDetach -// All plugins loaded -// Do forward functions init here (MF_RegisterForward) -// #define FN_AMXX_PLUGINSLOADED OnPluginsLoaded + +/** All plugins loaded + * Do forward functions init here (MF_RegisterForward) + */ +//#define FN_AMXX_PLUGINSLOADED OnPluginsLoaded + +/** All plugins are about to be unloaded */ +//#define FN_AMXX_PLUGINSUNLOADING OnPluginsUnloading + +/** All plguins are now unloaded */ +//#define FN_AMXX_PLUGINSUNLOADED OnPluginsUnloaded /**** METAMOD ****/ // If your module doesn't use metamod, you may close the file now :)