1
0
mirror of https://github.com/alliedmodders/metamod-source.git synced 2025-02-20 13:54:14 +01:00

Added new API for correct console/rcon printing

Bumped API version number
MM:S will no longer load newer plugins

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%4077
This commit is contained in:
David Anderson 2005-06-24 22:26:19 +00:00
parent 1c1b3953a3
commit 4eb23c422b
10 changed files with 602 additions and 82 deletions

View File

@ -249,10 +249,15 @@ CPluginManager::CPlugin *CPluginManager::_Load(const char *file, PluginId source
snprintf(error, maxlen, "Failed to get API");
pl->m_Status = Pl_Error;
} else {
if (pl->m_API->GetApiVersion() < PLAPI_MIN_VERSION)
int api = pl->m_API->GetApiVersion();
if (api < PLAPI_MIN_VERSION)
{
if (error)
snprintf(error, maxlen, "Plugin API %d is out of date with required minimum (%d)", pl->m_API->GetApiVersion(), PLAPI_MIN_VERSION);
snprintf(error, maxlen, "Plugin API %d is out of date with required minimum (%d)", api, PLAPI_MIN_VERSION);
pl->m_Status = Pl_Error;
} else if (api > PLAPI_VERSION) {
if (error)
snprintf(error, maxlen, "Plugin API %d is newer than internal version (%d)", api, PLAPI_VERSION);
pl->m_Status = Pl_Error;
} else {
if (pl->m_API->Load(pl->m_Id, static_cast<ISmmAPI *>(&g_SmmAPI), &(pl->fac_list), error, maxlen))

View File

@ -40,8 +40,7 @@ public:
virtual bool DLLInit( CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory, CGlobalVars *pGlobals);
virtual bool GameInit( void )
{ return m_pOrig->GameInit(); }
virtual bool LevelInit( char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background )
{ return m_pOrig->LevelInit(pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background); }
virtual bool LevelInit( char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background );
virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax )
{ m_pOrig->ServerActivate(pEdictList, edictCount, clientMax); }
virtual void GameFrame( bool simulating )

View File

@ -21,6 +21,12 @@ using namespace SourceMM;
CSmmAPI g_SmmAPI;
CSmmAPI::CSmmAPI()
{
m_ConPrintf = NULL;
m_Cache = false;
}
ISmmPluginManager *CSmmAPI::PluginManager()
{
return static_cast<ISmmPluginManager *>(&g_PluginMngr);
@ -117,3 +123,107 @@ void CSmmAPI::UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand)
g_SMConVarAccessor.Unregister(pCommand);
}
void CSmmAPI::ConPrint(const char *fmt)
{
(m_ConPrintf)("%s", fmt);
}
void CSmmAPI::ConPrintf(const char *fmt, ...)
{
va_list ap;
static char buf[4096];
va_start(ap, fmt);
vsnprintf(buf, sizeof(buf)-1, fmt, ap);
ConPrint(buf);
va_end(ap);
}
//////////////////////////////////////////////////////////////////////////
//THERE BE HAX HERE!!!! DON'T TELL ALFRED, BUT GABE WANTED IT THAT WAY. //
// (note: you can find the windows offset by looking for the text //
// "Echo text to console", you'll find the callback cmd pushed on the //
// stack.) //
//////////////////////////////////////////////////////////////////////////
#define SIGLEN 8
#define ENGINE486_SIG "\x55\x89\xE5\x53\x83\xEC\x14\xBB"
#define ENGINE486_OFFS 40
#define ENGINE686_SIG "\x53\x83\xEC\x08\xBB\x01\x00\x00"
#define ENGINE686_OFFS 50
#define ENGINEAMD_SIG "\x53\x31\xBB\x01\x00\x00\x00\x51"
#define ENGINEAMD_OFFS 47
#define ENGINEW32_SIG "\xA1\x2A\x2A\x2A\x2A\x56\xBE\x01"
#define ENGINEW32_OFFS 38
#define IA32_CALL 0xE8
bool vcmp(void *_addr1, void *_addr2, size_t len)
{
unsigned char *addr1 = (unsigned char *)_addr1;
unsigned char *addr2 = (unsigned char *)_addr2;
for (size_t i=0; i<len; i++)
{
if (addr2[i] == '*')
continue;
if (addr1[i] != addr2[i])
return false;
}
return true;
}
//Thanks to fysh for the idea of extracting info from "echo" and for
// having the original offsets at hand!
bool CSmmAPI::CacheCmds()
{
ICvar *pCvar = g_Engine.icvar;
ConCommandBase *pBase = pCvar->GetCommands();
unsigned char *ptr = NULL;
char *addr = NULL;
FnCommandCallback callback = NULL;
int offs = 0;
while (pBase)
{
if ( strcmp(pBase->GetName(), "echo") == 0 )
{
//callback = //*((FnCommandCallback *)((char *)pBase + offsetof(ConCommand, m_fnCommandCallback)));
callback = ((ConCommand *)pBase)->GetCallback();
ptr = (unsigned char *)callback;
if (vcmp(ptr, ENGINE486_SIG, SIGLEN))
{
offs = ENGINE486_OFFS;
} else if (vcmp(ptr, ENGINE686_SIG, SIGLEN)) {
offs = ENGINE686_OFFS;
} else if (vcmp(ptr, ENGINEAMD_SIG, SIGLEN)) {
offs = ENGINEAMD_OFFS;
} else if (vcmp(ptr, ENGINEW32_SIG, SIGLEN)) {
offs = ENGINEW32_OFFS;
}
if (!offs || ptr[offs-1] != IA32_CALL)
{
m_ConPrintf = (CONPRINTF_FUNC)Msg;
return false;
}
//get the relative offset
m_ConPrintf = *((CONPRINTF_FUNC *)(ptr + offs));
//add the base offset, to the ip (which is the address+offset + 4 bytes for next instruction)
m_ConPrintf = (CONPRINTF_FUNC)((unsigned long)m_ConPrintf + (unsigned long)(ptr + offs) + 4);
m_Cache = true;
return true;
}
pBase = const_cast<ConCommandBase *>(pBase->GetNext());
}
m_ConPrintf = (CONPRINTF_FUNC)Msg;
return false;
}
bool CSmmAPI::CacheSuccessful()
{
return m_Cache;
}

View File

@ -18,10 +18,14 @@
#include "ISmmAPI.h"
typedef void (*CONPRINTF_FUNC)(const char *, ...);
namespace SourceMM
{
class CSmmAPI : public ISmmAPI
{
public:
CSmmAPI::CSmmAPI();
public:
ISmmPluginManager *PluginManager();
SourceHook::ISourceHook *SourceHook();
@ -37,11 +41,20 @@ namespace SourceMM
IConCommandBaseAccessor *GetCvarBaseAccessor();
bool RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand);
void UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand);
void ConPrint(const char *fmt);
void ConPrintf(const char *fmt, ...);
bool CacheSuccessful();
public:
bool CacheCmds();
private:
META_RES m_Res;
CONPRINTF_FUNC m_ConPrintf;
bool m_Cache;
};
};
extern SourceMM::CSmmAPI g_SmmAPI;
#define CONMSG g_SmmAPI.ConPrintf
#endif //_INCLUDE_CSMM_API_H

View File

@ -44,6 +44,11 @@ public:
virtual IConCommandBaseAccessor *GetCvarBaseAccessor() =0;
virtual bool RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) =0;
virtual void UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) =0;
public:
//Added in 1.00-RC2. attempt fix at valve not exporting rcon printing
//these do not add newlines
virtual void ConPrint(const char *fmt) =0;
virtual void ConPrintf(const char *fmt, ...) =0;
};
#endif //_INCLUDE_ISMM_API_H

View File

@ -20,7 +20,7 @@
#include <sourcehook/sourcehook.h>
#include "ISmmAPI.h"
#define PLAPI_VERSION 5
#define PLAPI_VERSION 6
#define PLAPI_NAME "ISmmPlugin"
struct factories
@ -143,6 +143,8 @@ public:
#define META_REGCVAR(var) g_SMAPI->RegisterConCmdBase(g_PLAPI, var)
#define META_UNREGCMD(name) g_SMAPI->UnregisterConCmdBase(g_PLAPI, name##_command)
#define META_UNREGCVAR(var) g_SMAPI->UnregisterConCmdBase(g_PLAPI, var)
#define META_CONPRINT g_SMAPI->ConPrint
#define META_CONPRINTF g_SMAPI->ConPrintf
//probably should use this up above someday
#define CONCMD_VARNAME(name) name##_command

View File

@ -9,6 +9,7 @@
*/
#include <ctype.h>
#include "CSmmAPI.h"
#include "concommands.h"
#include "CPlugin.h"
#include <string>
@ -95,26 +96,26 @@ CON_COMMAND(meta, "Metamod:Source Menu")
const char *command = e->Cmd_Argv(1);
if (strcmp(command, "credits") == 0)
{
Msg("Metamod:Source was developed by:\n");
Msg(" SourceHook: Pavol \"PM OnoTo\" Marko\n");
Msg(" GameDLL/Plugins: David \"BAILOPAN\" Anderson\n");
Msg(" GameDLL: Scott \"Damaged Soul\" Ehlert\n");
Msg("For more information, see the official website\n");
Msg("http://www.sourcemm.net/\n");
CONMSG("Metamod:Source was developed by:\n");
CONMSG(" SourceHook: Pavol \"PM OnoTo\" Marko\n");
CONMSG(" GameDLL/Plugins: David \"BAILOPAN\" Anderson\n");
CONMSG(" GameDLL: Scott \"Damaged Soul\" Ehlert\n");
CONMSG("For more information, see the official website\n");
CONMSG("http://www.sourcemm.net/\n");
return;
} else if (strcmp(command, "version") == 0) {
Msg("Metamod:Source version %s\n", SOURCEMM_VERSION);
Msg("Compiled on: %s\n", SOURCEMM_DATE);
Msg("Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION);
Msg("SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion());
Msg("http://www.sourcemm.net/\n");
CONMSG("Metamod:Source version %s\n", SOURCEMM_VERSION);
CONMSG("Compiled on: %s\n", SOURCEMM_DATE);
CONMSG("Plugin interface version: %d:%d\n", PLAPI_VERSION, PLAPI_MIN_VERSION);
CONMSG("SourceHook version: %d:%d\n", g_SourceHook.GetIfaceVersion(), g_SourceHook.GetImplVersion());
CONMSG("http://www.sourcemm.net/\n");
return;
} else if (strcmp(command, "game") == 0) {
Msg("GameDLL Information\n");
Msg(" Mod path: %s\n", g_ModPath.c_str());
Msg(" Dll path: %s\n", g_BinPath.c_str());
CONMSG("GameDLL Information\n");
CONMSG(" Mod path: %s\n", g_ModPath.c_str());
CONMSG(" Dll path: %s\n", g_BinPath.c_str());
return;
} else if (strcmp(command, "refresh") == 0) {
@ -135,7 +136,7 @@ CON_COMMAND(meta, "Metamod:Source Menu")
const char *name=NULL;
const char *author=NULL;
Msg("-Id- %-16.15s %-8.7s %-12.11s %-8.7s\n", "Name", "Version", "Author", "Status");
CONMSG("-Id- %-16.15s %-8.7s %-12.11s %-8.7s\n", "Name", "Version", "Author", "Status");
for (i=g_PluginMngr._begin(); i!=g_PluginMngr._end(); i++)
{
pl = (*i);
@ -173,10 +174,10 @@ CON_COMMAND(meta, "Metamod:Source Menu")
name = pl->m_File.c_str();
Msg("[%02d] %-16.15s %-8.7s %-12.11s %-8.7s\n", pl->m_Id, name, version, author, status);
CONMSG("[%02d] %-16.15s %-8.7s %-12.11s %-8.7s\n", pl->m_Id, name, version, author, status);
}
//Msg("\n");
//CONMSG("\n");
return;
} else if (strcmp(command, "cmds") == 0) {
@ -187,26 +188,26 @@ CON_COMMAND(meta, "Metamod:Source Menu")
if (!pl)
{
Msg("Plugin %d not found.\n", id);
CONMSG("Plugin %d not found.\n", id);
return;
}
if (!pl->m_API)
{
Msg("Plugin %d is not loaded.\n", id);
CONMSG("Plugin %d is not loaded.\n", id);
} else {
Msg("Console commands for %s:\n", pl->m_API->GetName());
CONMSG("Console commands for %s:\n", pl->m_API->GetName());
std::list<ConCommandBase *>::iterator ci;
size_t count = 0;
for (ci=pl->m_Cmds.begin(); ci!=pl->m_Cmds.end(); ci++)
{
count++;
Msg(" [%5d] %-s\n", count, (*ci)->GetName());
CONMSG(" [%5d] %-s\n", count, (*ci)->GetName());
}
}
} else {
Msg("Usage: meta cmds <id>\n");
CONMSG("Usage: meta cmds <id>\n");
}
return;
@ -218,26 +219,26 @@ CON_COMMAND(meta, "Metamod:Source Menu")
if (!pl)
{
Msg("Plugin %d not found.\n", id);
CONMSG("Plugin %d not found.\n", id);
return;
}
if (!pl->m_API)
{
Msg("Plugin %d is not loaded.\n", id);
CONMSG("Plugin %d is not loaded.\n", id);
} else {
Msg("Registered cvars for %s:\n", pl->m_API->GetName());
CONMSG("Registered cvars for %s:\n", pl->m_API->GetName());
std::list<ConCommandBase *>::iterator ci;
size_t count = 0;
for (ci=pl->m_Cvars.begin(); ci!=pl->m_Cvars.end(); ci++)
{
count++;
Msg(" [%5d] %-s\n", count, (*ci)->GetName());
CONMSG(" [%5d] %-s\n", count, (*ci)->GetName());
}
}
} else {
Msg("Usage: meta cvars <id>\n");
CONMSG("Usage: meta cvars <id>\n");
}
return;
@ -248,32 +249,32 @@ CON_COMMAND(meta, "Metamod:Source Menu")
SourceMM::CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id);
if (!pl)
{
Msg("Plugin %d not found.\n", id);
CONMSG("Plugin %d not found.\n", id);
return;
}
if (!pl->m_API)
{
Msg("Plugin %d is not loaded.\n", id);
CONMSG("Plugin %d is not loaded.\n", id);
} else {
if (pl->m_Status == Pl_Paused)
{
Msg("Plugin %d is paused.\n", id);
CONMSG("Plugin %d is paused.\n", id);
} else if (pl->m_Status == Pl_Running) {
Msg("Plugin %d is running.\n", id);
CONMSG("Plugin %d is running.\n", id);
}
Msg(" Name: \"%s\" by %s\n", pl->m_API->GetName(), pl->m_API->GetAuthor());
Msg(" Version: %s\n", pl->m_API->GetVersion());
Msg(" Description: %s\n", pl->m_API->GetDescription());
Msg(" License: %s\n", pl->m_API->GetLicense());
Msg(" URL: %s\n", pl->m_API->GetURL());
Msg(" Details: API %03d, Date: %s\n", pl->m_API->GetApiVersion(), pl->m_API->GetDate());
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());
}
Msg("File: %s\n\n", pl->m_File.c_str());
CONMSG("File: %s\n\n", pl->m_File.c_str());
return;
} else {
Msg("Usage: meta info <id>\n");
CONMSG("Usage: meta info <id>\n");
return;
}
@ -286,15 +287,15 @@ CON_COMMAND(meta, "Metamod:Source Menu")
if (!g_PluginMngr.Pause(id, error, sizeof(error)-1))
{
Msg("Pause failed: %s\n", error);
CONMSG("Pause failed: %s\n", error);
return;
}
Msg("Plugin %d has been paused.\n", id);
CONMSG("Plugin %d has been paused.\n", id);
return;
} else {
Msg("Usage: meta pause <id>\n");
CONMSG("Usage: meta pause <id>\n");
return;
}
@ -306,15 +307,15 @@ CON_COMMAND(meta, "Metamod:Source Menu")
if (!g_PluginMngr.Unpause(id, error, sizeof(error)-1))
{
Msg("Unpause failed: %s\n", error);
CONMSG("Unpause failed: %s\n", error);
return;
}
Msg("Plugin %d has been unpaused.\n", id);
CONMSG("Plugin %d has been unpaused.\n", id);
return;
} else {
Msg("Usage: meta unpause <id>\n");
CONMSG("Usage: meta unpause <id>\n");
return;
}
@ -346,20 +347,20 @@ CON_COMMAND(meta, "Metamod:Source Menu")
pl = g_PluginMngr.FindById(id);
if (!pl || id < Pl_MinId || (pl->m_Status < Pl_Paused))
{
Msg("Failed to load plugin %s (%s).\n", file, error);
CONMSG("Failed to load plugin %s (%s).\n", file, error);
return;
}
if (!already)
{
Msg("Plugin \"%s\" loaded with id %d.\n", pl->m_API->GetName(), pl->m_Id);
CONMSG("Plugin \"%s\" loaded with id %d.\n", pl->m_API->GetName(), pl->m_Id);
} else {
Msg("Plugin \"%s\" is already loaded as %d.\n", pl->m_API->GetName(), pl->m_Id);
CONMSG("Plugin \"%s\" is already loaded as %d.\n", pl->m_API->GetName(), pl->m_Id);
}
return;
} else {
Msg("Usage: meta load <path>\n");
CONMSG("Usage: meta load <path>\n");
return;
}
@ -371,15 +372,15 @@ CON_COMMAND(meta, "Metamod:Source Menu")
if (!g_PluginMngr.Unload(id, false, error, sizeof(error)-1))
{
Msg("Unload failed: %s\n", error);
CONMSG("Unload failed: %s\n", error);
return;
}
Msg("Plugin %d unloaded.\n", id);
CONMSG("Plugin %d unloaded.\n", id);
return;
} else {
Msg("Usage: meta unload <id>\n");
CONMSG("Usage: meta unload <id>\n");
return;
}
@ -391,26 +392,26 @@ CON_COMMAND(meta, "Metamod:Source Menu")
if (!g_PluginMngr.Unload(id, false, error, sizeof(error)-1))
{
Msg("Force unload failed: %s\n", error);
CONMSG("Force unload failed: %s\n", error);
return;
}
Msg("Plugin %d force unloaded.\n", id);
CONMSG("Plugin %d force unloaded.\n", id);
return;
} else {
Msg("Usage: meta force_unload <id>\n");
CONMSG("Usage: meta force_unload <id>\n");
return;
}
} else if (strcmp(command, "clear") == 0) {
if (!g_PluginMngr.UnloadAll())
{
Msg("One or more plugins resisted removal (cleaned anyway).\n");
CONMSG("One or more plugins resisted removal (cleaned anyway).\n");
return;
}
Msg("All plugins unloaded.\n");
CONMSG("All plugins unloaded.\n");
return;
} else if (strcmp(command, "retry") == 0) {
@ -421,38 +422,38 @@ CON_COMMAND(meta, "Metamod:Source Menu")
if (!g_PluginMngr.Retry(id, error, sizeof(error)-1))
{
Msg("Error reloading plugin: %s\n", error);
CONMSG("Error reloading plugin: %s\n", error);
return;
}
Msg("Plugin %d successfully reloaded.\n", id);
CONMSG("Plugin %d successfully reloaded.\n", id);
return;
} else {
Msg("Usage: meta retry <id>\n");
CONMSG("Usage: meta retry <id>\n");
return;
}
}
}
Msg("Metamod:Source Menu\n");
Msg("usage: meta <command> [arguments]\n");
Msg(" clear - Unload all plugins forcefully\n");
Msg(" cmds - Show plugin commands\n");
Msg(" cvars - Show plugin cvars\n");
Msg(" credits - About Metamod:Source\n");
Msg(" force_unload - Forcefully unload a plugin\n");
Msg(" game - Information about GameDLL\n");
Msg(" info - Information about a plugin\n");
Msg(" list - List plugins\n");
Msg(" load - Load a plugin\n");
Msg(" pause - Pause a running plugin\n");
Msg(" refresh - Reparse plugins file\n");
Msg(" retry - Attempt to reload a plugin\n");
Msg(" unload - Unload a loaded plugin\n");
Msg(" unpause - Unpause a paused plugin\n");
Msg(" version - Version information\n");
CONMSG("Metamod:Source Menu\n");
CONMSG("usage: meta <command> [arguments]\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 plugins file\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");
}
int UTIL_CmpNocase(const std::string &s1, const std::string &s2)

365
sourcemm/convar.h Normal file
View File

@ -0,0 +1,365 @@
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $Date$
//
//-----------------------------------------------------------------------------
// $NoKeywords: $
//=============================================================================//
#ifndef CONVAR_H
#define CONVAR_H
#if _WIN32
#pragma once
#endif
#include "tier0/dbg.h"
// The default, no flags at all
#define FCVAR_NONE 0
// Command to ConVars and ConCommands
#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc.
#define FCVAR_LAUNCHER (1<<1) // defined by launcher
#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL
#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL
#define FCVAR_MATERIAL_SYSTEM (1<<4) // Defined by the material system.
#define FCVAR_STUDIORENDER (1<<15) // Defined by the material system.
#define FCVAR_PLUGIN (1<<18) // Defined by a 3rd party plugin.
#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
// ConVar only
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc
#define FCVAR_NOTIFY (1<<8) // notifies players when changed
#define FCVAR_USERINFO (1<<9) // changes the client's info string
#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar
// It's a ConVar that's shared between the client and the server.
// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
// client, of course )
// If a change is requested it must come from the console (i.e., no remote client changes)
// If a value is changed while a server is active, it's replicated to all connected clients
#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time
#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file
#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles
#define FCVAR_NOT_CONNECTED (1<<19) // cvar cannot be changed by a client that is connected to a server
class ConVar;
class ConCommand;
class ConCommandBase;
// Any executable that wants to use ConVars need to implement one of
// these to hook up access to console variables.
class IConCommandBaseAccessor
{
public:
// Flags is a combination of FCVAR flags in cvar.h.
// hOut is filled in with a handle to the variable.
virtual bool RegisterConCommandBase( ConCommandBase *pVar )=0;
};
// You don't have to instantiate one of these, just call its
// OneTimeInit function when your executable is initializing.
class ConCommandBaseMgr
{
public:
// Call this ONCE when the executable starts up.
static void OneTimeInit( IConCommandBaseAccessor *pAccessor );
};
// Called when a ConVar changes value
typedef void ( *FnChangeCallback )( ConVar *var, char const *pOldString );
// Called when a ConCommand needs to execute
typedef void ( *FnCommandCallback )( void );
#define COMMAND_COMPLETION_MAXITEMS 64
#define COMMAND_COMPLETION_ITEM_LENGTH 64
// Returns 0 to COMMAND_COMPLETION_MAXITEMS worth of completion strings
typedef int ( *FnCommandCompletionCallback )( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
//-----------------------------------------------------------------------------
// Purpose: The base console invoked command/cvar interface
//-----------------------------------------------------------------------------
class ConCommandBase
{
friend class ConCommandBaseMgr;
friend class CCvar;
friend class ConVar;
friend class ConCommand;
public:
ConCommandBase( void );
ConCommandBase( char const *pName, char const *pHelpString = 0,
int flags = 0 );
virtual ~ConCommandBase( void );
virtual bool IsCommand( void ) const;
// Check flag
virtual bool IsBitSet( int flag ) const;
// Set flag
virtual void AddFlags( int flags );
// Return name of cvar
virtual char const *GetName( void ) const;
// Return help text for cvar
virtual char const *GetHelpText( void ) const;
// Deal with next pointer
const ConCommandBase *GetNext( void ) const;
void SetNext( ConCommandBase *next );
virtual bool IsRegistered( void ) const;
// Global methods
static ConCommandBase const *GetCommands( void );
static void AddToList( ConCommandBase *var );
static void RemoveFlaggedCommands( int flag );
static void RevertFlaggedCvars( int flag );
static ConCommandBase const *FindCommand( char const *name );
protected:
virtual void Create( char const *pName, char const *pHelpString = 0,
int flags = 0 );
// Used internally by OneTimeInit to initialize.
virtual void Init();
// Internal copy routine ( uses new operator from correct module )
char *CopyString( char const *from );
// Next ConVar in chain
ConCommandBase *m_pNext;
private:
// Has the cvar been added to the global list?
bool m_bRegistered;
// Static data
char const *m_pszName;
char const *m_pszHelpString;
// ConVar flags
int m_nFlags;
protected:
// ConVars add themselves to this list for the executable. Then ConVarMgr::Init() runs through
// all the console variables and registers them.
static ConCommandBase *s_pConCommandBases;
// ConVars in this executable use this 'global' to access values.
static IConCommandBaseAccessor *s_pAccessor;
};
//-----------------------------------------------------------------------------
// Purpose: The console invoked command
//-----------------------------------------------------------------------------
class ConCommand : public ConCommandBase
{
friend class ConCommandBaseMgr;
friend class CCvar;
public:
typedef ConCommandBase BaseClass;
ConCommand( void );
ConCommand( char const *pName, FnCommandCallback callback,
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
virtual ~ConCommand( void );
virtual bool IsCommand( void ) const;
virtual int AutoCompleteSuggest( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] );
virtual bool CanAutoComplete( void );
// Invoke the function
virtual void Dispatch( void );
private:
virtual void Create( char const *pName, FnCommandCallback callback,
char const *pHelpString = 0, int flags = 0, FnCommandCompletionCallback completionFunc = 0 );
public:
// Call this function when executing the command
FnCommandCallback m_fnCommandCallback;
FnCommandCompletionCallback m_fnCompletionCallback;
bool m_bHasCompletionCallback;
public:
//HACKHACK from BAILOPAN - we want to access this okay!
FnCommandCallback GetCallback() { return m_fnCommandCallback; }
};
//-----------------------------------------------------------------------------
// Purpose: A console variable
//-----------------------------------------------------------------------------
class ConVar : public ConCommandBase
{
friend class ConCommandBaseMgr;
friend class CCvar;
friend class CDefaultCvar;
public:
typedef ConCommandBase BaseClass;
ConVar( char const *pName, char const *pDefaultValue, int flags = 0);
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString );
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax );
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString, FnChangeCallback callback );
ConVar( char const *pName, char const *pDefaultValue, int flags,
char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax,
FnChangeCallback callback );
virtual ~ConVar( void );
virtual bool IsBitSet( int flag ) const;
virtual char const* GetHelpText( void ) const;
virtual bool IsRegistered( void ) const;
virtual char const *GetName( void ) const;
virtual void AddFlags( int flags );
virtual bool IsCommand( void ) const;
// Install a change callback (there shouldn't already be one....)
void InstallChangeCallback( FnChangeCallback callback );
// Retrieve value
FORCEINLINE float GetFloat( void ) const;
FORCEINLINE int GetInt( void ) const;
FORCEINLINE bool GetBool() const { return !!GetInt(); }
FORCEINLINE char const *GetString( void ) const;
// Any function that allocates/frees memory needs to be virtual or else you'll have crashes
// from alloc/free across dll/exe boundaries.
// These just call into the IConCommandBaseAccessor to check flags and set the var (which ends up calling InternalSetValue).
virtual void SetValue( char const *value );
virtual void SetValue( float value );
virtual void SetValue( int value );
// Reset to default value
void Revert( void );
// True if it has a min/max setting
bool GetMin( float& minVal ) const;
bool GetMax( float& maxVal ) const;
char const *GetDefault( void ) const;
static void RevertAll( void );
private:
// Called by CCvar when the value of a var is changing.
virtual void InternalSetValue(char const *value);
// For CVARs marked FCVAR_NEVER_AS_STRING
virtual void InternalSetFloatValue( float fNewValue );
virtual void InternalSetIntValue( int nValue );
virtual bool ClampValue( float& value );
virtual void ChangeStringValue( char const *tempVal );
virtual void Create( char const *pName, char const *pDefaultValue, int flags = 0,
char const *pHelpString = 0, bool bMin = false, float fMin = 0.0,
bool bMax = false, float fMax = false, FnChangeCallback callback = 0 );
// Used internally by OneTimeInit to initialize.
virtual void Init();
private:
// This either points to "this" or it points to the original declaration of a ConVar.
// This allows ConVars to exist in separate modules, and they all use the first one to be declared.
// m_pParent->m_pParent must equal m_pParent (ie: m_pParent must be the root, or original, ConVar).
ConVar *m_pParent;
// Static data
char const *m_pszDefaultValue;
// Value
// Dynamically allocated
char *m_pszString;
int m_StringLength;
// Values
float m_fValue;
int m_nValue;
// Min/Max values
bool m_bHasMin;
float m_fMinVal;
bool m_bHasMax;
float m_fMaxVal;
// Call this function when ConVar changes
FnChangeCallback m_fnChangeCallback;
};
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a float
// Output : float
//-----------------------------------------------------------------------------
FORCEINLINE float ConVar::GetFloat( void ) const
{
return m_pParent->m_fValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as an int
// Output : int
//-----------------------------------------------------------------------------
FORCEINLINE int ConVar::GetInt( void ) const
{
return m_pParent->m_nValue;
}
//-----------------------------------------------------------------------------
// Purpose: Return ConVar value as a string, return "" for bogus string pointer, etc.
// Output : char const *
//-----------------------------------------------------------------------------
FORCEINLINE char const *ConVar::GetString( void ) const
{
if ( m_nFlags & FCVAR_NEVER_AS_STRING )
{
return "FCVAR_NEVER_AS_STRING";
}
return ( m_pParent->m_pszString ) ? m_pParent->m_pszString : "";
}
//-----------------------------------------------------------------------------
// Purpose: Utility to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND( name, description ) \
static void name(); \
static ConCommand name##_command( #name, name, description ); \
static void name()
//-----------------------------------------------------------------------------
// Purpose: Utility to quicky generate a simple console command
//-----------------------------------------------------------------------------
#define CON_COMMAND_F( name, description, flags ) \
static void name(); \
static ConCommand name##_command( #name, name, description, flags ); \
static void name()
#endif // CONVAR_H

View File

@ -222,6 +222,12 @@ bool CServerGameDLL::DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn
//Initialize our console hooks
ConCommandBaseMgr::OneTimeInit(static_cast<IConCommandBaseAccessor *>(&g_SMConVarAccessor));
if (!g_SmmAPI.CacheCmds())
{
LogMessage("[META] Warning: Failed to initialize Con_Printf. Defaulting to Msg().");
LogMessage("[META] Warning: Console messages will not be redirected to rcon console.");
}
//Now it's safe to load plugins.
#if defined WIN32 || defined _WIN32
@ -434,3 +440,14 @@ void LevelShutdown_handler(void)
bInFirstLevel = false;
}
}
bool CServerGameDLL::LevelInit( char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background )
{
if (!g_SmmAPI.CacheSuccessful())
{
LogMessage("[META] Warning: Failed to initialize Con_Printf. Defaulting to Msg().");
LogMessage("[META] Warning: Console messages will not be redirected to rcon console.");
}
return m_pOrig->LevelInit(pMapName, pMapEntities, pOldLevel, pLandmarkName, loadGame, background);
}

View File

@ -239,6 +239,9 @@
<File
RelativePath=".\convar.cpp">
</File>
<File
RelativePath=".\convar.h">
</File>
</Filter>
</Files>
<Globals>