Operation
=========

The basic operation is, for each api call:

  - iterate through list of plugins
  - for each plugin, if it provides this api call, then call the function
    in the plugin
  - call the "real" function (in the game dll, or from the engine)
  - for each plugin, check for a "post" version of the function, and call
    if present

Also, for any api call, each plugin has the opportunity to replace the
real routine, in two ways:

  - prevent the real routine from being called (SUPERCEDE)
  - allow the real routine to be called, but change the value that's
    returned (OVERRIDE)

Thus after each plugin is called, its META_RETURN flag is checked, and
action taken appropriately. Note that supercede/override only affects the
_real_ routine; other plugins will still be called. In addition to the 
SUPERCEDE and OVERRIDE flags, there are two additional flags a plugin can
return:

  - HANDLED ("I did something here")
  - IGNORED ("I didn't really do anything")

These aren't used by metamod itself, but could be used by plugins to get
an idea if a previous plugin did anything.

Plugin coding requirements
==========================

Plugins MUST provide the following standard HLSDK exported function:

   void GiveFnptrsToDll(enginefuncs_t* pengfuncsFromEngine, globalvars_t *pGlobals);

AS WELL AS the following new functions:

   int Meta_Query(char *interfaceVersion, plugin_info_t **pinfo);
   int Meta_Attach(PLUG_LOADTIME now, META_FUNCTIONS *pFunctionTable, meta_globals_t *pMGlobals);
   int Meta_Detach(PLUG_LOADTIME now, PL_UNLOAD_REASON reason);

Also, it must provide AT LEAST one function returning a standard HL
function table, from either the following standard HLSDK functions:

   int GetEntityAPI( DLL_FUNCTIONS *pFunctionTable, int interfaceVersion );
   int GetEntityAPI2( DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion );
   int GetNewDLLFunctions( NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion );

or from the following new functions:

   int GetEntityAPI_Post(DLL_FUNCTIONS *pFunctionTable, int interfaceVersion);
   int GetEntityAPI2_Post(DLL_FUNCTIONS *pFunctionTable, int *interfaceVersion ;
   int GetNewDLLFunctions_Post(NEW_DLL_FUNCTIONS *pNewFunctionTable, int *interfaceVersion);

   int GetEngineFunctions(enginefuncs_t *pengfuncsFromEngine, int *interfaceVersion);
   int GetEngineFunctions_Post(enginefuncs_t *pengfuncsFromEngine, int *interfaceVersion);

Thus, it needs to have (at least):

   GiveFnptrsToDll
   Meta_Query
   Meta_Attach
   Meta_Detach
   <one or more Get function>

See the "stub_plugin" for an example of _bare minimum_ code. See "
trace_plugin" for an example of more complete functionality.

Also, if the plugin needs to use LINK_ENTITY_TO_CLASS, support for the
particular entity(ies) has to be added explicitly to metamod
(linkfunc.cpp), just as it does for entities in game DLLs.

Operation Details
=================

Plugins are loaded when the engine calls GiveFnptrsToDll(). The config
file is parsed, and for each valid plugin (uncommented, platform
relevant), the operation is:

  - dlopen() the file, store the handle
  - dlsym() and call: GiveFnptrsToDll MetaInit
  - if present, call function pointers, and store resulting function
    table:
       GetEntityAPI
       GetEntityAPI2
       GetNewDLLFunctions
    
       GetEntityAPI_Post
       GetEntityAPI2_Post
       GetNewDLLFunctions_Post
    
       GetEngineFunctions
       GetEngineFunctions_Post

