mirror of
https://github.com/alliedmodders/metamod-source.git
synced 2024-11-28 10:24:20 +01:00
Initial import
--HG-- extra : convert_revision : svn%3Ac2935e3e-5518-0410-8daf-afa5dab7d4e3/trunk%408
This commit is contained in:
parent
b666b9acde
commit
118d4a85ff
35
sourcemm/CHLTVDirector.h
Normal file
35
sourcemm/CHLTVDirector.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_HLTVDIRECTOR_H
|
||||
#define _INCLUDE_HLTVDIRECTOR_H
|
||||
|
||||
/**
|
||||
* @brief Dummy class for IHLTVDirector
|
||||
* @file CHLTVDirector.
|
||||
*/
|
||||
|
||||
#include <eiface.h>
|
||||
#include <ihltvdirector.h>
|
||||
|
||||
class CHLTVDirector : IHLTVDirector
|
||||
{
|
||||
public:
|
||||
virtual bool IsActive() { return false; }
|
||||
virtual void SetHLTVServer(IHLTVServer *hltv) { }
|
||||
virtual IHLTVServer *GetHLTVServer() { return NULL; }
|
||||
virtual int GetDirectorTick() { return 0; }
|
||||
virtual int GetPVSEntity() { return 0; }
|
||||
virtual Vector GetPVSOrigin() { return Vector(0, 0, 0); }
|
||||
virtual float GetDelay() { return 0.0f; }
|
||||
virtual const char**GetModEvents() { return NULL; }
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_HLTVDIRECTOR_H
|
26
sourcemm/CISmmAPI.h
Normal file
26
sourcemm/CISmmAPI.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef _INCLUDE_CSMM_API_H
|
||||
#define _INCLUDE_CSMM_API_H
|
||||
|
||||
#include "ISmmAPI.h"
|
||||
|
||||
class CSmmAPI : public ISmmAPI
|
||||
{
|
||||
public:
|
||||
ISmmPluginManager *PluginManager();
|
||||
SourceHook::ISourceHook *SourceHook();
|
||||
void LogMsg(ISmmPlugin *pl, const char *msg, ...);
|
||||
public:
|
||||
CreateInterfaceFn engineFactory(bool syn=true);
|
||||
CreateInterfaceFn physicsFactory(bool syn=true);
|
||||
CreateInterfaceFn fileSystemFactory(bool syn=true);
|
||||
CreateInterfaceFn serverFactory(bool syn=true);
|
||||
CGlobalVars *pGlobals();
|
||||
void SetLastMetaReturn(META_RES res);
|
||||
META_RES GetLastMetaReturn();
|
||||
private:
|
||||
META_RES m_Res;
|
||||
};
|
||||
|
||||
extern CSmmAPI g_SmmAPI;
|
||||
|
||||
#endif //_INCLUDE_CSMM_API_H
|
324
sourcemm/CPlugin.cpp
Normal file
324
sourcemm/CPlugin.cpp
Normal file
@ -0,0 +1,324 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#include "CPlugin.h"
|
||||
#include "CISmmAPI.h"
|
||||
|
||||
/**
|
||||
* @brief Implements functions from CPlugin.h
|
||||
* @file CPlugin.cpp
|
||||
*/
|
||||
|
||||
using namespace SourceMM;
|
||||
|
||||
CPluginManager g_PluginMngr;
|
||||
|
||||
CPluginManager::CPluginManager()
|
||||
{
|
||||
m_LastId = Pl_MinId;
|
||||
}
|
||||
|
||||
CPluginManager::~CPluginManager()
|
||||
{
|
||||
if (m_Plugins.size())
|
||||
{
|
||||
UnloadAll();
|
||||
m_Plugins.clear();
|
||||
}
|
||||
}
|
||||
|
||||
CPluginManager::CPlugin::CPlugin() : m_Lib(NULL), m_API(NULL), m_Id(0), m_Source(0)
|
||||
{
|
||||
}
|
||||
|
||||
PluginId CPluginManager::Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen)
|
||||
{
|
||||
PluginIter i;
|
||||
|
||||
already = false;
|
||||
//Check if we're about to reload an old plugin
|
||||
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
||||
{
|
||||
if ( (*i) && (*i)->m_File.compare(file)==0 )
|
||||
{
|
||||
if ( (*i)->m_Status < Pl_Paused )
|
||||
{
|
||||
//Attempt to load the plugin again
|
||||
already = true;
|
||||
i = m_Plugins.erase(i);
|
||||
} else {
|
||||
//No need to load it
|
||||
already = true;
|
||||
return (*i)->m_Id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CPlugin *pl = _Load(file, source, error, maxlen);
|
||||
|
||||
if (!pl)
|
||||
return Pl_BadLoad;
|
||||
|
||||
return pl->m_Id;
|
||||
}
|
||||
|
||||
CPluginManager::CPlugin *CPluginManager::FindById(PluginId id)
|
||||
{
|
||||
PluginIter i;
|
||||
|
||||
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
||||
{
|
||||
if ( (*i)->m_Id == id )
|
||||
return (*i);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CPluginManager::Pause(PluginId id, char *error, size_t maxlen)
|
||||
{
|
||||
CPlugin *pl = FindById(id);
|
||||
|
||||
if (!pl)
|
||||
{
|
||||
snprintf(error, maxlen, "Plugin id not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
return _Pause(pl, error, maxlen);
|
||||
}
|
||||
|
||||
bool CPluginManager::Unpause(PluginId id, char *error, size_t maxlen)
|
||||
{
|
||||
CPlugin *pl = FindById(id);
|
||||
|
||||
if (!pl)
|
||||
{
|
||||
snprintf(error, maxlen, "Plugin id not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
return _Unpause(pl, error, maxlen);
|
||||
}
|
||||
|
||||
bool CPluginManager::Unload(PluginId id, char *error, size_t maxlen)
|
||||
{
|
||||
CPlugin *pl = FindById(id);
|
||||
|
||||
if (!pl)
|
||||
{
|
||||
snprintf(error, maxlen, "Plugin id not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
return _Unload(pl, error, maxlen);
|
||||
}
|
||||
|
||||
CPluginManager::CPlugin *CPluginManager::_Load(const char *file, PluginId source, char *error, size_t maxlen)
|
||||
{
|
||||
FILE *fp;
|
||||
CPlugin *pl;
|
||||
|
||||
pl = new CPlugin();
|
||||
*error = '\0';
|
||||
|
||||
//Add plugin to list
|
||||
pl->m_Id = m_LastId;
|
||||
pl->m_File.assign(file);
|
||||
m_Plugins.push_back(pl);
|
||||
m_LastId++;
|
||||
|
||||
//Check if the file even exists
|
||||
fp = fopen(file, "r");
|
||||
if (!fp)
|
||||
{
|
||||
if (error)
|
||||
snprintf(error, maxlen, "File not found: %s", file);
|
||||
pl->m_Status = Pl_NotFound;
|
||||
} else {
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
|
||||
//Load the file
|
||||
pl->m_Lib = dlmount(file);
|
||||
if (!pl->m_Lib)
|
||||
{
|
||||
if (error)
|
||||
snprintf(error, maxlen, "%s", dlerror());
|
||||
pl->m_Status = Pl_Error;
|
||||
} else {
|
||||
CreateInterfaceFn pfn = reinterpret_cast<CreateInterfaceFn>(dlsym(pl->m_Lib, PL_EXPOSURE_C));
|
||||
if (!pfn)
|
||||
{
|
||||
if (error)
|
||||
snprintf(error, maxlen, "Function %s not found", PL_EXPOSURE_C);
|
||||
pl->m_Status = Pl_Error;
|
||||
} else {
|
||||
pl->m_API = static_cast<ISmmPlugin *>((pfn)(PLAPI_NAME, NULL));
|
||||
if (!pl->m_API)
|
||||
{
|
||||
if (error)
|
||||
snprintf(error, maxlen, "Failed to get API");
|
||||
pl->m_Status = Pl_Error;
|
||||
} else {
|
||||
if (pl->m_API->GetApiVersion() < 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);
|
||||
pl->m_Status = Pl_Error;
|
||||
} else {
|
||||
if (pl->m_API->Load(pl->m_Id, static_cast<ISmmAPI *>(&g_SmmAPI), &(pl->fac_list), error, maxlen))
|
||||
{
|
||||
pl->m_Status = Pl_Running;
|
||||
} else {
|
||||
pl->m_Status = Pl_Refused;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pl->m_Lib && (pl->m_Status < Pl_Paused))
|
||||
{
|
||||
dlclose(pl->m_Lib);
|
||||
pl->m_Lib = NULL;
|
||||
pl->m_API = NULL;
|
||||
}
|
||||
|
||||
return pl;
|
||||
}
|
||||
|
||||
bool CPluginManager::_Unload(CPluginManager::CPlugin *pl, char *error, size_t maxlen)
|
||||
{
|
||||
if (error)
|
||||
*error = '\0';
|
||||
if (pl->m_API && pl->m_Lib)
|
||||
{
|
||||
if (pl->m_API->Unload(error, maxlen))
|
||||
{
|
||||
dlclose(pl->m_Lib);
|
||||
pl->m_Lib = NULL;
|
||||
pl->m_API = NULL;
|
||||
|
||||
//Remove the plugin from the list
|
||||
PluginIter i;
|
||||
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
||||
{
|
||||
if ( (*i)->m_Id == pl->m_Id )
|
||||
{
|
||||
i = m_Plugins.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete pl;
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
//The plugin is not valid, and let's just remove it from the list anyway
|
||||
PluginIter i;
|
||||
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
||||
{
|
||||
if ( (*i)->m_Id == pl->m_Id )
|
||||
{
|
||||
i = m_Plugins.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete pl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CPluginManager::_Pause(CPluginManager::CPlugin *pl, char *error, size_t maxlen)
|
||||
{
|
||||
if (error)
|
||||
*error = '\0';
|
||||
if (pl->m_Status != Pl_Running || !pl->m_API)
|
||||
{
|
||||
if (error)
|
||||
snprintf(error, maxlen, "Plugin cannot be paused");
|
||||
} else {
|
||||
return pl->m_API->Pause(error, maxlen);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CPluginManager::_Unpause(CPluginManager::CPlugin *pl, char *error, size_t maxlen)
|
||||
{
|
||||
if (error)
|
||||
*error = '\0';
|
||||
|
||||
if (pl->m_Status != Pl_Paused || !pl->m_API)
|
||||
{
|
||||
if (error)
|
||||
snprintf(error, maxlen, "Plugin cannot be unpaused");
|
||||
} else {
|
||||
return pl->m_API->Unpause(error, maxlen);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CPluginManager::UnloadAll()
|
||||
{
|
||||
PluginIter i;
|
||||
bool status = true;
|
||||
|
||||
for (i=m_Plugins.begin(); i!=m_Plugins.end(); i++)
|
||||
{
|
||||
if ( (*i) )
|
||||
{
|
||||
if ( (*i)->m_API )
|
||||
{
|
||||
if ( (*i)->m_API->Unload(NULL, 0) )
|
||||
status = false;
|
||||
|
||||
dlclose( (*i)->m_Lib );
|
||||
}
|
||||
delete (*i);
|
||||
}
|
||||
|
||||
i = m_Plugins.erase(i);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool CPluginManager::Query(PluginId id, const char *&file, factories *&list, Pl_Status &status, PluginId &source)
|
||||
{
|
||||
CPlugin *pl = FindById(id);
|
||||
|
||||
if (!pl)
|
||||
return false;
|
||||
|
||||
file = pl->m_File.c_str();
|
||||
list = &(pl->fac_list);
|
||||
status = pl->m_Status;
|
||||
source = pl->m_Source;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
PluginIter CPluginManager::_begin()
|
||||
{
|
||||
return m_Plugins.begin();
|
||||
}
|
||||
|
||||
PluginIter CPluginManager::_end()
|
||||
{
|
||||
return m_Plugins.end();
|
||||
}
|
87
sourcemm/CPlugin.h
Normal file
87
sourcemm/CPlugin.h
Normal file
@ -0,0 +1,87 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_CPLUGIN_H
|
||||
#define _INCLUDE_CPLUGIN_H
|
||||
|
||||
/**
|
||||
* @brief Implementation of Plugin API and Management routines
|
||||
* @file CPlugin.cpp
|
||||
*/
|
||||
|
||||
#include <list>
|
||||
#include "IPluginManager.h"
|
||||
#include "oslink.h"
|
||||
|
||||
namespace SourceMM
|
||||
{
|
||||
/**
|
||||
* @brief Implements Plugin Manager API
|
||||
*/
|
||||
class CPluginManager : public ISmmPluginManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Internal structure for holding plugin data
|
||||
*/
|
||||
class CPlugin
|
||||
{
|
||||
public:
|
||||
CPlugin();
|
||||
public:
|
||||
PluginId m_Id;
|
||||
std::string m_File;
|
||||
Pl_Status m_Status;
|
||||
PluginId m_Source;
|
||||
ISmmPlugin *m_API;
|
||||
HINSTANCE m_Lib;
|
||||
factories fac_list;
|
||||
};
|
||||
public:
|
||||
CPluginManager();
|
||||
~CPluginManager();
|
||||
public:
|
||||
PluginId Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen);
|
||||
bool Unload(PluginId id, char *error, size_t maxlen);
|
||||
bool Pause(PluginId id, char *error, size_t maxlen);
|
||||
bool Unpause(PluginId id, char *error, size_t maxlen);
|
||||
bool UnloadAll();
|
||||
public:
|
||||
bool Query(PluginId id, const char *&file, factories *&list, Pl_Status &status, PluginId &source);
|
||||
|
||||
/**
|
||||
* @brief Finds a plugin by Id
|
||||
*
|
||||
* @param id Id of plugin
|
||||
* @return CPlugin on success, NULL otherwise
|
||||
*/
|
||||
CPlugin *FindById(PluginId id);
|
||||
|
||||
//Internal iterators
|
||||
std::list<SourceMM::CPluginManager::CPlugin *>::iterator _begin();
|
||||
std::list<SourceMM::CPluginManager::CPlugin *>::iterator _end();
|
||||
private:
|
||||
//These are identical internal functions for the wrappers above.
|
||||
CPlugin *_Load(const char *file, PluginId source, char *error, size_t maxlen);
|
||||
bool _Unload(CPlugin *pl, char *error, size_t maxlen);
|
||||
bool _Pause(CPlugin *pl, char *error, size_t maxlen);
|
||||
bool _Unpause(CPlugin *pl, char *error, size_t maxlen);
|
||||
private:
|
||||
PluginId m_LastId;
|
||||
std::list<CPlugin *> m_Plugins;
|
||||
};
|
||||
};
|
||||
|
||||
typedef std::list<SourceMM::CPluginManager::CPlugin *>::iterator PluginIter;
|
||||
|
||||
/** @brief Singleton for plugin manager */
|
||||
extern SourceMM::CPluginManager g_PluginMngr;
|
||||
|
||||
#endif //_INCLUDE_CPLUGIN_H
|
41
sourcemm/CServerGameClients.h
Normal file
41
sourcemm/CServerGameClients.h
Normal file
@ -0,0 +1,41 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_CSERVERGAMECLIENTS_H
|
||||
#define _INCLUDE_CSERVERGAMECLIENTS_H
|
||||
|
||||
/**
|
||||
* @brief Dummy class for IServerGameClients
|
||||
* @file CServerGameClients.h
|
||||
*/
|
||||
|
||||
#include <eiface.h>
|
||||
|
||||
class CServerGameClients : public IServerGameClients
|
||||
{
|
||||
public:
|
||||
virtual void GetPlayerLimits(int& minplayers, int& maxplayers, int &defaultMaxPlayers) const { }
|
||||
virtual bool ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) { return false; }
|
||||
virtual void ClientActive(edict_t *pEntity, bool bLoadGame) { }
|
||||
virtual void ClientDisconnect(edict_t *pEntity) { }
|
||||
virtual void ClientPutInServer(edict_t *pEntity, char const *playername) { }
|
||||
virtual void ClientCommand(edict_t *pEntity) { }
|
||||
virtual void SetCommandClient(int index) { }
|
||||
virtual void ClientSettingsChanged(edict_t *pEdict) { }
|
||||
virtual void ClientSetupVisibility(edict_t *pViewEntity, edict_t *pClient, unsigned char *pvs, int pvssize) { }
|
||||
virtual float ProcessUsercmds(edict_t *player, bf_read *buf, int numcmds, int totalcmds, int dropped_packets, bool ignore, bool paused) { return 0.0f; }
|
||||
virtual void PostClientMessagesSent() { }
|
||||
virtual CPlayerState *GetPlayerState(edict_t *player) { return NULL; }
|
||||
virtual void ClientEarPosition(edict_t *pEntity, Vector *pEarOrigin) { }
|
||||
virtual int GetReplayDelay(edict_t *player) { return 0; }
|
||||
virtual void GetBugReportInfo(char *buf, int buflen) { }
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_CSERVERGAMECLIENTS_H
|
58
sourcemm/CServerGameDLL.h
Normal file
58
sourcemm/CServerGameDLL.h
Normal file
@ -0,0 +1,58 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_CSERVER_GAMEDLL_H
|
||||
#define _INCLUDE_CSERVER_GAMEDLL_H
|
||||
|
||||
/**
|
||||
* @brief Defines wrapper class for gamedll interfaces
|
||||
* @file CServerGameDLL.h
|
||||
*/
|
||||
|
||||
#include <eiface.h>
|
||||
|
||||
/**
|
||||
* @brief Empty class. We only care about DLLInit.
|
||||
*/
|
||||
class CServerGameDLL : public IServerGameDLL
|
||||
{
|
||||
public:
|
||||
virtual bool DLLInit( CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory, CGlobalVars *pGlobals);
|
||||
virtual bool GameInit( void ) { return false; }
|
||||
virtual bool LevelInit( char const *pMapName, char const *pMapEntities, char const *pOldLevel, char const *pLandmarkName, bool loadGame, bool background ) { return false; }
|
||||
virtual void ServerActivate( edict_t *pEdictList, int edictCount, int clientMax ) { }
|
||||
virtual void GameFrame( bool simulating ) { }
|
||||
virtual void PreClientUpdate( bool simulating ) { }
|
||||
virtual void LevelShutdown( void ) { }
|
||||
virtual void GameShutdown( void ) { }
|
||||
virtual void DLLShutdown( void ) { }
|
||||
virtual float GetTickInterval( void ) const { return 0.0f; }
|
||||
virtual ServerClass *GetAllServerClasses( void ) { return NULL; }
|
||||
virtual const char *GetGameDescription( void ) { return NULL; }
|
||||
virtual void CreateNetworkStringTables( void ) { }
|
||||
virtual CSaveRestoreData *SaveInit( int size ) { return NULL; }
|
||||
virtual void SaveWriteFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) { }
|
||||
virtual void SaveReadFields( CSaveRestoreData *, const char *, void *, datamap_t *, typedescription_t *, int ) { }
|
||||
virtual void SaveGlobalState( CSaveRestoreData * ) { }
|
||||
virtual void RestoreGlobalState( CSaveRestoreData * ) { }
|
||||
virtual void PreSave( CSaveRestoreData * ) { }
|
||||
virtual void Save( CSaveRestoreData * ) { }
|
||||
virtual void GetSaveComment( char *comment, int maxlength ) { }
|
||||
virtual void WriteSaveHeaders( CSaveRestoreData * ) { }
|
||||
virtual void ReadRestoreHeaders( CSaveRestoreData * ) { }
|
||||
virtual void Restore( CSaveRestoreData *, bool ) { }
|
||||
virtual bool IsRestoring() { return false; }
|
||||
virtual int CreateEntityTransitionList( CSaveRestoreData *, int ) { return 0; }
|
||||
virtual void BuildAdjacentMapList( void ) { }
|
||||
virtual bool GetUserMessageInfo( int msg_type, char *name, int maxnamelength, int& size ) { return false; }
|
||||
virtual CStandardSendProxies* GetStandardSendProxies() { return NULL; }
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_CSERVER_GAMEDLL_H
|
32
sourcemm/CServerGameEnts.h
Normal file
32
sourcemm/CServerGameEnts.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_CSERVER_GAMEENTS_H
|
||||
#define _INCLUDE_CSERVER_GAMEENTS_H
|
||||
|
||||
/**
|
||||
* @brief Dummy class for IServerGameEnts
|
||||
* @file CServerGameEnts.h
|
||||
*/
|
||||
|
||||
#include <eiface.h>
|
||||
|
||||
class CServerGameEnts : public IServerGameEnts
|
||||
{
|
||||
public:
|
||||
virtual void SetDebugEdictBase(edict_t *base) { }
|
||||
virtual void MarkEntitiesAsTouching(edict_t *e1, edict_t *e2) { }
|
||||
virtual void FreeContainingEntity(edict_t *e) { }
|
||||
virtual edict_t *BaseEntityToEdict(CBaseEntity *pEnt) { return NULL; }
|
||||
virtual CBaseEntity *EdictToBaseEntity(edict_t *pEdict) { return NULL; }
|
||||
virtual void CheckTransmit(CCheckTransmitInfo *pInfo, const unsigned short *pEdictIndices, int nEdicts) { }
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_CSERVER_GAMEENTS_H
|
71
sourcemm/CSmmAPI.cpp
Normal file
71
sourcemm/CSmmAPI.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
#include "CISmmAPI.h"
|
||||
#include "sourcemm.h"
|
||||
|
||||
CSmmAPI g_SmmAPI;
|
||||
|
||||
ISmmPluginManager *CSmmAPI::PluginManager()
|
||||
{
|
||||
return static_cast<ISmmPluginManager *>(&g_PluginMngr);
|
||||
}
|
||||
|
||||
SourceHook::ISourceHook *CSmmAPI::SourceHook()
|
||||
{
|
||||
return static_cast<SourceHook::ISourceHook *>(&g_SourceHook);
|
||||
}
|
||||
|
||||
void CSmmAPI::LogMsg(ISmmPlugin *pl, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
static char buffer[2048];
|
||||
|
||||
buffer[0] = '\0';
|
||||
|
||||
va_start(ap, msg);
|
||||
vsnprintf(buffer, sizeof(buffer)-1, msg, ap);
|
||||
va_end(ap);
|
||||
|
||||
LogMessage("[%s] %s", pl->GetLogTag(), buffer);
|
||||
}
|
||||
|
||||
CreateInterfaceFn CSmmAPI::engineFactory(bool syn)
|
||||
{
|
||||
if (syn)
|
||||
return EngineFactory;
|
||||
return g_Engine.engineFactory;
|
||||
}
|
||||
|
||||
CreateInterfaceFn CSmmAPI::physicsFactory(bool syn)
|
||||
{
|
||||
if (syn)
|
||||
return PhysicsFactory;
|
||||
return g_Engine.physicsFactory;
|
||||
}
|
||||
|
||||
CreateInterfaceFn CSmmAPI::fileSystemFactory(bool syn)
|
||||
{
|
||||
if (syn)
|
||||
return FileSystemFactory;
|
||||
return g_Engine.fileSystemFactory;
|
||||
}
|
||||
|
||||
CreateInterfaceFn CSmmAPI::serverFactory(bool syn)
|
||||
{
|
||||
if (syn)
|
||||
return CreateInterface;
|
||||
return g_GameDll.factory;
|
||||
}
|
||||
|
||||
CGlobalVars *CSmmAPI::pGlobals()
|
||||
{
|
||||
return g_Engine.pGlobals;
|
||||
}
|
||||
|
||||
void CSmmAPI::SetLastMetaReturn(META_RES res)
|
||||
{
|
||||
m_Res = res;
|
||||
}
|
||||
|
||||
META_RES CSmmAPI::GetLastMetaReturn()
|
||||
{
|
||||
return m_Res;
|
||||
}
|
98
sourcemm/IPluginManager.h
Normal file
98
sourcemm/IPluginManager.h
Normal file
@ -0,0 +1,98 @@
|
||||
#ifndef _INCLUDE_PLUGINMANAGER_H
|
||||
#define _INCLUDE_PLUGINMANAGER_H
|
||||
|
||||
#include "ISmmPlugin.h"
|
||||
|
||||
/**
|
||||
* @brief Status of a plugin at runtime
|
||||
*/
|
||||
enum Pl_Status
|
||||
{
|
||||
Pl_NotFound=-4,
|
||||
Pl_Error=-3,
|
||||
Pl_Refused=-2,
|
||||
Pl_Paused=-1,
|
||||
Pl_Running=0,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Load sources
|
||||
*/
|
||||
enum
|
||||
{
|
||||
Pl_BadLoad=0,
|
||||
Pl_Console,
|
||||
Pl_File,
|
||||
Pl_MinId,
|
||||
};
|
||||
|
||||
typedef unsigned int PluginId;
|
||||
struct factories;
|
||||
|
||||
class ISmmPluginManager
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Loads a plugin and returns its id
|
||||
*
|
||||
* @param file String containing file name
|
||||
* @param source Specifies who loaded the plugin
|
||||
* @param status Status of the plugin
|
||||
* @param ismm Pointer to Smm API
|
||||
* @param error String buffer for error messages
|
||||
* @param maxlen Maximum length of buffer
|
||||
* @return Id of plugin
|
||||
*/
|
||||
virtual PluginId Load(const char *file, PluginId source, bool &already, char *error, size_t maxlen) =0;
|
||||
|
||||
/**
|
||||
* @brief Unloads a plugin
|
||||
*
|
||||
* @param id Id of plugin
|
||||
* @param error String buffer for error messages
|
||||
* @param maxlen Maximum length of buffer
|
||||
* @return True on success, false otherwise
|
||||
*/
|
||||
virtual bool Unload(PluginId id, char *error, size_t maxlen) =0;
|
||||
|
||||
/**
|
||||
* @brief Pauses a plugin
|
||||
*
|
||||
* @param id Id of plugin
|
||||
* @param error String buffer for error messages
|
||||
* @param maxlen Maximum length of buffer
|
||||
* @return True on success, false otherwise
|
||||
*/
|
||||
virtual bool Pause(PluginId id, char *error, size_t maxlen) =0;
|
||||
|
||||
/**
|
||||
* @brief Unpauses a plugin
|
||||
*
|
||||
* @param id Id of plugin
|
||||
* @param error String buffer for error messages
|
||||
* @param maxlen Maximum length of buffer
|
||||
* @return True on success, false otherwise
|
||||
*/
|
||||
virtual bool Unpause(PluginId id, char *error, size_t maxlen) =0;
|
||||
|
||||
/**
|
||||
* @brief Unloads all plugins forcefully
|
||||
*
|
||||
* @return True on success, false otherwise
|
||||
*/
|
||||
virtual bool UnloadAll() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns information about a plugin
|
||||
*
|
||||
* @param id Id of plugin
|
||||
* @param file Pointer to file string by reference
|
||||
* @param list Pointer to factories by reference
|
||||
* @param status By reference status of plugin
|
||||
* @param source By reference source of plugin
|
||||
* @return True on success, false if not found
|
||||
*/
|
||||
virtual bool Query(PluginId id, const char *&file, factories *&list, Pl_Status &status, PluginId &source) =0;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_PLUGINMANAGER_H
|
27
sourcemm/ISmmAPI.h
Normal file
27
sourcemm/ISmmAPI.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef _INCLUDE_ISMM_API_H
|
||||
#define _INCLUDE_ISMM_API_H
|
||||
|
||||
#include <interface.h>
|
||||
#include <eiface.h>
|
||||
#include <sourcehook/sourcehook.h>
|
||||
#include "IPluginManager.h"
|
||||
|
||||
class ISmmPluginManager;
|
||||
class ISmmPlugin;
|
||||
|
||||
class ISmmAPI
|
||||
{
|
||||
public:
|
||||
virtual ISmmPluginManager *PluginManager() =0;
|
||||
virtual SourceHook::ISourceHook *SourceHook() =0;
|
||||
virtual void LogMsg(ISmmPlugin *pl, const char *msg, ...) =0;
|
||||
public:
|
||||
virtual CreateInterfaceFn engineFactory(bool syn=true) =0;
|
||||
virtual CreateInterfaceFn physicsFactory(bool syn=true) =0;
|
||||
virtual CreateInterfaceFn fileSystemFactory(bool syn=true) =0;
|
||||
virtual CreateInterfaceFn serverFactory(bool syn=true) =0;
|
||||
virtual CGlobalVars *pGlobals() =0;
|
||||
virtual void SetLastMetaReturn(META_RES res) =0;
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_ISMM_API_H
|
112
sourcemm/ISmmPlugin.h
Normal file
112
sourcemm/ISmmPlugin.h
Normal file
@ -0,0 +1,112 @@
|
||||
#ifndef _INCLUDE_ISMM_PLUGIN_H
|
||||
#define _INCLUDE_ISMM_PLUGIN_H
|
||||
|
||||
#include <interface.h>
|
||||
#include <sourcehook/sourcehook.h>
|
||||
#include "ISmmAPI.h"
|
||||
|
||||
#define PLAPI_VERSION 003
|
||||
#define PLAPI_NAME "ISmmPlugin"
|
||||
|
||||
struct factories
|
||||
{
|
||||
CreateInterfaceFn engine;
|
||||
CreateInterfaceFn server;
|
||||
CreateInterfaceFn physics;
|
||||
CreateInterfaceFn fileSystem;
|
||||
};
|
||||
|
||||
class ISmmAPI;
|
||||
typedef unsigned int PluginId;
|
||||
|
||||
class ISmmPlugin
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Called on plugin load.
|
||||
*
|
||||
* @param id Internal id of plugin.
|
||||
* @param ismm External API for SourceMM. Saved globally by PLUGIN_SAVEVARS()
|
||||
* @param list Contains a list of factories. Hook a factory call by setting one equal to your own function.
|
||||
* @param error Error message buffer
|
||||
* @param maxlen Size of error message buffer
|
||||
* @return True on success, return false to request no load.
|
||||
*/
|
||||
virtual bool Load(PluginId id, ISmmAPI *ismm, factories *list, char *error, size_t maxlen) =0;
|
||||
|
||||
/* @brief Called on plugin unload.
|
||||
*
|
||||
* @param error Error message buffer
|
||||
* @param maxlen Size of error message buffer
|
||||
* @return True on success, return false to request no unload.
|
||||
*/
|
||||
virtual bool Unload(char *error, size_t maxlen) =0;
|
||||
|
||||
/* @brief Called on plugin pause.
|
||||
*
|
||||
* @param error Error message buffer
|
||||
* @param maxlen Size of error message buffer
|
||||
* @return True on success, return false to request no pause.
|
||||
*/
|
||||
virtual bool Pause(char *error, size_t maxlen) =0;
|
||||
|
||||
/* @brief Called on plugin unpause.
|
||||
*
|
||||
* @param error Error message buffer
|
||||
* @param maxlen Size of error message buffer
|
||||
* @return True on success, return false to request no unpause.
|
||||
*/
|
||||
virtual bool Unpause(char *error, size_t maxlen) =0;
|
||||
public:
|
||||
virtual int GetApiVersion() { return PLAPI_VERSION; }
|
||||
public:
|
||||
virtual const char *GetAuthor() =0;
|
||||
virtual const char *GetName() =0;
|
||||
virtual const char *GetDescription() =0;
|
||||
virtual const char *GetURL() =0;
|
||||
virtual const char *GetLicense() =0;
|
||||
virtual const char *GetVersion() =0;
|
||||
virtual const char *GetDate() =0;
|
||||
virtual const char *GetLogTag() =0;
|
||||
};
|
||||
|
||||
#define PL_EXPOSURE CreateInterface
|
||||
#define PL_EXPOSURE_C "CreateInterface"
|
||||
#define PLAPI_MIN_VERSION 002
|
||||
|
||||
#define PLUGIN_EXPOSE(name, var) \
|
||||
ISmmAPI *g_SMAPI = NULL; \
|
||||
ISmmPlugin *g_PLID = NULL; \
|
||||
SourceHook::ISourceHook *g_SHPtr = NULL; \
|
||||
SMM_API void *PL_EXPOSURE(const char *name, int *code) { \
|
||||
if (name && !strcmp(name, PLAPI_NAME)) { \
|
||||
return static_cast<void *>(&var); \
|
||||
} \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
#define PLUGIN_GLOBALVARS() \
|
||||
extern SourceHook::ISourceHook *g_SHPtr; \
|
||||
extern ISmmAPI *g_SMAPI; \
|
||||
extern ISmmPlugin *g_PLID;
|
||||
|
||||
#define PLUGIN_SAVEVARS() \
|
||||
g_SMAPI = ismm; \
|
||||
g_SHPtr = ismm->SourceHook(); \
|
||||
g_PLID = static_cast<ISmmPlugin *>(this);
|
||||
|
||||
#define FACTORY_RETURN(mres, value) \
|
||||
g_SMAPI->SetLastMetaReturn(mres); \
|
||||
return value;
|
||||
|
||||
#define META_LOG g_SMAPI->LogMsg
|
||||
|
||||
#if !defined SMM_API
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
#define SMM_API extern "C" __declspec(dllexport)
|
||||
#elif defined __GNUC__
|
||||
#define SMM_API extern "C"
|
||||
#endif
|
||||
#endif //!defined SMM_API
|
||||
|
||||
#endif //_INCLUDE_ISMM_PLUGIN_H
|
147
sourcemm/concommands.cpp
Normal file
147
sourcemm/concommands.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#include "concommands.h"
|
||||
#include "CPlugin.h"
|
||||
|
||||
/**
|
||||
* @brief Console Command Implementations
|
||||
* @file concommands.cpp
|
||||
*/
|
||||
|
||||
SMConVarAccessor g_SMConVarAccessor;
|
||||
|
||||
bool SMConVarAccessor::RegisterConCommandBase(ConCommandBase *pCommand)
|
||||
{
|
||||
pCommand->SetNext( NULL );
|
||||
g_Engine.icvar->RegisterConCommandBase(pCommand);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ConVar metamod_version("metamod_version", SOURCEMM_VERSION, FCVAR_REPLICATED | FCVAR_SPONLY, "Metamod:Source Version");
|
||||
|
||||
CON_COMMAND(meta, "Metamod:Source Menu")
|
||||
{
|
||||
IVEngineServer *e = g_Engine.engine;
|
||||
|
||||
int args = e->Cmd_Argc();
|
||||
|
||||
if (args >= 2)
|
||||
{
|
||||
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");
|
||||
|
||||
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("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());
|
||||
|
||||
return;
|
||||
} 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");
|
||||
#else
|
||||
snprintf(full_path, sizeof(full_path)-1, "%s/%s", g_ModPath.c_str(), "metaplugins.ini");
|
||||
#endif
|
||||
LoadPluginsFromFile(full_path);
|
||||
|
||||
return;
|
||||
} else if (strcmp(command, "list") == 0) {
|
||||
SourceMM::CPluginManager::CPlugin *pl;
|
||||
PluginIter i;
|
||||
const char *status="";
|
||||
|
||||
Msg("[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);
|
||||
if (!pl)
|
||||
break;
|
||||
if (pl->m_Status == Pl_Paused)
|
||||
{
|
||||
status = "PAUSE";
|
||||
} else if (pl->m_Status == Pl_Running) {
|
||||
status = "RUN";
|
||||
} else if (pl->m_Status == Pl_Refused) {
|
||||
status = "FAIL";
|
||||
} else if (pl->m_Status == Pl_Error) {
|
||||
status = "ERROR";
|
||||
} else if (pl->m_Status == Pl_NotFound) {
|
||||
status = "NOFILE";
|
||||
}
|
||||
Msg("[%02d] %-16.15s %-8.7s %-12.11s %-8.7s\n", pl->m_Id, pl->m_API->GetName(), pl->m_API->GetVersion(), pl->m_API->GetAuthor(), status);
|
||||
}
|
||||
|
||||
return;
|
||||
} else if (strcmp(command, "info") == 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 {
|
||||
if (pl->m_Status == Pl_Paused)
|
||||
{
|
||||
Msg("Plugin %d is paused.\n", id);
|
||||
} else if (pl->m_Status == Pl_Running) {
|
||||
Msg("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());
|
||||
}
|
||||
Msg("File: %s\n", pl->m_File.c_str());
|
||||
|
||||
return;
|
||||
} else {
|
||||
Msg("Usage: meta info <id>\n");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Msg("Metamod:Source Menu\n");
|
||||
Msg("usage: meta <command> [arguments]\n");
|
||||
Msg(" credits - About Metamod:Source\n");
|
||||
Msg(" game - Information about GameDLL\n");
|
||||
Msg(" info - Information about a plugin\n");
|
||||
Msg(" list - List plugins\n");
|
||||
Msg(" refresh - Reparse plugins file\n");
|
||||
Msg(" version - Version information\n");
|
||||
}
|
30
sourcemm/concommands.h
Normal file
30
sourcemm/concommands.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_CONCOMMANDS_H
|
||||
#define _INCLUDE_CONCOMMANDS_H
|
||||
|
||||
/**
|
||||
* @brief Header for console commands
|
||||
* @file concommands.h
|
||||
*/
|
||||
|
||||
#include "sourcemm.h"
|
||||
#include <convar.h>
|
||||
|
||||
class SMConVarAccessor : public IConCommandBaseAccessor
|
||||
{
|
||||
public:
|
||||
virtual bool RegisterConCommandBase(ConCommandBase *pCommand);
|
||||
};
|
||||
|
||||
extern SMConVarAccessor g_SMConVarAccessor;
|
||||
|
||||
#endif //_INCLUDE_CONCOMMANDS_H
|
812
sourcemm/convar.cpp
Normal file
812
sourcemm/convar.cpp
Normal file
@ -0,0 +1,812 @@
|
||||
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "basetypes.h"
|
||||
#include "convar.h"
|
||||
#include "vstdlib/strtools.h"
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
ConCommandBase *ConCommandBase::s_pConCommandBases = NULL;
|
||||
IConCommandBaseAccessor *ConCommandBase::s_pAccessor = NULL;
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// ConCommandBaseMgr.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
void ConCommandBaseMgr::OneTimeInit( IConCommandBaseAccessor *pAccessor )
|
||||
{
|
||||
ConCommandBase *pCur, *pNext;
|
||||
|
||||
ConCommandBase::s_pAccessor = pAccessor;
|
||||
|
||||
pCur = ConCommandBase::s_pConCommandBases;
|
||||
while ( pCur )
|
||||
{
|
||||
pNext = pCur->m_pNext;
|
||||
pCur->Init();
|
||||
pCur = pNext;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Default constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommandBase::ConCommandBase( void )
|
||||
{
|
||||
m_bRegistered = false;
|
||||
m_pszName = NULL;
|
||||
m_pszHelpString = NULL;
|
||||
|
||||
m_nFlags = 0;
|
||||
m_pNext = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: The base console invoked command/cvar interface
|
||||
// Input : *pName - name of variable/command
|
||||
// *pHelpString - help text
|
||||
// flags - flags
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommandBase::ConCommandBase( char const *pName, char const *pHelpString /*=0*/, int flags /*= 0*/ )
|
||||
{
|
||||
Create( pName, pHelpString, flags );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommandBase::~ConCommandBase( void )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConCommandBase::IsCommand( void ) const
|
||||
{
|
||||
// Assert( 0 ); This can't assert. . causes a recursive assert in Sys_Printf, etc.
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *pName -
|
||||
// callback -
|
||||
// *pHelpString -
|
||||
// flags -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConCommandBase::Create( char const *pName, char const *pHelpString /*= 0*/, int flags /*= 0*/ )
|
||||
{
|
||||
static char *empty_string = "";
|
||||
|
||||
m_bRegistered = false;
|
||||
|
||||
// Name should be static data
|
||||
Assert( pName );
|
||||
m_pszName = pName;
|
||||
m_pszHelpString = pHelpString ? pHelpString : empty_string;
|
||||
|
||||
m_nFlags = flags;
|
||||
|
||||
if ( !( m_nFlags & FCVAR_UNREGISTERED ) )
|
||||
{
|
||||
m_pNext = s_pConCommandBases;
|
||||
s_pConCommandBases = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's unregistered
|
||||
m_pNext = NULL;
|
||||
}
|
||||
|
||||
// If s_pAccessor is already set (this ConVar is not a global variable),
|
||||
// register it.
|
||||
if ( s_pAccessor )
|
||||
{
|
||||
Init();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Used internally by OneTimeInit to initialize.
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConCommandBase::Init()
|
||||
{
|
||||
if ( !s_pAccessor )
|
||||
return;
|
||||
|
||||
if ( m_bRegistered )
|
||||
return;
|
||||
|
||||
s_pAccessor->RegisterConCommandBase( this );
|
||||
|
||||
m_bRegistered = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *name -
|
||||
// Output : ConCommandBase
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommandBase const *ConCommandBase::FindCommand( char const *name )
|
||||
{
|
||||
ConCommandBase const *cmd = GetCommands();
|
||||
for ( ; cmd; cmd = cmd->GetNext() )
|
||||
{
|
||||
if ( !stricmp( name, cmd->GetName() ) )
|
||||
return cmd;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : ConCommandBase
|
||||
//-----------------------------------------------------------------------------
|
||||
const ConCommandBase *ConCommandBase::GetCommands( void )
|
||||
{
|
||||
return s_pConCommandBases;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *var -
|
||||
// Output : static
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConCommandBase::AddToList( ConCommandBase *var )
|
||||
{
|
||||
// This routine is only valid on root ConCommandBases
|
||||
var->m_pNext = s_pConCommandBases;
|
||||
s_pConCommandBases = var;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Return name of the command/var
|
||||
// Output : char const
|
||||
//-----------------------------------------------------------------------------
|
||||
char const *ConCommandBase::GetName( void ) const
|
||||
{
|
||||
return m_pszName;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flag -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConCommandBase::RemoveFlaggedCommands( int flag )
|
||||
{
|
||||
ConCommandBase *pNewList;
|
||||
ConCommandBase *pCommand, *pNext;
|
||||
|
||||
pNewList = NULL;
|
||||
|
||||
pCommand = s_pConCommandBases;
|
||||
while ( pCommand )
|
||||
{
|
||||
pNext = pCommand->m_pNext;
|
||||
if ( !( pCommand->m_nFlags & flag ) )
|
||||
{
|
||||
pCommand->m_pNext = pNewList;
|
||||
pNewList = pCommand;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unlink
|
||||
pCommand->m_pNext = NULL;
|
||||
}
|
||||
|
||||
pCommand = pNext;
|
||||
}
|
||||
|
||||
s_pConCommandBases = pNewList;
|
||||
}
|
||||
|
||||
void ConCommandBase::RevertFlaggedCvars( int flag )
|
||||
{
|
||||
for (const ConCommandBase *var= GetCommands() ; var ; var=var->GetNext())
|
||||
{
|
||||
if ( var->IsCommand() )
|
||||
continue;
|
||||
|
||||
ConVar *cvar = ( ConVar * )var;
|
||||
|
||||
if ( !cvar->IsBitSet( flag ) )
|
||||
continue;
|
||||
|
||||
// It's == to the default value, don't count
|
||||
if ( !Q_strcasecmp( cvar->GetDefault(), cvar->GetString() ) )
|
||||
continue;
|
||||
|
||||
cvar->Revert();
|
||||
|
||||
// DevMsg( "%s = \"%s\" (reverted)\n", cvar->GetName(), cvar->GetString() );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flag -
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConCommandBase::IsBitSet( int flag ) const
|
||||
{
|
||||
return ( flag & m_nFlags ) ? true : false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : flags -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConCommandBase::AddFlags( int flags )
|
||||
{
|
||||
m_nFlags |= flags;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : const ConCommandBase
|
||||
//-----------------------------------------------------------------------------
|
||||
const ConCommandBase *ConCommandBase::GetNext( void ) const
|
||||
{
|
||||
return m_pNext;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *next -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConCommandBase::SetNext( ConCommandBase *next )
|
||||
{
|
||||
m_pNext = next;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Copies string using local new/delete operators
|
||||
// Input : *from -
|
||||
// Output : char
|
||||
//-----------------------------------------------------------------------------
|
||||
char *ConCommandBase::CopyString( char const *from )
|
||||
{
|
||||
int len;
|
||||
char *to;
|
||||
|
||||
len = strlen( from );
|
||||
if ( len <= 0 )
|
||||
{
|
||||
to = new char[1];
|
||||
to[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
to = new char[len+1];
|
||||
Q_strncpy( to, from, len+1 );
|
||||
}
|
||||
return to;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : char const
|
||||
//-----------------------------------------------------------------------------
|
||||
char const *ConCommandBase::GetHelpText( void ) const
|
||||
{
|
||||
return m_pszHelpString;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Has this cvar been registered
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConCommandBase::IsRegistered( void ) const
|
||||
{
|
||||
return m_bRegistered;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructs a console command
|
||||
// Input : *pName - name of command
|
||||
// callback - function to call upon execution
|
||||
// *pHelpString - help text for command
|
||||
// flags - command flags, if any
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommand::ConCommand( char const *pName, FnCommandCallback callback, char const *pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*= 0*/ )
|
||||
{
|
||||
Create( pName, callback, pHelpString, flags, completionFunc );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
ConCommand::~ConCommand( void )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConCommand::IsCommand( void ) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Invoke the function if there is one
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConCommand::Dispatch( void )
|
||||
{
|
||||
if ( m_fnCommandCallback )
|
||||
{
|
||||
( *m_fnCommandCallback )();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Command without callback!!!
|
||||
Assert( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *partial -
|
||||
// context -
|
||||
// longest -
|
||||
// maxcommands -
|
||||
// **commands -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int DefaultCompletionFunc( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Create the named command
|
||||
// Input : *pName -
|
||||
// callback -
|
||||
// *pHelpString -
|
||||
// flags -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConCommand::Create( char const *pName, FnCommandCallback callback, char const *pHelpString /*= 0*/, int flags /*= 0*/, FnCommandCompletionCallback completionFunc /*=0*/ )
|
||||
{
|
||||
// Set the callback
|
||||
m_fnCommandCallback = callback;
|
||||
|
||||
m_fnCompletionCallback = completionFunc ? completionFunc : DefaultCompletionFunc;
|
||||
m_bHasCompletionCallback = completionFunc != 0 ? true : false;
|
||||
|
||||
// Setup the rest
|
||||
BaseClass::Create( pName, pHelpString, flags );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *partial -
|
||||
// context -
|
||||
// longest -
|
||||
// maxcommands -
|
||||
// **commands -
|
||||
//-----------------------------------------------------------------------------
|
||||
int ConCommand::AutoCompleteSuggest( char const *partial, char commands[ COMMAND_COMPLETION_MAXITEMS ][ COMMAND_COMPLETION_ITEM_LENGTH ] )
|
||||
{
|
||||
Assert( m_fnCompletionCallback );
|
||||
if ( !m_fnCompletionCallback )
|
||||
return 0;
|
||||
|
||||
return ( m_fnCompletionCallback )( partial, commands );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConCommand::CanAutoComplete( void )
|
||||
{
|
||||
return m_bHasCompletionCallback;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// ConVar.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
ConVar::ConVar( char const *pName, char const *pDefaultValue, int flags /* = 0 */ )
|
||||
{
|
||||
Create( pName, pDefaultValue, flags );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// ConVar.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
ConVar::ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString )
|
||||
{
|
||||
Create( pName, pDefaultValue, flags, pHelpString );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// ConVar.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
ConVar::ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax )
|
||||
{
|
||||
Create( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// ConVar.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
ConVar::ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, FnChangeCallback callback )
|
||||
{
|
||||
Create( pName, pDefaultValue, flags, pHelpString, false, 0.0, false, 0.0, callback );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------- //
|
||||
// ConVar.
|
||||
// ----------------------------------------------------------------------------- //
|
||||
ConVar::ConVar( char const *pName, char const *pDefaultValue, int flags, char const *pHelpString, bool bMin, float fMin, bool bMax, float fMax, FnChangeCallback callback )
|
||||
{
|
||||
Create( pName, pDefaultValue, flags, pHelpString, bMin, fMin, bMax, fMax, callback );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Free dynamic memory
|
||||
//-----------------------------------------------------------------------------
|
||||
ConVar::~ConVar( void )
|
||||
{
|
||||
if ( m_pszString )
|
||||
{
|
||||
delete[] m_pszString;
|
||||
m_pszString = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Install a change callback (there shouldn't already be one....)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ConVar::InstallChangeCallback( FnChangeCallback callback )
|
||||
{
|
||||
Assert( !m_fnChangeCallback || !callback );
|
||||
m_fnChangeCallback = callback;
|
||||
|
||||
if (m_fnChangeCallback)
|
||||
{
|
||||
// Call it immediately to set the initial value...
|
||||
m_fnChangeCallback( this, m_pszString );
|
||||
}
|
||||
}
|
||||
|
||||
bool ConVar::IsBitSet( int flag ) const
|
||||
{
|
||||
return ( flag & m_pParent->m_nFlags ) ? true : false;
|
||||
}
|
||||
|
||||
char const *ConVar::GetHelpText( void ) const
|
||||
{
|
||||
return m_pParent->m_pszHelpString;
|
||||
}
|
||||
|
||||
void ConVar::AddFlags( int flags )
|
||||
{
|
||||
m_pParent->m_nFlags |= flags;
|
||||
}
|
||||
|
||||
bool ConVar::IsRegistered( void ) const
|
||||
{
|
||||
return m_pParent->m_bRegistered;
|
||||
}
|
||||
|
||||
char const *ConVar::GetName( void ) const
|
||||
{
|
||||
return m_pParent->m_pszName;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : Returns true on success, false on failure.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::IsCommand( void ) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input :
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::Init()
|
||||
{
|
||||
BaseClass::Init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::InternalSetValue( char const *value )
|
||||
{
|
||||
float fNewValue;
|
||||
char tempVal[ 32 ];
|
||||
char *val;
|
||||
|
||||
Assert(m_pParent == this); // Only valid for root convars.
|
||||
|
||||
val = (char *)value;
|
||||
fNewValue = ( float )atof( value );
|
||||
|
||||
if ( ClampValue( fNewValue ) )
|
||||
{
|
||||
Q_snprintf( tempVal,sizeof(tempVal), "%f", fNewValue );
|
||||
val = tempVal;
|
||||
}
|
||||
|
||||
// Redetermine value
|
||||
m_fValue = fNewValue;
|
||||
m_nValue = ( int )( m_fValue );
|
||||
|
||||
if ( !(m_nFlags & FCVAR_NEVER_AS_STRING) )
|
||||
ChangeStringValue( val );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *tempVal -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::ChangeStringValue( char const *tempVal )
|
||||
{
|
||||
Assert( !( m_nFlags & FCVAR_NEVER_AS_STRING ) );
|
||||
|
||||
char* pszOldValue = (char*)stackalloc( m_StringLength );
|
||||
|
||||
if ( m_fnChangeCallback )
|
||||
{
|
||||
memcpy( pszOldValue, m_pszString, m_StringLength );
|
||||
}
|
||||
|
||||
int len = Q_strlen(tempVal) + 1;
|
||||
|
||||
if ( len > m_StringLength)
|
||||
{
|
||||
if (m_pszString)
|
||||
delete[] m_pszString;
|
||||
|
||||
m_pszString = new char[len];
|
||||
m_StringLength = len;
|
||||
}
|
||||
|
||||
memcpy( m_pszString, tempVal, len );
|
||||
|
||||
// Invoke any necessary callback function
|
||||
if ( m_fnChangeCallback )
|
||||
{
|
||||
m_fnChangeCallback( this, pszOldValue );
|
||||
}
|
||||
|
||||
stackfree( pszOldValue );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Check whether to clamp and then perform clamp
|
||||
// Input : value -
|
||||
// Output : Returns true if value changed
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::ClampValue( float& value )
|
||||
{
|
||||
if ( m_bHasMin && ( value < m_fMinVal ) )
|
||||
{
|
||||
value = m_fMinVal;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( m_bHasMax && ( value > m_fMaxVal ) )
|
||||
{
|
||||
value = m_fMaxVal;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::InternalSetFloatValue( float fNewValue )
|
||||
{
|
||||
if ( fNewValue == m_fValue )
|
||||
return;
|
||||
|
||||
Assert( m_pParent == this ); // Only valid for root convars.
|
||||
|
||||
// Check bounds
|
||||
ClampValue( fNewValue );
|
||||
|
||||
// Redetermine value
|
||||
m_fValue = fNewValue;
|
||||
m_nValue = ( int )m_fValue;
|
||||
|
||||
if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) )
|
||||
{
|
||||
char tempVal[ 32 ];
|
||||
Q_snprintf( tempVal, sizeof( tempVal), "%f", m_fValue );
|
||||
ChangeStringValue( tempVal );
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( !m_fnChangeCallback );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::InternalSetIntValue( int nValue )
|
||||
{
|
||||
if ( nValue == m_nValue )
|
||||
return;
|
||||
|
||||
Assert( m_pParent == this ); // Only valid for root convars.
|
||||
|
||||
float fValue = (float)nValue;
|
||||
if ( ClampValue( fValue ) )
|
||||
{
|
||||
nValue = ( int )( fValue );
|
||||
}
|
||||
|
||||
// Redetermine value
|
||||
m_fValue = fValue;
|
||||
m_nValue = nValue;
|
||||
|
||||
if ( !( m_nFlags & FCVAR_NEVER_AS_STRING ) )
|
||||
{
|
||||
char tempVal[ 32 ];
|
||||
Q_snprintf( tempVal, sizeof( tempVal ), "%d", m_nValue );
|
||||
ChangeStringValue( tempVal );
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( !m_fnChangeCallback );
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Private creation
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::Create( char const *pName, char const *pDefaultValue, int flags /*= 0*/,
|
||||
char const *pHelpString /*= NULL*/, bool bMin /*= false*/, float fMin /*= 0.0*/,
|
||||
bool bMax /*= false*/, float fMax /*= false*/, FnChangeCallback callback /*= NULL*/ )
|
||||
{
|
||||
static char *empty_string = "";
|
||||
|
||||
m_pParent = this;
|
||||
|
||||
// Name should be static data
|
||||
m_pszDefaultValue = pDefaultValue ? pDefaultValue : empty_string;
|
||||
Assert( pDefaultValue );
|
||||
|
||||
m_StringLength = strlen( m_pszDefaultValue ) + 1;
|
||||
m_pszString = new char[m_StringLength];
|
||||
memcpy( m_pszString, m_pszDefaultValue, m_StringLength );
|
||||
|
||||
m_bHasMin = bMin;
|
||||
m_fMinVal = fMin;
|
||||
m_bHasMax = bMax;
|
||||
m_fMaxVal = fMax;
|
||||
|
||||
m_fnChangeCallback = callback;
|
||||
|
||||
m_fValue = ( float )atof( m_pszString );
|
||||
|
||||
// Bounds Check, should never happen, if it does, no big deal
|
||||
if ( m_bHasMin && ( m_fValue < m_fMinVal ) )
|
||||
{
|
||||
Assert( 0 );
|
||||
}
|
||||
|
||||
if ( m_bHasMax && ( m_fValue > m_fMaxVal ) )
|
||||
{
|
||||
Assert( 0 );
|
||||
}
|
||||
|
||||
m_nValue = ( int )m_fValue;
|
||||
|
||||
BaseClass::Create( pName, pHelpString, flags );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue(char const *value)
|
||||
{
|
||||
ConVar *var = ( ConVar * )m_pParent;
|
||||
var->InternalSetValue( value );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue( float value )
|
||||
{
|
||||
ConVar *var = ( ConVar * )m_pParent;
|
||||
var->InternalSetFloatValue( value );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : value -
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::SetValue( int value )
|
||||
{
|
||||
ConVar *var = ( ConVar * )m_pParent;
|
||||
var->InternalSetIntValue( value );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Reset to default value
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::Revert( void )
|
||||
{
|
||||
// Force default value again
|
||||
ConVar *var = ( ConVar * )m_pParent;
|
||||
var->SetValue( var->m_pszDefaultValue );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void ConVar::RevertAll( void )
|
||||
{
|
||||
ConCommandBase *p = s_pConCommandBases;
|
||||
while ( p )
|
||||
{
|
||||
if ( !p->IsCommand() )
|
||||
{
|
||||
ConVar *var = ( ConVar * )p;
|
||||
var->Revert();
|
||||
}
|
||||
p = p->m_pNext;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : minVal -
|
||||
// Output : true if there is a min set
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::GetMin( float& minVal ) const
|
||||
{
|
||||
minVal = m_pParent->m_fMinVal;
|
||||
return m_pParent->m_bHasMin;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : maxVal -
|
||||
//-----------------------------------------------------------------------------
|
||||
bool ConVar::GetMax( float& maxVal ) const
|
||||
{
|
||||
maxVal = m_pParent->m_fMaxVal;
|
||||
return m_pParent->m_bHasMax;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : char const
|
||||
//-----------------------------------------------------------------------------
|
||||
char const *ConVar::GetDefault( void ) const
|
||||
{
|
||||
return m_pParent->m_pszDefaultValue;
|
||||
}
|
||||
|
38
sourcemm/oslink.cpp
Normal file
38
sourcemm/oslink.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Implements OS-dependant functions from oslink.h
|
||||
* @file oslink.cpp
|
||||
*/
|
||||
|
||||
#include "oslink.h"
|
||||
#ifdef __linux
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
const char *dlerror()
|
||||
{
|
||||
static char buf[1024];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, GetLastError(),
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &buf, 0, NULL);
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined __linux__
|
||||
int GetLastError()
|
||||
{
|
||||
return errno;
|
||||
}
|
||||
#endif
|
66
sourcemm/oslink.h
Normal file
66
sourcemm/oslink.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_OSLINK_H
|
||||
#define _INCLUDE_OSLINK_H
|
||||
|
||||
/**
|
||||
* @brief Defines OS-independent information
|
||||
* @file oslink.h
|
||||
*/
|
||||
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define OS_WIN32
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#define mkdir(a) _mkdir(a)
|
||||
#define dlmount(x) LoadLibrary(x)
|
||||
#define dlsym(x, s) GetProcAddress(x, s)
|
||||
#define dlclose(x) FreeLibrary(x)
|
||||
const char* dlerror();
|
||||
#elif defined __linux__
|
||||
#define OS_LINUX
|
||||
#include <dlfcn.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#define dlmount(x) dlopen(x,RTLD_NOW)
|
||||
typedef void* HINSTANCE;
|
||||
#endif
|
||||
|
||||
#if defined __linux__
|
||||
extern int errno;
|
||||
int GetLastError();
|
||||
#endif
|
||||
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
#define SMM_API extern "C" __declspec(dllexport)
|
||||
#elif defined __GNUC__
|
||||
#define SMM_API extern "C"
|
||||
#endif
|
||||
|
||||
#if defined __WIN32__ || defined _WIN32 || defined WIN32
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#elif defined __GNUC__
|
||||
# if !__GLIBC_HAVE_LONG_LONG
|
||||
typedef long long int64_t;
|
||||
# endif
|
||||
typedef unsigned long long uint64_t;
|
||||
#endif
|
||||
|
||||
#ifndef __linux__
|
||||
#define snprintf _snprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#endif //_INCLUDE_OSLINK_H
|
17
sourcemm/sample_mm/SamplePlugin.cpp
Normal file
17
sourcemm/sample_mm/SamplePlugin.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "SamplePlugin.h"
|
||||
|
||||
SamplePlugin g_SamplePlugin;
|
||||
|
||||
PLUGIN_EXPOSE(SamplePlugin, g_SamplePlugin);
|
||||
|
||||
bool SamplePlugin::Load(PluginId id, ISmmAPI *ismm, factories *list, char *error, size_t maxlen)
|
||||
{
|
||||
PLUGIN_SAVEVARS();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SamplePlugin::Unload(char *error, size_t maxlen)
|
||||
{
|
||||
return true;
|
||||
}
|
59
sourcemm/sample_mm/SamplePlugin.h
Normal file
59
sourcemm/sample_mm/SamplePlugin.h
Normal file
@ -0,0 +1,59 @@
|
||||
#ifndef _INCLUDE_SAMPLEPLUGIN_H
|
||||
#define _INCLUDE_SAMPLEPLUGIN_H
|
||||
|
||||
#include <ISmmPlugin.h>
|
||||
|
||||
class SamplePlugin : public ISmmPlugin
|
||||
{
|
||||
public:
|
||||
bool Load(PluginId id, ISmmAPI *ismm, factories *list, char *error, size_t maxlen);
|
||||
bool Unload(char *error, size_t maxlen);
|
||||
bool Pause(char *error, size_t maxlen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool Unpause(char *error, size_t maxlen)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
int GetApiVersion() { return PLAPI_VERSION; }
|
||||
public:
|
||||
const char *GetAuthor()
|
||||
{
|
||||
return "BAILOPAN";
|
||||
}
|
||||
const char *GetName()
|
||||
{
|
||||
return "Sample Plugin";
|
||||
}
|
||||
const char *GetDescription()
|
||||
{
|
||||
return "Sample plugin that hooks basic things";
|
||||
}
|
||||
const char *GetURL()
|
||||
{
|
||||
return "http://www.sourcemm.net/";
|
||||
}
|
||||
const char *GetLicense()
|
||||
{
|
||||
return "zlib/libpng";
|
||||
}
|
||||
const char *GetVersion()
|
||||
{
|
||||
return "1.00";
|
||||
}
|
||||
const char *GetDate()
|
||||
{
|
||||
return __DATE__;
|
||||
}
|
||||
const char *GetLogTag()
|
||||
{
|
||||
return "SAMPLE";
|
||||
}
|
||||
};
|
||||
|
||||
extern SamplePlugin g_SamplePlugin;
|
||||
PLUGIN_GLOBALVARS();
|
||||
|
||||
#endif //_INCLUDE_SAMPLEPLUGIN_H
|
21
sourcemm/sample_mm/sample_mm.sln
Normal file
21
sourcemm/sample_mm/sample_mm.sln
Normal file
@ -0,0 +1,21 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample_mm", "sample_mm.vcproj", "{FAFF34FB-FE14-47B5-81BD-70D237392FB2}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{FAFF34FB-FE14-47B5-81BD-70D237392FB2}.Debug.ActiveCfg = Debug|Win32
|
||||
{FAFF34FB-FE14-47B5-81BD-70D237392FB2}.Debug.Build.0 = Debug|Win32
|
||||
{FAFF34FB-FE14-47B5-81BD-70D237392FB2}.Release.ActiveCfg = Release|Win32
|
||||
{FAFF34FB-FE14-47B5-81BD-70D237392FB2}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
137
sourcemm/sample_mm/sample_mm.vcproj
Normal file
137
sourcemm/sample_mm/sample_mm.vcproj
Normal file
@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="sample_mm"
|
||||
ProjectGUID="{FAFF34FB-FE14-47B5-81BD-70D237392FB2}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/sample_mm.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/sample_mm.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/sample_mm.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SAMPLE_MM_EXPORTS"
|
||||
RuntimeLibrary="4"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)/sample_mm.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
ImportLibrary="$(OutDir)/sample_mm.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\SamplePlugin.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath=".\SamplePlugin.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
379
sourcemm/sourcemm.cpp
Normal file
379
sourcemm/sourcemm.cpp
Normal file
@ -0,0 +1,379 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* Contributor(s): Scott "Damaged Soul" Ehlert
|
||||
* : Pavol "PM OnoTo" Marko
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#include "sourcemm.h"
|
||||
#include "CServerGameDLL.h"
|
||||
#include "CServerGameEnts.h"
|
||||
#include "CServerGameClients.h"
|
||||
#include "CHLTVDirector.h"
|
||||
#include "concommands.h"
|
||||
|
||||
/**
|
||||
* @brief Implementation of main SourceMM GameDLL functionality
|
||||
* @file sourcemm.cpp
|
||||
*/
|
||||
|
||||
CServerGameDLL *g_TempGameDLL = NULL;
|
||||
CServerGameEnts *g_TempGameEnts = NULL;
|
||||
CServerGameClients *g_TempGameClients = NULL;
|
||||
CHLTVDirector *g_TempDirector = NULL;
|
||||
GameDllInfo g_GameDll = {false, NULL, NULL};
|
||||
EngineInfo g_Engine = {NULL, NULL, NULL, NULL};
|
||||
SourceHook::CSourceHookImpl g_SourceHook;
|
||||
std::string g_ModPath;
|
||||
std::string g_BinPath;
|
||||
|
||||
///////////////////////////////////
|
||||
// Main code for HL2 Interaction //
|
||||
///////////////////////////////////
|
||||
|
||||
//This is where the magic happens
|
||||
SMM_API void *CreateInterface(const char *name, int *ret)
|
||||
{
|
||||
if (!g_GameDll.loaded)
|
||||
{
|
||||
//State of the Mod:
|
||||
// Currently, HL2 Engine has loaded Metamod:Source
|
||||
// It is now asking it to get an interface. We don't have one,
|
||||
// so we're gonna try to give it a fake one to get the information we need.
|
||||
// Then we'll swap the vtables with the real one from the real gamedll.
|
||||
|
||||
if (strcmp(name, INTERFACEVERSION_SERVERGAMEDLL) == 0)
|
||||
{
|
||||
//We're in. Give the server our fake class as bait.
|
||||
if (ret)
|
||||
*ret = IFACE_OK;
|
||||
|
||||
g_TempGameDLL = new CServerGameDLL;
|
||||
|
||||
return static_cast<void *>(g_TempGameDLL);
|
||||
} else if (strcmp(name, INTERFACEVERSION_SERVERGAMEENTS) == 0) {
|
||||
if (ret)
|
||||
*ret = IFACE_OK;
|
||||
|
||||
g_TempGameEnts = new CServerGameEnts;
|
||||
|
||||
return static_cast<void *>(g_TempGameEnts);
|
||||
} else if (strcmp(name, INTERFACEVERSION_SERVERGAMECLIENTS) == 0) {
|
||||
if (ret)
|
||||
*ret = IFACE_OK;
|
||||
|
||||
g_TempGameClients = new CServerGameClients;
|
||||
|
||||
return static_cast<void *>(g_TempGameClients);
|
||||
} else if (strcmp(name, INTERFACEVERSION_HLTVDIRECTOR) == 0) {
|
||||
if (ret)
|
||||
*ret = IFACE_OK;
|
||||
|
||||
g_TempDirector = new CHLTVDirector;
|
||||
|
||||
return static_cast<void *>(g_TempDirector);
|
||||
} else {
|
||||
if (ret)
|
||||
*ret = IFACE_FAILED;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
void *d = (g_GameDll.factory)(name, ret);
|
||||
|
||||
return d;
|
||||
}
|
||||
}
|
||||
|
||||
bool CServerGameDLL::DLLInit(CreateInterfaceFn engineFactory, CreateInterfaceFn physicsFactory, CreateInterfaceFn fileSystemFactory, CGlobalVars *pGlobals)
|
||||
{
|
||||
if (!g_GameDll.loaded)
|
||||
{
|
||||
//The gamedll isn't loaded yet. We need to find out where it's hiding.
|
||||
IVEngineServer *ive = (IVEngineServer *)((engineFactory)(INTERFACEVERSION_VENGINESERVER, NULL));
|
||||
if (!ive)
|
||||
{
|
||||
Error("Metamod:Source could not load %s", INTERFACEVERSION_VENGINESERVER);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Guess the file name
|
||||
//We'll have better heurestics[sp?] later on
|
||||
char mod_path[128], full_path[255];
|
||||
ive->GetGameDir(mod_path, sizeof(mod_path)-1);
|
||||
g_ModPath.assign(mod_path);
|
||||
#if defined WIN32 || defined _WIN32
|
||||
snprintf(full_path, sizeof(full_path)-1, "%s\\bin\\server.dll", mod_path);
|
||||
#else
|
||||
snprintf(full_path, sizeof(full_path)-1, "%s/bin/server_i486.so", mod_path);
|
||||
#endif
|
||||
|
||||
g_BinPath.assign(full_path);
|
||||
|
||||
//See if the file even exists
|
||||
FILE *fp = fopen(g_BinPath.c_str(), "r");
|
||||
if (!fp)
|
||||
{
|
||||
Error("Metamod:Source could not read %s", g_BinPath.c_str());
|
||||
return false;
|
||||
}
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
|
||||
//Load the DLL
|
||||
g_GameDll.lib = dlmount(g_BinPath.c_str());
|
||||
if (!g_GameDll.lib)
|
||||
{
|
||||
Error("Metamod:Source could not load GameDLL: %s", dlerror());
|
||||
return false;
|
||||
} else {
|
||||
//Find its factory
|
||||
g_GameDll.factory = (CreateInterfaceFn)(dlsym(g_GameDll.lib, "CreateInterface"));
|
||||
if (!g_GameDll.factory)
|
||||
{
|
||||
Error("Metamod:Source could not find an entry point in GameDLL: %s", g_BinPath.c_str());
|
||||
dlclose(g_GameDll.lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Find the new IServerGameDLL pointer
|
||||
IServerGameDLL *serverDll;
|
||||
serverDll = (IServerGameDLL *)((g_GameDll.factory)(INTERFACEVERSION_SERVERGAMEDLL, NULL));
|
||||
if (!serverDll)
|
||||
{
|
||||
Error("Metamod:Source could not find %s in GameDLL: %s", INTERFACEVERSION_SERVERGAMEDLL, g_BinPath.c_str());
|
||||
dlclose(g_GameDll.lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Set this information early in case our wrappers are called somehow
|
||||
g_Engine.engineFactory = engineFactory;
|
||||
g_Engine.icvar = (ICvar *)(g_Engine.engineFactory)(VENGINE_CVAR_INTERFACE_VERSION, NULL);
|
||||
if (!g_Engine.icvar)
|
||||
{
|
||||
Error("Metamod:Source could not find %s in engine!", VENGINE_CVAR_INTERFACE_VERSION);
|
||||
dlclose(g_GameDll.lib);
|
||||
return false;
|
||||
}
|
||||
g_Engine.fileSystemFactory = fileSystemFactory;
|
||||
g_Engine.pGlobals = pGlobals;
|
||||
g_Engine.physicsFactory = physicsFactory;
|
||||
g_Engine.engine = ive;
|
||||
|
||||
//Attempt to load the GameDLL
|
||||
// Note that nothing will be intercepting yet.
|
||||
// This is the one and only call that plugins have no chance of seeing.
|
||||
// Likewise, you won't be able to trick the Server DLL into loading random things.
|
||||
// Luckily, because of SourceHook, this really isn't a problem - you can change
|
||||
// the virtual interfaces in anything it requests.
|
||||
if (!serverDll->DLLInit(EngineFactory, PhysicsFactory, FileSystemFactory, pGlobals))
|
||||
{
|
||||
//For some reason, the GameDLL failed to load.
|
||||
Error("Metamod:Source: GameDLL %s refused to load.", g_BinPath.c_str());
|
||||
dlclose(g_GameDll.lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
IServerGameEnts *serverEnts;
|
||||
IServerGameClients *serverClients;
|
||||
IHLTVDirector *serverHLTV;
|
||||
|
||||
serverEnts = (IServerGameEnts *)((g_GameDll.factory)(INTERFACEVERSION_SERVERGAMEENTS, NULL));
|
||||
if (!serverEnts)
|
||||
{
|
||||
Error("Metamod:Source could not find %s in GameDLL: %s", INTERFACEVERSION_SERVERGAMEENTS, g_BinPath.c_str());
|
||||
dlclose(g_GameDll.lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
serverClients = (IServerGameClients *)((g_GameDll.factory)(INTERFACEVERSION_SERVERGAMECLIENTS, NULL));
|
||||
if (!serverClients)
|
||||
{
|
||||
Error("Metamod:Source could not find %s in GameDLL: %s", INTERFACEVERSION_SERVERGAMECLIENTS, g_BinPath.c_str());
|
||||
dlclose(g_GameDll.lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
serverHLTV = (IHLTVDirector *)((g_GameDll.factory)(INTERFACEVERSION_HLTVDIRECTOR, NULL));
|
||||
if (!serverHLTV)
|
||||
{
|
||||
Error("Metamod:Source could not find %s in GameDLL: %s", INTERFACEVERSION_HLTVDIRECTOR, g_BinPath.c_str());
|
||||
dlclose(g_GameDll.lib);
|
||||
return false;
|
||||
}
|
||||
|
||||
//The GameDLL has given the go - now we'll swap the vtables ( eww! )
|
||||
//This ugly hack will patch the pointer we've given the engine
|
||||
// so it will just be calling the real GameDLL instead.
|
||||
// Unlike Metamod:HL1, this is the effect we want, rather than duplicating
|
||||
// the entire class (because SourceHook doesn't do that).
|
||||
void *vtableDst = ((void *)(g_TempGameDLL));
|
||||
void *vtableSrc = ((void *)(serverDll));
|
||||
|
||||
SourceHook::SetMemAccess(vtableDst, sizeof(IServerGameDLL), SH_MEM_READ|SH_MEM_WRITE);
|
||||
memcpy(vtableDst, vtableSrc, sizeof(IServerGameDLL));
|
||||
|
||||
//Now patch IServerGameEnts
|
||||
vtableDst = ((void *)(g_TempGameEnts));
|
||||
vtableSrc = ((void *)(serverEnts));
|
||||
SourceHook::SetMemAccess(vtableDst, sizeof(IServerGameEnts), SH_MEM_READ|SH_MEM_WRITE);
|
||||
memcpy(vtableDst, vtableSrc, sizeof(IServerGameEnts));
|
||||
|
||||
//Now patch IServerGameClients
|
||||
vtableDst = ((void *)(g_TempGameClients));
|
||||
vtableSrc = ((void *)(serverClients));
|
||||
SourceHook::SetMemAccess(vtableDst, sizeof(IServerGameClients), SH_MEM_READ|SH_MEM_WRITE);
|
||||
memcpy(vtableDst, vtableSrc, sizeof(IServerGameClients));
|
||||
|
||||
//Now patch IHLTVDirector
|
||||
vtableDst = ((void *)(g_TempDirector));
|
||||
vtableSrc = ((void *)(serverHLTV));
|
||||
SourceHook::SetMemAccess(vtableDst, sizeof(IHLTVDirector), SH_MEM_READ|SH_MEM_WRITE);
|
||||
memcpy(vtableDst, vtableSrc, sizeof(IHLTVDirector));
|
||||
|
||||
//Everything's done.
|
||||
g_GameDll.loaded = true;
|
||||
|
||||
//Initialize our console hooks
|
||||
ConCommandBaseMgr::OneTimeInit(static_cast<IConCommandBaseAccessor *>(&g_SMConVarAccessor));
|
||||
|
||||
//Now it's safe to load plugins.
|
||||
#if defined WIN32 || defined _WIN32
|
||||
snprintf(full_path, sizeof(full_path)-1, "%s\\%s", g_ModPath.c_str(), "metaplugins.ini");
|
||||
#else
|
||||
snprintf(full_path, sizeof(full_path)-1, "%s/%s", g_ModPath.c_str(), "metaplugins.ini");
|
||||
#endif
|
||||
|
||||
LoadPluginsFromFile(full_path);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Somehow, the function got here. This should be impossible, as not only is it
|
||||
// only called once, but the vtables should be overridden.
|
||||
Error("Metamod:Source fatal error - IServerGameDLL::DLLInit() called inappropriately");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int LoadPluginsFromFile(const char *file)
|
||||
{
|
||||
FILE *fp;
|
||||
int total = 0, skipped=0;
|
||||
PluginId id;
|
||||
bool already;
|
||||
|
||||
fp = fopen(file, "rt");
|
||||
if (!fp)
|
||||
{
|
||||
LogMessage("[META] Could not open plugins file %s\n", file);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char buffer[255], error[255], full_path[128];
|
||||
const char *ptr, *ext;
|
||||
while (!feof(fp))
|
||||
{
|
||||
buffer[0] = '\0';
|
||||
fgets(buffer, sizeof(buffer)-1, fp);
|
||||
if (buffer[0] == ';' || strncmp(buffer, "//", 2) == 0)
|
||||
continue;
|
||||
//First find if it's an absolute path or not...
|
||||
if (buffer[0] == '/' || strncmp(&(buffer[1]), ":\\", 2) == 0)
|
||||
{
|
||||
//If we're in an absolute path, ignore our normal heuristics
|
||||
id = g_PluginMngr.Load(buffer, Pl_File, already, error, sizeof(error)-1);
|
||||
if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused)
|
||||
{
|
||||
LogMessage("[META] Failed to load plugin %s. %s", buffer, error);
|
||||
} else {
|
||||
if (already)
|
||||
skipped++;
|
||||
else
|
||||
total++;
|
||||
}
|
||||
} else {
|
||||
//Attempt to find a file extension
|
||||
ptr = UTIL_GetExtension(buffer);
|
||||
//Add an extension if there's none there
|
||||
if (!ptr)
|
||||
{
|
||||
#if defined WIN32 || defined _WIN32
|
||||
ext = ".dll";
|
||||
#else
|
||||
ext = "_i486.so";
|
||||
#endif
|
||||
} else {
|
||||
ext = "";
|
||||
}
|
||||
//Format the new path
|
||||
#if defined WIN32 || defined _WIN32
|
||||
snprintf(full_path, sizeof(full_path)-1, "%s\\%s%s", g_ModPath.c_str(), buffer, ext);
|
||||
#else
|
||||
snprintf(full_path, sizeof(full_path)-1, "%s/%s%s", g_ModPath.c_str(), buffer, ext);
|
||||
#endif
|
||||
id = g_PluginMngr.Load(full_path, Pl_File, already, error, sizeof(error)-1);
|
||||
if (id < Pl_MinId || g_PluginMngr.FindById(id)->m_Status < Pl_Paused)
|
||||
{
|
||||
LogMessage("[META] Failed to load plugin %s. %s", buffer, error);
|
||||
} else {
|
||||
if (already)
|
||||
skipped++;
|
||||
else
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
if (skipped)
|
||||
{
|
||||
LogMessage("[META] Loaded %d plugins from file (%d already loaded)", total, skipped);
|
||||
} else {
|
||||
LogMessage("[META] Loaded %d plugins from file.", total);
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
//Wrapper function. This is called when the GameDLL thinks it's using
|
||||
// the engine's real engineFactory.
|
||||
void *EngineFactory(const char *name, int *ret)
|
||||
{
|
||||
return (g_Engine.engineFactory)(name, ret);
|
||||
}
|
||||
|
||||
//Wrapper function. This is called when the GameDLL thinks it's using
|
||||
// the engine's real physicsFactory.
|
||||
void *PhysicsFactory(const char *name, int *ret)
|
||||
{
|
||||
return (g_Engine.physicsFactory)(name, ret);
|
||||
}
|
||||
|
||||
//Wrapper function. This is called when the GameDLL thinks it's using
|
||||
// the engine's real fileSystemFactory.
|
||||
void *FileSystemFactory(const char *name, int *ret)
|
||||
{
|
||||
return (g_Engine.fileSystemFactory)(name, ret);
|
||||
}
|
||||
|
||||
void LogMessage(const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
static char buffer[2048];
|
||||
|
||||
buffer[0] = '\0';
|
||||
|
||||
va_start(ap, msg);
|
||||
vsnprintf(buffer, sizeof(buffer)-5, msg, ap);
|
||||
strcat(buffer, "\n");
|
||||
va_end(ap);
|
||||
|
||||
g_Engine.engine->LogPrint(buffer);
|
||||
}
|
86
sourcemm/sourcemm.h
Normal file
86
sourcemm/sourcemm.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMM_H
|
||||
#define _INCLUDE_SOURCEMM_H
|
||||
|
||||
/**
|
||||
* @brief SourceMM main functionality for GameDLL interception
|
||||
* @file sourcemm.h
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <interface.h>
|
||||
#include <eiface.h>
|
||||
#include <sourcehook/sourcehook_impl.h>
|
||||
#include <sourcehook/sourcehook.h>
|
||||
#include "ISmmAPI.h"
|
||||
#include "CPlugin.h"
|
||||
#include "oslink.h"
|
||||
#include "util.h"
|
||||
|
||||
#define SOURCEMM_VERSION "1.00"
|
||||
#define SOURCEMM_DATE __DATE__
|
||||
|
||||
/**
|
||||
* @brief Entry point for HL2 Engine
|
||||
*/
|
||||
SMM_API void *CreateInterface(const char *name, int *code);
|
||||
|
||||
/** @brief Wrapper to catch GameDLL calls */
|
||||
void *EngineFactory(const char *name, int *code);
|
||||
|
||||
/** @brief Wrapper to catch GameDLL calls */
|
||||
void *PhysicsFactory(const char *name, int *code);
|
||||
|
||||
/** @brief Wrapper to catch GameDLL calls */
|
||||
void *FileSystemFactory(const char *name, int *code);
|
||||
|
||||
/** @brief Loads all plugins found in a file */
|
||||
int LoadPluginsFromFile(const char *file);
|
||||
|
||||
/** @brief Logs a message to the standard log file */
|
||||
void LogMessage(const char *msg, ...);
|
||||
|
||||
/** @brief Stores information about the GameDLL */
|
||||
struct GameDllInfo
|
||||
{
|
||||
bool loaded;
|
||||
HINSTANCE lib;
|
||||
CreateInterfaceFn factory;
|
||||
};
|
||||
|
||||
/** @brief Stores information about the HL2 Engine pointers */
|
||||
struct EngineInfo
|
||||
{
|
||||
CreateInterfaceFn engineFactory;
|
||||
CreateInterfaceFn physicsFactory;
|
||||
CreateInterfaceFn fileSystemFactory;
|
||||
CGlobalVars *pGlobals;
|
||||
ICvar *icvar;
|
||||
IVEngineServer *engine;
|
||||
};
|
||||
|
||||
/** @brief Global variable for GameDLL info */
|
||||
extern GameDllInfo g_GameDll;
|
||||
|
||||
/** @brief Global variable for Engine info */
|
||||
extern EngineInfo g_Engine;
|
||||
|
||||
/** @brief Global singleton for SourceHook */
|
||||
extern SourceHook::CSourceHookImpl g_SourceHook;
|
||||
|
||||
/** @brief Mod path (important!)*/
|
||||
extern std::string g_ModPath;
|
||||
|
||||
/** @brief Path to server binary */
|
||||
extern std::string g_BinPath;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMM_H
|
21
sourcemm/sourcemm.sln
Normal file
21
sourcemm/sourcemm.sln
Normal file
@ -0,0 +1,21 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 8.00
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sourcemm", "sourcemm.vcproj", "{F7D47743-73B3-49B5-9D76-2333C5DFD565}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfiguration) = preSolution
|
||||
Debug = Debug
|
||||
Release = Release
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfiguration) = postSolution
|
||||
{F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug.ActiveCfg = Debug|Win32
|
||||
{F7D47743-73B3-49B5-9D76-2333C5DFD565}.Debug.Build.0 = Debug|Win32
|
||||
{F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release.ActiveCfg = Release|Win32
|
||||
{F7D47743-73B3-49B5-9D76-2333C5DFD565}.Release.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityAddIns) = postSolution
|
||||
EndGlobalSection
|
||||
EndGlobal
|
233
sourcemm/sourcemm.vcproj
Normal file
233
sourcemm/sourcemm.vcproj
Normal file
@ -0,0 +1,233 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="sourcemm"
|
||||
ProjectGUID="{F7D47743-73B3-49B5-9D76-2333C5DFD565}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="tier0.lib"
|
||||
OutputFile="$(OutDir)/sourcemm.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="TRUE"
|
||||
ProgramDatabaseFile="$(OutDir)/sourcemm.pdb"
|
||||
SubSystem="2"
|
||||
ImportLibrary="$(OutDir)/sourcemm.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
FavorSizeOrSpeed="1"
|
||||
OmitFramePointers="TRUE"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SOURCEMM_EXPORTS"
|
||||
StringPooling="TRUE"
|
||||
ExceptionHandling="TRUE"
|
||||
RuntimeLibrary="4"
|
||||
BufferSecurityCheck="FALSE"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="FALSE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="tier0.lib vstdlib.lib"
|
||||
OutputFile="$(OutDir)/server.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="TRUE"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
ImportLibrary="$(OutDir)/sourcemm.lib"
|
||||
TargetMachine="1"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\concommands.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CPlugin.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CSmmAPI.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\oslink.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sourcemm.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\util.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath=".\CHLTVDirector.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CISmmAPI.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\concommands.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CPlugin.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CServerGameClients.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CServerGameDLL.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\CServerGameEnts.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\oslink.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\sourcemm.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\util.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Interfaces"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\IPluginManager.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ISmmAPI.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ISmmPlugin.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="SourceHook"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\sourcehook\sourcehook.cpp">
|
||||
</File>
|
||||
<Filter
|
||||
Name="Headers"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath="..\sourcehook\FastDelegate.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sourcehook\sh_memfuncinfo.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sourcehook\sh_memory.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sourcehook\sourcehook.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sourcehook\sourcehook_impl.h">
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="HL2SDK"
|
||||
Filter="">
|
||||
<File
|
||||
RelativePath=".\convar.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
39
sourcemm/util.cpp
Normal file
39
sourcemm/util.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "util.h"
|
||||
|
||||
/**
|
||||
* @brief Utility functons
|
||||
* @file util.cpp
|
||||
*/
|
||||
|
||||
/* UTIL_GetExtension
|
||||
* Returns a pointer to the extension in a file name
|
||||
*/
|
||||
const char *UTIL_GetExtension(const char *file)
|
||||
{
|
||||
int len = strlen(file);
|
||||
int i = 0;
|
||||
|
||||
for (i=len-1; i>=0; i--)
|
||||
{
|
||||
if (file[i] == '/' || file[i] == '\\')
|
||||
return NULL;
|
||||
|
||||
if ((file[i] == '.') && (i != len-1))
|
||||
{
|
||||
return (const char *)&(file[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
21
sourcemm/util.h
Normal file
21
sourcemm/util.h
Normal file
@ -0,0 +1,21 @@
|
||||
/* ======== SourceMM ========
|
||||
* Copyright (C) 2004-2005 SourceMM Development Team
|
||||
* No warranties of any kind
|
||||
*
|
||||
* License: zlib/libpng
|
||||
*
|
||||
* Author(s): David "BAILOPAN" Anderson
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_UTIL_H
|
||||
#define _INCLUDE_UTIL_H
|
||||
|
||||
/**
|
||||
* @brief Utility functons
|
||||
* @file util.h
|
||||
*/
|
||||
|
||||
const char *UTIL_GetExtension(const char *file);
|
||||
|
||||
#endif //_INCLUDE_UTIL_H
|
Loading…
Reference in New Issue
Block a user