diff --git a/core/interfaces/IPluginSys.h b/core/interfaces/IPluginSys.h index 3f728536..45f27065 100644 --- a/core/interfaces/IPluginSys.h +++ b/core/interfaces/IPluginSys.h @@ -148,7 +148,7 @@ namespace SourceMod /** * @brief Returns a plugin's identity token. */ - virtual IdentityToken_t *GetIdentity() =0; + virtual IdentityToken_t *GetIdentity() const =0; }; diff --git a/core/sm_srvcmds.cpp b/core/sm_srvcmds.cpp index 0b88e3ee..016c46fe 100644 --- a/core/sm_srvcmds.cpp +++ b/core/sm_srvcmds.cpp @@ -185,6 +185,54 @@ CON_COMMAND(sm, "SourceMod Menu") iter->Release(); return; + } else if (!strcmp("debug", cmd2)) { + if (argnum < 5) + { + META_CONPRINT("Usage: sm plugins debug <#> [on|off]\n"); + return; + } + + int num = atoi(engine->Cmd_Argv(3)); + if (num < 1 || num > (int)g_PluginSys.GetPluginCount()) + { + META_CONPRINT("Plugin index not found.\n"); + return; + } + + int res; + char *mode = engine->Cmd_Argv(4); + if ((res=strcmp("on", mode)) && strcmp("off", mode)) + { + META_CONPRINT("The only possible options are on and off.\n"); + return; + } + + bool debug; + if (!res) + { + debug = true; + } else { + debug = false; + } + + CPlugin *pl = g_PluginSys.GetPluginByOrder(num); + if (debug && pl->IsDebugging()) + { + META_CONPRINT("This plugin is already in debug mode.\n"); + return; + } else if (!debug && !pl->IsDebugging()) { + META_CONPRINT("Debug mode is already disabled in this plugin.\n"); + return; + } + + if (pl->ToggleDebugMode(debug)) + { + META_CONPRINTF("Toggled debug mode on plugin %s successfully.\n", pl->GetFilename()); + return; + } else { + META_CONPRINTF("Could not toggle debug mode in plugin %s.\n", pl->GetFilename()); + return; + } } } @@ -193,23 +241,24 @@ CON_COMMAND(sm, "SourceMod Menu") META_CONPRINT(" load - Load a plugin\n"); META_CONPRINT(" unload - Unload a plugin\n"); META_CONPRINT(" info - Information about a plugin\n"); + META_CONPRINT(" debug - Toggles debug mode in a plugin\n"); return; } else if (!strcmp("credits", cmd)) { - META_CONPRINTF(" SourceMod was developed by AlliedModders, LLC.\n"); - META_CONPRINTF(" Development would not have been possible without the following people:\n"); - META_CONPRINTF(" David \"BAILOPAN\" Anderson, lead developer\n"); - META_CONPRINTF(" Borja \"faluco\" Ferrer, Core developer\n"); - META_CONPRINTF(" Scott \"Damaged Soul\" Ehlert, SourceMM developer\n"); - META_CONPRINTF(" Pavol \"PM OnoTo\" Marko, SourceHook developer\n"); - META_CONPRINTF(" Special thanks to Viper of GameConnect, and Mani\n"); - META_CONPRINTF(" http://www.sourcemod.net/\n"); + META_CONPRINT(" SourceMod was developed by AlliedModders, LLC.\n"); + META_CONPRINT(" Development would not have been possible without the following people:\n"); + META_CONPRINT(" David \"BAILOPAN\" Anderson, lead developer\n"); + META_CONPRINT(" Borja \"faluco\" Ferrer, Core developer\n"); + META_CONPRINT(" Scott \"Damaged Soul\" Ehlert, SourceMM developer\n"); + META_CONPRINT(" Pavol \"PM OnoTo\" Marko, SourceHook developer\n"); + META_CONPRINT(" Special thanks to Viper of GameConnect, and Mani\n"); + META_CONPRINT(" http://www.sourcemod.net/\n"); return; } else if (!strcmp("version", cmd)) { META_CONPRINT(" SourceMod Version Information:\n"); META_CONPRINTF(" SourceMod Version: \"%s\"\n", SOURCEMOD_VERSION); META_CONPRINTF(" JIT Version: %s (%s)\n", g_pVM->GetVMName(), g_pVM->GetVersionString()); META_CONPRINTF(" JIT Settings: %s\n", g_pVM->GetCPUOptimizations()); - META_CONPRINTF(" http://www.sourcemod.net/\n"); + META_CONPRINT(" http://www.sourcemod.net/\n"); return; } } diff --git a/core/systems/PluginSys.cpp b/core/systems/PluginSys.cpp index 1d1551b6..d7f3bb07 100644 --- a/core/systems/PluginSys.cpp +++ b/core/systems/PluginSys.cpp @@ -485,11 +485,53 @@ bool CPlugin::SetPauseState(bool paused) return true; } -IdentityToken_t *CPlugin::GetIdentity() +IdentityToken_t *CPlugin::GetIdentity() const { return m_ident; } +bool CPlugin::ToggleDebugMode(bool debug) +{ + int err; + + if (!IsRunnable()) + { + return false; + } + + if ((debug && IsDebugging()) || (!debug && !IsDebugging())) + { + return false; + } + ICompilation *co = g_pVM->StartCompilation(m_ctx.ctx->plugin); + if (!g_pVM->SetCompilationOption(co, "debug", (debug) ? "1" : "0")) + { + return false; + } + sp_context_t *new_ctx = g_pVM->CompileToContext(co, &err); + + memcpy(new_ctx->memory, m_ctx.ctx->memory, m_ctx.ctx->mem_size); + new_ctx->hp = m_ctx.ctx->hp; + new_ctx->sp = m_ctx.ctx->sp; + new_ctx->frm = m_ctx.ctx->frm; + new_ctx->dbreak = m_ctx.ctx->dbreak; + new_ctx->context = m_ctx.ctx->context; + memcpy(new_ctx->user, m_ctx.ctx->user, sizeof(m_ctx.ctx->user)); + + g_pVM->FreeContext(m_ctx.ctx); + m_ctx.ctx = new_ctx; + m_ctx.base->SetContext(new_ctx); + + UpdateInfo(); + + return true; +} + +bool CPlugin::IsRunnable() const +{ + return (m_status <= Plugin_Paused) ? true : false; +} + /******************* * PLUGIN ITERATOR * *******************/ @@ -1152,7 +1194,7 @@ bool CPluginManager::TestAliasMatch(const char *alias, const char *localpath) return true; } -bool CPluginManager::IsLateLoadTime() +bool CPluginManager::IsLateLoadTime() const { return (m_AllPluginsLoaded || g_SourceMod.IsLateLoadInMap()); } @@ -1210,3 +1252,22 @@ IPlugin *CPluginManager::PluginFromHandle(Handle_t handle, HandleError *err) return pPlugin; } + +CPlugin *CPluginManager::GetPluginByOrder(int num) +{ + if (num < 1 || num > (int)GetPluginCount()) + { + return NULL; + } + + CPlugin *pl; + int id = 1; + + IPluginIterator *iter = GetPluginIterator(); + for (; iter->MorePlugins() && idNextPlugin(), id++) {} + + pl = (CPlugin *)(iter->GetPlugin()); + iter->Release(); + + return pl; +} \ No newline at end of file diff --git a/core/systems/PluginSys.h b/core/systems/PluginSys.h index 7ac3d980..5a585655 100644 --- a/core/systems/PluginSys.h +++ b/core/systems/PluginSys.h @@ -94,7 +94,7 @@ public: virtual const sp_plugin_t *GetPluginStructure() const; virtual IPluginFunction *GetFunctionByName(const char *public_name); virtual IPluginFunction *GetFunctionById(funcid_t func_id); - virtual IdentityToken_t *GetIdentity(); + virtual IdentityToken_t *GetIdentity() const; public: /** * Creates a plugin object with default values. @@ -146,6 +146,16 @@ public: * Calls the OnPluginUnload function. */ void Call_OnPluginUnload(); + + /** + * Toggles debug mode in the plugin + */ + bool ToggleDebugMode(bool debug); + + /** + * Returns true if a plugin is usable. + */ + bool IsRunnable() const; public: time_t HasUpdatedFile(); @@ -242,7 +252,7 @@ public: /** * Returns whether anything loaded will be a late load. */ - bool IsLateLoadTime(); + bool IsLateLoadTime() const; /** * Adds natives from core into the native pool. @@ -253,6 +263,11 @@ public: * Converts a Handle to an IPlugin if possible. */ IPlugin *PluginFromHandle(Handle_t handle, HandleError *err); + + /** + * Finds a plugin based on its index. (starts on index 1) + */ + CPlugin *GetPluginByOrder(int num); private: /** * Recursively loads all plugins in the given directory. diff --git a/core/vm/sp_vm_basecontext.cpp b/core/vm/sp_vm_basecontext.cpp index a1bf02f1..6b63ae53 100644 --- a/core/vm/sp_vm_basecontext.cpp +++ b/core/vm/sp_vm_basecontext.cpp @@ -29,6 +29,15 @@ BaseContext::BaseContext(sp_context_t *_ctx) m_CustomMsg = false; } +void BaseContext::SetContext(sp_context_t *_ctx) +{ + if (!_ctx) + { + return; + } + ctx = _ctx; +} + IVirtualMachine *BaseContext::GetVirtualMachine() { return (IVirtualMachine *)ctx->vmbase; diff --git a/core/vm/sp_vm_basecontext.h b/core/vm/sp_vm_basecontext.h index 5b495509..7ba4d0f6 100644 --- a/core/vm/sp_vm_basecontext.h +++ b/core/vm/sp_vm_basecontext.h @@ -52,6 +52,8 @@ namespace SourcePawn virtual int LookupFile(ucell_t addr, const char **filename); virtual int LookupFunction(ucell_t addr, const char **name); virtual int LookupLine(ucell_t addr, uint32_t *line); + public: + void SetContext(sp_context_t *_ctx); private: void SetErrorMessage(const char *msg, va_list ap); private: