Spring Cleaning, Part Ichi (1)
Various minor things done to project files Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way) Updated regex project file and makefile --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401971
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,195 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_SYSTEM_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_SYSTEM_H_
|
||||
|
||||
#include <IExtensionSys.h>
|
||||
#include <ILibrarySys.h>
|
||||
#include <sh_list.h>
|
||||
#include <sh_string.h>
|
||||
#include <sm_trie_tpl.h>
|
||||
#include "sm_globals.h"
|
||||
#include "ShareSys.h"
|
||||
#include <ISmmAPI.h>
|
||||
#include <IPluginSys.h>
|
||||
#include <IRootConsoleMenu.h>
|
||||
#include "PluginSys.h"
|
||||
|
||||
using namespace SourceMod;
|
||||
using namespace SourceHook;
|
||||
|
||||
class CExtension;
|
||||
|
||||
struct sm_extnative_t
|
||||
{
|
||||
CExtension *owner;
|
||||
const sp_nativeinfo_t *info;
|
||||
};
|
||||
|
||||
/* Replacement native */
|
||||
struct sm_repnative_t
|
||||
{
|
||||
CExtension *owner;
|
||||
sp_nativeinfo_t info;
|
||||
SPVM_NATIVE_FUNC original;
|
||||
};
|
||||
|
||||
class CExtension : public IExtension
|
||||
{
|
||||
friend class CExtensionManager;
|
||||
public:
|
||||
virtual ~CExtension();
|
||||
public: //IExtension
|
||||
IExtensionInterface *GetAPI();
|
||||
const char *GetFilename();
|
||||
IdentityToken_t *GetIdentity();
|
||||
ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface);
|
||||
bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface);
|
||||
void FreeDependencyIterator(ITERATOR *iter);
|
||||
bool IsRunning(char *error, size_t maxlength);
|
||||
public:
|
||||
void SetError(const char *error);
|
||||
void AddDependency(IfaceInfo *pInfo);
|
||||
void AddChildDependent(CExtension *pOther, SMInterface *iface);
|
||||
void AddInterface(SMInterface *pInterface);
|
||||
void AddPlugin(IPlugin *pPlugin);
|
||||
void RemovePlugin(IPlugin *pPlugin);
|
||||
void MarkAllLoaded();
|
||||
void AddLibrary(const char *library);
|
||||
public:
|
||||
virtual bool Load(char *error, size_t maxlength);
|
||||
virtual bool IsLoaded() =0;
|
||||
virtual void Unload() =0;
|
||||
protected:
|
||||
void Initialize(const char *filename, const char *path);
|
||||
bool PerformAPICheck(char *error, size_t maxlength);
|
||||
void CreateIdentity();
|
||||
void DestroyIdentity();
|
||||
protected:
|
||||
IdentityToken_t *m_pIdentToken;
|
||||
IExtensionInterface *m_pAPI;
|
||||
String m_File;
|
||||
String m_Path;
|
||||
String m_Error;
|
||||
List<IfaceInfo> m_Deps; /** Dependencies */
|
||||
List<IfaceInfo> m_ChildDeps; /** Children who might depend on us */
|
||||
List<SMInterface *> m_Interfaces;
|
||||
List<IPlugin *> m_Plugins;
|
||||
List<const sp_nativeinfo_t *> m_Natives;
|
||||
List<WeakNative> m_WeakNatives;
|
||||
List<WeakNative> m_ReplacedNatives;
|
||||
List<String> m_Libraries;
|
||||
unsigned int unload_code;
|
||||
bool m_bFullyLoaded;
|
||||
};
|
||||
|
||||
class CLocalExtension : public CExtension
|
||||
{
|
||||
public:
|
||||
CLocalExtension(const char *filename);
|
||||
public:
|
||||
bool Load(char *error, size_t maxlength);
|
||||
bool IsLoaded();
|
||||
void Unload();
|
||||
bool IsExternal();
|
||||
private:
|
||||
PluginId m_PlId;
|
||||
ILibrary *m_pLib;
|
||||
};
|
||||
|
||||
class CRemoteExtension : public CExtension
|
||||
{
|
||||
public:
|
||||
CRemoteExtension(IExtensionInterface *pAPI, const char *filename, const char *path);
|
||||
public:
|
||||
bool Load(char *error, size_t maxlength);
|
||||
bool IsLoaded();
|
||||
void Unload();
|
||||
bool IsExternal();
|
||||
};
|
||||
|
||||
class CExtensionManager :
|
||||
public IExtensionManager,
|
||||
public SMGlobalClass,
|
||||
public IPluginsListener,
|
||||
public IRootConsoleCommand
|
||||
{
|
||||
public:
|
||||
CExtensionManager();
|
||||
~CExtensionManager();
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
public: //IExtensionManager
|
||||
IExtension *LoadExtension(const char *path,
|
||||
char *error,
|
||||
size_t maxlength);
|
||||
bool UnloadExtension(IExtension *pExt);
|
||||
IExtension *FindExtensionByFile(const char *file);
|
||||
IExtension *FindExtensionByName(const char *ext);
|
||||
IExtension *LoadExternal(IExtensionInterface *pInterface,
|
||||
const char *filepath,
|
||||
const char *filename,
|
||||
char *error,
|
||||
size_t maxlength);
|
||||
public: //IPluginsListener
|
||||
void OnPluginDestroyed(IPlugin *plugin);
|
||||
public: //IRootConsoleCommand
|
||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
||||
public:
|
||||
IExtension *LoadAutoExtension(const char *path);
|
||||
void BindDependency(IExtension *pOwner, IfaceInfo *pInfo);
|
||||
void AddInterface(IExtension *pOwner, SMInterface *pInterface);
|
||||
void BindChildPlugin(IExtension *pParent, IPlugin *pPlugin);
|
||||
void AddNatives(IExtension *pOwner, const sp_nativeinfo_t *natives);
|
||||
void BindAllNativesToPlugin(IPlugin *pPlugin);
|
||||
void MarkAllLoaded();
|
||||
void AddDependency(IExtension *pSource, const char *file, bool required, bool autoload);
|
||||
void TryAutoload();
|
||||
void AddLibrary(IExtension *pSource, const char *library);
|
||||
bool LibraryExists(const char *library);
|
||||
void OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives);
|
||||
public:
|
||||
CExtension *GetExtensionFromIdent(IdentityToken_t *ptr);
|
||||
void Shutdown();
|
||||
private:
|
||||
CExtension *FindByOrder(unsigned int num);
|
||||
private:
|
||||
List<CExtension *> m_Libs;
|
||||
List<sm_repnative_t> m_RepNativeList;
|
||||
KTrie<sm_repnative_t> m_RepNatives;
|
||||
KTrie<sm_extnative_t> m_ExtNatives;
|
||||
};
|
||||
|
||||
extern CExtensionManager g_Extensions;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_EXTENSION_SYSTEM_H_
|
||||
@@ -0,0 +1,732 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "ForwardSys.h"
|
||||
#include "PluginSys.h"
|
||||
#include "ShareSys.h"
|
||||
#include "DebugReporter.h"
|
||||
|
||||
CForwardManager g_Forwards;
|
||||
|
||||
/**
|
||||
* Genesis turns to its source, reduction occurs stepwise although the essence is all one.
|
||||
* End of line. FTL system check.
|
||||
*
|
||||
* :TODO: WHAT NEEDS TO BE TESTED IN THIS BEAST
|
||||
* VARARG FUNCTIONS:
|
||||
* - Pushing no varargs
|
||||
*/
|
||||
|
||||
// :TODO: IMPORTANT!!! The result pointer arg in the execute function maybe invalid if the forward fails
|
||||
// so later evaluation of this result may cause problems on higher levels of abstraction. DOCUMENT OR FIX ALL FORWARDS!
|
||||
|
||||
CForwardManager::~CForwardManager()
|
||||
{
|
||||
CStack<CForward *>::iterator iter;
|
||||
for (iter=m_FreeForwards.begin(); iter!=m_FreeForwards.end(); iter++)
|
||||
{
|
||||
delete (*iter);
|
||||
}
|
||||
m_FreeForwards.popall();
|
||||
}
|
||||
|
||||
void CForwardManager::OnSourceModAllInitialized()
|
||||
{
|
||||
g_PluginSys.AddPluginsListener(this);
|
||||
g_ShareSys.AddInterface(NULL, this);
|
||||
}
|
||||
|
||||
IForward *CForwardManager::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, ...)
|
||||
{
|
||||
CForward *fwd;
|
||||
va_list ap;
|
||||
va_start(ap, types);
|
||||
|
||||
fwd = CForward::CreateForward(name, et, num_params, types, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
if (fwd)
|
||||
{
|
||||
g_PluginSys.AddFunctionsToForward(name, fwd);
|
||||
|
||||
m_managed.push_back(fwd);
|
||||
}
|
||||
|
||||
return fwd;
|
||||
}
|
||||
|
||||
IChangeableForward *CForwardManager::CreateForwardEx(const char *name, ExecType et, int num_params, const ParamType *types, ...)
|
||||
{
|
||||
CForward *fwd;
|
||||
va_list ap;
|
||||
va_start(ap, types);
|
||||
|
||||
fwd = CForward::CreateForward(name, et, num_params, types, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
if (fwd)
|
||||
{
|
||||
m_unmanaged.push_back(fwd);
|
||||
}
|
||||
|
||||
return fwd;
|
||||
}
|
||||
|
||||
void CForwardManager::OnPluginLoaded(IPlugin *plugin)
|
||||
{
|
||||
/* Attach any globally managed forwards */
|
||||
List<CForward *>::iterator iter;
|
||||
CForward *fwd;
|
||||
|
||||
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
||||
{
|
||||
fwd = (*iter);
|
||||
IPluginFunction *pFunc = plugin->GetBaseContext()->GetFunctionByName(fwd->GetForwardName());
|
||||
if (pFunc)
|
||||
{
|
||||
fwd->AddFunction(pFunc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CForwardManager::OnPluginUnloaded(IPlugin *plugin)
|
||||
{
|
||||
List<CForward *>::iterator iter;
|
||||
CForward *fwd;
|
||||
|
||||
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
||||
{
|
||||
fwd = (*iter);
|
||||
fwd->RemoveFunctionsOfPlugin(plugin);
|
||||
}
|
||||
|
||||
for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
|
||||
{
|
||||
fwd = (*iter);
|
||||
fwd->RemoveFunctionsOfPlugin(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
IForward *CForwardManager::FindForward(const char *name, IChangeableForward **ifchng)
|
||||
{
|
||||
List<CForward *>::iterator iter;
|
||||
CForward *fwd;
|
||||
|
||||
for (iter=m_managed.begin(); iter!=m_managed.end(); iter++)
|
||||
{
|
||||
fwd = (*iter);
|
||||
if (strcmp(fwd->GetForwardName(), name) == 0)
|
||||
{
|
||||
if (ifchng)
|
||||
{
|
||||
*ifchng = NULL;
|
||||
}
|
||||
return fwd;
|
||||
}
|
||||
}
|
||||
|
||||
for (iter=m_unmanaged.begin(); iter!=m_unmanaged.end(); iter++)
|
||||
{
|
||||
fwd = (*iter);
|
||||
if (strcmp(fwd->GetForwardName(), name) == 0)
|
||||
{
|
||||
if (ifchng)
|
||||
{
|
||||
*ifchng = fwd;
|
||||
}
|
||||
return fwd;
|
||||
}
|
||||
}
|
||||
|
||||
if (ifchng)
|
||||
{
|
||||
*ifchng = NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CForwardManager::ReleaseForward(IForward *forward)
|
||||
{
|
||||
ForwardFree(static_cast<CForward *>(forward));
|
||||
}
|
||||
|
||||
void CForwardManager::ForwardFree(CForward *fwd)
|
||||
{
|
||||
m_FreeForwards.push(fwd);
|
||||
m_managed.remove(fwd);
|
||||
}
|
||||
|
||||
CForward *CForwardManager::ForwardMake()
|
||||
{
|
||||
CForward *fwd;
|
||||
if (m_FreeForwards.empty())
|
||||
{
|
||||
fwd = new CForward;
|
||||
} else {
|
||||
fwd = m_FreeForwards.front();
|
||||
m_FreeForwards.pop();
|
||||
}
|
||||
return fwd;
|
||||
}
|
||||
|
||||
void CForwardManager::OnPluginPauseChange(IPlugin *plugin, bool paused)
|
||||
{
|
||||
/* No longer used */
|
||||
}
|
||||
|
||||
/*************************************
|
||||
* ACTUAL FORWARD API IMPLEMENTATION *
|
||||
*************************************/
|
||||
|
||||
CForward *CForward::CreateForward(const char *name, ExecType et, unsigned int num_params, const ParamType *types, va_list ap)
|
||||
{
|
||||
ParamType _types[SP_MAX_EXEC_PARAMS];
|
||||
|
||||
if (num_params > SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (types == NULL && num_params)
|
||||
{
|
||||
for (unsigned int i=0; i<num_params; i++)
|
||||
{
|
||||
_types[i] = (ParamType)va_arg(ap, int);
|
||||
if (_types[i] == Param_VarArgs && (i != num_params - 1))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
types = _types;
|
||||
} else {
|
||||
for (unsigned int i=0; i<num_params; i++)
|
||||
{
|
||||
_types[i] = types[i];
|
||||
if (types[i] == Param_VarArgs && (i != num_params - 1))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* First parameter can never be varargs */
|
||||
if (num_params && _types[0] == Param_VarArgs)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CForward *pForward = g_Forwards.ForwardMake();
|
||||
pForward->m_curparam = 0;
|
||||
pForward->m_ExecType = et;
|
||||
snprintf(pForward->m_name, FORWARDS_NAME_MAX, "%s", name ? name : "");
|
||||
|
||||
for (unsigned int i=0; i<num_params; i++)
|
||||
{
|
||||
pForward->m_types[i] = _types[i];
|
||||
}
|
||||
|
||||
if (num_params && _types[num_params-1] == Param_VarArgs)
|
||||
{
|
||||
pForward->m_varargs = num_params--;
|
||||
} else {
|
||||
pForward->m_varargs = false;
|
||||
}
|
||||
|
||||
pForward->m_numparams = num_params;
|
||||
pForward->m_errstate = SP_ERROR_NONE;
|
||||
|
||||
pForward->m_functions.clear();
|
||||
|
||||
return pForward;
|
||||
}
|
||||
|
||||
int CForward::Execute(cell_t *result, IForwardFilter *filter)
|
||||
{
|
||||
if (m_errstate)
|
||||
{
|
||||
int err = m_errstate;
|
||||
Cancel();
|
||||
return err;
|
||||
}
|
||||
|
||||
if (filter)
|
||||
{
|
||||
filter->OnExecuteBegin();
|
||||
}
|
||||
|
||||
FuncIter iter = m_functions.begin();
|
||||
IPluginFunction *func;
|
||||
cell_t cur_result = 0;
|
||||
cell_t high_result = 0;
|
||||
int err;
|
||||
unsigned int failed=0, success=0;
|
||||
unsigned int num_params = m_curparam;
|
||||
FwdParamInfo temp_info[SP_MAX_EXEC_PARAMS];
|
||||
FwdParamInfo *param;
|
||||
ParamType type;
|
||||
|
||||
/* Save local, reset */
|
||||
memcpy(temp_info, m_params, sizeof(m_params));
|
||||
m_curparam = 0;
|
||||
|
||||
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
|
||||
{
|
||||
func = (*iter);
|
||||
|
||||
for (unsigned int i=0; i<num_params; i++)
|
||||
{
|
||||
int err = SP_ERROR_PARAM;
|
||||
param = &temp_info[i];
|
||||
if (i >= m_numparams || m_types[i] == Param_Any)
|
||||
{
|
||||
type = param->pushedas;
|
||||
} else {
|
||||
type = m_types[i];
|
||||
}
|
||||
if ((i >= m_numparams) || (type & SP_PARAMFLAG_BYREF))
|
||||
{
|
||||
/* If we're byref or we're vararg, we always push everything by ref.
|
||||
* Even if they're byval, we must push them byref.
|
||||
*/
|
||||
if (type == Param_String)
|
||||
{
|
||||
err = func->PushStringEx((char *)param->byref.orig_addr, param->byref.cells, param->byref.sz_flags, param->byref.flags);
|
||||
} else if (type == Param_Float || type == Param_Cell) {
|
||||
err = func->PushCellByRef(¶m->val);
|
||||
} else {
|
||||
err = func->PushArray(param->byref.orig_addr, param->byref.cells, param->byref.flags);
|
||||
assert(type == Param_Array || type == Param_FloatByRef || type == Param_CellByRef);
|
||||
}
|
||||
} else {
|
||||
/* If we're not byref or not vararg, our job is a bit easier. */
|
||||
assert(type == Param_Cell || type == Param_Float);
|
||||
err = func->PushCell(param->val);
|
||||
}
|
||||
if (err != SP_ERROR_NONE)
|
||||
{
|
||||
if (!filter || !filter->OnErrorReport(this, func, err))
|
||||
{
|
||||
g_DbgReporter.GenerateError(func->GetParentContext(),
|
||||
func->GetFunctionID(),
|
||||
err,
|
||||
"Failed to push parameter while executing forward");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Call the function and deal with the return value. */
|
||||
if ((err=func->Execute(&cur_result)) != SP_ERROR_NONE)
|
||||
{
|
||||
if (filter)
|
||||
{
|
||||
filter->OnErrorReport(this, func, err);
|
||||
}
|
||||
failed++;
|
||||
} else {
|
||||
success++;
|
||||
switch (m_ExecType)
|
||||
{
|
||||
case ET_Event:
|
||||
{
|
||||
if (cur_result > high_result)
|
||||
{
|
||||
high_result = cur_result;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ET_Hook:
|
||||
{
|
||||
if (cur_result > high_result)
|
||||
{
|
||||
high_result = cur_result;
|
||||
if ((ResultType)high_result == Pl_Stop)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ET_Custom:
|
||||
{
|
||||
if (filter)
|
||||
{
|
||||
if (filter->OnFunctionReturn(this, func, &cur_result) == Pl_Stop)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if (success)
|
||||
{
|
||||
if (m_ExecType == ET_Event || m_ExecType == ET_Hook)
|
||||
{
|
||||
cur_result = high_result;
|
||||
} else if (m_ExecType == ET_Ignore) {
|
||||
cur_result = 0;
|
||||
}
|
||||
if (result)
|
||||
{
|
||||
*result = cur_result;
|
||||
}
|
||||
}
|
||||
|
||||
if (filter)
|
||||
{
|
||||
filter->OnExecuteEnd(&cur_result, success, failed);
|
||||
}
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
int CForward::PushCell(cell_t cell)
|
||||
{
|
||||
if (m_curparam < m_numparams)
|
||||
{
|
||||
if (m_types[m_curparam] == Param_Any)
|
||||
{
|
||||
m_params[m_curparam].pushedas = Param_Cell;
|
||||
} else if (m_types[m_curparam] != Param_Cell) {
|
||||
return SetError(SP_ERROR_PARAM);
|
||||
}
|
||||
} else {
|
||||
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
m_params[m_curparam].pushedas = Param_Cell;
|
||||
}
|
||||
|
||||
m_params[m_curparam++].val = cell;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
int CForward::PushFloat(float number)
|
||||
{
|
||||
if (m_curparam < m_numparams)
|
||||
{
|
||||
if (m_types[m_curparam] == Param_Any)
|
||||
{
|
||||
m_params[m_curparam].pushedas = Param_Float;
|
||||
} else if (m_types[m_curparam] != Param_Float) {
|
||||
return SetError(SP_ERROR_PARAM);
|
||||
}
|
||||
} else {
|
||||
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
m_params[m_curparam].pushedas = Param_Float;
|
||||
}
|
||||
|
||||
m_params[m_curparam++].val = *(cell_t *)&number;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
int CForward::PushCellByRef(cell_t *cell, int flags)
|
||||
{
|
||||
if (m_curparam < m_numparams)
|
||||
{
|
||||
if (m_types[m_curparam] == Param_Any)
|
||||
{
|
||||
m_params[m_curparam].pushedas = Param_CellByRef;
|
||||
} else if (m_types[m_curparam] != Param_CellByRef) {
|
||||
return SetError(SP_ERROR_PARAM);
|
||||
}
|
||||
} else {
|
||||
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
m_params[m_curparam].pushedas = Param_CellByRef;
|
||||
}
|
||||
|
||||
_Int_PushArray(cell, 1, flags);
|
||||
m_curparam++;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
int CForward::PushFloatByRef(float *num, int flags)
|
||||
{
|
||||
if (m_curparam < m_numparams)
|
||||
{
|
||||
if (m_types[m_curparam] == Param_Any)
|
||||
{
|
||||
m_params[m_curparam].pushedas = Param_FloatByRef;
|
||||
} else if (m_types[m_curparam] != Param_FloatByRef) {
|
||||
return SetError(SP_ERROR_PARAM);
|
||||
}
|
||||
} else {
|
||||
if (!m_varargs || m_numparams > SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
m_params[m_curparam].pushedas = Param_FloatByRef;
|
||||
}
|
||||
|
||||
_Int_PushArray((cell_t *)num, 1, flags);
|
||||
m_curparam++;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
void CForward::_Int_PushArray(cell_t *inarray, unsigned int cells, int flags)
|
||||
{
|
||||
m_params[m_curparam].byref.cells = cells;
|
||||
m_params[m_curparam].byref.flags = flags;
|
||||
m_params[m_curparam].byref.orig_addr = inarray;
|
||||
}
|
||||
|
||||
int CForward::PushArray(cell_t *inarray, unsigned int cells, int flags)
|
||||
{
|
||||
/* We don't allow this here */
|
||||
if (!inarray)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAM);
|
||||
}
|
||||
|
||||
if (m_curparam < m_numparams)
|
||||
{
|
||||
if (m_types[m_curparam] == Param_Any)
|
||||
{
|
||||
m_params[m_curparam].pushedas = Param_Array;
|
||||
} else if (m_types[m_curparam] != Param_Array) {
|
||||
return SetError(SP_ERROR_PARAM);
|
||||
}
|
||||
} else {
|
||||
if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
m_params[m_curparam].pushedas = Param_Array;
|
||||
}
|
||||
|
||||
_Int_PushArray(inarray, cells, flags);
|
||||
|
||||
m_curparam++;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
void CForward::_Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags)
|
||||
{
|
||||
m_params[m_curparam].byref.cells = cells; /* Notice this contains the char count not cell count */
|
||||
m_params[m_curparam].byref.flags = cp_flags;
|
||||
m_params[m_curparam].byref.orig_addr = inarray;
|
||||
m_params[m_curparam].byref.sz_flags = sz_flags;
|
||||
}
|
||||
|
||||
int CForward::PushString(const char *string)
|
||||
{
|
||||
if (m_curparam < m_numparams)
|
||||
{
|
||||
if (m_types[m_curparam] == Param_Any)
|
||||
{
|
||||
m_params[m_curparam].pushedas = Param_String;
|
||||
} else if (m_types[m_curparam] != Param_String) {
|
||||
return SetError(SP_ERROR_PARAM);
|
||||
}
|
||||
} else {
|
||||
if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
m_params[m_curparam].pushedas = Param_String;
|
||||
}
|
||||
|
||||
_Int_PushString((cell_t *)string, strlen(string)+1, SM_PARAM_STRING_COPY, 0);
|
||||
m_curparam++;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
int CForward::PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags)
|
||||
{
|
||||
if (m_curparam < m_numparams)
|
||||
{
|
||||
if (m_types[m_curparam] == Param_Any)
|
||||
{
|
||||
m_params[m_curparam].pushedas = Param_String;
|
||||
} else if (m_types[m_curparam] != Param_String) {
|
||||
return SetError(SP_ERROR_PARAM);
|
||||
}
|
||||
} else {
|
||||
if (!m_varargs || m_curparam > SP_MAX_EXEC_PARAMS)
|
||||
{
|
||||
return SetError(SP_ERROR_PARAMS_MAX);
|
||||
}
|
||||
m_params[m_curparam].pushedas = Param_String;
|
||||
}
|
||||
|
||||
_Int_PushString((cell_t *)buffer, length, sz_flags, cp_flags);
|
||||
m_curparam++;
|
||||
|
||||
return SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
void CForward::Cancel()
|
||||
{
|
||||
if (!m_curparam)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_curparam = 0;
|
||||
m_errstate = SP_ERROR_NONE;
|
||||
}
|
||||
|
||||
bool CForward::AddFunction(IPluginContext *pContext, funcid_t index)
|
||||
{
|
||||
IPluginFunction *pFunc = pContext->GetFunctionById(index);
|
||||
|
||||
if (!pFunc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return AddFunction(pFunc);
|
||||
}
|
||||
|
||||
bool CForward::RemoveFunction(IPluginContext *pContext, funcid_t index)
|
||||
{
|
||||
IPluginFunction *pFunc = pContext->GetFunctionById(index);
|
||||
|
||||
if (!pFunc)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return RemoveFunction(pFunc);
|
||||
}
|
||||
|
||||
bool CForward::RemoveFunction(IPluginFunction *func)
|
||||
{
|
||||
bool found = false;
|
||||
FuncIter iter;
|
||||
List<IPluginFunction *> *lst;
|
||||
|
||||
if (func->IsRunnable())
|
||||
{
|
||||
lst = &m_functions;
|
||||
} else {
|
||||
lst = &m_paused;
|
||||
}
|
||||
|
||||
for (iter=m_functions.begin(); iter!=m_functions.end(); iter++)
|
||||
{
|
||||
if ((*iter) == func)
|
||||
{
|
||||
found = true;
|
||||
lst->erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cancel a call, if any */
|
||||
if (found || m_curparam)
|
||||
{
|
||||
func->Cancel();
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
unsigned int CForward::RemoveFunctionsOfPlugin(IPlugin *plugin)
|
||||
{
|
||||
FuncIter iter;
|
||||
IPluginFunction *func;
|
||||
unsigned int removed = 0;
|
||||
IPluginContext *pContext = plugin->GetBaseContext();
|
||||
for (iter=m_functions.begin(); iter!=m_functions.end();)
|
||||
{
|
||||
func = (*iter);
|
||||
if (func->GetParentContext() == pContext)
|
||||
{
|
||||
iter = m_functions.erase(iter);
|
||||
removed++;
|
||||
} else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
bool CForward::AddFunction(IPluginFunction *func)
|
||||
{
|
||||
if (m_curparam)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (func->IsRunnable())
|
||||
{
|
||||
m_functions.push_back(func);
|
||||
} else {
|
||||
m_paused.push_back(func);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *CForward::GetForwardName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
unsigned int CForward::GetFunctionCount()
|
||||
{
|
||||
return m_functions.size();
|
||||
}
|
||||
|
||||
ExecType CForward::GetExecType()
|
||||
{
|
||||
return m_ExecType;
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_
|
||||
#define _INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_
|
||||
|
||||
#include <IForwardSys.h>
|
||||
#include <IPluginSys.h>
|
||||
#include "sm_globals.h"
|
||||
#include <sh_list.h>
|
||||
#include <sh_stack.h>
|
||||
#include "sourcemod.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
typedef List<IPluginFunction *>::iterator FuncIter;
|
||||
|
||||
//:TODO: a global name max define for sourcepawn, should mirror compiler's sNAMEMAX
|
||||
#define FORWARDS_NAME_MAX 64
|
||||
|
||||
struct ByrefInfo
|
||||
{
|
||||
unsigned int cells;
|
||||
cell_t *orig_addr;
|
||||
int flags;
|
||||
int sz_flags;
|
||||
};
|
||||
|
||||
struct FwdParamInfo
|
||||
{
|
||||
cell_t val;
|
||||
ByrefInfo byref;
|
||||
ParamType pushedas;
|
||||
};
|
||||
|
||||
class CForward : public IChangeableForward
|
||||
{
|
||||
public: //ICallable
|
||||
virtual int PushCell(cell_t cell);
|
||||
virtual int PushCellByRef(cell_t *cell, int flags);
|
||||
virtual int PushFloat(float number);
|
||||
virtual int PushFloatByRef(float *number, int flags);
|
||||
virtual int PushArray(cell_t *inarray, unsigned int cells, int flags);
|
||||
virtual int PushString(const char *string);
|
||||
virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags);
|
||||
virtual void Cancel();
|
||||
public: //IForward
|
||||
virtual const char *GetForwardName();
|
||||
virtual unsigned int GetFunctionCount();
|
||||
virtual ExecType GetExecType();
|
||||
virtual int Execute(cell_t *result, IForwardFilter *filter);
|
||||
public: //IChangeableForward
|
||||
virtual bool RemoveFunction(IPluginFunction *func);
|
||||
virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin);
|
||||
virtual bool AddFunction(IPluginFunction *func);
|
||||
virtual bool AddFunction(IPluginContext *ctx, funcid_t index);
|
||||
virtual bool RemoveFunction(IPluginContext *ctx, funcid_t index);
|
||||
public:
|
||||
static CForward *CreateForward(const char *name,
|
||||
ExecType et,
|
||||
unsigned int num_params,
|
||||
const ParamType *types,
|
||||
va_list ap);
|
||||
private:
|
||||
void _Int_PushArray(cell_t *inarray, unsigned int cells, int flags);
|
||||
void _Int_PushString(cell_t *inarray, unsigned int cells, int sz_flags, int cp_flags);
|
||||
inline int SetError(int err)
|
||||
{
|
||||
m_errstate = err;
|
||||
return err;
|
||||
}
|
||||
protected:
|
||||
/* :TODO: I want a caching list type here.
|
||||
* Destroying these things and using new/delete for their members feels bad.
|
||||
*/
|
||||
mutable List<IPluginFunction *> m_functions;
|
||||
mutable List<IPluginFunction *> m_paused;
|
||||
|
||||
/* Type and name information */
|
||||
FwdParamInfo m_params[SP_MAX_EXEC_PARAMS];
|
||||
ParamType m_types[SP_MAX_EXEC_PARAMS];
|
||||
char m_name[FORWARDS_NAME_MAX+1];
|
||||
unsigned int m_numparams;
|
||||
unsigned int m_varargs;
|
||||
ExecType m_ExecType;
|
||||
|
||||
/* State information */
|
||||
unsigned int m_curparam;
|
||||
int m_errstate;
|
||||
};
|
||||
|
||||
class CForwardManager :
|
||||
public IForwardManager,
|
||||
public IPluginsListener,
|
||||
public SMGlobalClass
|
||||
{
|
||||
friend class CForward;
|
||||
public:
|
||||
~CForwardManager();
|
||||
public: //IForwardManager
|
||||
IForward *CreateForward(const char *name,
|
||||
ExecType et,
|
||||
unsigned int num_params,
|
||||
const ParamType *types,
|
||||
...);
|
||||
IChangeableForward *CreateForwardEx(const char *name,
|
||||
ExecType et,
|
||||
int num_params,
|
||||
const ParamType *types,
|
||||
...);
|
||||
IForward *FindForward(const char *name, IChangeableForward **ifchng);
|
||||
void ReleaseForward(IForward *forward);
|
||||
public: //IPluginsListener
|
||||
void OnPluginLoaded(IPlugin *plugin);
|
||||
void OnPluginUnloaded(IPlugin *plugin);
|
||||
void OnPluginPauseChange(IPlugin *plugin, bool paused);
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
protected:
|
||||
CForward *ForwardMake();
|
||||
void ForwardFree(CForward *fwd);
|
||||
private:
|
||||
CStack<CForward *> m_FreeForwards;
|
||||
List<CForward *> m_managed;
|
||||
List<CForward *> m_unmanaged;
|
||||
};
|
||||
|
||||
extern CForwardManager g_Forwards;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_FORWARDSYSTEM_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,225 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
|
||||
#define _INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
|
||||
|
||||
#include <IHandleSys.h>
|
||||
#include <stdio.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sm_trie.h"
|
||||
#include "sourcemod.h"
|
||||
#include "sm_memtable.h"
|
||||
|
||||
#define HANDLESYS_MAX_HANDLES (1<<14)
|
||||
#define HANDLESYS_MAX_TYPES (1<<9)
|
||||
#define HANDLESYS_MAX_SUBTYPES 0xF
|
||||
#define HANDLESYS_SUBTYPE_MASK 0xF
|
||||
#define HANDLESYS_TYPEARRAY_SIZE (HANDLESYS_MAX_TYPES * (HANDLESYS_MAX_SUBTYPES + 1))
|
||||
#define HANDLESYS_MAX_SERIALS 0xFFFF
|
||||
#define HANDLESYS_SERIAL_MASK 0xFFFF0000
|
||||
#define HANDLESYS_HANDLE_MASK 0x0000FFFF
|
||||
|
||||
#define HANDLESYS_MEMUSAGE_MIN_VERSION 3
|
||||
|
||||
/**
|
||||
* The QHandle is a nasty structure that compacts the handle system into a big vector.
|
||||
* The members of the vector each encapsulate one Handle, however, they also act as nodes
|
||||
* in an inlined linked list and an inlined vector.
|
||||
*
|
||||
* The first of these lists is the 'freeID' list. Each node from 1 to N (where N
|
||||
* is the number of free nodes) has a 'freeID' that specifies a free Handle ID. This
|
||||
* is a quick hack to get around allocating a second base vector.
|
||||
*
|
||||
* The second vector is the identity linked list. An identity has its own handle, so
|
||||
* these handles are used as sentinel nodes for index linking. They point to the first and last
|
||||
* index into the handle array. Each subsequent Handle who is owned by that identity is mapped into
|
||||
* that list. This lets owning identities be unloaded in O(n) time.
|
||||
*
|
||||
* Eventually, there may be a third list for type chains.
|
||||
*/
|
||||
|
||||
enum HandleSet
|
||||
{
|
||||
HandleSet_None = 0,
|
||||
HandleSet_Used, /* The Handle is in use */
|
||||
HandleSet_Freed, /* The "master" Handle of a clone chain is freed */
|
||||
HandleSet_Identity, /* The Handle is a special identity */
|
||||
};
|
||||
|
||||
struct QHandle
|
||||
{
|
||||
HandleType_t type; /* Handle type */
|
||||
void *object; /* Unmaintained object pointer */
|
||||
IdentityToken_t *owner; /* Identity of object which owns this */
|
||||
unsigned int serial; /* Serial no. for sanity checking */
|
||||
unsigned int refcount; /* Reference count for safe destruction */
|
||||
unsigned int clone; /* If non-zero, this is our cloned parent index */
|
||||
HandleSet set; /* Information about the handle's state */
|
||||
bool access_special; /* Whether or not access rules are special or type-derived */
|
||||
bool is_destroying; /* Whether or not the handle is being destroyed */
|
||||
HandleAccess sec; /* Security rules */
|
||||
/* The following variables are unrelated to the Handle array, and used
|
||||
* as an inlined chain of information */
|
||||
unsigned int freeID; /* ID of a free handle in the free handle chain */
|
||||
/* Indexes into the handle array for owner membership.
|
||||
* For identity roots, these are treated as the head/tail. */
|
||||
unsigned int ch_prev; /* chained previous handle */
|
||||
unsigned int ch_next; /* chained next handle */
|
||||
};
|
||||
|
||||
struct QHandleType
|
||||
{
|
||||
IHandleTypeDispatch *dispatch;
|
||||
unsigned int freeID;
|
||||
unsigned int children;
|
||||
TypeAccess typeSec;
|
||||
HandleAccess hndlSec;
|
||||
unsigned int opened;
|
||||
int nameIdx;
|
||||
};
|
||||
|
||||
typedef void (HANDLE_REPORTER)(const char *str, ...);
|
||||
|
||||
class HandleSystem :
|
||||
public IHandleSys
|
||||
{
|
||||
friend HandleError IdentityHandle(IdentityToken_t *token, unsigned int *index);
|
||||
friend class ShareSystem;
|
||||
public:
|
||||
HandleSystem();
|
||||
~HandleSystem();
|
||||
public: //IHandleSystem
|
||||
|
||||
HandleType_t CreateType(const char *name,
|
||||
IHandleTypeDispatch *dispatch,
|
||||
HandleType_t parent,
|
||||
const TypeAccess *typeAccess,
|
||||
const HandleAccess *hndlAccess,
|
||||
IdentityToken_t *ident,
|
||||
HandleError *err);
|
||||
|
||||
bool RemoveType(HandleType_t type, IdentityToken_t *ident);
|
||||
|
||||
bool FindHandleType(const char *name, HandleType_t *type);
|
||||
|
||||
Handle_t CreateHandle(HandleType_t type,
|
||||
void *object,
|
||||
IdentityToken_t *owner,
|
||||
IdentityToken_t *ident,
|
||||
HandleError *err);
|
||||
|
||||
HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity);
|
||||
|
||||
HandleError CloneHandle(Handle_t handle,
|
||||
Handle_t *newhandle,
|
||||
IdentityToken_t *newOwner,
|
||||
const HandleSecurity *pSecurity);
|
||||
|
||||
HandleError ReadHandle(Handle_t handle,
|
||||
HandleType_t type,
|
||||
const HandleSecurity *pSecurity,
|
||||
void **object);
|
||||
|
||||
bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess);
|
||||
|
||||
bool TypeCheck(HandleType_t intype, HandleType_t outtype);
|
||||
|
||||
virtual Handle_t CreateHandleEx(HandleType_t type,
|
||||
void *object,
|
||||
const HandleSecurity *pSec,
|
||||
const HandleAccess *pAccess,
|
||||
HandleError *err);
|
||||
|
||||
void Dump(HANDLE_REPORTER rep);
|
||||
protected:
|
||||
/**
|
||||
* Decodes a handle with sanity and security checking.
|
||||
*/
|
||||
HandleError GetHandle(Handle_t handle,
|
||||
IdentityToken_t *ident,
|
||||
QHandle **pHandle,
|
||||
unsigned int *index,
|
||||
bool ignoreFree=false);
|
||||
|
||||
/**
|
||||
* Creates a basic handle and sets its reference count to 1.
|
||||
* Does not do any type or security checking.
|
||||
*/
|
||||
HandleError MakePrimHandle(HandleType_t type,
|
||||
QHandle **pHandle,
|
||||
unsigned int *index,
|
||||
HandleType_t *handle,
|
||||
IdentityToken_t *owner,
|
||||
bool identity=false);
|
||||
|
||||
/**
|
||||
* Frees a primitive handle. Does no object freeing, only reference count, bookkeeping,
|
||||
* and linked list maintenance.
|
||||
* If used on an Identity handle, destroys all Handles under that identity.
|
||||
*/
|
||||
void ReleasePrimHandle(unsigned int index);
|
||||
|
||||
/**
|
||||
* Sets the security owner of a type.
|
||||
*/
|
||||
void SetTypeSecurityOwner(HandleType_t type, IdentityToken_t *pToken);
|
||||
|
||||
/**
|
||||
* Helper function to check access rights.
|
||||
*/
|
||||
bool CheckAccess(QHandle *pHandle, HandleAccessRight right, const HandleSecurity *pSecurity);
|
||||
|
||||
/**
|
||||
* Some wrappers for internal functions, so we can pass indexes instead of encoded handles.
|
||||
*/
|
||||
HandleError FreeHandle(QHandle *pHandle, unsigned int index);
|
||||
void UnlinkHandleFromOwner(QHandle *pHandle, unsigned int index);
|
||||
HandleError CloneHandle(QHandle *pHandle, unsigned int index, Handle_t *newhandle, IdentityToken_t *newOwner);
|
||||
Handle_t CreateHandleInt(HandleType_t type, void *object, const HandleSecurity *pSec, HandleError *err, const HandleAccess *pAccess, bool identity);
|
||||
|
||||
bool TryAndFreeSomeHandles();
|
||||
HandleError TryAllocHandle(unsigned int *handle);
|
||||
private:
|
||||
QHandle *m_Handles;
|
||||
QHandleType *m_Types;
|
||||
Trie *m_TypeLookup;
|
||||
unsigned int m_TypeTail;
|
||||
unsigned int m_FreeTypes;
|
||||
unsigned int m_HandleTail;
|
||||
unsigned int m_FreeHandles;
|
||||
unsigned int m_HSerial;
|
||||
BaseStringTable *m_strtab;
|
||||
};
|
||||
|
||||
extern HandleSystem g_HandleSys;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_H_
|
||||
@@ -0,0 +1,428 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sm_platform.h>
|
||||
#include "sm_stringutil.h"
|
||||
#include "LibrarySys.h"
|
||||
|
||||
LibrarySystem g_LibSys;
|
||||
|
||||
CLibrary::~CLibrary()
|
||||
{
|
||||
if (m_lib)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
FreeLibrary(m_lib);
|
||||
#elif defined PLATFORM_POSIX
|
||||
dlclose(m_lib);
|
||||
#endif
|
||||
m_lib = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CLibrary::CLibrary(LibraryHandle me)
|
||||
{
|
||||
m_lib = me;
|
||||
}
|
||||
|
||||
void CLibrary::CloseLibrary()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void *CLibrary::GetSymbolAddress(const char *symname)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
return GetProcAddress(m_lib, symname);
|
||||
#elif defined PLATFORM_POSIX
|
||||
return dlsym(m_lib, symname);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
** Directory Code **
|
||||
********************/
|
||||
|
||||
|
||||
CDirectory::CDirectory(const char *path)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
char newpath[PLATFORM_MAX_PATH];
|
||||
snprintf(newpath, sizeof(newpath), "%s\\*.*", path);
|
||||
m_dir = FindFirstFileA(newpath, &m_fd);
|
||||
if (!IsValid())
|
||||
{
|
||||
m_fd.cFileName[0] = '\0';
|
||||
}
|
||||
#elif defined PLATFORM_POSIX
|
||||
m_dir = opendir(path);
|
||||
if (IsValid())
|
||||
{
|
||||
/* :TODO: we need to read past "." and ".."! */
|
||||
ep = readdir(m_dir);
|
||||
snprintf(m_origpath, PLATFORM_MAX_PATH, "%s", path);
|
||||
} else {
|
||||
ep = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CDirectory::~CDirectory()
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
FindClose(m_dir);
|
||||
#elif defined PLATFORM_POSIX
|
||||
closedir(m_dir);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CDirectory::NextEntry()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
if (FindNextFile(m_dir, &m_fd) == 0)
|
||||
{
|
||||
FindClose(m_dir);
|
||||
m_dir = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#elif defined PLATFORM_POSIX
|
||||
if ((ep=readdir(m_dir)) == NULL)
|
||||
{
|
||||
closedir(m_dir);
|
||||
m_dir = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CDirectory::IsEntryValid()
|
||||
{
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
bool CDirectory::IsEntryDirectory()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
return ((m_fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY);
|
||||
#elif defined PLATFORM_LINUX
|
||||
char temppath[PLATFORM_MAX_PATH];
|
||||
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
return g_LibSys.IsPathDirectory(temppath);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CDirectory::IsEntryFile()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
return !(m_fd.dwFileAttributes & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE));
|
||||
#elif defined PLATFORM_POSIX
|
||||
char temppath[PLATFORM_MAX_PATH];
|
||||
snprintf(temppath, sizeof(temppath), "%s/%s", m_origpath, GetEntryName());
|
||||
return g_LibSys.IsPathFile(temppath);
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *CDirectory::GetEntryName()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
return m_fd.cFileName;
|
||||
#elif defined PLATFORM_LINUX
|
||||
return ep ? ep->d_name : "";
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CDirectory::MoreFiles()
|
||||
{
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
bool CDirectory::IsValid()
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
return (m_dir != INVALID_HANDLE_VALUE);
|
||||
#elif defined PLATFORM_LINUX
|
||||
return (m_dir != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*************************
|
||||
** Library System Code **
|
||||
*************************/
|
||||
|
||||
|
||||
bool LibrarySystem::PathExists(const char *path)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
DWORD attr = GetFileAttributesA(path);
|
||||
|
||||
return (attr != INVALID_FILE_ATTRIBUTES);
|
||||
#elif defined PLATFORM_POSIX
|
||||
struct stat s;
|
||||
|
||||
return (stat(path, &s) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool LibrarySystem::IsPathFile(const char *path)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
DWORD attr = GetFileAttributes(path);
|
||||
|
||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (attr & (FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_DEVICE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#elif defined PLATFORM_LINUX
|
||||
struct stat s;
|
||||
|
||||
if (stat(path, &s) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return S_ISREG(s.st_mode) ? true : false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool LibrarySystem::IsPathDirectory(const char *path)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
DWORD attr = GetFileAttributes(path);
|
||||
|
||||
if (attr == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif defined PLATFORM_LINUX
|
||||
struct stat s;
|
||||
|
||||
if (stat(path, &s) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (S_ISDIR(s.st_mode))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
IDirectory *LibrarySystem::OpenDirectory(const char *path)
|
||||
{
|
||||
CDirectory *dir = new CDirectory(path);
|
||||
|
||||
if (!dir->IsValid())
|
||||
{
|
||||
delete dir;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
void LibrarySystem::GetPlatformError(char *error, size_t maxlength)
|
||||
{
|
||||
if (error && maxlength)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
DWORD dw = GetLastError();
|
||||
FormatMessageA(
|
||||
FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
dw,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPSTR)error,
|
||||
maxlength,
|
||||
NULL);
|
||||
#elif defined PLATFORM_POSIX
|
||||
snprintf(error, maxlength, "%s", strerror(errno));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void LibrarySystem::CloseDirectory(IDirectory *dir)
|
||||
{
|
||||
delete dir;
|
||||
}
|
||||
|
||||
ILibrary *LibrarySystem::OpenLibrary(const char *path, char *error, size_t maxlength)
|
||||
{
|
||||
LibraryHandle lib;
|
||||
#if defined PLATFORM_WINDOWS
|
||||
lib = LoadLibraryA(path);
|
||||
if (!lib)
|
||||
{
|
||||
GetPlatformError(error, maxlength);
|
||||
return false;
|
||||
}
|
||||
#elif defined PLATFORM_POSIX
|
||||
lib = dlopen(path, RTLD_NOW);
|
||||
if (!lib)
|
||||
{
|
||||
GetPlatformError(error, maxlength);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return new CLibrary(lib);
|
||||
}
|
||||
|
||||
size_t LibrarySystem::PathFormat(char *buffer, size_t len, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
size_t mylen = vsnprintf(buffer, len, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (mylen >= len)
|
||||
{
|
||||
mylen = len - 1;
|
||||
buffer[mylen] = '\0';
|
||||
}
|
||||
|
||||
for (size_t i=0; i<mylen; i++)
|
||||
{
|
||||
if (buffer[i] == PLATFORM_SEP_ALTCHAR)
|
||||
{
|
||||
buffer[i] = PLATFORM_SEP_CHAR;
|
||||
}
|
||||
}
|
||||
|
||||
return mylen;
|
||||
}
|
||||
|
||||
const char *LibrarySystem::GetFileExtension(const char *filename)
|
||||
{
|
||||
size_t end = strlen(filename) - 1;
|
||||
|
||||
for (size_t i = end; i >= 0; i--)
|
||||
{
|
||||
if (i > end)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (filename[i] == PLATFORM_SEP_CHAR || filename[i] == PLATFORM_SEP_ALTCHAR)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (filename[i] == '.' && i != end)
|
||||
{
|
||||
return &filename[++i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool LibrarySystem::CreateFolder(const char *path)
|
||||
{
|
||||
#if defined PLATFORM_WINDOWS
|
||||
return (mkdir(path) != -1);
|
||||
#elif defined PLATFORM_POSIX
|
||||
return (mkdir(path, 0775) != -1);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t LibrarySystem::GetFileFromPath(char *buffer, size_t maxlength, const char *path)
|
||||
{
|
||||
size_t length = strlen(path);
|
||||
|
||||
for (size_t i = length - 1;
|
||||
i >= 0 && i <= length - 1;
|
||||
i--)
|
||||
{
|
||||
if (path[i] == '/'
|
||||
#if defined PLATFORM_WINDOWS
|
||||
|| path[i] == '\\'
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return UTIL_Format(buffer, maxlength, "%s", &path[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* We scanned and found no path separator */
|
||||
return UTIL_Format(buffer, maxlength, "%s", path);
|
||||
}
|
||||
|
||||
bool LibrarySystem::FileTime(const char *path, FileTimeType type, time_t *pTime)
|
||||
{
|
||||
#ifdef PLATFORM_WINDOWS
|
||||
struct _stat s;
|
||||
if (_stat(path, &s) != 0)
|
||||
#elif defined PLATFORM_POSIX
|
||||
struct stat s;
|
||||
if (stat(path, &s) != 0)
|
||||
#endif
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == FileTime_LastAccess)
|
||||
{
|
||||
*pTime = s.st_atime;
|
||||
}
|
||||
else if (type == FileTime_Created)
|
||||
{
|
||||
*pTime = s.st_ctime;
|
||||
}
|
||||
else if (type == FileTime_LastChange)
|
||||
{
|
||||
*pTime = s.st_mtime;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_SYSTEM_LIBRARY_H_
|
||||
#define _INCLUDE_SOURCEMOD_SYSTEM_LIBRARY_H_
|
||||
|
||||
#include <ILibrarySys.h>
|
||||
#include "sm_platform.h"
|
||||
|
||||
using namespace SourceMod;
|
||||
|
||||
#if defined PLATFORM_WINDOWS
|
||||
typedef HMODULE LibraryHandle;
|
||||
#elif defined PLATFORM_POSIX
|
||||
typedef void * LibraryHandle;
|
||||
#endif
|
||||
|
||||
class CDirectory : public IDirectory
|
||||
{
|
||||
public:
|
||||
CDirectory(const char *path);
|
||||
~CDirectory();
|
||||
public:
|
||||
bool MoreFiles();
|
||||
void NextEntry();
|
||||
const char *GetEntryName();
|
||||
bool IsEntryDirectory();
|
||||
bool IsEntryFile();
|
||||
bool IsEntryValid();
|
||||
public:
|
||||
bool IsValid();
|
||||
private:
|
||||
#if defined PLATFORM_WINDOWS
|
||||
HANDLE m_dir;
|
||||
WIN32_FIND_DATAA m_fd;
|
||||
#elif defined PLATFORM_POSIX
|
||||
DIR *m_dir;
|
||||
struct dirent *ep;
|
||||
char m_origpath[PLATFORM_MAX_PATH];
|
||||
#endif
|
||||
};
|
||||
|
||||
class CLibrary : public ILibrary
|
||||
{
|
||||
public:
|
||||
CLibrary(LibraryHandle me);
|
||||
~CLibrary();
|
||||
public:
|
||||
void CloseLibrary();
|
||||
void *GetSymbolAddress(const char *symname);
|
||||
private:
|
||||
LibraryHandle m_lib;
|
||||
};
|
||||
|
||||
class LibrarySystem : public ILibrarySys
|
||||
{
|
||||
public:
|
||||
ILibrary *OpenLibrary(const char *path, char *error, size_t maxlength);
|
||||
IDirectory *OpenDirectory(const char *path);
|
||||
void CloseDirectory(IDirectory *dir);
|
||||
bool PathExists(const char *path);
|
||||
bool IsPathFile(const char *path);
|
||||
bool IsPathDirectory(const char *path);
|
||||
void GetPlatformError(char *error, size_t maxlength);
|
||||
size_t PathFormat(char *buffer, size_t len, const char *fmt, ...);
|
||||
const char *GetFileExtension(const char *filename);
|
||||
bool CreateFolder(const char *path);
|
||||
size_t GetFileFromPath(char *buffer, size_t maxlength, const char *path);
|
||||
bool FileTime(const char *path, FileTimeType type, time_t *pTime);
|
||||
};
|
||||
|
||||
extern LibrarySystem g_LibSys;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_SYSTEM_LIBRARY_H_
|
||||
@@ -0,0 +1,349 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "PluginInfoDatabase.h"
|
||||
#include "PluginSys.h"
|
||||
|
||||
void PluginSettings::Init()
|
||||
{
|
||||
name = -1;
|
||||
pause_val = false;
|
||||
type_val = PluginType_MapUpdated;
|
||||
optarray = -1;
|
||||
opts_num = 0;
|
||||
opts_size = 0;
|
||||
blockload_val = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* :TODO: write the logger, make these errors log instead of being static
|
||||
* NOTE: once we do that, we will have to change some code to ignore sections
|
||||
*/
|
||||
|
||||
CPluginInfoDatabase::CPluginInfoDatabase()
|
||||
{
|
||||
m_strtab = NULL;
|
||||
m_infodb_count = 0;
|
||||
m_infodb_size = 0;
|
||||
m_infodb = -1;
|
||||
}
|
||||
|
||||
CPluginInfoDatabase::~CPluginInfoDatabase()
|
||||
{
|
||||
delete m_strtab;
|
||||
}
|
||||
|
||||
void CPluginInfoDatabase::ReadSMC_ParseStart()
|
||||
{
|
||||
/* Create or reset our string table */
|
||||
if (m_strtab)
|
||||
{
|
||||
m_strtab->Reset();
|
||||
} else {
|
||||
m_strtab = new BaseStringTable(1024);
|
||||
}
|
||||
|
||||
/* Set our internal states to the beginning */
|
||||
in_plugins = false;
|
||||
cur_plugin = -1;
|
||||
in_options = false;
|
||||
m_infodb_size = 0;
|
||||
m_infodb_count = 0;
|
||||
m_infodb = -1;
|
||||
}
|
||||
|
||||
SMCResult CPluginInfoDatabase::MakeError(const char *fmt, ...)
|
||||
{
|
||||
char buffer[512];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
m_errmsg = m_strtab->AddString(buffer);
|
||||
|
||||
return SMCResult_HaltFail;
|
||||
}
|
||||
|
||||
unsigned int CPluginInfoDatabase::GetSettingsNum()
|
||||
{
|
||||
return m_infodb_count;
|
||||
}
|
||||
|
||||
PluginSettings *CPluginInfoDatabase::GetSettingsIfMatch(unsigned int index, const char *filename)
|
||||
{
|
||||
BaseMemTable *memtab = m_strtab->GetMemTable();
|
||||
int *table = (int *)memtab->GetAddress(m_infodb);
|
||||
|
||||
if (!table || index >= m_infodb_count)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PluginSettings *plugin = (PluginSettings *)memtab->GetAddress(table[index]);
|
||||
|
||||
const char *name = m_strtab->GetString(plugin->name);
|
||||
|
||||
if (!name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!g_PluginSys.TestAliasMatch(name, filename))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return plugin;
|
||||
}
|
||||
|
||||
void CPluginInfoDatabase::GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val)
|
||||
{
|
||||
PluginOpts *table = (PluginOpts *)m_strtab->GetMemTable()->GetAddress(settings->optarray);
|
||||
if (!table)
|
||||
{
|
||||
*key = NULL;
|
||||
*val = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (opt_num >= settings->opts_num)
|
||||
{
|
||||
*key = NULL;
|
||||
*val = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
*key = m_strtab->GetString(table[opt_num].key);
|
||||
*val = m_strtab->GetString(table[opt_num].val);
|
||||
}
|
||||
|
||||
SMCResult CPluginInfoDatabase::ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value)
|
||||
{
|
||||
if (cur_plugin != -1)
|
||||
{
|
||||
PluginSettings *plugin = (PluginSettings *)m_strtab->GetMemTable()->GetAddress(cur_plugin);
|
||||
if (!in_options)
|
||||
{
|
||||
if (strcmp(key, "pause") == 0)
|
||||
{
|
||||
if (strcasecmp(value, "yes") == 0)
|
||||
{
|
||||
plugin->pause_val = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin->pause_val = false;
|
||||
}
|
||||
}
|
||||
else if (strcmp(key, "lifetime") == 0)
|
||||
{
|
||||
if (strcasecmp(value, "private") == 0)
|
||||
{
|
||||
plugin->type_val = PluginType_Private;
|
||||
}
|
||||
else if (strcasecmp(value, "mapsync") == 0)
|
||||
{
|
||||
plugin->type_val = PluginType_MapUpdated;
|
||||
}
|
||||
else if (strcasecmp(value, "maponly") == 0)
|
||||
{
|
||||
plugin->type_val = PluginType_MapOnly;
|
||||
}
|
||||
else if (strcasecmp(value, "global") == 0)
|
||||
{
|
||||
plugin->type_val = PluginType_Global;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MakeError("Unknown value for key \"lifetime\": \"%s\"", value);
|
||||
}
|
||||
}
|
||||
else if (strcmp(key, "blockload") == 0)
|
||||
{
|
||||
plugin->blockload_val = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MakeError("Unknown property key: \"%s\"", key);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Cache every option, valid or not */
|
||||
int keyidx = m_strtab->AddString(key);
|
||||
int validx = m_strtab->AddString(value);
|
||||
PluginOpts *table;
|
||||
BaseMemTable *memtab = m_strtab->GetMemTable();
|
||||
plugin = (PluginSettings *)memtab->GetAddress(cur_plugin);
|
||||
if (plugin->opts_num + 1 > plugin->opts_size)
|
||||
{
|
||||
unsigned int oldsize = plugin->opts_size;
|
||||
if (oldsize == 0)
|
||||
{
|
||||
//right now we don't have many
|
||||
plugin->opts_size = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
plugin->opts_size *= 2;
|
||||
}
|
||||
int newidx = memtab->CreateMem(plugin->opts_size * sizeof(PluginOpts), (void **)&table);
|
||||
/* in case it resized */
|
||||
plugin = (PluginSettings *)memtab->GetAddress(cur_plugin);
|
||||
if (plugin->optarray != -1)
|
||||
{
|
||||
void *oldtable = memtab->GetAddress(plugin->optarray);
|
||||
memcpy(table, oldtable, oldsize * sizeof(PluginOpts));
|
||||
}
|
||||
plugin->optarray = newidx;
|
||||
}
|
||||
else
|
||||
{
|
||||
table = (PluginOpts *)memtab->GetAddress(plugin->optarray);
|
||||
}
|
||||
PluginOpts *opt = &table[plugin->opts_num++];
|
||||
opt->key = keyidx;
|
||||
opt->val = validx;
|
||||
}
|
||||
}
|
||||
else if (in_plugins)
|
||||
{
|
||||
return MakeError("Unknown property key: \"%s\"", key);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Ignore anything we don't know about! */
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
SMCResult CPluginInfoDatabase::ReadSMC_LeavingSection(const SMCStates *states)
|
||||
{
|
||||
if (in_plugins)
|
||||
{
|
||||
if (cur_plugin != -1)
|
||||
{
|
||||
if (in_options)
|
||||
{
|
||||
in_options = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If the plugin is ending, add it to the table */
|
||||
BaseMemTable *memtab = m_strtab->GetMemTable();
|
||||
int *table;
|
||||
if (m_infodb_count + 1 > m_infodb_size)
|
||||
{
|
||||
unsigned int oldsize = m_infodb_size;
|
||||
if (!m_infodb_size)
|
||||
{
|
||||
m_infodb_size = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_infodb_size *= 2;
|
||||
}
|
||||
int newidx = memtab->CreateMem(m_infodb_size, (void **)&table);
|
||||
if (m_infodb != -1)
|
||||
{
|
||||
void *oldtable = (int *)memtab->GetAddress(m_infodb);
|
||||
memcpy(table, oldtable, oldsize * sizeof(int));
|
||||
}
|
||||
m_infodb = newidx;
|
||||
}
|
||||
else
|
||||
{
|
||||
table = (int *)memtab->GetAddress(m_infodb);
|
||||
}
|
||||
/* Assign to table and scrap the current plugin */
|
||||
table[m_infodb_count++] = cur_plugin;
|
||||
cur_plugin = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
in_plugins = false;
|
||||
}
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
SMCResult CPluginInfoDatabase::ReadSMC_NewSection(const SMCStates *states, const char *name)
|
||||
{
|
||||
if (!in_plugins)
|
||||
{
|
||||
/* If we're not in the main Plugins section, and we don't get it for the name, error out */
|
||||
if (strcmp(name, "Plugins") != 0)
|
||||
{
|
||||
return MakeError("Unknown root section: \"%s\"", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise set our states */
|
||||
in_plugins = true;
|
||||
cur_plugin = -1;
|
||||
in_options = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cur_plugin == -1)
|
||||
{
|
||||
/* If we get a plugin node and we don't have a current plugin, create a new one */
|
||||
PluginSettings *plugin;
|
||||
int i_name = m_strtab->AddString(name);
|
||||
cur_plugin = m_strtab->GetMemTable()->CreateMem(sizeof(PluginSettings), (void **)&plugin);
|
||||
plugin->Init();
|
||||
plugin->name = i_name;
|
||||
in_options = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!in_options && strcmp(name, "Options") == 0)
|
||||
{
|
||||
in_options = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return MakeError("Unknown plugin sub-section: \"%s\"", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SMCResult_Continue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
|
||||
#define _INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
|
||||
|
||||
/**
|
||||
* This file parses plugin_settings.cfg and stores the information in cached memory.
|
||||
* It provides simplistic abstraction to retrieving the info.
|
||||
* :TODO: currently untested
|
||||
*/
|
||||
|
||||
#include "sm_memtable.h"
|
||||
#include "ITextParsers.h"
|
||||
#include "IPluginSys.h"
|
||||
#include "sm_globals.h"
|
||||
|
||||
struct PluginOpts
|
||||
{
|
||||
int key;
|
||||
int val;
|
||||
};
|
||||
|
||||
struct PluginSettings
|
||||
{
|
||||
void Init();
|
||||
int name;
|
||||
bool pause_val;
|
||||
PluginType type_val;
|
||||
int optarray;
|
||||
size_t opts_num;
|
||||
size_t opts_size;
|
||||
bool blockload_val;
|
||||
};
|
||||
|
||||
class CPluginInfoDatabase : public ITextListener_SMC
|
||||
{
|
||||
public:
|
||||
CPluginInfoDatabase();
|
||||
~CPluginInfoDatabase();
|
||||
public: //ITextListener_SMC
|
||||
void ReadSMC_ParseStart();
|
||||
SMCResult ReadSMC_NewSection(const SMCStates *states, const char *name);
|
||||
SMCResult ReadSMC_KeyValue(const SMCStates *states, const char *key, const char *value);
|
||||
SMCResult ReadSMC_LeavingSection(const SMCStates *states);
|
||||
public:
|
||||
/**
|
||||
* Returns the number of plugin settings available.
|
||||
*/
|
||||
unsigned int GetSettingsNum();
|
||||
|
||||
/**
|
||||
* Given an index, returns the plugin settings block if the filename matches.
|
||||
* Otherwise, returns NULL.
|
||||
*/
|
||||
PluginSettings *GetSettingsIfMatch(unsigned int index, const char *filename);
|
||||
|
||||
/**
|
||||
* Given a plugin settings struct and an index,
|
||||
* returns the given JIT key/value option pair at that index.
|
||||
* If the input is invalid, key and val will be set to NULL.
|
||||
*/
|
||||
void GetOptionsForPlugin(PluginSettings *settings, unsigned int opt_num, const char **key, const char **val);
|
||||
private:
|
||||
SMCResult MakeError(const char *fmt, ...);
|
||||
private:
|
||||
BaseStringTable *m_strtab;
|
||||
int m_errmsg;
|
||||
bool in_plugins;
|
||||
bool in_options;
|
||||
int m_infodb;
|
||||
size_t m_infodb_count;
|
||||
size_t m_infodb_size;
|
||||
int cur_plugin;
|
||||
};
|
||||
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_CORE_SYSTEM_PLUGININFODATABASE_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,523 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
|
||||
#define _INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <IPluginSys.h>
|
||||
#include <IHandleSys.h>
|
||||
#include <IForwardSys.h>
|
||||
#include <sh_list.h>
|
||||
#include <sh_stack.h>
|
||||
#include <sh_vector.h>
|
||||
#include <sh_string.h>
|
||||
#include "sm_globals.h"
|
||||
#include "vm/sp_vm_basecontext.h"
|
||||
#include "PluginInfoDatabase.h"
|
||||
#include "sm_trie.h"
|
||||
#include "sourcemod.h"
|
||||
#include <IRootConsoleMenu.h>
|
||||
#if defined ORANGEBOX_BUILD
|
||||
#include "convar_sm_ob.h"
|
||||
#else
|
||||
#include "convar_sm.h"
|
||||
#endif
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
/**
|
||||
* NOTES:
|
||||
*
|
||||
* UPDATE 2008-03-11: These comments are horribly out of date. They paint a good overall
|
||||
* picture of how PluginSys works, but things like dependencies and fake natives have
|
||||
* complicated things quite a bit.
|
||||
*
|
||||
* Currently this system needs a lot of work but it's good skeletally. Plugin creation
|
||||
* is done without actually compiling anything. This is done by Load functions in the
|
||||
* manager. This will need a rewrite when we add context switching.
|
||||
*
|
||||
* The plugin object itself has a few things to note. The most important is that it stores
|
||||
* a table of function objects. The manager marshals allocation and freeing of these objects.
|
||||
* The plugin object can be in erroneous states, they are:
|
||||
* Plugin_Error --> Some error occurred any time during or after compilation.
|
||||
* This error can be cleared since the plugin itself is valid.
|
||||
* However, the state itself being set prevents any runtime action.
|
||||
* Plugin_BadLoad --> The plugin failed to load entirely and nothing can be done to save it.
|
||||
*
|
||||
* If a plugin fails to load externally, it is never added to the internal tracker. However,
|
||||
* plugins that failed to load from the internal loading mechanism are always tracked. This
|
||||
* allows users to see which automatically loaded plugins failed, and makes the interface a bit
|
||||
* more flexible.
|
||||
*
|
||||
* Once a plugin is compiled, it sets its own state to Plugin_Created. This state is still invalid
|
||||
* for execution. SourceMod is a two pass system, and even though the second pass is not implemented
|
||||
* yet, it is structured so Plugin_Created must be switched to Plugin_Running in the second pass. When
|
||||
* implemented, a Created plugin will be switched to Error in the second pass if it not loadable.
|
||||
*
|
||||
* The two pass loading mechanism is described below. Modules/natives are not implemented yet.
|
||||
* PASS ONE: All loadable plugins are found and have the following steps performed:
|
||||
* 1. Loading and compilation is attempted.
|
||||
* 2. If successful, all natives from Core are added.
|
||||
* 3. OnPluginLoad() is called.
|
||||
* 4. If failed, any user natives are scrapped and the process halts here.
|
||||
* 5. If successful, the plugin is ready for Pass 2.
|
||||
* INTERMEDIATE:
|
||||
* 1. All forced modules are loaded.
|
||||
* PASS TWO: All loaded plugins are found and have these steps performed:
|
||||
* 1. Any modules referenced in the plugin that are not already loaded, are loaded.
|
||||
* 2. If any module fails to load and the plugin requires it, load fails and jump to step 6.
|
||||
* 3. If any natives are unresolved, check if they are found in the user-natives pool.
|
||||
* 4. If yes, load succeeds. If not, natives are passed through a native acceptance filter.
|
||||
* 5. If the filter fails, the plugin is marked as failed.
|
||||
* 6. If the plugin has failed to load at this point, any dynamic natives it has added are scrapped.
|
||||
* Furthermore, any plugin that referenced these natives must now have pass 2 re-ran.
|
||||
* PASS THREE (not a real pass):
|
||||
* 7. Once all plugins are deemed to be loaded, OnPluginStart() is called
|
||||
*/
|
||||
|
||||
#define SM_CONTEXTVAR_MYSELF 0
|
||||
|
||||
struct ContextPair
|
||||
{
|
||||
ContextPair() : base(NULL), ctx(NULL), co(NULL)
|
||||
{
|
||||
};
|
||||
BaseContext *base;
|
||||
sp_context_t *ctx;
|
||||
ICompilation *co;
|
||||
IVirtualMachine *vm;
|
||||
};
|
||||
|
||||
struct FakeNative
|
||||
{
|
||||
IPluginContext *ctx;
|
||||
IPluginFunction *call;
|
||||
String name;
|
||||
SPVM_NATIVE_FUNC func;
|
||||
};
|
||||
|
||||
enum LoadRes
|
||||
{
|
||||
LoadRes_Successful,
|
||||
LoadRes_AlreadyLoaded,
|
||||
LoadRes_Failure,
|
||||
LoadRes_NeverLoad
|
||||
};
|
||||
|
||||
struct AutoConfig
|
||||
{
|
||||
String autocfg;
|
||||
String folder;
|
||||
bool create;
|
||||
};
|
||||
|
||||
class CPlugin;
|
||||
struct WeakNative
|
||||
{
|
||||
WeakNative(CPlugin *plugin, uint32_t index)
|
||||
{
|
||||
pl = plugin;
|
||||
idx = index;
|
||||
}
|
||||
CPlugin *pl;
|
||||
uint32_t idx;
|
||||
};
|
||||
|
||||
class CPlugin : public IPlugin
|
||||
{
|
||||
friend class CPluginManager;
|
||||
friend class CFunction;
|
||||
public:
|
||||
CPlugin(const char *file);
|
||||
~CPlugin();
|
||||
public:
|
||||
PluginType GetType();
|
||||
SourcePawn::IPluginContext *GetBaseContext();
|
||||
sp_context_t *GetContext();
|
||||
const sm_plugininfo_t *GetPublicInfo();
|
||||
const char *GetFilename();
|
||||
bool IsDebugging();
|
||||
PluginStatus GetStatus();
|
||||
bool SetPauseState(bool paused);
|
||||
unsigned int GetSerial();
|
||||
const sp_plugin_t *GetPluginStructure();
|
||||
IdentityToken_t *GetIdentity();
|
||||
unsigned int CalcMemUsage();
|
||||
bool SetProperty(const char *prop, void *ptr);
|
||||
bool GetProperty(const char *prop, void **ptr, bool remove=false);
|
||||
public:
|
||||
/**
|
||||
* Creates a plugin object with default values.
|
||||
* If an error buffer is specified, and an error occurs, the error will be copied to the buffer
|
||||
* and NULL will be returned.
|
||||
* If an error buffer is not specified, the error will be copied to an internal buffer and
|
||||
* a valid (but error-stated) CPlugin will be returned.
|
||||
*/
|
||||
static CPlugin *CreatePlugin(const char *file, char *error, size_t maxlength);
|
||||
public:
|
||||
/**
|
||||
* Starts the initial compilation of a plugin.
|
||||
* Returns false if another compilation exists or there is a current context set.
|
||||
*/
|
||||
ICompilation *StartMyCompile(IVirtualMachine *vm);
|
||||
/**
|
||||
* Finalizes a compilation. If error buffer is NULL, the error is saved locally.
|
||||
*/
|
||||
bool FinishMyCompile(char *error, size_t maxlength);
|
||||
void CancelMyCompile();
|
||||
|
||||
/**
|
||||
* Sets an error state on the plugin
|
||||
*/
|
||||
void SetErrorState(PluginStatus status, const char *error_fmt, ...);
|
||||
|
||||
/**
|
||||
* Initializes the plugin's identity information
|
||||
*/
|
||||
void InitIdentity();
|
||||
|
||||
/**
|
||||
* Calls the OnPluginLoad function, and sets any failed states if necessary.
|
||||
* NOTE: Valid pre-states are: Plugin_Created
|
||||
* NOTE: If validated, plugin state is changed to Plugin_Loaded
|
||||
*
|
||||
* If the error buffer is NULL, the error message is cached locally.
|
||||
*/
|
||||
bool Call_AskPluginLoad(char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* Calls the OnPluginStart function.
|
||||
* NOTE: Valid pre-states are: Plugin_Created
|
||||
* NOTE: Post-state will be Plugin_Running
|
||||
*/
|
||||
void Call_OnPluginStart();
|
||||
|
||||
/**
|
||||
* Calls the OnPluginEnd function.
|
||||
*/
|
||||
void Call_OnPluginEnd();
|
||||
|
||||
/**
|
||||
* Calls the OnAllPluginsLoaded function.
|
||||
*/
|
||||
void Call_OnAllPluginsLoaded();
|
||||
|
||||
/**
|
||||
* Toggles debug mode in the plugin
|
||||
*/
|
||||
bool ToggleDebugMode(bool debug, char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* Returns true if a plugin is usable.
|
||||
*/
|
||||
bool IsRunnable();
|
||||
|
||||
/**
|
||||
* Adds a language file index to the plugin's list.
|
||||
*/
|
||||
void AddLangFile(unsigned int index);
|
||||
|
||||
/**
|
||||
* Get language file count for this plugin.
|
||||
*/
|
||||
size_t GetLangFileCount();
|
||||
|
||||
/**
|
||||
* Get language file index based on the vector index.
|
||||
*/
|
||||
unsigned int GetLangFileByIndex(unsigned int index);
|
||||
public:
|
||||
/**
|
||||
* Returns the modification time during last plugin load.
|
||||
*/
|
||||
time_t GetTimeStamp();
|
||||
|
||||
/**
|
||||
* Returns the current modification time of the plugin file.
|
||||
*/
|
||||
time_t GetFileTimeStamp();
|
||||
|
||||
/**
|
||||
* Returns true if the plugin was running, but is now invalid.
|
||||
*/
|
||||
bool WasRunning();
|
||||
|
||||
Handle_t GetMyHandle();
|
||||
|
||||
void AddConfig(bool autoCreate, const char *cfg, const char *folder);
|
||||
unsigned int GetConfigCount();
|
||||
AutoConfig *GetConfig(unsigned int i);
|
||||
inline void AddLibrary(const char *name)
|
||||
{
|
||||
m_Libraries.push_back(name);
|
||||
}
|
||||
void LibraryActions(bool dropping);
|
||||
protected:
|
||||
void UpdateInfo();
|
||||
void SetTimeStamp(time_t t);
|
||||
void DependencyDropped(CPlugin *pOwner);
|
||||
private:
|
||||
ContextPair m_ctx;
|
||||
PluginType m_type;
|
||||
char m_filename[PLATFORM_MAX_PATH];
|
||||
PluginStatus m_status;
|
||||
unsigned int m_serial;
|
||||
sm_plugininfo_t m_info;
|
||||
sp_plugin_t *m_plugin;
|
||||
char m_errormsg[256];
|
||||
time_t m_LastAccess;
|
||||
IdentityToken_t *m_ident;
|
||||
Handle_t m_handle;
|
||||
bool m_WasRunning;
|
||||
CVector<unsigned int> m_PhraseFiles;
|
||||
List<CPlugin *> m_dependents;
|
||||
List<CPlugin *> m_dependsOn;
|
||||
List<FakeNative *> m_fakeNatives;
|
||||
List<WeakNative> m_WeakNatives;
|
||||
List<String> m_RequiredLibs;
|
||||
List<String> m_Libraries;
|
||||
Trie *m_pProps;
|
||||
bool m_FakeNativesMissing;
|
||||
bool m_LibraryMissing;
|
||||
CVector<AutoConfig *> m_configs;
|
||||
bool m_bGotAllLoaded;
|
||||
};
|
||||
|
||||
class CPluginManager :
|
||||
public IPluginManager,
|
||||
public SMGlobalClass,
|
||||
public IHandleTypeDispatch,
|
||||
public IRootConsoleCommand
|
||||
{
|
||||
friend class CPlugin;
|
||||
public:
|
||||
CPluginManager();
|
||||
~CPluginManager();
|
||||
public:
|
||||
/* Implements iterator class */
|
||||
class CPluginIterator : public IPluginIterator
|
||||
{
|
||||
public:
|
||||
CPluginIterator(List<CPlugin *> *mylist);
|
||||
virtual ~CPluginIterator();
|
||||
virtual bool MorePlugins();
|
||||
virtual IPlugin *GetPlugin();
|
||||
virtual void NextPlugin();
|
||||
void Release();
|
||||
public:
|
||||
void Reset();
|
||||
private:
|
||||
List<CPlugin *> *mylist;
|
||||
List<CPlugin *>::iterator current;
|
||||
};
|
||||
friend class CPluginManager::CPluginIterator;
|
||||
public: //IPluginManager
|
||||
IPlugin *LoadPlugin(const char *path,
|
||||
bool debug,
|
||||
PluginType type,
|
||||
char error[],
|
||||
size_t maxlength,
|
||||
bool *wasloaded);
|
||||
bool UnloadPlugin(IPlugin *plugin);
|
||||
IPlugin *FindPluginByContext(const sp_context_t *ctx);
|
||||
unsigned int GetPluginCount();
|
||||
IPluginIterator *GetPluginIterator();
|
||||
void AddPluginsListener(IPluginsListener *listener);
|
||||
void RemovePluginsListener(IPluginsListener *listener);
|
||||
public: //SMGlobalClass
|
||||
void OnSourceModAllInitialized();
|
||||
void OnSourceModShutdown();
|
||||
public: //IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object);
|
||||
bool GetHandleApproxSize(HandleType_t type, void *object, unsigned int *pSize);
|
||||
public: //IRootConsoleCommand
|
||||
void OnRootConsoleCommand(const char *cmdname, const CCommand &command);
|
||||
public:
|
||||
/**
|
||||
* Loads all plugins not yet loaded
|
||||
*/
|
||||
void LoadAll_FirstPass(const char *config, const char *basedir);
|
||||
|
||||
/**
|
||||
* Runs the second loading pass for all plugins
|
||||
*/
|
||||
void LoadAll_SecondPass();
|
||||
|
||||
/**
|
||||
* Tests a plugin file mask against a local folder.
|
||||
* The alias is searched backwards from localdir - i.e., given this input:
|
||||
* csdm/ban csdm/ban
|
||||
* ban csdm/ban
|
||||
* csdm/ban optional/csdm/ban
|
||||
* All of these will return true for an alias match.
|
||||
* Wildcards are allowed in the filename.
|
||||
*/
|
||||
bool TestAliasMatch(const char *alias, const char *localdir);
|
||||
|
||||
/**
|
||||
* Returns whether anything loaded will be a late load.
|
||||
*/
|
||||
bool IsLateLoadTime() const;
|
||||
|
||||
/**
|
||||
* Adds natives from core into the native pool.
|
||||
*/
|
||||
void RegisterNativesFromCore(sp_nativeinfo_t *natives);
|
||||
|
||||
/**
|
||||
* Converts a Handle to an IPlugin if possible.
|
||||
*/
|
||||
IPlugin *PluginFromHandle(Handle_t handle, HandleError *err);
|
||||
|
||||
/**
|
||||
* Finds a plugin based on its index. (starts on index 1)
|
||||
*/
|
||||
CPlugin *GetPluginByOrder(int num);
|
||||
|
||||
int GetOrderOfPlugin(IPlugin *pl);
|
||||
|
||||
/**
|
||||
* Internal version of FindPluginByContext()
|
||||
*/
|
||||
inline CPlugin *GetPluginByCtx(const sp_context_t *ctx)
|
||||
{
|
||||
return reinterpret_cast<CPlugin *>(ctx->user[SM_CONTEXTVAR_MYSELF]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets status text for a status code
|
||||
*/
|
||||
const char *GetStatusText(PluginStatus status);
|
||||
|
||||
/**
|
||||
* Reload or update plugins on level shutdown.
|
||||
*/
|
||||
void ReloadOrUnloadPlugins();
|
||||
|
||||
/**
|
||||
* Add public functions from all running or paused
|
||||
* plugins to the specified forward if the names match.
|
||||
*/
|
||||
void AddFunctionsToForward(const char *name, IChangeableForward *pForward);
|
||||
|
||||
/**
|
||||
* Iterates through plugins to call OnAllPluginsLoaded.
|
||||
*/
|
||||
void AllPluginsLoaded();
|
||||
|
||||
CPlugin *GetPluginFromIdentity(IdentityToken_t *pToken);
|
||||
|
||||
void Shutdown();
|
||||
|
||||
void OnLibraryAction(const char *lib, bool is_a_plugin, bool drop);
|
||||
|
||||
bool LibraryExists(const char *lib);
|
||||
|
||||
bool ReloadPlugin(CPlugin *pl);
|
||||
|
||||
void UnloadAll();
|
||||
|
||||
CPlugin *FindPluginByConsoleArg(const char *arg);
|
||||
private:
|
||||
LoadRes _LoadPlugin(CPlugin **pPlugin, const char *path, bool debug, PluginType type, char error[], size_t maxlength);
|
||||
|
||||
void LoadAutoPlugin(const char *plugin);
|
||||
|
||||
/**
|
||||
* Recursively loads all plugins in the given directory.
|
||||
*/
|
||||
void LoadPluginsFromDir(const char *basedir, const char *localdir);
|
||||
|
||||
/**
|
||||
* Adds a plugin object. This is wrapped by LoadPlugin functions.
|
||||
*/
|
||||
void AddPlugin(CPlugin *pPlugin);
|
||||
|
||||
/**
|
||||
* Runs the second loading pass on a plugin.
|
||||
*/
|
||||
bool RunSecondPass(CPlugin *pPlugin, char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* Adds any globally registered natives to a plugin
|
||||
*/
|
||||
void AddCoreNativesToPlugin(CPlugin *pPlugin);
|
||||
|
||||
/**
|
||||
* Runs an extension pass on a plugin.
|
||||
*/
|
||||
bool LoadOrRequireExtensions(CPlugin *pPlugin, unsigned int pass, char *error, size_t maxlength);
|
||||
|
||||
/**
|
||||
* Manages required natives.
|
||||
*/
|
||||
bool FindOrRequirePluginDeps(CPlugin *pPlugin, char *error, size_t maxlength);
|
||||
|
||||
void _SetPauseState(CPlugin *pPlugin, bool pause);
|
||||
protected:
|
||||
/**
|
||||
* Caching internal objects
|
||||
*/
|
||||
void ReleaseIterator(CPluginIterator *iter);
|
||||
public:
|
||||
inline IdentityToken_t *GetIdentity()
|
||||
{
|
||||
return m_MyIdent;
|
||||
}
|
||||
public:
|
||||
bool AddFakeNative(IPluginFunction *pFunction, const char *name, SPVM_FAKENATIVE_FUNC func);
|
||||
SPVM_NATIVE_FUNC FindCoreNative(const char *name);
|
||||
private:
|
||||
void AddFakeNativesToPlugin(CPlugin *pPlugin);
|
||||
void TryRefreshDependencies(CPlugin *pOther);
|
||||
private:
|
||||
List<IPluginsListener *> m_listeners;
|
||||
List<CPlugin *> m_plugins;
|
||||
CStack<CPluginManager::CPluginIterator *> m_iters;
|
||||
CPluginInfoDatabase m_PluginInfo;
|
||||
Trie *m_LoadLookup;
|
||||
bool m_AllPluginsLoaded;
|
||||
IdentityToken_t *m_MyIdent;
|
||||
Trie *m_pCoreNatives;
|
||||
|
||||
/* Dynamic native stuff */
|
||||
List<FakeNative *> m_Natives;
|
||||
Trie *m_pNativeLookup;
|
||||
|
||||
bool m_LoadingLocked;
|
||||
};
|
||||
|
||||
extern CPluginManager g_PluginSys;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_PLUGINSYSTEM_H_
|
||||
@@ -0,0 +1,250 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#include "ShareSys.h"
|
||||
#include "HandleSys.h"
|
||||
#include "ExtensionSys.h"
|
||||
#include "LibrarySys.h"
|
||||
|
||||
ShareSystem g_ShareSys;
|
||||
|
||||
ShareSystem::ShareSystem()
|
||||
{
|
||||
m_IdentRoot.ident = 0;
|
||||
m_TypeRoot = 0;
|
||||
m_IfaceType = 0;
|
||||
m_CoreType = 0;
|
||||
}
|
||||
|
||||
IdentityToken_t *ShareSystem::CreateCoreIdentity()
|
||||
{
|
||||
if (!m_CoreType)
|
||||
{
|
||||
m_CoreType = CreateIdentType("CORE");
|
||||
}
|
||||
|
||||
return CreateIdentity(m_CoreType, this);
|
||||
}
|
||||
|
||||
void ShareSystem::Initialize()
|
||||
{
|
||||
TypeAccess sec;
|
||||
|
||||
g_HandleSys.InitAccessDefaults(&sec, NULL);
|
||||
sec.ident = GetIdentRoot();
|
||||
|
||||
m_TypeRoot = g_HandleSys.CreateType("Identity", this, 0, &sec, NULL, NULL, NULL);
|
||||
m_IfaceType = g_HandleSys.CreateType("Interface", this, 0, NULL, NULL, GetIdentRoot(), NULL);
|
||||
|
||||
/* Initialize our static identity handle */
|
||||
m_IdentRoot.ident = g_HandleSys.CreateHandle(m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
|
||||
|
||||
/* Add the Handle System and others... they are too innocent and pure to do it themselves */
|
||||
AddInterface(NULL, &g_HandleSys);
|
||||
AddInterface(NULL, &g_LibSys);
|
||||
}
|
||||
|
||||
void ShareSystem::OnSourceModShutdown()
|
||||
{
|
||||
if (m_CoreType)
|
||||
{
|
||||
g_HandleSys.RemoveType(m_CoreType, GetIdentRoot());
|
||||
}
|
||||
|
||||
g_HandleSys.RemoveType(m_IfaceType, GetIdentRoot());
|
||||
g_HandleSys.RemoveType(m_TypeRoot, GetIdentRoot());
|
||||
}
|
||||
|
||||
IdentityType_t ShareSystem::FindIdentType(const char *name)
|
||||
{
|
||||
HandleType_t type;
|
||||
|
||||
if (g_HandleSys.FindHandleType(name, &type))
|
||||
{
|
||||
if (g_HandleSys.TypeCheck(type, m_TypeRoot))
|
||||
{
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
IdentityType_t ShareSystem::CreateIdentType(const char *name)
|
||||
{
|
||||
if (!m_TypeRoot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return g_HandleSys.CreateType(name, this, m_TypeRoot, NULL, NULL, GetIdentRoot(), NULL);
|
||||
}
|
||||
|
||||
void ShareSystem::OnHandleDestroy(HandleType_t type, void *object)
|
||||
{
|
||||
/* THIS WILL NEVER BE CALLED FOR ANYTHING WITH THE IDENTITY TYPE */
|
||||
}
|
||||
|
||||
IdentityToken_t *ShareSystem::CreateIdentity(IdentityType_t type, void *ptr)
|
||||
{
|
||||
if (!m_TypeRoot)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* :TODO: Cache? */
|
||||
IdentityToken_t *pToken = new IdentityToken_t;
|
||||
|
||||
HandleSecurity sec;
|
||||
sec.pOwner = sec.pIdentity = GetIdentRoot();
|
||||
|
||||
pToken->ident = g_HandleSys.CreateHandleInt(type, NULL, &sec, NULL, NULL, true);
|
||||
pToken->ptr = ptr;
|
||||
pToken->type = type;
|
||||
|
||||
return pToken;
|
||||
}
|
||||
|
||||
bool ShareSystem::AddInterface(IExtension *myself, SMInterface *iface)
|
||||
{
|
||||
if (!iface)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IfaceInfo info;
|
||||
|
||||
info.owner = myself;
|
||||
info.iface = iface;
|
||||
|
||||
m_Interfaces.push_back(info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShareSystem::RequestInterface(const char *iface_name,
|
||||
unsigned int iface_vers,
|
||||
IExtension *myself,
|
||||
SMInterface **pIface)
|
||||
{
|
||||
/* See if the interface exists */
|
||||
List<IfaceInfo>::iterator iter;
|
||||
SMInterface *iface;
|
||||
IExtension *iface_owner;
|
||||
bool found = false;
|
||||
for (iter=m_Interfaces.begin(); iter!=m_Interfaces.end(); iter++)
|
||||
{
|
||||
IfaceInfo &info = (*iter);
|
||||
iface = info.iface;
|
||||
if (strcmp(iface->GetInterfaceName(), iface_name) == 0)
|
||||
{
|
||||
if (iface->GetInterfaceVersion() == iface_vers
|
||||
|| iface->IsVersionCompatible(iface_vers))
|
||||
{
|
||||
iface_owner = info.owner;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Add a dependency node */
|
||||
if (iface_owner)
|
||||
{
|
||||
IfaceInfo info;
|
||||
info.iface = iface;
|
||||
info.owner = iface_owner;
|
||||
g_Extensions.BindDependency(myself, &info);
|
||||
}
|
||||
|
||||
if (pIface)
|
||||
{
|
||||
*pIface = iface;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShareSystem::AddNatives(IExtension *myself, const sp_nativeinfo_t *natives)
|
||||
{
|
||||
g_Extensions.AddNatives(myself, natives);
|
||||
}
|
||||
|
||||
void ShareSystem::DestroyIdentity(IdentityToken_t *identity)
|
||||
{
|
||||
HandleSecurity sec;
|
||||
|
||||
sec.pOwner = GetIdentRoot();
|
||||
sec.pIdentity = GetIdentRoot();
|
||||
|
||||
g_HandleSys.FreeHandle(identity->ident, &sec);
|
||||
delete identity;
|
||||
}
|
||||
|
||||
void ShareSystem::DestroyIdentType(IdentityType_t type)
|
||||
{
|
||||
g_HandleSys.RemoveType(type, GetIdentRoot());
|
||||
}
|
||||
|
||||
void ShareSystem::RemoveInterfaces(IExtension *pExtension)
|
||||
{
|
||||
List<IfaceInfo>::iterator iter = m_Interfaces.begin();
|
||||
|
||||
while (iter != m_Interfaces.end())
|
||||
{
|
||||
if ((*iter).owner == pExtension)
|
||||
{
|
||||
iter = m_Interfaces.erase(iter);
|
||||
} else {
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShareSystem::AddDependency(IExtension *myself, const char *filename, bool require, bool autoload)
|
||||
{
|
||||
g_Extensions.AddDependency(myself, filename, require, autoload);
|
||||
}
|
||||
|
||||
void ShareSystem::RegisterLibrary(IExtension *myself, const char *name)
|
||||
{
|
||||
g_Extensions.AddLibrary(myself, name);
|
||||
}
|
||||
|
||||
void ShareSystem::OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives)
|
||||
{
|
||||
g_Extensions.OverrideNatives(myself, natives);
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* vim: set ts=4 :
|
||||
* =============================================================================
|
||||
* SourceMod
|
||||
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
|
||||
* =============================================================================
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it under
|
||||
* the terms of the GNU General Public License, version 3.0, as published by the
|
||||
* Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* As a special exception, AlliedModders LLC gives you permission to link the
|
||||
* code of this program (as well as its derivative works) to "Half-Life 2," the
|
||||
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
|
||||
* by the Valve Corporation. You must obey the GNU General Public License in
|
||||
* all respects for all other code used. Additionally, AlliedModders LLC grants
|
||||
* this exception to all derivative works. AlliedModders LLC defines further
|
||||
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
|
||||
* or <http://www.sourcemod.net/license.php>.
|
||||
*
|
||||
* Version: $Id$
|
||||
*/
|
||||
|
||||
#ifndef _INCLUDE_SOURCEMOD_SHARESYSTEM_H_
|
||||
#define _INCLUDE_SOURCEMOD_SHARESYSTEM_H_
|
||||
|
||||
#include <IShareSys.h>
|
||||
#include <IHandleSys.h>
|
||||
#include <sh_list.h>
|
||||
#include "sm_globals.h"
|
||||
#include "sourcemod.h"
|
||||
|
||||
using namespace SourceHook;
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
struct IdentityToken_t
|
||||
{
|
||||
Handle_t ident;
|
||||
void *ptr;
|
||||
IdentityType_t type;
|
||||
};
|
||||
};
|
||||
|
||||
struct IfaceInfo
|
||||
{
|
||||
bool operator ==(const IfaceInfo &info)
|
||||
{
|
||||
return (info.iface == iface && info.owner == owner);
|
||||
}
|
||||
SMInterface *iface;
|
||||
IExtension *owner;
|
||||
};
|
||||
|
||||
class ShareSystem :
|
||||
public IShareSys,
|
||||
public SMGlobalClass,
|
||||
public IHandleTypeDispatch
|
||||
{
|
||||
public:
|
||||
ShareSystem();
|
||||
public: //IShareSys
|
||||
bool AddInterface(IExtension *myself, SMInterface *pIface);
|
||||
bool RequestInterface(const char *iface_name,
|
||||
unsigned int iface_vers,
|
||||
IExtension *myself,
|
||||
SMInterface **pIface);
|
||||
void AddNatives(IExtension *myself, const sp_nativeinfo_t *natives);
|
||||
IdentityType_t CreateIdentType(const char *name);
|
||||
IdentityType_t FindIdentType(const char *name);
|
||||
IdentityToken_t *CreateIdentity(IdentityType_t type, void *ptr);
|
||||
void DestroyIdentType(IdentityType_t type);
|
||||
void DestroyIdentity(IdentityToken_t *identity);
|
||||
void AddDependency(IExtension *myself, const char *filename, bool require, bool autoload);
|
||||
void RegisterLibrary(IExtension *myself, const char *name);
|
||||
void OverrideNatives(IExtension *myself, const sp_nativeinfo_t *natives);
|
||||
public: //SMGlobalClass
|
||||
/* Pre-empt in case anything tries to register idents early */
|
||||
void Initialize();
|
||||
void OnSourceModShutdown();
|
||||
public: //IHandleTypeDispatch
|
||||
void OnHandleDestroy(HandleType_t type, void *object);
|
||||
public:
|
||||
IdentityToken_t *CreateCoreIdentity();
|
||||
void RemoveInterfaces(IExtension *pExtension);
|
||||
public:
|
||||
inline IdentityToken_t *GetIdentRoot()
|
||||
{
|
||||
return &m_IdentRoot;
|
||||
}
|
||||
private:
|
||||
List<IfaceInfo> m_Interfaces;
|
||||
HandleType_t m_TypeRoot;
|
||||
IdentityToken_t m_IdentRoot;
|
||||
HandleType_t m_IfaceType;
|
||||
IdentityType_t m_CoreType;
|
||||
};
|
||||
|
||||
extern ShareSystem g_ShareSys;
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_SHARESYSTEM_H_
|
||||
Reference in New Issue
Block a user