reorganized SourceMod for the public SDK
--HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%40329
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
|
||||
#define _INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
|
||||
|
||||
#include <IShareSys.h>
|
||||
#include <ILibrarySys.h>
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
class IExtensionInterface;
|
||||
typedef void * ITERATOR;
|
||||
|
||||
/**
|
||||
* @brief Encapsulates an IExtension.
|
||||
*/
|
||||
class IExtension
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Returns whether or not the extension is properly loaded.
|
||||
*/
|
||||
virtual bool IsLoaded() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the extension's API interface
|
||||
*
|
||||
* @return An IExtensionInterface pointer.
|
||||
*/
|
||||
virtual IExtensionInterface *GetAPI() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the filename of the extension, relative to the
|
||||
* extension folder.
|
||||
*
|
||||
* @return A string containing the extension file name.
|
||||
*/
|
||||
virtual const char *GetFilename() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the extension's identity token.
|
||||
*
|
||||
* @return An IdentityToken_t pointer.
|
||||
*/
|
||||
virtual IdentityToken_t *GetIdentity() =0;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the extension dependency list for this extension.
|
||||
*
|
||||
* @param pOwner Optional pointer to store the first interface's owner.
|
||||
* @param pInterface Optional pointer to store the first interface.
|
||||
* @return An ITERATOR pointer for the results, or NULL if no results at all.
|
||||
*/
|
||||
virtual ITERATOR *FindFirstDependency(IExtension **pOwner, SMInterface **pInterface) =0;
|
||||
|
||||
/**
|
||||
* @brief Finds the next dependency in the dependency list.
|
||||
*
|
||||
* @param iter Pointer to iterator from FindFirstDependency.
|
||||
* @param pOwner Optional pointer to store the interface's owner.
|
||||
* @param pInterface Optional pointer to store the interface.
|
||||
* @return True if there are more results after this, false otherwise.
|
||||
*/
|
||||
virtual bool FindNextDependency(ITERATOR *iter, IExtension **pOwner, SMInterface **pInterface) =0;
|
||||
|
||||
/**
|
||||
* @brief Frees an ITERATOR handle from FindFirstDependency.
|
||||
*
|
||||
* @param iter Pointer to iterator to free.
|
||||
*/
|
||||
virtual void FreeDependencyIterator(ITERATOR *iter) =0;
|
||||
|
||||
/**
|
||||
* @brief Queries the extension to see its run state.
|
||||
*
|
||||
* @param error Error buffer (may be NULL).
|
||||
* @param maxlength Maximum length of buffer.
|
||||
* @return True if extension is okay, false if not okay.
|
||||
*/
|
||||
virtual bool IsRunning(char *error, size_t maxlength) =0;
|
||||
};
|
||||
|
||||
#define SMINTERFACE_EXTENSIONAPI_VERSION 1
|
||||
|
||||
/**
|
||||
* @brief The interface an extension must expose.
|
||||
*/
|
||||
class IExtensionInterface
|
||||
{
|
||||
public:
|
||||
virtual unsigned int GetExtensionVersion()
|
||||
{
|
||||
return SMINTERFACE_EXTENSIONAPI_VERSION;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Called when the extension is loaded.
|
||||
*
|
||||
* @param me Pointer back to extension.
|
||||
* @param sys Pointer to interface sharing system of SourceMod.
|
||||
* @param error Error buffer to print back to, if any.
|
||||
* @param err_max Maximum size of error buffer.
|
||||
* @param late If this extension was loaded "late" (i.e. manually).
|
||||
* @return True if load should continue, false otherwise.
|
||||
*/
|
||||
virtual bool OnExtensionLoad(IExtension *me,
|
||||
IShareSys *sys,
|
||||
char *error,
|
||||
size_t err_max,
|
||||
bool late) =0;
|
||||
|
||||
/**
|
||||
* @brief Called when the extension is about to be unloaded.
|
||||
*/
|
||||
virtual void OnExtensionUnload() =0;
|
||||
|
||||
/**
|
||||
* @brief Called when all extensions are loaded (loading cycle is done).
|
||||
* If loaded late, this will be called right after OnExtensionLoad().
|
||||
*/
|
||||
virtual void OnExtensionsAllLoaded() =0;
|
||||
|
||||
/**
|
||||
* @brief Called when your pause state is about to change.
|
||||
*
|
||||
* @param pause True if pausing, false if unpausing.
|
||||
*/
|
||||
virtual void OnExtensionPauseChange(bool pause) =0;
|
||||
|
||||
/**
|
||||
* @brief Asks the extension whether it's safe to remove an external interface it's using.
|
||||
* If it's not safe, return false, and the extension will be unloaded afterwards.
|
||||
* NOTE: It is important to also hook NotifyInterfaceDrop() in order to clean up resources.
|
||||
*
|
||||
* @param pInterface Pointer to interface being dropped.
|
||||
* @return True to continue, false to unload this extension afterwards.
|
||||
*/
|
||||
virtual bool QueryInterfaceDrop(SMInterface *pInterface)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notifies the extension that an external interface it uses is being removed.
|
||||
*
|
||||
* @param pInterface Pointer to interface being dropped.
|
||||
*/
|
||||
virtual void NotifyInterfaceDrop(SMInterface *pInterface)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return false to tell Core that your extension should be considered unsable.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param maxlength Size of error buffer.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
virtual bool QueryRunning(char *error, size_t maxlength)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
virtual bool IsMetamodExtension() =0;
|
||||
virtual const char *GetExtensionName() =0;
|
||||
virtual const char *GetExtensionURL() =0;
|
||||
virtual const char *GetExtensionTag() =0;
|
||||
virtual const char *GetExtensionAuthor() =0;
|
||||
virtual const char *GetExtensionVerString() =0;
|
||||
virtual const char *GetExtensionDescription() =0;
|
||||
virtual const char *GetExtensionDateString() =0;
|
||||
};
|
||||
|
||||
#define SMINTERFACE_EXTENSIONMANAGER_NAME "IExtensionManager"
|
||||
#define SMINTERFACE_EXTENSIONMANAGER_VERSION 1
|
||||
|
||||
enum ExtensionLifetime
|
||||
{
|
||||
ExtLifetime_Forever, //Extension will never be unloaded automatically
|
||||
ExtLifetime_Map, //Extension will be unloaded at the end of the map
|
||||
};
|
||||
|
||||
class IExtensionManager : public SMInterface
|
||||
{
|
||||
public:
|
||||
virtual const char *GetInterfaceName()
|
||||
{
|
||||
return SMINTERFACE_EXTENSIONMANAGER_NAME;
|
||||
}
|
||||
virtual unsigned int GetInterfaceVersion()
|
||||
{
|
||||
return SMINTERFACE_EXTENSIONMANAGER_VERSION;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Loads a extension into the extension system.
|
||||
*
|
||||
* @param path Path to extension file, relative to the extensions folder.
|
||||
* @param lifetime Lifetime of the extension.
|
||||
* @param error Error buffer.
|
||||
* @param err_max Maximum error buffer length.
|
||||
* @return New IExtension on success, NULL on failure.
|
||||
*/
|
||||
virtual IExtension *LoadExtension(const char *path,
|
||||
ExtensionLifetime lifetime,
|
||||
char *error,
|
||||
size_t err_max) =0;
|
||||
|
||||
/**
|
||||
* @brief Attempts to unload a module.
|
||||
*
|
||||
* @param pExt IExtension pointer.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
virtual bool UnloadExtension(IExtension *pExt) =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_MODULE_INTERFACE_H_
|
||||
@@ -0,0 +1,350 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_FORWARDINTERFACE_H_
|
||||
#define _INCLUDE_SOURCEMOD_FORWARDINTERFACE_H_
|
||||
|
||||
#include <IForwardSys.h>
|
||||
#include <IPluginSys.h>
|
||||
#include <IPluginFunction.h>
|
||||
|
||||
#define SMINTERFACE_FORWARDMANAGER_NAME "IForwardManager"
|
||||
#define SMINTERFACE_FORWARDMANAGER_VERSION 1
|
||||
|
||||
/**
|
||||
* There is some very important documentation at the bottom of this file.
|
||||
* Readers interested in knowing more about the forward system, scrolling down is a must!
|
||||
*/
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
enum ResultType
|
||||
{
|
||||
Pl_Continue = 0, /* No result */
|
||||
Pl_Handled = 1, /* Result was handled, stop at the end */
|
||||
Pl_Stop = 2, /* Result was handled, stop now */
|
||||
};
|
||||
|
||||
enum ExecType
|
||||
{
|
||||
ET_Ignore = 0, /* Ignore all return values, return 0 */
|
||||
ET_Single = 1, /* Only return the last exec, ignore all others */
|
||||
ET_Event = 2, /* Acts as an event with the ResultTypes above, no mid-Stops allowed, returns highest */
|
||||
ET_Hook = 3, /* Acts as a hook with the ResultTypes above, mid-Stops allowed, returns highest */
|
||||
ET_Custom = 4, /* Ignored or handled by an IForwardFilter */
|
||||
};
|
||||
|
||||
class IForward;
|
||||
|
||||
class IForwardFilter
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Called when an error occurs executing a plugin.
|
||||
*
|
||||
* @param fwd IForward pointer.
|
||||
* @param func IPluginFunction pointer to the failed function.
|
||||
* @param err Error code.
|
||||
* @return True to handle, false to pass to global error reporter.
|
||||
*/
|
||||
virtual bool OnErrorReport(IForward *fwd,
|
||||
IPluginFunction *func,
|
||||
int err)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called after each function return during execution.
|
||||
* NOTE: Only used for ET_Custom.
|
||||
*
|
||||
* @param fwd IForward pointer.
|
||||
* @param func IPluginFunction pointer to the executed function.
|
||||
* @param retval Pointer to current return value (can be modified).
|
||||
* @return ResultType denoting the next action to take.
|
||||
*/
|
||||
virtual ResultType OnFunctionReturn(IForward *fwd,
|
||||
IPluginFunction *func,
|
||||
cell_t *retval)
|
||||
{
|
||||
return Pl_Continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when execution begins.
|
||||
*/
|
||||
virtual void OnExecuteBegin()
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Called when execution ends.
|
||||
*
|
||||
* @param final_ret Final return value (modifiable).
|
||||
* @param success Number of successful execs.
|
||||
* @param failed Number of failed execs.
|
||||
*/
|
||||
virtual void OnExecuteEnd(cell_t *final_ret, unsigned int success, unsigned int failed)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Abstracts multiple function calling.
|
||||
*
|
||||
* NOTE: Parameters should be pushed in forward order, unlike
|
||||
* the virtual machine/IPluginContext order.
|
||||
* NOTE: Some functions are repeated in here because their
|
||||
* documentation differs from their IPluginFunction equivalents.
|
||||
* Missing are the Push functions, whose only doc change is that
|
||||
* they throw SP_ERROR_PARAM on type mismatches.
|
||||
*/
|
||||
class IForward : public ICallable
|
||||
{
|
||||
public:
|
||||
virtual ~IForward()
|
||||
{
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Returns the name of the forward.
|
||||
*
|
||||
* @return Forward name.
|
||||
*/
|
||||
virtual const char *GetForwardName() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of functions in this forward.
|
||||
*
|
||||
* @return Number of functions in forward.
|
||||
*/
|
||||
virtual unsigned int GetFunctionCount() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the method of multi-calling this forward has.
|
||||
*
|
||||
* @return ExecType of the forward.
|
||||
*/
|
||||
virtual ExecType GetExecType() =0;
|
||||
|
||||
/**
|
||||
* @brief Executes the forward.
|
||||
*
|
||||
* @param result Pointer to store result in.
|
||||
* @param filter Optional pointer to an IForwardFilter.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int Execute(cell_t *result, IForwardFilter *filter=NULL) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes an array of cells onto the current call. Different rules than ICallable.
|
||||
* NOTE: On Execute, the pointer passed will be modified according to the copyback rule.
|
||||
*
|
||||
* @param inarray Array to copy. Cannot be NULL, unlike ICallable's version.
|
||||
* @param cells Number of cells to allocate and optionally read from the input array.
|
||||
* @param phys_addr Unused. If a value is passed, it will be filled with NULL.
|
||||
* @param flags Whether or not changes should be copied back to the input array.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int PushArray(cell_t *inarray,
|
||||
unsigned int cells,
|
||||
cell_t **phys_addr,
|
||||
int flags=0) =0;
|
||||
};
|
||||
|
||||
|
||||
class IChangeableForward : public IForward
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Removes a function from the call list.
|
||||
* NOTE: Only removes one instance.
|
||||
*
|
||||
* @param func Function to remove.
|
||||
* @return Whether or not the function was removed.
|
||||
*/
|
||||
virtual bool RemoveFunction(IPluginFunction *func) =0;
|
||||
|
||||
/**
|
||||
* @brief Removes all instances of a plugin from the call list.
|
||||
*
|
||||
* @param plugin Plugin to remove instances of.
|
||||
* @return Number of functions removed therein.
|
||||
*/
|
||||
virtual unsigned int RemoveFunctionsOfPlugin(IPlugin *plugin) =0;
|
||||
|
||||
/**
|
||||
* @brief Adds a function to the call list.
|
||||
* NOTE: Cannot be used during an incompleted call.
|
||||
* NOTE: If used during a call, function is temporarily queued until calls are over.
|
||||
* NOTE: Adding mulitple copies of the same function is illegal.
|
||||
*
|
||||
* @param func Function to add.
|
||||
* @return True on success, otherwise false.
|
||||
*/
|
||||
virtual bool AddFunction(IPluginFunction *func) =0;
|
||||
|
||||
/**
|
||||
* @brief Adds a function to the call list.
|
||||
* NOTE: Cannot be used during an incompleted call.
|
||||
* NOTE: If used during a call, function is temporarily queued until calls are over.
|
||||
*
|
||||
* @param ctx Context to use as a look-up.
|
||||
* @param funcid Function id to add.
|
||||
* @return True on success, otherwise false.
|
||||
*/
|
||||
virtual bool AddFunction(sp_context_t *ctx, funcid_t index) =0;
|
||||
};
|
||||
|
||||
#define SP_PARAMTYPE_ANY 0
|
||||
#define SP_PARAMFLAG_BYREF (1<<0)
|
||||
#define SP_PARAMTYPE_CELL (1<<1)
|
||||
#define SP_PARAMTYPE_FLOAT (2<<1)
|
||||
#define SP_PARAMTYPE_STRING (3<<1)|SP_PARAMFLAG_BYREF
|
||||
#define SP_PARAMTYPE_ARRAY (4<<1)|SP_PARAMFLAG_BYREF
|
||||
#define SP_PARAMTYPE_VARARG (5<<1)
|
||||
|
||||
enum ParamType
|
||||
{
|
||||
Param_Any = SP_PARAMTYPE_ANY,
|
||||
Param_Cell = SP_PARAMTYPE_CELL,
|
||||
Param_Float = SP_PARAMTYPE_FLOAT,
|
||||
Param_String = SP_PARAMTYPE_STRING,
|
||||
Param_Array = SP_PARAMTYPE_ARRAY,
|
||||
Param_VarArgs = SP_PARAMTYPE_VARARG,
|
||||
Param_CellByRef = SP_PARAMTYPE_CELL|SP_PARAMFLAG_BYREF,
|
||||
Param_FloatByRef = SP_PARAMTYPE_FLOAT|SP_PARAMFLAG_BYREF,
|
||||
};
|
||||
|
||||
class IForwardManager : public SMInterface
|
||||
{
|
||||
public:
|
||||
virtual const char *GetInterfaceName()
|
||||
{
|
||||
return SMINTERFACE_FORWARDMANAGER_NAME;
|
||||
}
|
||||
virtual unsigned int GetInterfaceVersion()
|
||||
{
|
||||
return SMINTERFACE_FORWARDMANAGER_VERSION;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a managed forward. This forward exists globally.
|
||||
* The name used to create the forward is used as its public function in all target plugins.
|
||||
* As new non-private plugins become loaded or unloaded, they will be automatically added
|
||||
* or removed. This is ideal for global, static forwards that are never changed.
|
||||
*
|
||||
* @param name Name of public function to use in forward.
|
||||
* @param et Execution type to be used.
|
||||
* @param num_params Number of parameter this function will have.
|
||||
* NOTE: For varargs, this should include the vararg parameter.
|
||||
* @param types Array of type information about each parameter. If NULL, types
|
||||
* are read off the vararg stream.
|
||||
* @param ... If types is NULL, num_params ParamTypes should be pushed.
|
||||
* @return A new IForward on success, NULL if type combination is impossible.
|
||||
*/
|
||||
virtual IForward *CreateForward(const char *name,
|
||||
ExecType et,
|
||||
unsigned int num_params,
|
||||
ParamType *types,
|
||||
...) =0;
|
||||
|
||||
/**
|
||||
* @brief Creates an unmanaged forward. This forward exists privately.
|
||||
* Unlike managed forwards, no functions are ever added by the Manager.
|
||||
* However, functions will be removed automatically if their parent plugin is unloaded.
|
||||
*
|
||||
* @param name Name of forward (unused except for lookup, can be NULL for anonymous).
|
||||
* @param et Execution type to be used.
|
||||
* @param num_params Number of parameter this function will have.
|
||||
* NOTE: For varargs, this should include the vararg parameter.
|
||||
* @param types Array of type information about each parameter. If NULL, types
|
||||
* are read off the vararg stream.
|
||||
* @param ... If types is NULL, num_params ParamTypes should be pushed.
|
||||
* @return A new IChangeableForward on success, NULL if type combination is impossible.
|
||||
*/
|
||||
virtual IChangeableForward *CreateForwardEx(const char *name,
|
||||
ExecType et,
|
||||
int num_params,
|
||||
ParamType *types,
|
||||
...) =0;
|
||||
|
||||
/**
|
||||
* @brief Finds a forward by name. Does not return anonymous forwards (named NULL or "").
|
||||
*
|
||||
* @param name Name of forward.
|
||||
* @param ifchng Optionally store either NULL or an IChangeableForward pointer
|
||||
* depending on type of forward.
|
||||
* @return IForward pointer, or NULL if none found matching the name.
|
||||
*/
|
||||
virtual IForward *FindForward(const char *name, IChangeableForward **ifchng) =0;
|
||||
|
||||
/**
|
||||
* @brief Frees and destroys a forward object.
|
||||
*
|
||||
* @param forward An IForward created by CreateForward() or CreateForwardEx().
|
||||
*/
|
||||
virtual void ReleaseForward(IForward *forward) =0;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* In the AMX Mod X model of forwarding, each forward contained a list of pairs, each pair containing
|
||||
* a function ID and an AMX structure. The forward structure itself did very little but hold parameter types.
|
||||
* An execution call worked like this:
|
||||
* - executeForward() took in a function id and a list of parameters
|
||||
* - for each contained plugin:
|
||||
* - the list of parameters was preprocessed and pushed
|
||||
* - the call was made
|
||||
* - the list was freed and copybacks were made
|
||||
* - return
|
||||
*
|
||||
* The advantages to this is that the system is very easy to implement, and it's fast. The disadvantage is
|
||||
* varargs tend to be very unforgiving and inflexible, and thus weird problems arose with casting. You also
|
||||
* lose flexibility, type checking, and the ability to reasonably use variable arguments lists in the VM.
|
||||
*
|
||||
* SourceMod replaces this forward system with a far more advanced, but a bit bulkier one. The idea is that
|
||||
* each plugin has a table of functions, and each function is an ICallable object. As well as being an ICallable,
|
||||
* each function is an IPluginFunction. An ICallable simply describes the process of adding parameters to a
|
||||
* function call. An IPluginFunction describes the process of actually calling a function and performing allocation,
|
||||
* copybacks, and deallocations.
|
||||
*
|
||||
* A very powerful forward system emerges: a Forward is just a collection of IPluginFunctions. Thus, the same
|
||||
* API can be easily wrapped around a simple list, and it will look transparent to the user.
|
||||
* Advantages:
|
||||
* 1) "SP Forwards" from AMX Mod X are simply IPluginFunctions without a collection.
|
||||
* 2) Forwards are function based, rather than plugin based, and are thus far more flexible at runtime..
|
||||
* 3) [2] Individual functions can be paused and more than one function from the same plugin can be hooked.
|
||||
* 4) [2] One hook type that used to map to many SP Forwards can now be centralized as one Forward.
|
||||
* This helps alleviate messes like Fakemeta.
|
||||
* 5) Parameter pushing is type-checked and allows for variable arguments.
|
||||
*
|
||||
* Note that while #2,3,4 could be added to AMX Mod X, the real binding property is #1, which makes the system
|
||||
* object oriented, rather than AMX Mod X, which hides the objects behind static functions. It is entirely a design
|
||||
* issue, rather than a usability one. The interesting part is when it gets to implementation, which has to cache
|
||||
* parameter pushing until execution. Without this, multiple function calls can be started across one plugin, which
|
||||
* will result in heap corruption given SourcePawn's implementation.
|
||||
*
|
||||
* Observe the new calling process:
|
||||
* - Each parameter is pushed into a local cache using the ICallable interface.
|
||||
* - For each function in the collection:
|
||||
* - Each parameter is decoded and -pushed into the function.
|
||||
* - The call is made.
|
||||
* - Return
|
||||
*
|
||||
* Astute readers will note the (minor) problems:
|
||||
* 1) More memory is used. Specifically, rather than N params of memory, you now have N params * M plugins.
|
||||
* This is because, again, parameters are cached both per-function and per-forward.
|
||||
* 2) There are slightly more calls going around: one extra call for each parameter, since each push is manual.
|
||||
*
|
||||
* HISTORICAL NOTES:
|
||||
* There used to be a # about copy backs.
|
||||
* Note that originally, the Forward implementation was a thin wrapper around IForwards. It did not cache pushes,
|
||||
* and instead immediately fired them to each internal plugin. This was to allow users to know that pointers would
|
||||
* be immediately resolved. Unfortunately, this became extremely burdensome on the API and exposed many problems,
|
||||
* the major (and breaking) one was that two separate Function objects cannot be in a calling process on the same
|
||||
* plugin at once. (:TODO: perhaps prevent that in the IPlugin object?) This is because heap functions lose their order
|
||||
* and become impossible to re-arrange without some global heap tracking mechanis. It also made iterative copy backs
|
||||
* for arrays/references overwhelmingly complex, since each plugin had to have its memory back-patched for each copy.
|
||||
* Therefore, this was scrapped for cached parameters (current implementation), which is the implementation AMX Mod X
|
||||
* uses. It is both faster and works better.
|
||||
*/
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_FORWARDINTERFACE_H_
|
||||
@@ -0,0 +1,252 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_HANDLESYSTEM_INTERFACE_H_
|
||||
#define _INCLUDE_SOURCEMOD_HANDLESYSTEM_INTERFACE_H_
|
||||
|
||||
#include <IShareSys.h>
|
||||
#include <sp_vm_types.h>
|
||||
|
||||
#define SMINTERFACE_HANDLESYSTEM_NAME "IHandleSys"
|
||||
#define SMINTERFACE_HANDLESYSTEM_VERSION 1
|
||||
|
||||
#define DEFAULT_IDENTITY NULL
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
/**
|
||||
* Both of these types have invalid values of '0' for error checking.
|
||||
*/
|
||||
typedef unsigned int HandleType_t;
|
||||
typedef unsigned int Handle_t;
|
||||
|
||||
class SourcePawn::IPluginContext;
|
||||
|
||||
/**
|
||||
* About type checking:
|
||||
* Types can be inherited - a Parent type ("Supertype") can have child types.
|
||||
* When accessing handles, type checking is done. This table shows how this is resolved:
|
||||
*
|
||||
* HANDLE CHECK -> RESULT
|
||||
* ------ ----- ------
|
||||
* Parent Parent Success
|
||||
* Parent Child Fail
|
||||
* Child Parent Success
|
||||
* Child Child Success
|
||||
*/
|
||||
|
||||
enum HandleError
|
||||
{
|
||||
HandleError_None = 0, /* No error */
|
||||
HandleError_Changed, /* The handle has been freed and reassigned */
|
||||
HandleError_Type, /* The handle has a different type registered */
|
||||
HandleError_Freed, /* The handle has been freed */
|
||||
HandleError_Index, /* generic internal indexing error */
|
||||
HandleError_Access, /* No access permitted to free this handle */
|
||||
HandleError_Limit, /* The limited number of handles has been reached */
|
||||
HandleError_Identity, /* The identity token was not usable */
|
||||
HandleError_Owner, /* Owners do not match for this operation */
|
||||
HandleError_Version, /* Unrecognized security structure version */
|
||||
HandleError_Parameter, /* An invalid parameter was passed */
|
||||
HandleError_NoInherit, /* This type cannot be inherited */
|
||||
};
|
||||
|
||||
/**
|
||||
* Access rights specific to a type
|
||||
*/
|
||||
enum HTypeAccessRight
|
||||
{
|
||||
HTypeAccess_Create = 0, /* Handles of this type can be created (DEFAULT=false) */
|
||||
HTypeAccess_Inherit, /* Sub-types can inherit this type (DEFAULT=false) */
|
||||
/* -------------- */
|
||||
HTypeAccess_TOTAL, /* Total number of type access rights */
|
||||
};
|
||||
|
||||
/**
|
||||
* Access rights specific to a Handle. These rights are exclusive.
|
||||
* For example, you do not need "read" access to delete or clone.
|
||||
*/
|
||||
enum HandleAccessRight
|
||||
{
|
||||
HandleAccess_Read, /* Can be read (DEFAULT=ident only) */
|
||||
HandleAccess_Delete, /* Can be deleted (DEFAULT=owner only) */
|
||||
HandleAccess_Clone, /* Can be cloned (DEFAULT=any) */
|
||||
/* ------------- */
|
||||
HandleAccess_TOTAL, /* Total number of access rights */
|
||||
};
|
||||
|
||||
#define HANDLE_RESTRICT_IDENTITY (1<<0) /* Access is restricted to the identity */
|
||||
#define HANDLE_RESTRICT_OWNER (1<<1) /* Access is restricted to the owner */
|
||||
|
||||
/**
|
||||
* This is used to define per-type access rights.
|
||||
*/
|
||||
struct TypeAccess
|
||||
{
|
||||
TypeAccess()
|
||||
{
|
||||
hsVersion = SMINTERFACE_HANDLESYSTEM_VERSION;
|
||||
}
|
||||
unsigned int hsVersion;
|
||||
IdentityToken_t *ident;
|
||||
bool access[HTypeAccess_TOTAL];
|
||||
};
|
||||
|
||||
/**
|
||||
* This is used to define per-Handle access rights.
|
||||
*/
|
||||
struct HandleAccess
|
||||
{
|
||||
HandleAccess()
|
||||
{
|
||||
hsVersion = SMINTERFACE_HANDLESYSTEM_VERSION;
|
||||
}
|
||||
unsigned int hsVersion;
|
||||
unsigned int access[HandleAccess_TOTAL];
|
||||
};
|
||||
|
||||
/**
|
||||
* This pair of tokens is used for identification.
|
||||
*/
|
||||
struct HandleSecurity
|
||||
{
|
||||
IdentityToken_t *pOwner; /* Owner of the Handle */
|
||||
IdentityToken_t *pIdentity; /* Owner of the Type */
|
||||
};
|
||||
|
||||
class IHandleTypeDispatch
|
||||
{
|
||||
public:
|
||||
virtual unsigned int GetDispatchVersion()
|
||||
{
|
||||
return SMINTERFACE_HANDLESYSTEM_VERSION;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Called when destroying a handle. Must be implemented.
|
||||
*/
|
||||
virtual void OnHandleDestroy(HandleType_t type, void *object) =0;
|
||||
};
|
||||
|
||||
class IHandleSys : public SMInterface
|
||||
{
|
||||
public:
|
||||
virtual unsigned int GetInterfaceVersion()
|
||||
{
|
||||
return SMINTERFACE_HANDLESYSTEM_VERSION;
|
||||
}
|
||||
virtual const char *GetInterfaceName()
|
||||
{
|
||||
return SMINTERFACE_HANDLESYSTEM_NAME;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Creates a new Handle type.
|
||||
* NOTE: Currently, a child type may not have its own children.
|
||||
* NOTE: Handle names must be unique if not private.
|
||||
*
|
||||
* @param name Name of handle type (NULL or "" to be anonymous)
|
||||
* @param dispatch Pointer to a valid IHandleTypeDispatch object.
|
||||
* @param parent Parent handle to inherit from, 0 for none.
|
||||
* @param typeAccess Pointer to a TypeAccess object, NULL to use default
|
||||
* or inherited permissions. Pointer can be temporary.
|
||||
* @param hndlAccess Pointer to a HandleAccess object to define default
|
||||
* default permissions on each Handle. NULL to use default
|
||||
* permissions.
|
||||
* @param ident Security token for any permissions. If typeAccess is NULL, this
|
||||
* becomes the owning identity.
|
||||
* @param err Optional pointer to store an error code.
|
||||
* @return A new HandleType_t unique ID, or 0 on failure.
|
||||
*/
|
||||
virtual HandleType_t CreateType(const char *name,
|
||||
IHandleTypeDispatch *dispatch,
|
||||
HandleType_t parent,
|
||||
const TypeAccess *typeAccess,
|
||||
const HandleAccess *hndlAccess,
|
||||
IdentityToken_t *ident,
|
||||
HandleError *err) =0;
|
||||
|
||||
/**
|
||||
* @brief Removes a handle type.
|
||||
* NOTE: This removes all child types.
|
||||
*
|
||||
* @param type Type chain to remove.
|
||||
* @param ident Identity token. Removal fails if the token does not match.
|
||||
* @return True on success, false on failure.
|
||||
*/
|
||||
virtual bool RemoveType(HandleType_t type, IdentityToken_t *ident) =0;
|
||||
|
||||
/**
|
||||
* @brief Finds a handle type by name.
|
||||
*
|
||||
* @param name Name of handle type to find (anonymous not allowed).
|
||||
* @param type Address to store found handle in (if not found, undefined).
|
||||
* @return True if found, false otherwise.
|
||||
*/
|
||||
virtual bool FindHandleType(const char *name, HandleType_t *type) =0;
|
||||
|
||||
/**
|
||||
* @brief Creates a new handle.
|
||||
*
|
||||
* @param type Type to use on the handle.
|
||||
* @param object Object to bind to the handle.
|
||||
* @param owner Owner of the new Handle (may be NULL).
|
||||
* @param ident Identity for type access if needed (may be NULL).
|
||||
* @param err Optional pointer to store an error code.
|
||||
* @return A new Handle_t, or 0 on failure.
|
||||
*/
|
||||
virtual Handle_t CreateHandle(HandleType_t type,
|
||||
void *object,
|
||||
IdentityToken_t *owner,
|
||||
IdentityToken_t *ident,
|
||||
HandleError *err) =0;
|
||||
|
||||
/**
|
||||
* @brief Frees the memory associated with a handle and calls any destructors.
|
||||
* NOTE: This function will decrement the internal reference counter. It will
|
||||
* only perform any further action if the counter hits 0.
|
||||
*
|
||||
* @param type Handle_t identifier to destroy.
|
||||
* @param pSecurity Security information struct (may be NULL).
|
||||
* @return A HandleError error code.
|
||||
*/
|
||||
virtual HandleError FreeHandle(Handle_t handle, const HandleSecurity *pSecurity) =0;
|
||||
|
||||
/**
|
||||
* @brief Clones a handle by adding to its internal reference count. Its data,
|
||||
* type, and security permissions remain the same.
|
||||
*
|
||||
* @param handle Handle to duplicate. Any non-free handle target is valid.
|
||||
* @param newhandle Stores the duplicated handle in the pointer (must not be NULL).
|
||||
* @param newOwner New owner of cloned handle.
|
||||
* @param pSecurity Security information struct (may be NULL).
|
||||
* @return A HandleError error code.
|
||||
*/
|
||||
virtual HandleError CloneHandle(Handle_t handle,
|
||||
Handle_t *newhandle,
|
||||
IdentityToken_t *newOwner,
|
||||
const HandleSecurity *pSecurity) =0;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the contents of a handle.
|
||||
*
|
||||
* @param handle Handle_t from which to retrieve contents.
|
||||
* @param type Expected type to read as. 0 ignores typing rules.
|
||||
* @param pSecurity Security information struct (may be NULL).
|
||||
* @param object Optional address to store object in.
|
||||
* @return HandleError error code.
|
||||
*/
|
||||
virtual HandleError ReadHandle(Handle_t handle,
|
||||
HandleType_t type,
|
||||
const HandleSecurity *pSecurity,
|
||||
void **object) =0;
|
||||
|
||||
/**
|
||||
* @brief Sets access permissions on one or more structures.
|
||||
*
|
||||
* @param pTypeAccess Optional TypeAccess buffer to initialize with the default values.
|
||||
* @param pHandleAccess Optional HandleAccess buffer to initialize with the default values.
|
||||
* @return True on success, false if version is unsupported.
|
||||
*/
|
||||
virtual bool InitAccessDefaults(TypeAccess *pTypeAccess, HandleAccess *pHandleAccess) =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_HANDLESYSTEM_INTERFACE_H_
|
||||
@@ -0,0 +1,155 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_LIBRARY_INTERFACE_SYS_H_
|
||||
#define _INCLUDE_SOURCEMOD_LIBRARY_INTERFACE_SYS_H_
|
||||
|
||||
#include <IShareSys.h>
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
#define SMINTERFACE_LIBRARYSYS_NAME "ILibrarySys"
|
||||
#define SMINTERFACE_LIBRARYSYS_VERSION 1
|
||||
|
||||
class ILibrary
|
||||
{
|
||||
public:
|
||||
virtual ~ILibrary()
|
||||
{
|
||||
/* Calling delete will call CloseLibrary! */
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* @brief Closes dynamic library and invalidates pointer.
|
||||
*/
|
||||
virtual void CloseLibrary() =0;
|
||||
|
||||
/**
|
||||
* @brief Retrieves a symbol pointer from the dynamic library.
|
||||
*
|
||||
* @param symname Symbol name.
|
||||
* @return Symbol pointer, NULL if not found.
|
||||
*/
|
||||
virtual void *GetSymbolAddress(const char *symname) =0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Directory browsing abstraction.
|
||||
*/
|
||||
class IDirectory
|
||||
{
|
||||
public:
|
||||
virtual ~IDirectory()
|
||||
{
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Returns true if there are more files to read, false otherwise.
|
||||
*/
|
||||
virtual bool MoreFiles() =0;
|
||||
|
||||
/**
|
||||
* @brief Advances to the next entry in the stream.
|
||||
*/
|
||||
virtual void NextEntry() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the name of the current entry.
|
||||
*/
|
||||
virtual const char *GetEntryName() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns whether the current entry is a directory.
|
||||
*/
|
||||
virtual bool IsEntryDirectory() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns whether the current entry is a file.
|
||||
*/
|
||||
virtual bool IsEntryFile() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the current entry is valid
|
||||
* (Used similarly to MoreFiles).
|
||||
*/
|
||||
virtual bool IsEntryValid() =0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Contains various operating system specific code.
|
||||
*/
|
||||
class ILibrarySys : public SMInterface
|
||||
{
|
||||
public:
|
||||
virtual const char *GetInterfaceName()
|
||||
{
|
||||
return SMINTERFACE_LIBRARYSYS_NAME;
|
||||
}
|
||||
virtual unsigned int GetInterfaceVersion()
|
||||
{
|
||||
return SMINTERFACE_LIBRARYSYS_VERSION;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Opens a dynamic library file.
|
||||
*
|
||||
* @param path Path to library file (.dll/.so).
|
||||
* @param error Buffer for any error message (may be NULL).
|
||||
* @param err_max Maximum length of error buffer.
|
||||
* @return Pointer to an ILibrary, NULL if failed.
|
||||
*/
|
||||
virtual ILibrary *OpenLibrary(const char *path, char *error, size_t err_max) =0;
|
||||
|
||||
/**
|
||||
* @brief Opens a directory for reading.
|
||||
*
|
||||
* @param path Path to directory.
|
||||
* @return Pointer to an IDirectory, NULL if failed.
|
||||
*/
|
||||
virtual IDirectory *OpenDirectory(const char *path) =0;
|
||||
|
||||
/**
|
||||
* @brief Closes a directory and frees its handle.
|
||||
*
|
||||
* @param dir Pointer to IDirectory.
|
||||
*/
|
||||
virtual void CloseDirectory(IDirectory *dir) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns true if a path exists.
|
||||
*/
|
||||
virtual bool PathExists(const char *path) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the path is a normal file.
|
||||
*/
|
||||
virtual bool IsPathFile(const char *path) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the path is a normal directory.
|
||||
*/
|
||||
virtual bool IsPathDirectory(const char *path) =0;
|
||||
|
||||
/**
|
||||
* @brief Gets a platform-specific error message.
|
||||
* This should only be called when an ILibrary function fails.
|
||||
* Win32 equivalent: GetLastError() + FormatMessage()
|
||||
* POSIX equivalent: errno + strerror()
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param err_max Maximum length of error buffer.
|
||||
*/
|
||||
virtual void GetPlatformError(char *error, size_t err_max) =0;
|
||||
|
||||
/**
|
||||
* @brief Formats a string similar to snprintf(), except
|
||||
* corrects all non-platform compatible path separators to be
|
||||
* the correct platform character.
|
||||
*
|
||||
* @param buffer Output buffer pointer.
|
||||
* @param maxlength Output buffer size.
|
||||
* @param pathfmt Format string of path.
|
||||
* @param ... Format string arguments.
|
||||
*/
|
||||
virtual size_t PathFormat(char *buffer, size_t maxlength, const char *pathfmt, ...) =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_LIBRARY_INTERFACE_SYS_H_
|
||||
@@ -0,0 +1,153 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_PLUGINFUNCTION_INTERFACE_H_
|
||||
#define _INCLUDE_SOURCEMOD_PLUGINFUNCTION_INTERFACE_H_
|
||||
|
||||
#include <IPluginSys.h>
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
#define SM_PARAM_COPYBACK (1<<0) /* Copy an array/reference back after call */
|
||||
|
||||
#define SM_PARAM_STRING_UTF8 (1<<0) /* String should be UTF-8 handled */
|
||||
#define SM_PARAM_STRING_COPY (1<<1) /* String should be copied into the plugin */
|
||||
|
||||
/**
|
||||
* @brief Represents what a function needs to implement in order to be callable.
|
||||
*/
|
||||
class ICallable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Pushes a cell onto the current call.
|
||||
*
|
||||
* @param cell Parameter value to push.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int PushCell(cell_t cell) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes a cell by reference onto the current call.
|
||||
* NOTE: On Execute, the pointer passed will be modified if copyback is enabled.
|
||||
* NOTE: By reference parameters are cached and thus are not read until execution.
|
||||
* This means you cannot push a pointer, change it, and push it again and expect
|
||||
* two different values to come out.
|
||||
*
|
||||
* @param cell Address containing parameter value to push.
|
||||
* @param flags Copy-back flags.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int PushCellByRef(cell_t *cell, int flags) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes a float onto the current call.
|
||||
*
|
||||
* @param float Parameter value to push.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int PushFloat(float number) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes a float onto the current call by reference.
|
||||
* NOTE: On Execute, the pointer passed will be modified if copyback is enabled.
|
||||
* NOTE: By reference parameters are cached and thus are not read until execution.
|
||||
* This means you cannot push a pointer, change it, and push it again and expect
|
||||
* two different values to come out.
|
||||
*
|
||||
* @param float Parameter value to push.
|
||||
& @param flags Copy-back flags.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int PushFloatByRef(float *number, int flags) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes an array of cells onto the current call.
|
||||
* NOTE: On Execute, the pointer passed will be modified if non-NULL and copy-back
|
||||
* is enabled.
|
||||
* NOTE: By reference parameters are cached and thus are not read until execution.
|
||||
* This means you cannot push a pointer, change it, and push it again and expect
|
||||
* two different values to come out.
|
||||
*
|
||||
* @param inarray Array to copy, NULL if no initial array should be copied.
|
||||
* @param cells Number of cells to allocate and optionally read from the input array.
|
||||
* @param phys_addr Optional return address for physical array, if one was made.
|
||||
* @param flags Whether or not changes should be copied back to the input array.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int PushArray(cell_t *inarray,
|
||||
unsigned int cells,
|
||||
cell_t **phys_addr,
|
||||
int flags=0) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes a string onto the current call.
|
||||
*
|
||||
* @param string String to push.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int PushString(const char *string) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes a string or string buffer.
|
||||
* NOTE: On Execute, the pointer passed will be modified if copy-back is enabled.
|
||||
*
|
||||
* @param buffer Pointer to string buffer.
|
||||
* @param length Length of buffer.
|
||||
* @param sz_flags String flags.
|
||||
* @param cp_flags Copy-back flags.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int PushStringEx(char *buffer, size_t length, int sz_flags, int cp_flags) =0;
|
||||
|
||||
/**
|
||||
* @brief Cancels a function call that is being pushed but not yet executed.
|
||||
* This can be used be reset for CallFunction() use.
|
||||
*/
|
||||
virtual void Cancel() =0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Encapsulates a function call in a plugin.
|
||||
* NOTE: Function calls must be atomic to one execution context.
|
||||
* NOTE: This object should not be deleted. It lives for the lifetime of the plugin.
|
||||
*/
|
||||
class IPluginFunction : public ICallable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Executes the forward, resets the pushed parameter list, and performs any copybacks.
|
||||
*
|
||||
* @param result Pointer to store return value in.
|
||||
* @return Error code, if any.
|
||||
*/
|
||||
virtual int Execute(cell_t *result) =0;
|
||||
|
||||
/**
|
||||
* @brief Executes the function with the given parameter array.
|
||||
* Parameters are read in forward order (i.e. index 0 is parameter #1)
|
||||
* NOTE: You will get an error if you attempt to use CallFunction() with
|
||||
* previously pushed parameters.
|
||||
*
|
||||
* @param param Array of cell parameters.
|
||||
* @param num_params Number of parameters to push.
|
||||
* @param result Pointer to store result of function on return.
|
||||
* @return SourcePawn error code (if any).
|
||||
*/
|
||||
virtual int CallFunction(const cell_t *params, unsigned int num_params, cell_t *result) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns which plugin this function belongs to.
|
||||
*
|
||||
* @return IPlugin pointer to parent plugin.
|
||||
*/
|
||||
virtual IPlugin *GetParentPlugin() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the physical address of a by-reference parameter.
|
||||
*
|
||||
* @param Parameter index to read (beginning at 0).
|
||||
* @return Address, or NULL if invalid parameter specified.
|
||||
*/
|
||||
virtual cell_t *GetAddressOfPushedParam(unsigned int param) =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_PLUGINFUNCTION_INTERFACE_H_
|
||||
@@ -0,0 +1,302 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_PLUGINMNGR_INTERFACE_H_
|
||||
#define _INCLUDE_SOURCEMOD_PLUGINMNGR_INTERFACE_H_
|
||||
|
||||
#include <IShareSys.h>
|
||||
#include <sp_vm_api.h>
|
||||
|
||||
#define SMINTERFACE_PLUGINSYSTEM_NAME "IPluginManager"
|
||||
#define SMINTERFACE_PLUGINSYSTEM_VERSION 1
|
||||
|
||||
#define SM_CONTEXTVAR_USER 3
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
class IPlugin;
|
||||
|
||||
/**
|
||||
* @brief Encapsulates plugin public information.
|
||||
*/
|
||||
typedef struct sm_plugininfo_s
|
||||
{
|
||||
const char *name;
|
||||
const char *author;
|
||||
const char *description;
|
||||
const char *version;
|
||||
const char *url;
|
||||
} sm_plugininfo_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Describes the usability status of a plugin.
|
||||
* Note: The status "Loaded" and "Created" are only reachable
|
||||
* during map load.
|
||||
*/
|
||||
enum PluginStatus
|
||||
{
|
||||
Plugin_Running=0, /* Plugin is running */
|
||||
/* All states below are unexecutable */
|
||||
Plugin_Paused, /* Plugin is loaded but paused */
|
||||
Plugin_Error, /* Plugin is loaded but errored/locked */
|
||||
/* All states below do not have all natives */
|
||||
Plugin_Loaded, /* Plugin has passed loading and can be finalized */
|
||||
Plugin_Failed, /* Plugin has a fatal failure */
|
||||
Plugin_Created, /* Plugin is created but not initialized */
|
||||
Plugin_Uncompiled, /* Plugin is not yet compiled by the JIT */
|
||||
Plugin_BadLoad, /* Plugin failed to load */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Describes the object lifetime of a plugin.
|
||||
*/
|
||||
enum PluginType
|
||||
{
|
||||
PluginType_Private, /* Plugin is privately managed and receives no forwards */
|
||||
PluginType_MapUpdated, /* Plugin will never be unloaded unless for updates on mapchange */
|
||||
PluginType_MapOnly, /* Plugin will be removed at mapchange */
|
||||
PluginType_Global, /* Plugin will never be unloaded or updated */
|
||||
};
|
||||
|
||||
class IPluginFunction;
|
||||
|
||||
/**
|
||||
* @brief Encapsulates a run-time plugin as maintained by SourceMod.
|
||||
*/
|
||||
class IPlugin
|
||||
{
|
||||
public:
|
||||
virtual ~IPlugin()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the lifetime of a plugin.
|
||||
*/
|
||||
virtual PluginType GetType() const =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the current API context being used in the plugin.
|
||||
*
|
||||
* @return Pointer to an IPluginContext, or NULL if not loaded.
|
||||
*/
|
||||
virtual SourcePawn::IPluginContext *GetBaseContext() const =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the context structure being used in the plugin.
|
||||
*
|
||||
* @return Pointer to an sp_context_t, or NULL if not loaded.
|
||||
*/
|
||||
virtual sp_context_t *GetContext() const =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the plugin file structure.
|
||||
*
|
||||
* @return Pointer to an sp_plugin_t, or NULL if not loaded.
|
||||
*/
|
||||
virtual const sp_plugin_t *GetPluginStructure() const =0;
|
||||
|
||||
/**
|
||||
* @brief Returns information about the plugin by reference.
|
||||
*
|
||||
* @return Pointer to a sm_plugininfo_t object, NULL if plugin is not loaded.
|
||||
*/
|
||||
virtual const sm_plugininfo_t *GetPublicInfo() const =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the plugin filename (relative to plugins dir).
|
||||
*/
|
||||
virtual const char *GetFilename() const =0;
|
||||
|
||||
/**
|
||||
* @brief Returns true if a plugin is in debug mode, false otherwise.
|
||||
*/
|
||||
virtual bool IsDebugging() const =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the plugin status.
|
||||
*/
|
||||
virtual PluginStatus GetStatus() const =0;
|
||||
|
||||
/**
|
||||
* @brief Sets whether the plugin is paused or not.
|
||||
*
|
||||
* @return True on successful state change, false otherwise.
|
||||
*/
|
||||
virtual bool SetPauseState(bool paused) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the unique serial number of a plugin.
|
||||
*/
|
||||
virtual unsigned int GetSerial() const =0;
|
||||
|
||||
/**
|
||||
* @brief Returns a function by name.
|
||||
*
|
||||
* @param public_name Name of the function.
|
||||
* @return A new IPluginFunction pointer, NULL if not found.
|
||||
*/
|
||||
virtual IPluginFunction *GetFunctionByName(const char *public_name) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns a function by its id.
|
||||
*
|
||||
* @param func_id Function ID.
|
||||
* @return A new IPluginFunction pointer, NULL if not found.
|
||||
*/
|
||||
virtual IPluginFunction *GetFunctionById(funcid_t func_id) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns a plugin's identity token.
|
||||
*/
|
||||
virtual IdentityToken_t *GetIdentity() const =0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Iterates over a list of plugins.
|
||||
*/
|
||||
class IPluginIterator
|
||||
{
|
||||
public:
|
||||
virtual ~IPluginIterator()
|
||||
{
|
||||
};
|
||||
public:
|
||||
/**
|
||||
* @brief Returns true if there are more plugins in the iterator.
|
||||
*/
|
||||
virtual bool MorePlugins() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the plugin at the current iterator position.
|
||||
*/
|
||||
virtual IPlugin *GetPlugin() =0;
|
||||
|
||||
/**
|
||||
* @brief Advances to the next plugin in the iterator.
|
||||
*/
|
||||
virtual void NextPlugin() =0;
|
||||
|
||||
/**
|
||||
* @brief Destroys the iterator object.
|
||||
* Note: You may use 'delete' in lieu of this function.
|
||||
*/
|
||||
virtual void Release() =0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Listens for plugin-oriented events.
|
||||
*/
|
||||
class IPluginsListener
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Called when a plugin is created/mapped into memory.
|
||||
*/
|
||||
virtual void OnPluginCreated(IPlugin *plugin)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when a plugin is fully loaded successfully.
|
||||
*/
|
||||
virtual void OnPluginLoaded(IPlugin *plugin)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when a plugin is unloaded (only if fully loaded).
|
||||
*/
|
||||
virtual void OnPluginUnloaded(IPlugin *plugin)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when a plugin is destroyed.
|
||||
* NOTE: Always called if Created, even if load failed.
|
||||
*/
|
||||
virtual void OnPluginDestroyed(IPlugin *plugin)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Manages the runtime loading and unloading of plugins.
|
||||
*/
|
||||
class IPluginManager : public SMInterface
|
||||
{
|
||||
public:
|
||||
virtual const char *GetInterfaceName()
|
||||
{
|
||||
return SMINTERFACE_PLUGINSYSTEM_NAME;
|
||||
}
|
||||
|
||||
virtual unsigned int GetInterfaceVersion()
|
||||
{
|
||||
return SMINTERFACE_PLUGINSYSTEM_VERSION;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Attempts to load a plugin.
|
||||
*
|
||||
* @param path Path and filename of plugin, relative to plugins folder.
|
||||
* @param debug Whether or not to default the plugin into debug mode.
|
||||
* @param type Lifetime of the plugin.
|
||||
* @param error Buffer to hold any error message.
|
||||
* @param err_max Maximum length of error message buffer.
|
||||
* @return A new plugin pointer on success, false otherwise.
|
||||
*/
|
||||
virtual IPlugin *LoadPlugin(const char *path,
|
||||
bool debug,
|
||||
PluginType type,
|
||||
char error[],
|
||||
size_t err_max) =0;
|
||||
|
||||
/**
|
||||
* @brief Attempts to unload a plugin.
|
||||
*
|
||||
* @param plugin Pointer to the plugin handle.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
virtual bool UnloadPlugin(IPlugin *plugin) =0;
|
||||
|
||||
/**
|
||||
* @brief Finds a plugin by its context.
|
||||
* Note: This function should be considered O(1).
|
||||
*
|
||||
* @param ctx Pointer to an sp_context_t.
|
||||
* @return Pointer to a matching IPlugin, or NULL if none found.
|
||||
*/
|
||||
virtual IPlugin *FindPluginByContext(const sp_context_t *ctx) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of plugins (both failed and loaded).
|
||||
*
|
||||
* @return The number of internally cached plugins.
|
||||
*/
|
||||
virtual unsigned int GetPluginCount() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns a pointer that can be used to iterate through plugins.
|
||||
* Note: This pointer must be freed using EITHER delete OR IPluginIterator::Release().
|
||||
*/
|
||||
virtual IPluginIterator *GetPluginIterator() =0;
|
||||
|
||||
/**
|
||||
* @brief Adds a plugin manager listener.
|
||||
*
|
||||
* @param listener Pointer to a listener.
|
||||
*/
|
||||
virtual void AddPluginsListener(IPluginsListener *listener) =0;
|
||||
|
||||
/**
|
||||
* @brief Removes a plugin listener.
|
||||
*
|
||||
* @param listener Pointer to a listener.
|
||||
*/
|
||||
virtual void RemovePluginsListener(IPluginsListener *listener) =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_PLUGINMNGR_INTERFACE_H_
|
||||
@@ -0,0 +1,90 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_ROOT_CONSOLE_MENU_H_
|
||||
#define _INCLUDE_SOURCEMOD_ROOT_CONSOLE_MENU_H_
|
||||
|
||||
/**
|
||||
* @brief Note: This interface is not exposed.
|
||||
* The reason should be obvious: we do not want users touching the "root" console menu.
|
||||
* If we exposed this, every little plugin would be dropping down a silly set of user commands,
|
||||
* whereas this menu is explicitly provided for stuff that only Core itself is capable of managing.
|
||||
*/
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
/**
|
||||
* @brief Handles a root console menu action.
|
||||
*/
|
||||
class IRootConsoleCommand
|
||||
{
|
||||
public:
|
||||
virtual void OnRootConsoleCommand(const char *command, unsigned int argcount) =0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Manages the root console menu - the "sm" command for servers.
|
||||
*/
|
||||
class IRootConsole
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Adds a root console command handler. The command must be unique.
|
||||
*
|
||||
* @param cmd String containing the console command.
|
||||
* @param text Description text.
|
||||
* @param pHandler An IRootConsoleCommand pointer to handle the command.
|
||||
* @return True on success, false on too many commands or duplicate command.
|
||||
*/
|
||||
virtual bool AddRootConsoleCommand(const char *cmd, const char *text, IRootConsoleCommand *pHandler) =0;
|
||||
|
||||
/**
|
||||
* @brief Removes a root console command handler.
|
||||
*
|
||||
* @param cmd String containing the console command.
|
||||
* @param pHandler An IRootConsoleCommand pointer for verification.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
virtual bool RemoveRootConsoleCommand(const char *cmd, IRootConsoleCommand *pHandler) =0;
|
||||
|
||||
/**
|
||||
* @brief Prints text back to the console.
|
||||
*
|
||||
* @param fmt Format of string.
|
||||
* @param ... Format arguments.
|
||||
*/
|
||||
virtual void ConsolePrint(const char *fmt, ...) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the string of an argument.
|
||||
*
|
||||
* @param argno The index of the argument.
|
||||
* @return A string containing the argument, or nothing if invalid.
|
||||
*/
|
||||
virtual const char *GetArgument(unsigned int argno) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of arguments.
|
||||
*
|
||||
* @return Number of arguments.
|
||||
*/
|
||||
virtual unsigned int GetArgumentCount() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the entire argument string.
|
||||
*
|
||||
* @return String containing all arguments.
|
||||
*/
|
||||
virtual const char *GetArguments() =0;
|
||||
|
||||
/**
|
||||
* @brief Draws a generic command/description pair.
|
||||
* NOTE: The pair is currently four spaces indented and 16-N spaces of separation,
|
||||
* N being the length of the command name. This is subject to change in case we
|
||||
* account for Valve's font choices.
|
||||
*
|
||||
* @param option String containing the command option.
|
||||
* @param description String containing the command description.
|
||||
*/
|
||||
virtual void DrawGenericOption(const char *cmd, const char *text) =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_ROOT_CONSOLE_MENU_H_
|
||||
@@ -0,0 +1,149 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_IFACE_SHARE_SYS_H_
|
||||
#define _INCLUDE_SOURCEMOD_IFACE_SHARE_SYS_H_
|
||||
|
||||
#include <sp_vm_types.h>
|
||||
|
||||
#define NO_IDENTITY 0
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
class IExtension;
|
||||
struct IdentityToken_t;
|
||||
typedef unsigned int HandleType_t;
|
||||
typedef HandleType_t IdentityType_t;
|
||||
/**
|
||||
* @brief Defines the base functionality required by a shared interface.
|
||||
*/
|
||||
class SMInterface
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Must return an integer defining the interface's version.
|
||||
*/
|
||||
virtual unsigned int GetInterfaceVersion() =0;
|
||||
|
||||
/**
|
||||
* @brief Must return a string defining the interface's unique name.
|
||||
*/
|
||||
virtual const char *GetInterfaceName() =0;
|
||||
|
||||
/**
|
||||
* @brief Must return whether the requested version number is backwards comaptible.
|
||||
* Note: This can be overridden for breaking changes or custom versioning.
|
||||
*
|
||||
* @param version Version number to compare against.
|
||||
* @return True if compatible, false otherwise.
|
||||
*/
|
||||
virtual bool IsVersionCompatible(unsigned int version)
|
||||
{
|
||||
if (version > GetInterfaceVersion())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Tracks dependencies and fires dependency listeners.
|
||||
*/
|
||||
class IShareSys
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Adds an interface to the global interface system.
|
||||
*
|
||||
* @param myself Object adding this interface, in order to track dependencies.
|
||||
* @param iface Interface pointer (must be unique).
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
virtual bool AddInterface(IExtension *myself, SMInterface *iface) =0;
|
||||
|
||||
/**
|
||||
* @brief Requests an interface from the global interface system.
|
||||
* If found, the interface's internal reference count will be increased.
|
||||
*
|
||||
* @param iface_name Interface name.
|
||||
* @param iface_vers Interface version to attempt to match.
|
||||
* @param myself Object requesting this interface, in order to track dependencies.
|
||||
* @param pIface Pointer to store the return value in.
|
||||
*/
|
||||
virtual bool RequestInterface(const char *iface_name,
|
||||
unsigned int iface_vers,
|
||||
IExtension *myself,
|
||||
SMInterface **pIface) =0;
|
||||
|
||||
/**
|
||||
* @brief Adds a list of natives to the global native pool, to be bound on plugin load.
|
||||
* NOTE: Adding natives currently does not bind them to any loaded plugins.
|
||||
* You must manually bind late natives.
|
||||
*
|
||||
* @param token Identity token of parent object.
|
||||
* @param natives Array of natives to add. The last entry must have NULL members.
|
||||
*/
|
||||
virtual void AddNatives(IExtension *myself, const sp_nativeinfo_t *natives) =0;
|
||||
|
||||
/**
|
||||
* @brief Creates a new identity type.
|
||||
* NOTE: Module authors should never need to use this. Due to the current implementation,
|
||||
* there is a hardcoded limit of 15 types. Core uses up a few, so think carefully!
|
||||
*
|
||||
* @param name String containing type name. Must not be empty or NULL.
|
||||
* @return A new HandleType_t identifier, or 0 on failure.
|
||||
*/
|
||||
virtual IdentityType_t CreateIdentType(const char *name) =0;
|
||||
|
||||
/**
|
||||
* @brief Finds an identity type by name.
|
||||
* DEFAULT IDENTITY TYPES:
|
||||
* "PLUGIN" - An IPlugin object.
|
||||
* "MODULE" - An IModule object.
|
||||
* "CORE" - An SMGlobalClass or other singleton.
|
||||
*
|
||||
* @param name String containing type name to search for.
|
||||
* @return A HandleType_t identifier if found, 0 otherwise.
|
||||
*/
|
||||
virtual IdentityType_t FindIdentType(const char *name) =0;
|
||||
|
||||
/**
|
||||
* @brief Creates a new identity token. This token is guaranteed to be unique
|
||||
* amongst all other open identities.
|
||||
*
|
||||
* @param type Identity type.
|
||||
* @return A new IdentityToken_t identifier.
|
||||
*/
|
||||
virtual IdentityToken_t *CreateIdentity(IdentityType_t type) =0;
|
||||
|
||||
/**
|
||||
* @brief Destroys an identity type. Note that this will delete any identities
|
||||
* that are under this type.
|
||||
*
|
||||
* @param type Identity type.
|
||||
*/
|
||||
virtual void DestroyIdentType(IdentityType_t type) =0;
|
||||
|
||||
/**
|
||||
* @brief Destroys an identity token. Any handles being owned by this token, or
|
||||
* any handles being
|
||||
*
|
||||
* @param identity Identity to remove.
|
||||
*/
|
||||
virtual void DestroyIdentity(IdentityToken_t *identity) =0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Requires an extension. This tells SourceMod that without this extension,
|
||||
* your extension should not be loaded. The name should not include the ".dll" or
|
||||
* the ".so" part of the file name.
|
||||
*
|
||||
* @param myself IExtension pointer to yourself.
|
||||
* @param filename File of extension to require.
|
||||
* @param require Whether or not this extension is a required dependency.
|
||||
* @param autoload Whether or not to autoload this extension.
|
||||
*/
|
||||
virtual void AddDependency(IExtension *myself, const char *filename, bool require, bool autoload) =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_IFACE_SHARE_SYS_H_
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_MAIN_HELPER_INTERFACE_H_
|
||||
#define _INCLUDE_SOURCEMOD_MAIN_HELPER_INTERFACE_H_
|
||||
|
||||
#include <IShareSys.h>
|
||||
|
||||
#define SMINTERFACE_SOURCEMOD_NAME "ISourceMod"
|
||||
#define SMINTERFACE_SOURCEMOD_VERSION 1
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
enum PathType
|
||||
{
|
||||
Path_None = 0,
|
||||
Path_Game,
|
||||
Path_SM,
|
||||
};
|
||||
|
||||
class ISourceMod : public SMInterface
|
||||
{
|
||||
public:
|
||||
virtual const char *GetInterfaceName()
|
||||
{
|
||||
return SMINTERFACE_SOURCEMOD_NAME;
|
||||
}
|
||||
virtual unsigned int GetInterfaceVersion()
|
||||
{
|
||||
return SMINTERFACE_SOURCEMOD_VERSION;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Returns the full path to the mod directory.
|
||||
*
|
||||
* @return A string containing the full mod path.
|
||||
*/
|
||||
virtual const char *GetModPath() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the full path to the SourceMod directory.
|
||||
*
|
||||
* @return A string containing the full SourceMod path.
|
||||
*/
|
||||
virtual const char *GetSourceModPath() =0;
|
||||
|
||||
/**
|
||||
* @brief Builds a platform path for a specific target base path.
|
||||
*
|
||||
* @param type Type of path to use as a base.
|
||||
* @param buffer Buffer to write to.
|
||||
* @param maxlength Size of buffer.
|
||||
* @param format Format string.
|
||||
* @param ... Format arguments.
|
||||
* @return Number of bytes written.
|
||||
*/
|
||||
virtual size_t BuildPath(PathType type, char *buffer, size_t maxlength, char *format, ...) =0;
|
||||
|
||||
/**
|
||||
* @brief Logs a message to the SourceMod logs.
|
||||
*
|
||||
* @param format Message format.
|
||||
* @param ... Message format parameters.
|
||||
*/
|
||||
virtual void LogMessage(IExtension *pExt, const char *format, ...) =0;
|
||||
|
||||
/**
|
||||
* @brief Logs a message to the SourceMod error logs.
|
||||
*
|
||||
* @param format Message format.
|
||||
* @param ... Message format parameters.
|
||||
*/
|
||||
virtual void LogError(IExtension *pExt, const char *format, ...) =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_MAIN_HELPER_INTERFACE_H_
|
||||
@@ -0,0 +1,316 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||
#define _INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||
|
||||
#include <IShareSys.h>
|
||||
|
||||
namespace SourceMod
|
||||
{
|
||||
/**
|
||||
* The INI file format is defined as:
|
||||
* WHITESPACE: 0x20, \n, \t, \r
|
||||
* IDENTIFIER: A-Z a-z 0-9 _ - , + . $ ? /
|
||||
* STRING: Any set of symbols
|
||||
*
|
||||
* Basic syntax is comprised of SECTIONs.
|
||||
* A SECTION is defined as:
|
||||
* [SECTIONNAME]
|
||||
* OPTION
|
||||
* OPTION
|
||||
* OPTION...
|
||||
*
|
||||
* SECTIONNAME is an IDENTIFIER.
|
||||
* OPTION can be repeated any number of times, once per line.
|
||||
* OPTION is defined as one of:
|
||||
* KEY = "VALUE"
|
||||
* KEY = VALUE
|
||||
* KEY
|
||||
* Where KEY is an IDENTIFIER and VALUE is a STRING.
|
||||
*
|
||||
* WHITESPACE should always be omitted.
|
||||
* COMMENTS should be stripped, and are defined as text occuring in:
|
||||
* ;<TEXT>
|
||||
*
|
||||
* Example file below. Note that
|
||||
* The second line is technically invalid. The event handler
|
||||
* must decide whether this should be allowed.
|
||||
* --FILE BELOW--
|
||||
* [gaben]
|
||||
* hi = clams
|
||||
* bye = "NO CLAMS"
|
||||
*
|
||||
* [valve]
|
||||
* cannot
|
||||
* maintain
|
||||
* products
|
||||
*/
|
||||
class ITextListener_INI
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Called when a new section is encountered in an INI file.
|
||||
*
|
||||
* @param section Name of section in between the [ and ] characters.
|
||||
* @param invalid_tokens True if invalid tokens were detected in the name.
|
||||
* @param close_bracket True if a closing bracket was detected, false otherwise.
|
||||
* @param extra_tokens True if extra tokens were detected on the line.
|
||||
* @param curtok Contains current token in the line where the section name starts.
|
||||
* You can add to this offset when failing to point to a token.
|
||||
* @return True to keep parsing, false otherwise.
|
||||
*/
|
||||
virtual bool ReadINI_NewSection(const char *section,
|
||||
bool invalid_tokens,
|
||||
bool close_bracket,
|
||||
bool extra_tokens,
|
||||
unsigned int *curtok)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when encountering a key/value pair in an INI file.
|
||||
*
|
||||
* @param key Name of key.
|
||||
* @param value String containing value (with quotes stripped, if any).
|
||||
* @param invalid_tokens Whether or not the key contained invalid tokens.
|
||||
* @param equal_token There was an '=' sign present (in case the value is missing).
|
||||
* @param quotes Whether value was enclosed in quotes.
|
||||
* @param curtoken Contains the token index of the start of the value string.
|
||||
* This can be changed when returning false.
|
||||
* @return True to keep parsing, false otherwise.
|
||||
*/
|
||||
virtual bool ReadINI_KeyValue(const char *key,
|
||||
const char *value,
|
||||
bool invalid_tokens,
|
||||
bool equal_token,
|
||||
bool quotes,
|
||||
unsigned int *curtok)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called after a line has been preprocessed, if it has text.
|
||||
*
|
||||
* @param line Contents of line.
|
||||
* @param curtok Pointer to optionally store failed position in string.
|
||||
* @return True to keep parsing, false otherwise.
|
||||
*/
|
||||
virtual bool ReadINI_RawLine(const char *line, unsigned int *cutok)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* :TODO: write this in CFG (context free grammar) format so it makes sense
|
||||
*
|
||||
* The SMC file format is defined as:
|
||||
* WHITESPACE: 0x20, \n, \t, \r
|
||||
* IDENTIFIER: Any ASCII character EXCLUDING ", {, }, ;, //, /*, or WHITESPACE.
|
||||
* STRING: Any set of symbols enclosed in quotes.
|
||||
* Note: if a STRING does not have quotes, it is parsed as an IDENTIFIER.
|
||||
*
|
||||
* Basic syntax is comprised of SECTIONBLOCKs.
|
||||
* A SECTIONBLOCK defined as:
|
||||
*
|
||||
* SECTIONNAME
|
||||
* {
|
||||
* OPTION
|
||||
* }
|
||||
*
|
||||
* OPTION can be repeated any number of times inside a SECTIONBLOCK.
|
||||
* A new line will terminate an OPTION, but there can be more than one OPTION per line.
|
||||
* OPTION is defined any of:
|
||||
* "KEY" "VALUE"
|
||||
* SECTIONBLOCK
|
||||
*
|
||||
* SECTIONNAME, KEY, VALUE, and SINGLEKEY are strings
|
||||
* SECTIONNAME cannot have trailing characters if quoted, but the quotes can be optionally removed.
|
||||
* If SECTIONNAME is not enclosed in quotes, the entire sectionname string is used (minus surrounding whitespace).
|
||||
* If KEY is not enclosed in quotes, the key is terminated at first whitespace.
|
||||
* If VALUE is not properly enclosed in quotes, the entire value string is used (minus surrounding whitespace).
|
||||
* The VALUE may have inner quotes, but the key string may not.
|
||||
*
|
||||
* For an example, see configs/permissions.cfg
|
||||
*
|
||||
* WHITESPACE should be ignored.
|
||||
* Comments are text occuring inside the following tokens, and should be stripped
|
||||
* unless they are inside literal strings:
|
||||
* ;<TEXT>
|
||||
* //<TEXT>
|
||||
* /*<TEXT> */
|
||||
|
||||
enum SMCParseResult
|
||||
{
|
||||
SMCParse_Continue, //continue parsing
|
||||
SMCParse_Halt, //stop parsing here
|
||||
SMCParse_HaltFail //stop parsing and return failure
|
||||
};
|
||||
|
||||
enum SMCParseError
|
||||
{
|
||||
SMCParse_Okay = 0, //no error
|
||||
SMCParse_StreamOpen, //stream failed to open
|
||||
SMCParse_StreamError, //the stream died... somehow
|
||||
SMCParse_Custom, //a custom handler threw an error
|
||||
SMCParse_InvalidSection1, //a section was declared without quotes, and had extra tokens
|
||||
SMCParse_InvalidSection2, //a section was declared without any header
|
||||
SMCParse_InvalidSection3, //a section ending was declared with too many unknown tokens
|
||||
SMCParse_InvalidSection4, //a section ending has no matching beginning
|
||||
SMCParse_InvalidSection5, //a section beginning has no matching ending
|
||||
SMCParse_InvalidTokens, //there were too many unidentifiable strings on one line
|
||||
SMCParse_TokenOverflow, //the token buffer overflowed
|
||||
SMCParse_InvalidProperty1, //a property was declared outside of any section
|
||||
};
|
||||
|
||||
class ITextListener_SMC
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Called when starting parsing.
|
||||
*/
|
||||
virtual void ReadSMC_ParseStart()
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Called when ending parsing.
|
||||
*
|
||||
* @param halted True if abnormally halted, false otherwise.
|
||||
* @param failed True if parsing failed, false otherwise.
|
||||
*/
|
||||
virtual void ReadSMC_ParseEnd(bool halted, bool failed)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when a warning occurs.
|
||||
* @param error By-reference variable containing the error message of the warning.
|
||||
* @param tokens Pointer to the token stream causing the error.
|
||||
* @return SMCParseResult directive.
|
||||
*/
|
||||
virtual SMCParseResult ReadSMC_OnWarning(SMCParseError &error, const char *tokens)
|
||||
{
|
||||
return SMCParse_HaltFail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when entering a new section
|
||||
*
|
||||
* @param name Name of section, with the colon omitted.
|
||||
* @param opt_quotes Whether or not the option string was enclosed in quotes.
|
||||
* @return SMCParseResult directive.
|
||||
*/
|
||||
virtual SMCParseResult ReadSMC_NewSection(const char *name, bool opt_quotes)
|
||||
{
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when encountering a key/value pair in a section.
|
||||
*
|
||||
* @param key Key string.
|
||||
* @param value Value string. If no quotes were specified, this will be NULL,
|
||||
and key will contain the entire string.
|
||||
* @param key_quotes Whether or not the key was in quotation marks.
|
||||
* @param value_quotes Whether or not the value was in quotation marks.
|
||||
* @return SMCParseResult directive.
|
||||
*/
|
||||
virtual SMCParseResult ReadSMC_KeyValue(const char *key,
|
||||
const char *value,
|
||||
bool key_quotes,
|
||||
bool value_quotes)
|
||||
{
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called when leaving the current section.
|
||||
*
|
||||
* @return SMCParseResult directive.
|
||||
*/
|
||||
virtual SMCParseResult ReadSMC_LeavingSection()
|
||||
{
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Called after an input line has been preprocessed.
|
||||
*
|
||||
* @param line String containing line input.
|
||||
* @param curline Number of line in file.
|
||||
* @return SMCParseResult directive.
|
||||
*/
|
||||
virtual SMCParseResult ReadSMC_RawLine(const char *line, unsigned int curline)
|
||||
{
|
||||
return SMCParse_Continue;
|
||||
}
|
||||
};
|
||||
|
||||
#define SMINTERFACE_TEXTPARSERS_NAME "ITextParsers"
|
||||
#define SMINTERFACE_TEXTPARSERS_VERSION 1
|
||||
|
||||
class ITextParsers : public SMInterface
|
||||
{
|
||||
public:
|
||||
virtual const char *GetInterfaceName()
|
||||
{
|
||||
return SMINTERFACE_TEXTPARSERS_NAME;
|
||||
}
|
||||
virtual unsigned int GetInterfaceVersion()
|
||||
{
|
||||
return SMINTERFACE_TEXTPARSERS_VERSION;
|
||||
}
|
||||
public:
|
||||
/**
|
||||
* @brief Parses an INI-format file.
|
||||
*
|
||||
* @param file Path to file.
|
||||
* @param ini_listener Event handler for reading file.
|
||||
* @param line If non-NULL, will contain last line parsed (0 if file could not be opened).
|
||||
* @param col If non-NULL, will contain last column parsed (undefined if file could not be opened).
|
||||
* @return True if parsing succeded, false if file couldn't be opened or there was a syntax error.
|
||||
*/
|
||||
virtual bool ParseFile_INI(const char *file,
|
||||
ITextListener_INI *ini_listener,
|
||||
unsigned int *line,
|
||||
unsigned int *col) =0;
|
||||
|
||||
/**
|
||||
* @brief Parses an SMC-format text file.
|
||||
* Note that the parser makes every effort to obey broken syntax.
|
||||
* For example, if an open brace is missing, but the section name has a colon,
|
||||
* it will let you know. It is up to the event handlers to decide whether to be strict or not.
|
||||
*
|
||||
* @param file Path to file.
|
||||
* @param smc_listener Event handler for reading file.
|
||||
* @param line If non-NULL, will contain last line parsed (0 if file could not be opened).
|
||||
* @param col If non-NULL, will contain last column parsed (undefined if file could not be opened).
|
||||
* @return An SMCParseError result code.
|
||||
*/
|
||||
virtual SMCParseError ParseFile_SMC(const char *file,
|
||||
ITextListener_SMC *smc_listener,
|
||||
unsigned int *line,
|
||||
unsigned int *col) =0;
|
||||
|
||||
/**
|
||||
* @brief Converts an SMCParseError to a stirng.
|
||||
*
|
||||
* @param err SMCParseError.
|
||||
* @return String error message, or NULL if none.
|
||||
*/
|
||||
virtual const char *GetSMCErrorString(SMCParseError err) =0;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Returns the number of bytes that a multi-byte character contains in a UTF-8 stream.
|
||||
* If the current character is not multi-byte, the function returns 1.
|
||||
*
|
||||
* @param stream Pointer to multi-byte ANSI character string.
|
||||
* @return Number of bytes in current character.
|
||||
*/
|
||||
virtual unsigned int GetUTF8CharBytes(const char *stream) =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_TEXTPARSERS_INTERFACE_H_
|
||||
@@ -0,0 +1,5 @@
|
||||
#include "extension.h"
|
||||
|
||||
Sample g_Sample;
|
||||
|
||||
SMEXT_LINK(&g_Sample);
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
|
||||
#include "smsdk_ext.h"
|
||||
|
||||
/**
|
||||
* @brief Sample implementation of the SDK Extension.
|
||||
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
|
||||
*/
|
||||
class Sample : public SDKExtension
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief This is called after the initial loading sequence has been processed.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param err_max Size of error message buffer.
|
||||
* @param late Whether or not the module was loaded after map load.
|
||||
* @return True to succeed loading, false to fail.
|
||||
*/
|
||||
//virtual bool SDK_OnLoad(char *error, size_t err_max, bool late);
|
||||
|
||||
/**
|
||||
* @brief This is called right before the extension is unloaded.
|
||||
*/
|
||||
//virtual void SDK_OnUnload();
|
||||
|
||||
/**
|
||||
* @brief This is called once all known extensions have been loaded.
|
||||
* Note: It is is a good idea to add natives here, if any are provided.
|
||||
*/
|
||||
//virtual void SDK_OnAllLoaded();
|
||||
|
||||
/**
|
||||
* @brief Called when the pause state is changed.
|
||||
*/
|
||||
//virtual void SDK_OnPauseChange(bool paused);
|
||||
|
||||
/**
|
||||
* @brief this is called when Core wants to know if your extension is working.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param err_max Size of error message buffer.
|
||||
* @return True if working, false otherwise.
|
||||
*/
|
||||
//virtual void QueryRunning(char *error, size_t maxlength);
|
||||
public:
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
/**
|
||||
* Read smext_base.h for documentation on these.
|
||||
*/
|
||||
|
||||
//virtual bool SDK_OnMetamodLoad(char *error, size_t err_max, bool late);
|
||||
//virtual bool SDK_OnMetamodUnload(char *error, size_t err_max);
|
||||
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t err_max);
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
|
||||
@@ -0,0 +1,26 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 9.00
|
||||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sdk", "sdk.vcproj", "{B3E797CF-4E77-4C9D-B8A8-7589B6902206}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug - Metamod|Win32 = Debug - Metamod|Win32
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release - Metamod|Win32 = Release - Metamod|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug - Metamod|Win32.ActiveCfg = Debug - Metamod|Win32
|
||||
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug - Metamod|Win32.Build.0 = Debug - Metamod|Win32
|
||||
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release - Metamod|Win32.ActiveCfg = Release - Metamod|Win32
|
||||
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release - Metamod|Win32.Build.0 = Release - Metamod|Win32
|
||||
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B3E797CF-4E77-4C9D-B8A8-7589B6902206}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,368 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="sdk"
|
||||
ProjectGUID="{B3E797CF-4E77-4C9D-B8A8-7589B6902206}"
|
||||
RootNamespace="sdk"
|
||||
Keyword="Win32Proj"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\sample.ext.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\sample.ext.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug - Metamod|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SMEXT_CONF_METAMOD"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="tier0.lib"
|
||||
OutputFile="$(OutDir)\sample.ext.dll"
|
||||
LinkIncremental="2"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release - Metamod|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;SDK_EXPORTS;_CRT_SECURE_NO_DEPRECATE;SMEXT_CONF_METAMOD"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
OutputFile="$(OutDir)\sample.ext.dll"
|
||||
LinkIncremental="1"
|
||||
GenerateDebugInformation="true"
|
||||
SubSystem="2"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\extension.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\smsdk_ext.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\extension.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\smsdk_config.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\smsdk_ext.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||
|
||||
/* Basic information exposed publically */
|
||||
#define SMEXT_CONF_NAME "Sample Extension"
|
||||
#define SMEXT_CONF_DESCRIPTION "Sample extension to help developers"
|
||||
#define SMEXT_CONF_VERSION "0.0.0.0"
|
||||
#define SMEXT_CONF_AUTHOR "AlliedModders"
|
||||
#define SMEXT_CONF_URL "http://www.sourcemod.net/"
|
||||
#define SMEXT_CONF_LOGTAG "SAMPLE"
|
||||
#define SMEXT_CONF_LICENSE "GPL"
|
||||
#define SMEXT_CONF_DATESTRING __DATE__
|
||||
|
||||
/**
|
||||
* @brief Exposes plugin's main interface.
|
||||
*/
|
||||
#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name;
|
||||
|
||||
/**
|
||||
* @brief Sets whether or not this plugin required Metamod.
|
||||
* NOTE: Uncomment to enable, comment to disable.
|
||||
* NOTE: This is enabled automatically if a Metamod build is chosen in
|
||||
* the Visual Studio project.
|
||||
*/
|
||||
//#define SMEXT_CONF_METAMOD
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
|
||||
@@ -0,0 +1,279 @@
|
||||
#include <stdio.h>
|
||||
#include "smsdk_ext.h"
|
||||
|
||||
IShareSys *g_pShareSys = NULL;
|
||||
IExtension *myself = NULL;
|
||||
IHandleSys *g_pHandleSys = NULL;
|
||||
ISourceMod *g_pSM = NULL;
|
||||
|
||||
PLATFORM_EXTERN_C IExtensionInterface *GetSMExtAPI()
|
||||
{
|
||||
return g_pExtensionIface;
|
||||
}
|
||||
|
||||
SDKExtension::SDKExtension()
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_SourceMMLoaded = false;
|
||||
m_WeAreUnloaded = false;
|
||||
m_WeGotPauseChange = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SDKExtension::OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t err_max, bool late)
|
||||
{
|
||||
g_pShareSys = sys;
|
||||
myself = me;
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_WeAreUnloaded = true;
|
||||
|
||||
if (!m_SourceMMLoaded)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, err_max, "Metamod attach failed");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
SM_GET_IFACE(HANDLESYSTEM, g_pHandleSys);
|
||||
SM_GET_IFACE(SOURCEMOD, g_pSM);
|
||||
|
||||
if (SDK_OnLoad(error, err_max, late))
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_WeAreUnloaded = true;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SDKExtension::IsMetamodExtension()
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void SDKExtension::OnExtensionPauseChange(bool state)
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_WeGotPauseChange = true;
|
||||
#endif
|
||||
SDK_OnPauseChange(state);
|
||||
}
|
||||
|
||||
void SDKExtension::OnExtensionsAllLoaded()
|
||||
{
|
||||
SDK_OnAllLoaded();
|
||||
}
|
||||
|
||||
void SDKExtension::OnExtensionUnload()
|
||||
{
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
m_WeAreUnloaded = true;
|
||||
#endif
|
||||
SDK_OnUnload();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionAuthor()
|
||||
{
|
||||
return SMEXT_CONF_AUTHOR;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionDateString()
|
||||
{
|
||||
return SMEXT_CONF_DATESTRING;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionDescription()
|
||||
{
|
||||
return SMEXT_CONF_DESCRIPTION;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionVerString()
|
||||
{
|
||||
return SMEXT_CONF_VERSION;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionName()
|
||||
{
|
||||
return SMEXT_CONF_NAME;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionTag()
|
||||
{
|
||||
return SMEXT_CONF_LOGTAG;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetExtensionURL()
|
||||
{
|
||||
return SMEXT_CONF_URL;
|
||||
}
|
||||
|
||||
bool SDKExtension::SDK_OnLoad(char *error, size_t err_max, bool late)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void SDKExtension::SDK_OnUnload()
|
||||
{
|
||||
}
|
||||
|
||||
void SDKExtension::SDK_OnPauseChange(bool paused)
|
||||
{
|
||||
}
|
||||
|
||||
void SDKExtension::SDK_OnAllLoaded()
|
||||
{
|
||||
}
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
|
||||
PluginId g_PLID = 0;
|
||||
ISmmPlugin *g_PLAPI = NULL;
|
||||
SourceHook::ISourceHook *g_SHPtr = NULL;
|
||||
ISmmAPI *g_SMAPI = NULL;
|
||||
|
||||
IVEngineServer *engine = NULL;
|
||||
IServerGameDLL *gamedll = NULL;
|
||||
|
||||
SMM_API void *PL_EXPOSURE(const char *name, int *code)
|
||||
{
|
||||
if (name && !strcmp(name, PLAPI_NAME))
|
||||
{
|
||||
if (code)
|
||||
{
|
||||
*code = IFACE_OK;
|
||||
}
|
||||
return static_cast<void *>(g_pExtensionIface);
|
||||
}
|
||||
|
||||
if (code)
|
||||
{
|
||||
*code = IFACE_FAILED;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool SDKExtension::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool late)
|
||||
{
|
||||
PLUGIN_SAVEVARS();
|
||||
|
||||
GET_V_IFACE_ANY(serverFactory, gamedll, IServerGameDLL, INTERFACEVERSION_SERVERGAMEDLL);
|
||||
GET_V_IFACE_CURRENT(engineFactory, engine, IVEngineServer, INTERFACEVERSION_VENGINESERVER);
|
||||
|
||||
m_SourceMMLoaded = true;
|
||||
|
||||
return SDK_OnMetamodLoad(error, maxlen, late);
|
||||
}
|
||||
|
||||
bool SDKExtension::Unload(char *error, size_t maxlen)
|
||||
{
|
||||
if (!m_WeAreUnloaded)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlen, "This extension must be unloaded by SourceMod.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return SDK_OnMetamodUnload(error, maxlen);
|
||||
}
|
||||
|
||||
bool SDKExtension::Pause(char *error, size_t maxlen)
|
||||
{
|
||||
if (!m_WeGotPauseChange)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlen, "This extension must be paused by SourceMod.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
m_WeGotPauseChange = false;
|
||||
|
||||
return SDK_OnMetamodPauseChange(true, error, maxlen);
|
||||
}
|
||||
|
||||
bool SDKExtension::Unpause(char *error, size_t maxlen)
|
||||
{
|
||||
if (!m_WeGotPauseChange)
|
||||
{
|
||||
if (error)
|
||||
{
|
||||
snprintf(error, maxlen, "This extension must be unpaused by SourceMod.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
m_WeGotPauseChange = false;
|
||||
|
||||
return SDK_OnMetamodPauseChange(false, error, maxlen);
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetAuthor()
|
||||
{
|
||||
return GetExtensionAuthor();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetDate()
|
||||
{
|
||||
return GetExtensionDateString();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetDescription()
|
||||
{
|
||||
return GetExtensionDescription();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetLicense()
|
||||
{
|
||||
return SMEXT_CONF_LICENSE;
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetLogTag()
|
||||
{
|
||||
return GetExtensionTag();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetName()
|
||||
{
|
||||
return GetExtensionName();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetURL()
|
||||
{
|
||||
return GetExtensionURL();
|
||||
}
|
||||
|
||||
const char *SDKExtension::GetVersion()
|
||||
{
|
||||
return GetExtensionVerString();
|
||||
}
|
||||
|
||||
bool SDKExtension::SDK_OnMetamodLoad(char *error, size_t err_max, bool late)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDKExtension::SDK_OnMetamodUnload(char *error, size_t err_max)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDKExtension::SDK_OnMetamodPauseChange(bool paused, char *error, size_t err_max)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,142 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
|
||||
#define _INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
|
||||
|
||||
#include "smsdk_config.h"
|
||||
#include <IExtensionSys.h>
|
||||
#include <IHandleSys.h>
|
||||
#include <sp_vm_api.h>
|
||||
#include <sm_platform.h>
|
||||
#include <ISourceMod.h>
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
#include <ISmmPlugin.h>
|
||||
#include <eiface.h>
|
||||
#endif
|
||||
|
||||
using namespace SourceMod;
|
||||
using namespace SourcePawn;
|
||||
|
||||
class SDKExtension :
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
public ISmmPlugin,
|
||||
#endif
|
||||
public IExtensionInterface
|
||||
{
|
||||
public:
|
||||
SDKExtension();
|
||||
public:
|
||||
/**
|
||||
* @brief This is called after the initial loading sequence has been processed.
|
||||
*
|
||||
* @param error Error message buffer.
|
||||
* @param err_max Size of error message buffer.
|
||||
* @param late Whether or not the module was loaded after map load.
|
||||
* @return True to succeed loading, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnLoad(char *error, size_t err_max, bool late);
|
||||
|
||||
/**
|
||||
* @brief This is called right before the extension is unloaded.
|
||||
*/
|
||||
virtual void SDK_OnUnload();
|
||||
|
||||
/**
|
||||
* @brief This is called once all known extensions have been loaded.
|
||||
*/
|
||||
virtual void SDK_OnAllLoaded();
|
||||
|
||||
/**
|
||||
* @brief Called when the pause state is changed.
|
||||
*/
|
||||
virtual void SDK_OnPauseChange(bool paused);
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
/**
|
||||
* @brief Called when Metamod is attached, before the extension version is called.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param err_max Maximum size of error buffer.
|
||||
* @param late Whether or not Metamod considers this a late load.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnMetamodLoad(char *error, size_t err_max, bool late);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod is detaching, after the extension version is called.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param error Error buffer.
|
||||
* @param err_max Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnMetamodUnload(char *error, size_t err_max);
|
||||
|
||||
/**
|
||||
* @brief Called when Metamod's pause state is changing.
|
||||
* NOTE: By default this is blocked unless sent from SourceMod.
|
||||
*
|
||||
* @param paused Pause state being set.
|
||||
* @param error Error buffer.
|
||||
* @param err_max Maximum size of error buffer.
|
||||
* @return True to succeed, false to fail.
|
||||
*/
|
||||
virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t err_max);
|
||||
#endif
|
||||
|
||||
public: //IExtensionInterface
|
||||
virtual bool OnExtensionLoad(IExtension *me, IShareSys *sys, char *error, size_t err_max, bool late);
|
||||
virtual void OnExtensionUnload();
|
||||
virtual void OnExtensionsAllLoaded();
|
||||
virtual bool IsMetamodExtension();
|
||||
virtual void OnExtensionPauseChange(bool state);
|
||||
virtual const char *GetExtensionName();
|
||||
virtual const char *GetExtensionURL();
|
||||
virtual const char *GetExtensionTag();
|
||||
virtual const char *GetExtensionAuthor();
|
||||
virtual const char *GetExtensionVerString();
|
||||
virtual const char *GetExtensionDescription();
|
||||
virtual const char *GetExtensionDateString();
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
public: //ISmmPlugin
|
||||
virtual bool Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlength, bool late);
|
||||
virtual const char *GetAuthor();
|
||||
virtual const char *GetName();
|
||||
virtual const char *GetDescription();
|
||||
virtual const char *GetURL();
|
||||
virtual const char *GetLicense();
|
||||
virtual const char *GetVersion();
|
||||
virtual const char *GetDate();
|
||||
virtual const char *GetLogTag();
|
||||
virtual bool Unload(char *error, size_t maxlen);
|
||||
virtual bool Pause(char *error, size_t maxlen);
|
||||
virtual bool Unpause(char *error, size_t maxlen);
|
||||
private:
|
||||
bool m_SourceMMLoaded;
|
||||
bool m_WeAreUnloaded;
|
||||
bool m_WeGotPauseChange;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern SDKExtension *g_pExtensionIface;
|
||||
|
||||
extern IShareSys *g_pShareSys;
|
||||
extern IExtension *myself;
|
||||
extern IHandleSys *g_pHandleSys;
|
||||
extern ISourceMod *g_pSM;
|
||||
|
||||
#if defined SMEXT_CONF_METAMOD
|
||||
PLUGIN_GLOBALVARS();
|
||||
extern IVEngineServer *engine;
|
||||
extern IServerGameDLL *gamedll;
|
||||
#endif
|
||||
|
||||
#define SM_MKIFACE(name) SMINTERFACE_##name##_NAME, SMINTERFACE_##name##_VERSION
|
||||
#define SM_GET_IFACE(prefix,addr) \
|
||||
if (!g_pShareSys->RequestInterface(SM_MKIFACE(prefix), myself, (SMInterface **)&addr)) { \
|
||||
if (error) { \
|
||||
snprintf(error, err_max, "Could not find interface: %s", SMINTERFACE_##prefix##_NAME); \
|
||||
} \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_EXTENSION_BASESDK_H_
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef _INCLUDE_SOURCEMOD_PLATFORM_H_
|
||||
#define _INCLUDE_SOURCEMOD_PLATFORM_H_
|
||||
|
||||
/**
|
||||
* @file Contains platform-specific macros for abstraction.
|
||||
*/
|
||||
|
||||
#if defined WIN32 || defined WIN64
|
||||
#define PLATFORM_WINDOWS
|
||||
#if !defined WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#if !defined snprintf
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#if !defined stat
|
||||
#define stat _stat
|
||||
#endif
|
||||
#define strcasecmp strcmpi
|
||||
#include <windows.h>
|
||||
#include <direct.h>
|
||||
#define PLATFORM_LIB_EXT "dll"
|
||||
#define PLATFORM_MAX_PATH MAX_PATH
|
||||
#define PLATFORM_SEP_CHAR '\\'
|
||||
#define PLATFORM_SEP_ALTCHAR '/'
|
||||
#define PLATFORM_EXTERN_C extern "C" __declspec(dllexport)
|
||||
#else if defined __linux__
|
||||
#define PLATFORM_LINUX
|
||||
#define PLATFORM_POSIX
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#define PLATFORM_MAX_PATH PATH_MAX
|
||||
#define PLATFORM_LIB_EXT "so"
|
||||
#define PLATFORM_SEP_CHAR '/'
|
||||
#define PLATFORM_SEP_ALTCHAR '\\'
|
||||
#define PLATFORM_EXTERN_C extern "C" __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
#endif //_INCLUDE_SOURCEMOD_PLATFORM_H_
|
||||
@@ -0,0 +1,163 @@
|
||||
#ifndef _INCLUDE_SPFILE_HEADERS_H
|
||||
#define _INCLUDE_SPFILE_HEADERS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#if defined __GNUC__ || defined HAVE_STDINT_
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#if !defined HAVE_STDINT_H
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int8 int8_t;
|
||||
#define HAVE_STDINT_H
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define SPFILE_MAGIC 0x53504646 /* Source Pawn File Format (SPFF) */
|
||||
//#define SPFILE_VERSION 0x0100
|
||||
#define SPFILE_VERSION 0x0101 /* Uncompressed bytecode */
|
||||
|
||||
//:TODO: better compiler/nix support
|
||||
#if defined __linux__
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#else
|
||||
#pragma pack(push)
|
||||
#pragma pack(1) /* structures must be packed (byte-aligned) */
|
||||
#endif
|
||||
|
||||
#define SPFILE_COMPRESSION_NONE 0
|
||||
#define SPFILE_COMPRESSION_GZ 1
|
||||
|
||||
typedef struct sp_file_section_s
|
||||
{
|
||||
uint32_t nameoffs; /* rel offset into global string table */
|
||||
uint32_t dataoffs;
|
||||
uint32_t size;
|
||||
} sp_file_section_t;
|
||||
|
||||
/**
|
||||
* If compression is 0, then
|
||||
* disksize may be 0 to mean that
|
||||
* only the imagesize is needed.
|
||||
*/
|
||||
typedef struct sp_file_hdr_s
|
||||
{
|
||||
uint32_t magic; /* magic number */
|
||||
uint16_t version; /* version code */
|
||||
uint8_t compression;/* compression algorithm */
|
||||
uint32_t disksize; /* size on disk */
|
||||
uint32_t imagesize; /* size in memory */
|
||||
uint8_t sections; /* number of sections */
|
||||
uint32_t stringtab; /* offset to string table */
|
||||
uint32_t dataoffs; /* offset to file proper (any compression starts here) */
|
||||
} sp_file_hdr_t;
|
||||
|
||||
#define SP_FLAG_DEBUG (1<<0)
|
||||
|
||||
/* section is ".code" */
|
||||
typedef struct sp_file_code_s
|
||||
{
|
||||
uint32_t codesize; /* codesize in bytes */
|
||||
uint8_t cellsize; /* cellsize in bytes */
|
||||
uint8_t codeversion; /* version of opcodes supported */
|
||||
uint16_t flags; /* flags */
|
||||
uint32_t main; /* address to "main" if any */
|
||||
uint32_t code; /* rel offset to code */
|
||||
} sp_file_code_t;
|
||||
|
||||
/* section is .data */
|
||||
typedef struct sp_file_data_s
|
||||
{
|
||||
uint32_t datasize; /* size of data section in memory */
|
||||
uint32_t memsize; /* total mem required (includes data) */
|
||||
uint32_t data; /* file offset to data (helper) */
|
||||
} sp_file_data_t;
|
||||
|
||||
/* section is .publics */
|
||||
typedef struct sp_file_publics_s
|
||||
{
|
||||
uint32_t address; /* address rel to code section */
|
||||
uint32_t name; /* index into nametable */
|
||||
} sp_file_publics_t;
|
||||
|
||||
/* section is .natives */
|
||||
typedef struct sp_file_natives_s
|
||||
{
|
||||
uint32_t name; /* name of native at index */
|
||||
} sp_file_natives_t;
|
||||
|
||||
/* section is .libraries */
|
||||
typedef struct sp_file_libraries_s
|
||||
{
|
||||
uint32_t name; /* index into nametable */
|
||||
} sp_file_libraries_t;
|
||||
|
||||
/* section is .pubvars */
|
||||
typedef struct sp_file_pubvars_s
|
||||
{
|
||||
uint32_t address; /* address rel to dat section */
|
||||
uint32_t name; /* index into nametable */
|
||||
} sp_file_pubvars_t;
|
||||
|
||||
#if defined __linux__
|
||||
#pragma pack() /* reset default packing */
|
||||
#else
|
||||
#pragma pack(pop) /* reset previous packing */
|
||||
#endif
|
||||
|
||||
typedef struct sp_fdbg_info_s
|
||||
{
|
||||
uint32_t num_files; /* number of files */
|
||||
uint32_t num_lines; /* number of lines */
|
||||
uint32_t num_syms; /* number of symbols */
|
||||
uint32_t num_arrays; /* number of symbols which are arrays */
|
||||
} sp_fdbg_info_t;
|
||||
|
||||
/**
|
||||
* Debug information structures
|
||||
*/
|
||||
typedef struct sp_fdbg_file_s
|
||||
{
|
||||
uint32_t addr; /* address into code */
|
||||
uint32_t name; /* offset into debug nametable */
|
||||
} sp_fdbg_file_t;
|
||||
|
||||
typedef struct sp_fdbg_line_s
|
||||
{
|
||||
uint32_t addr; /* address into code */
|
||||
uint32_t line; /* line number */
|
||||
} sp_fdbg_line_t;
|
||||
|
||||
#define SP_SYM_VARIABLE 1 /* cell that has an address and that can be fetched directly (lvalue) */
|
||||
#define SP_SYM_REFERENCE 2 /* VARIABLE, but must be dereferenced */
|
||||
#define SP_SYM_ARRAY 3
|
||||
#define SP_SYM_REFARRAY 4 /* an array passed by reference (i.e. a pointer) */
|
||||
#define SP_SYM_FUNCTION 9
|
||||
|
||||
typedef struct sp_fdbg_symbol_s
|
||||
{
|
||||
int32_t addr; /* address rel to DAT or stack frame */
|
||||
int16_t tagid; /* tag id */
|
||||
uint32_t codestart; /* start scope validity in code */
|
||||
uint32_t codeend; /* end scope validity in code */
|
||||
uint8_t ident; /* variable type */
|
||||
uint8_t vclass; /* scope class (local vs global) */
|
||||
uint16_t dimcount; /* dimension count (for arrays) */
|
||||
uint32_t name; /* offset into debug nametable */
|
||||
} sp_fdbg_symbol_t;
|
||||
|
||||
typedef struct sp_fdbg_arraydim_s
|
||||
{
|
||||
int16_t tagid; /* tag id */
|
||||
uint32_t size; /* size of dimension */
|
||||
} sp_fdbg_arraydim_t;
|
||||
|
||||
/* section is .names */
|
||||
typedef char * sp_file_nametab_t;
|
||||
|
||||
#endif //_INCLUDE_SPFILE_HEADERS_H
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef _INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
|
||||
#define _INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
|
||||
|
||||
#include "sp_vm_types.h"
|
||||
|
||||
inline cell_t sp_ftoc(float val)
|
||||
{
|
||||
return *(cell_t *)&val;
|
||||
}
|
||||
inline float sp_ctof(cell_t val)
|
||||
{
|
||||
return *(float *)&val;
|
||||
}
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_VM_TYPEUTIL_H_
|
||||
@@ -0,0 +1,631 @@
|
||||
#ifndef _INCLUDE_SOURCEPAWN_VM_API_H_
|
||||
#define _INCLUDE_SOURCEPAWN_VM_API_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include "sp_vm_types.h"
|
||||
|
||||
#define SOURCEPAWN_VM_API_VERSION 1
|
||||
|
||||
#if defined SOURCEMOD_BUILD
|
||||
namespace SourceMod
|
||||
{
|
||||
struct IdentityToken_t;
|
||||
};
|
||||
#endif
|
||||
|
||||
namespace SourcePawn
|
||||
{
|
||||
class IVirtualMachine;
|
||||
|
||||
/**
|
||||
* @brief Interface to managing a debug context at runtime.
|
||||
*/
|
||||
class IPluginDebugInfo
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Given a code pointer, finds the file it is associated with.
|
||||
*
|
||||
* @param addr Code address offset.
|
||||
* @param filename Pointer to store filename pointer in.
|
||||
*/
|
||||
virtual int LookupFile(ucell_t addr, const char **filename) =0;
|
||||
|
||||
/**
|
||||
* @brief Given a code pointer, finds the function it is associated with.
|
||||
*
|
||||
* @param addr Code address offset.
|
||||
* @param name Pointer to store function name pointer in.
|
||||
*/
|
||||
virtual int LookupFunction(ucell_t addr, const char **name) =0;
|
||||
|
||||
/**
|
||||
* @brief Given a code pointer, finds the line it is associated with.
|
||||
*
|
||||
* @param addr Code address offset.
|
||||
* @param line Pointer to store line number in.
|
||||
*/
|
||||
virtual int LookupLine(ucell_t addr, uint32_t *line) =0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Interface to managing a context at runtime.
|
||||
*/
|
||||
class IPluginContext
|
||||
{
|
||||
public:
|
||||
virtual ~IPluginContext() { };
|
||||
public:
|
||||
/**
|
||||
* @brief Returns the parent IVirtualMachine.
|
||||
*
|
||||
* @return Parent virtual machine pointer.
|
||||
*/
|
||||
virtual IVirtualMachine *GetVirtualMachine() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the child sp_context_t structure.
|
||||
*
|
||||
* @return Child sp_context_t structure.
|
||||
*/
|
||||
virtual sp_context_t *GetContext() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns true if the plugin is in debug mode.
|
||||
*
|
||||
* @return True if in debug mode, false otherwise.
|
||||
*/
|
||||
virtual bool IsDebugging() =0;
|
||||
|
||||
/**
|
||||
* @brief Installs a debug break and returns the old one, if any.
|
||||
* This will fail if the plugin is not debugging.
|
||||
*
|
||||
* @param newpfn New function pointer.
|
||||
* @param oldpfn Pointer to retrieve old function pointer.
|
||||
*/
|
||||
virtual int SetDebugBreak(SPVM_DEBUGBREAK newpfn, SPVM_DEBUGBREAK *oldpfn) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns debug info.
|
||||
*
|
||||
* @return IPluginDebugInfo, or NULL if no debug info found.
|
||||
*/
|
||||
virtual IPluginDebugInfo *GetDebugInfo() =0;
|
||||
|
||||
/**
|
||||
* @brief Allocs memory on the secondary stack of a plugin.
|
||||
* Note that although called a heap, it is in fact a stack.
|
||||
*
|
||||
* @param cells Number of cells to allocate.
|
||||
* @param local_addr Will be filled with data offset to heap.
|
||||
* @param phys_addr Physical address to heap memory.
|
||||
*/
|
||||
virtual int HeapAlloc(unsigned int cells, cell_t *local_addr, cell_t **phys_addr) =0;
|
||||
|
||||
/**
|
||||
* @brief Pops a heap address off the heap stack. Use this to free memory allocated with
|
||||
* SP_HeapAlloc().
|
||||
* Note that in SourcePawn, the heap is in fact a bottom-up stack. Deallocations
|
||||
* with this native should be performed in precisely the REVERSE order.
|
||||
*
|
||||
* @param local_addr Local address to free.
|
||||
*/
|
||||
virtual int HeapPop(cell_t local_addr) =0;
|
||||
|
||||
/**
|
||||
* @brief Releases a heap address using a different method than SP_HeapPop().
|
||||
* This allows you to release in any order. However, if you allocate N
|
||||
* objects, release only some of them, then begin allocating again,
|
||||
* you cannot go back and starting freeing the originals.
|
||||
* In other words, for each chain of allocations, if you start deallocating,
|
||||
* then allocating more in a chain, you must only deallocate from the current
|
||||
* allocation chain. This is basically HeapPop() except on a larger scale.
|
||||
*
|
||||
* @param local_addr Local address to free.
|
||||
*/
|
||||
virtual int HeapRelease(cell_t local_addr) =0;
|
||||
|
||||
/**
|
||||
* @brief Finds a native by name.
|
||||
*
|
||||
* @param name Name of native.
|
||||
* @param index Optionally filled with native index number.
|
||||
*/
|
||||
virtual int FindNativeByName(const char *name, uint32_t *index) =0;
|
||||
|
||||
/**
|
||||
* @brief Gets native info by index.
|
||||
*
|
||||
* @param index Index number of native.
|
||||
* @param native Optionally filled with pointer to native structure.
|
||||
*/
|
||||
virtual int GetNativeByIndex(uint32_t index, sp_native_t **native) =0;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of natives.
|
||||
*
|
||||
* @return Filled with the number of natives.
|
||||
*/
|
||||
virtual uint32_t GetNativesNum() =0;
|
||||
|
||||
/**
|
||||
* @brief Finds a public function by name.
|
||||
*
|
||||
* @param name Name of public
|
||||
* @param index Optionally filled with public index number.
|
||||
*/
|
||||
virtual int FindPublicByName(const char *name, uint32_t *index) =0;
|
||||
|
||||
/**
|
||||
* @brief Gets public function info by index.
|
||||
*
|
||||
* @param index Public function index number.
|
||||
* @param publicptr Optionally filled with pointer to public structure.
|
||||
*/
|
||||
virtual int GetPublicByIndex(uint32_t index, sp_public_t **publicptr) =0;
|
||||
|
||||
/**
|
||||
* @brief Gets the number of public functions.
|
||||
*
|
||||
* @return Filled with the number of public functions.
|
||||
*/
|
||||
virtual uint32_t GetPublicsNum() =0;
|
||||
|
||||
/**
|
||||
* @brief Gets public variable info by index.
|
||||
*
|
||||
* @param index Public variable index number.
|
||||
* @param pubvar Optionally filled with pointer to pubvar structure.
|
||||
*/
|
||||
virtual int GetPubvarByIndex(uint32_t index, sp_pubvar_t **pubvar) =0;
|
||||
|
||||
/**
|
||||
* @brief Finds a public variable by name.
|
||||
*
|
||||
* @param name Name of pubvar
|
||||
* @param index Optionally filled with pubvar index number.
|
||||
*/
|
||||
virtual int FindPubvarByName(const char *name, uint32_t *index) =0;
|
||||
|
||||
/**
|
||||
* @brief Gets the addresses of a public variable.
|
||||
*
|
||||
* @param index Index of public variable.
|
||||
* @param local_addr Address to store local address in.
|
||||
* @param phys_addr Address to store physically relocated in.
|
||||
*/
|
||||
virtual int GetPubvarAddrs(uint32_t index, cell_t *local_addr, cell_t **phys_addr) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of public variables.
|
||||
*
|
||||
* @return Number of public variables.
|
||||
*/
|
||||
virtual uint32_t GetPubVarsNum() =0;
|
||||
|
||||
/**
|
||||
* @brief Round-about method of converting a plugin reference to a physical address
|
||||
*
|
||||
* @param local_addr Local address in plugin.
|
||||
* @param phys_addr Optionally filled with relocated physical address.
|
||||
*/
|
||||
virtual int LocalToPhysAddr(cell_t local_addr, cell_t **phys_addr) =0;
|
||||
|
||||
/**
|
||||
* @brief Converts a local address to a physical string.
|
||||
*
|
||||
* @param local_addr Local address in plugin.
|
||||
* @param addr Destination output pointer.
|
||||
*/
|
||||
virtual int LocalToString(cell_t local_addr, char **addr) =0;
|
||||
|
||||
/**
|
||||
* @brief Converts a physical string to a local address.
|
||||
*
|
||||
* @param local_addr Local address in plugin.
|
||||
* @param bytes Number of chars to write, including NULL terminator.
|
||||
* @param source Source string to copy.
|
||||
*/
|
||||
virtual int StringToLocal(cell_t local_addr, size_t bytes, const char *source) =0;
|
||||
|
||||
/**
|
||||
* @brief Converts a physical UTF-8 string to a local address.
|
||||
* This function is the same as the ANSI version, except it will copy the maximum number of characters possible
|
||||
* without accidentally chopping a multi-byte character.
|
||||
*
|
||||
* @param local_addr Local address in plugin.
|
||||
* @param maxbytes Number of bytes to write, including NULL terminator.
|
||||
* @param source Source string to copy.
|
||||
* @param wrtnbytes Optionally set to the number of actual bytes written.
|
||||
*/
|
||||
virtual int StringToLocalUTF8(cell_t local_addr,
|
||||
size_t maxbytes,
|
||||
const char *source,
|
||||
size_t *wrtnbytes) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes a cell onto the stack. Increases the parameter count by one.
|
||||
*
|
||||
* @param value Cell value.
|
||||
*/
|
||||
virtual int PushCell(cell_t value) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes an array of cells onto the stack. Increases the parameter count by one.
|
||||
* If the function returns an error it will fail entirely, releasing anything allocated in the process.
|
||||
* Note that this does not release the heap, so you should release it after
|
||||
* calling Execute().
|
||||
*
|
||||
* @param local_addr Filled with local address to release.
|
||||
* @param phys_addr Optionally filled with physical address of new array.
|
||||
* @param array Cell array to copy.
|
||||
* @param numcells Number of cells in the array to copy.
|
||||
*/
|
||||
virtual int PushCellArray(cell_t *local_addr, cell_t **phys_addr, cell_t array[], unsigned int numcells) =0;
|
||||
|
||||
/**
|
||||
* @brief Pushes a string onto the stack (by reference) and increases the parameter count by one.
|
||||
* Note that this does not release the heap, so you should release it after
|
||||
* calling Execute().
|
||||
*
|
||||
* @param local_addr Filled with local address to release.
|
||||
* @param phys_addr Optionally filled with physical address of new array.
|
||||
* @param string Source string to push.
|
||||
*/
|
||||
virtual int PushString(cell_t *local_addr, char **phys_addr, const char *string) =0;
|
||||
|
||||
/**
|
||||
* @brief Individually pushes each cell of an array of cells onto the stack. Increases the
|
||||
* parameter count by the number of cells pushed.
|
||||
* If the function returns an error it will fail entirely, releasing anything allocated in the process.
|
||||
*
|
||||
* @param array Array of cells to read from.
|
||||
* @param numcells Number of cells to read.
|
||||
*/
|
||||
virtual int PushCellsFromArray(cell_t array[], unsigned int numcells) =0;
|
||||
|
||||
/**
|
||||
* @brief Binds a list of native names and their function pointers to a context.
|
||||
* If num is 0, the list is read until an entry with a NULL name is reached.
|
||||
* If overwrite is non-zero, already registered natives will be overwritten.
|
||||
*
|
||||
* @param natives Array of natives.
|
||||
* @param num Number of natives in array.
|
||||
* @param overwrite Toggles overwrite.
|
||||
*/
|
||||
virtual int BindNatives(const sp_nativeinfo_t *natives, unsigned int num, int overwrite) =0;
|
||||
|
||||
/**
|
||||
* @brief Binds a single native. Overwrites any existing bind.
|
||||
* If the context does not contain the native that will be binded the function will return
|
||||
* with a SP_ERROR_NOT_FOUND error.
|
||||
*
|
||||
* @param native Pointer to native.
|
||||
*/
|
||||
virtual int BindNative(const sp_nativeinfo_t *native) =0;
|
||||
|
||||
/**
|
||||
* @brief Binds a single native to any non-registered native.
|
||||
*
|
||||
* @param native Native to bind.
|
||||
*/
|
||||
virtual int BindNativeToAny(SPVM_NATIVE_FUNC native) =0;
|
||||
|
||||
/**
|
||||
* @brief Executes a function ID located in this context.
|
||||
*
|
||||
* @param funcid Function id to execute.
|
||||
* @param result Pointer to store the return value (required).
|
||||
* @return Error code (if any) from the VM.
|
||||
*/
|
||||
virtual int Execute(uint32_t funcid, cell_t *result) =0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Throws a error and halts any current execution.
|
||||
*
|
||||
* @param error The error number to set.
|
||||
* @param msg Custom error message format. NULL to use default.
|
||||
* @param ... Message format arguments, if any.
|
||||
*/
|
||||
virtual void ThrowNativeErrorEx(int error, const char *msg, ...) =0;
|
||||
|
||||
/**
|
||||
* @brief Throws a generic native error and halts any current execution.
|
||||
*
|
||||
* @param msg Custom error message format. NULL to set no message.
|
||||
* @param ... Message format arguments, if any.
|
||||
* @return 0 for convenience.
|
||||
*/
|
||||
virtual cell_t ThrowNativeError(const char *msg, ...) =0;
|
||||
|
||||
#if defined SOURCEMOD_BUILD
|
||||
/**
|
||||
* @brief Returns the identity token for this context.
|
||||
* Note: This is a helper function for native calls and the Handle System.
|
||||
*
|
||||
* @return Identity token.
|
||||
*/
|
||||
virtual SourceMod::IdentityToken_t *GetIdentity() =0;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Information about a position in a call stack.
|
||||
*/
|
||||
struct CallStackInfo
|
||||
{
|
||||
const char *filename; /* NULL if not found */
|
||||
unsigned int line; /* 0 if not found */
|
||||
const char *function; /* NULL if not found */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Retrieves error information from a debug hook.
|
||||
*/
|
||||
class IContextTrace
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Returns the integer error code.
|
||||
*
|
||||
* @return Integer error code.
|
||||
*/
|
||||
virtual int GetErrorCode() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns a string describing the error.
|
||||
*
|
||||
* @return Error string.
|
||||
*/
|
||||
virtual const char *GetErrorString() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns whether debug info is available.
|
||||
*
|
||||
* @return True if debug info is available, false otherwise.
|
||||
*/
|
||||
virtual bool DebugInfoAvailable() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns a custom error message.
|
||||
*
|
||||
* @return A pointer to a custom error message, or NULL otherwise.
|
||||
*/
|
||||
virtual const char *GetCustomErrorString() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns trace info for a specific point in the backtrace, if any.
|
||||
* The next subsequent call to GetTraceInfo() will return the next item in the call stack.
|
||||
* Calls are retrieved in descending order (i.e. the first item is at the top of the stack/call sequence).
|
||||
*
|
||||
* @param trace An ErrorTraceInfo buffer to store information (NULL to ignore).
|
||||
* @return True if successful, false if there are no more traces.
|
||||
*/
|
||||
virtual bool GetTraceInfo(CallStackInfo *trace) =0;
|
||||
|
||||
/**
|
||||
* @brief Resets the trace to its original position (the call on the top of the stack).
|
||||
*/
|
||||
virtual void ResetTrace() =0;
|
||||
|
||||
/**
|
||||
* @brief Retrieves the name of the last native called.
|
||||
* Returns NULL if there was no native that caused the error.
|
||||
*
|
||||
* @param index Optional pointer to store index.
|
||||
* @return Native name, or NULL if none.
|
||||
*/
|
||||
virtual const char *GetLastNative(uint32_t *index) =0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Provides callbacks for debug information.
|
||||
*/
|
||||
class IDebugListener
|
||||
{
|
||||
public:
|
||||
virtual void OnContextExecuteError(IPluginContext *ctx, IContextTrace *error) =0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Contains helper functions used by VMs and the host app
|
||||
*/
|
||||
class ISourcePawnEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Loads a named file from a file pointer.
|
||||
* Note: Using this means the memory will be allocated by the VM.
|
||||
*
|
||||
* @param fp File pointer. May be at any offset. Not closed on return.
|
||||
* @param err Optional error code pointer.
|
||||
* @return A new plugin structure.
|
||||
*/
|
||||
virtual sp_plugin_t *LoadFromFilePointer(FILE *fp, int *err) =0;
|
||||
|
||||
/**
|
||||
* @brief Loads a file from a base memory address.
|
||||
*
|
||||
* @param base Base address of the plugin's memory region.
|
||||
* @param plugin If NULL, a new plugin pointer is returned.
|
||||
* Otherwise, the passed pointer is used.
|
||||
* @param err Optional error code pointer.
|
||||
* @return The resulting plugin pointer.
|
||||
*/
|
||||
virtual sp_plugin_t *LoadFromMemory(void *base, sp_plugin_t *plugin, int *err) =0;
|
||||
|
||||
/**
|
||||
* Frees all of the memory associated with a plugin file.
|
||||
* If allocated using SP_LoadFromMemory, the base and plugin pointer
|
||||
* itself are not freed (so this may end up doing nothing).
|
||||
*/
|
||||
virtual int FreeFromMemory(sp_plugin_t *plugin) =0;
|
||||
|
||||
/**
|
||||
* @brief Allocates large blocks of temporary memory.
|
||||
*
|
||||
* @param size Size of memory to allocate.
|
||||
* @return Pointer to memory, NULL if allocation failed.
|
||||
*/
|
||||
virtual void *BaseAlloc(size_t size) =0;
|
||||
|
||||
/**
|
||||
* @brief Frees memory allocated with BaseAlloc.
|
||||
*
|
||||
* @param memory Memory address to free.
|
||||
*/
|
||||
virtual void BaseFree(void *memory) =0;
|
||||
|
||||
/**
|
||||
* @brief Allocates executable memory.
|
||||
*
|
||||
* @param size Size of memory to allocate.
|
||||
* @return Pointer to memory, NULL if allocation failed.
|
||||
*/
|
||||
virtual void *ExecAlloc(size_t size) =0;
|
||||
|
||||
/**
|
||||
* @brief Frees executable memory.
|
||||
*
|
||||
* @param address Address to free.
|
||||
*/
|
||||
virtual void ExecFree(void *address) =0;
|
||||
|
||||
/**
|
||||
* @brief Sets the debug listener. This should only be called once.
|
||||
* If called successively (using manual chaining), only the last function should
|
||||
* attempt to call back into the same plugin. Otherwise, globally cached states
|
||||
* can be accidentally overwritten.
|
||||
*
|
||||
* @param listener Pointer to an IDebugListener.
|
||||
* @return Old IDebugListener, or NULL if none.
|
||||
*/
|
||||
virtual IDebugListener *SetDebugListener(IDebugListener *listener) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of plugins on the call stack.
|
||||
*
|
||||
* @return Number of contexts in the call stack.
|
||||
*/
|
||||
virtual unsigned int GetContextCallCount() =0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Dummy class for encapsulating private compilation data.
|
||||
*/
|
||||
class ICompilation
|
||||
{
|
||||
public:
|
||||
virtual ~ICompilation() { };
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Outlines the interface a Virtual Machine (JIT) must expose
|
||||
*/
|
||||
class IVirtualMachine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Returns the current API version.
|
||||
*/
|
||||
virtual unsigned int GetAPIVersion() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the string name of a VM implementation.
|
||||
*/
|
||||
virtual const char *GetVMName() =0;
|
||||
|
||||
/**
|
||||
* @brief Begins a new compilation
|
||||
*
|
||||
* @param plugin Pointer to a plugin structure.
|
||||
* @return New compilation pointer.
|
||||
*/
|
||||
virtual ICompilation *StartCompilation(sp_plugin_t *plugin) =0;
|
||||
|
||||
/**
|
||||
* @brief Sets a compilation option.
|
||||
*
|
||||
* @param co Pointer to a compilation.
|
||||
* @param key Option key name.
|
||||
* @param val Option value string.
|
||||
* @return True if option could be set, false otherwise.
|
||||
*/
|
||||
virtual bool SetCompilationOption(ICompilation *co, const char *key, const char *val) =0;
|
||||
|
||||
/**
|
||||
* @brief Finalizes a compilation into a new sp_context_t.
|
||||
* Note: This will free the ICompilation pointer.
|
||||
*
|
||||
* @param co Compilation pointer.
|
||||
* @param err Filled with error code on exit.
|
||||
* @return New plugin context.
|
||||
*/
|
||||
virtual sp_context_t *CompileToContext(ICompilation *co, int *err) =0;
|
||||
|
||||
/**
|
||||
* @brief Aborts a compilation and frees the ICompilation pointer.
|
||||
*
|
||||
* @param co Compilation pointer.
|
||||
*/
|
||||
virtual void AbortCompilation(ICompilation *co) =0;
|
||||
|
||||
/**
|
||||
* @brief Frees any internal variable usage on a context.
|
||||
*
|
||||
* @param ctx Context structure pointer.
|
||||
*/
|
||||
virtual void FreeContext(sp_context_t *ctx) =0;
|
||||
|
||||
/**
|
||||
* @brief Calls the "execute" function on a context.
|
||||
*
|
||||
* @param ctx Executes a function in a context.
|
||||
* @param code_addr Index into the code section.
|
||||
* @param result Pointer to store result into.
|
||||
* @return Error code (if any).
|
||||
*/
|
||||
virtual int ContextExecute(sp_context_t *ctx, uint32_t code_addr, cell_t *result) =0;
|
||||
|
||||
/**
|
||||
* @brief Given a context and a code address, returns the index of the function.
|
||||
*
|
||||
* @param ctx Context to search.
|
||||
* @param code_addr Index into the code section.
|
||||
* @param result Pointer to store result into.
|
||||
* @return True if code index is valid, false otherwise.
|
||||
*/
|
||||
virtual bool FunctionLookup(const sp_context_t *ctx, uint32_t code_addr, unsigned int *result) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns the number of functions defined in the context.
|
||||
*
|
||||
* @param ctx Context to search.
|
||||
* @return Number of functions.
|
||||
*/
|
||||
virtual unsigned int FunctionCount(const sp_context_t *ctx) =0;
|
||||
|
||||
/**
|
||||
* @brief Returns a version string.
|
||||
*
|
||||
* @return Versioning string.
|
||||
*/
|
||||
virtual const char *GetVersionString() =0;
|
||||
|
||||
/**
|
||||
* @brief Returns a string describing optimizations.
|
||||
*
|
||||
* @return String describing CPU specific optimizations.
|
||||
*/
|
||||
virtual const char *GetCPUOptimizations() =0;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_VM_API_H_
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef _INCLUDE_SOURCEPAWN_VM_BASE_H_
|
||||
#define _INCLUDE_SOURCEPAWN_VM_BASE_H_
|
||||
|
||||
#include <sp_vm_api.h>
|
||||
|
||||
/* :TODO: rename this to sp_vm_linkage.h */
|
||||
|
||||
#if defined WIN32
|
||||
#define EXPORT_LINK extern "C" __declspec(dllexport)
|
||||
#else if defined __GNUC__
|
||||
#define EXPORT_LINK extern "C" __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
typedef SourcePawn::IVirtualMachine *(*SP_GETVM_FUNC)(SourcePawn::ISourcePawnEngine *);
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_VM_BASE_H_
|
||||
@@ -0,0 +1,251 @@
|
||||
#ifndef _INCLUDE_SOURCEPAWN_VM_TYPES_H
|
||||
#define _INCLUDE_SOURCEPAWN_VM_TYPES_H
|
||||
|
||||
#include "sp_file_headers.h"
|
||||
|
||||
typedef uint32_t ucell_t;
|
||||
typedef int32_t cell_t;
|
||||
typedef uint32_t funcid_t;
|
||||
|
||||
#include "sp_typeutil.h"
|
||||
|
||||
#define SP_MAX_EXEC_PARAMS 32 /* Maximum number of parameters in a function */
|
||||
|
||||
/**
|
||||
* Error codes
|
||||
* NOTE: Be sure to update the error string table when changing these
|
||||
*/
|
||||
#define SP_ERROR_NONE 0
|
||||
#define SP_ERROR_FILE_FORMAT 1 /* File format unrecognized */
|
||||
#define SP_ERROR_DECOMPRESSOR 2 /* A decompressor was not found */
|
||||
#define SP_ERROR_HEAPLOW 3 /* Not enough space left on the heap */
|
||||
#define SP_ERROR_PARAM 4 /* Invalid parameter or parameter type */
|
||||
#define SP_ERROR_INVALID_ADDRESS 5 /* A memory address was not valid */
|
||||
#define SP_ERROR_NOT_FOUND 6 /* The object in question was not found */
|
||||
#define SP_ERROR_INDEX 7 /* Invalid index parameter */
|
||||
#define SP_ERROR_STACKLOW 8 /* Nnot enough space left on the stack */
|
||||
#define SP_ERROR_NOTDEBUGGING 9 /* Debug mode was not on or debug section not found */
|
||||
#define SP_ERROR_INVALID_INSTRUCTION 10 /* Invalid instruction was encountered */
|
||||
#define SP_ERROR_MEMACCESS 11 /* Invalid memory access */
|
||||
#define SP_ERROR_STACKMIN 12 /* Stack went beyond its minimum value */
|
||||
#define SP_ERROR_HEAPMIN 13 /* Heap went beyond its minimum value */
|
||||
#define SP_ERROR_DIVIDE_BY_ZERO 14 /* Division by zero */
|
||||
#define SP_ERROR_ARRAY_BOUNDS 15 /* Array index is out of bounds */
|
||||
#define SP_ERROR_INSTRUCTION_PARAM 16 /* Instruction had an invalid parameter */
|
||||
#define SP_ERROR_STACKLEAK 17 /* A native leaked an item on the stack */
|
||||
#define SP_ERROR_HEAPLEAK 18 /* A native leaked an item on the heap */
|
||||
#define SP_ERROR_ARRAY_TOO_BIG 19 /* A dynamic array is too big */
|
||||
#define SP_ERROR_TRACKER_BOUNDS 20 /* Tracker stack is out of bounds */
|
||||
#define SP_ERROR_INVALID_NATIVE 21 /* Native was pending or invalid */
|
||||
#define SP_ERROR_PARAMS_MAX 22 /* Maximum number of parameters reached */
|
||||
#define SP_ERROR_NATIVE 23 /* Error originates from a native */
|
||||
|
||||
/**********************************************
|
||||
*** The following structures are reference structures.
|
||||
*** They are not essential to the API, but are used
|
||||
*** to hold the back end database format of the plugin
|
||||
*** binary.
|
||||
**********************************************/
|
||||
|
||||
/**
|
||||
* Information about the core plugin tables.
|
||||
* These may or may not be present!
|
||||
*/
|
||||
typedef struct sp_plugin_infotab_s
|
||||
{
|
||||
const char *stringbase; /* base of string table */
|
||||
uint32_t publics_num; /* number of publics */
|
||||
sp_file_publics_t *publics; /* public table */
|
||||
uint32_t natives_num; /* number of natives */
|
||||
sp_file_natives_t *natives; /* native table */
|
||||
uint32_t pubvars_num; /* number of pubvars */
|
||||
sp_file_pubvars_t *pubvars; /* pubvars table */
|
||||
uint32_t libraries_num; /* number of libraries */
|
||||
sp_file_libraries_t *lib; /* library table */
|
||||
} sp_plugin_infotab_t;
|
||||
|
||||
/**
|
||||
* Information about the plugin's debug tables.
|
||||
* These are all present if one is present.
|
||||
*/
|
||||
typedef struct sp_plugin_debug_s
|
||||
{
|
||||
const char *stringbase; /* base of string table */
|
||||
uint32_t files_num; /* number of files */
|
||||
sp_fdbg_file_t *files; /* files table */
|
||||
uint32_t lines_num; /* number of lines */
|
||||
sp_fdbg_line_t *lines; /* lines table */
|
||||
uint32_t syms_num; /* number of symbols */
|
||||
sp_fdbg_symbol_t *symbols; /* symbol table */
|
||||
} sp_plugin_debug_t;
|
||||
|
||||
#define SP_FA_SELF_EXTERNAL (1<<0)
|
||||
#define SP_FA_BASE_EXTERNAL (1<<1)
|
||||
|
||||
/**
|
||||
* The rebased, in-memory format of a plugin.
|
||||
* This differs from the on-disk structure to ensure
|
||||
* that the format is properly read.
|
||||
*/
|
||||
typedef struct sp_plugin_s
|
||||
{
|
||||
uint8_t *base; /* base of memory */
|
||||
uint8_t *pcode; /* p-code */
|
||||
uint32_t pcode_size; /* size of p-code */
|
||||
uint8_t *data; /* data size */
|
||||
uint32_t data_size; /* size of data */
|
||||
uint32_t memory; /* required memory */
|
||||
uint16_t flags; /* code flags */
|
||||
uint32_t allocflags; /* allocation flags */
|
||||
sp_plugin_infotab_t info; /* base info table */
|
||||
sp_plugin_debug_t debug; /* debug info table */
|
||||
} sp_plugin_t;
|
||||
|
||||
/** Forward declarations */
|
||||
|
||||
namespace SourcePawn
|
||||
{
|
||||
class IPluginContext;
|
||||
class IVirtualMachine;
|
||||
};
|
||||
|
||||
struct sp_context_s;
|
||||
|
||||
typedef cell_t (*SPVM_NATIVE_FUNC)(SourcePawn::IPluginContext *, const cell_t *);
|
||||
|
||||
/**********************************************
|
||||
*** The following structures are bound to the VM/JIT.
|
||||
*** Changing them will result in necessary recompilation.
|
||||
**********************************************/
|
||||
|
||||
/**
|
||||
* Offsets and names to a public function.
|
||||
* By default, these point back to the string table
|
||||
* in the sp_plugin_infotab_t structure.
|
||||
*/
|
||||
typedef struct sp_public_s
|
||||
{
|
||||
funcid_t funcid; /* encoded function id */
|
||||
uint32_t code_offs; /* code offset */
|
||||
const char *name; /* name */
|
||||
} sp_public_t;
|
||||
|
||||
/**
|
||||
* Offsets and names to public variables.
|
||||
* The offset is relocated and the name by default
|
||||
* points back to the sp_plugin_infotab_t structure.
|
||||
*/
|
||||
typedef struct sp_pubvar_s
|
||||
{
|
||||
cell_t *offs; /* pointer to data */
|
||||
const char *name; /* name */
|
||||
} sp_pubvar_t;
|
||||
|
||||
#define SP_NATIVE_UNBOUND (0) /* Native is undefined */
|
||||
#define SP_NATIVE_BOUND (1) /* Native is bound */
|
||||
|
||||
/**
|
||||
* Native lookup table, by default names
|
||||
* point back to the sp_plugin_infotab_t structure.
|
||||
* A native is NULL if unit
|
||||
*/
|
||||
typedef struct sp_native_s
|
||||
{
|
||||
SPVM_NATIVE_FUNC pfn; /* function pointer */
|
||||
const char * name; /* name of function */
|
||||
uint32_t status; /* status flags */
|
||||
} sp_native_t;
|
||||
|
||||
/**
|
||||
* Used for setting natives from modules/host apps.
|
||||
*/
|
||||
typedef struct sp_nativeinfo_s
|
||||
{
|
||||
const char *name;
|
||||
SPVM_NATIVE_FUNC func;
|
||||
} sp_nativeinfo_t;
|
||||
|
||||
/**
|
||||
* Debug file table
|
||||
*/
|
||||
typedef struct sp_debug_file_s
|
||||
{
|
||||
uint32_t addr; /* address into code */
|
||||
const char * name; /* name of file */
|
||||
} sp_debug_file_t;
|
||||
|
||||
/**
|
||||
* Note that line is missing. It is not necessary since
|
||||
* this can be retrieved from the base plugin info.
|
||||
*/
|
||||
typedef struct sp_debug_line_s
|
||||
{
|
||||
uint32_t addr; /* address into code */
|
||||
uint32_t line; /* line no. */
|
||||
} sp_debug_line_t;
|
||||
|
||||
typedef sp_fdbg_arraydim_t sp_debug_arraydim_t;
|
||||
|
||||
/**
|
||||
* The majority of this struct is already located in the parent
|
||||
* block. Thus, only the relocated portions are required.
|
||||
*/
|
||||
typedef struct sp_debug_symbol_s
|
||||
{
|
||||
uint32_t codestart; /* relocated code address */
|
||||
uint32_t codeend; /* relocated code end address */
|
||||
const char * name; /* relocated name */
|
||||
sp_debug_arraydim_t *dims; /* relocated dimension struct, if any */
|
||||
sp_fdbg_symbol_t *sym; /* pointer to original symbol */
|
||||
} sp_debug_symbol_t;
|
||||
|
||||
/**
|
||||
* Breaks into a debugger
|
||||
* Params:
|
||||
* [0] - plugin context
|
||||
* [1] - frm
|
||||
* [2] - cip
|
||||
*/
|
||||
typedef int (*SPVM_DEBUGBREAK)(struct sp_context_s *, uint32_t, uint32_t);
|
||||
|
||||
#define SPFLAG_PLUGIN_DEBUG (1<<0) /* plugin is in debug mode */
|
||||
|
||||
/**
|
||||
* This is the heart of the VM. It contains all of the runtime
|
||||
* information about a plugin context.
|
||||
* Note that user[0..3] can be used for any user based pointers.
|
||||
* vm[0..3] should not be touched, as it is reserved for the VM.
|
||||
*/
|
||||
typedef struct sp_context_s
|
||||
{
|
||||
/* general/parent information */
|
||||
void *codebase; /* base of generated code and memory */
|
||||
sp_plugin_t *plugin; /* pointer back to parent information */
|
||||
SourcePawn::IPluginContext *context; /* pointer to IPluginContext */
|
||||
SourcePawn::IVirtualMachine *vmbase; /* pointer to IVirtualMachine */
|
||||
void *user[4]; /* user specific pointers */
|
||||
void *vm[4]; /* VM specific pointers */
|
||||
uint32_t flags; /* compilation flags */
|
||||
SPVM_DEBUGBREAK dbreak; /* debug break function */
|
||||
/* context runtime information */
|
||||
uint8_t *memory; /* data chunk */
|
||||
ucell_t mem_size; /* total memory size; */
|
||||
cell_t data_size; /* data chunk size, always starts at 0 */
|
||||
cell_t heap_base; /* where the heap starts */
|
||||
/* execution specific data */
|
||||
cell_t hp; /* heap pointer */
|
||||
cell_t sp; /* stack pointer */
|
||||
cell_t frm; /* frame pointer */
|
||||
uint32_t pushcount; /* push count */
|
||||
int32_t n_err; /* error code set by a native */
|
||||
uint32_t n_idx; /* current native index being executed */
|
||||
/* context rebased database */
|
||||
sp_public_t *publics; /* public functions table */
|
||||
sp_pubvar_t *pubvars; /* public variables table */
|
||||
sp_native_t *natives; /* natives table */
|
||||
sp_debug_file_t *files; /* files */
|
||||
sp_debug_line_t *lines; /* lines */
|
||||
sp_debug_symbol_t *symbols; /* symbols */
|
||||
} sp_context_t;
|
||||
|
||||
#endif //_INCLUDE_SOURCEPAWN_VM_TYPES_H
|
||||
Reference in New Issue
Block a user