engine: common: make single shared print buffer with stripped colorcodes

- in xrcon, make delay and timeout macros into cvars
This commit is contained in:
Alibek Omarov
2026-05-30 06:37:48 +05:00
parent b36f107a2e
commit e9f5bca5c4
4 changed files with 82 additions and 89 deletions

View File

@@ -946,6 +946,7 @@ void XRcon_Init( void );
void XRcon_Shutdown( void );
void XRcon_Frame( void );
void XRcon_Print( const char *msg );
qboolean XRcon_IsActive( void );
#ifdef REF_DLL
#error "common.h in ref_dll"

View File

@@ -167,7 +167,6 @@ void Sys_CloseLog( const char *finalmsg )
s_ld.logfile = NULL;
}
#if XASH_COLORIZE_CONSOLE
static qboolean Sys_WriteEscapeSequenceForColorcode( int fd, int c )
{
static const char *q3ToAnsi[ 8 ] =
@@ -185,14 +184,8 @@ static qboolean Sys_WriteEscapeSequenceForColorcode( int fd, int c )
return write( fd, esc, c == 7 ? 4 : 7 ) < 0 ? false : true;
}
#else
static qboolean Sys_WriteEscapeSequenceForColorcode( int fd, int c )
{
return true;
}
#endif
static void Sys_PrintLogfile( const int fd, const char *logtime, size_t logtime_len, const char *msg, const int colorize )
static void Sys_PrintLogfile( const int fd, const char *logtime, size_t logtime_len, const char *msg, qboolean colorize )
{
const char *p = msg;
@@ -204,6 +197,17 @@ static void Sys_PrintLogfile( const int fd, const char *logtime, size_t logtime_
}
}
if( !colorize )
{
if( write( fd, msg, Q_strlen( msg )) < 0 )
{
// don't call engine Msg, might cause recursion
fprintf( stderr, "%s: write failed: %s\n", __func__, strerror( errno ));
}
return;
}
while( p && *p )
{
p = Q_strchr( msg, '^' );
@@ -226,8 +230,7 @@ static void Sys_PrintLogfile( const int fd, const char *logtime, size_t logtime_
}
msg = p + 2;
if( colorize )
Sys_WriteEscapeSequenceForColorcode( fd, ColorIndex( p[1] ));
Sys_WriteEscapeSequenceForColorcode( fd, ColorIndex( p[1] ));
}
else
{
@@ -238,73 +241,89 @@ static void Sys_PrintLogfile( const int fd, const char *logtime, size_t logtime_
}
// flush the color
if( colorize )
Sys_WriteEscapeSequenceForColorcode( fd, 7 );
Sys_WriteEscapeSequenceForColorcode( fd, 7 );
}
static void Sys_PrintStdout( const char *logtime, size_t logtime_len, const char *msg )
static void Sys_WriteLogfile( int fd, const char *logtime, size_t logtime_len, const char *msg )
{
#if XASH_MOBILE_PLATFORM
static char buf[MAX_PRINT_MSG];
if( logtime_len != 0 )
{
if( write( fd, logtime, logtime_len ) < 0 )
{
// not critical for us
}
}
// strip color codes
COM_StripColors( msg, buf );
}
// platform-specific output
static void Sys_PrintStdout( const char *logtime, size_t logtime_len, const char *msg, const char *stripped )
{
#if XASH_ANDROID && !XASH_DEDICATED
__android_log_write( ANDROID_LOG_INFO, "Xash", buf );
__android_log_write( ANDROID_LOG_INFO, "Xash", stripped );
#endif // XASH_ANDROID && !XASH_DEDICATED
#if TARGET_OS_IOS
void IOS_Log( const char * );
IOS_Log( buf );
IOS_Log( stripped );
#endif // TARGET_OS_IOS
#if XASH_NSWITCH && NSWITCH_DEBUG
// just spew it to stderr normally in debug mode
fprintf( stderr, "%s %s", logtime, buf );
fprintf( stderr, "%s %s", logtime, stripped );
#endif // XASH_NSWITCH && NSWITCH_DEBUG
#if XASH_PSVITA
// spew to stderr only in developer mode
if( host_developer.value )
{
fprintf( stderr, "%s %s", logtime, buf );
fprintf( stderr, "%s %s", logtime, stripped );
}
#endif
#elif !XASH_WIN32 // Wcon does the job
Sys_PrintLogfile( STDOUT_FILENO, logtime, logtime_len, msg, XASH_COLORIZE_CONSOLE );
#if !XASH_MOBILE_PLATFORM && !XASH_WIN32 // Wcon does the job
Sys_PrintLogfile( STDOUT_FILENO, logtime, logtime_len, XASH_COLORIZE_CONSOLE ? msg : stripped, XASH_COLORIZE_CONSOLE );
Sys_FlushStdout();
#endif
XRcon_Print( stripped );
}
void Sys_PrintLog( const char *pMsg )
{
const struct tm *crt_tm = NULL;
char logtime[32] = "";
static char lastchar;
qboolean print_time = false;
size_t logtime_len = 0;
const struct tm *crt_tm = NULL;
if( !lastchar || lastchar == '\n' )
{
time_t crt_time;
if( time( &crt_time ) >= 0 )
{
crt_tm = localtime( &crt_time );
print_time = crt_tm != NULL;
}
}
if( print_time )
char logtime[32] = "";
size_t logtime_len = 0;
if( crt_tm != NULL )
{
logtime_len = strftime( logtime, sizeof( logtime ), "[%H:%M:%S] ", crt_tm ); // short time
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
}
#if !XASH_WIN32 && !XASH_COLORIZE_CONSOLE
qboolean need_strip = true; // stdout sink can't render ^N, must strip first
#else
qboolean need_strip = s_ld.logfile != NULL || XRcon_IsActive();
#endif
const char *log_msg = pMsg;
if( need_strip )
{
static char stripped[MAX_PRINT_MSG];
COM_StripColors( pMsg, stripped );
log_msg = stripped;
}
// spew to stdout
Sys_PrintStdout( logtime, logtime_len, pMsg );
Sys_PrintStdout( logtime, logtime_len, pMsg, log_msg );
size_t len = Q_strlen( pMsg );
@@ -314,7 +333,7 @@ void Sys_PrintLog( const char *pMsg )
// spew to engine.log
if( s_ld.logfile )
{
if( s_ld.log_time && print_time )
if( s_ld.log_time && crt_tm != NULL )
{
logtime_len = strftime( logtime, sizeof( logtime ), "[%Y:%m:%d|%H:%M:%S] ", crt_tm ); //full time
logtime_len = Q_min( logtime_len, sizeof( logtime ) - 1 ); // just in case
@@ -325,7 +344,7 @@ void Sys_PrintLog( const char *pMsg )
logtime_len = 0;
}
Sys_PrintLogfile( s_ld.logfileno, logtime, logtime_len, pMsg, false );
Sys_WriteLogfile( s_ld.logfileno, logtime, logtime_len, log_msg );
Sys_FlushLogfile();
}
}

View File

@@ -517,7 +517,6 @@ void Sys_Print( const char *pMsg )
Sys_PrintLog( pMsg );
Rcon_Print( &host.rd, pMsg );
XRcon_Print( pMsg );
}
/*

View File

@@ -38,6 +38,8 @@ GNU General Public License for more details.
static CVAR_DEFINE_AUTO( xrcon_enable, "0", FCVAR_PRIVILEGED, "enable remote console access server" );
static CVAR_DEFINE_AUTO( xrcon_address, "127.0.0.1:27000", FCVAR_PRIVILEGED, "XRCON server bind address and port" );
static CVAR_DEFINE_AUTO( xrcon_flush_interval, "0.05", FCVAR_PRIVILEGED, "seconds between flushes of pending console output to the XRCON client" );
static CVAR_DEFINE_AUTO( xrcon_retry_delay, "5.0", FCVAR_PRIVILEGED, "seconds to wait before retrying to bind the XRCON listen socket after a failure" );
typedef enum
{
@@ -368,9 +370,8 @@ static void XRcon_HandleDataTx( void )
{
int err = WSAGetLastError();
if( err != WSAEWOULDBLOCK && err != WSAEALREADY )
{
XRcon_DisconnectClient();
}
return;
}
@@ -516,7 +517,7 @@ static void XRcon_UpdateConnected( void )
if( xrcon.print_pos > 0 && Platform_DoubleTime() >= xrcon.print_flush_time )
{
XRcon_FlushPrintBuffer();
xrcon.print_flush_time = Platform_DoubleTime() + XRCON_FLUSH_INTERVAL;
xrcon.print_flush_time = Platform_DoubleTime() + xrcon_flush_interval.value;
}
}
@@ -526,7 +527,7 @@ static void XRcon_UpdateIdle( void )
return;
XRcon_StartListening();
xrcon.retry_timeout = Platform_DoubleTime() + XRCON_RETRY_DELAY;
xrcon.retry_timeout = Platform_DoubleTime() + xrcon_retry_delay.value;
}
void XRcon_Print( const char *msg )
@@ -534,63 +535,29 @@ void XRcon_Print( const char *msg )
if( xrcon.state != XRCON_STATE_CONNECTED )
return;
if( !msg || !*msg )
if( !msg )
return;
const char *p = msg;
while( p && *p )
while( *msg )
{
p = Q_strpbrk( msg, "^\n\r" );
if( p == NULL )
{
size_t length = Q_strlen( msg );
if( xrcon.print_pos + length < sizeof( xrcon.print_buffer ) - 1 )
{
memcpy( xrcon.print_buffer + xrcon.print_pos, msg, length );
xrcon.print_pos += length;
}
break;
}
else if( *p == '\n' || *p == '\r' )
{
size_t length = p - msg;
if( xrcon.print_pos + length < sizeof( xrcon.print_buffer ) - 1 )
{
memcpy( xrcon.print_buffer + xrcon.print_pos, msg, length );
xrcon.print_pos += length;
}
const char *p = Q_strchrnul( msg, '\n' );
size_t length = p - msg;
if( xrcon.print_pos > 0 )
{
XRcon_FlushPrintBuffer();
xrcon.print_flush_time = Platform_DoubleTime() + XRCON_FLUSH_INTERVAL;
}
msg = p + 1;
}
else if( IsColorString( p ))
if( xrcon.print_pos + length < sizeof( xrcon.print_buffer ) - 1 )
{
if( p != msg )
{
size_t length = p - msg;
if( xrcon.print_pos + length < sizeof( xrcon.print_buffer ) - 1 )
{
memcpy( xrcon.print_buffer + xrcon.print_pos, msg, length );
xrcon.print_pos += length;
}
}
msg = p + 2;
memcpy( xrcon.print_buffer + xrcon.print_pos, msg, length );
xrcon.print_pos += length;
}
else
if( *p == '\0' )
return;
if( xrcon.print_pos > 0 )
{
size_t length = p - msg + 1;
if( xrcon.print_pos + length < sizeof( xrcon.print_buffer ) - 1 )
{
memcpy( xrcon.print_buffer + xrcon.print_pos, msg, length );
xrcon.print_pos += length;
}
msg = p + 1;
XRcon_FlushPrintBuffer();
xrcon.print_flush_time = Platform_DoubleTime() + xrcon_flush_interval.value;
}
msg = p + 1;
}
}
@@ -649,6 +616,8 @@ void XRcon_Init( void )
Cvar_RegisterVariable( &xrcon_enable );
Cvar_RegisterVariable( &xrcon_address );
Cvar_RegisterVariable( &xrcon_flush_interval );
Cvar_RegisterVariable( &xrcon_retry_delay );
NET_NetadrSetType( &xrcon.bindadr, NA_UNDEFINED );
}
@@ -658,3 +627,8 @@ void XRcon_Shutdown( void )
XRcon_CloseListenSocket();
XRcon_SetState( XRCON_STATE_IDLE );
}
qboolean XRcon_IsActive( void )
{
return xrcon.state == XRCON_STATE_CONNECTED;
}