Skip to content

Commit

Permalink
cmod: Misc Lua interface updates and tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
Chomenor committed Jan 20, 2024
1 parent 8366db1 commit bc8d074
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 41 deletions.
1 change: 1 addition & 0 deletions code/eliteforce/server/stef_sv_general.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ qboolean Record_ProcessPacketEvent( const netadr_t *address, msg_t *msg, int qpo
#define SV_LUA_EVENT_CLIENT_COMMAND "sv_client_cmd"
#define SV_LUA_EVENT_PACKET_COMMAND "sv_packet_cmd"

extern qboolean sv_lua_running_client_command;
qboolean SV_Lua_SimpleClientEventCall( const char *name, int clientNum );
qboolean SV_Lua_GamestateConfigstrings( int clientNum, msg_t *msg );
void SV_Lua_OpenDownload( int clientNum );
Expand Down
56 changes: 45 additions & 11 deletions code/eliteforce/server/stef_sv_lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

extern lua_State *stef_lua_state;

qboolean sv_lua_running_client_command;

#define SERVER_RUNNING ( sv.state != SS_DEAD )
#define CLIENTNUM_VALID( clientNum ) ( SERVER_RUNNING && clientNum >= 0 && clientNum < sv_maxclients->integer )
#define CLIENT_CONNECTED( clientNum ) ( CLIENTNUM_VALID( clientNum ) && svs.clients[clientNum].state >= CS_CONNECTED )

void SV_SendClientGameState( client_t *client );

Expand Down Expand Up @@ -259,14 +262,13 @@ static int SV_Lua_SendServerCmd( lua_State *L ) {
const char *msg = lua_tostring( L, 2 );
client_t *cl = NULL;
if ( !msg ) {
Com_Printf( "lua sv.send_servercmd: invalid message\n" );
Logging_Printf( LP_CONSOLE, "WARNINGS", "lua sv.send_servercmd: invalid message\n" );
return 0;
}
if ( !lua_isnil( L, 1 ) ) {
int clientNum = lua_tointegerx( L, 1, &clientValid );
if ( !clientValid || clientNum < 0 || clientNum >= sv_maxclients->integer ||
svs.clients[clientNum].state < CS_CONNECTED ) {
Com_Printf( "lua sv.send_servercmd: invalid client\n" );
if ( !clientValid || !CLIENT_CONNECTED( clientNum ) ) {
Logging_Printf( LP_CONSOLE, "WARNINGS", "lua sv.send_servercmd: invalid client\n" );
return 0;
}
cl = &svs.clients[clientNum];
Expand All @@ -283,15 +285,44 @@ SV_Lua_SendGamestate
static int SV_Lua_SendGamestate( lua_State *L ) {
int clientValid = 0;
int clientNum = lua_tointegerx( L, 1, &clientValid );
if ( !clientValid || clientNum < 0 || clientNum >= sv_maxclients->integer ||
svs.clients[clientNum].state < CS_CONNECTED ) {
Com_Printf( "lua send_gamestate: invalid client\n" );
if ( !clientValid || !CLIENT_CONNECTED( clientNum ) ) {
Logging_Printf( LP_CONSOLE, "WARNINGS", "lua send_gamestate: invalid client\n" );
return 0;
}
SV_SendClientGameState( &svs.clients[clientNum] );
return 0;
}

/*
=================
SV_Lua_ExecClientCmd
Run a command as if it was issued by a client. Bypasses flood protection.
Will result in a SV_LUA_EVENT_CLIENT_COMMAND call back to Lua. Lua script is
responsible for avoiding a loop if calling back from this event.
=================
*/
static int SV_Lua_ExecClientCmd( lua_State *L ) {
const char *cmd = lua_tostring( L, 2 );
if ( !cmd ) {
Logging_Printf( LP_CONSOLE, "WARNINGS", "lua sv.exec_client_cmd: invalid cmd\n" );
} else {
int clientValid = 0;
int clientNum = lua_tointegerx( L, 1, &clientValid );
if ( !clientValid || !CLIENT_CONNECTED( clientNum ) ) {
Logging_Printf( LP_CONSOLE, "WARNINGS", "lua sv.exec_client_cmd: invalid client\n" );
} else if ( sv_lua_running_client_command ) {
// shouldn't happen
Logging_Printf( LP_CONSOLE, "WARNINGS", "lua sv.exec_client_cmd: already running\n" );
} else {
sv_lua_running_client_command = qtrue;
SV_ExecuteClientCommand( &svs.clients[clientNum], cmd );
sv_lua_running_client_command = qfalse;
}
}
return 0;
}

/*
=================
SV_Lua_SetupInterace
Expand All @@ -314,6 +345,7 @@ static void SV_Lua_SetupInterface( lua_State *L ) {
ADD_FUNCTION( "is_client_cs_ready", SV_Lua_IsClientCSReady );
ADD_FUNCTION( "send_servercmd", SV_Lua_SendServerCmd );
ADD_FUNCTION( "send_gamestate", SV_Lua_SendGamestate );
ADD_FUNCTION( "exec_client_cmd", SV_Lua_ExecClientCmd );

#define ADD_STRING_CONSTANT( name, value ) \
lua_pushstring( L, value ); \
Expand Down Expand Up @@ -392,7 +424,7 @@ qboolean SV_Lua_GamestateConfigstrings( int clientNum, msg_t *msg ) {
}
lua_pop( stef_lua_state, 1 );
}
Com_Printf( "gamestate cs override for client %i\n", clientNum );
Logging_Printf( LP_INFO, "SV_LUA_GAMESTATE", "gamestate cs override for client %i\n", clientNum );
override = qtrue;
}
lua_pop( stef_lua_state, 1 );
Expand Down Expand Up @@ -440,7 +472,8 @@ void SV_Lua_OpenDownload( int clientNum ) {
}
if ( cl->download == FS_INVALID_HANDLE ) {
// Abort download
Com_Printf( "WARNING: Lua script specified download path '%s', but the file could not be opened.\n", path );
Logging_Printf( LP_CONSOLE, "WARNINGS", "WARNING: Lua script specified download path '%s',"
" but the file could not be opened.\n", path );
SV_Lua_OpenDownloadError( &svs.clients[clientNum], "Server failed to open file for downloading." );
*cl->downloadName = '\0';
}
Expand All @@ -451,7 +484,8 @@ void SV_Lua_OpenDownload( int clientNum ) {
if ( lua_getfield( stef_lua_state, -2, "message" ) == LUA_TSTRING ) {
message = lua_tostring( stef_lua_state, -1 );
} else {
Com_Printf( "WARNING: Lua script specified error command, but no error message.\n" );
Logging_Printf( LP_CONSOLE, "WARNINGS", "WARNING: Lua script specified error command,"
" but no error message.\n" );
}
SV_Lua_OpenDownloadError( &svs.clients[clientNum], message );
*cl->downloadName = '\0';
Expand All @@ -462,7 +496,7 @@ void SV_Lua_OpenDownload( int clientNum ) {
*cl->downloadName = '\0';

} else if ( *cmd ) {
Com_Printf( "WARNING: Unrecognized Lua download command '%s'.\n", cmd );
Logging_Printf( LP_CONSOLE, "WARNINGS", "WARNING: Unrecognized Lua download command '%s'.\n", cmd );
}
}
lua_pop( stef_lua_state, 1 );
Expand Down
67 changes: 56 additions & 11 deletions code/eliteforce/stef_lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,24 @@ Stef_Lua_RunFile
*/
static int Stef_Lua_RunFile( lua_State *L ) {
const char *path = lua_tostring( L, 1 );
char *data = NULL;
int length = FS_ReadFile( path, (void **)&data );
if ( length > 0 ) {
if ( luaL_loadstring( L, data ) ) {
Com_Printf( "lua sys.runfile: error '%s'\n", lua_tostring( stef_lua_state, -1 ) );
lua_pop( L, 1 );
lua_pushnil( L );
if ( !path ) {
lua_pushstring( L, "com.run_file invalid path parameter" );
lua_error( L );
} else {
char *data = NULL;
int length = FS_ReadFile( path, (void **)&data );
if ( length > 0 ) {
if ( luaL_loadstring( L, data ) ) {
lua_error( L );
} else {
lua_call( L, 0, 1 );
}
} else {
lua_call( L, 0, 1 );
char buffer[256];
Com_sprintf( buffer, sizeof( buffer ), "com.run_file failed to read '%s'", path );
lua_pushstring( L, buffer );
lua_error( L );
}
} else {
Com_Printf( "lua sys.runfile: failed to read '%s'\n", path );
lua_pushnil( L );
}
return 1;
}
Expand Down Expand Up @@ -276,6 +281,44 @@ static int Stef_Lua_CloseHandle( lua_State *L ) {
return 0;
}

/*
=================
Stef_Lua_ListFiles
=================
*/
static int Stef_Lua_ListFiles( lua_State *L ) {
const char *path = lua_tostring( L, 1 );
if ( !path ) {
lua_pushstring( L, "com.list_files invalid path parameter" );
lua_error( L );
} else {
int i;
int numFiles = 0;
const char **files = FS_ListFiles( path, lua_tostring( L, 2 ), &numFiles );
lua_createtable( L, numFiles, 0 );
for ( i = 0; i < numFiles; ++i ) {
lua_pushstring( L, files[i] );
lua_rawseti( L, -2, i + 1 );
}
FS_FreeFileList( files );
}
return 1;
}

/*
=================
Stef_Lua_FsAutoRefresh
=================
*/
static int Stef_Lua_FsAutoRefresh( lua_State *L ) {
#ifdef NEW_FILESYSTEM
FS_AutoRefresh();
#else
Com_Printf( "Lua com.fs_auto_refresh failed due to build wthout NEW_FILESYSTEM.\n" );
#endif
return 0;
}

/*
=================
Stef_Lua_RunCmd
Expand Down Expand Up @@ -463,6 +506,8 @@ static void Stef_Lua_SetupInterface( lua_State *L ) {
ADD_FUNCTION( "handle_write", Stef_Lua_WriteHandle );
ADD_FUNCTION( "handle_flush", Stef_Lua_FlushHandle );
ADD_FUNCTION( "handle_close", Stef_Lua_CloseHandle );
ADD_FUNCTION( "list_files", Stef_Lua_ListFiles );
ADD_FUNCTION( "fs_auto_refresh", Stef_Lua_FsAutoRefresh );
ADD_FUNCTION( "cmd_exec", Stef_Lua_RunCmd );
ADD_FUNCTION( "cvar_get_string", Stef_Lua_CvarGetString );
ADD_FUNCTION( "cvar_get_integer", Stef_Lua_CvarGetInteger );
Expand Down
20 changes: 12 additions & 8 deletions code/qcommon/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,16 +286,12 @@ void FORMAT_PRINTF(1, 2) QDECL Com_DPrintf( const char *fmt, ... ) {
va_list argptr;
char msg[MAXPRINTMSG];

if ( !com_developer || !com_developer->integer ) {
return; // don't confuse non-developers with techie stuff...
}

va_start( argptr,fmt );
Q_vsnprintf( msg, sizeof( msg ), fmt, argptr );
va_end( argptr );

#ifdef STEF_LUA_EVENTS
if ( !stef_lua_suppress_print_event && Stef_Lua_InitEventCall( STEF_LUA_EVENT_LOG_PRINT ) ) {
va_start( argptr, fmt );
Q_vsnprintf( msg, sizeof( msg ), fmt, argptr );
va_end( argptr );

// generate lua event with printlevel 1 (developer)
Stef_Lua_PushString( "text", msg );
Stef_Lua_PushInteger( "printlevel", 1 );
Expand All @@ -313,6 +309,14 @@ void FORMAT_PRINTF(1, 2) QDECL Com_DPrintf( const char *fmt, ... ) {
}
#endif

if ( !com_developer || !com_developer->integer ) {
return; // don't confuse non-developers with techie stuff...
}

va_start( argptr,fmt );
Q_vsnprintf( msg, sizeof( msg ), fmt, argptr );
va_end( argptr );

Com_Printf( S_COLOR_CYAN "%s", msg );
}

Expand Down
27 changes: 16 additions & 11 deletions code/server/sv_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,7 @@ static void SV_SendClientGameState( client_t *client ) {
// so at least try to inform him in console and release connection slot
if ( msg.overflowed ) {
#ifdef STEF_LOGGING_DEFS
Logging_Printf( LP_INFO, "SERVER_WARNINGS SERVERSTATE", "Gamestate overflow for client %i", (int)( client - svs.clients ) );
Logging_Printf( LP_INFO, "WARNINGS SERVERSTATE", "Gamestate overflow for client %i", (int)( client - svs.clients ) );
#endif
if ( client->netchan.remoteAddress.type == NA_LOOPBACK ) {
Com_Error( ERR_DROP, "gamestate overflow" );
Expand Down Expand Up @@ -2189,12 +2189,6 @@ qboolean SV_ExecuteClientCommand( client_t *cl, const char *s ) {

Cmd_TokenizeString( s );

#ifdef STEF_LUA_SERVER
if ( SV_Lua_SimpleClientEventCall( SV_LUA_EVENT_CLIENT_COMMAND, cl - svs.clients ) ) {
return qtrue;
}
#endif

// malicious users may try using too many string commands
// to lag other players. If we decide that we want to stall
// the command, we will stop processing the rest of the packet,
Expand All @@ -2205,6 +2199,17 @@ qboolean SV_ExecuteClientCommand( client_t *cl, const char *s ) {
// normal to spam a lot of commands when downloading
bFloodProtect = cl->netchan.remoteAddress.type != NA_BOT && cl->state >= CS_ACTIVE;

#ifdef STEF_LUA_SERVER
if ( sv_lua_running_client_command ) {
// command issued from lua
bFloodProtect = qfalse;
}
if ( SV_Lua_SimpleClientEventCall( SV_LUA_EVENT_CLIENT_COMMAND, cl - svs.clients ) ) {
// command handled by lua
return qtrue;
}
#endif

// see if it is a server level command
for ( ucmd = ucmds; ucmd->name; ucmd++ ) {
if ( !strcmp( Cmd_Argv(0), ucmd->name ) ) {
Expand Down Expand Up @@ -2526,11 +2531,11 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg ) {
if ( cl->gentity )
Com_DPrintf( "%s: dropped gamestate, resending\n", cl->name );
#ifdef STEF_LOGGING_DEFS
Logging_Printf(LP_INFO, "SERVERSTATE",
"NLOG Sending gamestate for client %i due to primary trigger: state(%i) msg_serverId(%i) sv_serverId(%i) "
Logging_Printf( LP_INFO, "SERVERSTATE",
"Sending gamestate for client %i due to primary trigger: state(%i) msg_serverId(%i) sv_serverId(%i) "
"restarted_serverId(%i) messageAcknowledge(%i) gamestateMessageNum(%i)\n",
(int)(cl-svs.clients), cl->state, serverId, sv.serverId, sv.restartedServerId, cl->messageAcknowledge,
cl->gamestateMessageNum);
(int)( cl - svs.clients ), cl->state, serverId, sv.serverId, sv.restartedServerId, cl->messageAcknowledge,
cl->gamestateMessageNum );
#endif
SV_SendClientGameState( cl );
}
Expand Down

0 comments on commit bc8d074

Please sign in to comment.