-
Notifications
You must be signed in to change notification settings - Fork 32
API Overview
JK2MV implements several new Sys- and VMCalls which can be used to implement more advanced functionality into your mod.
Terms used in the following:
Term | Meaning |
---|---|
Engine | JK2MV itself or what loads your mod. (jk2mvmp.exe, jk2mp.exe, jk2ded.exe) |
Module | Your mod. cgame/jk2mpgame/ui (.qvm) |
Legacy JK2 / Clients | Old / Standard JK2 Versions from CD / Stream etc. Practically everything but JK2MV. |
VMCall | A function call that goes into your mods vmMain (g_main.c) function. |
SysCall | A function call that goes into the engine. |
The functions are organized into API-Levels so that binary compatibility can be provided for future JK2MV versions. You should target the lowest possible API-Level which suits your needs. If used carefully, your mod can still be fully compatible with legacy JK2 versions.
Grab the mvapi.h for the API-Level you are going to target. You can get it from the JK2MV source code. Make sure to use a version which is not in development.
MV_APILEVEL
defines the API-Level you are working with. MV_MIN_VERSION
is the minimum required JK2MV version which implements this API-Level. All future ( >= MV_MIN_VERSION
) JK2MV versions are guaranteed to also implement this API-Level.
You need to initialize the API before you can use any of the Sys- and VMCalls which are defined by your selected API-Level. Example:
int MVAPI_Init(int apilevel);
void MVAPI_AfterInit(void);
qboolean mvapi;
int vmMain( int command, int arg0, int arg1, int arg2, int arg3, int arg4, int arg5, int arg6, int arg7, int arg8, int arg9, int arg10, int arg11 ) {
switch ( command ) {
case GAME_INIT:
G_InitGame( arg0, arg1, arg2 );
return MVAPI_Init(arg11);
case MVAPI_AFTER_INIT:
MVAPI_AfterInit();
return 0;
case GAME_SHUTDOWN:
G_ShutdownGame( arg0 );
return 0;
case GAME_CLIENT_CONNECT:
return (int)ClientConnect( arg0, arg1, arg2 );
case GAME_CLIENT_THINK:
ClientThink( arg0 );
return 0;
...
}
return -1;
}
int MVAPI_Init(int apilevel) {
if (!trap_Cvar_VariableIntegerValue("mv_apienabled")) {
G_Printf("MVAPI is not supported at all or has been disabled.\n");
G_Printf("You need at least JK2MV " MV_MIN_VERSION ".\n");
return 0;
}
if (apilevel < MV_APILEVEL) {
G_Printf("MVAPI level %i not supported.\n", MV_APILEVEL);
G_Printf("You need at least JK2MV " MV_MIN_VERSION ".\n");
return 0;
}
mvapi = qtrue;
G_Printf("Using MVAPI level %i (%i supported).\n", MV_APILEVEL, apilevel);
return MV_APILEVEL;
}
void MVAPI_AfterInit(void) {
// do something smart
}
As you can see, the highest supported API-Level is stored in arg11 on a GAME_INIT
call. Your return value to this call should be MV_APILEVEL
. The value of arg11 is undefined in legacy JK2 versions, this is why the
if (!trap_Cvar_VariableIntegerValue("mv_apienabled"))
part is needed.
You can't use any MV-API SysCalls during GAME_INIT
because the engine unlocks them just after receiving the return value.
For this purpose you can use the MVAPI_AFTER_INIT
VMCall which is called just after GAME_INIT
has returned.
There is one exception: The MVAPI_GET_VERSION
SysCall, which can be called everywhere and at any time. This exception exists because multi-version QVM's need it very early to determine the currently running JK2 version. Thus, MVAPI_GET_VERSION
is not part of any API-Level.
JK2MV
Client
Server
Modding
Development