I’m trying to force idle players (g_inactivity matches) to team spectator.
However, I’m getting an error when compiling:
LD build/release-linux-x86_64/ioq3ded.x86_64
build/release-linux-x86_64/ded/sv_game.o: In function SV_GameSystemCalls': sv_game.c:(.text+0x2474): undefined reference to
SV_forcespec’
build/release-linux-x86_64/ded/sv_game.o: In function SV_GameDropClient': sv_game.c:(.text+0x268b): undefined reference to
SV_forcespec’
collect2: error: ld returned 1 exit status
/code/game/g_svcmds.c:
void SV_forcespec( int client ) {
Com_Printf(“Forcing player to spectate\n”);
trap_SendConsoleCommand( EXEC_NOW, va( “forceteam %d spectator\n”, client ) );
}
/code/game/g_public.h:
extern void SV_forcespec( int client );
/code/server/sv_game.c:
void SV_GameDropClient( int clientNum, const char *reason ) {
if ( clientNum < 0 || clientNum >= sv_maxclients->integer ) {
return;
}
// clientNum confirmed to return correct clientid
char *inactivity, *team = “”;
sprintf( team, “%d spectator”, clientNum );
inactivity = “Dropped due to inactivity”;
if( strcmp(inactivity,reason) == 0 ) {
// force player to team spectator and notify them
SV_forcespec( clientNum );
SV_SendServerCommand( svs.clients + clientNum, “cp "^1You’ve been moved to the spectators\n^1for idling too long!\n"” );
} else {
SV_DropClient( svs.clients + clientNum, reason );
}
}
I can’t figure out what I’m doing wrong. I’m certain it’s some simple, amateur mistake. Thanks!
You’re trying to call a function that is in the Game VM from inside the engine. You cannot do without using VM_Call function and GAME_* gameExport_t, which requires using custom game VM. However, from your example you do not need to have the function in the Game VM at all.
I’d recommend removing SV_forcespec from g_public.h and g_svcmds.c, instead put the code in SV_GameDropClient directly;
void SV_GameDropClient( int clientNum, const char *reason ) {
char *inactivity, team[32]; // NOTE: team must be an array, not a pointer.
if ( clientNum < 0 || clientNum >= sv_maxclients->integer ) {
return;
}
// clientNum confirmed to return correct clientid
Com_sprintf( team, sizeof (team), "%d spectator", clientNum ); // NOTE: sprint is not safe, might go past end of array. Use Com_sprint instead.
inactivity = "Dropped due to inactivity";
if( strcmp(inactivity,reason) == 0 ) {
// force player to team spectator and notify them
//START SV_forcespec
Com_Printf("Forcing player to spectate\n");
Cbuf_ExecuteText( EXEC_NOW, va( "forceteam %d spectator\n", clientNum ) );
//END
SV_SendServerCommand( svs.clients + clientNum, "cp
\"^1You've been moved to the spectators\n^1for idling too long!\n\"" );
} else {
SV_DropClient( svs.clients + clientNum, reason );
}
}
2 Likes
Zturtleman, you’re a life-saver. Thank you for taking the time to explain your answer, too. I wasn’t aware of the Cbuf_ExecuteText() function.
Everything works great now. Thanks again.
You’re welcome. I’m glad it worked for you.