From 9ef8cc70640aab759da1b9c04b758224571fa60e Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 14 Aug 2015 17:55:58 -0700 Subject: [PATCH 1/5] Separate the top of UnloadPlugin into a precursor function. --- core/logic/PluginSys.cpp | 27 ++++++++++++++++----------- core/logic/PluginSys.h | 3 +++ core/logic/smn_fakenatives.cpp | 1 - 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index 3bd6ef73..0d2edf92 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -1478,23 +1478,30 @@ void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin) bool CPluginManager::UnloadPlugin(IPlugin *plugin) { - CPlugin *pPlugin = (CPlugin *)plugin; + return ScheduleUnload((CPlugin *)plugin); +} - /* This prevents removal during insertion or anything else weird */ - if (m_plugins.find(pPlugin) == m_plugins.end()) - { - return false; - } +bool CPluginManager::ScheduleUnload(CPlugin *pPlugin) +{ + // Should not be recursively removing. + assert(m_plugins.find(pPlugin) != m_plugins.end()); - IPluginContext *pContext = plugin->GetBaseContext(); - if (pContext != NULL && pContext->IsInExec()) + IPluginContext *pContext = pPlugin->GetBaseContext(); + if (pContext && pContext->IsInExec()) { char buffer[255]; - ke::SafeSprintf(buffer, sizeof(buffer), "sm plugins unload %s\n", plugin->GetFilename()); + ke::SafeSprintf(buffer, sizeof(buffer), "sm plugins unload %s\n", pPlugin->GetFilename()); engine->ServerCommand(buffer); return false; } + // No need to schedule an unload, we can unload immediately. + UnloadPluginImpl(pPlugin); + return true; +} + +void CPluginManager::UnloadPluginImpl(CPlugin *pPlugin) +{ /* Remove us from the lookup table and linked list */ m_plugins.remove(pPlugin); m_LoadLookup.remove(pPlugin->m_filename); @@ -1535,8 +1542,6 @@ bool CPluginManager::UnloadPlugin(IPlugin *plugin) /* Tell the plugin to delete itself */ delete pPlugin; - - return true; } IPlugin *CPluginManager::FindPluginByContext(const sp_context_t *ctx) diff --git a/core/logic/PluginSys.h b/core/logic/PluginSys.h index 2073f0e3..7fa9a929 100644 --- a/core/logic/PluginSys.h +++ b/core/logic/PluginSys.h @@ -455,6 +455,9 @@ private: bool FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size_t maxlength); void _SetPauseState(CPlugin *pPlugin, bool pause); + + bool ScheduleUnload(CPlugin *plugin); + void UnloadPluginImpl(CPlugin *plugin); protected: /** * Caching internal objects diff --git a/core/logic/smn_fakenatives.cpp b/core/logic/smn_fakenatives.cpp index 40baa604..c4c7cf8a 100644 --- a/core/logic/smn_fakenatives.cpp +++ b/core/logic/smn_fakenatives.cpp @@ -392,7 +392,6 @@ static cell_t FormatNativeString(IPluginContext *pContext, const cell_t *params) } /* Get buffer information */ - int err; char *output_buffer; char *format_buffer; From 0aaa659e29ae73c5333a26fe4d25c5cbfa364a89 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 14 Aug 2015 18:19:36 -0700 Subject: [PATCH 2/5] Fix how the mark-serial is used. The mark-serial is a generation number to optimize dependency tracking. It did not actually get applied correctly, meaning that in rare cases we could miss dependencies. This patch removes the incorrect serial propagation and ensures that we don't double-count a dependent plugin. Additionally, this patch ensures that all callers of BindNativeToPlugin() will update the mark serial, as is required to correctly track dependencies. --- core/logic/NativeOwner.cpp | 18 ++---------------- core/logic/NativeOwner.h | 1 - core/logic/PluginSys.cpp | 1 + core/logic/ShareSys.cpp | 31 ++++++++++++++----------------- core/logic/ShareSys.h | 1 + 5 files changed, 18 insertions(+), 34 deletions(-) diff --git a/core/logic/NativeOwner.cpp b/core/logic/NativeOwner.cpp index e6adcb2e..a4b092e6 100644 --- a/core/logic/NativeOwner.cpp +++ b/core/logic/NativeOwner.cpp @@ -48,7 +48,8 @@ unsigned int CNativeOwner::GetMarkSerial() void CNativeOwner::AddDependent(CPlugin *pPlugin) { - m_Dependents.push_back(pPlugin); + if (m_Dependents.find(pPlugin) == m_Dependents.end()) + m_Dependents.push_back(pPlugin); } void CNativeOwner::AddWeakRef(const WeakNative & ref) @@ -64,23 +65,8 @@ void CNativeOwner::AddNatives(const sp_nativeinfo_t *natives) m_natives.append(natives); } -void CNativeOwner::PropagateMarkSerial(unsigned int serial) -{ - CNativeOwner *pOwner; - List::iterator iter; - - for (iter = m_Dependents.begin(); - iter != m_Dependents.end(); - iter++) - { - pOwner = (*iter); - pOwner->SetMarkSerial(serial); - } -} - void CNativeOwner::UnbindWeakRef(const WeakNative &ref) { - sp_native_t *native; IPluginContext *pContext; pContext = ref.pl->GetBaseContext(); diff --git a/core/logic/NativeOwner.h b/core/logic/NativeOwner.h index e8037827..f55d954b 100644 --- a/core/logic/NativeOwner.h +++ b/core/logic/NativeOwner.h @@ -69,7 +69,6 @@ public: public: void SetMarkSerial(unsigned int serial); unsigned int GetMarkSerial(); - void PropagateMarkSerial(unsigned int serial); public: void AddDependent(CPlugin *pPlugin); void AddWeakRef(const WeakNative & ref); diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index 0d2edf92..dfcfa665 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -1381,6 +1381,7 @@ bool CPluginManager::RunSecondPass(CPlugin *pPlugin, char *error, size_t maxleng || pOther->GetStatus() == Plugin_Paused) && pOther != pPlugin) { + g_ShareSys.BeginBindingFor(pPlugin); for (size_t i = 0; i < pPlugin->m_fakes.length(); i++) g_ShareSys.BindNativeToPlugin(pOther, pPlugin->m_fakes[i]); } diff --git a/core/logic/ShareSys.cpp b/core/logic/ShareSys.cpp index 16067b43..3119f36c 100644 --- a/core/logic/ShareSys.cpp +++ b/core/logic/ShareSys.cpp @@ -269,19 +269,19 @@ PassRef ShareSystem::FindNative(const char *name) return *r; } +void ShareSystem::BeginBindingFor(CPlugin *pPlugin) +{ + g_mark_serial++; +} + void ShareSystem::BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly) { - uint32_t i, native_count; - IPluginContext *pContext; + IPluginContext *pContext = pPlugin->GetBaseContext(); - pContext = pPlugin->GetBaseContext(); + BeginBindingFor(pPlugin); - /* Generate a new serial ID, mark our dependencies with it. */ - g_mark_serial++; - pPlugin->PropagateMarkSerial(g_mark_serial); - - native_count = pContext->GetNativesNum(); - for (i = 0; i < native_count; i++) + uint32_t native_count = pContext->GetNativesNum(); + for (uint32_t i = 0; i < native_count; i++) { const sp_native_t *native = pContext->GetRuntime()->GetNative(i); if (!native) @@ -349,15 +349,12 @@ void ShareSystem::BindNativeToPlugin(CPlugin *pPlugin, const sp_native_t *native /* Otherwise, we're a strong dependent and not a weak one */ else { - /* See if this has already been marked as a dependent. - * If it has, it means this relationship has already occurred, - * and there is no reason to do it again. - */ - if (pEntry->owner != pPlugin->ToNativeOwner() - && pEntry->owner->GetMarkSerial() != g_mark_serial) + // If this plugin is not binding to itself, and it hasn't been marked as a + // dependency already, then add it now. We use the mark serial to track + // which plugins we already consider a dependency. + if (pEntry->owner != pPlugin->ToNativeOwner() && + pEntry->owner->GetMarkSerial() != g_mark_serial) { - /* This has not been marked as a dependency yet */ - //pPlugin->AddDependency(pEntry->owner); pEntry->owner->AddDependent(pPlugin); pEntry->owner->SetMarkSerial(g_mark_serial); } diff --git a/core/logic/ShareSys.h b/core/logic/ShareSys.h index 456e2c59..18eaf956 100644 --- a/core/logic/ShareSys.h +++ b/core/logic/ShareSys.h @@ -119,6 +119,7 @@ public: return &m_IdentRoot; } public: + void BeginBindingFor(CPlugin *pPlugin); void BindNativesToPlugin(CPlugin *pPlugin, bool bCoreOnly); void BindNativeToPlugin(CPlugin *pPlugin, const ke::Ref &pEntry); ke::PassRef AddFakeNative(IPluginFunction *pFunc, const char *name, SPVM_FAKENATIVE_FUNC func); From 3430962cbece4d3620bd392d39dd115ca175aefb Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 14 Aug 2015 19:16:28 -0700 Subject: [PATCH 3/5] Simplify required libs handling and make sure they create dependency links. --- core/logic/PluginSys.cpp | 98 +++++++++++++--------------------------- 1 file changed, 32 insertions(+), 66 deletions(-) diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index dfcfa665..76c61d33 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -629,15 +629,11 @@ void CPlugin::DependencyDropped(CPlugin *pOwner) if (!m_pRuntime) return; - List::iterator reqlib_iter; - List::iterator lib_iter; - for (lib_iter=pOwner->m_Libraries.begin(); lib_iter!=pOwner->m_Libraries.end(); lib_iter++) - { - for (reqlib_iter=m_RequiredLibs.begin(); reqlib_iter!=m_RequiredLibs.end(); reqlib_iter++) - { - if ((*reqlib_iter) == (*lib_iter)) - m_LibraryMissing = true; - } + for (auto lib_iter=pOwner->m_Libraries.begin(); lib_iter!=pOwner->m_Libraries.end(); lib_iter++) { + if (m_RequiredLibs.find(*lib_iter) != m_RequiredLibs.end()) { + m_LibraryMissing = true; + break; + } } unsigned int unbound = 0; @@ -1146,35 +1142,23 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size char *name, *file; char pathfile[PLATFORM_MAX_PATH]; - for (uint32_t i=0; iGetPubvarByIndex(i, &pubvar) != SP_ERROR_NONE) - { continue; - } - if (strncmp(pubvar->name, "__pl_", 5) == 0) - { + if (strncmp(pubvar->name, "__pl_", 5) == 0) { pl = (_pl *)pubvar->offs; if (pBase->LocalToString(pl->file, &file) != SP_ERROR_NONE) - { continue; - } if (pBase->LocalToString(pl->name, &name) != SP_ERROR_NONE) - { continue; - } libsys->GetFileFromPath(pathfile, sizeof(pathfile), pPlugin->GetFilename()); if (strcmp(pathfile, file) == 0) - { continue; - } - if (pl->required == false) - { + if (pl->required == false) { IPluginFunction *pFunc; char buffer[64]; ke::SafeSprintf(buffer, sizeof(buffer), "__pl_%s_SetNTVOptional", &pubvar->name[5]); - if ((pFunc=pBase->GetFunctionByName(buffer))) - { + if ((pFunc=pBase->GetFunctionByName(buffer))) { cell_t res; if (pFunc->Execute(&res) != SP_ERROR_NONE) { if (error) @@ -1182,38 +1166,28 @@ bool CPluginManager::FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size return false; } } - } - else - { + } else { /* Check that we aren't registering the same library twice */ - if (pPlugin->m_RequiredLibs.find(name) == pPlugin->m_RequiredLibs.end()) - { - pPlugin->m_RequiredLibs.push_back(name); - } - else - { + if (pPlugin->m_RequiredLibs.find(name) != pPlugin->m_RequiredLibs.end()) continue; - } - List::iterator iter; - CPlugin *pl; - bool found = false; - for (iter=m_plugins.begin(); iter!=m_plugins.end(); iter++) - { - pl = (*iter); - if (pl->m_Libraries.find(name) != pl->m_Libraries.end()) - { - found = true; + + pPlugin->m_RequiredLibs.push_back(name); + + CPlugin *found; + for (auto iter=m_plugins.begin(); iter!=m_plugins.end(); iter++) { + CPlugin *pl = (*iter); + if (pl->m_Libraries.find(name) != pl->m_Libraries.end()) { + found = pl; break; } } - if (!found) - { + if (!found) { if (error) - { ke::SafeSprintf(error, maxlength, "Could not find required plugin \"%s\"", name); - } return false; } + + found->AddDependent(pPlugin); } } } @@ -1423,29 +1397,21 @@ void CPluginManager::TryRefreshDependencies(CPlugin *pPlugin) g_ShareSys.BindNativesToPlugin(pPlugin, false); - List::iterator lib_iter; - List::iterator req_iter; - List::iterator pl_iter; - CPlugin *pl; - for (req_iter=pPlugin->m_RequiredLibs.begin(); req_iter!=pPlugin->m_RequiredLibs.end(); req_iter++) - { - bool found = false; - for (pl_iter=m_plugins.begin(); pl_iter!=m_plugins.end(); pl_iter++) - { - pl = (*pl_iter); - for (lib_iter=pl->m_Libraries.begin(); lib_iter!=pl->m_Libraries.end(); lib_iter++) - { - if ((*req_iter) == (*lib_iter)) - { - found = true; - } + for (auto req_iter=pPlugin->m_RequiredLibs.begin(); req_iter!=pPlugin->m_RequiredLibs.end(); req_iter++) { + CPlugin *found = nullptr; + for (auto pl_iter=m_plugins.begin(); pl_iter!=m_plugins.end(); pl_iter++) { + CPlugin *search = (*pl_iter); + if (search->m_Libraries.find(*req_iter) != search->m_Libraries.end()) { + found = search; + break; } } - if (!found) - { + if (!found) { pPlugin->SetErrorState(Plugin_Error, "Library not found: %s", (*req_iter).c_str()); return; } + + found->AddDependent(pPlugin); } /* Find any unbound natives From 2adae275573c2e7dd2b8b459ddc4b1bff049d9f9 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 16 Aug 2015 13:08:18 -0700 Subject: [PATCH 4/5] Clean up CPlugin member variables. --- core/logic/PluginSys.cpp | 70 +++++++++++++-------------------------- core/logic/PluginSys.h | 48 ++++++++++++++++----------- core/logic/Translator.cpp | 2 +- core/logic/Translator.h | 3 +- 4 files changed, 55 insertions(+), 68 deletions(-) diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index 76c61d33..bd4f7493 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -52,23 +52,26 @@ HandleType_t g_PluginType = 0; IdentityType_t g_PluginIdent = 0; CPlugin::CPlugin(const char *file) + : m_serial(0), + m_status(Plugin_Uncompiled), + m_SilentFailure(false), + m_FakeNativesMissing(false), + m_LibraryMissing(false), + m_pContext(nullptr), + m_MaxClientsVar(nullptr), + m_ident(nullptr), + m_bGotAllLoaded(false), + m_FileVersion(0), + m_LastAccess(0), + m_handle(BAD_HANDLE) { static int MySerial = 0; - m_type = PluginType_Private; - m_status = Plugin_Uncompiled; - m_bSilentlyFailed = false; m_serial = ++MySerial; - m_pRuntime = NULL; - m_errormsg[sizeof(m_errormsg) - 1] = '\0'; + m_errormsg[0] = '\0'; ke::SafeSprintf(m_filename, sizeof(m_filename), "%s", file); - m_handle = 0; - m_ident = NULL; - m_FakeNativesMissing = false; - m_LibraryMissing = false; - m_bGotAllLoaded = false; + m_pPhrases = g_Translator.CreatePhraseCollection(); - m_MaxClientsVar = NULL; } CPlugin::~CPlugin() @@ -83,22 +86,9 @@ CPlugin::~CPlugin() g_ShareSys.DestroyIdentity(m_ident); } - if (m_pRuntime != NULL) - { - delete m_pRuntime; - m_pRuntime = NULL; - } - for (size_t i=0; iDestroy(); - m_pPhrases = NULL; - } } void CPlugin::InitIdentity() @@ -120,25 +110,16 @@ unsigned int CPlugin::CalcMemUsage() + (m_configs.size() * (sizeof(AutoConfig *) + sizeof(AutoConfig))) + m_Props.mem_usage(); - for (unsigned int i = 0; i < m_configs.size(); i++) - { + for (unsigned int i = 0; i < m_configs.size(); i++) { base_size += m_configs[i]->autocfg.size(); base_size += m_configs[i]->folder.size(); } - for (List::iterator i = m_Libraries.begin(); - i != m_Libraries.end(); - i++) - { + for (auto i = m_Libraries.begin(); i != m_Libraries.end(); i++) base_size += (*i).size(); - } - for (List::iterator i = m_RequiredLibs.begin(); - i != m_RequiredLibs.end(); - i++) - { + for (auto i = m_RequiredLibs.begin(); i != m_RequiredLibs.end(); i++) base_size += (*i).size(); - } return base_size; } @@ -156,12 +137,9 @@ CPlugin *CPlugin::CreatePlugin(const char *file, char *error, size_t maxlength) CPlugin *pPlugin = new CPlugin(file); - if (!fp) - { + if (!fp) { if (error) - { ke::SafeSprintf(error, maxlength, "Unable to open file"); - } pPlugin->m_status = Plugin_BadLoad; return pPlugin; } @@ -481,7 +459,7 @@ const char *CPlugin::GetFilename() PluginType CPlugin::GetType() { - return m_type; + return PluginType_MapUpdated; } const sm_plugininfo_t *CPlugin::GetPublicInfo() @@ -505,7 +483,7 @@ PluginStatus CPlugin::GetStatus() bool CPlugin::IsSilentlyFailed() { - return m_bSilentlyFailed; + return m_SilentFailure; } bool CPlugin::IsDebugging() @@ -518,9 +496,9 @@ bool CPlugin::IsDebugging() return true; } -void CPlugin::SetSilentlyFailed(bool sf) +void CPlugin::SetSilentlyFailed() { - m_bSilentlyFailed = sf; + m_SilentFailure = true; } void CPlugin::LibraryActions(LibraryAction action) @@ -922,8 +900,6 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **aResult, const char *path, bool de pPlugin = CPlugin::CreatePlugin(path, error, maxlength); assert(pPlugin != NULL); - pPlugin->m_type = PluginType_MapUpdated; - if (pPlugin->m_status == Plugin_Uncompiled) { char fullpath[PLATFORM_MAX_PATH]; @@ -1001,7 +977,7 @@ LoadRes CPluginManager::_LoadPlugin(CPlugin **aResult, const char *path, bool de case APLRes_SilentFailure: pPlugin->SetErrorState(Plugin_Failed, "%s", error); loadFailure = LoadRes_SilentFailure; - pPlugin->SetSilentlyFailed(true); + pPlugin->SetSilentlyFailed(); break; default: assert(false); diff --git a/core/logic/PluginSys.h b/core/logic/PluginSys.h index 7fa9a929..8e08b2f5 100644 --- a/core/logic/PluginSys.h +++ b/core/logic/PluginSys.h @@ -50,6 +50,7 @@ #include "IGameConfigs.h" #include "NativeOwner.h" #include "ShareSys.h" +#include "PhraseCollection.h" #include class CPlayer; @@ -140,7 +141,7 @@ public: bool IsDebugging(); PluginStatus GetStatus(); bool IsSilentlyFailed(); - void SetSilentlyFailed(bool sf); + void SetSilentlyFailed(); const sm_plugininfo_t *GetPublicInfo(); bool SetPauseState(bool paused); unsigned int GetSerial(); @@ -251,31 +252,40 @@ protected: bool UpdateInfo(); void SetTimeStamp(time_t t); void DependencyDropped(CPlugin *pOwner); + private: - PluginType m_type; + // This information is static for the lifetime of the plugin. char m_filename[PLATFORM_MAX_PATH]; - PluginStatus m_status; - bool m_bSilentlyFailed; unsigned int m_serial; - sm_plugininfo_t m_info; - char m_errormsg[256]; - time_t m_LastAccess; - IdentityToken_t *m_ident; - Handle_t m_handle; - bool m_WasRunning; - IPhraseCollection *m_pPhrases; - List m_RequiredLibs; - List m_Libraries; - StringHashMap m_Props; + + PluginStatus m_status; + + // Statuses that are set during failure. + bool m_SilentFailure; bool m_FakeNativesMissing; bool m_LibraryMissing; - CVector m_configs; - bool m_bGotAllLoaded; - int m_FileVersion; - char m_DateTime[256]; - IPluginRuntime *m_pRuntime; + char m_errormsg[256]; + + // Internal properties that must by reset if the runtime is evicted. + ke::AutoPtr m_pRuntime; + ke::AutoPtr m_pPhrases; IPluginContext *m_pContext; sp_pubvar_t *m_MaxClientsVar; + StringHashMap m_Props; + CVector m_configs; + IdentityToken_t *m_ident; + bool m_bGotAllLoaded; + int m_FileVersion; + + // Information that survives past eviction. + List m_RequiredLibs; + List m_Libraries; + time_t m_LastAccess; + Handle_t m_handle; + char m_DateTime[256]; + + // Cached. + sm_plugininfo_t m_info; }; class CPluginManager : diff --git a/core/logic/Translator.cpp b/core/logic/Translator.cpp index 05e9684d..dbd49ac0 100644 --- a/core/logic/Translator.cpp +++ b/core/logic/Translator.cpp @@ -991,7 +991,7 @@ unsigned int Translator::GetInterfaceVersion() return SMINTERFACE_TRANSLATOR_VERSION; } -IPhraseCollection *Translator::CreatePhraseCollection() +CPhraseCollection *Translator::CreatePhraseCollection() { return new CPhraseCollection(); } diff --git a/core/logic/Translator.h b/core/logic/Translator.h index 601e9b41..cd88728f 100644 --- a/core/logic/Translator.h +++ b/core/logic/Translator.h @@ -39,6 +39,7 @@ #include "sm_memtable.h" #include "ITextParsers.h" #include +#include "PhraseCollection.h" /* :TODO: write a templatized version of tries? */ @@ -127,7 +128,7 @@ public: //ITranslator unsigned int GetClientLanguage(int client); const char *GetInterfaceName(); unsigned int GetInterfaceVersion(); - IPhraseCollection *CreatePhraseCollection(); + CPhraseCollection *CreatePhraseCollection(); int SetGlobalTarget(int index); int GetGlobalTarget() const; size_t FormatString( From d473b0441d49bb3c1aec7a198075213c722a63c5 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 16 Aug 2015 13:20:47 -0700 Subject: [PATCH 5/5] Allow plugin info fields to outlive their runtime. --- core/logic/PluginSys.cpp | 59 ++++++++++++++++++++-------------------- core/logic/PluginSys.h | 6 ++++ 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/core/logic/PluginSys.cpp b/core/logic/PluginSys.cpp index bd4f7493..3ad689bc 100644 --- a/core/logic/PluginSys.cpp +++ b/core/logic/PluginSys.cpp @@ -71,6 +71,8 @@ CPlugin::CPlugin(const char *file) m_errormsg[0] = '\0'; ke::SafeSprintf(m_filename, sizeof(m_filename), "%s", file); + memset(&m_info, 0, sizeof(m_info)); + m_pPhrases = g_Translator.CreatePhraseCollection(); } @@ -208,10 +210,7 @@ bool CPlugin::UpdateInfo() IPluginContext *base = GetBaseContext(); int err = base->FindPubvarByName("myinfo", &idx); - memset(&m_info, 0, sizeof(m_info)); - - if (err == SP_ERROR_NONE) - { + if (err == SP_ERROR_NONE) { struct sm_plugininfo_c_t { cell_t name; @@ -223,22 +222,24 @@ bool CPlugin::UpdateInfo() sm_plugininfo_c_t *cinfo; cell_t local_addr; + auto update_field = [base](cell_t addr, ke::AString *dest) { + const char* ptr; + if (base->LocalToString(addr, (char **)&ptr) == SP_ERROR_NONE) + *dest = ptr; + else + *dest = ""; + }; + base->GetPubvarAddrs(idx, &local_addr, (cell_t **)&cinfo); - base->LocalToString(cinfo->name, (char **)&m_info.name); - base->LocalToString(cinfo->description, (char **)&m_info.description); - base->LocalToString(cinfo->author, (char **)&m_info.author); - base->LocalToString(cinfo->url, (char **)&m_info.url); - base->LocalToString(cinfo->version, (char **)&m_info.version); + update_field(cinfo->name, &info_name_); + update_field(cinfo->description, &info_description_); + update_field(cinfo->author, &info_author_); + update_field(cinfo->version, &info_version_); + update_field(cinfo->url, &info_url_); } - m_info.author = m_info.author ? m_info.author : ""; - m_info.description = m_info.description ? m_info.description : ""; - m_info.name = m_info.name ? m_info.name : ""; - m_info.url = m_info.url ? m_info.url : ""; - m_info.version = m_info.version ? m_info.version : ""; - - if ((err = base->FindPubvarByName("__version", &idx)) == SP_ERROR_NONE) - { + ke::SafeStrcpy(m_DateTime, sizeof(m_DateTime), "unknown"); + if ((err = base->FindPubvarByName("__version", &idx)) == SP_ERROR_NONE) { struct __version_info { cell_t version; @@ -255,28 +256,24 @@ bool CPlugin::UpdateInfo() base->GetPubvarAddrs(idx, &local_addr, (cell_t **)&info); m_FileVersion = info->version; - if (m_FileVersion >= 4) - { + if (m_FileVersion >= 4) { base->LocalToString(info->date, (char **)&pDate); base->LocalToString(info->time, (char **)&pTime); ke::SafeSprintf(m_DateTime, sizeof(m_DateTime), "%s %s", pDate, pTime); } - if (m_FileVersion > 5) - { + if (m_FileVersion > 5) { base->LocalToString(info->filevers, (char **)&pFileVers); SetErrorState(Plugin_Failed, "Newer SourceMod required (%s or higher)", pFileVers); return false; } - } - else - { + } else { m_FileVersion = 0; } if ((err = base->FindPubvarByName("MaxClients", &idx)) == SP_ERROR_NONE) - { base->GetPubvarByIndex(idx, &m_MaxClientsVar); - } + else + m_MaxClientsVar = nullptr; return true; } @@ -465,9 +462,13 @@ PluginType CPlugin::GetType() const sm_plugininfo_t *CPlugin::GetPublicInfo() { if (GetStatus() >= Plugin_Created) - { - return NULL; - } + return nullptr; + + m_info.author = info_author_.chars(); + m_info.description = info_description_.chars(); + m_info.name = info_name_.chars(); + m_info.url = info_url_.chars(); + m_info.version = info_version_.chars(); return &m_info; } diff --git a/core/logic/PluginSys.h b/core/logic/PluginSys.h index 8e08b2f5..f237d477 100644 --- a/core/logic/PluginSys.h +++ b/core/logic/PluginSys.h @@ -51,6 +51,7 @@ #include "NativeOwner.h" #include "ShareSys.h" #include "PhraseCollection.h" +#include #include class CPlayer; @@ -286,6 +287,11 @@ private: // Cached. sm_plugininfo_t m_info; + ke::AString info_name_; + ke::AString info_author_; + ke::AString info_description_; + ke::AString info_version_; + ke::AString info_url_; }; class CPluginManager :