diff --git a/amxmodx/CModule.cpp b/amxmodx/CModule.cpp index b7628d8b..e6a471f2 100755 --- a/amxmodx/CModule.cpp +++ b/amxmodx/CModule.cpp @@ -163,6 +163,26 @@ void CModule::clear(bool clearFilename) m_Natives.clear(); } +bool CModule::attachMetamod(const char *mmfile, PLUG_LOADTIME now) +{ + void **handle; + void *dummy = NULL; + + if (!m_Handle) + handle = &dummy; + else + handle = (void **)&m_Handle; + + int res = LoadMetamodPlugin(mmfile, handle, now); + + if (!res) + { + m_Metamod = false; + } + + return true; +} + bool CModule::attachModule() { // old & new @@ -336,6 +356,12 @@ bool CModule::detachModule() if (detachFunc_Old) (*detachFunc_Old)(); } +#ifndef FAKEMETA + if (IsMetamod()) + { + UnloadMetamodPlugin(m_Handle); + } +#endif DLFREE(m_Handle); clear(); return true; diff --git a/amxmodx/CModule.h b/amxmodx/CModule.h index ce713e8e..c7b7f915 100755 --- a/amxmodx/CModule.h +++ b/amxmodx/CModule.h @@ -88,6 +88,9 @@ public: bool attachModule(); bool queryModule(); bool detachModule(); +#ifndef FAKEMETA + bool attachMetamod(const char *mmfile, PLUG_LOADTIME now); +#endif const char* getStatus() const; inline const char* getType() const { return m_Amxx ? "amxx" : (m_Metamod ? "amx&mm" : "amx"); } inline const char* getAuthor() const { return m_Amxx ? (m_InfoNew.author) : (m_InfoOld ? m_InfoOld->author : "unknown"); } @@ -101,13 +104,12 @@ public: inline bool isAmxx() const { return m_Amxx; } inline const char *getMissingFunc() const { return m_MissingFunc; } inline const char *getFilename() { return m_Filename.c_str(); } + inline bool IsMetamod() { return m_Metamod; } void CModule::CallPluginsLoaded(); CList m_Natives; }; - - #endif diff --git a/amxmodx/amxmodx.h b/amxmodx/amxmodx.h index 8226772e..0bca46a3 100755 --- a/amxmodx/amxmodx.h +++ b/amxmodx/amxmodx.h @@ -226,11 +226,12 @@ void plugin_srvcmd(); const char* stristr(const char* a,const char* b); char *strptime(const char *buf, const char *fmt, struct tm *tm, short addthem); -int loadModules(const char* filename); +int loadModules(const char* filename, PLUG_LOADTIME now); void detachModules(); void detachReloadModules(); +#ifdef FAKEMETA void attachModules(); -void attachMetaModModules(PLUG_LOADTIME now, const char* filename); +#endif // Count modules enum CountModulesMode @@ -297,7 +298,9 @@ extern int FF_PluginEnd; extern int FF_InconsistentFile; extern int FF_ClientAuthorized; +#ifdef FAKEMETA extern CFakeMeta g_FakeMeta; +#endif struct func_s { diff --git a/amxmodx/fakemeta.cpp b/amxmodx/fakemeta.cpp index 0240c421..ae5277fa 100755 --- a/amxmodx/fakemeta.cpp +++ b/amxmodx/fakemeta.cpp @@ -28,10 +28,53 @@ * version. */ -// Fake metamod api #include "amxmodx.h" #include "fakemeta.h" +#ifndef FAKEMETA +int LoadMetamodPlugin(const char *path, void **handle, PLUG_LOADTIME now) +{ + if (gpMetaPExtFuncs) + { + if(PEXT_LOAD_PLUGIN_BY_NAME(PLID, path, now, handle) || !*handle) + { + LOG_MESSAGE(PLID, "Can't Attach metamod-module \"%s\".", path); + return 0; + } + return 1; + } else if (g_IsNewMM) { + int err = 0; + if ( (err = LOAD_PLUGIN(PLID, path, now, handle)) || !*handle) + { + LOG_MESSAGE(PLID, "Can't Attach Module \"%s\".", path); + return 0; + } + return 1; + } + return 0; +} +int UnloadMetamodPlugin(void *handle) +{ + if (gpMetaPExtFuncs) + { + if(PEXT_UNLOAD_PLUGIN_BY_HANDLE(PLID, (void*)handle, PT_ANYTIME, PNL_PLUGIN)) { + return 0; + } + return 1; + } else if (g_IsNewMM) { + if (UNLOAD_PLUGIN_BY_HANDLE(PLID, (void *)handle, PT_ANYTIME, PNL_PLUGIN)) + { + return 0; + } + return 1; + } + + return 0; +} +#else + +// Fake metamod api + // for varargs #define MAX_STRBUF_LEN 512 @@ -2900,4 +2943,6 @@ int CFakeMeta::GetNewDLLFunctions_Post(NEW_DLL_FUNCTIONS *pNewFunctionTable, int } return TRUE; -} \ No newline at end of file +} + +#endif //FAKEMETA diff --git a/amxmodx/fakemeta.h b/amxmodx/fakemeta.h index ee7a2680..fc6450a7 100755 --- a/amxmodx/fakemeta.h +++ b/amxmodx/fakemeta.h @@ -31,6 +31,10 @@ #ifndef __FAKEMETA_H__ #define __FAKEMETA_H__ +#ifndef FAKEMETA +int UnloadMetamodPlugin(void *handle); +int LoadMetamodPlugin(const char *path, void **handle, PLUG_LOADTIME now); +#else // Fake metamod api for modules #include "CList.h" @@ -225,5 +229,7 @@ public: // defined in meta_api.cpp extern CFakeMeta g_FakeMeta; +#endif FAKEMETA + #endif // #ifndef __FAKEMETA_H__ diff --git a/amxmodx/meta_api.cpp b/amxmodx/meta_api.cpp index abd861e2..f3053caf 100755 --- a/amxmodx/meta_api.cpp +++ b/amxmodx/meta_api.cpp @@ -89,6 +89,7 @@ float g_task_time; float g_auth_time; bool g_initialized = false; bool g_IsNewMM = false; +bool g_NeedsP = false; #ifdef MEMORY_TEST float g_next_memreport_time; @@ -129,7 +130,9 @@ int FF_ClientAuthorized = -1; int FF_ChangeLevel = -1; // fake metamod api +#ifdef FAKEMETA CFakeMeta g_FakeMeta; +#endif // Precache stuff from force consistency calls // or check for pointed files won't be done @@ -240,8 +243,7 @@ int C_Spawn( edict_t *pent ) { get_localinfo("amxx_customdir", "addons/amxmodx/custom"); // ###### Load modules - loadModules(get_localinfo("amxx_modules", "addons/amxmodx/configs/modules.ini")); - attachModules(); + loadModules(get_localinfo("amxx_modules", "addons/amxmodx/configs/modules.ini"), PT_ANYTIME); int loaded = countModules(CountModules_Running); // Call after attachModules so all modules don't have pending stat // Set some info about amx version and modules CVAR_SET_STRING(init_amxmodx_version.name, AMX_VERSION); @@ -1020,6 +1022,8 @@ void C_AlertMessage_Post(ALERT_TYPE atype, char *szFmt, ...) RETURN_META(MRES_IGNORED); } +bool m_NeedsP = false; + C_DLLEXPORT int Meta_Query(char *ifvers, plugin_info_t **pPlugInfo, mutil_funcs_t *pMetaUtilFuncs) { gpMetaUtilFuncs=pMetaUtilFuncs; @@ -1038,21 +1042,29 @@ C_DLLEXPORT int Meta_Query(char *ifvers, plugin_info_t **pPlugInfo, mutil_funcs_ LOG_ERROR(PLID, "metamod version is incompatible with this plugin; please find a newer version of this plugin"); return(FALSE); } else if (pmajor==mmajor) { +#ifdef FAKEMETA if (mminor == 10) { LOG_MESSAGE(PLID, "WARNING: metamod version is older than expected; consider finding a newer version"); g_IsNewMM = false; //hack! Plugin_info.ifvers = "5:10"; +#else + if (mminor < 11) + { + g_NeedsP = true; + +#endif } else if (mminor == 11) { g_IsNewMM = true; } else if (pminor > mminor) { - LOG_ERROR(PLID, "metamod version is incompatible with this plugin; please find a newer version of this plugin"); + LOG_ERROR(PLID, "metamod version is incompatible with this plugin; please find a newer version of this plugin"); return FALSE; } else if (pminor < mminor) { LOG_MESSAGE(PLID, "WARNING: metamod version is newer than expected; consider finding a newer version of this plugin"); + if (mminor > 11) + g_IsNewMM = true; } - LOG_MESSAGE(PLID, "WARNING: metamod version is newer than expected; consider finding a newer version of this plugin"); } else { LOG_ERROR(PLID, "unexpected version comparison; metavers=%s, mmajor=%d, mminor=%d; plugvers=%s, pmajor=%d, pminor=%d", ifvers, mmajor, mminor, META_INTERFACE_VERSION, pmajor, pminor); } @@ -1084,17 +1096,23 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m { if(now > Plugin_info.loadable) { - LOG_ERROR(PLID, "Can't load plugin right now"); + LOG_ERROR(PLID, "Can't load plugin right now"); + return(FALSE); + } + if (g_NeedsP && !gpMetaPExtFuncs) + { + LOG_ERROR(PLID, "You need Metamod-P or Metamod-1.18 to use AMX Mod X 1.1!"); return(FALSE); } - LOG_MESSAGE(PLID, "gpMetaPExtFuncs=%p, g_IsNewMM=%d", gpMetaPExtFuncs, g_IsNewMM); gpMetaGlobals=pMGlobals; gMetaFunctionTable.pfnGetEntityAPI2 = GetEntityAPI2; gMetaFunctionTable.pfnGetEntityAPI2_Post = GetEntityAPI2_Post; gMetaFunctionTable.pfnGetEngineFunctions = GetEngineFunctions; gMetaFunctionTable.pfnGetEngineFunctions_Post = GetEngineFunctions_Post; +#ifdef FAKEMETA gMetaFunctionTable.pfnGetNewDLLFunctions = GetNewDLLFunctions; gMetaFunctionTable.pfnGetNewDLLFunctions_Post = GetNewDLLFunctions_Post; +#endif memcpy(pFunctionTable, &gMetaFunctionTable, sizeof(META_FUNCTIONS)); gpGamedllFuncs=pGamedllFuncs; @@ -1140,7 +1158,7 @@ C_DLLEXPORT int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, m // ###### Now attach metamod modules // This will also call modules Meta_Query and Meta_Attach functions - attachMetaModModules(now, get_localinfo("amxx_modules", "addons/amxmodx/configs/modules.ini") ); + loadModules(get_localinfo("amxx_modules", "addons/amxmodx/configs/modules.ini"), now); return(TRUE); } @@ -1169,8 +1187,10 @@ C_DLLEXPORT int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason) { detachModules(); // ###### Now detach metamod modules +#ifdef FAKEMETA g_FakeMeta.Meta_Detach(now, reason); g_FakeMeta.ReleasePlugins(); +#endif g_log.CloseFile(); @@ -1263,7 +1283,12 @@ C_DLLEXPORT int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVers gFunctionTable.pfnInconsistentFile = C_InconsistentFile; gFunctionTable.pfnServerActivate = C_ServerActivate; +#ifdef FAKEMETA return g_FakeMeta.GetEntityAPI2(pFunctionTable, interfaceVersion, &gFunctionTable); +#else + memcpy(pFunctionTable, &gFunctionTable, sizeof(DLL_FUNCTIONS)); + return 1; +#endif } DLL_FUNCTIONS gFunctionTable_Post; @@ -1275,7 +1300,12 @@ C_DLLEXPORT int GetEntityAPI2_Post( DLL_FUNCTIONS *pFunctionTable, int *interfac gFunctionTable_Post.pfnStartFrame = C_StartFrame_Post; gFunctionTable_Post.pfnServerDeactivate = C_ServerDeactivate_Post; +#ifdef FAKEMETA return g_FakeMeta.GetEntityAPI2_Post(pFunctionTable, interfaceVersion, &gFunctionTable_Post); +#else + memcpy(pFunctionTable, &gFunctionTable_Post, sizeof(DLL_FUNCTIONS)); + return 1; +#endif } enginefuncs_t meta_engfuncs; @@ -1300,7 +1330,12 @@ C_DLLEXPORT int GetEngineFunctions(enginefuncs_t *pengfuncsFromEngine, int *inte meta_engfuncs.pfnPrecacheSound = C_PrecacheSound; meta_engfuncs.pfnChangeLevel = C_ChangeLevel; +#ifdef FAKEMETA return g_FakeMeta.GetEngineFunctions(pengfuncsFromEngine, interfaceVersion, &meta_engfuncs); +#else + memcpy(pengfuncsFromEngine, &meta_engfuncs, sizeof(enginefuncs_t)); + return 1; +#endif } enginefuncs_t meta_engfuncs_post; @@ -1319,32 +1354,15 @@ C_DLLEXPORT int GetEngineFunctions_Post(enginefuncs_t *pengfuncsFromEngine, int meta_engfuncs_post.pfnAlertMessage = C_AlertMessage_Post; meta_engfuncs_post.pfnRegUserMsg = C_RegUserMsg_Post; - - CList list; - list.put(new int (8)); - list.put_back(new int(10)); - list.put_front(new int(6)); - list.put(new int (12)); - CList::iterator iter; - iter = list.begin(); - while (iter) - { - if (*iter == 10) - iter.remove(); - else if (*iter == 8) - iter.put(new int (9)); - else - ++iter; - } - iter = list.begin(); - while (iter) - { - AMXXLOG_Log("%d", *iter); - ++iter; - } +#ifdef FAKEMETA return g_FakeMeta.GetEngineFunctions_Post(pengfuncsFromEngine, interfaceVersion, &meta_engfuncs_post); +#else + memcpy(pengfuncsFromEngine, &meta_engfuncs_post, sizeof(enginefuncs_t)); + return 1; +#endif } +#ifdef FAKEMETA NEW_DLL_FUNCTIONS gNewDLLFunctionTable; C_DLLEXPORT int GetNewDLLFunctions(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion) { @@ -1356,3 +1374,4 @@ C_DLLEXPORT int GetNewDLLFunctions_Post(NEW_DLL_FUNCTIONS *pNewFunctionTable, in { return g_FakeMeta.GetNewDLLFunctions_Post(pNewFunctionTable, interfaceVersion, &gNewDLLFunctionTable_Post); } +#endif \ No newline at end of file diff --git a/amxmodx/modules.cpp b/amxmodx/modules.cpp index ddca1677..5e1c6f49 100755 --- a/amxmodx/modules.cpp +++ b/amxmodx/modules.cpp @@ -603,7 +603,7 @@ void ConvertModuleName(const char *pathString, String &path) #endif //SMALL_CELL_SIZE==64 } -int loadModules(const char* filename) +int loadModules(const char* filename, PLUG_LOADTIME now) { FILE *fp = fopen(build_pathname("%s",filename), "rt"); @@ -637,7 +637,7 @@ int loadModules(const char* filename) path.assign(""); - ConvertModuleName(pathString, path); + ConvertModuleName(pathString, path); if (!validFile(path.c_str())) continue; @@ -687,6 +687,34 @@ int loadModules(const char* filename) g_modules.put( cc ); +#ifndef FAKEMETA + if ( cc->IsMetamod()) + { + char* mmpathname = build_pathname_addons("%s/%s", get_localinfo("amxx_modulesdir", "addons/amxmodx/modules"), line); + 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; + } + } +#endif } fclose(fp); @@ -711,7 +739,11 @@ void detachReloadModules() while ( a ) { +#ifdef FAKEMETA if ( (*a).isReloadable() ) +#else + if ( (*a).isReloadable() && !(*a).IsMetamod() ) +#endif { (*a).detachModule(); a.remove(); @@ -723,6 +755,7 @@ void detachReloadModules() } +#ifdef FAKEMETA void attachModules() { CList::iterator a = g_modules.begin(); @@ -752,6 +785,7 @@ void attachModules() ++a; } } +#endif const char* strip_name( const char* a ) { @@ -766,6 +800,7 @@ const char* strip_name( const char* a ) return ret; } +#ifdef FAKEMETA void attachMetaModModules(PLUG_LOADTIME now, const char* filename) { File fp( build_pathname("%s",filename), "r" ); @@ -828,7 +863,7 @@ void attachMetaModModules(PLUG_LOADTIME now, const char* filename) g_FakeMeta.Meta_Query(gpMetaUtilFuncs); g_FakeMeta.Meta_Attach(now, gpMetaGlobals, gpGamedllFuncs); } - +#endif // Get the number of running modules