Working ConCommandBase replacement code

--HG--
extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%4068
This commit is contained in:
David Anderson 2005-05-26 08:06:23 +00:00
parent a7da6651b9
commit 5155055435
10 changed files with 298 additions and 38 deletions

View File

@ -11,6 +11,7 @@
#include "CPlugin.h"
#include "CSmmAPI.h"
#include "sourcemm.h"
#include "concommands.h"
/**
* @brief Implements functions from CPlugin.h
@ -184,6 +185,23 @@ bool CPluginManager::Retry(PluginId id, char *error, size_t len)
return false;
}
CPluginManager::CPlugin *CPluginManager::FindByAPI(ISmmPlugin *api)
{
PluginIter i;
//don't find bad plugins!
if (!api)
return NULL;
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
{
if ( (*i)->m_API == api )
return (*i);
}
return NULL;
}
CPluginManager::CPlugin *CPluginManager::_Load(const char *file, PluginId source, char *error, size_t maxlen)
{
FILE *fp;
@ -278,6 +296,8 @@ bool CPluginManager::_Unload(CPluginManager::CPlugin *pl, bool force, char *erro
//Make sure to detach it from sourcehook!
g_SourceHook.UnloadPlugin(pl->m_Id);
UnregAllConCmds(pl);
//Clean up the DLL
dlclose(pl->m_Lib);
pl->m_Lib = NULL;
@ -374,6 +394,8 @@ bool CPluginManager::UnloadAll()
if ( (*i)->m_API->Unload(NULL, 0) )
status = false;
UnregAllConCmds( (*i) );
//Unlink from SourceHook
g_SourceHook.UnloadPlugin( (*i)->m_Id );
@ -382,10 +404,10 @@ bool CPluginManager::UnloadAll()
}
delete (*i);
}
i = m_Plugins.erase(i);
}
m_Plugins.clear();
return status;
}
@ -413,3 +435,58 @@ PluginIter CPluginManager::_end()
{
return m_Plugins.end();
}
void CPluginManager::AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar)
{
CPlugin *pl = FindByAPI(api);
if (!pl)
return;
pl->m_Cvars.push_back(pCvar);
}
void CPluginManager::AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd)
{
CPlugin *pl = FindByAPI(api);
if (!pl)
return;
pl->m_Cmds.push_back(pCmd);
}
void CPluginManager::RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar)
{
CPlugin *pl = FindByAPI(api);
if (!pl)
return;
pl->m_Cvars.remove(pCvar);
}
void CPluginManager::RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd)
{
CPlugin *pl = FindByAPI(api);
if (!pl)
return;
pl->m_Cmds.remove(pCmd);
}
void CPluginManager::UnregAllConCmds(CPlugin *pl)
{
std::list<ConCommandBase *>::iterator i;
for (i=pl->m_Cvars.begin(); i!=pl->m_Cvars.end(); i++)
g_SMConVarAccessor.Unregister( (*i) );
pl->m_Cvars.clear();
for (i=pl->m_Cmds.begin(); i!=pl->m_Cmds.end(); i++)
g_SMConVarAccessor.Unregister( (*i) );
pl->m_Cmds.clear();
}

View File

@ -18,6 +18,9 @@
#include <list>
#include <string>
#include <interface.h>
#include <eiface.h>
#include <convar.h>
#include "IPluginManager.h"
#include "oslink.h"
@ -55,6 +58,8 @@ namespace SourceMM
ISmmPlugin *m_API;
HINSTANCE m_Lib;
factories fac_list;
std::list<ConCommandBase *> m_Cvars;
std::list<ConCommandBase *> m_Cmds;
};
public:
CPluginManager();
@ -69,6 +74,11 @@ namespace SourceMM
public:
bool Query(PluginId id, const char *&file, factories *&list, Pl_Status &status, PluginId &source);
void AddPluginCvar(ISmmPlugin *api, ConCommandBase *pCvar);
void AddPluginCmd(ISmmPlugin *api, ConCommandBase *pCmd);
void RemovePluginCvar(ISmmPlugin *api, ConCommandBase *pCvar);
void RemovePluginCmd(ISmmPlugin *api, ConCommandBase *pCmd);
/**
* @brief Finds a plugin by Id
*
@ -77,6 +87,8 @@ namespace SourceMM
*/
CPlugin *FindById(PluginId id);
CPlugin *FindByAPI(ISmmPlugin *api);
/**
* @brief Attempts to reload a failed plugin
*
@ -96,6 +108,7 @@ namespace SourceMM
bool _Unload(CPlugin *pl, bool force, char *error, size_t maxlen);
bool _Pause(CPlugin *pl, char *error, size_t maxlen);
bool _Unpause(CPlugin *pl, char *error, size_t maxlen);
void UnregAllConCmds(CPlugin *pl);
private:
PluginId m_LastId;
std::list<CPlugin *> m_Plugins;

View File

@ -93,13 +93,27 @@ IConCommandBaseAccessor *CSmmAPI::GetCvarBaseAccessor()
return static_cast<IConCommandBaseAccessor *>(&g_SMConVarAccessor);
}
bool CSmmAPI::RegisterConCmdBase(ConCommandBase *pCommand)
bool CSmmAPI::RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand)
{
return g_SMConVarAccessor.RegisterConCommandBase(pCommand);
if (pCommand->IsCommand())
{
g_PluginMngr.AddPluginCmd(plugin, pCommand);
} else {
g_PluginMngr.AddPluginCvar(plugin, pCommand);
}
return g_SMConVarAccessor.Register(pCommand);
}
void CSmmAPI::UnregisterConCmdBase(ConCommandBase *pCommand)
void CSmmAPI::UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand)
{
if (pCommand->IsCommand())
{
g_PluginMngr.RemovePluginCmd(plugin, pCommand);
} else {
g_PluginMngr.RemovePluginCvar(plugin, pCommand);
}
g_SMConVarAccessor.Unregister(pCommand);
}

View File

@ -35,8 +35,8 @@ namespace SourceMM
void SetLastMetaReturn(META_RES res);
META_RES GetLastMetaReturn();
IConCommandBaseAccessor *GetCvarBaseAccessor();
bool RegisterConCmdBase(ConCommandBase *pCommand);
void UnregisterConCmdBase(ConCommandBase *pCommand);
bool RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand);
void UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand);
private:
META_RES m_Res;
};

View File

@ -42,8 +42,8 @@ public:
public:
//Added in 1.00-RC2 to solve concommand problems
virtual IConCommandBaseAccessor *GetCvarBaseAccessor() =0;
virtual bool RegisterConCmdBase(ConCommandBase *pCommand) =0;
virtual void UnregisterConCmdBase(ConCommandBase *pCommand) =0;
virtual bool RegisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) =0;
virtual void UnregisterConCmdBase(ISmmPlugin *plugin, ConCommandBase *pCommand) =0;
};
#endif //_INCLUDE_ISMM_API_H

View File

@ -138,8 +138,13 @@ public:
g_SMAPI->SetLastMetaReturn(mres); \
return value;
#define META_LOG g_SMAPI->LogMsg
#define META_LOG g_SMAPI->LogMsg
#define META_REGCMD(name) g_SMAPI->RegisterConCmdBase(g_PLAPI, name##_command)
#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)
//probably should use this up above someday
#define CONCMD_VARNAME(name) name##_command
#if !defined SMM_API

View File

@ -8,6 +8,8 @@
* ============================
*/
#include <string>
#include <ctype.h>
#include "concommands.h"
#include "CPlugin.h"
@ -16,6 +18,7 @@
* @file concommands.cpp
*/
CAlwaysRegisterableCommand g_EternalCommand;
SMConVarAccessor g_SMConVarAccessor;
bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand)
@ -34,6 +37,15 @@ bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand)
return true;
}
bool SMConVarAccessor::Register(ConCommandBase *pCommand)
{
//simple, don't mark as part of sourcemm!
pCommand->SetNext( NULL );
g_Engine.icvar->RegisterConCommandBase(pCommand);
return true;
}
void SMConVarAccessor::MarkCommandsAsGameDLL()
{
for (std::list<ConCommandBase*>::iterator iter = m_RegisteredCommands.begin();
@ -43,37 +55,34 @@ void SMConVarAccessor::MarkCommandsAsGameDLL()
}
}
void SMConVarAccessor::Unregister(ConCommandBase *pCvar)
void SMConVarAccessor::Unregister(ConCommandBase *pCommand)
{
ICvar *cv = g_Engine.icvar;
ConCommandBase *ptr = cv->GetCommands();
if (ptr == pCvar && ptr->GetNext())
if (ptr == pCommand)
{
//we're at the beginning of the list
*ptr = *(ptr->GetNext());
return;
//first in list
g_EternalCommand.BringToFront();
g_EternalCommand.SetNext(const_cast<ConCommandBase *>(pCommand->GetNext()));
} else {
//find us and unregister us
ConCommandBase *pPrev = NULL;
while (ptr)
{
if (ptr == pCommand)
break;
pPrev = ptr;
ptr = const_cast<ConCommandBase *>(ptr->GetNext());
}
if (pPrev && ptr == pCommand)
{
pPrev->SetNext(const_cast<ConCommandBase *>(pCommand->GetNext()));
}
}
while (ptr)
{
ConCommandBase *pNext = const_cast<ConCommandBase *>(ptr->GetNext());
if (pNext == pCvar)
break;
ptr = pNext;
}
if (ptr)
{
ptr->SetNext(const_cast<ConCommandBase *>(pCvar->GetNext()));
pCvar->SetNext(NULL);
}
m_RegisteredCommands.remove(pCvar);
}
ConVar metamod_version("metamod_version", SOURCEMM_VERSION, FCVAR_REPLICATED | FCVAR_SPONLY, "Metamod:Source Version");
ConVar metamod_version("metamod_version", SOURCEMM_VERSION, FCVAR_REPLICATED | FCVAR_SPONLY | FCVAR_NOTIFY, "Metamod:Source Version");
CON_COMMAND(meta, "Metamod:Source Menu")
{
@ -111,9 +120,9 @@ CON_COMMAND(meta, "Metamod:Source Menu")
} else if (strcmp(command, "refresh") == 0) {
char full_path[255];
#if defined WIN32 || defined _WIN32
snprintf(full_path, sizeof(full_path)-1, "%s\\%s", g_ModPath.c_str(), "metaplugins.ini");
snprintf(full_path, sizeof(full_path)-1, "%s\\addons\\metamod\\%s", g_ModPath.c_str(), "metaplugins.ini");
#else
snprintf(full_path, sizeof(full_path)-1, "%s/%s", g_ModPath.c_str(), "metaplugins.ini");
snprintf(full_path, sizeof(full_path)-1, "%s/addons/metamod/%s", g_ModPath.c_str(), "metaplugins.ini");
#endif
LoadPluginsFromFile(full_path);
@ -169,6 +178,68 @@ CON_COMMAND(meta, "Metamod:Source Menu")
Msg("\n");
return;
} else if (strcmp(command, "cmds") == 0) {
if (args >= 3)
{
int id = atoi(e->Cmd_Argv(2));
SourceMM::CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id);
if (!pl)
{
Msg("Plugin %d not found.\n", id);
return;
}
if (!pl->m_API)
{
Msg("Plugin %d is not loaded.\n", id);
} else {
Msg("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());
}
}
} else {
Msg("Usage: meta cmds <id>\n");
}
return;
} else if (strcmp(command, "cvars") == 0) {
if (args >= 3)
{
int id = atoi(e->Cmd_Argv(2));
SourceMM::CPluginManager::CPlugin *pl = g_PluginMngr.FindById(id);
if (!pl)
{
Msg("Plugin %d not found.\n", id);
return;
}
if (!pl->m_API)
{
Msg("Plugin %d is not loaded.\n", id);
} else {
Msg("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());
}
}
} else {
Msg("Usage: meta cvars <id>\n");
}
return;
} else if (strcmp(command, "info") == 0) {
if (args >= 3)
@ -368,6 +439,8 @@ CON_COMMAND(meta, "Metamod:Source Menu")
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");
@ -382,3 +455,65 @@ CON_COMMAND(meta, "Metamod:Source Menu")
Msg(" version - Version information\n");
Msg("\n");
}
int UTIL_CmpNocase(const std::string &s1, const std::string &s2)
{
std::string::const_iterator p1 = s1.begin();
std::string::const_iterator p2 = s2.begin();
while (p1 != s1.end() && p2 != s2.end())
{
if(toupper(*p1) != toupper(*p2))
return (toupper(*p1)<toupper(*p2)) ? -1 : 1;
++p1;
++p2;
}
return (s2.size() == s1.size()) ? 0 : (s1.size() < s2.size()) ? -1 : 1; // size is unsigned
}
CAlwaysRegisterableCommand::CAlwaysRegisterableCommand()
{
Create("", NULL, FCVAR_UNREGISTERED|FCVAR_GAMEDLL);
m_pICvar = NULL;
}
bool CAlwaysRegisterableCommand::IsRegistered( void ) const
{
return false;
}
void CAlwaysRegisterableCommand::BringToFront()
{
if (!m_pICvar)
m_pICvar = g_Engine.icvar;
// First, let's try to find us!
ConCommandBase *pPtr = m_pICvar->GetCommands();
if (pPtr == this)
{
// We are already at the beginning; Nothing to do
return;
}
while (pPtr)
{
if (pPtr == this && pPtr->IsCommand() && UTIL_CmpNocase(GetName(), pPtr->GetName()) == 0)
break;
ConCommandBase *pPrev = NULL;
while (pPtr)
{
if (pPtr == this)
break;
pPrev = pPtr;
pPtr = const_cast<ConCommandBase*>(pPtr->GetNext());
}
if (pPrev && pPtr == this)
{
pPrev->SetNext(m_pNext); // Remove us from the list
}
// Now, register us
m_pICvar->RegisterConCommandBase(this);
}
}

View File

@ -27,8 +27,20 @@ class SMConVarAccessor : public IConCommandBaseAccessor
std::list<ConCommandBase*> m_RegisteredCommands;
public:
virtual bool RegisterConCommandBase(ConCommandBase *pCommand);
bool Register(ConCommandBase *pCommand);
void MarkCommandsAsGameDLL();
void Unregister(ConCommandBase *pCvar);
void Unregister(ConCommandBase *pCommand);
};
class CAlwaysRegisterableCommand : public ConCommandBase
{
ICvar *m_pICvar;
public:
CAlwaysRegisterableCommand();
bool IsRegistered( void ) const;
// If already registered, removes us
// Then it registers us again
void BringToFront();
};
extern SMConVarAccessor g_SMConVarAccessor;

View File

@ -87,6 +87,7 @@
AdditionalDependencies="tier0.lib vstdlib.lib"
OutputFile="$(OutDir)/server.dll"
LinkIncremental="1"
IgnoreDefaultLibraryNames=""
GenerateDebugInformation="TRUE"
SubSystem="2"
OptimizeReferences="2"
@ -175,6 +176,9 @@
<File
RelativePath=".\oslink.h">
</File>
<File
RelativePath=".\resource.h">
</File>
<File
RelativePath=".\sourcemm.h">
</File>

View File

@ -27,8 +27,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,2
PRODUCTVERSION 1,0,0,2
FILEVERSION 1,0,0,3
PRODUCTVERSION 1,0,0,3
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L