@@ -190,3 +190,195 @@ static class CRD_Convar_Hacks final : public CAutoGameSystem
190190 pConVar->SetValue ( szNewDefault );
191191 }
192192} s_RD_Convar_Hacks;
193+
194+
195+
196+
197+ static bool ConCommandBaseSortFunc ( const ConCommandBase* const &hLeftCMD, const ConCommandBase* const &hRightCMD )
198+ {
199+ const char * szLeftCMDName = hLeftCMD->GetName ();
200+ const char * szRightCMDName = hRightCMD->GetName ();
201+
202+ if ( *szLeftCMDName == ' -' || *szLeftCMDName == ' +' )
203+ szLeftCMDName++;
204+ if ( *szRightCMDName == ' -' || *szRightCMDName == ' +' )
205+ szRightCMDName++;
206+
207+ return ( Q_stricmp ( szLeftCMDName, szRightCMDName ) < 0 );
208+ }
209+
210+ static char *StripTabsAndReturns ( const char *inbuffer, char *outbuffer, int outbufferSize )
211+ {
212+ char *out = outbuffer;
213+ const char *i = inbuffer;
214+ char *o = out;
215+
216+ out[ 0 ] = 0 ;
217+
218+ while ( *i && o - out < outbufferSize - 1 )
219+ {
220+ if ( *i == ' \n ' ||
221+ *i == ' \r ' ||
222+ *i == ' \t ' )
223+ {
224+ *o++ = ' ' ;
225+ i++;
226+ continue ;
227+ }
228+ if ( *i == ' \" ' )
229+ {
230+ *o++ = ' \' ' ;
231+ i++;
232+ continue ;
233+ }
234+
235+ *o++ = *i++;
236+ }
237+
238+ *o = ' \0 ' ;
239+
240+ return out;
241+ }
242+
243+ CON_COMMAND ( cvarlist_rd, " Prints a list of all cvars, with correct values (unlike normal cvarlist). No argument - current values, arg being 1 - default values, arg being 2 - current values in csv format, arg being 3 - default values in csv format" )
244+ {
245+ bool bDefault = false ;
246+ bool bCSV = false ;
247+ int nArgs = args.ArgC ();
248+ if ( nArgs >= 2 )
249+ {
250+ int nArg1 = atoi ( args[1 ] );
251+
252+ bDefault = nArg1 == 1 || nArg1 == 3 ;
253+ bCSV = nArg1 >= 2 ;
254+ }
255+
256+ if ( !bCSV )
257+ ConMsg ( " cvar list\n --------------\n " );
258+ else
259+ ConMsg ( " \" Name\" ,\" Value\" ,\" GAMEDLL\" ,\" CLIENTDLL\" ,\" PROTECTED\" ,\" SPONLY\" ,\" ARCHIVE\" ,\" NOTIFY\" ,\" USERINFO\" ,\" PRINTABLEONLY\" ,\" UNLOGGED\" ,\" NEVER_AS_STRING\" ,\" REPLICATED\" ,\" CHEAT\" ,\" SS\" ,\" DEMO\" ,\" DONTRECORD\" ,\" SS_ADDED\" ,,\" Help Text\"\n " );
260+
261+ const ConCommandBase* pCMD;
262+ ICvar::Iterator cvariterator ( g_pCVar );
263+ CUtlRBTree< const ConCommandBase* > cvarsorted ( 0 , 0 , ConCommandBaseSortFunc );
264+
265+ for ( cvariterator.SetFirst (); cvariterator.IsValid (); cvariterator.Next () )
266+ {
267+ pCMD = cvariterator.Get ();
268+
269+ if ( pCMD->IsFlagSet ( FCVAR_HIDDEN ) || pCMD->IsFlagSet ( FCVAR_DEVELOPMENTONLY ) )
270+ continue ;
271+
272+ cvarsorted.Insert ( pCMD );
273+ }
274+
275+ for ( int i = cvarsorted.FirstInorder (); i != cvarsorted.InvalidIndex (); i = cvarsorted.NextInorder ( i ) )
276+ {
277+ pCMD = cvarsorted[ i ];
278+ if ( pCMD->IsCommand () )
279+ {
280+ if ( !bCSV ) // unchanged cvarlist console output format
281+ {
282+ char tempbuff[512 ]{};
283+ ConMsg ( " %-40s : %-8s : %-16s : %s\n " , pCMD->GetName (), " cmd" , " " , StripTabsAndReturns ( pCMD->GetHelpText (), tempbuff, sizeof ( tempbuff ) ) );
284+ }
285+ else // CSV format
286+ {
287+ char tempbuff[512 ]{};
288+ ConMsg ( " \" %s\" ,\" %s\" ,%s,\" %s\"\n " , pCMD->GetName (), " cmd" , " ,,,,,,,,,,,,,,,," , StripTabsAndReturns ( pCMD->GetHelpText (), tempbuff, sizeof ( tempbuff ) ) );
289+ }
290+ }
291+ else
292+ {
293+ char szFullFlags[256 ]{};
294+
295+ if ( !bCSV ) // unchanged cvarlist console output format
296+ {
297+ constexpr static const char * s_szFlagDesc[] =
298+ {
299+ " " ,
300+ " " ,
301+ " sv" ,
302+ " cl" ,
303+ " " ,
304+ " prot" ,
305+ " sp" ,
306+ " a" ,
307+ " nf" ,
308+ " user" ,
309+ " print" ,
310+ " log" ,
311+ " numeric" ,
312+ " rep" ,
313+ " cheat" ,
314+ " " ,
315+ " demo" ,
316+ " norecord" ,
317+ };
318+
319+ for ( int c = 2 ; c < ARRAYSIZE ( s_szFlagDesc ); ++c )
320+ {
321+ char szFlag[32 ]{};
322+
323+ if ( pCMD->IsFlagSet ( 1 << c ) && sizeof ( s_szFlagDesc[c] ) != sizeof ( " " ) )
324+ {
325+ Q_snprintf ( szFlag, sizeof ( szFlag ), " , %s" , s_szFlagDesc[c] );
326+ Q_strncat ( szFullFlags, szFlag, sizeof ( szFullFlags ), COPY_ALL_CHARACTERS );
327+ }
328+ }
329+ char tempbuff[512 ]{};
330+ ConMsg ( " %-40s : %-8s : %-16s : %s\n " , pCMD->GetName (), bDefault ? static_cast < const ConVar* >( pCMD )->GetDefault () : static_cast < const ConVar* >( pCMD )->GetString (), szFullFlags, StripTabsAndReturns ( pCMD->GetHelpText (), tempbuff, sizeof (tempbuff) ) );
331+ }
332+ else // CSV format
333+ {
334+ constexpr static const char * s_szFlagDesc[] =
335+ {
336+ " " ,
337+ " " ,
338+ " GAMEDLL" ,
339+ " CLIENTDLL" ,
340+ " " ,
341+ " PROTECTED" ,
342+ " SPONLY" ,
343+ " ARCHIVE" ,
344+ " NOTIFY" ,
345+ " USERINFO" ,
346+ " PRINTABLEONLY" ,
347+ " UNLOGGED" ,
348+ " NEVER_AS_STRING" ,
349+ " REPLICATED" ,
350+ " CHEAT" ,
351+ " SS" ,
352+ " DEMO" ,
353+ " DONTRECORD" ,
354+ " SS_ADDED" ,
355+ };
356+
357+ for ( int c = 2 ; c < ARRAYSIZE ( s_szFlagDesc ); ++c )
358+ {
359+ if ( c == 4 ) // FCVAR_HIDDEN, we filter those out anyway
360+ continue ;
361+
362+ char szFlag[32 ]{};
363+
364+ if ( pCMD->IsFlagSet ( 1 << c ) && sizeof ( s_szFlagDesc[c] ) != sizeof ( " " ) )
365+ {
366+ Q_snprintf ( szFlag, sizeof ( szFlag ), " \" %s\" ," , s_szFlagDesc[c] );
367+ Q_strncat ( szFullFlags, szFlag, sizeof ( szFullFlags ), COPY_ALL_CHARACTERS );
368+ }
369+ else
370+ {
371+ Q_snprintf ( szFlag, sizeof ( szFlag ), " ," );
372+ Q_strncat ( szFullFlags, szFlag, sizeof ( szFullFlags ), COPY_ALL_CHARACTERS );
373+ }
374+ }
375+
376+ char tempbuff[512 ]{};
377+ ConMsg ( " \" %s\" ,\" %s\" ,%s,\" %s\"\n " , pCMD->GetName (), bDefault ? static_cast < const ConVar* >( pCMD )->GetDefault () : static_cast < const ConVar* >( pCMD )->GetString (), szFullFlags, StripTabsAndReturns ( pCMD->GetHelpText (), tempbuff, sizeof (tempbuff) ) );
378+ }
379+ }
380+ }
381+
382+ if ( !bCSV )
383+ ConMsg (" --------------\n %3i total convars/concommands\n " , cvarsorted.Count () );
384+ }
0 commit comments