Finished porting the "plugins" command to the new menu system

--HG--
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40314
This commit is contained in:
David Anderson 2007-01-17 18:22:00 +00:00
parent 35d0c555fa
commit 3597a8b1fe
5 changed files with 321 additions and 53 deletions

View File

@ -71,6 +71,17 @@ namespace SourceMod
* @return String containing all arguments.
*/
virtual const char *GetArguments() =0;
/**
* @brief Draws a generic command/description pair.
* NOTE: The pair is currently four spaces indented and 16-N spaces of separation,
* N being the length of the command name. This is subject to change in case we
* account for Valve's font choices.
*
* @param option String containing the command option.
* @param description String containing the command description.
*/
virtual void DrawGenericOption(const char *cmd, const char *text) =0;
};
};

View File

@ -41,28 +41,6 @@ bool RootConsoleMenu::RegisterConCommandBase(ConCommandBase *pCommand)
return true;
}
inline const char *StatusToStr(PluginStatus st)
{
switch (st)
{
case Plugin_Running:
return "Running";
case Plugin_Paused:
return "Paused";
case Plugin_Error:
return "Error";
case Plugin_Uncompiled:
return "Uncompiled";
case Plugin_BadLoad:
return "Bad Load";
case Plugin_Failed:
return "Failed";
default:
assert(false);
return "-";
}
}
void RootConsoleMenu::ConsolePrint(const char *fmt, ...)
{
char buffer[512];
@ -155,6 +133,24 @@ bool RootConsoleMenu::RemoveRootConsoleCommand(const char *cmd, IRootConsoleComm
return true;
}
void RootConsoleMenu::DrawGenericOption(const char *cmd, const char *text)
{
char buffer[255];
size_t len, cmdlen = strlen(cmd);
len = snprintf(buffer, sizeof(buffer), " %s", cmd);
if (cmdlen < 16)
{
size_t num = 16 - cmdlen;
for (size_t i = 0; i < num; i++)
{
buffer[len++] = ' ';
}
len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", text);
ConsolePrint("%s", buffer);
}
}
void RootConsoleMenu::GotRootCmd()
{
unsigned int argnum = GetArgumentCount();
@ -175,22 +171,10 @@ void RootConsoleMenu::GotRootCmd()
List<ConsoleEntry *>::iterator iter;
ConsoleEntry *pEntry;
char buffer[255];
size_t len;
for (iter=m_Menu.begin(); iter!=m_Menu.end(); iter++)
{
pEntry = (*iter);
len = snprintf(buffer, sizeof(buffer), " %s", pEntry->command.c_str());
if (pEntry->command.size() < 16)
{
size_t num = 16 - pEntry->command.size();
for (size_t i = 0; i < num; i++)
{
buffer[len++] = ' ';
}
}
len += snprintf(&buffer[len], sizeof(buffer) - len, " - %s", pEntry->description.c_str());
ConsolePrint("%s", buffer);
DrawGenericOption(pEntry->command.c_str(), pEntry->description.c_str());
}
}
@ -231,7 +215,6 @@ void RootConsoleMenu::OnRootConsoleCommand(const char *cmd, unsigned int argcoun
}
}
#define IS_STR_FILLED(var) (var[0] != '\0')
CON_COMMAND(sm, "SourceMod Menu")
{
g_RootMenu.GotRootCmd();

View File

@ -42,6 +42,7 @@ public: //IRootConsole
const char *GetArgument(unsigned int argno);
unsigned int GetArgumentCount();
const char *GetArguments();
void DrawGenericOption(const char *cmd, const char *text);
public:
void GotRootCmd();
private:

View File

@ -8,6 +8,8 @@
#include "CTextParsers.h"
#include "CLogger.h"
#include "ExtensionSys.h"
#include "sm_srvcmds.h"
#include "sm_stringutil.h"
CPluginManager g_PluginSys;
HandleType_t g_PluginType = 0;
@ -477,39 +479,68 @@ IdentityToken_t *CPlugin::GetIdentity() const
return m_ident;
}
bool CPlugin::ToggleDebugMode(bool debug)
bool CPlugin::ToggleDebugMode(bool debug, char *error, size_t maxlength)
{
int err;
if (!IsRunnable())
{
if (error)
{
snprintf(error, maxlength, "Plugin is not runnable.");
}
return false;
}
if ((debug && IsDebugging()) || (!debug && !IsDebugging()))
if (debug && IsDebugging())
{
if (error)
{
snprintf(error, maxlength, "Plugin is already in debug mode.");
}
return false;
} else if (!debug && !IsDebugging()) {
if (error)
{
snprintf(error, maxlength, "Plugins is already in production mode.");
}
return false;
}
ICompilation *co = g_pVM->StartCompilation(m_ctx.ctx->plugin);
if (!g_pVM->SetCompilationOption(co, "debug", (debug) ? "1" : "0"))
{
if (error)
{
snprintf(error, maxlength, "Failed to change plugin mode (JIT failure).");
}
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));
if (new_ctx)
{
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);
g_pVM->FreeContext(m_ctx.ctx);
m_ctx.ctx = new_ctx;
m_ctx.base->SetContext(new_ctx);
UpdateInfo();
UpdateInfo();
} else {
if (error)
{
snprintf(error, maxlength, "Failed to recompile plugin (JIT error %d).", err);
}
return false;
}
return true;
}
@ -1252,10 +1283,14 @@ void CPluginManager::OnSourceModAllInitialized()
g_PluginType = g_HandleSys.CreateType("Plugin", this, 0, NULL, &sec, m_MyIdent, NULL);
g_PluginIdent = g_ShareSys.CreateIdentType("PLUGIN");
g_RootMenu.AddRootConsoleCommand("plugins", "Manage Plugins", this);
}
void CPluginManager::OnSourceModShutdown()
{
g_RootMenu.RemoveRootConsoleCommand("plugins", this);
List<CPlugin *>::iterator iter;
while ( (iter = m_plugins.begin()) != m_plugins.end() )
{
@ -1318,3 +1353,232 @@ CPlugin *CPluginManager::GetPluginByOrder(int num)
return pl;
}
const char *CPluginManager::GetStatusText(PluginStatus st)
{
switch (st)
{
case Plugin_Running:
return "Running";
case Plugin_Paused:
return "Paused";
case Plugin_Error:
return "Error";
case Plugin_Uncompiled:
return "Uncompiled";
case Plugin_BadLoad:
return "Bad Load";
case Plugin_Failed:
return "Failed";
default:
assert(false);
return "-";
}
}
#define IS_STR_FILLED(var) (var[0] != '\0')
void CPluginManager::OnRootConsoleCommand(const char *command, unsigned int argcount)
{
if (argcount >= 3)
{
const char *cmd = g_RootMenu.GetArgument(2);
if (strcmp(cmd, "list") == 0)
{
char buffer[256];
unsigned int id = 1;
int plnum = GetPluginCount();
if (!plnum)
{
g_RootMenu.ConsolePrint("[SM] No plugins loaded");
return;
} else {
g_RootMenu.ConsolePrint("[SM] Displaying %d plugin%s:", GetPluginCount(), (plnum > 1) ? "s" : "");
}
IPluginIterator *iter = GetPluginIterator();
for (; iter->MorePlugins(); iter->NextPlugin(), id++)
{
IPlugin *pl = iter->GetPlugin();
assert(pl->GetStatus() != Plugin_Created);
int len = 0;
const sm_plugininfo_t *info = pl->GetPublicInfo();
len += UTIL_Format(buffer, sizeof(buffer), " %02d <%s>", id, GetStatusText(pl->GetStatus()));
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " \"%s\"", (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
if (IS_STR_FILLED(info->version))
{
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", info->version);
}
if (IS_STR_FILLED(info->author))
{
UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", info->author);
}
g_RootMenu.ConsolePrint("%s", buffer);
}
iter->Release();
return;
} else if (strcmp(cmd, "load") == 0) {
if (argcount < 4)
{
g_RootMenu.ConsolePrint("Usage: sm plugins load <file>");
return;
}
char error[128];
const char *filename = g_RootMenu.GetArgument(3);
IPlugin *pl = LoadPlugin(filename, false, PluginType_MapUpdated, error, sizeof(error));
if (pl)
{
g_RootMenu.ConsolePrint("[SM] Loaded plugin %s successfully.", filename);
} else {
g_RootMenu.ConsolePrint("[SM] Plugin %s failed to load: %s.", filename, error);
}
return;
} else if (strcmp(cmd, "unload") == 0) {
if (argcount < 4)
{
g_RootMenu.ConsolePrint("Usage: sm plugins unload <#>");
return;
}
int id = 1;
int num = atoi(g_RootMenu.GetArgument(3));
if (num < 1 || num > (int)GetPluginCount())
{
g_RootMenu.ConsolePrint("Plugin index %d not found.", num);
return;
}
IPluginIterator *iter = GetPluginIterator();
for (; iter->MorePlugins() && id<num; iter->NextPlugin(), id++)
;
IPlugin *pl = iter->GetPlugin();
char name[PLATFORM_MAX_PATH+1];
const sm_plugininfo_t *info = pl->GetPublicInfo();
strcpy(name, (IS_STR_FILLED(info->name)) ? info->name : pl->GetFilename());
if (UnloadPlugin(pl))
{
g_RootMenu.ConsolePrint("Plugin %s unloaded successfully.", name);
} else {
g_RootMenu.ConsolePrint("Failed to unload plugin %s.", name);
}
iter->Release();
return;
} else if (strcmp(cmd, "info") == 0) {
if (argcount < 4)
{
g_RootMenu.ConsolePrint("Usage: sm plugins info <#>");
return;
}
int id = 1;
int num = atoi(g_RootMenu.GetArgument(3));
if (num < 1 || num > (int)GetPluginCount())
{
g_RootMenu.ConsolePrint("Plugin index not found.");
return;
}
IPluginIterator *iter = GetPluginIterator();
for (; iter->MorePlugins() && id<num; iter->NextPlugin(), id++) {}
IPlugin *pl = iter->GetPlugin();
const sm_plugininfo_t *info = pl->GetPublicInfo();
g_RootMenu.ConsolePrint(" Filename: %s", pl->GetFilename());
if (IS_STR_FILLED(info->name))
{
g_RootMenu.ConsolePrint(" Title: %s", info->name);
}
if (IS_STR_FILLED(info->author))
{
g_RootMenu.ConsolePrint(" Author: %s", info->author);
}
if (IS_STR_FILLED(info->version))
{
g_RootMenu.ConsolePrint(" Version: %s", info->version);
}
if (IS_STR_FILLED(info->description))
{
g_RootMenu.ConsolePrint(" Description: %s", info->description);
}
if (IS_STR_FILLED(info->url))
{
g_RootMenu.ConsolePrint(" URL: %s", info->url);
}
if (pl->GetStatus() >= Plugin_Error)
{
g_RootMenu.ConsolePrint(" Debugging: %s", pl->IsDebugging() ? "yes" : "no");
}
iter->Release();
return;
} else if (strcmp(cmd, "debug") == 0) {
if (argcount < 5)
{
g_RootMenu.ConsolePrint("Usage: sm plugins debug <#> [on|off]");
return;
}
int num = atoi(g_RootMenu.GetArgument(3));
if (num < 1 || num > (int)GetPluginCount())
{
g_RootMenu.ConsolePrint("Plugin index not found.");
return;
}
int res;
const char *mode = g_RootMenu.GetArgument(4);
if ((res=strcmp("on", mode)) && strcmp("off", mode))
{
g_RootMenu.ConsolePrint("The only possible options are \"on\" and \"off.\"");
return;
}
bool debug;
if (!res)
{
debug = true;
} else {
debug = false;
}
CPlugin *pl = GetPluginByOrder(num);
if (debug && pl->IsDebugging())
{
g_RootMenu.ConsolePrint("[SM] This plugin is already in debug mode.");
return;
} else if (!debug && !pl->IsDebugging()) {
g_RootMenu.ConsolePrint("[SM] Debug mode is already disabled in this plugin.");
return;
}
char error[256];
if (pl->ToggleDebugMode(debug, error, sizeof(error)))
{
g_RootMenu.ConsolePrint("Successfully toggled debug mode on plugin %s.", pl->GetFilename());
return;
} else {
g_RootMenu.ConsolePrint("[SM] Could not toggle debug mode on plugin %s.", pl->GetFilename());
g_RootMenu.ConsolePrint("[SM] Plugin returned error: %s", error);
return;
}
}
}
/* Draw the main menu */
g_RootMenu.ConsolePrint("SourceMod Plugins Menu:");
g_RootMenu.DrawGenericOption("list", "Show loaded plugins");
g_RootMenu.DrawGenericOption("load", "Load a plugin");
g_RootMenu.DrawGenericOption("unload", "Unload a plugin");
g_RootMenu.DrawGenericOption("info", "Information about a plugin");
g_RootMenu.DrawGenericOption("debug", "Toggle debug mode on a plugin");
}

View File

@ -12,6 +12,7 @@
#include "PluginInfoDatabase.h"
#include "sm_trie.h"
#include "sourcemod.h"
#include <IRootConsoleMenu.h>
using namespace SourceHook;
@ -150,7 +151,7 @@ public:
/**
* Toggles debug mode in the plugin
*/
bool ToggleDebugMode(bool debug);
bool ToggleDebugMode(bool debug, char *error, size_t maxlength);
/**
* Returns true if a plugin is usable.
@ -186,7 +187,8 @@ private:
class CPluginManager :
public IPluginManager,
public SMGlobalClass,
public IHandleTypeDispatch
public IHandleTypeDispatch,
public IRootConsoleCommand
{
friend class CPlugin;
public:
@ -227,6 +229,8 @@ public: //SMGlobalClass
void OnSourceModShutdown();
public: //IHandleTypeDispatch
void OnHandleDestroy(HandleType_t type, void *object);
public: //IRootConsoleCommand
void OnRootConsoleCommand(const char *command, unsigned int argcount);
public:
/**
* Loads all plugins not yet loaded
@ -265,9 +269,14 @@ public:
IPlugin *PluginFromHandle(Handle_t handle, HandleError *err);
/**
* Finds a plugin based on its index. (starts on index 1)
*/
* Finds a plugin based on its index. (starts on index 1)
*/
CPlugin *GetPluginByOrder(int num);
/**
* Gets status text for a status code
*/
const char *GetStatusText(PluginStatus status);
private:
bool _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t err_max);