mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2024-12-01 13:24:25 +01:00
1f1d6e57f9
Games where the above function can crash are handled by detouring tier0's Error() function and jumping back to our own code. So in theory this should work on all games now.
771 lines
18 KiB
C++
771 lines
18 KiB
C++
/**
|
|
* vim: set ts=4 sw=4 tw=99 noet :
|
|
* ======================================================
|
|
* Metamod:Source
|
|
* Copyright (C) 2004-2009 AlliedModders LLC and authors.
|
|
* All rights reserved.
|
|
* ======================================================
|
|
*
|
|
* This software is provided 'as-is', without any express or implied warranty.
|
|
* In no event will the authors be held liable for any damages arising from
|
|
* the use of this software.
|
|
*
|
|
* Permission is granted to anyone to use this software for any purpose,
|
|
* including commercial applications, and to alter it and redistribute it
|
|
* freely, subject to the following restrictions:
|
|
*
|
|
* 1. The origin of this software must not be misrepresented; you must not
|
|
* claim that you wrote the original software. If you use this software in a
|
|
* product, an acknowledgment in the product documentation would be
|
|
* appreciated but is not required.
|
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
|
* misrepresented as being the original software.
|
|
* 3. This notice may not be removed or altered from any source distribution.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include "metamod_oslink.h"
|
|
#include <ctype.h>
|
|
#include "metamod.h"
|
|
#include "metamod_util.h"
|
|
#include "metamod_console.h"
|
|
#include "metamod_plugins.h"
|
|
|
|
using namespace SourceMM;
|
|
using namespace SourceHook;
|
|
|
|
/**
|
|
* @brief Console Command Implementations
|
|
* @file concommands.cpp
|
|
*/
|
|
|
|
#define CONMSG g_Metamod.ConPrintf
|
|
#define CLIENT_CONMSG g_Metamod.ClientConPrintf
|
|
|
|
bool Command_Meta(IMetamodSourceCommandInfo *info)
|
|
{
|
|
unsigned int args = info->GetArgCount();
|
|
|
|
if (mm_IsVspBridged() && !mm_IsVspLoadComplete())
|
|
{
|
|
CONMSG("You must change the map to activate Metamod:Source.\n");
|
|
return true;
|
|
}
|
|
|
|
if (args >= 1)
|
|
{
|
|
const char *command = info->GetArg(1);
|
|
if (strcmp(command, "credits") == 0)
|
|
{
|
|
CONMSG("Metamod:Source was developed by:\n");
|
|
CONMSG(" SourceHook: Pavol \"PM OnoTo\" Marko\n");
|
|
CONMSG(" GameDLL/Plugins: David \"BAILOPAN\" Anderson\n");
|
|
CONMSG(" GameDLL: Scott \"DS\" Ehlert\n");
|
|
CONMSG("For more information, see the official website\n");
|
|
CONMSG("http://www.metamodsource.net/\n");
|
|
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "version") == 0)
|
|
{
|
|
CONMSG("Metamod:Source version %s\n", MMS_FULL_VERSION);
|
|
CONMSG("Build ID: %s\n", MMS_BUILD_UNIQUEID);
|
|
|
|
if (g_Metamod.IsLoadedAsGameDLL())
|
|
{
|
|
CONMSG("Loaded As: GameDLL (gameinfo.txt)\n");
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Loaded As: Valve Server Plugin\n");
|
|
}
|
|
|
|
CONMSG("Compiled on: %s\n", SOURCEMM_DATE);
|
|
CONMSG("Plugin interface version: %d:%d\n", METAMOD_PLAPI_VERSION, PLAPI_MIN_VERSION);
|
|
CONMSG("SourceHook version: %d:%d\n", g_SHPtr->GetIfaceVersion(), g_SHPtr->GetImplVersion());
|
|
CONMSG("http://www.metamodsource.net/\n");
|
|
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "game") == 0)
|
|
{
|
|
CONMSG("GameDLL Information\n");
|
|
CONMSG(" Description: %s\n", provider->GetGameDescription());
|
|
CONMSG(" Mod Path: %s\n", g_Metamod.GetBaseDir());
|
|
CONMSG(" DLL Path: %s\n", g_Metamod.GetGameBinaryPath());
|
|
CONMSG(" Interface: ServerGameDLL%03d\n", g_Metamod.GetGameDLLVersion());
|
|
|
|
#if 0
|
|
int engine = g_Metamod.GetSourceEngineBuild();
|
|
if (engine == SOURCE_ENGINE_ORIGINAL)
|
|
{
|
|
CONMSG(" Engine: Original (pre-Episode 1)\n");
|
|
}
|
|
else if (engine == SOURCE_ENGINE_EPISODEONE)
|
|
{
|
|
CONMSG(" Engine: Episode 1 (2004)\n");
|
|
}
|
|
else if (engine == SOURCE_ENGINE_ORANGEBOX)
|
|
{
|
|
CONMSG(" Engine: Episode 2 (Orange Box, 2007)\n");
|
|
}
|
|
#endif
|
|
|
|
#if SOURCE_ENGINE == SE_LEFT4DEAD2
|
|
CONMSG(" Engine: Left 4 Dead 2 (2009)\n");
|
|
#elif SOURCE_ENGINE == SE_LEFT4DEAD
|
|
CONMSG(" Engine: Left 4 Dead (2008)\n");
|
|
#elif SOURCE_ENGINE == SE_ORANGEBOX
|
|
CONMSG(" Engine: Episode 2 (Orange Box, 2007)\n");
|
|
#elif SOURCE_ENGINE == SE_ORANGEBOXVALVE
|
|
CONMSG(" Engine: Episode 2 (Valve Orange Box, 2009)\n");
|
|
#elif SOURCE_ENGINE == SE_DARKMESSIAH
|
|
CONMSG(" Engine: Dark Messiah (2006)\n");
|
|
#else
|
|
#error "SOURCE_ENGINE not defined to a known value"
|
|
#endif
|
|
|
|
// Display user messages
|
|
const char *msgname;
|
|
int msgsize;
|
|
int messages = g_Metamod.GetUserMessageCount();
|
|
|
|
if (messages > 0)
|
|
{
|
|
CONMSG(" User Messages: %-32.31s %-5s %-5s\n", "Name", "Index", "Size");
|
|
|
|
for (int i = 0; i < messages; i++)
|
|
{
|
|
msgname = g_Metamod.GetUserMessage(i, &msgsize);
|
|
|
|
CONMSG(" %-32.31s %-5d %-5d\n", msgname, i, msgsize);
|
|
}
|
|
|
|
CONMSG(" %d user message%s in total\n", messages, (messages > 1) ? "s" : "");
|
|
}
|
|
else
|
|
{
|
|
CONMSG(" User Messages: None\n");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "refresh") == 0)
|
|
{
|
|
char filepath[PATH_SIZE], vdfpath[PATH_SIZE];
|
|
g_Metamod.PathFormat(filepath,
|
|
sizeof(filepath),
|
|
"%s/%s",
|
|
g_Metamod.GetBaseDir(),
|
|
g_Metamod.GetPluginsFile());
|
|
g_Metamod.PathFormat(vdfpath,
|
|
sizeof(vdfpath),
|
|
"%s/%s",
|
|
g_Metamod.GetBaseDir(),
|
|
g_Metamod.GetVDFDir());
|
|
|
|
mm_LoadPlugins(filepath, vdfpath);
|
|
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "list") == 0)
|
|
{
|
|
CPluginManager::CPlugin *pl;
|
|
ISmmPlugin *plapi;
|
|
const char *plname;
|
|
PluginIter i;
|
|
char buffer[256];
|
|
int len;
|
|
int plnum = g_PluginMngr.GetPluginCount();
|
|
|
|
if (!plnum)
|
|
{
|
|
CONMSG("No plugins loaded.\n");
|
|
return true;
|
|
} else {
|
|
CONMSG("Listing %d plugin%s:\n", plnum, (plnum > 1) ? "s" : "");
|
|
}
|
|
|
|
for (i = g_PluginMngr._begin(); i != g_PluginMngr._end(); i++)
|
|
{
|
|
pl = (*i);
|
|
if (!pl)
|
|
{
|
|
break;
|
|
}
|
|
|
|
len = 0;
|
|
|
|
if (pl->m_Status != Pl_Running)
|
|
{
|
|
len += UTIL_Format(buffer, sizeof(buffer), " [%02d] <%s>", pl->m_Id, g_PluginMngr.GetStatusText(pl));
|
|
} else {
|
|
len += UTIL_Format(buffer, sizeof(buffer), " [%02d]", pl->m_Id);
|
|
}
|
|
|
|
if ((plapi = pl->m_API))
|
|
{
|
|
plname = IS_STR_FILLED(plapi->GetName()) ? plapi->GetName() : pl->m_File.c_str();
|
|
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " %s", plname);
|
|
|
|
if (IS_STR_FILLED(plapi->GetVersion()))
|
|
{
|
|
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", plapi->GetVersion());
|
|
}
|
|
if (IS_STR_FILLED(plapi->GetAuthor()))
|
|
{
|
|
UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", plapi->GetAuthor());
|
|
}
|
|
}
|
|
|
|
CONMSG("%s\n", buffer);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "cmds") == 0)
|
|
{
|
|
if (args >= 2)
|
|
{
|
|
int id = atoi(info->GetArg(2));
|
|
CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id);
|
|
|
|
if (!pl)
|
|
{
|
|
CONMSG("Plugin %d not found.\n", id);
|
|
return true;
|
|
}
|
|
|
|
if (!pl->m_API)
|
|
{
|
|
CONMSG("Plugin %d is not loaded.\n", id);
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Console commands for %s:\n", pl->m_API->GetName());
|
|
List<ConCommandBase *>::iterator ci;
|
|
size_t count = 0;
|
|
|
|
for (ci=pl->m_Cmds.begin(); ci!=pl->m_Cmds.end(); ci++)
|
|
{
|
|
count++;
|
|
CONMSG(" [%5d] %-s\n", count, (*ci)->GetName());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Usage: meta cmds <id>\n");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "cvars") == 0)
|
|
{
|
|
if (args >= 2)
|
|
{
|
|
int id = atoi(info->GetArg(2));
|
|
CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id);
|
|
|
|
if (!pl)
|
|
{
|
|
CONMSG("Plugin %d not found.\n", id);
|
|
return true;
|
|
}
|
|
|
|
if (!pl->m_API)
|
|
{
|
|
CONMSG("Plugin %d is not loaded.\n", id);
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Registered cvars for %s:\n", pl->m_API->GetName());
|
|
List<ConCommandBase *>::iterator ci;
|
|
size_t count = 0;
|
|
|
|
for (ci=pl->m_Cvars.begin(); ci!=pl->m_Cvars.end(); ci++)
|
|
{
|
|
count++;
|
|
CONMSG(" [%5d] %-s\n", count, (*ci)->GetName());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Usage: meta cvars <id>\n");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "info") == 0)
|
|
{
|
|
if (args >= 2)
|
|
{
|
|
int id = atoi(info->GetArg(2));
|
|
CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id);
|
|
if (!pl)
|
|
{
|
|
CONMSG("Plugin %d not found.\n", id);
|
|
return true;
|
|
}
|
|
|
|
if (!pl->m_API)
|
|
{
|
|
CONMSG("Plugin %d is not loaded.\n", id);
|
|
}
|
|
else
|
|
{
|
|
if (pl->m_Status == Pl_Paused)
|
|
{
|
|
CONMSG("Plugin %d is paused.\n", id);
|
|
}
|
|
else if (pl->m_Status == Pl_Running)
|
|
{
|
|
char run_msg[255];
|
|
bool run = false;
|
|
if (pl->m_API && pl->m_API->QueryRunning(run_msg, sizeof(run_msg)-1))
|
|
{
|
|
run = true;
|
|
}
|
|
if (run)
|
|
{
|
|
CONMSG("Plugin %d is running.\n", id);
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Plugin %d is stopped: %s\n", id, run_msg);
|
|
}
|
|
}
|
|
CONMSG(" Name: \"%s\" by %s\n", pl->m_API->GetName(), pl->m_API->GetAuthor());
|
|
CONMSG(" Version: %s\n", pl->m_API->GetVersion());
|
|
CONMSG(" Description: %s\n", pl->m_API->GetDescription());
|
|
CONMSG(" License: %s\n", pl->m_API->GetLicense());
|
|
CONMSG(" URL: %s\n", pl->m_API->GetURL());
|
|
CONMSG(" Details: API %03d, Date: %s\n", pl->m_API->GetApiVersion(), pl->m_API->GetDate());
|
|
}
|
|
CONMSG("File: %s\n\n", pl->m_File.c_str());
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Usage: meta info <id>\n");
|
|
|
|
return true;
|
|
}
|
|
}
|
|
else if (strcmp(command, "pause") == 0)
|
|
{
|
|
if (args >= 2)
|
|
{
|
|
int id = atoi(info->GetArg(2));
|
|
|
|
char error[255];
|
|
|
|
if (!g_PluginMngr.Pause(id, error, sizeof(error)))
|
|
{
|
|
CONMSG("Pause failed: %s\n", error);
|
|
return true;
|
|
}
|
|
|
|
CONMSG("Plugin %d has been paused.\n", id);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Usage: meta pause <id>\n");
|
|
|
|
return true;
|
|
}
|
|
}
|
|
else if (strcmp(command, "unpause") == 0)
|
|
{
|
|
if (args >= 2)
|
|
{
|
|
int id = atoi(info->GetArg(2));
|
|
char error[255];
|
|
|
|
if (!g_PluginMngr.Unpause(id, error, sizeof(error)))
|
|
{
|
|
CONMSG("Unpause failed: %s\n", error);
|
|
return true;
|
|
}
|
|
|
|
CONMSG("Plugin %d has been unpaused.\n", id);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Usage: meta unpause <id>\n");
|
|
|
|
return true;
|
|
}
|
|
}
|
|
else if (strcmp(command, "load") == 0)
|
|
{
|
|
if (args >= 2)
|
|
{
|
|
const char *file = info->GetArg(2);
|
|
char full_path[255];
|
|
|
|
const char *alias = g_PluginMngr.LookupAlias(file);
|
|
if (alias)
|
|
{
|
|
file = alias;
|
|
}
|
|
|
|
if (file[0] == '/' || strcmp(&(file[1]), ":\\") == 0)
|
|
{
|
|
g_Metamod.PathFormat(full_path, sizeof(full_path), "%s", file);
|
|
}
|
|
else
|
|
{
|
|
const char *ext = UTIL_GetExtension(file);
|
|
#if defined WIN32 || defined _WIN32
|
|
ext = ext ? "" : ".dll";
|
|
#else
|
|
ext = ext ? "" : "_i486.so";
|
|
#endif
|
|
g_Metamod.PathFormat(full_path,
|
|
sizeof(full_path),
|
|
"%s/%s%s",
|
|
g_Metamod.GetBaseDir(),
|
|
file,
|
|
ext);
|
|
}
|
|
|
|
char error[255]={0};
|
|
bool already;
|
|
CPluginManager::CPlugin *pl;
|
|
|
|
PluginId id = g_PluginMngr.Load(full_path, Pl_Console, already, error, sizeof(error));
|
|
pl = g_PluginMngr.FindById(id);
|
|
if (!pl || id < Pl_MinId || (pl->m_Status < Pl_Paused))
|
|
{
|
|
CONMSG("Failed to load plugin %s (%s).\n", file, error);
|
|
return true;
|
|
}
|
|
|
|
if (!already)
|
|
{
|
|
CONMSG("Plugin \"%s\" loaded with id %d.\n", pl->m_API->GetName(), pl->m_Id);
|
|
} else {
|
|
CONMSG("Plugin \"%s\" is already loaded as %d.\n", pl->m_API->GetName(), pl->m_Id);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Usage: meta load <path>\n");
|
|
|
|
return true;
|
|
}
|
|
}
|
|
else if ( (strcmp(command, "alias") == 0) ||
|
|
(strcmp(command, "aliases") == 0) )
|
|
{
|
|
if (args >= 3)
|
|
{
|
|
const char *alias = info->GetArg(2);
|
|
const char *value = info->GetArg(3);
|
|
|
|
g_PluginMngr.SetAlias(alias, value);
|
|
if (value == NULL || value[0] == '\0')
|
|
{
|
|
CONMSG("Deleted alias: %s.\n", alias);
|
|
} else {
|
|
CONMSG("Set alias \"%s\" to: %s\n", alias, value);
|
|
}
|
|
}
|
|
else if (args >= 2)
|
|
{
|
|
const char *alias = info->GetArg(2);
|
|
const char *value = g_PluginMngr.LookupAlias(alias);
|
|
if (value)
|
|
{
|
|
CONMSG("Alias \"%s\" is set to: %s\n", alias, value);
|
|
} else {
|
|
CONMSG("Alias \"%s\" was not found.\n", alias);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
List<CNameAlias *>::iterator iter, end;
|
|
CNameAlias *p;
|
|
|
|
iter = g_PluginMngr._alias_begin();
|
|
end = g_PluginMngr._alias_end();
|
|
size_t total = 0;
|
|
if (iter != end)
|
|
{
|
|
CONMSG("%-10.9s %s\n", "Alias", "File");
|
|
CONMSG(" --- \n");
|
|
for (; iter!=end; iter++)
|
|
{
|
|
p = (*iter);
|
|
CONMSG("%-10.9s %s\n", p->alias.c_str(), p->value.c_str());
|
|
total++;
|
|
}
|
|
CONMSG(" --- \n");
|
|
CONMSG("%d aliases total.\n", total);
|
|
}
|
|
else
|
|
{
|
|
CONMSG("No aliases found.\n");
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "unload") == 0)
|
|
{
|
|
if (args >= 2)
|
|
{
|
|
const char *file = info->GetArg(2);
|
|
int id = atoi(file);
|
|
char error[255]={0};
|
|
|
|
if (id == 0 && isalpha(file[0]))
|
|
{
|
|
char full_path[255];
|
|
const char *alias = g_PluginMngr.LookupAlias(file);
|
|
|
|
if (alias)
|
|
{
|
|
file = alias;
|
|
}
|
|
|
|
/* first check if it's a known filename */
|
|
if (file[0] == '/' || strcmp(&(file[1]), ":\\") == 0)
|
|
{
|
|
g_Metamod.PathFormat(full_path, sizeof(full_path), "%s", file);
|
|
}
|
|
else
|
|
{
|
|
const char *ext = UTIL_GetExtension(file);
|
|
#if defined WIN32 || defined _WIN32
|
|
ext = ext ? "" : ".dll";
|
|
#else
|
|
ext = ext ? "" : "_i486.so";
|
|
#endif
|
|
g_Metamod.PathFormat(full_path,
|
|
sizeof(full_path),
|
|
"%s/%s%s",
|
|
g_Metamod.GetBaseDir(),
|
|
file,
|
|
ext);
|
|
}
|
|
|
|
List<CPluginManager::CPlugin *>::iterator iter, end;
|
|
CPluginManager::CPlugin *pl;
|
|
iter = g_PluginMngr._begin();
|
|
end = g_PluginMngr._end();
|
|
for (; iter!=end; iter++)
|
|
{
|
|
pl = (*iter);
|
|
if (strcmp(pl->m_File.c_str(), full_path) == 0)
|
|
{
|
|
id = pl->m_Id;
|
|
break;
|
|
}
|
|
}
|
|
if (id == 0)
|
|
{
|
|
CONMSG("Plugin \"%s\" not found.\n", full_path);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (!g_PluginMngr.Unload(id, false, error, sizeof(error)))
|
|
{
|
|
CONMSG("Unload failed: %s\n", error);
|
|
return true;
|
|
}
|
|
|
|
CONMSG("Plugin %d unloaded.\n", id);
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Usage: meta unload <id>\n");
|
|
}
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "force_unload") == 0)
|
|
{
|
|
if (args >= 2)
|
|
{
|
|
int id = atoi(info->GetArg(2));
|
|
char error[255]={0};
|
|
|
|
if (!g_PluginMngr.Unload(id, false, error, sizeof(error)))
|
|
{
|
|
CONMSG("Force unload failed: %s\n", error);
|
|
return true;
|
|
}
|
|
|
|
CONMSG("Plugin %d force unloaded.\n", id);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Usage: meta force_unload <id>\n");
|
|
|
|
return true;
|
|
}
|
|
}
|
|
else if (strcmp(command, "clear") == 0)
|
|
{
|
|
if (!g_PluginMngr.UnloadAll())
|
|
{
|
|
CONMSG("One or more plugins resisted removal (cleaned anyway).\n");
|
|
return true;
|
|
}
|
|
|
|
CONMSG("All plugins unloaded.\n");
|
|
|
|
return true;
|
|
}
|
|
else if (strcmp(command, "retry") == 0)
|
|
{
|
|
if (args >= 2)
|
|
{
|
|
int id = atoi(info->GetArg(2));
|
|
char error[255];
|
|
|
|
if (!g_PluginMngr.Retry(id, error, sizeof(error)))
|
|
{
|
|
CONMSG("Error reloading plugin: %s\n", error);
|
|
return true;
|
|
}
|
|
|
|
CONMSG("Plugin %d successfully reloaded.\n", id);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
CONMSG("Usage: meta retry <id>\n");
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
CONMSG("Metamod:Source Menu\n");
|
|
CONMSG("usage: meta <command> [arguments]\n");
|
|
CONMSG(" alias - List or set an alias\n");
|
|
CONMSG(" clear - Unload all plugins forcefully\n");
|
|
CONMSG(" cmds - Show plugin commands\n");
|
|
CONMSG(" cvars - Show plugin cvars\n");
|
|
CONMSG(" credits - About Metamod:Source\n");
|
|
CONMSG(" force_unload - Forcefully unload a plugin\n");
|
|
CONMSG(" game - Information about GameDLL\n");
|
|
CONMSG(" info - Information about a plugin\n");
|
|
CONMSG(" list - List plugins\n");
|
|
CONMSG(" load - Load a plugin\n");
|
|
CONMSG(" pause - Pause a running plugin\n");
|
|
CONMSG(" refresh - Reparse plugin files\n");
|
|
CONMSG(" retry - Attempt to reload a plugin\n");
|
|
CONMSG(" unload - Unload a loaded plugin\n");
|
|
CONMSG(" unpause - Unpause a paused plugin\n");
|
|
CONMSG(" version - Version information\n");
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Command_ClientMeta(edict_t *client, IMetamodSourceCommandInfo *info)
|
|
{
|
|
const char *cmd = info->GetArg(0);
|
|
|
|
if (strcmp(cmd, "meta") == 0)
|
|
{
|
|
unsigned int args = info->GetArgCount();
|
|
if (args == 1)
|
|
{
|
|
const char *subcmd = info->GetArg(1);
|
|
|
|
if (strcmp(subcmd, "credits") == 0)
|
|
{
|
|
CLIENT_CONMSG(client, "Metamod:Source was developed by:\n");
|
|
CLIENT_CONMSG(client, " SourceHook: Pavol \"PM OnoTo\" Marko\n");
|
|
CLIENT_CONMSG(client, " GameDLL/Plugins: David \"BAILOPAN\" Anderson\n");
|
|
CLIENT_CONMSG(client, " GameDLL: Scott \"DS\" Ehlert\n");
|
|
CLIENT_CONMSG(client, "For more information, see the official website\n");
|
|
CLIENT_CONMSG(client, "http://www.metamodsource.net/\n");
|
|
|
|
return true;
|
|
}
|
|
else if(strcmp(subcmd, "version") == 0)
|
|
{
|
|
CLIENT_CONMSG(client, "Metamod:Source version %s\n", MMS_FULL_VERSION);
|
|
CLIENT_CONMSG(client, "Compiled on: %s\n", SOURCEMM_DATE);
|
|
CLIENT_CONMSG(client, "Plugin interface version: %d:%d\n", METAMOD_PLAPI_VERSION, PLAPI_MIN_VERSION);
|
|
CLIENT_CONMSG(client, "SourceHook version: %d:%d\n", g_SHPtr->GetIfaceVersion(), g_SHPtr->GetImplVersion());
|
|
CLIENT_CONMSG(client, "http://www.metamodsource.net/\n");
|
|
|
|
return true;
|
|
}
|
|
else if(strcmp(subcmd, "list") == 0)
|
|
{
|
|
CPluginManager::CPlugin *pl;
|
|
ISmmPlugin *plapi;
|
|
const char *plname;
|
|
PluginIter i;
|
|
char buffer[256];
|
|
int len = 0;
|
|
int plnum = 0;
|
|
|
|
for (i = g_PluginMngr._begin(); i != g_PluginMngr._end(); i++, len=0)
|
|
{
|
|
pl = (*i);
|
|
if (pl && pl->m_Status == Pl_Running)
|
|
{
|
|
plapi = pl->m_API;
|
|
if (!plapi || !plapi->QueryRunning(NULL, 0))
|
|
{
|
|
continue;
|
|
}
|
|
plnum++;
|
|
|
|
len += UTIL_Format(buffer, sizeof(buffer), " [%02d]", plnum);
|
|
|
|
plname = IS_STR_FILLED(plapi->GetName()) ? plapi->GetName() : pl->m_File.c_str();
|
|
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " %s", plname);
|
|
|
|
if (IS_STR_FILLED(plapi->GetVersion()))
|
|
{
|
|
len += UTIL_Format(&buffer[len], sizeof(buffer)-len, " (%s)", plapi->GetVersion());
|
|
}
|
|
if (IS_STR_FILLED(plapi->GetAuthor()))
|
|
{
|
|
UTIL_Format(&buffer[len], sizeof(buffer)-len, " by %s", plapi->GetAuthor());
|
|
}
|
|
|
|
CLIENT_CONMSG(client, "%s\n", buffer);
|
|
}
|
|
}
|
|
|
|
if (!plnum)
|
|
{
|
|
CLIENT_CONMSG(client, "No active plugins loaded.\n");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
CLIENT_CONMSG(client, "Metamod:Source Menu\n");
|
|
CLIENT_CONMSG(client, "usage: meta <command>\n");
|
|
CLIENT_CONMSG(client, " credits - About Metamod:Source\n");
|
|
CLIENT_CONMSG(client, " list - List plugins\n");
|
|
CLIENT_CONMSG(client, " version - Version information\n");
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|