2004-09-24 02:45:00 +00:00
//This file should be easily portable.
//The biggest strength of this plugin system is that ALL interactions are performed via
//named functions, this makes it *really* easy to port plugins from one engine to annother.
# include "quakedef.h"
2004-09-30 22:51:15 +00:00
# ifdef PLUGINS
2004-09-24 02:45:00 +00:00
2005-01-15 17:46:40 +00:00
cvar_t plug_sbar = { " plug_sbar " , " 1 " } ;
cvar_t plug_loaddefault = { " plug_loaddefault " , " 1 " } ;
2005-08-01 14:17:27 +00:00
# ifdef RGLQUAKE
2004-10-10 06:32:29 +00:00
# include "glquake.h"
2005-08-01 14:17:27 +00:00
# endif
2004-10-10 06:32:29 +00:00
2005-11-29 13:32:15 +00:00
# include "netinc.h"
2004-09-24 02:45:00 +00:00
typedef struct plugin_s {
char * name ;
vm_t * vm ;
int tick ;
int executestring ;
2005-01-13 16:50:37 +00:00
int conexecutecommand ;
2004-09-26 00:30:42 +00:00
int menufunction ;
2004-10-10 06:32:29 +00:00
int sbarlevel [ 3 ] ; //0 - main sbar, 1 - supplementry sbar sections (make sure these can be switched off), 2 - overlays (scoreboard). menus kill all.
int reschange ;
2004-09-24 02:45:00 +00:00
2005-08-03 23:14:59 +00:00
//protocol-in-a-plugin
int connectionlessclientpacket ;
2005-11-30 05:01:43 +00:00
int messagefunction ;
2004-09-24 02:45:00 +00:00
struct plugin_s * next ;
} plugin_t ;
2005-03-10 03:55:18 +00:00
void Plug_SubConsoleCommand ( console_t * con , char * line ) ;
2004-09-24 02:45:00 +00:00
plugin_t * currentplug ;
//custom plugin builtins.
2005-08-12 00:22:38 +00:00
typedef int ( VARGS * Plug_Builtin_t ) ( void * offset , unsigned int mask , const long * arg ) ;
2004-09-24 02:45:00 +00:00
void Plug_RegisterBuiltin ( char * name , Plug_Builtin_t bi , int flags ) ;
# define PLUG_BIF_DLLONLY 1
# define PLUG_BIF_QVMONLY 2
void Plug_Init ( void ) ;
2005-08-03 23:14:59 +00:00
void Plug_Close ( plugin_t * plug ) ;
2004-09-24 02:45:00 +00:00
void Plug_Tick ( void ) ;
qboolean Plugin_ExecuteString ( void ) ;
void Plug_Shutdown ( void ) ;
static plugin_t * plugs ;
2004-09-26 00:30:42 +00:00
static plugin_t * menuplug ; //plugin that has the current menu
2005-08-03 23:14:59 +00:00
static plugin_t * protocolclientplugin ;
2004-09-24 02:45:00 +00:00
typedef struct {
char * name ;
Plug_Builtin_t func ;
2005-11-30 01:20:53 +00:00
int flags ;
2004-09-24 02:45:00 +00:00
} Plug_Plugins_t ;
Plug_Plugins_t * plugbuiltins ;
int numplugbuiltins ;
void Plug_RegisterBuiltin ( char * name , Plug_Builtin_t bi , int flags )
{
//randomize the order a little.
int newnum ;
newnum = rand ( ) % 128 ;
while ( newnum < numplugbuiltins & & plugbuiltins [ newnum ] . func )
newnum + = 128 ;
2004-12-04 16:26:22 +00:00
if ( newnum > = numplugbuiltins )
2004-09-24 02:45:00 +00:00
{
numplugbuiltins = newnum + 128 ;
plugbuiltins = BZ_Realloc ( plugbuiltins , sizeof ( Plug_Plugins_t ) * numplugbuiltins ) ;
}
//got an empty number.
plugbuiltins [ newnum ] . name = name ;
plugbuiltins [ newnum ] . func = bi ;
2005-11-30 01:20:53 +00:00
plugbuiltins [ newnum ] . flags = flags ;
2004-09-24 02:45:00 +00:00
}
/*
static void Plug_RegisterBuiltinIndex ( char * name , Plug_Builtin_t bi , int flags , int index ) //I d
{
//randomize the order a little.
int newnum ;
newnum = rand ( ) % 128 ;
while ( newnum + 1 < numplugbuiltins & & plugbuiltins [ newnum + 1 ] . func )
newnum + = 128 ;
newnum + + ;
2004-12-04 16:26:22 +00:00
if ( newnum > = numplugbuiltins )
2004-09-24 02:45:00 +00:00
{
numplugbuiltins = newnum + 128 ;
plugbuiltins = BZ_Realloc ( plugbuiltins , sizeof ( Plug_Plugins_t ) * numplugbuiltins ) ;
}
//got an empty number.
plugbuiltins [ newnum ] . name = name ;
plugbuiltins [ newnum ] . func = bi ;
}
*/
2005-08-12 00:22:38 +00:00
int VARGS Plug_FindBuiltin ( void * offset , unsigned int mask , const long * args )
2004-09-24 02:45:00 +00:00
{
int i ;
for ( i = 0 ; i < numplugbuiltins ; i + + )
if ( plugbuiltins [ i ] . name )
2004-09-26 00:30:42 +00:00
if ( ! strcmp ( plugbuiltins [ i ] . name , ( char * ) VM_POINTER ( args [ 0 ] ) ) )
2005-11-30 01:20:53 +00:00
{
if ( offset & & plugbuiltins [ i ] . flags & PLUG_BIF_DLLONLY )
return 0 ; //block it, if not native
if ( ! offset & & plugbuiltins [ i ] . flags & PLUG_BIF_QVMONLY )
return 0 ; //block it, if not native
2004-09-24 02:45:00 +00:00
return - i ;
2005-11-30 01:20:53 +00:00
}
2004-09-24 02:45:00 +00:00
return 0 ;
}
long Plug_SystemCallsEx ( void * offset , unsigned int mask , int fn , const long * arg )
{
fn = fn + 1 ;
if ( fn > = 0 & & fn < numplugbuiltins & & plugbuiltins [ fn ] . func ! = NULL )
return plugbuiltins [ fn ] . func ( offset , mask , arg ) ;
Sys_Error ( " QVM Plugin tried calling invalid builtin %i " , fn ) ;
return 0 ;
}
# ifdef _DEBUG
static long Plug_SystemCallsExWrapper ( void * offset , unsigned int mask , int fn , const long * arg )
{ //this is so we can use edit and continue properly (vc doesn't like function pointers for edit+continue)
return Plug_SystemCallsEx ( offset , mask , fn , arg ) ;
}
# define Plug_SystemCallsEx Plug_SystemCallsExWrapper
# endif
//I'm not keen on this.
//but dlls call it without saying what sort of vm it comes from, so I've got to have them as specifics
static int EXPORT_FN Plug_SystemCalls ( int arg , . . . )
{
long args [ 9 ] ;
va_list argptr ;
va_start ( argptr , arg ) ;
args [ 0 ] = va_arg ( argptr , int ) ;
args [ 1 ] = va_arg ( argptr , int ) ;
args [ 2 ] = va_arg ( argptr , int ) ;
args [ 3 ] = va_arg ( argptr , int ) ;
args [ 4 ] = va_arg ( argptr , int ) ;
args [ 5 ] = va_arg ( argptr , int ) ;
args [ 6 ] = va_arg ( argptr , int ) ;
args [ 7 ] = va_arg ( argptr , int ) ;
args [ 8 ] = va_arg ( argptr , int ) ;
va_end ( argptr ) ;
arg = - arg ;
if ( arg > = 0 & & arg < numplugbuiltins & & plugbuiltins [ arg ] . func )
return plugbuiltins [ arg ] . func ( NULL , ~ 0 , args ) ;
Sys_Error ( " DLL Plugin tried calling invalid biultin %i " , arg ) ;
return 0 ;
}
plugin_t * Plug_Load ( char * file )
{
plugin_t * newplug ;
2005-01-24 23:47:32 +00:00
long argarray ;
2004-09-24 02:45:00 +00:00
for ( newplug = plugs ; newplug ; newplug = newplug - > next )
{
if ( ! stricmp ( newplug - > name , file ) )
2005-08-03 23:14:59 +00:00
return newplug ;
2004-09-24 02:45:00 +00:00
}
newplug = Z_Malloc ( sizeof ( plugin_t ) + strlen ( file ) + 1 ) ;
newplug - > name = ( char * ) ( newplug + 1 ) ;
strcpy ( newplug - > name , file ) ;
newplug - > vm = VM_Create ( NULL , file , Plug_SystemCalls , Plug_SystemCallsEx ) ;
currentplug = newplug ;
if ( newplug - > vm )
{
2005-08-03 23:14:59 +00:00
Con_Printf ( " Created plugin %s \n " , file ) ;
2004-09-24 02:45:00 +00:00
newplug - > next = plugs ;
plugs = newplug ;
2005-05-26 12:55:34 +00:00
argarray = 4 ;
2005-08-03 23:14:59 +00:00
if ( ! VM_Call ( newplug - > vm , 0 , Plug_FindBuiltin ( " Plug_GetEngineFunction " - 4 , ~ 0 , & argarray ) ) )
{
Plug_Close ( newplug ) ;
return NULL ;
}
2004-10-10 06:32:29 +00:00
if ( newplug - > reschange )
VM_Call ( newplug - > vm , newplug - > reschange , vid . width , vid . height ) ;
2004-09-24 02:45:00 +00:00
}
else
{
Z_Free ( newplug ) ;
newplug = NULL ;
}
currentplug = NULL ;
return newplug ;
}
int Plug_Emumerated ( char * name , int size , void * param )
{
char vmname [ MAX_QPATH ] ;
strcpy ( vmname , name ) ;
vmname [ strlen ( vmname ) - strlen ( param ) ] = ' \0 ' ;
Plug_Load ( vmname ) ;
return true ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Con_Print ( void * offset , unsigned int mask , const long * arg )
2004-09-24 02:45:00 +00:00
{
2004-09-26 00:30:42 +00:00
Con_Print ( ( char * ) VM_POINTER ( arg [ 0 ] ) ) ;
2004-09-24 02:45:00 +00:00
return 0 ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Sys_Error ( void * offset , unsigned int mask , const long * arg )
2004-09-24 02:45:00 +00:00
{
Sys_Error ( " %s " , ( char * ) offset + arg [ 0 ] ) ;
return 0 ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Sys_Milliseconds ( void * offset , unsigned int mask , const long * arg )
2005-03-01 15:36:23 +00:00
{
return Sys_DoubleTime ( ) * 1000 ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_ExportToEngine ( void * offset , unsigned int mask , const long * arg )
2004-09-24 02:45:00 +00:00
{
2004-09-26 00:30:42 +00:00
char * name = ( char * ) VM_POINTER ( arg [ 0 ] ) ;
2004-09-24 02:45:00 +00:00
if ( ! strcmp ( name , " Tick " ) )
currentplug - > tick = arg [ 1 ] ;
else if ( ! strcmp ( name , " ExecuteCommand " ) )
currentplug - > executestring = arg [ 1 ] ;
2005-01-13 16:50:37 +00:00
else if ( ! strcmp ( name , " ConExecuteCommand " ) )
currentplug - > conexecutecommand = arg [ 1 ] ;
2004-09-26 00:30:42 +00:00
else if ( ! strcmp ( name , " MenuEvent " ) )
currentplug - > menufunction = arg [ 1 ] ;
2004-10-10 06:32:29 +00:00
else if ( ! strcmp ( name , " UpdateVideo " ) )
currentplug - > reschange = arg [ 1 ] ;
2004-10-13 07:24:59 +00:00
else if ( ! strcmp ( name , " SbarBase " ) ) //basic SBAR.
currentplug - > sbarlevel [ 0 ] = arg [ 1 ] ;
else if ( ! strcmp ( name , " SbarSupplement " ) ) //supplementry stuff - teamplay
currentplug - > sbarlevel [ 1 ] = arg [ 1 ] ;
else if ( ! strcmp ( name , " SbarOverlay " ) ) //overlay - scoreboard type stuff.
currentplug - > sbarlevel [ 2 ] = arg [ 1 ] ;
2005-08-03 23:14:59 +00:00
else if ( ! strcmp ( name , " ConnectionlessClientPacket " ) )
currentplug - > connectionlessclientpacket = arg [ 1 ] ;
2005-11-30 05:01:43 +00:00
else if ( ! strcmp ( name , " MessageEvent " ) )
currentplug - > messagefunction = arg [ 1 ] ;
2004-09-24 02:45:00 +00:00
else
return 0 ;
return 1 ;
}
2004-10-10 06:32:29 +00:00
2005-11-30 01:20:53 +00:00
typedef void ( * funcptr_t ) ( ) ;
int VARGS Plug_ExportNative ( void * offset , unsigned int mask , const long * arg )
{
funcptr_t func ;
char * name = ( char * ) VM_POINTER ( arg [ 0 ] ) ;
arg + + ;
func = * ( funcptr_t * ) arg ;
if ( ! strcmp ( name , " S_LoadSound " ) )
S_RegisterSoundInputPlugin ( func ) ;
else
return 0 ;
return 1 ;
}
2004-10-10 06:32:29 +00:00
typedef struct {
//Make SURE that the engine has resolved all cvar pointers into globals before this happens.
plugin_t * plugin ;
cvar_t * var ;
} plugincvararray_t ;
int plugincvararraylen ;
plugincvararray_t * plugincvararray ;
//qhandle_t Cvar_Register (char *name, char *defaultval, int flags, char *grouphint);
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cvar_Register ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ;
char * defaultvalue = VM_POINTER ( arg [ 1 ] ) ;
unsigned int flags = VM_LONG ( arg [ 2 ] ) ;
char * groupname = VM_POINTER ( arg [ 3 ] ) ;
cvar_t * var ;
int i ;
var = Cvar_Get ( name , defaultvalue , flags & 1 , groupname ) ;
for ( i = 0 ; i < plugincvararraylen ; i + + )
{
if ( ! plugincvararray [ i ] . var )
{ //hmm... a gap...
plugincvararray [ i ] . plugin = currentplug ;
plugincvararray [ i ] . var = var ;
return i ;
}
}
plugincvararray = BZ_Realloc ( plugincvararray , ( plugincvararraylen + 1 ) * sizeof ( plugincvararray_t ) ) ;
plugincvararray [ plugincvararraylen ] . plugin = currentplug ;
plugincvararray [ plugincvararraylen ] . var = var ;
plugincvararraylen + + ;
return plugincvararraylen - 1 ;
}
//int Cvar_Update, (qhandle_t handle, int modificationcount, char *stringv, float *floatv)); //stringv is 256 chars long, don't expect this function to do anything if modification count is unchanged.
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cvar_Update ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
int handle ;
int modcount ;
char * stringv ; //255 bytes long.
float * floatv ;
cvar_t * var ;
handle = VM_LONG ( arg [ 0 ] ) ;
if ( handle < 0 | | handle > = plugincvararraylen )
return 0 ;
if ( plugincvararray [ handle ] . plugin ! = currentplug )
return 0 ; //I'm not letting you know what annother plugin has registered.
if ( VM_OOB ( arg [ 2 ] , 256 ) | | VM_OOB ( arg [ 3 ] , 4 ) ) //Oi, plugin - you screwed up
return 0 ;
modcount = VM_LONG ( arg [ 1 ] ) ;
stringv = VM_POINTER ( arg [ 2 ] ) ;
floatv = VM_POINTER ( arg [ 3 ] ) ;
var = plugincvararray [ handle ] . var ;
strcpy ( stringv , var - > string ) ;
* floatv = var - > value ;
return var - > modified ;
}
//void Cmd_Args(char *buffer, int buffersize)
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cmd_Args ( void * offset , unsigned int mask , const long * arg )
2004-09-24 02:45:00 +00:00
{
2004-09-26 00:30:42 +00:00
char * buffer = ( char * ) VM_POINTER ( arg [ 0 ] ) ;
2004-09-24 02:45:00 +00:00
char * args ;
args = Cmd_Args ( ) ;
if ( strlen ( args ) + 1 > arg [ 1 ] )
return 0 ;
strcpy ( buffer , args ) ;
return 1 ;
}
2004-10-10 06:32:29 +00:00
//void Cmd_Argv(int num, char *buffer, int buffersize)
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cmd_Argv ( void * offset , unsigned int mask , const long * arg )
2004-09-24 02:45:00 +00:00
{
2004-09-26 00:30:42 +00:00
char * buffer = ( char * ) VM_POINTER ( arg [ 1 ] ) ;
2004-09-24 02:45:00 +00:00
char * args ;
args = Cmd_Argv ( arg [ 0 ] ) ;
if ( strlen ( args ) + 1 > arg [ 2 ] )
return 0 ;
strcpy ( buffer , args ) ;
return 1 ;
}
2004-10-10 06:32:29 +00:00
//int Cmd_Argc(void)
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cmd_Argc ( void * offset , unsigned int mask , const long * arg )
2004-09-24 02:45:00 +00:00
{
return Cmd_Argc ( ) ;
}
2004-09-26 00:30:42 +00:00
2005-08-12 00:22:38 +00:00
int VARGS Plug_Menu_Control ( void * offset , unsigned int mask , const long * arg )
2004-09-26 00:30:42 +00:00
{
switch ( VM_LONG ( arg [ 0 ] ) )
{
2004-10-10 06:32:29 +00:00
case 0 : //take away all menus
case 1 :
if ( menuplug )
{
plugin_t * oldplug = currentplug ;
currentplug = menuplug ;
Plug_Menu_Event ( 3 , 0 ) ;
menuplug = NULL ;
currentplug = oldplug ;
key_dest = key_game ;
}
if ( VM_LONG ( arg [ 0 ] ) ! = 1 )
return 1 ;
//give us menu control
2004-09-26 00:30:42 +00:00
menuplug = currentplug ;
key_dest = key_menu ;
2004-10-10 06:32:29 +00:00
m_state = m_plugin ;
2004-09-26 00:30:42 +00:00
return 1 ;
2004-10-10 06:32:29 +00:00
case 2 : //weather it's us or not.
return currentplug = = menuplug & & m_state = = m_plugin ;
case 3 : //weather a menu is active
return key_dest = = key_menu ;
default :
return 0 ;
}
}
2004-10-13 07:24:59 +00:00
typedef struct {
//Make SURE that the engine has resolved all cvar pointers into globals before this happens.
plugin_t * plugin ;
char name [ 64 ] ;
qboolean picfromwad ;
2004-12-24 08:45:56 +00:00
mpic_t * pic ;
2004-10-13 07:24:59 +00:00
} pluginimagearray_t ;
int pluginimagearraylen ;
pluginimagearray_t * pluginimagearray ;
2005-08-12 00:22:38 +00:00
int VARGS Plug_Draw_LoadImage ( void * offset , unsigned int mask , const long * arg )
2004-10-13 07:24:59 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ;
qboolean fromwad = arg [ 1 ] ;
int i ;
2004-12-24 08:45:56 +00:00
mpic_t * pic ;
2004-10-13 07:24:59 +00:00
for ( i = 0 ; i < pluginimagearraylen ; i + + )
{
if ( ! pluginimagearray [ i ] . plugin )
break ;
if ( pluginimagearray [ i ] . plugin = = currentplug )
{
if ( ! strcmp ( name , pluginimagearray [ i ] . name ) )
break ;
}
}
if ( i = = pluginimagearraylen )
{
pluginimagearraylen + + ;
pluginimagearray = BZ_Realloc ( pluginimagearray , pluginimagearraylen * sizeof ( pluginimagearray_t ) ) ;
}
2005-01-15 17:46:40 +00:00
if ( pluginimagearray [ i ] . pic )
return i ; //already loaded.
2004-10-13 07:24:59 +00:00
if ( qrenderer )
{
if ( fromwad )
pic = Draw_SafePicFromWad ( name ) ;
else
{
# ifdef RGLQUAKE //GL saves images persistantly (so don't bother with cachepic stuff)
if ( qrenderer = = QR_OPENGL )
pic = Draw_SafeCachePic ( name ) ;
else
# endif
pic = NULL ;
}
}
else
pic = NULL ;
Q_strncpyz ( pluginimagearray [ i ] . name , name , sizeof ( pluginimagearray [ i ] . name ) ) ;
pluginimagearray [ i ] . picfromwad = fromwad ;
pluginimagearray [ i ] . pic = pic ;
pluginimagearray [ i ] . plugin = currentplug ;
return i ;
}
void Plug_DrawReloadImages ( void )
{
int i ;
for ( i = 0 ; i < pluginimagearraylen ; i + + )
{
if ( ! pluginimagearray [ i ] . plugin )
2005-01-15 17:46:40 +00:00
{
pluginimagearray [ i ] . pic = NULL ;
2004-10-13 07:24:59 +00:00
continue ;
2005-01-15 17:46:40 +00:00
}
2004-10-13 07:24:59 +00:00
if ( pluginimagearray [ i ] . picfromwad )
pluginimagearray [ i ] . pic = Draw_SafePicFromWad ( pluginimagearray [ i ] . name ) ;
# ifdef RGLQUAKE
else if ( qrenderer = = QR_OPENGL )
pluginimagearray [ i ] . pic = Draw_SafeCachePic ( pluginimagearray [ i ] . name ) ;
# endif
else
pluginimagearray [ i ] . pic = NULL ;
}
}
2005-01-15 17:46:40 +00:00
void Plug_FreePlugImages ( plugin_t * plug )
{
int i ;
for ( i = 0 ; i < pluginimagearraylen ; i + + )
{
if ( pluginimagearray [ i ] . plugin = = plug )
{
pluginimagearray [ i ] . plugin = 0 ;
pluginimagearray [ i ] . pic = NULL ;
pluginimagearray [ i ] . name [ 0 ] = ' \0 ' ;
}
}
}
2004-10-13 07:24:59 +00:00
//int Draw_Image (float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t image)
2005-08-12 00:22:38 +00:00
int VARGS Plug_Draw_Image ( void * offset , unsigned int mask , const long * arg )
2004-10-13 07:24:59 +00:00
{
2004-12-24 08:45:56 +00:00
mpic_t * pic ;
2004-10-13 07:24:59 +00:00
int i ;
if ( ! qrenderer )
return 0 ;
2004-12-24 08:45:56 +00:00
if ( ! Draw_Image )
return 0 ;
2004-10-13 07:24:59 +00:00
i = VM_LONG ( arg [ 8 ] ) ;
if ( i < 0 | | i > = pluginimagearraylen )
return - 1 ; // you fool
if ( pluginimagearray [ i ] . plugin ! = currentplug )
return - 1 ;
if ( pluginimagearray [ i ] . pic )
pic = pluginimagearray [ i ] . pic ;
else if ( pluginimagearray [ i ] . picfromwad )
return 0 ; //wasn't loaded.
else
pic = Draw_CachePic ( pluginimagearray [ i ] . name ) ;
2004-12-24 08:45:56 +00:00
Draw_Image ( VM_FLOAT ( arg [ 0 ] ) , VM_FLOAT ( arg [ 1 ] ) , VM_FLOAT ( arg [ 2 ] ) , VM_FLOAT ( arg [ 3 ] ) , VM_FLOAT ( arg [ 4 ] ) , VM_FLOAT ( arg [ 5 ] ) , VM_FLOAT ( arg [ 6 ] ) , VM_FLOAT ( arg [ 7 ] ) , pic ) ;
2004-10-13 07:24:59 +00:00
return 1 ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Draw_Character ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
Draw_Character ( arg [ 0 ] , arg [ 1 ] , ( unsigned int ) arg [ 2 ] ) ;
return 0 ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Draw_Fill ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
2004-10-13 07:24:59 +00:00
float x , y , width , height ;
x = VM_FLOAT ( arg [ 0 ] ) ;
y = VM_FLOAT ( arg [ 1 ] ) ;
width = VM_FLOAT ( arg [ 2 ] ) ;
height = VM_FLOAT ( arg [ 3 ] ) ;
2005-01-24 23:47:32 +00:00
switch ( qrenderer ) //FIXME: I don't want qrenderer seen outside the refresh
2004-10-13 07:24:59 +00:00
{
# ifdef RGLQUAKE
case QR_OPENGL :
2005-01-13 16:50:37 +00:00
qglDisable ( GL_TEXTURE_2D ) ;
qglBegin ( GL_QUADS ) ;
qglVertex2f ( x , y ) ;
qglVertex2f ( x + width , y ) ;
qglVertex2f ( x + width , y + height ) ;
qglVertex2f ( x , y + height ) ;
qglEnd ( ) ;
qglEnable ( GL_TEXTURE_2D ) ;
2004-10-13 07:24:59 +00:00
return 1 ;
# endif
2005-01-24 23:47:32 +00:00
default :
break ;
2004-10-13 07:24:59 +00:00
}
2004-10-10 06:32:29 +00:00
return 0 ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Draw_ColourP ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
2004-11-13 09:23:09 +00:00
qbyte * pal = host_basepal + VM_LONG ( arg [ 0 ] ) * 3 ;
2004-10-10 06:32:29 +00:00
if ( arg [ 0 ] < 0 | | arg [ 0 ] > 255 )
return false ;
2004-11-23 01:11:54 +00:00
if ( Draw_ImageColours )
2004-10-10 06:32:29 +00:00
{
2004-11-23 01:11:54 +00:00
Draw_ImageColours ( pal [ 0 ] / 255.0f , pal [ 1 ] / 255.0f , pal [ 2 ] / 255.0f , 1 ) ;
return 1 ;
2004-10-10 06:32:29 +00:00
}
2004-11-23 01:11:54 +00:00
return 0 ;
2004-10-10 06:32:29 +00:00
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Draw_Colour3f ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
2004-11-23 01:11:54 +00:00
if ( Draw_ImageColours )
2004-10-10 06:32:29 +00:00
{
2004-11-23 01:11:54 +00:00
Draw_ImageColours ( VM_FLOAT ( arg [ 0 ] ) , VM_FLOAT ( arg [ 1 ] ) , VM_FLOAT ( arg [ 2 ] ) , 1 ) ;
return 1 ;
2004-10-10 06:32:29 +00:00
}
2004-11-23 01:11:54 +00:00
return 0 ;
2004-10-10 06:32:29 +00:00
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Draw_Colour4f ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
2004-11-23 01:11:54 +00:00
if ( Draw_ImageColours )
2004-10-10 06:32:29 +00:00
{
2004-11-23 01:11:54 +00:00
Draw_ImageColours ( VM_FLOAT ( arg [ 0 ] ) , VM_FLOAT ( arg [ 1 ] ) , VM_FLOAT ( arg [ 2 ] ) , VM_FLOAT ( arg [ 3 ] ) ) ;
return 1 ;
2004-09-26 00:30:42 +00:00
}
2004-11-23 01:11:54 +00:00
return 0 ;
2004-10-10 06:32:29 +00:00
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Media_ShowFrameRGBA_32 ( void * offset , unsigned int mask , const long * arg )
2005-03-01 15:36:23 +00:00
{
void * src = VM_POINTER ( arg [ 0 ] ) ;
int srcwidth = VM_LONG ( arg [ 1 ] ) ;
int srcheight = VM_LONG ( arg [ 2 ] ) ;
int x = VM_LONG ( arg [ 3 ] ) ;
int y = VM_LONG ( arg [ 4 ] ) ;
int width = VM_LONG ( arg [ 5 ] ) ;
int height = VM_LONG ( arg [ 6 ] ) ;
Media_ShowFrameRGBA_32 ( src , srcwidth , srcheight ) ;
return 0 ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Key_GetKeyCode ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
int modifier ;
return Key_StringToKeynum ( VM_POINTER ( arg [ 0 ] ) , & modifier ) ;
}
//void Cvar_SetString (char *name, char *value);
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cvar_SetString ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ,
* value = VM_POINTER ( arg [ 1 ] ) ;
cvar_t * var = Cvar_Get ( name , value , 0 , " Plugin vars " ) ;
if ( var )
{
Cvar_Set ( var , value ) ;
return 1 ;
}
return 0 ;
}
//void Cvar_SetFloat (char *name, float value);
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cvar_SetFloat ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ;
float value = VM_FLOAT ( arg [ 1 ] ) ;
cvar_t * var = Cvar_Get ( name , " " , 0 , " Plugin vars " ) ; //"" because I'm lazy
if ( var )
{
Cvar_SetValue ( var , value ) ;
return 1 ;
}
return 0 ;
}
//void Cvar_GetFloat (char *name);
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cvar_GetFloat ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ;
int ret ;
cvar_t * var = Cvar_Get ( name , " " , 0 , " Plugin vars " ) ;
if ( var )
{
VM_FLOAT ( ret ) = var - > value ;
}
else
VM_FLOAT ( ret ) = 0 ;
return ret ;
}
//qboolean Cvar_GetString (char *name, char *retstring, int sizeofretstring);
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cvar_GetString ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
char * name , * ret ;
int retsize ;
cvar_t * var ;
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
{
return false ;
}
name = VM_POINTER ( arg [ 0 ] ) ;
ret = VM_POINTER ( arg [ 1 ] ) ;
retsize = VM_LONG ( arg [ 2 ] ) ;
var = Cvar_Get ( name , " " , 0 , " Plugin vars " ) ;
if ( strlen ( var - > name ) + 1 > retsize )
return false ;
strcpy ( ret , var - > string ) ;
return true ;
}
//void Cmd_AddText (char *text, qboolean insert); //abort the entire engine.
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cmd_AddText ( void * offset , unsigned int mask , const long * arg )
2004-10-10 06:32:29 +00:00
{
if ( VM_LONG ( arg [ 1 ] ) )
Cbuf_InsertText ( VM_POINTER ( arg [ 0 ] ) , RESTRICT_LOCAL ) ;
else
Cbuf_AddText ( VM_POINTER ( arg [ 0 ] ) , RESTRICT_LOCAL ) ;
return 1 ;
2004-09-26 00:30:42 +00:00
}
2005-01-15 17:46:40 +00:00
int plugincommandarraylen ;
typedef struct {
plugin_t * plugin ;
char command [ 64 ] ;
} plugincommand_t ;
plugincommand_t * plugincommandarray ;
void Plug_Command_f ( void )
{
int i ;
char * cmd = Cmd_Argv ( 0 ) ;
plugin_t * oldplug = currentplug ;
for ( i = 0 ; i < plugincommandarraylen ; i + + )
{
if ( ! plugincommandarray [ i ] . plugin )
continue ; //don't check commands who's owners died.
if ( stricmp ( plugincommandarray [ i ] . command , cmd ) ) //not the right command
continue ;
currentplug = plugincommandarray [ i ] . plugin ;
if ( currentplug - > executestring )
VM_Call ( currentplug - > vm , currentplug - > executestring , 0 ) ;
break ;
}
currentplug = oldplug ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Cmd_AddCommand ( void * offset , unsigned int mask , const long * arg )
2005-01-15 17:46:40 +00:00
{
int i ;
char * name = VM_POINTER ( arg [ 0 ] ) ;
for ( i = 0 ; i < plugincommandarraylen ; i + + )
{
if ( ! plugincommandarray [ i ] . plugin )
break ;
if ( plugincommandarray [ i ] . plugin = = currentplug )
{
if ( ! strcmp ( name , plugincommandarray [ i ] . command ) )
break ;
}
}
if ( i = = plugincommandarraylen )
{
plugincommandarraylen + + ;
plugincommandarray = BZ_Realloc ( plugincommandarray , plugincommandarraylen * sizeof ( plugincommand_t ) ) ;
}
Q_strncpyz ( plugincommandarray [ i ] . command , name , sizeof ( plugincommandarray [ i ] . command ) ) ;
if ( ! Cmd_AddRemCommand ( plugincommandarray [ i ] . command , Plug_Command_f ) )
return false ;
plugincommandarray [ i ] . plugin = currentplug ; //worked
return true ;
}
2005-08-12 00:22:38 +00:00
void VARGS Plug_FreeConCommands ( plugin_t * plug )
2005-01-15 17:46:40 +00:00
{
int i ;
for ( i = 0 ; i < plugincommandarraylen ; i + + )
{
if ( plugincommandarray [ i ] . plugin = = plug )
{
plugincommandarray [ i ] . plugin = NULL ;
Cmd_RemoveCommand ( plugincommandarray [ i ] . command ) ;
}
}
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_CL_GetStats ( void * offset , unsigned int mask , const long * arg )
2004-10-13 07:24:59 +00:00
{
int i ;
int pnum = VM_LONG ( arg [ 0 ] ) ;
unsigned int * stats = VM_POINTER ( arg [ 1 ] ) ;
int pluginstats = VM_LONG ( arg [ 2 ] ) ;
int max ;
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] * 4 ) )
return 0 ;
max = pluginstats ;
if ( max > MAX_CL_STATS )
max = MAX_CL_STATS ;
for ( i = 0 ; i < max ; i + + )
{ //fill stats with the right player's stats
stats [ i ] = cl . stats [ pnum ] [ i ] ;
}
for ( ; i < pluginstats ; i + + ) //plugin has too many stats (wow)
stats [ i ] = 0 ; //fill the rest.
return max ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Con_SubPrint ( void * offset , unsigned int mask , const long * arg )
2005-01-13 16:50:37 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ;
char * text = VM_POINTER ( arg [ 1 ] ) ;
console_t * con ;
con = Con_FindConsole ( name ) ;
if ( ! con )
{
con = Con_Create ( name ) ;
Con_SetVisible ( con ) ;
2005-03-10 03:55:18 +00:00
if ( currentplug - > conexecutecommand )
{
con - > userdata = currentplug ;
con - > linebuffered = Plug_SubConsoleCommand ;
}
2005-01-13 16:50:37 +00:00
}
Con_PrintCon ( con , text ) ;
return 1 ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Con_RenameSub ( void * offset , unsigned int mask , const long * arg )
2005-01-13 16:50:37 +00:00
{
char * name = VM_POINTER ( arg [ 0 ] ) ;
console_t * con ;
con = Con_FindConsole ( name ) ;
if ( ! con )
return 0 ;
Q_strncpyz ( con - > name , name , sizeof ( con - > name ) ) ;
return 1 ;
}
2005-03-01 15:36:23 +00:00
typedef enum {
STREAM_NONE ,
STREAM_SOCKET ,
2005-11-30 01:20:53 +00:00
STREAM_OSFILE ,
2005-03-01 15:36:23 +00:00
STREAM_FILE
} plugstream_e ;
typedef struct {
plugin_t * plugin ;
plugstream_e type ;
int socket ;
2005-11-30 01:20:53 +00:00
struct {
char filename [ MAX_QPATH ] ;
qbyte * buffer ;
int buflen ;
int curlen ;
int curpos ;
} file ;
2005-03-01 15:36:23 +00:00
} pluginstream_t ;
pluginstream_t * pluginstreamarray ;
int pluginstreamarraylen ;
int Plug_NewStreamHandle ( plugstream_e type )
{
int i ;
for ( i = 0 ; i < pluginstreamarraylen ; i + + )
{
if ( ! pluginstreamarray [ i ] . plugin )
break ;
}
if ( i = = pluginstreamarraylen )
{
pluginstreamarraylen + + ;
pluginstreamarray = BZ_Realloc ( pluginstreamarray , pluginstreamarraylen * sizeof ( pluginstream_t ) ) ;
}
memset ( & pluginstreamarray [ i ] , 0 , sizeof ( pluginstream_t ) ) ;
pluginstreamarray [ i ] . plugin = currentplug ;
pluginstreamarray [ i ] . type = type ;
pluginstreamarray [ i ] . socket = - 1 ;
2005-11-30 01:20:53 +00:00
pluginstreamarray [ i ] . file . buffer = NULL ;
* pluginstreamarray [ i ] . file . filename = ' \0 ' ;
2005-03-01 15:36:23 +00:00
return i ;
}
//EBUILTIN(int, NET_TCPListen, (char *ip, int port, int maxcount));
//returns a new socket with listen enabled.
2005-08-12 00:22:38 +00:00
int VARGS Plug_Net_TCPListen ( void * offset , unsigned int mask , const long * arg )
2005-03-01 15:36:23 +00:00
{
int handle ;
int sock ;
struct sockaddr_qstorage address ;
int _true = 1 ;
char * localip = VM_POINTER ( arg [ 0 ] ) ;
unsigned short localport = VM_LONG ( arg [ 1 ] ) ;
int maxcount = VM_LONG ( arg [ 2 ] ) ;
netadr_t a ;
if ( localip )
{
if ( ! NET_StringToAdr ( localip , & a ) )
return - 1 ;
NetadrToSockadr ( & a , & address ) ;
}
else
{
memset ( & address , 0 , sizeof ( address ) ) ;
( ( struct sockaddr_in * ) & address ) - > sin_family = AF_INET ;
}
if ( ( ( struct sockaddr_in * ) & address ) - > sin_family = = AF_INET & & ! ( ( struct sockaddr_in * ) & address ) - > sin_port )
( ( struct sockaddr_in * ) & address ) - > sin_port = htons ( localport ) ;
# ifdef IPPROTO_IPV6
2005-03-20 02:57:11 +00:00
else if ( ( ( struct sockaddr_in6 * ) & address ) - > sin6_family = = AF_INET6 & & ! ( ( struct sockaddr_in6 * ) & address ) - > sin6_port )
2005-03-01 15:36:23 +00:00
( ( struct sockaddr_in6 * ) & address ) - > sin6_port = htons ( localport ) ;
# endif
if ( ( sock = socket ( ( ( struct sockaddr * ) & address ) - > sa_family , SOCK_STREAM , 0 ) ) = = - 1 )
{
Con_Printf ( " Failed to create socket \n " ) ;
return - 2 ;
}
if ( ioctlsocket ( sock , FIONBIO , & _true ) = = - 1 )
{
closesocket ( sock ) ;
return - 2 ;
}
if ( bind ( sock , ( void * ) & address , sizeof ( address ) ) = = - 1 )
{
closesocket ( sock ) ;
return - 2 ;
}
if ( listen ( sock , maxcount ) = = - 1 )
{
closesocket ( sock ) ;
return - 2 ;
}
handle = Plug_NewStreamHandle ( STREAM_SOCKET ) ;
pluginstreamarray [ handle ] . socket = sock ;
return handle ;
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Net_Accept ( void * offset , unsigned int mask , const long * arg )
2005-03-01 15:36:23 +00:00
{
int handle = VM_LONG ( arg [ 0 ] ) ;
struct sockaddr_in address ;
int addrlen ;
int sock ;
int _true = 1 ;
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug | | pluginstreamarray [ handle ] . type ! = STREAM_SOCKET )
return - 2 ;
sock = pluginstreamarray [ handle ] . socket ;
addrlen = sizeof ( address ) ;
sock = accept ( sock , ( struct sockaddr * ) & address , & addrlen ) ;
if ( sock < 0 )
return - 1 ;
if ( ioctlsocket ( sock , FIONBIO , & _true ) = = - 1 ) //now make it non blocking.
{
closesocket ( sock ) ;
return - 1 ;
}
if ( arg [ 2 ] & & ! VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
{
netadr_t a ;
char * s ;
SockadrToNetadr ( ( struct sockaddr_qstorage * ) & address , & a ) ;
s = NET_AdrToString ( a ) ;
Q_strncpyz ( VM_POINTER ( arg [ 1 ] ) , s , addrlen ) ;
}
handle = Plug_NewStreamHandle ( STREAM_SOCKET ) ;
pluginstreamarray [ handle ] . socket = sock ;
return handle ;
}
//EBUILTIN(int, NET_TCPConnect, (char *ip, int port));
2005-08-12 00:22:38 +00:00
int VARGS Plug_Net_TCPConnect ( void * offset , unsigned int mask , const long * arg )
2005-03-01 15:36:23 +00:00
{
char * localip = VM_POINTER ( arg [ 0 ] ) ;
unsigned short localport = VM_LONG ( arg [ 1 ] ) ;
int handle ;
struct sockaddr_qstorage to , from ;
int sock ;
int _true = 1 ;
netadr_t a ;
2005-06-18 23:54:34 +00:00
if ( ! NET_StringToAdr ( localip , & a ) )
return - 1 ;
2005-03-01 15:36:23 +00:00
NetadrToSockadr ( & a , & to ) ;
if ( ( ( struct sockaddr_in * ) & to ) - > sin_family = = AF_INET & & ! ( ( struct sockaddr_in * ) & to ) - > sin_port )
( ( struct sockaddr_in * ) & to ) - > sin_port = htons ( localport ) ;
# ifdef IPPROTO_IPV6
2005-03-20 03:23:46 +00:00
else if ( ( ( struct sockaddr_in6 * ) & to ) - > sin6_family = = AF_INET6 & & ! ( ( struct sockaddr_in6 * ) & to ) - > sin6_port )
2005-03-01 15:36:23 +00:00
( ( struct sockaddr_in6 * ) & to ) - > sin6_port = htons ( localport ) ;
# endif
if ( ( sock = socket ( PF_INET , SOCK_STREAM , IPPROTO_TCP ) ) = = - 1 )
{
return - 2 ;
}
memset ( & from , 0 , sizeof ( from ) ) ;
( ( struct sockaddr * ) & from ) - > sa_family = ( ( struct sockaddr * ) & to ) - > sa_family ;
if ( bind ( sock , ( struct sockaddr * ) & from , sizeof ( from ) ) = = - 1 )
{
return - 2 ;
}
//not yet blocking. So no frequent attempts please...
//non blocking prevents connect from returning worthwhile sensible value.
if ( connect ( sock , ( struct sockaddr * ) & to , sizeof ( to ) ) = = - 1 )
{
closesocket ( sock ) ;
return - 2 ;
}
if ( ioctlsocket ( sock , FIONBIO , & _true ) = = - 1 ) //now make it non blocking.
{
return - 1 ;
}
handle = Plug_NewStreamHandle ( STREAM_SOCKET ) ;
pluginstreamarray [ handle ] . socket = sock ;
return handle ;
}
2005-11-30 01:20:53 +00:00
int VARGS Plug_FS_Open ( void * offset , unsigned int mask , const long * arg )
{
//modes:
//1: read
//2: write
//char *name, int *handle, int mode
//return value is length of the file.
int handle ;
int * ret ;
char * data ;
if ( VM_OOB ( arg [ 1 ] , sizeof ( int ) ) )
return - 2 ;
ret = VM_POINTER ( arg [ 1 ] ) ;
if ( arg [ 2 ] = = 1 )
{
data = COM_LoadMallocFile ( VM_POINTER ( arg [ 0 ] ) ) ;
if ( ! data )
return - 1 ;
handle = Plug_NewStreamHandle ( STREAM_FILE ) ;
pluginstreamarray [ handle ] . file . buffer = data ;
pluginstreamarray [ handle ] . file . curpos = 0 ;
pluginstreamarray [ handle ] . file . curlen = com_filesize ;
pluginstreamarray [ handle ] . file . buflen = com_filesize ;
* ret = handle ;
return com_filesize ;
}
else if ( arg [ 2 ] = = 2 )
{
data = BZ_Malloc ( 8192 ) ;
if ( ! data )
return - 1 ;
handle = Plug_NewStreamHandle ( STREAM_FILE ) ;
Q_strncpyz ( pluginstreamarray [ handle ] . file . filename , VM_POINTER ( arg [ 0 ] ) , MAX_QPATH ) ;
pluginstreamarray [ handle ] . file . buffer = data ;
pluginstreamarray [ handle ] . file . curpos = 0 ;
pluginstreamarray [ handle ] . file . curlen = 0 ;
pluginstreamarray [ handle ] . file . buflen = 8192 ;
* ret = handle ;
return com_filesize ;
}
else
return - 2 ;
}
2005-12-01 01:21:08 +00:00
int VARGS Plug_memset ( void * offset , unsigned int mask , const long * arg )
{
if ( VM_OOB ( arg [ 0 ] , arg [ 2 ] ) )
return false ;
memset ( VM_POINTER ( arg [ 0 ] ) , VM_LONG ( arg [ 1 ] ) , VM_LONG ( arg [ 2 ] ) ) ;
return arg [ 0 ] ;
}
int VARGS Plug_memcpy ( void * offset , unsigned int mask , const long * arg )
{
if ( VM_OOB ( arg [ 0 ] , arg [ 2 ] ) )
return false ;
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
return false ;
memcpy ( VM_POINTER ( arg [ 0 ] ) , VM_POINTER ( arg [ 1 ] ) , VM_LONG ( arg [ 2 ] ) ) ;
return arg [ 0 ] ;
}
int VARGS Plug_memmove ( void * offset , unsigned int mask , const long * arg )
{
if ( VM_OOB ( arg [ 0 ] , arg [ 2 ] ) )
return false ;
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
return false ;
memmove ( VM_POINTER ( arg [ 0 ] ) , VM_POINTER ( arg [ 1 ] ) , VM_LONG ( arg [ 2 ] ) ) ;
return arg [ 0 ] ;
}
2005-11-30 01:20:53 +00:00
2005-08-12 00:22:38 +00:00
int VARGS Plug_Net_Recv ( void * offset , unsigned int mask , const long * arg )
2005-03-01 15:36:23 +00:00
{
int read ;
int handle = VM_LONG ( arg [ 0 ] ) ;
void * dest = VM_POINTER ( arg [ 1 ] ) ;
int destlen = VM_LONG ( arg [ 2 ] ) ;
if ( VM_OOB ( arg [ 1 ] , arg [ 2 ] ) )
return - 2 ;
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug )
return - 2 ;
switch ( pluginstreamarray [ handle ] . type )
{
case STREAM_SOCKET :
read = recv ( pluginstreamarray [ handle ] . socket , dest , destlen , 0 ) ;
if ( read < 0 )
{
if ( qerrno = = EWOULDBLOCK )
return - 1 ;
else
return - 2 ;
}
else if ( read = = 0 )
return - 2 ; //closed by remote connection.
return read ;
2005-11-30 01:20:53 +00:00
case STREAM_FILE :
if ( pluginstreamarray [ handle ] . file . curlen - pluginstreamarray [ handle ] . file . curpos < destlen )
{
destlen = pluginstreamarray [ handle ] . file . curlen - pluginstreamarray [ handle ] . file . curpos ;
if ( destlen < 0 )
return - 2 ;
}
memcpy ( dest , pluginstreamarray [ handle ] . file . buffer + pluginstreamarray [ handle ] . file . curpos , destlen ) ;
pluginstreamarray [ handle ] . file . curpos + = destlen ;
return destlen ;
2005-03-01 15:36:23 +00:00
default :
return - 2 ;
}
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Net_Send ( void * offset , unsigned int mask , const long * arg )
2005-03-01 15:36:23 +00:00
{
int written ;
int handle = VM_LONG ( arg [ 0 ] ) ;
void * src = VM_POINTER ( arg [ 1 ] ) ;
int srclen = VM_LONG ( arg [ 2 ] ) ;
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug )
return - 2 ;
switch ( pluginstreamarray [ handle ] . type )
{
case STREAM_SOCKET :
written = send ( pluginstreamarray [ handle ] . socket , src , srclen , 0 ) ;
if ( written < 0 )
{
if ( qerrno = = EWOULDBLOCK )
return - 1 ;
else
return - 2 ;
}
else if ( written = = 0 )
return - 2 ; //closed by remote connection.
return written ;
2005-11-30 01:20:53 +00:00
case STREAM_FILE :
if ( pluginstreamarray [ handle ] . file . buflen < pluginstreamarray [ handle ] . file . curpos + srclen )
{
pluginstreamarray [ handle ] . file . buflen = pluginstreamarray [ handle ] . file . curpos + srclen + 8192 ;
pluginstreamarray [ handle ] . file . buffer =
BZ_Realloc ( pluginstreamarray [ handle ] . file . buffer , pluginstreamarray [ handle ] . file . buflen ) ;
}
memcpy ( pluginstreamarray [ handle ] . file . buffer + pluginstreamarray [ handle ] . file . curpos , src , srclen ) ;
pluginstreamarray [ handle ] . file . curpos + = srclen ;
if ( pluginstreamarray [ handle ] . file . curpos > pluginstreamarray [ handle ] . file . curlen )
pluginstreamarray [ handle ] . file . curlen = pluginstreamarray [ handle ] . file . curpos ;
return - 2 ;
2005-03-01 15:36:23 +00:00
default :
return - 2 ;
}
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Net_SendTo ( void * offset , unsigned int mask , const long * arg )
2005-08-03 23:14:59 +00:00
{
int written ;
int handle = VM_LONG ( arg [ 0 ] ) ;
void * src = VM_POINTER ( arg [ 1 ] ) ;
int srclen = VM_LONG ( arg [ 2 ] ) ;
netadr_t * address = VM_POINTER ( arg [ 3 ] ) ;
struct sockaddr_qstorage sockaddr ;
if ( handle = = - 1 )
{
NET_SendPacket ( NS_CLIENT , srclen , src , * address ) ;
return srclen ;
}
NetadrToSockadr ( address , & sockaddr ) ;
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug )
return - 2 ;
switch ( pluginstreamarray [ handle ] . type )
{
case STREAM_SOCKET :
written = sendto ( pluginstreamarray [ handle ] . socket , src , srclen , 0 , ( struct sockaddr * ) & sockaddr , sizeof ( sockaddr ) ) ;
if ( written < 0 )
{
if ( qerrno = = EWOULDBLOCK )
return - 1 ;
else
return - 2 ;
}
else if ( written = = 0 )
return - 2 ; //closed by remote connection.
return written ;
default :
return - 2 ;
}
}
2005-08-12 00:22:38 +00:00
int VARGS Plug_Net_Close ( void * offset , unsigned int mask , const long * arg )
2005-03-01 15:36:23 +00:00
{
int handle = VM_LONG ( arg [ 0 ] ) ;
2005-11-30 01:20:53 +00:00
if ( handle < 0 | | handle > = pluginstreamarraylen | | pluginstreamarray [ handle ] . plugin ! = currentplug )
2005-03-01 15:36:23 +00:00
return - 2 ;
2005-11-30 01:20:53 +00:00
switch ( pluginstreamarray [ handle ] . type )
{
case STREAM_SOCKET :
closesocket ( pluginstreamarray [ handle ] . socket ) ;
break ;
case STREAM_FILE :
if ( * pluginstreamarray [ handle ] . file . filename )
COM_WriteFile ( pluginstreamarray [ handle ] . file . filename , pluginstreamarray [ handle ] . file . buffer , pluginstreamarray [ handle ] . file . curlen ) ;
BZ_Free ( pluginstreamarray [ handle ] . file . buffer ) ;
break ;
}
2005-03-01 15:36:23 +00:00
pluginstreamarray [ handle ] . plugin = NULL ;
return 0 ;
}
2005-01-15 17:46:40 +00:00
void Plug_CloseAll_f ( void ) ;
2005-03-01 15:36:23 +00:00
void Plug_List_f ( void ) ;
2005-01-15 20:50:45 +00:00
void Plug_Close_f ( void ) ;
2005-01-15 17:46:40 +00:00
void Plug_Load_f ( void )
{
2005-06-18 23:54:34 +00:00
char * plugin ;
plugin = Cmd_Argv ( 1 ) ;
if ( ! * plugin )
{
Con_Printf ( " Loads a plugin \n " ) ;
Con_Printf ( " plug_load [pluginpath] \n " ) ;
2005-08-03 23:14:59 +00:00
Con_Printf ( " example pluginpath: plugins/blah \n " ) ;
Con_Printf ( " will load blahx86.dll or blah.so \n " ) ;
2005-06-18 23:54:34 +00:00
return ;
}
if ( ! Plug_Load ( plugin ) )
{
if ( ! Plug_Load ( va ( " plugins/%s " , plugin ) ) )
Con_Printf ( " Couldn't load plugin %s \n " , Cmd_Argv ( 1 ) ) ;
}
2005-01-15 17:46:40 +00:00
}
2005-08-26 22:56:51 +00:00
/*
static long Test_SysCalls_Ex ( void * offset , unsigned int mask , int fn , const long * arg )
{
switch ( fn )
{
case 1 :
Con_Printf ( " %s " , VM_POINTER ( arg [ 0 ] ) ) ;
break ;
default :
Con_Printf ( " Can't handle %i \n " , fn ) ;
}
return 0 ;
}
static int EXPORT_FN Test_SysCalls ( int arg , . . . )
{
return 0 ;
}
void VM_Test_f ( void )
{
vm_t * vm ;
vm = VM_Create ( NULL , " vm/test " , Test_SysCalls , Test_SysCalls_Ex ) ;
if ( vm )
{
VM_Call ( vm , 0 , " " ) ;
VM_Destroy ( vm ) ;
}
} */
2005-01-15 17:46:40 +00:00
2004-09-24 02:45:00 +00:00
void Plug_Init ( void )
{
2005-08-26 22:56:51 +00:00
// Cmd_AddCommand("testvm", VM_Test_f);
2005-01-15 17:46:40 +00:00
Cvar_Register ( & plug_sbar , " plugins " ) ;
Cvar_Register ( & plug_loaddefault , " plugins " ) ;
Cmd_AddCommand ( " plug_closeall " , Plug_CloseAll_f ) ;
2005-01-15 20:50:45 +00:00
Cmd_AddCommand ( " plug_close " , Plug_Close_f ) ;
2005-01-15 17:46:40 +00:00
Cmd_AddCommand ( " plug_load " , Plug_Load_f ) ;
2005-03-01 15:36:23 +00:00
Cmd_AddCommand ( " plug_list " , Plug_List_f ) ;
2005-01-15 17:46:40 +00:00
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Plug_GetEngineFunction " , Plug_FindBuiltin , 0 ) ; //plugin wishes to find a builtin number.
Plug_RegisterBuiltin ( " Plug_ExportToEngine " , Plug_ExportToEngine , 0 ) ; //plugin has a call back that we might be interested in.
2005-11-30 01:20:53 +00:00
Plug_RegisterBuiltin ( " Plug_ExportNative " , Plug_ExportNative , PLUG_BIF_DLLONLY ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Con_Print " , Plug_Con_Print , 0 ) ; //printf is not possible - qvm floats are never doubles, vararg floats in a cdecl call are always converted to doubles.
Plug_RegisterBuiltin ( " Sys_Error " , Plug_Sys_Error , 0 ) ;
2005-03-01 15:36:23 +00:00
Plug_RegisterBuiltin ( " Sys_Milliseconds " , Plug_Sys_Milliseconds , 0 ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Com_Error " , Plug_Sys_Error , 0 ) ; //make zquake programmers happy.
2005-01-15 17:46:40 +00:00
Plug_RegisterBuiltin ( " Cmd_AddCommand " , Plug_Cmd_AddCommand , 0 ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Cmd_Args " , Plug_Cmd_Args , 0 ) ;
Plug_RegisterBuiltin ( " Cmd_Argc " , Plug_Cmd_Argc , 0 ) ;
Plug_RegisterBuiltin ( " Cmd_Argv " , Plug_Cmd_Argv , 0 ) ;
Plug_RegisterBuiltin ( " Cmd_AddText " , Plug_Cmd_AddText , 0 ) ;
2004-09-24 02:45:00 +00:00
2004-10-13 07:24:59 +00:00
Plug_RegisterBuiltin ( " CL_GetStats " , Plug_CL_GetStats , 0 ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Menu_Control " , Plug_Menu_Control , 0 ) ;
2004-10-13 07:24:59 +00:00
Plug_RegisterBuiltin ( " Key_GetKeyCode " , Plug_Key_GetKeyCode , 0 ) ;
2004-09-24 02:45:00 +00:00
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Cvar_Register " , Plug_Cvar_Register , 0 ) ;
2005-08-01 12:35:16 +00:00
Plug_RegisterBuiltin ( " Cvar_Update " , Plug_Cvar_Update , 0 ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Cvar_SetString " , Plug_Cvar_SetString , 0 ) ;
Plug_RegisterBuiltin ( " Cvar_SetFloat " , Plug_Cvar_SetFloat , 0 ) ;
Plug_RegisterBuiltin ( " Cvar_GetString " , Plug_Cvar_GetString , 0 ) ;
Plug_RegisterBuiltin ( " Cvar_GetFloat " , Plug_Cvar_GetFloat , 0 ) ;
2004-10-13 07:24:59 +00:00
Plug_RegisterBuiltin ( " Draw_LoadImage " , Plug_Draw_LoadImage , 0 ) ;
Plug_RegisterBuiltin ( " Draw_Image " , Plug_Draw_Image , 0 ) ;
2004-10-10 06:32:29 +00:00
Plug_RegisterBuiltin ( " Draw_Character " , Plug_Draw_Character , 0 ) ;
Plug_RegisterBuiltin ( " Draw_Fill " , Plug_Draw_Fill , 0 ) ;
Plug_RegisterBuiltin ( " Draw_Colourp " , Plug_Draw_ColourP , 0 ) ;
Plug_RegisterBuiltin ( " Draw_Colour3f " , Plug_Draw_Colour3f , 0 ) ;
Plug_RegisterBuiltin ( " Draw_Colour4f " , Plug_Draw_Colour4f , 0 ) ;
2005-01-13 16:50:37 +00:00
Plug_RegisterBuiltin ( " Con_SubPrint " , Plug_Con_SubPrint , 0 ) ;
Plug_RegisterBuiltin ( " Con_RenameSub " , Plug_Con_RenameSub , 0 ) ;
2004-10-10 06:32:29 +00:00
2005-03-01 15:36:23 +00:00
Plug_RegisterBuiltin ( " Net_TCPListen " , Plug_Net_TCPListen , 0 ) ;
Plug_RegisterBuiltin ( " Net_Accept " , Plug_Net_Accept , 0 ) ;
Plug_RegisterBuiltin ( " Net_TCPConnect " , Plug_Net_TCPConnect , 0 ) ;
Plug_RegisterBuiltin ( " Net_Recv " , Plug_Net_Recv , 0 ) ;
Plug_RegisterBuiltin ( " Net_Send " , Plug_Net_Send , 0 ) ;
2005-08-03 23:14:59 +00:00
Plug_RegisterBuiltin ( " Net_SendTo " , Plug_Net_SendTo , 0 ) ;
2005-03-01 15:36:23 +00:00
Plug_RegisterBuiltin ( " Net_Close " , Plug_Net_Close , 0 ) ;
2005-11-30 01:20:53 +00:00
Plug_RegisterBuiltin ( " FS_Open " , Plug_FS_Open , 0 ) ;
Plug_RegisterBuiltin ( " FS_Read " , Plug_Net_Recv , 0 ) ;
Plug_RegisterBuiltin ( " FS_Write " , Plug_Net_Send , 0 ) ;
Plug_RegisterBuiltin ( " FS_Close " , Plug_Net_Close , 0 ) ;
2005-12-01 01:21:08 +00:00
Plug_RegisterBuiltin ( " memset " , Plug_memset , 0 ) ;
Plug_RegisterBuiltin ( " memcpy " , Plug_memcpy , 0 ) ;
Plug_RegisterBuiltin ( " memmove " , Plug_memmove , 0 ) ;
2005-03-01 15:36:23 +00:00
Plug_RegisterBuiltin ( " Media_ShowFrameRGBA_32 " , Plug_Media_ShowFrameRGBA_32 , 0 ) ;
2005-08-03 23:14:59 +00:00
if ( plug_loaddefault . value )
{
2004-09-24 02:45:00 +00:00
# ifdef _WIN32
2005-08-03 23:14:59 +00:00
COM_EnumerateFiles ( " plugins/*x86.dll " , Plug_Emumerated , " x86.dll " ) ;
2004-09-24 02:45:00 +00:00
# elif defined(__linux__)
2005-08-03 23:14:59 +00:00
COM_EnumerateFiles ( " plugins/*x86.so " , Plug_Emumerated , " x86.so " ) ;
2004-09-24 02:45:00 +00:00
# endif
2005-08-03 23:14:59 +00:00
COM_EnumerateFiles ( " plugins/*.qvm " , Plug_Emumerated , " .qvm " ) ;
}
2004-09-24 02:45:00 +00:00
}
void Plug_Tick ( void )
{
2005-01-15 17:46:40 +00:00
plugin_t * oldplug = currentplug ;
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
2004-09-24 02:45:00 +00:00
{
2005-01-15 17:46:40 +00:00
if ( currentplug - > tick )
2004-09-24 02:45:00 +00:00
{
2005-01-15 17:46:40 +00:00
VM_Call ( currentplug - > vm , currentplug - > tick , ( int ) ( realtime * 1000 ) ) ;
2004-09-24 02:45:00 +00:00
}
}
2005-01-15 17:46:40 +00:00
currentplug = oldplug ;
2004-09-24 02:45:00 +00:00
}
2004-10-10 06:32:29 +00:00
void Plug_ResChanged ( void )
{
plugin_t * oldplug = currentplug ;
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > reschange )
VM_Call ( currentplug - > vm , currentplug - > reschange , vid . width , vid . height ) ;
}
currentplug = oldplug ;
}
2004-09-24 02:45:00 +00:00
qboolean Plugin_ExecuteString ( void )
{
2005-01-15 17:46:40 +00:00
plugin_t * oldplug = currentplug ;
2004-09-24 02:45:00 +00:00
if ( Cmd_Argc ( ) > 0 )
{
2005-01-15 17:46:40 +00:00
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
2004-09-24 02:45:00 +00:00
{
2005-01-15 17:46:40 +00:00
if ( currentplug - > executestring )
2004-09-24 02:45:00 +00:00
{
2005-01-15 17:46:40 +00:00
if ( VM_Call ( currentplug - > vm , currentplug - > executestring , 0 ) )
2005-01-15 20:50:45 +00:00
{
currentplug = oldplug ;
2004-09-24 02:45:00 +00:00
return true ;
2005-01-15 20:50:45 +00:00
}
2004-09-24 02:45:00 +00:00
}
}
}
2005-01-15 17:46:40 +00:00
currentplug = oldplug ;
2004-09-24 02:45:00 +00:00
return false ;
}
2005-03-10 03:55:18 +00:00
void Plug_SubConsoleCommand ( console_t * con , char * line )
{
char buffer [ 2048 ] ;
plugin_t * oldplug = currentplug ; //shouldn't really be needed, but oh well
currentplug = con - > userdata ;
Q_strncpyz ( buffer , va ( " %s %s " , con - > name , line ) , sizeof ( buffer ) ) ;
Cmd_TokenizeString ( buffer , false , false ) ;
VM_Call ( currentplug - > vm , currentplug - > conexecutecommand , 0 ) ;
currentplug = oldplug ;
}
2004-09-26 00:30:42 +00:00
qboolean Plug_Menu_Event ( int eventtype , int param ) //eventtype = draw/keydown/keyup, param = time/key
{
2005-01-15 20:50:45 +00:00
plugin_t * oc = currentplug ;
qboolean ret ;
2004-10-13 07:24:59 +00:00
extern int mousecursor_x , mousecursor_y ;
2004-09-26 00:30:42 +00:00
if ( ! menuplug )
return false ;
2005-01-15 20:50:45 +00:00
currentplug = menuplug ;
ret = VM_Call ( menuplug - > vm , menuplug - > menufunction , eventtype , param , mousecursor_x , mousecursor_y ) ;
currentplug = oc ;
return ret ;
2004-10-13 07:24:59 +00:00
}
2005-08-03 23:14:59 +00:00
int Plug_ConnectionlessClientPacket ( char * buffer , int size )
{
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > connectionlessclientpacket )
{
switch ( VM_Call ( currentplug - > vm , currentplug - > connectionlessclientpacket , buffer , size , & net_from ) )
{
case 0 :
continue ; //wasn't handled
case 1 :
currentplug = NULL ; //was handled with no apparent result
return true ;
case 2 :
# ifndef SERVERONLY
cls . protocol = CP_PLUGIN ; //woo, the plugin wants to connect to them!
protocolclientplugin = currentplug ;
# endif
currentplug = NULL ;
return true ;
}
}
}
return false ;
}
2004-10-13 07:24:59 +00:00
void Plug_SBar ( void )
{
plugin_t * oc = currentplug ;
int cp ;
vrect_t rect ;
2005-01-15 17:46:40 +00:00
if ( ! plug_sbar . value )
currentplug = NULL ;
else
2004-10-13 07:24:59 +00:00
{
2005-01-15 17:46:40 +00:00
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
2004-10-13 07:24:59 +00:00
{
2005-01-15 17:46:40 +00:00
if ( currentplug - > sbarlevel [ 0 ] )
{
for ( cp = 0 ; cp < cl . splitclients ; cp + + )
{ //if you don't use splitscreen, use a full videosize rect.
SCR_VRectForPlayer ( & rect , cp ) ;
VM_Call ( currentplug - > vm , currentplug - > sbarlevel [ 0 ] , cp , rect . x , rect . y , rect . width , rect . height ) ;
}
break ;
2004-10-13 07:24:59 +00:00
}
}
}
if ( ! currentplug )
{
Sbar_Draw ( ) ;
2005-01-15 17:46:40 +00:00
currentplug = oc ;
2004-10-13 07:24:59 +00:00
return ; //our current sbar draws a scoreboard too. We don't want that bug to be quite so apparent.
//please don't implement this identical hack in your engines...
}
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > sbarlevel [ 1 ] )
{
for ( cp = 0 ; cp < cl . splitclients ; cp + + )
{ //if you don't use splitscreen, use a full videosize rect.
SCR_VRectForPlayer ( & rect , cp ) ;
VM_Call ( currentplug - > vm , currentplug - > sbarlevel [ 1 ] , cp , rect . x , rect . y , rect . width , rect . height ) ;
}
}
}
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > sbarlevel [ 2 ] )
{
for ( cp = 0 ; cp < cl . splitclients ; cp + + )
{ //if you don't use splitscreen, use a full videosize rect.
SCR_VRectForPlayer ( & rect , cp ) ;
VM_Call ( currentplug - > vm , currentplug - > sbarlevel [ 2 ] , cp , rect . x , rect . y , rect . width , rect . height ) ;
}
}
}
currentplug = oc ;
2004-09-26 00:30:42 +00:00
}
2005-11-30 05:01:43 +00:00
int Plug_Message ( int clientnum , int messagelevel , char * buffer )
{
for ( currentplug = plugs ; currentplug ; currentplug = currentplug - > next )
{
if ( currentplug - > messagefunction )
{
VM_Call ( currentplug - > vm , currentplug - > messagefunction , clientnum , messagelevel , buffer ) ;
}
}
return 1 ; // don't silence message
}
2004-09-24 02:45:00 +00:00
void Plug_Close ( plugin_t * plug )
{
if ( plugs = = plug )
plugs = plug - > next ;
else
{
plugin_t * prev ;
for ( prev = plugs ; prev ; prev = prev - > next )
{
if ( prev - > next = = plug )
break ;
}
if ( ! prev )
Sys_Error ( " Plug_Close: not linked \n " ) ;
prev - > next = plug - > next ;
}
2005-01-15 20:50:45 +00:00
Con_Printf ( " Closing plugin %s \n " , plug - > name ) ;
2004-09-24 02:45:00 +00:00
VM_Destroy ( plug - > vm ) ;
2005-01-15 17:46:40 +00:00
Plug_FreePlugImages ( plug ) ;
Plug_FreeConCommands ( plug ) ;
if ( currentplug = = plug )
currentplug = NULL ;
2005-01-15 20:50:45 +00:00
if ( menuplug = = plug )
{
menuplug = NULL ;
key_dest = key_game ;
}
2005-08-03 23:14:59 +00:00
if ( protocolclientplugin = = plug )
{
protocolclientplugin = NULL ;
if ( cls . protocol = = CP_PLUGIN )
cls . protocol = CP_UNKNOWN ;
}
2005-01-15 20:50:45 +00:00
}
void Plug_Close_f ( void )
{
plugin_t * plug ;
char * name = Cmd_Argv ( 1 ) ;
if ( Cmd_Argc ( ) < 2 )
{
Con_Printf ( " Close which plugin? \n " ) ;
return ;
}
for ( plug = plugs ; plug ; plug = plug - > next )
{
2005-01-24 23:47:32 +00:00
if ( ! strcmp ( plug - > name , name ) )
2005-01-15 20:50:45 +00:00
{
Plug_Close ( plug ) ;
return ;
}
}
2005-06-18 23:54:34 +00:00
name = va ( " plugins/%s " , name ) ;
for ( plug = plugs ; plug ; plug = plug - > next )
{
if ( ! strcmp ( plug - > name , name ) )
{
Plug_Close ( plug ) ;
return ;
}
}
Con_Printf ( " Plugin %s does not appear to be loaded \n " , Cmd_Argv ( 1 ) ) ;
2004-09-24 02:45:00 +00:00
}
2005-01-15 17:46:40 +00:00
void Plug_CloseAll_f ( void )
2004-09-24 02:45:00 +00:00
{
2005-01-15 17:46:40 +00:00
if ( currentplug )
Sys_Error ( " Plug_CloseAll_f called inside a plugin! \n " ) ;
while ( plugs )
{
Plug_Close ( plugs ) ;
}
}
2004-09-24 02:45:00 +00:00
2005-03-01 15:36:23 +00:00
void Plug_List_f ( void )
{
plugin_t * plug ;
for ( plug = plugs ; plug ; plug = plug - > next )
{
2005-11-30 05:01:43 +00:00
Con_Printf ( " %s - \n " , plug - > name ) ;
VM_PrintInfo ( plug - > vm ) ;
2005-03-01 15:36:23 +00:00
}
}
2005-01-15 17:46:40 +00:00
void Plug_Shutdown ( void )
{
while ( plugs )
{
Plug_Close ( plugs ) ;
}
2004-09-30 22:51:15 +00:00
}
# endif