diff --git a/AMBuildScript b/AMBuildScript index e2ffb7c..74093f4 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -78,7 +78,6 @@ class SM: self.compiler.AddToListVar('CXXFLAGS', '-fvisibility-inlines-hidden') self.compiler.AddToListVar('CFLAGS', '-Wall') self.compiler.AddToListVar('CFLAGS', '-Werror') - self.compiler.AddToListVar('CFLAGS', '-Wno-uninitialized') self.compiler.AddToListVar('CFLAGS', '-Wno-unused') self.compiler.AddToListVar('CFLAGS', '-Wno-switch') self.compiler.AddToListVar('CFLAGS', '-Wno-implicit-exception-spec-mismatch') diff --git a/extension/extension.cpp b/extension/extension.cpp index 8b73837..76238ae 100644 --- a/extension/extension.cpp +++ b/extension/extension.cpp @@ -229,44 +229,6 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, } } -#if 0 - char pis[64]; - char pds[32]; - for (unsigned i = 0; i < plugin_count; ++i) { - PluginInfo *p = &plugins[i]; - if (p->serial == 0) continue; - my_uitos(pds, i, my_uint_len(i)); - pds[my_uint_len(i)] = '\0'; - my_strlcpy(pis, "plugin[", sizeof(pis)); - my_strlcat(pis, pds, sizeof(pis)); - my_strlcat(pis, "].", sizeof(pis)); - sys_write(extra, pis, my_strlen(pis)); - sys_write(extra, "filename=", 9); - sys_write(extra, p->filename, my_strlen(p->filename)); - sys_write(extra, "\n", 1); - sys_write(extra, pis, my_strlen(pis)); - sys_write(extra, "name=", 5); - sys_write(extra, p->name, my_strlen(p->name)); - sys_write(extra, "\n", 1); - sys_write(extra, pis, my_strlen(pis)); - sys_write(extra, "author=", 7); - sys_write(extra, p->author, my_strlen(p->author)); - sys_write(extra, "\n", 1); - sys_write(extra, pis, my_strlen(pis)); - sys_write(extra, "description=", 12); - sys_write(extra, p->description, my_strlen(p->description)); - sys_write(extra, "\n", 1); - sys_write(extra, pis, my_strlen(pis)); - sys_write(extra, "version=", 8); - sys_write(extra, p->version, my_strlen(p->version)); - sys_write(extra, "\n", 1); - sys_write(extra, pis, my_strlen(pis)); - sys_write(extra, "url=", 4); - sys_write(extra, p->url, my_strlen(p->url)); - sys_write(extra, "\n", 1); - } -#endif - sys_close(extra); return succeeded; @@ -1226,28 +1188,17 @@ bool Accelerator::SDK_OnLoad(char *error, size_t maxlength, bool late) #error Bad platform. #endif -#if 0 - IPluginIterator *i = plsys->GetPluginIterator(); - while (i->MorePlugins()) { - IPlugin *p = i->GetPlugin(); - const sm_plugininfo_t *pmi = p->GetPublicInfo(); - PluginInfo *pi = &plugins[plugin_count++]; + plsys->AddPluginsListener(this); - pi->serial = p->GetSerial(); - pi->status = p->GetStatus(); - - strncpy(pi->filename, p->GetFilename(), sizeof(pi->filename) - 1); - - strncpy(pi->name, pmi->name, sizeof(pi->name) - 1); - strncpy(pi->author, pmi->author, sizeof(pi->author) - 1); - strncpy(pi->description, pmi->description, sizeof(pi->description) - 1); - strncpy(pi->version, pmi->version, sizeof(pi->version) - 1); - strncpy(pi->url, pmi->url, sizeof(pi->url) - 1); - - i->NextPlugin(); + IPluginIterator *iterator = plsys->GetPluginIterator(); + while (iterator->MorePlugins()) { + IPlugin *plugin = iterator->GetPlugin(); + if (plugin->GetStatus() == Plugin_Running) { + this->OnPluginLoaded(plugin); + } + iterator->NextPlugin(); } - delete i; -#endif + delete iterator; strncpy(crashCommandLine, GetCmdLine(), sizeof(crashCommandLine) - 1); @@ -1316,6 +1267,8 @@ bool Accelerator::SDK_OnLoad(char *error, size_t maxlength, bool late) void Accelerator::SDK_OnUnload() { + plsys->RemovePluginsListener(this); + #if defined _LINUX g_pSM->RemoveGameFrameHook(OnGameFrame); #elif defined _WINDOWS @@ -1333,3 +1286,162 @@ void Accelerator::OnCoreMapStart(edict_t *pEdictList, int edictCount, int client { strncpy(crashMap, gamehelpers->GetCurrentMap(), sizeof(crashMap) - 1); } + +/* 010 Editor Template +uint64 headerMagic; +uint32 version; +uint32 size; +uint32 count; +struct { + uint32 size; + uint32 context ; + char file[]; + uint32 count; + struct { + uint32 pcode ; + char name[]; + } functions[count] ; +} plugins[count] ; +uint64 tailMagic; +*/ + +unsigned char *serializedPluginContexts = nullptr; +std::map pluginContextMap; + +void SerializePluginContexts() +{ + if (serializedPluginContexts) { + handler->UnregisterAppMemory(serializedPluginContexts); + free(serializedPluginContexts); + serializedPluginContexts = nullptr; + } + + uint32_t count = pluginContextMap.size(); + if (count == 0) { + return; + } + + uint32_t size = 0; + size += sizeof(uint64_t); // header magic + size += sizeof(uint32_t); // version + size += sizeof(uint32_t); // size + size += sizeof(uint32_t); // count + + for (auto &it : pluginContextMap) { + unsigned char *buffer = it.second; + + uint32_t bufferSize; + memcpy(&bufferSize, buffer, sizeof(uint32_t)); + + size += bufferSize; + } + + size += sizeof(uint64_t); // tail magic + + serializedPluginContexts = (unsigned char *)malloc(size); + handler->RegisterAppMemory(serializedPluginContexts, size); + unsigned char *cursor = serializedPluginContexts; + + uint64_t headerMagic = 103582791429521979ULL; + memcpy(cursor, &headerMagic, sizeof(uint64_t)); + cursor += sizeof(uint64_t); + + uint32_t version = 1; + memcpy(cursor, &version, sizeof(uint32_t)); + cursor += sizeof(uint32_t); + + memcpy(cursor, &size, sizeof(uint32_t)); + cursor += sizeof(uint32_t); + + memcpy(cursor, &count, sizeof(uint32_t)); + cursor += sizeof(uint32_t); + + for (auto &it : pluginContextMap) { + unsigned char *buffer = it.second; + + uint32_t bufferSize; + memcpy(&bufferSize, buffer, sizeof(uint32_t)); + + memcpy(cursor, buffer, bufferSize); + cursor += bufferSize; + } + + uint64_t tailMagic = 76561197987819599ULL; + memcpy(cursor, &tailMagic, sizeof(uint64_t)); + cursor += sizeof(uint64_t); +} + +void Accelerator::OnPluginLoaded(IPlugin *plugin) +{ + IPluginRuntime *runtime = plugin->GetRuntime(); + IPluginContext *context = plugin->GetBaseContext(); + if (!runtime || !context) { + return; + } + + const char *filename = plugin->GetFilename(); + size_t filenameSize = strlen(filename) + 1; + + uint32_t size = 0; + size += sizeof(uint32_t); // size + size += sizeof(void *); // GetBaseContext + size += filenameSize; + + uint32_t count = runtime->GetPublicsNum(); + size += sizeof(uint32_t); // count + size += count * sizeof(uint32_t); // pubinfo->code_offs + + for (uint32_t i = 0; i < count; ++i) { + sp_public_t *pubinfo; + runtime->GetPublicByIndex(i, &pubinfo); + + size += strlen(pubinfo->name) + 1; + } + + unsigned char *buffer = (unsigned char *)malloc(size); + unsigned char *cursor = buffer; + + memcpy(cursor, &size, sizeof(uint32_t)); + cursor += sizeof(uint32_t); + + memcpy(cursor, &context, sizeof(void *)); + cursor += sizeof(void *); + + memcpy(cursor, filename, filenameSize); + cursor += filenameSize; + + memcpy(cursor, &count, sizeof(uint32_t)); + cursor += sizeof(uint32_t); + + for (uint32_t i = 0; i < count; ++i) { + sp_public_t *pubinfo; + runtime->GetPublicByIndex(i, &pubinfo); + + memcpy(cursor, &pubinfo->code_offs, sizeof(uint32_t)); + cursor += sizeof(uint32_t); + + size_t nameSize = strlen(pubinfo->name) + 1; + memcpy(cursor, pubinfo->name, nameSize); + cursor += nameSize; + } + + pluginContextMap[context] = buffer; + + SerializePluginContexts(); +} + +void Accelerator::OnPluginUnloaded(IPlugin *plugin) +{ + IPluginContext *context = plugin->GetBaseContext(); + if (!context) { + return; + } + + auto it = pluginContextMap.find(context); + if (it != pluginContextMap.end()) { + free(it->second); + pluginContextMap.erase(it); + } + + SerializePluginContexts(); +} diff --git a/extension/extension.h b/extension/extension.h index e153ff1..d9495ef 100644 --- a/extension/extension.h +++ b/extension/extension.h @@ -30,11 +30,10 @@ /** * @brief Sample implementation of the SDK Extension. - * Note: Uncomment one of the pre-defined virtual functions in order to use it. */ -class Accelerator : public SDKExtension +class Accelerator : public SDKExtension, IPluginsListener { -public: +public: // SDKExtension /** * @brief This is called after the initial loading sequence has been processed. * @@ -50,52 +49,6 @@ public: */ virtual void SDK_OnUnload(); - /** - * @brief Called when the pause state is changed. - */ - //virtual void SDK_OnPauseChange(bool paused); - - /** - * @brief this is called when Core wants to know if your extension is working. - * - * @param error Error message buffer. - * @param maxlength Size of error message buffer. - * @return True if working, false otherwise. - */ - //virtual bool QueryRunning(char *error, size_t maxlen); -public: -#if defined SMEXT_CONF_METAMOD - /** - * @brief Called when Metamod is attached, before the extension version is called. - * - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @param late Whether or not Metamod considers this a late load. - * @return True to succeed, false to fail. - */ - //virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlen, bool late); - - /** - * @brief Called when Metamod is detaching, after the extension version is called. - * NOTE: By default this is blocked unless sent from SourceMod. - * - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @return True to succeed, false to fail. - */ - //virtual bool SDK_OnMetamodUnload(char *error, size_t maxlen); - - /** - * @brief Called when Metamod's pause state is changing. - * NOTE: By default this is blocked unless sent from SourceMod. - * - * @param paused Pause state being set. - * @param error Error buffer. - * @param maxlength Maximum size of error buffer. - * @return True to succeed, false to fail. - */ - //virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlen); -#endif /** * @brief Called on server activation before plugins receive the OnServerLoad forward. * @@ -104,6 +57,17 @@ public: * @param clientMax Maximum number of clients allowed in the server. */ virtual void OnCoreMapStart(edict_t *pEdictList, int edictCount, int clientMax); + +public: // IPluginsListener + /** + * @brief Called when a plugin is fully loaded successfully. + */ + virtual void OnPluginLoaded(IPlugin *plugin); + + /** + * @brief Called when a plugin is unloaded (only if fully loaded). + */ + virtual void OnPluginUnloaded(IPlugin *plugin); }; #endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_