engine: server: add requested server command status. Only expose client input devices for now, as everything else might be considered sensitive information

This commit is contained in:
Alibek Omarov
2025-03-20 05:46:49 +03:00
parent a1950ec7b0
commit ecbfdb82f4
3 changed files with 102 additions and 32 deletions

View File

@@ -790,7 +790,7 @@ void Con_NPrintf( int idx, const char *fmt, ... ) FORMAT_CHECK( 2 );
void Con_NXPrintf( con_nprint_t *info, const char *fmt, ... ) FORMAT_CHECK( 2 );
void UI_NPrintf( int idx, const char *fmt, ... ) FORMAT_CHECK( 2 );
void UI_NXPrintf( con_nprint_t *info, const char *fmt, ... ) FORMAT_CHECK( 2 );
const char *Info_ValueForKey( const char *s, const char *key );
const char *Info_ValueForKey( const char *s, const char *key ) RETURNS_NONNULL NONNULL;
void Info_RemovePrefixedKeys( char *start, char prefix );
qboolean Info_RemoveKey( char *s, const char *key );
qboolean Info_SetValueForKey( char *s, const char *key, const char *value, int maxsize );

View File

@@ -1882,20 +1882,6 @@ static void SV_UserinfoChanged( sv_client_t *cl )
ent->v.netname = MAKE_STRING( cl->name );
}
/*
==================
SV_UpdateUserinfo_f
==================
*/
static qboolean SV_UpdateUserinfo_f( sv_client_t *cl )
{
Q_strncpy( cl->userinfo, Cmd_Argv( 1 ), sizeof( cl->userinfo ));
if( cl->state >= cs_connected )
SetBits( cl->flags, FCL_RESEND_USERINFO ); // needs for update client info
return true;
}
/*
==================
SV_SetInfo_f
@@ -2188,6 +2174,83 @@ static qboolean SV_SendBuildInfo_f( sv_client_t *cl )
return true;
}
/*
==================
SV_ClientStatus_f
==================
*/
static qboolean SV_ClientStatus_f( sv_client_t *cl )
{
netadr_t ip4, ip6;
vec3_t origin = { 0 };
int clients, bots, i;
NET_GetLocalAddress( &ip4, &ip6 );
if( cl->edict )
VectorCopy( cl->edict->v.origin, origin );
SV_GetPlayerCount( &clients, &bots );
SV_ClientPrintf( cl,
"hostname: %s\n"
"version: %i/%s %d\n",
hostname.string,
PROTOCOL_VERSION, XASH_VERSION, Q_buildnum( ));
if( ip4.type == NA_IP )
SV_ClientPrintf( cl, "tcp/ip: %s\n", NET_AdrToString( ip4 ));
if( ip6.type == NA_IP6 )
SV_ClientPrintf( cl, "tcp/ipv6: %s\n", NET_AdrToString( ip4 ));
SV_ClientPrintf( cl,
"map:\t%s at %d x, %d y, %d z\n"
"players: %i active (%i max)\n"
"# score ping dev playtime name\n",
sv.name, (int)origin[0], (int)origin[1], (int)origin[2],
clients, svs.maxclients );
for( i = 0; i < svs.maxclients; i++ )
{
const sv_client_t *pcl = &svs.clients[i];
int j = 0;
int input_devices;
const char *s;
char devices[8];
if( pcl->state != cs_spawned )
continue;
if( FBitSet( pcl->flags, FCL_FAKECLIENT ))
s = "Bot ";
else
s = va( "%i", SV_CalcPing( pcl ));
input_devices = Q_atoi( Info_ValueForKey( pcl->useragent, "d" ));
if( FBitSet( input_devices, INPUT_DEVICE_MOUSE ))
devices[j++] = 'm';
if( FBitSet( input_devices, INPUT_DEVICE_TOUCH ))
devices[j++] = 't';
if( FBitSet( input_devices, INPUT_DEVICE_JOYSTICK ))
devices[j++] = 'j';
if( FBitSet( input_devices, INPUT_DEVICE_VR ))
devices[j++] = 'v';
if( j == 0 )
Q_strncpy( devices, "n/a", sizeof( devices ));
else
devices[j++] = 0;
SV_ClientPrintf( cl,
"%2i %5i %4s %4s %g %s\n",
i, (int)pcl->edict->v.frags, s, devices, host.realtime - pcl->netchan.connect_time, pcl->name );
}
return true;
}
/*
==================
SV_GetCrossEnt
@@ -2969,32 +3032,33 @@ static qboolean SV_EntGetVars_f( sv_client_t *cl )
return true;
}
// keep it sorted
static const ucmd_t ucmds[] =
{
{ "new", SV_New_f },
{ "god", SV_Godmode_f },
{ "kill", SV_Kill_f },
{ "begin", SV_Begin_f },
{ "spawn", SV_Spawn_f },
{ "pause", SV_Pause_f },
{ "noclip", SV_Noclip_f },
{ "setinfo", SV_SetInfo_f },
{ "sendres", SV_SendRes_f },
{ "notarget", SV_Notarget_f },
{ "info", SV_ShowServerinfo_f },
{ "dlfile", SV_DownloadFile_f },
{ "disconnect", SV_Disconnect_f },
{ "userinfo", SV_UpdateUserinfo_f },
{ "_sv_build_info", SV_SendBuildInfo_f },
{ "begin", SV_Begin_f },
{ "disconnect", SV_Disconnect_f },
{ "dlfile", SV_DownloadFile_f },
{ "god", SV_Godmode_f },
{ "info", SV_ShowServerinfo_f },
{ "kill", SV_Kill_f },
{ "new", SV_New_f },
{ "noclip", SV_Noclip_f },
{ "notarget", SV_Notarget_f },
{ "pause", SV_Pause_f },
{ "sendres", SV_SendRes_f },
{ "setinfo", SV_SetInfo_f },
{ "spawn", SV_Spawn_f },
{ "status", SV_ClientStatus_f },
};
static const ucmd_t enttoolscmds[] =
{
{ "ent_list", SV_EntList_f },
{ "ent_info", SV_EntInfo_f },
{ "ent_fire", SV_EntFire_f },
{ "ent_create", SV_EntCreate_f },
{ "ent_fire", SV_EntFire_f },
{ "ent_getvars", SV_EntGetVars_f },
{ "ent_info", SV_EntInfo_f },
{ "ent_list", SV_EntList_f },
};
/*

View File

@@ -630,6 +630,12 @@ static void SV_Status_f( void )
sv_client_t *cl;
int i;
if( !svs.clients && CL_Active( ))
{
Cmd_ForwardToServer();
return;
}
if( !svs.clients || sv.background )
{
Con_Printf( "^3no server running.\n" );