From 70f301e4ffb16785c57d2a89c2e18c0416755b1e Mon Sep 17 00:00:00 2001 From: myT Date: Tue, 3 Oct 2017 19:11:10 +0200 Subject: [PATCH] cvar help extension cvar type+range extension module tracking for cvars and commands lots of help text --- changelog.txt | 6 + code/client/cl_browser.cpp | 3 - code/client/cl_cgame.cpp | 31 +- code/client/cl_console.cpp | 65 +++-- code/client/cl_input.cpp | 241 +++++++-------- code/client/cl_keys.cpp | 2 + code/client/cl_main.cpp | 290 ++++++------------- code/client/cl_ui.cpp | 33 ++- code/client/client.h | 3 +- code/client/client_help.h | 42 +++ code/client/snd_dma.cpp | 22 +- code/client/snd_local.h | 2 +- code/client/snd_main.cpp | 37 ++- code/client/snd_mem.cpp | 2 + code/qcommon/cg_public.h | 5 +- code/qcommon/cmd.cpp | 245 +++++++++++++--- code/qcommon/common.cpp | 249 +++++++++++----- code/qcommon/common_help.h | 59 ++++ code/qcommon/cvar.cpp | 286 +++++++++++++++++- code/qcommon/files.cpp | 22 +- code/qcommon/g_public.h | 5 +- code/qcommon/net_chan.cpp | 7 + code/qcommon/net_ip.cpp | 4 + code/qcommon/q_shared.c | 45 +++ code/qcommon/q_shared.h | 19 ++ code/qcommon/qcommon.h | 120 +++++++- code/qcommon/ui_public.h | 5 +- code/qcommon/vm.cpp | 13 +- code/renderer/tr_bsp.cpp | 2 +- code/renderer/tr_gl2.cpp | 4 +- code/renderer/tr_help.h | 86 ++++++ code/renderer/tr_image.cpp | 10 +- code/renderer/tr_init.cpp | 248 +++++++--------- code/renderer/tr_local.h | 1 - code/renderer/tr_public.h | 6 +- code/server/server.h | 3 +- code/server/sv_ccmds.cpp | 56 ++-- code/server/sv_client.cpp | 4 +- code/server/sv_game.cpp | 29 +- code/server/sv_init.cpp | 85 +++--- code/server/sv_main.cpp | 5 +- code/win32/win_help.h | 9 + code/win32/win_input.cpp | 21 +- code/win32/win_main.cpp | 4 + makefiles/vs2013/cnq3-server.vcxproj | 3 + makefiles/vs2013/cnq3-server.vcxproj.filters | 9 + makefiles/vs2013/cnq3.vcxproj | 4 + makefiles/vs2013/cnq3.vcxproj.filters | 12 + makefiles/vs2013/renderer.vcxproj | 1 + 49 files changed, 1686 insertions(+), 779 deletions(-) create mode 100644 code/client/client_help.h create mode 100644 code/qcommon/common_help.h create mode 100644 code/renderer/tr_help.h create mode 100644 code/win32/win_help.h diff --git a/changelog.txt b/changelog.txt index 8df5985..d61384e 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,12 @@ DD Mmm 17 - 1.49 +add: new cvar type and range extension for compatible mods like CPMA 1.50 + +add: new help commands for commands and cvars of the engine and compatible mods like CPMA 1.50 + help|man to display the help of a cvar or command + searchhelp to list all cvars and commands whose help or name matches the pattern + fix: /bind was treating single-character key names in a case sensitive manner add: new CNQ3 download system that uses checksums to get the right pak files diff --git a/code/client/cl_browser.cpp b/code/client/cl_browser.cpp index a794d17..ed3b493 100644 --- a/code/client/cl_browser.cpp +++ b/code/client/cl_browser.cpp @@ -625,9 +625,6 @@ void CL_GetPing( int n, char *buf, int buflen, int *pingtime ) // check for timeout time = cls.realtime - cl_pinglist[n].start; maxPing = Cvar_VariableIntegerValue( "cl_maxPing" ); - if( maxPing < 100 ) { - maxPing = 100; - } if (time < maxPing) { // not timed out yet diff --git a/code/client/cl_cgame.cpp b/code/client/cl_cgame.cpp index c4bf785..90eec52 100644 --- a/code/client/cl_cgame.cpp +++ b/code/client/cl_cgame.cpp @@ -133,12 +133,6 @@ static void CL_SetUserCmdValue( int userCmdValue, float sensitivityScale ) } -static void CL_AddCgameCommand( const char* cmd ) -{ - Cmd_AddCommandEx( cmd, NULL, qtrue ); -} - - static void CL_ConfigstringModified() { int index = atoi( Cmd_Argv(1) ); @@ -297,7 +291,7 @@ void CL_ShutdownCGame() VM_Call( cgvm, CG_SHUTDOWN ); VM_Free( cgvm ); cgvm = NULL; - Cmd_RemoveCGameCommands(); + Cmd_UnregisterModule( MODULE_CGAME ); } @@ -308,7 +302,10 @@ static qbool CL_CG_GetValue( char* value, int valueSize, const char* key ) { "trap_LocateInteropData", CG_EXT_LOCATEINTEROPDATA }, { "trap_R_AddRefEntityToScene2", CG_EXT_R_ADDREFENTITYTOSCENE2 }, { "trap_R_ForceFixedDLights", CG_EXT_R_FORCEFIXEDDLIGHTS }, - { "trap_SetInputForwarding", CG_EXT_SETINPUTFORWARDING } + { "trap_SetInputForwarding", CG_EXT_SETINPUTFORWARDING }, + { "trap_Cvar_SetRange", CG_EXT_CVAR_SETRANGE }, + { "trap_Cvar_SetHelp", CG_EXT_CVAR_SETHELP }, + { "trap_Cmd_SetHelp", CG_EXT_CMD_SETHELP } }; for ( int i = 0; i < ARRAY_LEN( syscalls ); ++i ) { @@ -339,7 +336,8 @@ static intptr_t CL_CgameSystemCalls( intptr_t *args ) case CG_MILLISECONDS: return Sys_Milliseconds(); case CG_CVAR_REGISTER: - Cvar_Register( VMA(1), VMA(2), VMA(3), args[4] ); + Cvar_Register( VMA(1), VMA(2), VMA(3), args[4] ); + Cvar_SetModule( VMA(2), MODULE_CGAME ); return 0; case CG_CVAR_UPDATE: Cvar_Update( VMA(1) ); @@ -375,7 +373,8 @@ static intptr_t CL_CgameSystemCalls( intptr_t *args ) Cbuf_AddText( VMA(1) ); return 0; case CG_ADDCOMMAND: - CL_AddCgameCommand( VMA(1) ); + Cmd_AddCommand( VMA(1), NULL ); + Cmd_SetModule( VMA(1), MODULE_CGAME ); return 0; case CG_REMOVECOMMAND: Cmd_RemoveCommand( VMA(1) ); @@ -595,6 +594,18 @@ static intptr_t CL_CgameSystemCalls( intptr_t *args ) cls.cgameForwardInput = (int)args[1]; return 0; + case CG_EXT_CVAR_SETRANGE: + Cvar_SetRange( VMA(1), (cvarType_t)args[2], VMA(3), VMA(4) ); + return 0; + + case CG_EXT_CVAR_SETHELP: + Cvar_SetHelp( VMA(1), VMA(2) ); + return 0; + + case CG_EXT_CMD_SETHELP: + Cmd_SetHelp( VMA(1), VMA(2) ); + return 0; + default: Com_Error( ERR_DROP, "Bad cgame system trap: %i", args[0] ); } diff --git a/code/client/cl_console.cpp b/code/client/cl_console.cpp index 072b5e2..7f6667a 100644 --- a/code/client/cl_console.cpp +++ b/code/client/cl_console.cpp @@ -22,13 +22,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // console.c #include "client.h" +#include "client_help.h" -static const cvar_t* con_noprint; -static const cvar_t* con_notifytime; -static const cvar_t* con_scale; -static const cvar_t* con_scaleMode; // 0 = without res, 1 = with res, 2 = 8x12 -static const cvar_t* con_speed; +static cvar_t* con_noprint; +static cvar_t* con_notifytime; +static cvar_t* con_scale; +static cvar_t* con_scaleMode; // 0 = without res, 1 = with res, 2 = 8x12 +static cvar_t* con_speed; #define CON_NOTIFYLINES 4 @@ -65,7 +66,6 @@ static console_t con; #define CONCHAR_WIDTH 8 #define CONCHAR_HEIGHT 12 -#define CONSOLE_WIDTH 78 int g_console_field_width = CONSOLE_WIDTH; @@ -264,12 +264,8 @@ static void Con_ResizeFont() if (con_scaleMode->integer == 1) SCR_AdjustFrom640( &con.cw, &con.ch, NULL, NULL ); - // bugs in the renderer's overflow handling will cause crashes - // if the console has too many polys/verts because of too small a font - // this is a fairly arbitrary lower bound, but better than nothing - const float scale = max( 0.25f, fabsf( con_scale->value ) ); - con.cw *= scale; - con.ch *= scale; + con.cw *= con_scale->value; + con.ch *= con_scale->value; if ( cls.glconfig.vidWidth * SCREEN_HEIGHT > cls.glconfig.vidHeight * SCREEN_WIDTH ) { // the console distorts horribly on widescreens @@ -280,13 +276,34 @@ static void Con_ResizeFont() } +static const cvarTableItem_t con_cvars[] = +{ + // con_scale: + // bugs in the renderer's overflow handling will cause crashes + // if the console has too many polys/verts because of too small a font + { &con_noprint, "con_noprint", "0", 0, CVART_BOOL, NULL, NULL, "disables console printing and history writing" }, + { &con_notifytime, "con_notifytime", "3", CVAR_ARCHIVE, CVART_FLOAT, "0", "30", "number of seconds a notify line stays visible" }, + { &con_scale, "con_scale", "1.2", CVAR_ARCHIVE, CVART_FLOAT, "0.25", "10", "console text scaling factor" }, + { &con_scaleMode, "con_scaleMode", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "2", help_con_scaleMode }, + { &con_speed, "con_speed", "1000", CVAR_ARCHIVE, CVART_FLOAT, "0.1", "1000", "console opening/closing speed" } +}; + + +static const cmdTableItem_t con_cmds[] = +{ + { "toggleconsole", Con_ToggleConsole_f, NULL, "toggles console display" }, + { "messagemode", Con_MessageMode_f, NULL, "chat with everyone" }, + { "messagemode2", Con_MessageMode2_f, NULL, "chat with teammates" }, + { "messagemode3", Con_MessageMode3_f, NULL, "chat with the player being aimed at" }, + { "messagemode4", Con_MessageMode4_f, NULL, "chat with the last attacker" }, + { "clear", Con_Clear_f, NULL, "clears the console" }, + { "condump", Con_Dump_f, NULL, "dumps console history to a text file" } +}; + + void CL_ConInit() { - con_noprint = Cvar_Get( "con_noprint", "0", 0 ); - con_notifytime = Cvar_Get( "con_notifytime", "3", CVAR_ARCHIVE ); - con_scale = Cvar_Get( "con_scale", "1", CVAR_ARCHIVE ); - con_scaleMode = Cvar_Get( "con_scaleMode", "0", CVAR_ARCHIVE ); - con_speed = Cvar_Get( "con_speed", "3", CVAR_ARCHIVE ); + Cvar_RegisterArray( con_cvars, MODULE_CONSOLE ); Field_Clear( &g_consoleField ); g_consoleField.widthInChars = g_console_field_width; @@ -295,13 +312,13 @@ void CL_ConInit() CL_LoadCommandHistory(); - Cmd_AddCommand( "toggleconsole", Con_ToggleConsole_f ); - Cmd_AddCommand( "messagemode", Con_MessageMode_f ); - Cmd_AddCommand( "messagemode2", Con_MessageMode2_f ); - Cmd_AddCommand( "messagemode3", Con_MessageMode3_f ); - Cmd_AddCommand( "messagemode4", Con_MessageMode4_f ); - Cmd_AddCommand( "clear", Con_Clear_f ); - Cmd_AddCommand( "condump", Con_Dump_f ); + Cmd_RegisterArray( con_cmds, MODULE_CONSOLE ); +} + + +void CL_ConShutdown() +{ + Cmd_UnregisterModule( MODULE_CONSOLE ); } diff --git a/code/client/cl_input.cpp b/code/client/cl_input.cpp index 454128e..194bbc3 100644 --- a/code/client/cl_input.cpp +++ b/code/client/cl_input.cpp @@ -22,27 +22,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // cl.input.c -- builds an intended movement command to send to the server #include "client.h" +#include "client_help.h" -static const cvar_t* m_speed; -static const cvar_t* m_accel; -static const cvar_t* m_accelStyle; // 0=original, 1=new -static const cvar_t* m_accelOffset; // for style 1 only -static const cvar_t* m_limit; // for style 0 only -static const cvar_t* m_pitch; -static const cvar_t* m_yaw; -static const cvar_t* m_forward; -static const cvar_t* m_side; -static const cvar_t* m_filter; +static cvar_t* m_speed; +static cvar_t* m_accel; +static cvar_t* m_accelStyle; // 0=original, 1=new +static cvar_t* m_accelOffset; // for style 1 only +static cvar_t* m_limit; // for style 0 only +static cvar_t* m_pitch; +static cvar_t* m_yaw; +static cvar_t* m_forward; +static cvar_t* m_side; +static cvar_t* m_filter; -static const cvar_t* cl_pitchspeed; -static const cvar_t* cl_yawspeed; -static const cvar_t* cl_run; -static const cvar_t* cl_anglespeedkey; -static const cvar_t* cl_freelook; +static cvar_t* cl_pitchspeed; +static cvar_t* cl_yawspeed; +static cvar_t* cl_run; +static cvar_t* cl_anglespeedkey; +static cvar_t* cl_freelook; -static const cvar_t* cl_nodelta; -static const cvar_t* cl_showMouseRate; +static cvar_t* cl_nodelta; +static cvar_t* cl_showMouseRate; static unsigned frame_msec; static int old_com_frameTime; @@ -382,7 +383,7 @@ static void CL_MouseMove( usercmd_t* cmd ) my *= speed; // new style, similar to quake3e's cl_mouseAccelStyle 1 } else { - const float offset = Com_Clamp( 0.001f, 5000.0f, m_accelOffset->value ); + const float offset = m_accelOffset->value; const float rateXa = fabsf( mx ) / (float)frame_msec; const float rateYa = fabsf( my ) / (float)frame_msec; const float powerXa = powf( rateXa / offset, m_accel->value ); @@ -591,12 +592,6 @@ static qbool CL_ReadyToSendPacket() return qtrue; } - // check for exceeding cl_maxpackets - if ( cl_maxpackets->integer < 15 ) { - Cvar_Set( "cl_maxpackets", "15" ); - } else if ( cl_maxpackets->integer > 125 ) { - Cvar_Set( "cl_maxpackets", "125" ); - } oldPacketNum = (clc.netchan.outgoingSequence - 1) & PACKET_MASK; delta = cls.realtime - cl.outPackets[ oldPacketNum ].p_realtime; if ( delta < 1000 / cl_maxpackets->integer ) { @@ -673,11 +668,6 @@ void CL_WritePacket( void ) // we want to send all the usercmds that were generated in the last // few packet, so even if a couple packets are dropped in a row, // all the cmds will make it to the server - if ( cl_packetdup->integer < 0 ) { - Cvar_Set( "cl_packetdup", "0" ); - } else if ( cl_packetdup->integer > 5 ) { - Cvar_Set( "cl_packetdup", "5" ); - } oldPacketNum = (clc.netchan.outgoingSequence - 1 - cl_packetdup->integer) & PACKET_MASK; count = cl.cmdNumber - cl.outPackets[ oldPacketNum ].p_cmdNumber; if ( count > MAX_PACKET_USERCMDS ) { @@ -835,96 +825,109 @@ static void IN_Button15Down(void) {IN_KeyDown(&in_buttons[15]);} static void IN_Button15Up(void) {IN_KeyUp(&in_buttons[15]);} +static const cvarTableItem_t cl_cvars[] = +{ + { NULL, "cl_drawMouseLag", "0", 0, CVART_BOOL, NULL, NULL, "draws sampling to display/upload delays" }, + { &m_speed, "m_speed", "2", CVAR_ARCHIVE, CVART_FLOAT, "0", "100", "mouse sensitivity" }, + { &m_accel, "m_accel", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", NULL, "mouse acceleration" }, + { &m_accelStyle, "m_accelStyle", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "1", "0=original, 1=new" }, + { &m_accelOffset, "m_accelOffset", "0", CVAR_ARCHIVE, CVART_FLOAT, "0.001", "5000", "offset for the power function\nfor m_accelStyle 1 only" }, + { &m_limit, "m_limit", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", NULL, "mouse speed cap (0=disabled)\nfor m_accelStyle 0 only" }, + { &m_pitch, "m_pitch", "0.022", CVAR_ARCHIVE, CVART_FLOAT, "-100", "100", "post-accel vertical mouse sens." }, + { &m_yaw, "m_yaw", "0.022", CVAR_ARCHIVE, CVART_FLOAT, "-100", "100", "post-accel horizontal mouse sens." }, + { &m_forward, "m_forward", "0.25", CVAR_ARCHIVE, CVART_FLOAT, "-32767", "32767", "forward/backwards mouse sensitivity (+strafe)" }, + { &m_side, "m_side", "0.25", CVAR_ARCHIVE, CVART_FLOAT, "-32767", "32767", "left/right mouse sensitivity (+strafe)" }, + { &m_filter, "m_filter", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "mouse smoothing" }, + { &cl_pitchspeed, "cl_pitchspeed", "140", CVAR_ARCHIVE, CVART_FLOAT, "0", NULL, "+lookup +lookdown speed" }, + { &cl_yawspeed, "cl_yawspeed", "140", CVAR_ARCHIVE, CVART_FLOAT, "0", NULL, "+right +left speed" }, + { &cl_anglespeedkey, "cl_anglespeedkey", "1.5", 0, CVART_FLOAT }, + { &cl_run, "cl_run", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "running enabled (0=walk)" }, + { &cl_freelook, "cl_freelook", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "0 means you can't look up/down" }, + { &cl_showMouseRate, "cl_showmouserate", "0", 0, CVART_BOOL, NULL, NULL, "prints info when m_accel != 0" }, + { &cl_nodelta, "cl_nodelta", "0", 0, CVART_BOOL, NULL, NULL, "disables delta-compression on uploaded user commands" }, + { &cl_debugMove, "cl_debugMove", "0", 0, CVART_INTEGER, "0", "2", help_cl_debugMove } +}; + + +static const cmdTableItem_t cl_cmds[] = +{ +#define help_button1 "\nYou can't move and there's a chat bubble over your head." + { "+moveup", IN_UpDown, NULL, "starts jumping/moving up" help_plus_minus }, + { "-moveup", IN_UpUp, NULL, "stops jumping/moving up" help_plus_minus }, + { "+movedown", IN_DownDown, NULL, "starts crouching/moving down" help_plus_minus }, + { "-movedown", IN_DownUp, NULL, "stops crouching/moving down" help_plus_minus }, + { "+left", IN_LeftDown, NULL, "starts rotating left" help_plus_minus }, + { "-left", IN_LeftUp, NULL, "stops rotating left" help_plus_minus }, + { "+right", IN_RightDown, NULL, "starts rotating right" help_plus_minus }, + { "-right", IN_RightUp, NULL, "stops rotating right" help_plus_minus }, + { "+forward", IN_ForwardDown, NULL, "starts moving forward" help_plus_minus }, + { "-forward", IN_ForwardUp, NULL, "stops moving forward" help_plus_minus }, + { "+back", IN_BackDown, NULL, "starts moving backwards" help_plus_minus }, + { "-back", IN_BackUp, NULL, "stops moving backwards" help_plus_minus }, + { "+lookup", IN_LookupDown, NULL, "starts looking up" help_plus_minus }, + { "-lookup", IN_LookupUp, NULL, "stops looking up" help_plus_minus }, + { "+lookdown", IN_LookdownDown, NULL, "starts looking down" help_plus_minus }, + { "-lookdown", IN_LookdownUp, NULL, "stops looking down" help_plus_minus }, + { "+strafe", IN_StrafeDown, NULL, "starts mouse strafing mode" help_plus_minus }, + { "-strafe", IN_StrafeUp, NULL, "stops mouse strafing mode" help_plus_minus }, + { "+moveleft", IN_MoveleftDown, NULL, "starts strafing left" help_plus_minus }, + { "-moveleft", IN_MoveleftUp, NULL, "stops strafing left" help_plus_minus }, + { "+moveright", IN_MoverightDown, NULL, "starts strafing right" help_plus_minus }, + { "-moveright", IN_MoverightUp, NULL, "stops strafing right" help_plus_minus }, + { "+speed", IN_SpeedDown, NULL, "start walk/run toggle" }, + { "-speed", IN_SpeedUp, NULL, "stops walk/run toggle" }, + { "+attack", IN_Button0Down, NULL, "starts firing the gun" help_plus_minus }, + { "-attack", IN_Button0Up, NULL, "stops firing the gun" help_plus_minus }, + { "+button0", IN_Button0Down, NULL, "starts firing the gun" help_plus_minus }, + { "-button0", IN_Button0Up, NULL, "stops firing the gun" help_plus_minus }, + { "+button1", IN_Button1Down, NULL, "starts chat stance" help_button1 help_plus_minus }, + { "-button1", IN_Button1Up, NULL, "stops chat stance" help_button1 help_plus_minus }, + { "+button2", IN_Button2Down, NULL, "starts using item" help_plus_minus }, + { "-button2", IN_Button2Up, NULL, "stops using item" help_plus_minus }, + { "+button3", IN_Button3Down, NULL, "starts taunt" help_plus_minus }, + { "-button3", IN_Button3Up, NULL, "stops taunt" help_plus_minus }, + { "+button4", IN_Button4Down }, + { "-button4", IN_Button4Up }, + { "+button5", IN_Button5Down }, + { "-button5", IN_Button5Up }, + { "+button6", IN_Button6Down }, + { "-button6", IN_Button6Up }, + { "+button7", IN_Button7Down }, + { "-button7", IN_Button7Up }, + { "+button8", IN_Button8Down }, + { "-button8", IN_Button8Up }, + { "+button9", IN_Button9Down }, + { "-button9", IN_Button9Up }, + { "+button10", IN_Button10Down }, + { "-button10", IN_Button10Up }, + { "+button11", IN_Button11Down }, + { "-button11", IN_Button11Up }, + { "+button12", IN_Button12Down }, + { "-button12", IN_Button12Up }, + { "+button13", IN_Button13Down }, + { "-button13", IN_Button13Up }, + { "+button14", IN_Button14Down }, + { "-button14", IN_Button14Up }, + { "+button15", IN_Button15Down }, + { "-button15", IN_Button15Up }, + { "+mlook", IN_MLookDown, NULL, "enables free look when cl_freelook is 0" help_plus_minus }, + { "-mlook", IN_MLookUp, NULL, "disables free look when cl_freelook is 0" help_plus_minus } +#undef help_button1 +}; + + +// @TODO: move "in_restart" here and let the platform layer +// implement Sys_InitInput and Sys_ShutdownInput + + void CL_InitInput() { - Cmd_AddCommand ("+moveup",IN_UpDown); - Cmd_AddCommand ("-moveup",IN_UpUp); - Cmd_AddCommand ("+movedown",IN_DownDown); - Cmd_AddCommand ("-movedown",IN_DownUp); - Cmd_AddCommand ("+left",IN_LeftDown); - Cmd_AddCommand ("-left",IN_LeftUp); - Cmd_AddCommand ("+right",IN_RightDown); - Cmd_AddCommand ("-right",IN_RightUp); - Cmd_AddCommand ("+forward",IN_ForwardDown); - Cmd_AddCommand ("-forward",IN_ForwardUp); - Cmd_AddCommand ("+back",IN_BackDown); - Cmd_AddCommand ("-back",IN_BackUp); - Cmd_AddCommand ("+lookup", IN_LookupDown); - Cmd_AddCommand ("-lookup", IN_LookupUp); - Cmd_AddCommand ("+lookdown", IN_LookdownDown); - Cmd_AddCommand ("-lookdown", IN_LookdownUp); - Cmd_AddCommand ("+strafe", IN_StrafeDown); - Cmd_AddCommand ("-strafe", IN_StrafeUp); - Cmd_AddCommand ("+moveleft", IN_MoveleftDown); - Cmd_AddCommand ("-moveleft", IN_MoveleftUp); - Cmd_AddCommand ("+moveright", IN_MoverightDown); - Cmd_AddCommand ("-moveright", IN_MoverightUp); - Cmd_AddCommand ("+speed", IN_SpeedDown); - Cmd_AddCommand ("-speed", IN_SpeedUp); - Cmd_AddCommand ("+attack", IN_Button0Down); - Cmd_AddCommand ("-attack", IN_Button0Up); - Cmd_AddCommand ("+button0", IN_Button0Down); - Cmd_AddCommand ("-button0", IN_Button0Up); - Cmd_AddCommand ("+button1", IN_Button1Down); - Cmd_AddCommand ("-button1", IN_Button1Up); - Cmd_AddCommand ("+button2", IN_Button2Down); - Cmd_AddCommand ("-button2", IN_Button2Up); - Cmd_AddCommand ("+button3", IN_Button3Down); - Cmd_AddCommand ("-button3", IN_Button3Up); - Cmd_AddCommand ("+button4", IN_Button4Down); - Cmd_AddCommand ("-button4", IN_Button4Up); - Cmd_AddCommand ("+button5", IN_Button5Down); - Cmd_AddCommand ("-button5", IN_Button5Up); - Cmd_AddCommand ("+button6", IN_Button6Down); - Cmd_AddCommand ("-button6", IN_Button6Up); - Cmd_AddCommand ("+button7", IN_Button7Down); - Cmd_AddCommand ("-button7", IN_Button7Up); - Cmd_AddCommand ("+button8", IN_Button8Down); - Cmd_AddCommand ("-button8", IN_Button8Up); - Cmd_AddCommand ("+button9", IN_Button9Down); - Cmd_AddCommand ("-button9", IN_Button9Up); - Cmd_AddCommand ("+button10", IN_Button10Down); - Cmd_AddCommand ("-button10", IN_Button10Up); - Cmd_AddCommand ("+button11", IN_Button11Down); - Cmd_AddCommand ("-button11", IN_Button11Up); - Cmd_AddCommand ("+button12", IN_Button12Down); - Cmd_AddCommand ("-button12", IN_Button12Up); - Cmd_AddCommand ("+button13", IN_Button13Down); - Cmd_AddCommand ("-button13", IN_Button13Up); - Cmd_AddCommand ("+button14", IN_Button14Down); - Cmd_AddCommand ("-button14", IN_Button14Up); - Cmd_AddCommand ("+button15", IN_Button15Down); - Cmd_AddCommand ("-button15", IN_Button15Up); - Cmd_AddCommand ("+mlook", IN_MLookDown); - Cmd_AddCommand ("-mlook", IN_MLookUp); - - Cvar_Get( "cl_drawMouseLag", "0", 0 ); - - m_speed = Cvar_Get( "m_speed", "8", CVAR_ARCHIVE ); - m_accel = Cvar_Get( "m_accel", "0", CVAR_ARCHIVE ); - m_accelStyle = Cvar_Get( "m_accelStyle", "0", CVAR_ARCHIVE ); - m_accelOffset = Cvar_Get( "m_accelOffset", "5", CVAR_ARCHIVE ); - m_limit = Cvar_Get( "m_limit", "0", CVAR_ARCHIVE ); - m_pitch = Cvar_Get( "m_pitch", "0.022", CVAR_ARCHIVE ); - m_yaw = Cvar_Get( "m_yaw", "0.022", CVAR_ARCHIVE ); - m_forward = Cvar_Get( "m_forward", "0.25", CVAR_ARCHIVE ); - m_side = Cvar_Get( "m_side", "0.25", CVAR_ARCHIVE ); - -#ifdef MACOS_X - // input is jittery on OS X w/o this - m_filter = Cvar_Get( "m_filter", "1", CVAR_ARCHIVE ); -#else - m_filter = Cvar_Get( "m_filter", "0", CVAR_ARCHIVE ); -#endif - - cl_pitchspeed = Cvar_Get( "cl_pitchspeed", "140", CVAR_ARCHIVE ); - cl_yawspeed = Cvar_Get( "cl_yawspeed", "140", CVAR_ARCHIVE ); - cl_anglespeedkey = Cvar_Get( "cl_anglespeedkey", "1.5", 0 ); - cl_run = Cvar_Get( "cl_run", "1", CVAR_ARCHIVE ); - cl_freelook = Cvar_Get( "cl_freelook", "1", CVAR_ARCHIVE ); - - cl_showMouseRate = Cvar_Get( "cl_showmouserate", "0", 0 ); - cl_nodelta = Cvar_Get( "cl_nodelta", "0", 0 ); - - cl_debugMove = Cvar_Get( "cl_debugMove", "0", 0 ); + Cmd_RegisterArray( cl_cmds, MODULE_INPUT ); + Cvar_RegisterArray( cl_cvars, MODULE_INPUT ); +} + + +void CL_ShutdownInput() +{ + Cmd_UnregisterModule( MODULE_INPUT ); } diff --git a/code/client/cl_keys.cpp b/code/client/cl_keys.cpp index 8427666..03061a5 100644 --- a/code/client/cl_keys.cpp +++ b/code/client/cl_keys.cpp @@ -1144,6 +1144,8 @@ static const cvar_t* con_history; void CL_LoadCommandHistory() { con_history = Cvar_Get( "con_history", "0", CVAR_ARCHIVE ); + Cvar_SetRange( "con_history", CVART_BOOL, NULL, NULL ); + Cvar_SetHelp( "con_history", "writes the command history to a file on exit" ); fileHandle_t f; FS_FOpenFileRead( HISTORY_PATH, &f, qfalse ); diff --git a/code/client/cl_main.cpp b/code/client/cl_main.cpp index 464a7b4..2ddaaff 100644 --- a/code/client/cl_main.cpp +++ b/code/client/cl_main.cpp @@ -22,17 +22,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // cl_main.c -- client main loop #include "client.h" +#include "client_help.h" cvar_t *cl_debugMove; -cvar_t *rcon_client_password; +cvar_t *rconPassword; cvar_t *rconAddress; cvar_t* cl_timeout; cvar_t* cl_maxpackets; cvar_t* cl_packetdup; -cvar_t* cl_timeNudge; cvar_t* cl_showTimeDelta; cvar_t* cl_serverStatusResendTime; cvar_t* cl_shownet; @@ -42,9 +42,6 @@ cvar_t *cl_timedemo; cvar_t *cl_aviFrameRate; cvar_t *cl_aviMotionJpeg; -static cvar_t* cl_motd; -static cvar_t* cl_motdString; - cvar_t *cl_allowDownload; cvar_t *cl_inGameVideo; @@ -571,8 +568,8 @@ static void CL_RequestAuthorization() } key[i] = 0; - const cvar_t* anon = Cvar_Get( "cl_anonymous", "0", CVAR_INIT|CVAR_SYSTEMINFO ); - NET_OutOfBandPrint( NS_CLIENT, cls.authorizeServer, va("getKeyAuthorize %i %s", anon->integer, key) ); + int anonymous = 0; // previously set by cl_anonymous + NET_OutOfBandPrint( NS_CLIENT, cls.authorizeServer, va("getKeyAuthorize %i %s", anonymous, key) ); } @@ -818,42 +815,6 @@ void CL_ForwardCommandToServer( const char *string ) } -static void CL_RequestMotd() -{ - char info[MAX_INFO_STRING]; - - if ( !cl_motd->integer ) { - return; - } - - Com_Printf( "Resolving %s\n", UPDATE_SERVER_NAME ); - if ( !NET_StringToAdr( UPDATE_SERVER_NAME, &cls.updateServer ) ) { - Com_Printf( "Couldn't resolve address\n" ); - return; - } - - cls.updateServer.port = BigShort( PORT_UPDATE ); - Com_Printf( "%s resolved to %i.%i.%i.%i:%i\n", UPDATE_SERVER_NAME, - cls.updateServer.ip[0], cls.updateServer.ip[1], - cls.updateServer.ip[2], cls.updateServer.ip[3], - BigShort( cls.updateServer.port ) ); - - info[0] = 0; - // NOTE TTimo xoring against Com_Milliseconds, otherwise we may not have a qtrue randomization - // only srand I could catch before here is tr_noise.c l:26 srand(1001) - // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=382 - // NOTE: the Com_Milliseconds xoring only affects the lower 16-bit word, - // but I decided it was enough randomization - Com_sprintf( cls.updateChallenge, sizeof( cls.updateChallenge ), "%i", ((rand() << 16) ^ rand()) ^ Com_Milliseconds()); - - Info_SetValueForKey( info, "challenge", cls.updateChallenge ); - Info_SetValueForKey( info, "renderer", cls.glconfig.renderer_string ); - Info_SetValueForKey( info, "version", com_version->string ); - - NET_OutOfBandPrint( NS_CLIENT, cls.updateServer, "getmotd \"%s\"\n", info ); -} - - /* ====================================================================== @@ -902,9 +863,6 @@ static void CL_Connect_f() return; } - // fire a message off to the motd server - CL_RequestMotd(); - // clear any previous "server full" type messages clc.serverMessage[0] = 0; @@ -960,7 +918,7 @@ static void CL_Connect_f() static void CL_Rcon_f( void ) { - if ( !rcon_client_password->string ) { + if ( !rconPassword->string ) { Com_Printf ("You must set 'rconpassword' before\n" "issuing an rcon command.\n"); return; @@ -975,7 +933,7 @@ static void CL_Rcon_f( void ) Q_strcat (message, MAX_RCON_MESSAGE, "rcon "); - Q_strcat (message, MAX_RCON_MESSAGE, rcon_client_password->string); + Q_strcat (message, MAX_RCON_MESSAGE, rconPassword->string); Q_strcat (message, MAX_RCON_MESSAGE, " "); // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=543 @@ -1328,26 +1286,6 @@ static void CL_DisconnectPacket( const netadr_t& from ) } -static void CL_MotdPacket( const netadr_t& from ) -{ - // if not from our server, ignore it - if ( !NET_CompareAdr( from, cls.updateServer ) ) { - return; - } - - const char* s; - const char* info = Cmd_Argv(1); - - s = Info_ValueForKey( info, "challenge" ); - if ( strcmp( s, cls.updateChallenge ) ) - return; - - s = Info_ValueForKey( info, "motd" ); - Q_strncpyz( cls.updateInfoString, info, sizeof( cls.updateInfoString ) ); - Cvar_Set( "cl_motdString", s ); -} - - // responses to broadcasts, etc static void CL_ConnectionlessPacket( const netadr_t& from, msg_t* msg ) @@ -1435,7 +1373,6 @@ static void CL_ConnectionlessPacket( const netadr_t& from, msg_t* msg ) // global MOTD from id if ( !Q_stricmp(c, "motd") ) { - CL_MotdPacket( from ); return; } @@ -1713,17 +1650,29 @@ static void CL_ShutdownRef() if ( !re.Shutdown ) { return; } + Cmd_UnregisterModule( MODULE_RENDERER ); re.Shutdown( qtrue ); Com_Memset( &re, 0, sizeof( re ) ); } +static void RI_Cmd_RegisterTable( const cmdTableItem_t* cmds, int count ) +{ + Cmd_RegisterTable( cmds, count, MODULE_RENDERER ); +} + + +static void RI_Cvar_RegisterTable( const cvarTableItem_t* cvars, int count ) +{ + Cvar_RegisterTable( cvars, count, MODULE_RENDERER ); +} + + static void CL_InitRef() { refimport_t ri; - ri.Cmd_AddCommand = Cmd_AddCommand; - ri.Cmd_RemoveCommand = Cmd_RemoveCommand; + ri.Cmd_RegisterTable = RI_Cmd_RegisterTable; ri.Cmd_Argc = Cmd_Argc; ri.Cmd_Argv = Cmd_Argv; ri.Printf = CL_RefPrintf; @@ -1745,7 +1694,9 @@ static void CL_InitRef() ri.FS_FreeFileList = FS_FreeFileList; ri.FS_ListFiles = FS_ListFiles; ri.Cvar_Get = Cvar_Get; + ri.Cvar_SetHelp = Cvar_SetHelp; ri.Cvar_Set = Cvar_Set; + ri.Cvar_RegisterTable = RI_Cvar_RegisterTable; // cinematic stuff @@ -1836,23 +1787,6 @@ static void CL_Snd_Restart_f() /////////////////////////////////////////////////////////////// -static void CL_SetModel_f() -{ - char name[256]; - const char* arg = Cmd_Argv(1); - - if (arg[0]) { - Cvar_Set( "model", arg ); - } else { - Cvar_VariableStringBuffer( "model", name, sizeof(name) ); - Com_Printf("model is set to %s\n", name); - } -} - - -/////////////////////////////////////////////////////////////// - - static void CL_Video_f() { char s[ MAX_OSPATH ]; @@ -1962,7 +1896,7 @@ static void CL_CompleteCallVote_f( int startArg, int compArg ) Field_AutoCompleteCustom( startArg, compArg, &Field_AutoCompleteMapName ); } - + static void CL_PrintDownloadPakUsage() { Com_Printf( "Usage: %s checksum (signed decimal, '0x' or '0X' prefix for hex)\n", Cmd_Argv(0) ); @@ -2043,6 +1977,65 @@ static void CL_CancelDownload_f() { CL_MapDownload_Cancel(); } + + +static const cvarTableItem_t cl_cvars[] = +{ + { &cl_timeout, "cl_timeout", "200", 0, CVART_INTEGER, "30", "300", "connection time-out, in seconds" }, + { NULL, "cl_timeNudge", "0", CVAR_TEMP, CVART_INTEGER, NULL, NULL, help_cl_timeNudge }, + { &cl_shownet, "cl_shownet", "0", CVAR_TEMP, CVART_INTEGER, "-2", "4", help_cl_shownet }, + { &cl_showSend, "cl_showSend", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, help_cl_showSend }, + { &cl_showTimeDelta, "cl_showTimeDelta", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "prints delta adjustment values and events" }, + { &rconPassword, "rconPassword", "", CVAR_TEMP, CVART_STRING, NULL, NULL, "server password, used by /rcon" }, + { &cl_timedemo, "timedemo", "0", 0, CVART_BOOL, NULL, NULL, "demo benchmarking mode" }, + { &cl_aviFrameRate, "cl_aviFrameRate", "25", CVAR_ARCHIVE, CVART_INTEGER, "1", "250", "frame-rate for /video" }, + { &cl_aviMotionJpeg, "cl_aviMotionJpeg", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "/video stores frames as JPEGs" }, + { &rconAddress, "rconAddress", "", 0, CVART_STRING, NULL, NULL, "IP address of the server to /rcon to" }, + { &cl_maxpackets, "cl_maxpackets", "125", CVAR_ARCHIVE, CVART_INTEGER, "15", "125", "max. packet upload rate" }, + { &cl_packetdup, "cl_packetdup", "1", CVAR_ARCHIVE, CVART_INTEGER, "0", "5", "number of extra transmissions per packet" }, + { &cl_allowDownload, "cl_allowDownload", "1", CVAR_ARCHIVE, CVART_INTEGER, "-1", "1", help_cl_allowDownload }, + { &cl_inGameVideo, "r_inGameVideo", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "enables roq video playback" }, + { &cl_serverStatusResendTime, "cl_serverStatusResendTime", "750", 0, CVART_INTEGER, "500", "1000", "milli-seconds to wait before resending getstatus" }, + { NULL, "cl_maxPing", "999", CVAR_ARCHIVE, CVART_INTEGER, "80", "999", "max. ping for the server browser" }, + { NULL, "name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE, CVART_STRING, NULL, NULL, "your name" }, + { NULL, "rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE, CVART_INTEGER, "4000", "99999", "network transfer rate" }, + { NULL, "snaps", "30", CVAR_USERINFO | CVAR_ARCHIVE, CVART_INTEGER }, // documented by the mod + { NULL, "password", "", CVAR_USERINFO, CVART_STRING, NULL, NULL, "used by /connect" } +}; + + +static const cmdTableItem_t cl_cmds[] = +{ + { "cmd", CL_ForwardToServer_f, NULL, "forwards all arguments as a command to the server" }, + { "configstrings", CL_Configstrings_f, NULL, "prints all non-empty config strings" }, + { "clientinfo", CL_Clientinfo_f, NULL, "prints some client settings" }, + { "snd_restart", CL_Snd_Restart_f, NULL, "restarts the sound system" }, + { "vid_restart", CL_Vid_Restart_f, NULL, "restarts the video system" }, + { "disconnect", CL_Disconnect_f, NULL, "disconnects from the current server" }, + { "record", CL_Record_f, CL_CompleteDemoRecord_f, "starts recording a demo" }, + { "demo", CL_PlayDemo_f, CL_CompleteDemoPlay_f, "starts demo playback" }, + { "cinematic", CL_PlayCinematic_f, NULL, "starts playback of a .roq video file" }, + { "stoprecord", CL_StopRecord_f, NULL, "stops demo recording" }, + { "connect", CL_Connect_f, NULL, "connects to a server" }, + { "reconnect", CL_Reconnect_f, NULL, "reconnects to the current or last server" }, + { "localservers", CL_LocalServers_f, NULL, "finds and prints local LAN servers" }, + { "globalservers", CL_GlobalServers_f, NULL, "requests server lists from master servers" }, + { "rcon", CL_Rcon_f, CL_CompleteRcon_f, "executes the arguments as a command on the server" }, + { "ping", CL_Ping_f, NULL, "pings a server" }, + { "serverstatus", CL_ServerStatus_f, NULL, "prints server status and player list" }, + { "showip", CL_ShowIP_f, NULL, "shows your open IP address(es)" }, + { "fs_referencedList", CL_ReferencedPK3List_f, NULL, "prints the names of referenced pak files" }, + { "video", CL_Video_f, NULL, "starts writing a .avi file" }, + { "stopvideo", CL_StopVideo_f, NULL, "stops writing the .avi file" }, + { "dlpak", CL_DownloadPak_f, NULL, "starts a pk3 download by checksum if not existing" }, + { "dlmap", CL_DownloadMap_f, NULL, "starts a pk3 download by map name if not existing" }, + { "dlmapf", CL_ForceDownloadMap_f, NULL, "start a pk3 download by map name" }, + { "dlstop", CL_CancelDownload_f, NULL, "stops the current pk3 download" }, + + // we use these until we get proper handling on the mod side + { "cv", CL_CallVote_f, CL_CompleteCallVote_f, "calls a vote" }, + { "callvote", CL_CallVote_f, CL_CompleteCallVote_f, "calls a vote" } +}; void CL_Init() @@ -2058,87 +2051,9 @@ void CL_Init() cls.realtime = 0; CL_InitInput(); - - // register our variables - // - cl_timeout = Cvar_Get ("cl_timeout", "200", 0); - - cl_timeNudge = Cvar_Get ("cl_timeNudge", "0", CVAR_TEMP ); - cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_TEMP ); - cl_showSend = Cvar_Get ("cl_showSend", "0", CVAR_TEMP ); - cl_showTimeDelta = Cvar_Get ("cl_showTimeDelta", "0", CVAR_TEMP ); - rcon_client_password = Cvar_Get ("rconPassword", "", CVAR_TEMP ); - - cl_timedemo = Cvar_Get ("timedemo", "0", 0); - cl_aviFrameRate = Cvar_Get ("cl_aviFrameRate", "25", CVAR_ARCHIVE); - cl_aviMotionJpeg = Cvar_Get ("cl_aviMotionJpeg", "1", CVAR_ARCHIVE); - - rconAddress = Cvar_Get ("rconAddress", "", 0); - - cl_maxpackets = Cvar_Get ("cl_maxpackets", "30", CVAR_ARCHIVE ); - cl_packetdup = Cvar_Get ("cl_packetdup", "1", CVAR_ARCHIVE ); - - cl_allowDownload = Cvar_Get ("cl_allowDownload", "1", CVAR_ARCHIVE); - -#ifdef MACOS_X - // In game video is REALLY slow in Mac OS X right now due to driver slowness - cl_inGameVideo = Cvar_Get ("r_inGameVideo", "0", CVAR_ARCHIVE); -#else - cl_inGameVideo = Cvar_Get ("r_inGameVideo", "1", CVAR_ARCHIVE); -#endif - - cl_serverStatusResendTime = Cvar_Get ("cl_serverStatusResendTime", "750", 0); - - cl_motd = Cvar_Get( "cl_motd", "1", 0 ); - cl_motdString = Cvar_Get( "cl_motdString", "", CVAR_ROM ); - - Cvar_Get( "cl_maxPing", "800", CVAR_ARCHIVE ); - - - // userinfo - Cvar_Get ("name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("rate", "3000", CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("cl_anonymous", "0", CVAR_USERINFO | CVAR_ARCHIVE ); - Cvar_Get ("password", "", CVAR_USERINFO); - - // register our commands - // - Cmd_AddCommand ("cmd", CL_ForwardToServer_f); - Cmd_AddCommand ("configstrings", CL_Configstrings_f); - Cmd_AddCommand ("clientinfo", CL_Clientinfo_f); - Cmd_AddCommand ("snd_restart", CL_Snd_Restart_f); - Cmd_AddCommand ("vid_restart", CL_Vid_Restart_f); - Cmd_AddCommand ("disconnect", CL_Disconnect_f); - Cmd_AddCommand ("record", CL_Record_f); - Cmd_SetAutoCompletion ("record", CL_CompleteDemoRecord_f); - Cmd_AddCommand ("demo", CL_PlayDemo_f); - Cmd_SetAutoCompletion ("demo", CL_CompleteDemoPlay_f); - Cmd_AddCommand ("cinematic", CL_PlayCinematic_f); - Cmd_AddCommand ("stoprecord", CL_StopRecord_f); - Cmd_AddCommand ("connect", CL_Connect_f); - Cmd_AddCommand ("reconnect", CL_Reconnect_f); - Cmd_AddCommand ("localservers", CL_LocalServers_f); - Cmd_AddCommand ("globalservers", CL_GlobalServers_f); - Cmd_AddCommand ("rcon", CL_Rcon_f); - Cmd_SetAutoCompletion ("rcon", CL_CompleteRcon_f); - Cmd_AddCommand ("ping", CL_Ping_f ); - Cmd_AddCommand ("serverstatus", CL_ServerStatus_f ); - Cmd_AddCommand ("showip", CL_ShowIP_f ); - Cmd_AddCommand ("fs_referencedList", CL_ReferencedPK3List_f ); - Cmd_AddCommand ("model", CL_SetModel_f ); - Cmd_AddCommand ("video", CL_Video_f ); - Cmd_AddCommand ("stopvideo", CL_StopVideo_f ); - Cmd_AddCommand ("dlpak", CL_DownloadPak_f ); - Cmd_AddCommand ("dlmap", CL_DownloadMap_f ); - Cmd_AddCommand ("dlmapf", CL_ForceDownloadMap_f ); - Cmd_AddCommand ("dlstop", CL_CancelDownload_f ); - - // we use these until we get proper handling on the mod side - Cmd_AddCommand ("cv", CL_CallVote_f ); - Cmd_AddCommand ("callvote", CL_CallVote_f ); - Cmd_SetAutoCompletion ("cv", CL_CompleteCallVote_f ); - Cmd_SetAutoCompletion ("callvote", CL_CompleteCallVote_f ); + + Cvar_RegisterArray( cl_cvars, MODULE_CLIENT ); + Cmd_RegisterArray( cl_cmds, MODULE_CLIENT ); CL_InitRef(); @@ -2173,42 +2088,19 @@ void CL_Shutdown() CL_Disconnect( qtrue ); S_Shutdown(); + + CL_ShutdownInput(); + CL_ShutdownRef(); CL_ShutdownUI(); CL_SaveCommandHistory(); CL_MapDownload_Cancel(); + + Cmd_UnregisterModule( MODULE_CLIENT ); - Cmd_RemoveCommand ("cmd"); - Cmd_RemoveCommand ("configstrings"); - Cmd_RemoveCommand ("userinfo"); - Cmd_RemoveCommand ("snd_restart"); - Cmd_RemoveCommand ("vid_restart"); - Cmd_RemoveCommand ("disconnect"); - Cmd_RemoveCommand ("record"); - Cmd_RemoveCommand ("demo"); - Cmd_RemoveCommand ("cinematic"); - Cmd_RemoveCommand ("stoprecord"); - Cmd_RemoveCommand ("connect"); - Cmd_RemoveCommand ("localservers"); - Cmd_RemoveCommand ("globalservers"); - Cmd_RemoveCommand ("rcon"); - Cmd_RemoveCommand ("setenv"); - Cmd_RemoveCommand ("ping"); - Cmd_RemoveCommand ("serverstatus"); - Cmd_RemoveCommand ("showip"); - Cmd_RemoveCommand ("model"); - Cmd_RemoveCommand ("video"); - Cmd_RemoveCommand ("stopvideo"); - Cmd_RemoveCommand ("dlpak"); - Cmd_RemoveCommand ("dlmap"); - Cmd_RemoveCommand ("dlmapf"); - Cmd_RemoveCommand ("dlstop"); - - // we use these until we get proper handling on the mod side - Cmd_RemoveCommand ("cv"); - Cmd_RemoveCommand ("callvote"); + CL_ConShutdown(); Cvar_Set( "cl_running", "0" ); diff --git a/code/client/cl_ui.cpp b/code/client/cl_ui.cpp index 3309be9..646dd7c 100644 --- a/code/client/cl_ui.cpp +++ b/code/client/cl_ui.cpp @@ -753,14 +753,20 @@ static int GetConfigString(int index, char *buf, int size) static qbool CL_UI_GetValue( char* value, int valueSize, const char* key ) { - if( Q_stricmp(key, "trap_LocateInteropData") == 0 ) { - Com_sprintf( value, valueSize, "%d", UI_EXT_LOCATEINTEROPDATA ); - return qtrue; - } + struct syscall_t { const char* name; int number; }; + static const syscall_t syscalls[] = { + { "trap_LocateInteropData", UI_EXT_LOCATEINTEROPDATA }, + { "trap_R_AddRefEntityToScene2", UI_EXT_R_ADDREFENTITYTOSCENE2 }, + { "trap_Cvar_SetRange", UI_EXT_CVAR_SETRANGE }, + { "trap_Cvar_SetHelp", UI_EXT_CVAR_SETHELP }, + { "trap_Cmd_SetHelp", UI_EXT_CMD_SETHELP } + }; - if( Q_stricmp(key, "trap_R_AddRefEntityToScene2") == 0 ) { - Com_sprintf( value, valueSize, "%d", UI_EXT_R_ADDREFENTITYTOSCENE2 ); - return qtrue; + for ( int i = 0; i < ARRAY_LEN( syscalls ); ++i ) { + if( Q_stricmp(key, syscalls[i].name) == 0 ) { + Com_sprintf( value, valueSize, "%d", syscalls[i].number ); + return qtrue; + } } return qfalse; @@ -788,6 +794,7 @@ static intptr_t CL_UISystemCalls( intptr_t* args ) case UI_CVAR_REGISTER: Cvar_Register( VMA(1), VMA(2), VMA(3), args[4] ); + Cvar_SetModule( VMA(2), MODULE_UI ); return 0; case UI_CVAR_UPDATE: @@ -1115,6 +1122,18 @@ static intptr_t CL_UISystemCalls( intptr_t* args ) re.AddRefEntityToScene( VMA(1), qtrue ); return 0; + case UI_EXT_CVAR_SETRANGE: + Cvar_SetRange( VMA(1), (cvarType_t)args[2], VMA(3), VMA(4) ); + return 0; + + case UI_EXT_CVAR_SETHELP: + Cvar_SetHelp( VMA(1), VMA(2) ); + return 0; + + case UI_EXT_CMD_SETHELP: + Cmd_SetHelp( VMA(1), VMA(2) ); + return 0; + default: Com_Error( ERR_DROP, "Bad UI system trap: %i", args[0] ); } diff --git a/code/client/client.h b/code/client/client.h index 9865cad..76c84f9 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -318,7 +318,6 @@ extern cvar_t *cl_maxpackets; extern cvar_t *cl_packetdup; extern cvar_t *cl_shownet; extern cvar_t *cl_showSend; -extern cvar_t *cl_timeNudge; extern cvar_t *cl_showTimeDelta; extern cvar_t *cl_serverStatusResendTime; @@ -372,6 +371,7 @@ void CL_ServerStatusResponse( const netadr_t& from, msg_t *msg ); // cl_input // void CL_InitInput(); +void CL_ShutdownInput(); void CL_SendCmd(); void CL_ClearState(); @@ -400,6 +400,7 @@ qbool CL_UpdateVisiblePings_f( int source ); // console // void CL_ConInit(); +void CL_ConShutdown(); void Con_ToggleConsole_f(); void Con_ClearNotify(); void Con_RunConsole(); diff --git a/code/client/client_help.h b/code/client/client_help.h new file mode 100644 index 0000000..5362cd2 --- /dev/null +++ b/code/client/client_help.h @@ -0,0 +1,42 @@ +#define help_cl_timeNudge \ +"id's crippled timenudge\n" \ +"This still exists in CPMA, but should always be 0.\n" \ +"All it really does now is mess up the automatic adaptive nudges." + +#define help_cl_shownet \ +"prints network info\n" \ +" -2 = commandTime\n" \ +" -1 = entity removed/changed events\n" \ +" 0 = disabled\n" \ +" 1 = message lengths\n" \ +" 2 = message types, commandTime, etc\n" \ +" 3 = 2 + entity parsing details\n" \ +" 4 = 2 + player state details" + +#define help_cl_showSend \ +"prints client to server packet info\n" \ +"format: (usercmd_count) packet_size\n" \ +"each dot symbolizes a frame of delay" + +#define help_cl_allowDownload \ +"selects the download system\n" \ +" -1 = id's old download system\n" \ +" 0 = downloads disabled\n" \ +" 1 = CNQ3's new download system" + +#define help_con_scaleMode \ +"console text scaling mode\n" \ +" 0 = text size scales with con_scale but not the resolution\n" \ +" 1 = text size scales with con_scale and the resolution\n" \ +" 2 = text size is always 8x12" + +#define help_plus_minus \ +"\nAbout commands starting with '+' or '-':\n" \ +"- If '+cmdname' is called from a bind, the command is executed every frame until the bind key is released.\n" \ +"- If '+cmdname' is not called from a bind, the command is executed every frame until '-cmdname' is called." + +#define help_cl_debugMove \ +"prints a graph of view angle deltas\n" \ +" 0 = disabled\n" \ +" 1 = horizontal axis\n" \ +" 2 = vertical axis" diff --git a/code/client/snd_dma.cpp b/code/client/snd_dma.cpp index e95b850..a6d48d1 100644 --- a/code/client/snd_dma.cpp +++ b/code/client/snd_dma.cpp @@ -61,10 +61,10 @@ static int s_numSfx; #define SFX_HASH_SIZE 128 static sfx_t* sfxHash[SFX_HASH_SIZE]; -static const cvar_t* s_show; -static const cvar_t* s_mixahead; -static const cvar_t* s_mixPreStep; -const cvar_t* s_testsound; +static cvar_t* s_show; +static cvar_t* s_mixahead; +static cvar_t* s_mixPreStep; +cvar_t* s_testsound; static loopSound_t loopSounds[MAX_GENTITIES]; static channel_t *freelist = NULL; @@ -1098,14 +1098,20 @@ static void S_Base_Shutdown() } +static const cvarTableItem_t cl_cvars[] = +{ + { &s_mixahead, "s_mixahead", "0.2", CVAR_ARCHIVE, CVART_FLOAT }, + { &s_mixPreStep, "s_mixPreStep", "0.05", CVAR_ARCHIVE, CVART_FLOAT }, + { &s_show, "s_show", "0", CVAR_CHEAT, CVART_INTEGER, "0", "2" }, + { &s_testsound, "s_testsound", "0", CVAR_CHEAT, CVART_BOOL } +}; + + qbool S_Base_Init( soundInterface_t *si ) { Com_Memset( si, 0, sizeof(*si) ); - s_mixahead = Cvar_Get( "s_mixahead", "0.2", CVAR_ARCHIVE ); - s_mixPreStep = Cvar_Get( "s_mixPreStep", "0.05", CVAR_ARCHIVE ); - s_show = Cvar_Get( "s_show", "0", CVAR_CHEAT ); - s_testsound = Cvar_Get( "s_testsound", "0", CVAR_CHEAT ); + Cvar_RegisterArray( cl_cvars, MODULE_SOUND ); if (!SNDDMA_Init()) return qfalse; diff --git a/code/client/snd_local.h b/code/client/snd_local.h index 6410227..f4145dc 100644 --- a/code/client/snd_local.h +++ b/code/client/snd_local.h @@ -140,7 +140,7 @@ extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES]; extern cvar_t *s_volume; extern cvar_t *s_musicVolume; -extern const cvar_t* s_testsound; +extern cvar_t *s_testsound; qbool S_LoadSound( sfx_t* sfx ); diff --git a/code/client/snd_main.cpp b/code/client/snd_main.cpp index f62bb81..46d4ace 100644 --- a/code/client/snd_main.cpp +++ b/code/client/snd_main.cpp @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA cvar_t *s_volume; cvar_t *s_musicVolume; +cvar_t *s_initsound; static soundInterface_t si; @@ -230,16 +231,31 @@ static void S_Music_f( void ) /////////////////////////////////////////////////////////////// +static const cvarTableItem_t cl_cvars[] = +{ + { &s_volume, "s_volume", "0.8", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "global sound volume" }, + { &s_musicVolume, "s_musicvolume", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "16", "music volume" }, + { &s_initsound, "s_initsound", "1", 0, CVART_BOOL, NULL, NULL, "enables the audio system" } +}; + + +static const cmdTableItem_t cl_cmds[] = +{ + { "play", S_Play_f, NULL, "starts local sound playback" }, + { "music", S_Music_f, NULL, "starts music playback" }, + { "s_list", S_SoundList, NULL, "lists loaded sounds" }, + { "s_stop", S_StopAllSounds, NULL, "stops all sound playbacks" }, + { "s_info", S_SoundInfo, NULL, "prints sound system info" } +}; + + void S_Init() { QSUBSYSTEM_INIT_START( "Sound" ); - s_volume = Cvar_Get( "s_volume", "0.8", CVAR_ARCHIVE ); - s_musicVolume = Cvar_Get( "s_musicvolume", "0.25", CVAR_ARCHIVE ); - Cmd_AddCommand( "s_info", S_SoundInfo ); + Cvar_RegisterArray( cl_cvars, MODULE_SOUND ); - const cvar_t* cv = Cvar_Get( "s_initsound", "1", 0 ); - if ( !cv->integer ) { + if ( !s_initsound->integer ) { Com_Memset( &si, 0, sizeof(si) ); Com_Printf( "Sound disabled.\n" ); return; @@ -247,10 +263,7 @@ void S_Init() S_CodecInit(); - Cmd_AddCommand( "play", S_Play_f ); - Cmd_AddCommand( "music", S_Music_f ); - Cmd_AddCommand( "s_list", S_SoundList ); - Cmd_AddCommand( "s_stop", S_StopAllSounds ); + Cmd_RegisterArray( cl_cmds, MODULE_SOUND ); if (!S_Base_Init( &si )) { Com_Printf( "Sound initialization failed.\n" ); @@ -273,11 +286,7 @@ void S_Shutdown() Com_Memset( &si, 0, sizeof(si) ); - Cmd_RemoveCommand( "play" ); - Cmd_RemoveCommand( "music" ); - Cmd_RemoveCommand( "s_list" ); - Cmd_RemoveCommand( "s_stop" ); - Cmd_RemoveCommand( "s_info" ); + Cmd_UnregisterModule( MODULE_SOUND ); S_CodecShutdown(); } diff --git a/code/client/snd_mem.cpp b/code/client/snd_mem.cpp index c1be20f..1d1e74e 100644 --- a/code/client/snd_mem.cpp +++ b/code/client/snd_mem.cpp @@ -61,6 +61,8 @@ void SND_setup() // a sndBuffer is actually 2K+, so this isn't even REMOTELY close to actual megs const cvar_t* cv = Cvar_Get( "com_soundMegs", DEF_COMSOUNDMEGS, CVAR_LATCH | CVAR_ARCHIVE ); + Cvar_SetRange( "com_soundMegs", CVART_INTEGER, "1", "64" ); + Cvar_SetHelp( "com_soundMegs", "sound system buffer size [MB]" ); int scs = cv->integer * 1024; sndbuffers = (sndBuffer*)Hunk_Alloc( scs * sizeof(sndBuffer), h_high ); diff --git a/code/qcommon/cg_public.h b/code/qcommon/cg_public.h index 14cc5b8..3008e46 100644 --- a/code/qcommon/cg_public.h +++ b/code/qcommon/cg_public.h @@ -183,7 +183,10 @@ typedef enum { CG_EXT_LOCATEINTEROPDATA, CG_EXT_R_ADDREFENTITYTOSCENE2, CG_EXT_R_FORCEFIXEDDLIGHTS, - CG_EXT_SETINPUTFORWARDING + CG_EXT_SETINPUTFORWARDING, + CG_EXT_CVAR_SETRANGE, + CG_EXT_CVAR_SETHELP, + CG_EXT_CMD_SETHELP } cgameImport_t; diff --git a/code/qcommon/cmd.cpp b/code/qcommon/cmd.cpp index f791c22..1e84a27 100644 --- a/code/qcommon/cmd.cpp +++ b/code/qcommon/cmd.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "q_shared.h" #include "qcommon.h" +#include "common_help.h" #define MAX_CMD_BUFFER 32768 #define MAX_CMD_LINE 1024 @@ -51,6 +52,83 @@ static void Cmd_Wait_f( void ) } +static void Cmd_Help_f() +{ + const char* const arg0 = Cmd_Argv( 0 ); + if ( Cmd_Argc() != 2 ) { + Com_Printf( "usage: %s cvarname|cmdname\n", arg0 ); + return; + } + + const char* const arg1 = Cmd_Argv(1); + if ( !Q_stricmp( arg0, "man" ) && !Q_stricmp( arg1, "woman" ) ) { + Com_Printf( "yeah... no\n" ); + return; + } + + qbool isCvar = qfalse; + const char *desc; + const char *help; + module_t firstModule; + int moduleMask; + if ( Cvar_GetHelp( &desc, &help, arg1 ) ) { + isCvar = qtrue; + Cvar_GetModuleInfo( &firstModule, &moduleMask, arg1 ); + } else if ( Cmd_GetHelp( &desc, &help, arg1 ) ) { + Cmd_GetModuleInfo( &firstModule, &moduleMask, arg1 ); + } else { + Com_Printf( "found no cvar/command with the name '%s'\n", arg1 ); + return; + } + + if ( isCvar ) { + Cvar_PrintTypeAndRange( arg1 ); + } + + Com_PrintModules( firstModule, moduleMask ); + + if ( !desc ) { + Com_Printf( "no help text found for %s '%s'\n", isCvar ? "cvar" : "command", arg1 ); + return; + } + + const char firstLetter = toupper( *desc ); + Com_Printf( COLOR_HELP"%c%s.\n", firstLetter, desc + 1 ); + if ( help ) + Com_Printf( COLOR_HELP"%s\n", help ); +} + + +static void Cmd_PrintSearchResult( const char *name, const char *desc, const char *help, const char *pattern ) +{ + if ( Q_stristr(name, pattern) || (desc && Q_stristr(desc, pattern)) || (help && Q_stristr(help, pattern)) ) { + if ( desc ) + Com_Printf( " %s - %s\n", name, desc ); + else + Com_Printf( " %s\n", name ); + } +} + + +static void Cmd_SearchHelp_f() +{ + if ( Cmd_Argc() != 2 ) { + Com_Printf( "usage: %s string_pattern\n", Cmd_Argv( 0 ) ); + return; + } + + Cmd_EnumHelp( Cmd_PrintSearchResult, Cmd_Argv( 1 ) ); + Cvar_EnumHelp( Cmd_PrintSearchResult, Cmd_Argv( 1 ) ); +} + + +static void Cmd_CompleteHelp_f( int startArg, int compArg ) +{ + if ( compArg == startArg + 1 ) + Field_AutoCompleteFrom( compArg, compArg, qtrue, qtrue ); +} + + void Cbuf_Init() { cmd_text.data = cmd_text_buf; @@ -228,9 +306,12 @@ typedef struct cmd_function_s { struct cmd_function_s *next; char *name; + char *desc; + char *help; xcommand_t function; xcommandCompletion_t completion; - qbool cgame; // registered by cgame? + module_t firstModule; + int moduleMask; } cmd_function_t; @@ -453,12 +534,6 @@ void Cmd_TokenizeStringIgnoreQuotes( const char* text ) void Cmd_AddCommand( const char* cmd_name, xcommand_t function ) -{ - Cmd_AddCommandEx( cmd_name, function, qfalse ); -} - - -void Cmd_AddCommandEx( const char* cmd_name, xcommand_t function, qbool cgame ) { cmd_function_t* cmd; @@ -478,7 +553,10 @@ void Cmd_AddCommandEx( const char* cmd_name, xcommand_t function, qbool cgame ) cmd->name = CopyString( cmd_name ); cmd->function = function; cmd->completion = NULL; - cmd->cgame = cgame; + cmd->firstModule = MODULE_NONE; + cmd->moduleMask = 0; + cmd->desc = NULL; + cmd->help = NULL; // add the command if ( cmd_functions == NULL || Q_stricmp(cmd_functions->name, cmd_name) > 0 ) { @@ -507,6 +585,18 @@ void Cmd_AddCommandEx( const char* cmd_name, xcommand_t function, qbool cgame ) } +static void Cmd_Free( cmd_function_t* cmd ) +{ + if ( cmd->name ) + Z_Free( cmd->name ); + if ( cmd->desc ) + Z_Free( cmd->desc ); + if ( cmd->help ) + Z_Free( cmd->help ); + Z_Free( cmd ); +} + + void Cmd_RemoveCommand( const char* cmd_name ) { cmd_function_t** back = &cmd_functions; @@ -519,10 +609,7 @@ void Cmd_RemoveCommand( const char* cmd_name ) } if ( !strcmp( cmd_name, cmd->name ) ) { *back = cmd->next; - if ( cmd->name ) { - Z_Free( cmd->name ); - } - Z_Free( cmd ); + Cmd_Free( cmd ); return; } back = &cmd->next; @@ -530,28 +617,33 @@ void Cmd_RemoveCommand( const char* cmd_name ) } -void Cmd_RemoveCGameCommands() +void Cmd_SetHelp( const char* cmd_name, const char* cmd_help ) { - cmd_function_t** back = &cmd_functions; - - for(;;) { - cmd_function_t* const cmd = *back; - if ( !cmd ) - break; - - if ( !cmd->cgame ) { - back = &cmd->next; - continue; + cmd_function_t* cmd; + for ( cmd = cmd_functions; cmd; cmd = cmd->next ) { + if ( !strcmp( cmd_name, cmd->name ) ) { + Help_AllocSplitText( &cmd->desc, &cmd->help, cmd_help ); + return; } - - *back = cmd->next; - if ( cmd->name ) - Z_Free( cmd->name ); - Z_Free( cmd ); } } +qbool Cmd_GetHelp( const char** desc, const char** help, const char* cmd_name ) +{ + cmd_function_t* cmd; + for ( cmd = cmd_functions; cmd; cmd = cmd->next ) { + if ( !strcmp( cmd_name, cmd->name ) ) { + *desc = cmd->desc; + *help = cmd->help; + return qtrue; + } + } + + return qfalse; +} + + void Cmd_SetAutoCompletion( const char* cmd_name, xcommandCompletion_t completion ) { cmd_function_t* cmd; @@ -586,6 +678,18 @@ void Cmd_CommandCompletion( void(*callback)(const char* s) ) } +void Cmd_EnumHelp( search_callback_t callback, const char* pattern ) +{ + if ( pattern == NULL || *pattern == '\0' ) + return; + + cmd_function_t* cmd; + for ( cmd = cmd_functions; cmd; cmd = cmd->next) { + callback( cmd->name, cmd->desc, cmd->help, pattern ); + } +} + + // a complete command line has been parsed, so try to execute it void Cmd_ExecuteString( const char* text ) @@ -657,14 +761,85 @@ static void Cmd_List_f() } +static const cmdTableItem_t cl_cmds[] = +{ + { "cmdlist", Cmd_List_f, NULL, help_cmdlist }, + { "exec", Cmd_Exec_f, Cmd_CompleteExec_f, "executes all commands in a text file" }, + { "vstr", Cmd_Vstr_f, Cmd_CompleteVstr_f, "executes the string value of a cvar" }, + { "echo", Cmd_Echo_f, NULL, "prints the arguments to the console" }, + { "wait", Cmd_Wait_f, NULL, "delays command execution by N frames" }, + { "help", Cmd_Help_f, Cmd_CompleteHelp_f, "displays the help of a cvar or command" }, + { "man", Cmd_Help_f, Cmd_CompleteHelp_f, "displays the help of a cvar or command" }, + { "searchhelp", Cmd_SearchHelp_f, NULL, "lists all cvars+cmds whose help matches" } +}; + + void Cmd_Init() { - Cmd_AddCommand( "cmdlist", Cmd_List_f ); - Cmd_AddCommand( "exec", Cmd_Exec_f ); - Cmd_SetAutoCompletion( "exec", Cmd_CompleteExec_f ); - Cmd_AddCommand( "vstr", Cmd_Vstr_f ); - Cmd_SetAutoCompletion( "vstr", Cmd_CompleteVstr_f ); - Cmd_AddCommand( "echo", Cmd_Echo_f ); - Cmd_AddCommand( "wait", Cmd_Wait_f ); + Cmd_RegisterArray( cl_cmds, MODULE_COMMON ); +} + + +void Cmd_RegisterTable( const cmdTableItem_t* cmds, int count, module_t module ) +{ + for ( int i = 0; i < count; ++i ) { + const cmdTableItem_t* item = &cmds[i]; + + Cmd_AddCommand( item->name, item->function ); + + if ( item->completion ) + Cmd_SetAutoCompletion( item->name, item->completion ); + + if ( item->help ) + Cmd_SetHelp( item->name, item->help ); + + Cmd_SetModule( item->name, module ); + } +} + + +void Cmd_SetModule( const char* cmd_name, module_t module ) +{ + cmd_function_t* cmd; + for ( cmd = cmd_functions; cmd; cmd = cmd->next ) { + if ( !strcmp( cmd_name, cmd->name ) ) { + cmd->moduleMask |= 1 << (int)module; + if ( cmd->firstModule == MODULE_NONE ) + cmd->firstModule = module; + return; + } + } +} + + +void Cmd_UnregisterModule( module_t module ) +{ + if ( module <= MODULE_NONE || module >= MODULE_COUNT ) + return; + + cmd_function_t* cmd = cmd_functions; + while( cmd ) { + if ( cmd->firstModule == module && cmd->moduleMask == 1 << (int)module ) { + cmd_function_t* next; + next = cmd->next; + Cmd_RemoveCommand( cmd->name ); + cmd = next; + } else { + cmd = cmd->next; + } + } +} + + +void Cmd_GetModuleInfo( module_t* firstModule, int* moduleMask, const char* cmd_name ) +{ + cmd_function_t* cmd; + for ( cmd = cmd_functions; cmd; cmd = cmd->next ) { + if ( !strcmp( cmd_name, cmd->name ) ) { + *firstModule = cmd->firstModule; + *moduleMask = cmd->moduleMask; + return; + } + } } diff --git a/code/qcommon/common.cpp b/code/qcommon/common.cpp index 39b8664..91f2fa5 100644 --- a/code/qcommon/common.cpp +++ b/code/qcommon/common.cpp @@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "q_shared.h" #include "qcommon.h" +#include "common_help.h" #include #if (_MSC_VER >= 1400) // Visual C++ 2005 or later @@ -47,8 +48,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define MIN_COMHUNKMEGS 56 #define DEF_COMHUNKMEGS 64 #define DEF_COMZONEMEGS 24 -#define XSTRING(x) STRING(x) -#define STRING(x) #x #define DEF_COMHUNKMEGS_S XSTRING(DEF_COMHUNKMEGS) #define DEF_COMZONEMEGS_S XSTRING(DEF_COMZONEMEGS) @@ -56,9 +55,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA static jmp_buf abortframe; // an ERR_DROP occured, exit the entire frame -static fileHandle_t logfile = 0; -static fileHandle_t com_journalFile = 0; // events are written here -fileHandle_t com_journalDataFile = 0; // config files are written here +static fileHandle_t logfile = 0; +static fileHandle_t com_journalFile = 0; // events are written here +fileHandle_t com_journalDataFile = 0; // config files are written here cvar_t *com_viewlog = 0; cvar_t *com_speeds = 0; @@ -74,8 +73,6 @@ cvar_t *com_cl_running = 0; cvar_t *com_logfile = 0; // 1 = buffer log, 2 = flush after each print cvar_t *com_showtrace = 0; cvar_t *com_version = 0; -cvar_t *com_buildScript = 0; // for automated data building scripts -cvar_t *com_introPlayed = 0; cvar_t *cl_paused = 0; cvar_t *sv_paused = 0; cvar_t *cl_packetdelay = 0; @@ -230,12 +227,6 @@ void QDECL Com_Error( int code, const char *fmt, ... ) static int lastErrorTime; static int errorCount; - // when we are running automated scripts, make sure we - // know if anything failed - if ( com_buildScript && com_buildScript->integer ) { - code = ERR_FATAL; - } - // make sure we can get at our local stuff FS_PureServerSetLoadedPaks( "" ); @@ -1253,10 +1244,10 @@ static void Com_InitZoneMemory() //FIXME: 05/01/06 com_zoneMegs is useless right now as neither q3config.cfg nor // Com_StartupVariable have been executed by this point. The net result is that // s_zoneTotal will always be set to the default value. + // myT: removed com_zoneMegs for now // allocate the random block zone - const cvar_t* cv = Cvar_Get( "com_zoneMegs", DEF_COMZONEMEGS_S, CVAR_LATCH | CVAR_ARCHIVE ); - s_zoneTotal = 1024 * 1024 * max( DEF_COMZONEMEGS, cv->integer ); + s_zoneTotal = 1024 * 1024 * DEF_COMZONEMEGS; mainzone = (memzone_t*)calloc( s_zoneTotal, 1 ); if ( !mainzone ) @@ -1341,6 +1332,19 @@ void Hunk_SmallLog( void ) #endif +static const cmdTableItem_t hunk_cmds[] = +{ + { "meminfo", Com_Meminfo_f, NULL, "prints memory allocation info" }, +#ifdef ZONE_DEBUG + { "zonelog", Z_LogHeap }, +#endif +#ifdef HUNK_DEBUG + { "hunklog", Hunk_Log }, + { "hunksmalllog", Hunk_SmallLog } +#endif +}; + + static void Com_InitHunkMemory() { // make sure the file system has allocated and "not" freed any temp blocks @@ -1352,8 +1356,11 @@ static void Com_InitHunkMemory() // allocate the stack based hunk allocator const cvar_t* cv = Cvar_Get( "com_hunkMegs", DEF_COMHUNKMEGS_S, CVAR_LATCH | CVAR_ARCHIVE ); + if (com_dedicated && com_dedicated->integer) + Cvar_SetRange( "com_hunkMegs", CVART_INTEGER, XSTRING(MIN_DEDICATED_COMHUNKMEGS), "256" ); + else + Cvar_SetRange( "com_hunkMegs", CVART_INTEGER, XSTRING(MIN_COMHUNKMEGS), "256" ); - // if we are not dedicated min allocation is 56, otherwise min is 1 int nMinAlloc; const char* s; if (com_dedicated && com_dedicated->integer) { @@ -1374,7 +1381,7 @@ static void Com_InitHunkMemory() #if defined( _MSC_VER ) && defined( _DEBUG ) && defined( idx64 ) // try to allocate at the highest possible address range to help detect errors during development s_hunkData = (byte*)VirtualAlloc( NULL, ( s_hunkTotal + 4095 ) & ( ~4095 ), MEM_COMMIT | MEM_TOP_DOWN, PAGE_READWRITE ); - Cvar_Get( "sys_hunkBaseAddress", va( "%p", s_hunkData ), 0 ); + Cvar_Get( "sys_hunkBaseAddress", va( "%p", s_hunkData ), CVAR_ROM ); #else s_hunkData = (byte*)calloc( s_hunkTotal + 63, 1 ); #endif @@ -1385,14 +1392,7 @@ static void Com_InitHunkMemory() s_hunkData = (byte *) ( ( (intptr_t)s_hunkData + 63 ) & ( ~63 ) ); Hunk_Clear(); - Cmd_AddCommand( "meminfo", Com_Meminfo_f ); -#ifdef ZONE_DEBUG - Cmd_AddCommand( "zonelog", Z_LogHeap ); -#endif -#ifdef HUNK_DEBUG - Cmd_AddCommand( "hunklog", Hunk_Log ); - Cmd_AddCommand( "hunksmalllog", Hunk_SmallLog ); -#endif + Cmd_RegisterArray( hunk_cmds, MODULE_COMMON ); } @@ -2127,6 +2127,43 @@ static qbool Com_GetProcessorInfo() #undef IS_X64 +static const cmdTableItem_t com_cmds[] = +{ +#if defined(DEBUG) || defined(CNQ3_DEV) + { "error", Com_Error_f }, + { "crash", Com_Crash_f }, + { "freeze", Com_Freeze_f }, + { "exit", Com_Exit_f }, +#endif + { "quit", Com_Quit_f, NULL, "closes the application" }, + { "writeconfig", Com_WriteConfig_f, Com_CompleteWriteConfig_f, "write the cvars and key binds to a file" } +}; + + +static const cvarTableItem_t com_cvars[] = +{ + { &com_maxfps, "com_maxfps", "125", CVAR_ARCHIVE, CVART_INTEGER, "60", "250", help_com_maxfps }, + { &com_developer, "developer", "0", CVAR_TEMP, CVART_BOOL, NULL, NULL, "enables detailed logging" }, + { &com_logfile, "logfile", "0", CVAR_TEMP, CVART_INTEGER, "0", "2", help_com_logfile }, + { &com_timescale, "timescale", "1", CVAR_CHEAT | CVAR_SYSTEMINFO, CVART_FLOAT, "0.1", "100", "game time to real time ratio" }, + { &com_fixedtime, "fixedtime", "0", CVAR_CHEAT, CVART_INTEGER, "1", "64", "fixed number of ms per simulation tick" }, + { &com_showtrace, "com_showtrace", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "prints trace optimization info" }, + { &com_viewlog, "viewlog", "0", CVAR_CHEAT, CVART_INTEGER, "0", "2", help_com_viewlog }, + { &com_speeds, "com_speeds", "0", 0, CVART_BOOL, NULL, NULL, "prints timing info" }, + { &com_timedemo, "timedemo", "0", CVAR_CHEAT, CVART_BOOL, NULL, NULL, "benchmarking mode for demo playback" }, + { &cl_paused, "cl_paused", "0", CVAR_ROM, CVART_BOOL }, + { &sv_paused, "sv_paused", "0", CVAR_ROM, CVART_BOOL }, + { &cl_packetdelay, "cl_packetdelay", "0", CVAR_CHEAT, CVART_INTEGER, "0", NULL }, + { &sv_packetdelay, "sv_packetdelay", "0", CVAR_CHEAT, CVART_INTEGER, "0", NULL }, + { &com_sv_running, "sv_running", "0", CVAR_ROM, CVART_BOOL }, + { &com_cl_running, "cl_running", "0", CVAR_ROM, CVART_BOOL }, +#if defined(_WIN32) && defined(_DEBUG) + { &com_noErrorInterrupt, "com_noErrorInterrupt", "0", 0, CVART_BOOL }, +#endif + { &com_completionStyle, "com_completionStyle", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_com_completionStyle } +}; + + #if defined(_MSC_VER) #pragma warning (disable: 4611) // setjmp + destructors = bad. which it is, but... #endif @@ -2189,6 +2226,7 @@ void Com_Init( char *commandLine ) #else com_dedicated = Cvar_Get("dedicated", "0", CVAR_LATCH); #endif + // allocate the stack based hunk allocator Com_InitHunkMemory(); @@ -2199,33 +2237,7 @@ void Com_Init( char *commandLine ) // // init commands and vars // - com_maxfps = Cvar_Get ("com_maxfps", "85", CVAR_ARCHIVE); - - com_developer = Cvar_Get ("developer", "0", CVAR_TEMP ); - com_logfile = Cvar_Get ("logfile", "0", CVAR_TEMP ); - - com_timescale = Cvar_Get ("timescale", "1", CVAR_CHEAT | CVAR_SYSTEMINFO ); - com_fixedtime = Cvar_Get ("fixedtime", "0", CVAR_CHEAT); - com_showtrace = Cvar_Get ("com_showtrace", "0", CVAR_CHEAT); - com_viewlog = Cvar_Get( "viewlog", "0", CVAR_CHEAT ); - com_speeds = Cvar_Get ("com_speeds", "0", 0); - com_timedemo = Cvar_Get ("timedemo", "0", CVAR_CHEAT); - - cl_paused = Cvar_Get ("cl_paused", "0", CVAR_ROM); - sv_paused = Cvar_Get ("sv_paused", "0", CVAR_ROM); - cl_packetdelay = Cvar_Get ("cl_packetdelay", "0", CVAR_CHEAT); - sv_packetdelay = Cvar_Get ("sv_packetdelay", "0", CVAR_CHEAT); - com_sv_running = Cvar_Get ("sv_running", "0", CVAR_ROM); - com_cl_running = Cvar_Get ("cl_running", "0", CVAR_ROM); - com_buildScript = Cvar_Get( "com_buildScript", "0", 0 ); - - com_introPlayed = Cvar_Get( "com_introplayed", "0", CVAR_ARCHIVE ); - -#if defined(_WIN32) && defined(_DEBUG) - com_noErrorInterrupt = Cvar_Get( "com_noErrorInterrupt", "0", 0 ); -#endif - - com_completionStyle = Cvar_Get( "com_completionStyle", "0", CVAR_ARCHIVE ); + Cvar_RegisterArray( com_cvars, MODULE_COMMON ); if ( com_dedicated->integer ) { if ( !com_viewlog->integer ) { @@ -2233,16 +2245,7 @@ void Com_Init( char *commandLine ) } } -#if defined(DEBUG) || defined(CNQ3_DEV) - Cmd_AddCommand( "error", Com_Error_f ); - Cmd_AddCommand( "crash", Com_Crash_f ); - Cmd_AddCommand( "freeze", Com_Freeze_f ); - Cmd_AddCommand( "exit", Com_Exit_f ); -#endif - - Cmd_AddCommand( "quit", Com_Quit_f ); - Cmd_AddCommand( "writeconfig", Com_WriteConfig_f ); - Cmd_SetAutoCompletion( "writeconfig", Com_CompleteWriteConfig_f ); + Cmd_RegisterArray( com_cmds, MODULE_COMMON ); const char* s = Q3_VERSION" "PLATFORM_STRING" "__DATE__; com_version = Cvar_Get( "version", s, CVAR_ROM | CVAR_SERVERINFO ); @@ -2270,16 +2273,7 @@ void Com_Init( char *commandLine ) com_frameTime = Com_Milliseconds(); // add + commands from command line - if ( !Com_AddStartupCommands() ) { - // if the user didn't give any commands, run default action - if ( !com_dedicated->integer ) { - if ( !com_introPlayed->integer ) { - Cvar_Set( com_introPlayed->name, "1" ); - Cbuf_AddText( "cinematic idlogo.RoQ\n" ); - Cvar_Set( "nextmap", "cinematic intro.RoQ" ); - } - } - } + Com_AddStartupCommands(); // start in full screen ui mode Cvar_Set( "r_uiFullScreen", "1" ); @@ -2696,11 +2690,42 @@ static void PrintMatches( const char *s ) } +static void PrintCmdMatches( const char *s ) +{ + if ( Q_stricmpn( s, shortestMatch, strlen( shortestMatch ) ) ) + return; + + char msg[CONSOLE_WIDTH * 2]; // account for lots of color codes + const char* desc; + const char* help; + Cmd_GetHelp( &desc, &help, s ); + + if ( desc ) + Com_sprintf( msg, sizeof(msg), " "COLOR_CMD"%s - "COLOR_HELP"%s\n", s, desc ); + else + Com_sprintf( msg, sizeof(msg), " "COLOR_CMD"%s\n", s ); + + Com_TruncatePrintString( msg, sizeof(msg), CONSOLE_WIDTH ); + Com_Printf( msg ); +} + + static void PrintCvarMatches( const char *s ) { - if ( !Q_stricmpn( s, shortestMatch, strlen( shortestMatch ) ) ) { - Com_Printf( " %s = \"%s\"\n", s, Cvar_VariableString( s ) ); - } + if ( Q_stricmpn( s, shortestMatch, strlen( shortestMatch ) ) ) + return; + + char msg[CONSOLE_WIDTH * 2]; // account for lots of color codes + const char* desc; + const char* help; + Cvar_GetHelp( &desc, &help, s ); + if ( desc ) + Com_sprintf( msg, sizeof(msg), " "COLOR_CVAR"%s^7 = \""COLOR_VAL"%s^7\" - "COLOR_HELP"%s\n", s, Cvar_VariableString( s ), desc ); + else + Com_sprintf( msg, sizeof(msg), " "COLOR_CVAR"%s^7 = \""COLOR_VAL"%s^7\"\n", s, Cvar_VariableString( s ) ); + + Com_TruncatePrintString( msg, sizeof(msg), CONSOLE_WIDTH ); + Com_Printf( msg ); } @@ -2845,7 +2870,7 @@ static void Field_AutoCompleteCmdOrVarName( int startArg, int compArg, qbool sea } if ( searchCmds ) - Cmd_CommandCompletion( PrintMatches ); + Cmd_CommandCompletion( PrintCmdMatches ); if ( searchVars ) Cvar_CommandCompletion( PrintCvarMatches ); } @@ -3136,3 +3161,75 @@ const char* Q_itohex( uint64_t number, qbool uppercase, qbool prefix ) return buffer + startOffset; } + + +void Help_AllocSplitText( char** desc, char** help, const char* combined ) +{ + if ( *desc != NULL || *help != NULL ) { + // break here for some debugging fun + return; + } + + const char* const newLine = strchr( combined, '\n' ); + if ( !newLine ) { + *desc = CopyString( combined ); + return; + } + + const int srcLen = strlen( combined ); + const int descLen = newLine - combined; + const int helpLen = srcLen - descLen - 1; + *desc = (char*)S_Malloc( descLen + 1 ); + *help = (char*)S_Malloc( helpLen + 1 ); + memcpy( *desc, combined, descLen ); + memcpy( *help, combined + descLen + 1, helpLen ); + (*desc)[descLen] = '\0'; + (*help)[helpLen] = '\0'; +} + + +void Com_TruncatePrintString( char* buffer, int size, int maxLength ) +{ + if ( Q_PrintStrlen( buffer ) <= maxLength ) + return; + + int byteIndex = Q_PrintStroff( buffer, maxLength ); + if ( byteIndex < 0 || byteIndex >= size ) + byteIndex = size - 1; + + buffer[byteIndex - 4] = '.'; + buffer[byteIndex - 3] = '.'; + buffer[byteIndex - 2] = '.'; + buffer[byteIndex - 1] = '\n'; + buffer[byteIndex - 0] = '\0'; +} + + +void Com_PrintModules( module_t firstModule, int moduleMask ) +{ +#define MODULE_ITEM(Enum, Desc) Desc, + static const char* ModuleNames[MODULE_COUNT + 1] = + { + MODULE_LIST(MODULE_ITEM) + "" + }; +#undef MODULE_ITEM + + if ( firstModule == MODULE_NONE || moduleMask == 0 ) + return; + + const int otherModules = moduleMask & (~(1 << firstModule)); + + if ( otherModules ) + Com_Printf( "Modules: " ); + else + Com_Printf( "Module: " ); + Com_Printf( "%s", ModuleNames[firstModule] ); + + for ( int i = 0; i < 32; ++i ) { + if ( (otherModules >> i) & 1 ) + Com_Printf( ", %s", ModuleNames[i] ); + } + + Com_Printf("\n"); +} diff --git a/code/qcommon/common_help.h b/code/qcommon/common_help.h new file mode 100644 index 0000000..7f3f996 --- /dev/null +++ b/code/qcommon/common_help.h @@ -0,0 +1,59 @@ +#define help_pattern_matching \ +"\n" \ +"If no argument is passed, the list is unfiltered.\n" \ +"If you pass an argument, it is used to filter the list.\n" \ +"The star character (*) will match 0, 1 or more characters.\n" \ +"\n" + +#define help_toggle \ +"toggles the boolean value of a variable\n" \ +"non-0 becomes 0 and 0 becomes 1" + +#define help_cvarlist \ +"lists and filters all cvars\n" \ +help_pattern_matching \ +" Argument Matches\n" \ +"Example: r_ cvars starting with 'r_'\n" \ +"Example: *light cvars containing 'light'\n" \ +"Example: r_*light cvars starting with 'r_' AND containing 'light'" + +#define help_cmdlist \ +"lists and filters all commands\n" \ +help_pattern_matching \ +" Argument Matches\n" \ +"Example: fs_ cmds starting with 'fs_'\n" \ +"Example: *list cmds containing 'list'\n" \ +"Example: fs_*list cmds starting with 'fs_' AND containing 'list'" + +#define help_com_logfile \ +"console logging to qconsole.log\n" \ +" 0 = disabled\n" \ +" 1 = enabled\n" \ +" 2 = enabled and flushes the file after every write" + +#define help_com_viewlog \ +"early console window visibility\n" \ +" 0 = hidden\n" \ +" 1 = visible\n" \ +" 2 = minimized" + +#define help_com_completionStyle \ +"auto-completion style\n" \ +" 0 = legacy, always print all results\n" \ +" 1 = ET-style, print once then cycle" + +#define help_qport \ +"internal network port\n" \ +"this allows more than one person to play from behind a NAT router by using only one IP address" + +#define help_vm_load \ +"\n" \ +" 0 = shared library (native code)\n" \ +" 1 = interpreted QVM\n" \ +" 2 = JIT-compiled QVM" + +#define help_com_maxfps \ +"max. allowed framerate\n" \ +"It's highly recommended to only use 125 or 250 with V-Sync disabled." \ +"If you get the 'connection interruped' message with 250,\n" \ +"set it back to 125." diff --git a/code/qcommon/cvar.cpp b/code/qcommon/cvar.cpp index 8063fe2..fe8443b 100644 --- a/code/qcommon/cvar.cpp +++ b/code/qcommon/cvar.cpp @@ -25,6 +25,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "qcommon.h" #include "crash.h" #include "git.h" +#include "common_help.h" +#include static cvar_t* cvar_vars; static cvar_t* cvar_cheats; @@ -141,6 +143,74 @@ void Cvar_CommandCompletion( void(*callback)(const char *s) ) } +void Cvar_EnumHelp( search_callback_t callback, const char* pattern ) +{ + if( pattern == NULL || *pattern == '\0' ) + return; + + cvar_t* cvar; + for ( cvar = cvar_vars; cvar; cvar = cvar->next ) { + if( cvar->name && !(cvar->flags & CVAR_USER_CREATED) ) + callback( cvar->name, cvar->desc, cvar->help, pattern ); + } +} + + +static qbool Cvar_IsValidGet( cvar_t *var, const char *value ) +{ + if ( var->type == CVART_STRING ) + return qtrue; + + if ( var->type == CVART_FLOAT ) { + float f; + if ( sscanf(value, "%f", &f) != 1 || + !isfinite(f) || + f < var->validator.f.min || + f > var->validator.f.max) + return qfalse; + } else { + int i; + if ( sscanf(value, "%d", &i) != 1 || + i < var->validator.i.min || + i > var->validator.i.max) + return qfalse; + } + + return qtrue; +} + + +static qbool Cvar_IsValidSet( cvar_t *var, const char *value ) +{ +#define WARNING( Message ) { Com_Printf( "WARNING %s: " Message "\n", var->name ); return qfalse; } + + if ( var->type == CVART_STRING ) + return qtrue; + + if ( var->type == CVART_FLOAT ) { + float f; + if ( sscanf(value, "%f", &f) != 1 || !isfinite(f) ) + WARNING( "not a finite floating-point value" ) + if( f < var->validator.f.min ) + WARNING( "float value too low" ) + if( f > var->validator.f.max ) + WARNING( "float value too high" ) + } else { + int i; + if ( sscanf(value, "%d", &i) != 1 ) + WARNING("not a whole number (integer)") + if( i < var->validator.i.min ) + WARNING( "integer value too low" ) + if( i > var->validator.i.max ) + WARNING( "integer value too high" ) + } + + return qtrue; + +#undef WARNING +} + + static cvar_t* Cvar_Set2( const char *var_name, const char *value, qbool force ) { // Com_DPrintf( "Cvar_Set2: %s %s\n", var_name, value ); @@ -162,9 +232,11 @@ static cvar_t* Cvar_Set2( const char *var_name, const char *value, qbool force ) value = var->resetString; } - if (!strcmp(value,var->string)) { + if (!strcmp(value, var->string) || + !Cvar_IsValidSet(var, value)) { return var; } + // note what types of cvars have been modified (userinfo, archive, serverinfo, systeminfo) cvar_modifiedFlags |= var->flags; @@ -256,6 +328,8 @@ cvar_t* Cvar_Get( const char *var_name, const char *var_value, int flags ) cvar_t* var = Cvar_FindVar( var_name ); if ( var ) { + var_value = Cvar_IsValidGet( var, var_value ) ? var_value : var->resetString; + // if the C code is now specifying a variable that the user already // set a value for, take the new value as the reset value if ( ( var->flags & CVAR_USER_CREATED ) && !( flags & CVAR_USER_CREATED ) @@ -320,6 +394,11 @@ breaks every single mod except CPMA otherwise, but it IS wrong, and critically s var->value = atof(var->string); var->integer = atoi(var->string); var->resetString = CopyString( var_value ); + var->desc = NULL; + var->help = NULL; + var->type = CVART_STRING; + var->firstModule = MODULE_NONE; + var->moduleMask = 0; // link the variable in if ( cvar_vars == NULL || Q_stricmp(cvar_vars->name, var_name) > 0 ) { @@ -357,6 +436,177 @@ breaks every single mod except CPMA otherwise, but it IS wrong, and critically s } +void Cvar_SetHelp( const char *var_name, const char *help ) +{ + cvar_t* var = Cvar_FindVar( var_name ); + if ( !var ) + return; + + Help_AllocSplitText( &var->desc, &var->help, help ); +} + + +qbool Cvar_GetHelp( const char **desc, const char **help, const char* var_name ) +{ + cvar_t* var = Cvar_FindVar( var_name ); + if ( !var ) + return qfalse; + + *desc = var->desc; + *help = var->help; + + return qtrue; +} + + +void Cvar_SetRange( const char *var_name, cvarType_t type, const char *minStr, const char *maxStr ) +{ +#define WARNING( Message ) { assert(0); Com_Printf( "Cvar_SetRange on %s: " Message "\n", var_name ); return; } + + cvar_t* var = Cvar_FindVar( var_name ); + if( !var ) + WARNING( "cvar not found" ); + + if( (unsigned int)type >= CVART_COUNT ) + WARNING( "invalid cvar type" ); + + if ( type == CVART_BOOL ) { + var->validator.i.min = 0; + var->validator.i.max = 1; + } else if ( type == CVART_INTEGER || type == CVART_BITMASK ) { + int min = INT_MIN; + int max = INT_MAX; + if ( minStr && sscanf(minStr, "%d", &min) != 1 ) + WARNING( "invalid min value" ) + if ( maxStr && sscanf(maxStr, "%d", &max) != 1 ) + WARNING( "invalid max value" ) + if ( min > max ) + WARNING( "min greater than max" ) + var->validator.i.min = min; + var->validator.i.max = max; + } else if ( type == CVART_FLOAT ) { + // yes, sscanf *does* recognize special strings for inf and NaN + float min = -FLT_MAX; + float max = FLT_MAX; + if ( minStr && sscanf(minStr, "%f", &min) != 1 && !isfinite(min) ) + WARNING( "invalid min value" ) + if ( maxStr && sscanf(maxStr, "%f", &max) != 1 && !isfinite(max) ) + WARNING( "invalid max value" ) + if ( min > max ) + WARNING( "min greater than max" ) + var->validator.f.min = min; + var->validator.f.max = max; + } + var->type = type; + + // run a validation pass right away + Cvar_Set( var_name, var->string ); + +#undef ERROR +} + + +void Cvar_RegisterTable( const cvarTableItem_t* cvars, int count, module_t module ) +{ + for ( int i = 0; i < count; ++i ) { + const cvarTableItem_t* item = &cvars[i]; + + if ( item->cvar ) + *item->cvar = Cvar_Get( item->name, item->reset, item->flags ); + else + Cvar_Get( item->name, item->reset, item->flags ); + + if ( item->help ) + Cvar_SetHelp( item->name, item->help ); + + if ( item->min || + item->max || + item->type == CVART_BITMASK || + item->type == CVART_BOOL ) + Cvar_SetRange( item->name, item->type, item->min, item->max ); + + Cvar_SetModule( item->name, module ); + } +} + + +void Cvar_SetModule( const char *var_name, module_t module ) +{ + cvar_t* var = Cvar_FindVar( var_name ); + if ( !var ) + return; + + var->moduleMask |= 1 << (int)module; + if ( var->firstModule == MODULE_NONE ) + var->firstModule = module; +} + + +void Cvar_GetModuleInfo( module_t *firstModule, int *moduleMask, const char *var_name ) +{ + cvar_t* var = Cvar_FindVar( var_name ); + if ( !var ) + return; + + *firstModule = var->firstModule; + *moduleMask = var->moduleMask; +} + + +static const char* Cvar_FormatRangeFloat( float vf ) +{ + const int vi = (int)vf; + const qbool round = vf == (float)vi; + + return round ? va( "%d.0", vi ) : va( "%.3g", vf ); +} + + +void Cvar_PrintTypeAndRange( const char *var_name ) +{ + cvar_t* var = Cvar_FindVar( var_name ); + if ( !var ) + return; + + if ( var->type == CVART_BOOL ) { + Com_Printf( "%s <0|1> (default: %s)\n", var_name, var->resetString ); + } else if ( var->type == CVART_BITMASK ) { + Com_Printf( "%s (default: %s)\n", var_name, var->resetString ); + } else if ( var->type == CVART_FLOAT ) { + const float minV = var->validator.f.min; + const float maxV = var->validator.f.max; + if ( minV == -FLT_MAX && maxV == FLT_MAX ) { + Com_Printf( "%s (default: %s)\n", var_name, var->resetString); + } else { + const char* min = minV == -FLT_MAX ? "-inf" : Cvar_FormatRangeFloat( minV ); + const char* max = maxV == +FLT_MAX ? "+inf" : Cvar_FormatRangeFloat( maxV ); + Com_Printf( "%s <%s..%s> (default: %s)\n", var_name, min, max, var->resetString ); + } + } else if ( var->type == CVART_INTEGER ) { + const int minV = var->validator.i.min; + const int maxV = var->validator.i.max; + const int diff = maxV - minV; + if( minV == INT_MIN && maxV == INT_MAX ) { + Com_Printf( "%s (default: %s)\n", var_name, var->resetString ); + } else if ( diff == 0 ) { + Com_Printf( "%s <%d> (default: %s)\n", var_name, minV, var->resetString ); + } else if ( diff == 1 ) { + Com_Printf( "%s <%d|%d> (default: %s)\n", var_name, minV, minV + 1, var->resetString ); + } else if ( diff == 2 ) { + Com_Printf( "%s <%d|%d|%d> (default: %s)\n", var_name, minV, minV + 1, minV + 2, var->resetString ); + } else if ( diff == 3 ) { + Com_Printf( "%s <%d|%d|%d|%d> (default: %s)\n", var_name, minV, minV + 1, minV + 2, minV + 3, var->resetString ); + } else { + const char* min = minV == INT_MIN ? "-inf" : va( "%d", minV ); + const char* max = maxV == INT_MAX ? "+inf" : va( "%d", maxV ); + Com_Printf( "%s <%s..%s> (default: %s)\n", var_name, min, max, var->resetString ); + } + } else { + Com_Printf( "%s (default: %s)\n", var_name, var->resetString ); + } +} + + void Cvar_Set( const char *var_name, const char *value ) { Cvar_Set2( var_name, value, qtrue ); @@ -596,6 +846,12 @@ static void Cvar_Restart_f( void ) if ( var->resetString ) { Z_Free( var->resetString ); } + if ( var->desc ) { + Z_Free( var->desc ); + } + if ( var->help ) { + Z_Free( var->help ); + } // clear the var completely, since we // can't remove the index from the list Com_Memset( var, 0, sizeof( var ) ); @@ -705,6 +961,19 @@ void Cvar_Update( vmCvar_t *vmCvar ) } +static const cmdTableItem_t cl_cmds[] = +{ + { "toggle", Cvar_Toggle_f, Cvar_CompleteName, help_toggle }, + { "set", Cvar_Set_f, Cvar_CompleteName, "creates or changes a cvar's value" }, + { "sets", Cvar_SetS_f, Cvar_CompleteName, "like /set with the server info flag" }, + { "setu", Cvar_SetU_f, Cvar_CompleteName, "like /set with the user info flag" }, + { "seta", Cvar_SetA_f, Cvar_CompleteName, "like /set with the archive flag" }, + { "reset", Cvar_Reset_f, Cvar_CompleteName, "sets a cvar back to its default value" }, + { "cvarlist", Cvar_List_f, NULL, help_cvarlist }, + { "cvar_restart", Cvar_Restart_f, NULL, "restarts the cvar system" } +}; + + void Cvar_Init() { // this cvar is the single entry point of the entire extension system @@ -714,18 +983,5 @@ void Cvar_Init() Cvar_Get( "git_branch", GIT_BRANCH, CVAR_ROM ); Cvar_Get( "git_headHash", GIT_COMMIT, CVAR_ROM ); - Cmd_AddCommand( "toggle", Cvar_Toggle_f ); - Cmd_AddCommand( "set", Cvar_Set_f ); - Cmd_AddCommand( "sets", Cvar_SetS_f ); - Cmd_AddCommand( "setu", Cvar_SetU_f ); - Cmd_AddCommand( "seta", Cvar_SetA_f ); - Cmd_AddCommand( "reset", Cvar_Reset_f ); - Cmd_AddCommand( "cvarlist", Cvar_List_f ); - Cmd_AddCommand( "cvar_restart", Cvar_Restart_f ); - Cmd_SetAutoCompletion( "toggle", Cvar_CompleteName ); - Cmd_SetAutoCompletion( "set", Cvar_CompleteName ); - Cmd_SetAutoCompletion( "sets", Cvar_CompleteName ); - Cmd_SetAutoCompletion( "setu", Cvar_CompleteName ); - Cmd_SetAutoCompletion( "seta", Cvar_CompleteName ); - Cmd_SetAutoCompletion( "reset", Cvar_CompleteName ); + Cmd_RegisterArray( cl_cmds, MODULE_COMMON ); } diff --git a/code/qcommon/files.cpp b/code/qcommon/files.cpp index d8dca76..62e3563 100644 --- a/code/qcommon/files.cpp +++ b/code/qcommon/files.cpp @@ -2545,6 +2545,14 @@ static void FS_ReorderPurePaks() } +static const cmdTableItem_t fs_cmds[] = +{ + { "path", FS_Path_f, NULL, "prints info about the current search path" }, + { "dir", FS_Dir_f, NULL, "prints an extension-filtered file list" }, + { "fdir", FS_NewDir_f, NULL, "prints a pattern-filtered file list" } +}; + + static void FS_Startup( const char *gameName ) { QSUBSYSTEM_INIT_START( "FileSystem" ); @@ -2557,13 +2565,16 @@ static void FS_Startup( const char *gameName ) fs_packFiles = 0; fs_debug = Cvar_Get( "fs_debug", "0", 0 ); + Cvar_SetRange( "fs_debug", CVART_BOOL, NULL, NULL ); + Cvar_SetHelp( "fs_debug", "prints file open/write accesses" ); fs_basepath = Cvar_Get ("fs_basepath", Sys_Cwd(), CVAR_INIT ); fs_basegame = Cvar_Get ("fs_basegame", "", CVAR_INIT ); + fs_gamedirvar = Cvar_Get ("fs_game", APEXGAME, CVAR_INIT | CVAR_SYSTEMINFO ); + Cvar_SetHelp( "fs_game", "name of the mod folder" ); const char* homePath = Sys_DefaultHomePath(); if (!homePath || !homePath[0]) homePath = fs_basepath->string; fs_homepath = Cvar_Get ("fs_homepath", homePath, CVAR_INIT ); - fs_gamedirvar = Cvar_Get ("fs_game", APEXGAME, CVAR_INIT|CVAR_SYSTEMINFO ); // add search path elements in reverse priority order if (fs_basepath->string[0]) { @@ -2596,15 +2607,12 @@ static void FS_Startup( const char *gameName ) } Com_ReadCDKey(BASEGAME); - cvar_t* fs = Cvar_Get( "fs_game", "", CVAR_INIT|CVAR_SYSTEMINFO ); - if (fs && fs->string[0] != 0) { - Com_AppendCDKey( fs->string ); + if (fs_gamedirvar && fs_gamedirvar->string[0] != 0) { + Com_AppendCDKey( fs_gamedirvar->string ); } // add our commands - Cmd_AddCommand ("path", FS_Path_f); - Cmd_AddCommand ("dir", FS_Dir_f ); - Cmd_AddCommand ("fdir", FS_NewDir_f ); + Cmd_RegisterArray( fs_cmds, MODULE_COMMON ); // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=506 // reorder the pure pk3 files according to server order diff --git a/code/qcommon/g_public.h b/code/qcommon/g_public.h index 060971d..0cb1691 100644 --- a/code/qcommon/g_public.h +++ b/code/qcommon/g_public.h @@ -389,7 +389,10 @@ typedef enum { // engine extensions // the mod should _never_ use these symbols G_EXT_GETVALUE = 700, - G_EXT_LOCATEINTEROPDATA + G_EXT_LOCATEINTEROPDATA, + G_EXT_CVAR_SETRANGE, + G_EXT_CVAR_SETHELP, + G_EXT_CMD_SETHELP } gameImport_t; diff --git a/code/qcommon/net_chan.cpp b/code/qcommon/net_chan.cpp index 715086c..494ffd4 100644 --- a/code/qcommon/net_chan.cpp +++ b/code/qcommon/net_chan.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "q_shared.h" #include "qcommon.h" +#include "common_help.h" /* @@ -68,8 +69,14 @@ void Netchan_Init( int port ) { port &= 0xffff; showpackets = Cvar_Get( "showpackets", "0", CVAR_TEMP ); + Cvar_SetRange( "showpackets", CVART_BOOL, NULL, NULL ); + Cvar_SetHelp( "showpackets", "prints received and sent packets" ); showdrop = Cvar_Get( "showdrop", "0", CVAR_TEMP ); + Cvar_SetRange( "showdrop", CVART_BOOL, NULL, NULL ); + Cvar_SetHelp( "showdrop", "prints dropped packets" ); qport = Cvar_Get( "net_qport", va("%i", port), CVAR_INIT ); + Cvar_SetRange( "net_qport", CVART_INTEGER, "0", "65535" ); + Cvar_SetHelp( "net_qport", help_qport ); } /* diff --git a/code/qcommon/net_ip.cpp b/code/qcommon/net_ip.cpp index fbf3675..0091176 100644 --- a/code/qcommon/net_ip.cpp +++ b/code/qcommon/net_ip.cpp @@ -768,6 +768,7 @@ static void NET_GetLocalAddress() static void NET_OpenIP() { const cvar_t* ip = Cvar_Get( "net_ip", "localhost", CVAR_LATCH ); + Cvar_SetRange( "net_ip", CVART_INTEGER, "0", "65535" ); int port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), CVAR_LATCH )->integer; // automatically scan for a valid port, so multiple @@ -799,10 +800,12 @@ static qboolean NET_GetCvars() if (net_noudp && net_noudp->modified) modified = qtrue; net_noudp = Cvar_Get( "net_noudp", "0", CVAR_LATCH | CVAR_ARCHIVE ); + Cvar_SetRange( "net_noudp", CVART_BOOL, NULL, NULL ); if (net_socksEnabled && net_socksEnabled->modified) modified = qtrue; net_socksEnabled = Cvar_Get( "net_socksEnabled", "0", CVAR_LATCH | CVAR_ARCHIVE ); + Cvar_SetRange( "net_socksEnabled", CVART_BOOL, NULL, NULL ); if (net_socksEnabled->integer) { if (net_socksServer && net_socksServer->modified) @@ -812,6 +815,7 @@ static qboolean NET_GetCvars() if (net_socksPort && net_socksPort->modified) modified = qtrue; net_socksPort = Cvar_Get( "net_socksPort", "1080", CVAR_LATCH | CVAR_ARCHIVE ); + Cvar_SetRange( "net_socksPort", CVART_INTEGER, "0", "65535" ); if (net_socksUsername && net_socksUsername->modified) modified = qtrue; diff --git a/code/qcommon/q_shared.c b/code/qcommon/q_shared.c index 3bcf97e..a4d6520 100644 --- a/code/qcommon/q_shared.c +++ b/code/qcommon/q_shared.c @@ -446,6 +446,30 @@ char* Q_strrchr( const char* string, int c ) } +const char *Q_stristr( const char *s, const char *find ) +{ + char c; + if ((c = *find++) != 0) { + if (c >= 'a' && c <= 'z') + c -= ('a' - 'A'); + + const size_t len = strlen(find); + do { + char sc; + do { + if ((sc = *s++) == 0) + return NULL; + if (sc >= 'a' && sc <= 'z') + sc -= ('a' - 'A'); + } while (sc != c); + } while (Q_stricmpn(s, find, len) != 0); + s--; + } + + return s; +} + + // safe strncpy that ensures a trailing zero void Q_strncpyz( char *dest, const char *src, int destsize ) @@ -573,6 +597,27 @@ int Q_PrintStrlen( const char *string ) } +int Q_PrintStroff( const char *string, int charOffset ) +{ + int len = 0; + const char* p = string; + + if (!p) + return 0; + + while ( *p && len < charOffset ) { + if( Q_IsColorString( p ) ) { + p += 2; + continue; + } + p++; + len++; + } + + return p - string; +} + + char *Q_CleanStr( char *string ) { char* d; char* s; diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 2fa6c9e..885c7d8 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -575,6 +575,7 @@ int Q_stricmpn( const char *s1, const char *s2, int n ); char *Q_strlwr( char *s1 ); char *Q_strupr( char *s1 ); char *Q_strrchr( const char* string, int c ); +const char *Q_stristr( const char *s, const char *find ); // buffer size safe library replacements void Q_strncpyz( char *dest, const char *src, int destsize ); @@ -582,6 +583,8 @@ void Q_strcat( char *dest, int size, const char *src ); // strlen that discounts Quake color sequences int Q_PrintStrlen( const char *string ); +// gets the byte offset of the Nth printable character +int Q_PrintStroff( const char *string, int charOffset ); // removes color sequences from string char *Q_CleanStr( char *string ); @@ -637,6 +640,15 @@ default values. #define MAX_CVAR_VALUE_STRING 256 +typedef enum { + CVART_STRING, // no validation + CVART_FLOAT, // uses floating-point min/max bounds + CVART_INTEGER, // uses integer min/max bounds + CVART_BITMASK, // uses integer min/max bounds + CVART_BOOL, // uses integer min/max bounds, min=0 and max=1 + CVART_COUNT // always last in the enum +} cvarType_t; + typedef int cvarHandle_t; // the modules that run in the virtual machine can't access the cvar_t directly, @@ -1060,6 +1072,13 @@ typedef enum { #define CDKEY_LEN 16 #define CDCHKSUM_LEN 2 + +// #define ANSWER 42 +// STRING(ANSWER) -> "ANSWER" +// XSTRING(ANSWER) -> "42" +#define STRING(x) #x // stringifies x +#define XSTRING(x) STRING(x) // expands x and then stringifies the result + #if defined(__cplusplus) }; diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index f8396f5..9fbc96d 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -302,6 +302,30 @@ intptr_t QDECL VM_Call( vm_t *vm, int callNum, ... ); void VM_Debug( int level ); +/////////////////////////////////////////////////////////////// + + +#define MODULE_LIST(X) \ + X(NONE, "") \ + X(COMMON, "Common") \ + X(CLIENT, "Client") \ + X(SERVER, "Server") \ + X(RENDERER, "Renderer") \ + X(SOUND, "Sound") \ + X(INPUT, "Input") \ + X(CONSOLE, "Console") \ + X(CGAME, "CGame") \ + X(GAME, "Game") \ + X(UI, "UI") + +#define MODULE_ITEM(Enum, Desc) MODULE_##Enum, +typedef enum { + MODULE_LIST(MODULE_ITEM) + MODULE_COUNT +} module_t; +#undef MODULE_ITEM + + /* ============================================================== @@ -343,6 +367,13 @@ then searches for a command or variable that matches the first token. typedef void (*xcommand_t) (void); typedef void (*xcommandCompletion_t) (int startArg, int compArg); +typedef struct cmdTableItem_s { + const char* name; + xcommand_t function; + xcommandCompletion_t completion; + const char* help; +} cmdTableItem_t; + void Cmd_Init(); // called by the init functions of other parts of the program to @@ -351,10 +382,22 @@ void Cmd_Init(); // if function is NULL, the command will be forwarded to the server // as a clc_clientCommand instead of executed locally void Cmd_AddCommand( const char* cmd_name, xcommand_t function ); -void Cmd_AddCommandEx( const char* cmd_name, xcommand_t function, qbool cgame ); void Cmd_RemoveCommand( const char* cmd_name ); -void Cmd_RemoveCGameCommands(); + +void Cmd_SetHelp( const char* cmd_name, const char* cmd_help ); +qbool Cmd_GetHelp( const char** desc, const char** help, const char* cmd_name ); // qtrue if the cmd was found + +void Cmd_RegisterTable( const cmdTableItem_t* cmds, int count, module_t module ); +void Cmd_UnregisterTable( const cmdTableItem_t* cmds, int count ); +#define Cmd_RegisterArray(a, m) Cmd_RegisterTable( a, ARRAY_LEN(a), m ) + +void Cmd_SetModule( const char* cmd_name, module_t module ); + +// removes all commands that were *only* registered by the given module +void Cmd_UnregisterModule( module_t module ); + +void Cmd_GetModuleInfo( module_t* firstModule, int* moduleMask, const char* cmd_name ); // auto-completion of command arguments void Cmd_SetAutoCompletion( const char* cmd_name, xcommandCompletion_t complete ); @@ -364,6 +407,9 @@ void Cmd_AutoCompleteArgument( const char* cmd_name, int startArg, int compArg ) // callback with each valid string void Cmd_CommandCompletion( void(*callback)(const char* s) ); +typedef void (*search_callback_t)( const char* name, const char* desc, const char* help, const char* pattern ); +void Cmd_EnumHelp( search_callback_t callback, const char* pattern ); + // the functions that execute commands get their parameters with these // if arg > argc, Cmd_Argv() will return "", not NULL, so string ops are always safe int Cmd_Argc(); @@ -411,22 +457,54 @@ modules of the program. */ +typedef struct intValidator_s { + int min; + int max; +} intValidator_t; + +typedef struct floatValidator_s { + float min; + float max; +} floatValidator_t; + +typedef union { + intValidator_t i; + floatValidator_s f; +} cvarValidator_t; + // nothing outside the Cvar_*() functions should modify these fields! typedef struct cvar_s { char *name; char *string; char *resetString; // cvar_restart will reset to this value char *latchedString; // for CVAR_LATCH vars + char *desc; + char *help; int flags; + cvarType_t type; + module_t firstModule; + int moduleMask; qboolean modified; // set each time the cvar is changed int modificationCount; // incremented each time the cvar is changed float value; // atof( string ) int integer; // atoi( string ) qbool mismatchPrinted; // have we already notified of mismatching initial values? + cvarValidator_t validator; struct cvar_s *next; struct cvar_s *hashNext; } cvar_t; +typedef struct cvarTableItem_s { + cvar_t** cvar; + const char* name; + const char* reset; + int flags; + cvarType_t type; + const char* min; + const char* max; + const char* help; +} cvarTableItem_t; + cvar_t *Cvar_Get( const char *var_name, const char *value, int flags ); // creates the variable if it doesn't exist, or returns the existing one @@ -434,6 +512,19 @@ cvar_t *Cvar_Get( const char *var_name, const char *value, int flags ); // that allows variables to be unarchived without needing bitflags // if value is "", the value will not override a previously set value. +void Cvar_SetHelp( const char *var_name, const char *help ); +qbool Cvar_GetHelp( const char **desc, const char **help, const char* var_name ); // qtrue if the cvar was found + +void Cvar_SetRange( const char *var_name, cvarType_t type, const char *min, const char *max ); + +void Cvar_RegisterTable( const cvarTableItem_t* cvars, int count, module_t module ); +#define Cvar_RegisterArray(a, m) Cvar_RegisterTable( a, ARRAY_LEN(a), m ) + +void Cvar_SetModule( const char *var_name, module_t module ); +void Cvar_GetModuleInfo( module_t *firstModule, int *moduleMask, const char *var_name ); + +void Cvar_PrintTypeAndRange( const char *var_name ); + void Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ); // basically a slightly modified Cvar_Get for the interpreted modules @@ -460,6 +551,8 @@ int Cvar_Flags( const char *var_name ); void Cvar_CommandCompletion( void(*callback)(const char *s) ); // callback with each valid string +void Cvar_EnumHelp( search_callback_t callback, const char* pattern ); + void Cvar_Reset( const char *var_name ); void Cvar_SetCheatState(); @@ -487,10 +580,15 @@ extern int cvar_modifiedFlags; // etc, variables have been modified since the last check. The bit // can then be cleared to allow another change detection. + +/////////////////////////////////////////////////////////////// + + void CRC32_Begin( unsigned int* crc ); void CRC32_ProcessBlock( unsigned int* crc, const void* buffer, unsigned int length ); void CRC32_End( unsigned int* crc ); + /* ============================================================== @@ -752,7 +850,6 @@ extern cvar_t *com_sv_running; extern cvar_t *com_cl_running; extern cvar_t *com_viewlog; // 0 = hidden, 1 = visible, 2 = minimized extern cvar_t *com_version; -extern cvar_t *com_buildScript; // for building release pak files extern cvar_t *com_journal; // both client and server must agree to pause @@ -1027,4 +1124,21 @@ int StatHuff_WriteSymbol( int symbol, byte* buffer, int bitIndex ); // returns const char* Q_itohex( uint64_t number, qbool uppercase, qbool prefix ); +void Help_AllocSplitText( char** desc, char** help, const char* combined ); + + +#define COLOR_HELP "^7" +#define COLOR_CMD "^7" +#define COLOR_CVAR "^7" +#define COLOR_VAL "^7" + + +#define CONSOLE_WIDTH 78 + + +void Com_TruncatePrintString( char* buffer, int size, int maxLength ); + +void Com_PrintModules( module_t firstModule, int moduleMask ); + + #endif // _QCOMMON_H_ diff --git a/code/qcommon/ui_public.h b/code/qcommon/ui_public.h index 2c787bb..ab2afde 100644 --- a/code/qcommon/ui_public.h +++ b/code/qcommon/ui_public.h @@ -143,7 +143,10 @@ typedef enum { // the mod should _never_ use these symbols UI_EXT_GETVALUE = 700, UI_EXT_LOCATEINTEROPDATA, - UI_EXT_R_ADDREFENTITYTOSCENE2 + UI_EXT_R_ADDREFENTITYTOSCENE2, + UI_EXT_CVAR_SETRANGE, + UI_EXT_CVAR_SETHELP, + UI_EXT_CMD_SETHELP } uiImport_t; diff --git a/code/qcommon/vm.cpp b/code/qcommon/vm.cpp index d5a2d30..41cd938 100644 --- a/code/qcommon/vm.cpp +++ b/code/qcommon/vm.cpp @@ -35,6 +35,7 @@ and one exported function: Perform #include "vm_local.h" #include "crash.h" +#include "common_help.h" opcode_info_t ops[ OP_MAX ] = { @@ -128,15 +129,21 @@ static const char *vmName[ VM_COUNT ] = { }; +static const cvarTableItem_t vm_cvars[] = +{ + { NULL, "vm_cgame", "2", CVAR_ARCHIVE, CVART_INTEGER, "0", "2", "how to load the cgame VM" help_vm_load }, + { NULL, "vm_game", "2", CVAR_ARCHIVE, CVART_INTEGER, "0", "2", "how to load the qagame VM" help_vm_load }, + { NULL, "vm_ui", "2", CVAR_ARCHIVE, CVART_INTEGER, "0", "2", "how to load the ui VM" help_vm_load } +}; + + /* ============== VM_Init ============== */ void VM_Init( void ) { - Cvar_Get( "vm_cgame", "2", CVAR_ARCHIVE ); - Cvar_Get( "vm_game", "2", CVAR_ARCHIVE ); - Cvar_Get( "vm_ui", "2", CVAR_ARCHIVE ); + Cvar_RegisterArray( vm_cvars, MODULE_COMMON ); Com_Memset( vmTable, 0, sizeof( vmTable ) ); } diff --git a/code/renderer/tr_bsp.cpp b/code/renderer/tr_bsp.cpp index 36a5738..82b00ca 100644 --- a/code/renderer/tr_bsp.cpp +++ b/code/renderer/tr_bsp.cpp @@ -34,7 +34,7 @@ static byte* fileBase; static void R_ColorShiftLightingBytes( const byte in[4], byte out[4] ) { // shift the color data based on overbright range - int shift = r_mapOverBrightBits->integer - tr.overbrightBits; + const int shift = Com_ClampInt( 0, 2, r_mapOverBrightBits->integer - tr.overbrightBits ); // shift the data based on overbright range int r = in[0] << shift; diff --git a/code/renderer/tr_gl2.cpp b/code/renderer/tr_gl2.cpp index 83c04a4..ff95690 100644 --- a/code/renderer/tr_gl2.cpp +++ b/code/renderer/tr_gl2.cpp @@ -632,9 +632,9 @@ static GLSL_GammaProgramAttribs gammaProgAttribs; static void GL2_PostProcessGamma() { - const int obBits = Com_ClampInt( 0, 2, r_overBrightBits->integer ); + const int obBits = r_overBrightBits->integer; const float obScale = (float)( 1 << obBits ); - const float gamma = 1.0f / Com_Clamp( 0.5f, 3.0f, r_gamma->value ); + const float gamma = 1.0f / r_gamma->value; if ( gamma == 1.0f && obBits == 0 ) return; diff --git a/code/renderer/tr_help.h b/code/renderer/tr_help.h new file mode 100644 index 0000000..f48e57e --- /dev/null +++ b/code/renderer/tr_help.h @@ -0,0 +1,86 @@ +#define help_r_ext_max_anisotropy \ +"max. allowed anisotropy ratio\n" \ +"For anisotropic filtering to be enabled, this needs to be 2 or higher.\n" \ +" 2 = 8-16 tap filtering\n" \ +" 4 = 16-32 tap filtering\n" \ +" 8 = 32-64 tap filtering" + +#define help_r_picmip \ +"lowest allowed mip level\n" \ +"Lower number means sharper textures." + +#define help_r_roundImagesDown \ +"allows image downscaling before texture upload\n" \ +"The maximum scale ratio is 2 on both the horizontal and vertical axis." + +#define help_r_overBrightBits \ +"linear brightness scale\n" \ +" 0 = 1x\n" \ +" 1 = 2x\n" \ +" 2 = 4x" + +#define help_r_mapOverBrightBits \ +"linear map brightness scale\n" \ +"This increases the maximum brightness of the map.\n" \ +"The amount of over-brighting applied is r_mapOverBrightBits - r_overBrightBits.\n" \ +" 0 = 1x\n" \ +" 1 = 2x\n" \ +" 2 = 4x" + +#define help_r_mode \ +"enables custom resolution for r_fullscreen 1\n" \ +" 0 = desktop resolution\n" \ +" 1 = custom resolution (r_width x r_height)" + +#define help_r_mode0 \ +"\nOnly used when r_mode is 0 and r_fullscreen is 1." + +#define help_r_subdivisions \ +"tessellation step size for patch surfaces\n" \ +"This sets the step size of a subdivision, *not* the number of subdivisions.\n" \ +"In other words, lower values produce smoother curves." + +#define help_r_gamma \ +"gamma correction factor\n" \ +" <1 = darker\n" \ +" 1 = no change\n" \ +" >1 = brighter" + +#define help_r_lodbias \ +"MD3 models LOD bias\n" \ +"For all MD3 models, including player characters.\n" \ +"A higher number means a higher quality loss. 0 means no loss." + +#define help_r_fastsky \ +"makes the sky and portals pure black\n" \ +"Portal example: the bottom teleporter on q3dm7." + +#define help_r_noportals \ +"disables rendering of portals\n" \ +"Portal example: the bottom teleporter on q3dm7." + +#define help_r_textureMode \ +"texture filtering mode\n" \ +" GL_NEAREST = no filtering\n" \ +" GL_LINEAR_MIPMAP_NEAREST = bilinear filtering\n" \ +" GL_LINEAR_MIPMAP_LINEAR = trilinear filtering\n" \ +"For anisotropic filtering, refer to /help r_ext_max_anisotropy." + +#define help_r_swapInterval \ +"v-blanks to wait for before swapping buffers\n" \ +" 0 = No V-Sync\n" \ +" 1 = Synced to the monitor's refresh rate\n" \ +" 2 = Synced to half the monitor's refresh rate\n" \ +" 3 = Synced to one third of the monitor's refresh rate\n" \ +" N = Synced to monitor_refresh_rate / N\n" \ +"It is not recommended to use V-Sync." + +#define help_r_lightmap \ +"renders the lightmaps only\n" \ +"Shaders with a lightmap stage will only draw the lightmap stage.\n" \ +"This is mutually exclusive with r_fullbright." + +#define help_r_fullbright \ +"renders the diffuse textures only\n" \ +"Shaders with a lightmap stage will not draw the lightmap stage.\n" \ +"This is mutually exclusive with r_lightmap." diff --git a/code/renderer/tr_image.cpp b/code/renderer/tr_image.cpp index 50b650e..9917ad2 100644 --- a/code/renderer/tr_image.cpp +++ b/code/renderer/tr_image.cpp @@ -862,18 +862,10 @@ static void R_CreateBuiltinImages() void R_SetColorMappings() { - tr.overbrightBits = Com_Clamp( 0, 2, r_overBrightBits->integer ); + tr.overbrightBits = r_overBrightBits->integer; tr.identityLight = 1.0f / (float)( 1 << tr.overbrightBits ); tr.identityLightByte = (int)( 255.0f * tr.identityLight ); - if ( r_intensity->value < 1 ) - ri.Cvar_Set( "r_intensity", "1" ); - - if ( r_gamma->value < 0.5f ) - ri.Cvar_Set( "r_gamma", "0.5" ); - if ( r_gamma->value > 3.0f ) - ri.Cvar_Set( "r_gamma", "3.0" ); - for (int i = 0; i < 256; ++i) { s_intensitytable[i] = (byte)min( r_intensity->value * i, 255.0f ); } diff --git a/code/renderer/tr_init.cpp b/code/renderer/tr_init.cpp index 89ea9e6..fe94e0f 100644 --- a/code/renderer/tr_init.cpp +++ b/code/renderer/tr_init.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // tr_init.c -- functions that are not called every frame #include "tr_local.h" +#include "tr_help.h" glconfig_t glConfig; glinfo_t glInfo; @@ -48,7 +49,6 @@ cvar_t *r_greyscale; cvar_t *r_measureOverdraw; -cvar_t *r_inGameVideo; cvar_t *r_fastsky; cvar_t *r_dynamiclight; @@ -65,7 +65,6 @@ cvar_t *r_novis; cvar_t *r_nocull; cvar_t *r_nocurves; -cvar_t *r_ext_compressed_textures; cvar_t *r_ext_max_anisotropy; cvar_t *r_msaa; @@ -131,30 +130,6 @@ int max_polys; int max_polyverts; -static void AssertCvarRange( cvar_t *cv, float minVal, float maxVal, qbool shouldBeIntegral ) -{ - if ( shouldBeIntegral ) - { - if ( ( int ) cv->value != cv->integer ) - { - ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' must be integral (%f)\n", cv->name, cv->value ); - ri.Cvar_Set( cv->name, va( "%d", cv->integer ) ); - } - } - - if ( cv->value < minVal ) - { - ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f < %f)\n", cv->name, cv->value, minVal ); - ri.Cvar_Set( cv->name, va( "%f", minVal ) ); - } - else if ( cv->value > maxVal ) - { - ri.Printf( PRINT_WARNING, "WARNING: cvar '%s' out of range (%f > %f)\n", cv->name, cv->value, maxVal ); - ri.Cvar_Set( cv->name, va( "%f", maxVal ) ); - } -} - - static void GL_SetDefaultState() { qglClearDepth( 1.0f ); @@ -423,7 +398,6 @@ const void *RB_TakeVideoFrameCmd( const void *data ) void GfxInfo_f( void ) { cvar_t* sys_cpustring = ri.Cvar_Get( "sys_cpustring", "", 0 ); - const char* enablestrings[] = { "disabled", "enabled" }; ri.Printf( PRINT_DEVELOPER, "\nGL_VENDOR: %s\n", glConfig.vendor_string ); ri.Printf( PRINT_DEVELOPER, "GL_RENDERER: %s\n", glConfig.renderer_string ); @@ -440,7 +414,6 @@ void GfxInfo_f( void ) ri.Printf( PRINT_DEVELOPER, "texturemode: %s\n", r_textureMode->string ); ri.Printf( PRINT_DEVELOPER, "picmip: %d\n", r_picmip->integer ); - ri.Printf( PRINT_DEVELOPER, "compressed textures: %s\n", enablestrings[r_ext_compressed_textures->integer] ); ri.Printf( PRINT_DEVELOPER, "ambient pass: %s\n", r_vertexLight->integer ? "vertex" : "lightmap" ); if ( r_finish->integer ) { ri.Printf( PRINT_DEVELOPER, "Forcing glFinish\n" ); @@ -458,129 +431,108 @@ void GfxInfo_f( void ) /////////////////////////////////////////////////////////////// -static struct r_ConsoleCmd { - const char* cmd; - xcommand_t fn; -} const r_ConsoleCmds[] = { - { "gfxinfo", GfxInfo_f }, - { "imagelist", R_ImageList_f }, - { "shaderlist", R_ShaderList_f }, - { "skinlist", R_SkinList_f }, - { "modellist", R_Modellist_f }, - { "screenshot", R_ScreenShotTGA_f }, - { "screenshotJPEG", R_ScreenShotJPG_f }, - { } +static const cmdTableItem_t r_cmds[] = +{ + { "gfxinfo", GfxInfo_f, NULL, "prints display mode info" }, + { "imagelist", R_ImageList_f, NULL, "prints loaded images" }, + { "shaderlist", R_ShaderList_f, NULL, "prints loaded shaders" }, + { "skinlist", R_SkinList_f, NULL, "prints loaded skins" }, + { "modellist", R_Modellist_f, NULL, "prints loaded models" }, + { "screenshot", R_ScreenShotTGA_f, NULL, "takes a TARGA (.tga) screenshot" }, + { "screenshotJPEG", R_ScreenShotJPG_f, NULL, "takes a JPEG (.jpg) screenshot" } +}; + + +static const cvarTableItem_t r_cvars[] = +{ + // + // latched and archived variables + // + { &r_ext_max_anisotropy, "r_ext_max_anisotropy", "4", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "4", help_r_ext_max_anisotropy }, + { &r_msaa, "r_msaa", "4", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "16", "anti-aliasing sample count, 0=off" }, + { &r_picmip, "r_picmip", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "16", help_r_picmip }, + { &r_roundImagesDown, "r_roundImagesDown", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_roundImagesDown }, + { &r_colorMipLevels, "r_colorMipLevels", "0", CVAR_LATCH, CVART_BOOL, NULL, NULL, "colorizes textures based on their mip level" }, + { &r_detailTextures, "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "enables detail textures shader stages" }, + { &r_overBrightBits, "r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "2", help_r_overBrightBits }, + { &r_mode, "r_mode", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_mode }, + { &r_fullscreen, "r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "full-screen mode" }, + { &r_width, "r_width", "1280", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "320", "65535", "custom window width" help_r_mode0 }, + { &r_height, "r_height", "720", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "240", "65535", "custom window height" help_r_mode0 }, + { &r_customaspect, "r_customaspect", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0.1", "10", "custom pixel aspect ratio" help_r_mode0 }, + { &r_vertexLight, "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, "disables lightmap texture blending" }, + { &r_subdivisions, "r_subdivisions", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "1", "64", help_r_subdivisions }, +#ifdef USE_R_SMP + { &r_smp, "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH }, + { &r_showSmp, "r_showSmp", "0", CVAR_CHEAT }, + { &r_skipBackEnd, "r_skipBackEnd", "0", CVAR_CHEAT }, +#endif + + // + // latched variables that can only change over a restart + // + { &r_displayRefresh, "r_displayRefresh", "0", CVAR_LATCH, CVART_INTEGER, "0", "480", "0 lets the driver decide" }, + { &r_mapOverBrightBits, "r_mapOverBrightBits", "2", CVAR_LATCH, CVART_INTEGER, "0", "2", help_r_mapOverBrightBits }, + { &r_intensity, "r_intensity", "1", CVAR_ARCHIVE | CVAR_LATCH, CVART_FLOAT, "1", NULL, "linear brightness scale for textures and dynamic lights" }, + { &r_singleShader, "r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH }, + + // + // archived variables that can change at any time + // + { &r_lodbias, "r_lodbias", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "16", help_r_lodbias }, + { &r_flares, "r_flares", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "enables light flares" }, + { &r_ignoreGLErrors, "r_ignoreGLErrors", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "if 0, OpenGL errors are fatal" }, + { &r_fastsky, "r_fastsky", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_fastsky }, + { &r_noportals, "r_noportals", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_noportals }, + { &r_dynamiclight, "r_dynamiclight", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "enables dynamic lights" }, + { &r_finish, "r_finish", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "enables glFinish calls" }, + { &r_textureMode, "r_textureMode", "GL_LINEAR_MIPMAP_LINEAR", CVAR_ARCHIVE, CVART_STRING, NULL, NULL, help_r_textureMode }, + { &r_swapInterval, "r_swapInterval", "0", CVAR_ARCHIVE, CVART_INTEGER, "0", "8", help_r_swapInterval }, + { &r_gamma, "r_gamma", "1", CVAR_ARCHIVE, CVART_FLOAT, "0.5", "3", help_r_gamma }, + { &r_greyscale, "r_greyscale", "0", CVAR_ARCHIVE, CVART_FLOAT, "0", "1", "controls how monochrome the final image looks" }, + { &r_lightmap, "r_lightmap", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_lightmap }, + { &r_fullbright, "r_fullbright", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, help_r_fullbright }, + + // + // temporary variables that can change at any time + // + { &r_lodCurveError, "r_lodCurveError", "250", CVAR_CHEAT }, + { &r_ambientScale, "r_ambientScale", "0.6", CVAR_CHEAT }, + { &r_directedScale, "r_directedScale", "1", CVAR_CHEAT }, + { &r_uiFullScreen, "r_uifullscreen", "0", CVAR_TEMP }, + { &r_showImages, "r_showImages", "0", CVAR_TEMP }, + { &r_debugLight, "r_debuglight", "0", CVAR_TEMP }, + { &r_debugSort, "r_debugSort", "0", CVAR_CHEAT }, + { &r_nocurves, "r_nocurves", "0", CVAR_CHEAT }, + { &r_drawworld, "r_drawworld", "1", CVAR_CHEAT }, + { &r_portalOnly, "r_portalOnly", "0", CVAR_CHEAT }, + { &r_flareSize, "r_flareSize", "40", CVAR_CHEAT }, + { &r_flareFade, "r_flareFade", "7", CVAR_CHEAT }, + { &r_flareCoeff, "r_flareCoeff", "150", CVAR_CHEAT }, + { &r_measureOverdraw, "r_measureOverdraw", "0", CVAR_CHEAT }, + { &r_lodscale, "r_lodscale", "5", CVAR_CHEAT }, + { &r_norefresh, "r_norefresh", "0", CVAR_CHEAT }, + { &r_drawentities, "r_drawentities", "1", CVAR_CHEAT }, + { &r_nocull, "r_nocull", "0", CVAR_CHEAT }, + { &r_novis, "r_novis", "0", CVAR_CHEAT }, + { &r_speeds, "r_speeds", "0", CVAR_CHEAT }, + { &r_verbose, "r_verbose", "0", CVAR_CHEAT }, + { &r_debugSurface, "r_debugSurface", "0", CVAR_CHEAT }, + { &r_nobind, "r_nobind", "0", CVAR_CHEAT }, + { &r_showtris, "r_showtris", "0", CVAR_CHEAT }, + { &r_showsky, "r_showsky", "0", CVAR_CHEAT }, + { &r_shownormals, "r_shownormals", "0", CVAR_CHEAT }, + { &r_clear, "r_clear", "0", CVAR_CHEAT }, + { &r_lockpvs, "r_lockpvs", "0", CVAR_CHEAT }, + { &r_maxpolys, "r_maxpolys", XSTRING(DEFAULT_MAX_POLYS), 0 }, + { &r_maxpolyverts, "r_maxpolyverts", XSTRING(DEFAULT_MAX_POLYVERTS), 0 } }; static void R_Register() { - // - // latched and archived variables - // - r_ext_compressed_textures = ri.Cvar_Get( "r_ext_compressed_textures", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_ext_max_anisotropy = ri.Cvar_Get( "r_ext_max_anisotropy", "16", CVAR_ARCHIVE | CVAR_LATCH ); - r_msaa = ri.Cvar_Get( "r_msaa", "0", CVAR_ARCHIVE | CVAR_LATCH ); - - r_picmip = ri.Cvar_Get ("r_picmip", "0", CVAR_ARCHIVE | CVAR_LATCH ); - AssertCvarRange( r_picmip, 0, 16, qtrue ); - r_roundImagesDown = ri.Cvar_Get ("r_roundImagesDown", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_colorMipLevels = ri.Cvar_Get ("r_colorMipLevels", "0", CVAR_LATCH ); - r_detailTextures = ri.Cvar_Get( "r_detailtextures", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_overBrightBits = ri.Cvar_Get( "r_overBrightBits", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_mode = ri.Cvar_Get( "r_mode", "0", CVAR_ARCHIVE | CVAR_LATCH ); -#if USE_SDL_VIDEO - r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE ); -#else - r_fullscreen = ri.Cvar_Get( "r_fullscreen", "1", CVAR_ARCHIVE | CVAR_LATCH ); -#endif - r_width = ri.Cvar_Get( "r_width", "800", CVAR_ARCHIVE | CVAR_LATCH ); - r_height = ri.Cvar_Get( "r_height", "600", CVAR_ARCHIVE | CVAR_LATCH ); - r_customaspect = ri.Cvar_Get( "r_customaspect", "1.333", CVAR_ARCHIVE | CVAR_LATCH ); - r_vertexLight = ri.Cvar_Get( "r_vertexLight", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_subdivisions = ri.Cvar_Get( "r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH ); -#ifdef USE_R_SMP - r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH ); - r_showSmp = ri.Cvar_Get ("r_showSmp", "0", CVAR_CHEAT); - r_skipBackEnd = ri.Cvar_Get ("r_skipBackEnd", "0", CVAR_CHEAT); -#endif - - // - // temporary latched variables that can only change over a restart - // - r_displayRefresh = ri.Cvar_Get( "r_displayRefresh", "0", CVAR_LATCH ); - AssertCvarRange( r_displayRefresh, 0, 200, qtrue ); - r_mapOverBrightBits = ri.Cvar_Get ("r_mapOverBrightBits", "2", CVAR_LATCH ); - r_intensity = ri.Cvar_Get ("r_intensity", "1", CVAR_ARCHIVE | CVAR_LATCH ); - r_singleShader = ri.Cvar_Get ("r_singleShader", "0", CVAR_CHEAT | CVAR_LATCH ); - - // - // archived variables that can change at any time - // - r_lodCurveError = ri.Cvar_Get( "r_lodCurveError", "250", CVAR_CHEAT ); - r_lodbias = ri.Cvar_Get( "r_lodbias", "0", CVAR_ARCHIVE ); - r_flares = ri.Cvar_Get ("r_flares", "0", CVAR_ARCHIVE ); - r_ignoreGLErrors = ri.Cvar_Get( "r_ignoreGLErrors", "1", CVAR_ARCHIVE ); - r_fastsky = ri.Cvar_Get( "r_fastsky", "0", CVAR_ARCHIVE ); - r_noportals = ri.Cvar_Get( "r_noportals", "0", CVAR_ARCHIVE ); - r_inGameVideo = ri.Cvar_Get( "r_inGameVideo", "1", CVAR_ARCHIVE ); - r_dynamiclight = ri.Cvar_Get( "r_dynamiclight", "1", CVAR_ARCHIVE ); - r_finish = ri.Cvar_Get( "r_finish", "0", CVAR_ARCHIVE ); - r_textureMode = ri.Cvar_Get( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST", CVAR_ARCHIVE ); -#if USE_SDL_VIDEO - r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0", CVAR_ARCHIVE | CVAR_LATCH ); -#else - r_swapInterval = ri.Cvar_Get( "r_swapInterval", "0", CVAR_ARCHIVE ); -#endif - r_gamma = ri.Cvar_Get( "r_gamma", "1", CVAR_ARCHIVE ); - r_greyscale = ri.Cvar_Get( "r_greyscale", "0", CVAR_ARCHIVE ); - r_lightmap = ri.Cvar_Get( "r_lightmap", "0", CVAR_ARCHIVE ); - r_fullbright = ri.Cvar_Get( "r_fullbright", "0", CVAR_ARCHIVE ); - - r_ambientScale = ri.Cvar_Get( "r_ambientScale", "0.6", CVAR_CHEAT ); - r_directedScale = ri.Cvar_Get( "r_directedScale", "1", CVAR_CHEAT ); - - // - // temporary variables that can change at any time - // - r_uiFullScreen = ri.Cvar_Get( "r_uifullscreen", "0", CVAR_TEMP ); - - r_showImages = ri.Cvar_Get( "r_showImages", "0", CVAR_TEMP ); - - r_debugLight = ri.Cvar_Get( "r_debuglight", "0", CVAR_TEMP ); - r_debugSort = ri.Cvar_Get( "r_debugSort", "0", CVAR_CHEAT ); - - r_nocurves = ri.Cvar_Get ("r_nocurves", "0", CVAR_CHEAT ); - r_drawworld = ri.Cvar_Get ("r_drawworld", "1", CVAR_CHEAT ); - r_portalOnly = ri.Cvar_Get ("r_portalOnly", "0", CVAR_CHEAT ); - - r_flareSize = ri.Cvar_Get ("r_flareSize", "40", CVAR_CHEAT); - r_flareFade = ri.Cvar_Get ("r_flareFade", "7", CVAR_CHEAT); - r_flareCoeff = ri.Cvar_Get ("r_flareCoeff", "150", CVAR_CHEAT); - - - r_measureOverdraw = ri.Cvar_Get( "r_measureOverdraw", "0", CVAR_CHEAT ); - r_lodscale = ri.Cvar_Get( "r_lodscale", "5", CVAR_CHEAT ); - r_norefresh = ri.Cvar_Get ("r_norefresh", "0", CVAR_CHEAT); - r_drawentities = ri.Cvar_Get ("r_drawentities", "1", CVAR_CHEAT ); - r_nocull = ri.Cvar_Get ("r_nocull", "0", CVAR_CHEAT); - r_novis = ri.Cvar_Get ("r_novis", "0", CVAR_CHEAT); - r_speeds = ri.Cvar_Get ("r_speeds", "0", CVAR_CHEAT); - r_verbose = ri.Cvar_Get( "r_verbose", "0", CVAR_CHEAT ); - r_debugSurface = ri.Cvar_Get ("r_debugSurface", "0", CVAR_CHEAT); - r_nobind = ri.Cvar_Get ("r_nobind", "0", CVAR_CHEAT); - r_showtris = ri.Cvar_Get ("r_showtris", "0", CVAR_CHEAT); - r_showsky = ri.Cvar_Get ("r_showsky", "0", CVAR_CHEAT); - r_shownormals = ri.Cvar_Get ("r_shownormals", "0", CVAR_CHEAT); - r_clear = ri.Cvar_Get ("r_clear", "0", CVAR_CHEAT); - r_lockpvs = ri.Cvar_Get ("r_lockpvs", "0", CVAR_CHEAT); - - r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", DEFAULT_MAX_POLYS), 0 ); - r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", DEFAULT_MAX_POLYVERTS), 0 ); - - for (int i = 0; r_ConsoleCmds[i].cmd; ++i) { - ri.Cmd_AddCommand( r_ConsoleCmds[i].cmd, r_ConsoleCmds[i].fn ); - } + ri.Cvar_RegisterTable( r_cvars, ARRAY_LEN(r_cvars) ); + ri.Cmd_RegisterTable( r_cmds, ARRAY_LEN(r_cmds) ); } @@ -667,10 +619,6 @@ static void RE_Shutdown( qbool destroyWindow ) { ri.Printf( PRINT_DEVELOPER, "RE_Shutdown( %i )\n", destroyWindow ); - for (int i = 0; r_ConsoleCmds[i].cmd; ++i) { - ri.Cmd_RemoveCommand( r_ConsoleCmds[i].cmd ); - } - if ( tr.registered ) { R_SyncRenderThread(); R_ShutdownCommandBuffers(); diff --git a/code/renderer/tr_local.h b/code/renderer/tr_local.h index 07954c5..11c03be 100644 --- a/code/renderer/tr_local.h +++ b/code/renderer/tr_local.h @@ -939,7 +939,6 @@ extern cvar_t *r_measureOverdraw; // enables stencil buffer overdraw measuremen extern cvar_t *r_lodbias; // push/pull LOD transitions extern cvar_t *r_lodscale; -extern cvar_t *r_inGameVideo; // controls whether in game video should be draw extern cvar_t *r_fastsky; // controls whether sky should be cleared or drawn extern cvar_t *r_noportals; // controls portal/mirror "second view" drawing extern cvar_t *r_dynamiclight; // dynamic lights enabled/disabled diff --git a/code/renderer/tr_public.h b/code/renderer/tr_public.h index cdbeda4..ffb07d2 100644 --- a/code/renderer/tr_public.h +++ b/code/renderer/tr_public.h @@ -189,10 +189,12 @@ typedef struct { void (*Free)( void *buf ); cvar_t *(*Cvar_Get)( const char *name, const char *value, int flags ); + void (*Cvar_SetHelp)( const char *name, const char *help ); void (*Cvar_Set)( const char *name, const char *value ); - void (*Cmd_AddCommand)( const char *name, void(*cmd)(void) ); - void (*Cmd_RemoveCommand)( const char *name ); + void (*Cvar_RegisterTable)( const cvarTableItem_t* cvars, int count ); + + void (*Cmd_RegisterTable)( const cmdTableItem_t* cmds, int count ); int (*Cmd_Argc)(); const char* (*Cmd_Argv)(int i); diff --git a/code/server/server.h b/code/server/server.h index fca0e9d..d643e81 100644 --- a/code/server/server.h +++ b/code/server/server.h @@ -233,11 +233,9 @@ extern cvar_t *sv_privateClients; extern cvar_t *sv_hostname; extern cvar_t *sv_master[MAX_MASTER_SERVERS]; extern cvar_t *sv_reconnectlimit; -extern cvar_t *sv_showloss; extern cvar_t *sv_padPackets; extern cvar_t *sv_killserver; extern cvar_t *sv_mapname; -extern cvar_t *sv_mapChecksum; extern cvar_t *sv_serverid; extern cvar_t *sv_minRate; extern cvar_t *sv_maxRate; @@ -248,6 +246,7 @@ extern cvar_t *sv_pure; extern cvar_t *sv_floodProtect; extern cvar_t *sv_lanForceRate; extern cvar_t *sv_strictAuth; +extern cvar_t *sv_minRebootDelayMins; //=========================================================== diff --git a/code/server/sv_ccmds.cpp b/code/server/sv_ccmds.cpp index 5b974aa..75b79c3 100644 --- a/code/server/sv_ccmds.cpp +++ b/code/server/sv_ccmds.cpp @@ -683,6 +683,7 @@ static void SV_KillServer_f() { SV_Shutdown( "killserver" ); } + static void SV_ServerRestart_f() { char mapname[MAX_QPATH]; @@ -694,6 +695,25 @@ static void SV_ServerRestart_f() } +static const cmdTableItem_t sv_cmds[] = +{ + { "heartbeat", SV_Heartbeat_f, NULL, "sends a heartbeat to master servers" }, + { "kick", SV_Kick_f, NULL, "kicks a player by name" }, + { "banUser", SV_Ban_f, NULL, "bans a player by name" }, + { "banClient", SV_BanNum_f, NULL, "bans a player by client number" }, + { "clientkick", SV_KickNum_f, NULL, "kicks a player by client number" }, + { "status", SV_Status_f, NULL, "prints the current player list" }, + { "serverinfo", SV_Serverinfo_f, NULL, "prints all server info cvars" }, + { "systeminfo", SV_Systeminfo_f, NULL, "prints all system info cvars" }, + { "dumpuser", SV_DumpUser_f, NULL, "prints a user's info cvars" }, + { "map_restart", SV_MapRestart_f, NULL, "resets the game without reloading the map" }, + { "sectorlist", SV_SectorList_f, NULL, "prints entity count for all sectors" }, + { "map", SV_Map_f, SV_CompleteMap_f, "loads a map" }, + { "devmap", SV_DevMap_f, SV_CompleteMap_f, "loads a map with cheats enabled" }, + { "killserver", SV_KillServer_f, NULL, "shuts the server down" }, + { "sv_restart", SV_ServerRestart_f, NULL, "restarts the server" } +}; + void SV_AddOperatorCommands() { @@ -704,44 +724,18 @@ void SV_AddOperatorCommands() initialized = qtrue; - Cmd_AddCommand ("heartbeat", SV_Heartbeat_f); - Cmd_AddCommand ("kick", SV_Kick_f); - Cmd_AddCommand ("banUser", SV_Ban_f); - Cmd_AddCommand ("banClient", SV_BanNum_f); - Cmd_AddCommand ("clientkick", SV_KickNum_f); - Cmd_AddCommand ("status", SV_Status_f); - Cmd_AddCommand ("serverinfo", SV_Serverinfo_f); - Cmd_AddCommand ("systeminfo", SV_Systeminfo_f); - Cmd_AddCommand ("dumpuser", SV_DumpUser_f); - Cmd_AddCommand ("map_restart", SV_MapRestart_f); - Cmd_AddCommand ("sectorlist", SV_SectorList_f); - Cmd_AddCommand ("map", SV_Map_f); - Cmd_AddCommand ("devmap", SV_DevMap_f); - Cmd_SetAutoCompletion ("map", SV_CompleteMap_f); - Cmd_SetAutoCompletion ("devmap", SV_CompleteMap_f); - Cmd_AddCommand ("killserver", SV_KillServer_f); - Cmd_AddCommand ("sv_restart", SV_ServerRestart_f ); + Cmd_RegisterArray( sv_cmds, MODULE_SERVER ); + if( com_dedicated->integer ) { - Cmd_AddCommand ("say", SV_ConSay_f); + Cmd_AddCommand( "say", SV_ConSay_f ); + Cmd_SetModule( "say", MODULE_SERVER ); } } void SV_RemoveOperatorCommands() { -#if 0 // removing these won't let the server start again - Cmd_RemoveCommand ("heartbeat"); - Cmd_RemoveCommand ("kick"); - Cmd_RemoveCommand ("banUser"); - Cmd_RemoveCommand ("banClient"); - Cmd_RemoveCommand ("status"); - Cmd_RemoveCommand ("serverinfo"); - Cmd_RemoveCommand ("systeminfo"); - Cmd_RemoveCommand ("dumpuser"); - Cmd_RemoveCommand ("map_restart"); - Cmd_RemoveCommand ("sectorlist"); - Cmd_RemoveCommand ("say"); -#endif + //Cmd_UnregisterModule( MODULE_SERVER ); } diff --git a/code/server/sv_client.cpp b/code/server/sv_client.cpp index 5cd05b2..59bf53d 100644 --- a/code/server/sv_client.cpp +++ b/code/server/sv_client.cpp @@ -38,14 +38,14 @@ static void SV_UserinfoChanged( client_t *cl ) val = Info_ValueForKey( cl->userinfo, "rate" ); if (val[0]) { - cl->rate = Com_Clamp( 4000, 99999, atoi(val) ); + cl->rate = Com_ClampInt( 4000, 99999, atoi(val) ); } else { cl->rate = 25000; } val = Info_ValueForKey( cl->userinfo, "snaps" ); if (val[0]) { - i = Com_Clamp( 10, sv_fps->integer, atoi(val) ); + i = Com_ClampInt( 10, sv_fps->integer, atoi(val) ); } else { i = sv_fps->integer; } diff --git a/code/server/sv_game.cpp b/code/server/sv_game.cpp index b84d0b3..13cbfa3 100644 --- a/code/server/sv_game.cpp +++ b/code/server/sv_game.cpp @@ -236,9 +236,19 @@ static void SV_GetUsercmd( int clientNum, usercmd_t* cmd ) static qbool SV_G_GetValue( char* value, int valueSize, const char* key ) { - if( Q_stricmp(key, "trap_LocateInteropData") == 0 ) { - Com_sprintf( value, valueSize, "%d", G_EXT_LOCATEINTEROPDATA ); - return qtrue; + struct syscall_t { const char* name; int number; }; + static const syscall_t syscalls[] = { + { "trap_LocateInteropData", G_EXT_LOCATEINTEROPDATA }, + { "trap_Cvar_SetRange", G_EXT_CVAR_SETRANGE }, + { "trap_Cvar_SetHelp", G_EXT_CVAR_SETHELP }, + { "trap_Cmd_SetHelp", G_EXT_CMD_SETHELP } + }; + + for ( int i = 0; i < ARRAY_LEN( syscalls ); ++i ) { + if( Q_stricmp(key, syscalls[i].name) == 0 ) { + Com_sprintf( value, valueSize, "%d", syscalls[i].number ); + return qtrue; + } } return qfalse; @@ -266,6 +276,7 @@ static intptr_t SV_GameSystemCalls( intptr_t* args ) case G_CVAR_REGISTER: Cvar_Register( VMA(1), VMA(2), VMA(3), args[4] ); + Cvar_SetModule( VMA(2), MODULE_GAME ); return 0; case G_CVAR_UPDATE: Cvar_Update( VMA(1) ); @@ -803,6 +814,18 @@ static intptr_t SV_GameSystemCalls( intptr_t* args ) interopBufferOutSize = args[4]; return 0; + case G_EXT_CVAR_SETRANGE: + Cvar_SetRange( VMA(1), (cvarType_t)args[2], VMA(3), VMA(4) ); + return 0; + + case G_EXT_CVAR_SETHELP: + Cvar_SetHelp( VMA(1), VMA(2) ); + return 0; + + case G_EXT_CMD_SETHELP: + Cmd_SetHelp( VMA(1), VMA(2) ); + return 0; + default: Com_Error( ERR_DROP, "Bad game system trap: %i", args[0] ); } diff --git a/code/server/sv_init.cpp b/code/server/sv_init.cpp index cb566bc..67f3554 100644 --- a/code/server/sv_init.cpp +++ b/code/server/sv_init.cpp @@ -525,6 +525,48 @@ void SV_SpawnServer( const char* mapname ) QSUBSYSTEM_INIT_DONE( "Server" ); } + +static const cvarTableItem_t sv_cvars[] = +{ + // serverinfo vars + { &sv_gametype, "g_gametype", "0", CVAR_SERVERINFO | CVAR_LATCH, CVART_INTEGER, NULL, NULL, "game mode" }, + { NULL, "protocol", XSTRING(PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_ROM, CVART_INTEGER, NULL, NULL, "protocol version" }, + { &sv_mapname, "mapname", "nomap", CVAR_SERVERINFO | CVAR_ROM, CVART_STRING, NULL, NULL, "name of the loaded map" }, + { NULL, "sv_currentPak", "0", CVAR_SERVERINFO | CVAR_ROM, CVART_INTEGER, NULL, NULL, "checksum of the pak the current map is from" }, + { &sv_privateClients, "sv_privateClients", "0", CVAR_SERVERINFO, CVART_INTEGER, "0", XSTRING(MAX_CLIENTS), "number of password-reserved player slots" }, + { &sv_hostname, "sv_hostname", "noname", CVAR_SERVERINFO | CVAR_ARCHIVE, CVART_STRING, NULL, NULL, "server name" }, + { &sv_maxclients, "sv_maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(MAX_CLIENTS), "max. player count" }, + { &sv_minRate, "sv_minRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, CVART_INTEGER, "0", NULL, "min. rate allowed, 0 means no limit" }, + { &sv_maxRate, "sv_maxRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, CVART_INTEGER, "0", NULL, "max. rate allowed, 0 means no limit" }, + { &sv_minPing, "sv_minPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, CVART_INTEGER, "0", NULL, "min. ping allowed, 0 means no limit" }, + { &sv_maxPing, "sv_maxPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO, CVART_INTEGER, "0", NULL, "max. ping allowed, 0 means no limit" }, + { &sv_floodProtect, "sv_floodProtect", "1", CVAR_ARCHIVE | CVAR_SERVERINFO, CVART_BOOL, NULL, NULL, "prevents malicious users from lagging the entire server" }, + // systeminfo vars + { NULL, "sv_cheats", "0", CVAR_SYSTEMINFO | CVAR_ROM, CVART_BOOL, NULL, NULL, "enables cheat commands and changing cheat cvars" }, + { &sv_serverid, "sv_serverid", "0", CVAR_SYSTEMINFO | CVAR_ROM, CVART_INTEGER, NULL, NULL, "server session identifier" }, + { &sv_pure, "sv_pure", "1", CVAR_SYSTEMINFO | CVAR_ROM, CVART_BOOL, NULL, NULL, "disables native code and forces client pk3s to match the server's" }, + { NULL, "sv_paks", "", CVAR_SYSTEMINFO | CVAR_ROM, CVART_STRING, NULL, NULL, "checksums of the paks you're allowed to load data from" }, + { NULL, "sv_pakNames", "", CVAR_SYSTEMINFO | CVAR_ROM, CVART_STRING, NULL, NULL, "names of the paks you're allowed to load data from" }, + { NULL, "sv_referencedPaks", "", CVAR_SYSTEMINFO | CVAR_ROM, CVART_STRING, NULL, NULL, "checksums of the paks you might need to download" }, + { NULL, "sv_referencedPakNames", "", CVAR_SYSTEMINFO | CVAR_ROM, CVART_STRING, NULL, NULL, "name of the paks you might need to download" }, + // server vars + { &sv_rconPassword, "rconPassword", "", CVAR_TEMP, CVART_STRING, NULL, NULL, "password for /rcon access" }, + { &sv_privatePassword, "sv_privatePassword", "", CVAR_TEMP, CVART_STRING, NULL, NULL, "password for the sv_privateClients slots" }, + { &sv_fps, "sv_fps", "30", CVAR_TEMP, CVART_INTEGER, "10", "40", "snapshot generation frequency" }, + { &sv_timeout, "sv_timeout", "200", CVAR_TEMP, CVART_INTEGER, "0", NULL, "max. seconds allowed without any messages" }, + { &sv_zombietime, "sv_zombietime", "2", CVAR_TEMP, CVART_INTEGER, "0", NULL, "seconds to sink messages after disconnect" }, + { NULL, "nextmap", "", CVAR_TEMP, CVART_STRING, NULL, NULL, "name of the next map in the rotation" }, + { &sv_allowDownload, "sv_allowDownload", "0", CVAR_SERVERINFO, CVART_BOOL, NULL, NULL, "enables slow pk3 downloads directly from the server" }, + { &sv_reconnectlimit, "sv_reconnectlimit", "3", 0, CVART_INTEGER, "0", NULL, "min. seconds between connection attempts" }, + { &sv_padPackets, "sv_padPackets", "0", 0, CVART_BOOL, NULL, NULL, "add nop bytes to messages" }, + { &sv_killserver, "sv_killserver", "0", 0, CVART_BOOL, NULL, NULL, "menu system can set to 1 to shut server down" }, + { NULL, "sv_mapChecksum", "", CVAR_ROM, CVART_INTEGER, NULL, NULL, ".bsp file checksum" }, + { &sv_lanForceRate, "sv_lanForceRate", "1", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "1 means uncapped rate on LAN" }, + { &sv_strictAuth, "sv_strictAuth", "0", CVAR_ARCHIVE, CVART_BOOL, NULL, NULL, "requires CD key authentication" }, + { &sv_minRebootDelayMins, "sv_minRebootDelayMins", "120", 0, CVART_INTEGER, "60", NULL, "min. minutes before rebooting the server" } +}; + + /* =============== SV_Init @@ -537,47 +579,8 @@ void SV_BotInitBotLib(void); void SV_Init() { SV_AddOperatorCommands(); - - // serverinfo vars - sv_gametype = Cvar_Get ("g_gametype", "0", CVAR_SERVERINFO | CVAR_LATCH ); - Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_ROM); - sv_mapname = Cvar_Get ("mapname", "nomap", CVAR_SERVERINFO | CVAR_ROM); - Cvar_Get ("sv_currentPak", "", CVAR_SERVERINFO | CVAR_ROM); - sv_privateClients = Cvar_Get ("sv_privateClients", "0", CVAR_SERVERINFO); - sv_hostname = Cvar_Get ("sv_hostname", "noname", CVAR_SERVERINFO | CVAR_ARCHIVE ); - sv_maxclients = Cvar_Get ("sv_maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH); - - sv_minRate = Cvar_Get ("sv_minRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); - sv_maxRate = Cvar_Get ("sv_maxRate", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); - sv_minPing = Cvar_Get ("sv_minPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); - sv_maxPing = Cvar_Get ("sv_maxPing", "0", CVAR_ARCHIVE | CVAR_SERVERINFO ); - sv_floodProtect = Cvar_Get ("sv_floodProtect", "1", CVAR_ARCHIVE | CVAR_SERVERINFO ); - - // systeminfo - Cvar_Get ("sv_cheats", "1", CVAR_SYSTEMINFO | CVAR_ROM ); - sv_serverid = Cvar_Get ("sv_serverid", "0", CVAR_SYSTEMINFO | CVAR_ROM ); - sv_pure = Cvar_Get ("sv_pure", "1", CVAR_SYSTEMINFO | CVAR_ROM ); - Cvar_Get ("sv_paks", "", CVAR_SYSTEMINFO | CVAR_ROM ); - Cvar_Get ("sv_pakNames", "", CVAR_SYSTEMINFO | CVAR_ROM ); - Cvar_Get ("sv_referencedPaks", "", CVAR_SYSTEMINFO | CVAR_ROM ); - Cvar_Get ("sv_referencedPakNames", "", CVAR_SYSTEMINFO | CVAR_ROM ); - - // server vars - sv_rconPassword = Cvar_Get ("rconPassword", "", CVAR_TEMP ); - sv_privatePassword = Cvar_Get ("sv_privatePassword", "", CVAR_TEMP ); - sv_fps = Cvar_Get ("sv_fps", "20", CVAR_TEMP ); - sv_timeout = Cvar_Get ("sv_timeout", "200", CVAR_TEMP ); - sv_zombietime = Cvar_Get ("sv_zombietime", "2", CVAR_TEMP ); - Cvar_Get ("nextmap", "", CVAR_TEMP ); - - sv_allowDownload = Cvar_Get ("sv_allowDownload", "0", CVAR_SERVERINFO); - sv_reconnectlimit = Cvar_Get ("sv_reconnectlimit", "3", 0); - sv_showloss = Cvar_Get ("sv_showloss", "0", 0); - sv_padPackets = Cvar_Get ("sv_padPackets", "0", 0); - sv_killserver = Cvar_Get ("sv_killserver", "0", 0); - sv_mapChecksum = Cvar_Get ("sv_mapChecksum", "", CVAR_ROM); - sv_lanForceRate = Cvar_Get ("sv_lanForceRate", "1", CVAR_ARCHIVE ); - sv_strictAuth = Cvar_Get ("sv_strictAuth", "1", CVAR_ARCHIVE ); + + Cvar_RegisterArray( sv_cvars, MODULE_SERVER ); sv_master[0] = Cvar_Get ("sv_master1", MASTER_SERVER_NAME, 0 ); for (int i = 1; i < MAX_MASTER_SERVERS; ++i) diff --git a/code/server/sv_main.cpp b/code/server/sv_main.cpp index 0d45b1f..f5e34ac 100644 --- a/code/server/sv_main.cpp +++ b/code/server/sv_main.cpp @@ -38,11 +38,9 @@ cvar_t *sv_privateClients; // number of clients reserved for password cvar_t *sv_hostname; cvar_t *sv_master[MAX_MASTER_SERVERS]; // master server ip address cvar_t *sv_reconnectlimit; // minimum seconds between connect messages -cvar_t *sv_showloss; // report when usercmds are lost cvar_t *sv_padPackets; // add nop bytes to messages cvar_t *sv_killserver; // menu system can set to 1 to shut server down cvar_t *sv_mapname; -cvar_t *sv_mapChecksum; cvar_t *sv_serverid; cvar_t *sv_minRate; cvar_t *sv_maxRate; @@ -53,6 +51,7 @@ cvar_t *sv_pure; cvar_t *sv_floodProtect; cvar_t *sv_lanForceRate; // dedicated 1 (LAN) server forces local client rates to 99999 (bug #491) cvar_t *sv_strictAuth; +cvar_t *sv_minRebootDelayMins; @@ -792,7 +791,7 @@ void SV_Frame( int msec ) { // Some mods may still have code like "sin(cg.time / 1000.0f)". // IEEE 754 floats have a 23-bit mantissa. // Rounding errors will start after roughly ((1<<23) / (60*1000)) ~ 139.8 minutes. - const int minRebootTimeCvar = 60 * 1000 * Cvar_Get( "sv_minRebootDelayMins", "1440", 0 )->integer; + const int minRebootTimeCvar = 60 * 1000 * sv_minRebootDelayMins->integer; const int minRebootTimeConst = 60 * 60 * 1000; // absolute min. time: 1 hour const int maxRebootTime = 0x7FFFFFFF; // absolute max. time: ~ 24.86 days const int minRebootTime = max( minRebootTimeCvar, minRebootTimeConst ); diff --git a/code/win32/win_help.h b/code/win32/win_help.h new file mode 100644 index 0000000..9b66aa6 --- /dev/null +++ b/code/win32/win_help.h @@ -0,0 +1,9 @@ +#define help_in_mouse \ +"mouse input mode\n" \ +" 0 = disabled\n" \ +" 1 = raw input\n" \ +" 2 = win32 input" + +#define help_in_minimize \ +"hotkey to minimize/restore the window\n" \ +"Use /minimizekeynames to print the list of usable key names." diff --git a/code/win32/win_input.cpp b/code/win32/win_input.cpp index ed1064d..e928974 100644 --- a/code/win32/win_input.cpp +++ b/code/win32/win_input.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "../client/client.h" #include "win_local.h" +#include "win_help.h" struct Mouse { @@ -274,6 +275,8 @@ static void IN_StartupMouse() mouseSettingsSet = qfalse; cvar_t* in_mouse = Cvar_Get( "in_mouse", "1", CVAR_ARCHIVE|CVAR_LATCH ); + Cvar_SetRange( "in_mouse", CVART_INTEGER, "0", "2" ); + Cvar_SetHelp( "in_mouse", help_in_mouse ); in_mouse->modified = qfalse; if (!in_mouse->integer) { @@ -339,12 +342,15 @@ static void IN_Startup() void IN_Init() -{ +{ if (g_wv.inputInitialized) return; + + in_midi = Cvar_Get( "in_midi", "0", CVAR_ARCHIVE ); + Cvar_SetModule( "in_midi", MODULE_INPUT ); - in_midi = Cvar_Get( "in_midi", "0", CVAR_ARCHIVE ); - in_joystick = Cvar_Get( "in_joystick", "0", CVAR_ARCHIVE|CVAR_LATCH ); + in_joystick = Cvar_Get( "in_joystick", "0", CVAR_ARCHIVE|CVAR_LATCH ); + Cvar_SetModule( "in_joystick", MODULE_INPUT ); in_joystick->modified = qfalse; IN_Startup(); @@ -795,6 +801,7 @@ static void IN_StartupMIDI() in_mididevice = Cvar_Get ("in_mididevice", "0", CVAR_ARCHIVE); Cmd_AddCommand( "midiinfo", MidiInfo_f ); + Cmd_SetHelp( "midiinfo", "prints MIDI devices info" ); // // open the MIDI IN port @@ -1306,10 +1313,16 @@ static void WIN_PrintMinimizeKeyNames() static void IN_StartupHotKey( qbool fullStartUp ) { in_minimize = Cvar_Get( "in_minimize", "", CVAR_ARCHIVE ); + Cvar_SetHelp( "in_minimize", help_in_minimize ); + Cvar_SetModule( "in_minimize", MODULE_INPUT ); in_minimize->modified = qfalse; if ( fullStartUp ) + { Cmd_AddCommand( "minimizekeynames", &WIN_PrintMinimizeKeyNames ); + Cmd_SetHelp( "minimizekeynames", "prints all key names usable with in_minimize" ); + Cmd_SetModule( "minimizekeynames", MODULE_INPUT ); + } WIN_UnregisterHotKey(); @@ -1326,6 +1339,7 @@ static void IN_StartupHotKey( qbool fullStartUp ) static void IN_ShutDownHotKey() { + // @TODO: remove this once Sys_InitInput and Sys_ShutdownInput are done Cmd_RemoveCommand( "minimizekeynames" ); WIN_UnregisterHotKey(); @@ -1337,6 +1351,5 @@ static void IN_UpdateHotKey() if ( !in_minimize->modified ) return; - in_minimize->modified = qtrue; IN_StartupHotKey( qfalse ); } diff --git a/code/win32/win_main.cpp b/code/win32/win_main.cpp index c46fd38..3137bb9 100644 --- a/code/win32/win_main.cpp +++ b/code/win32/win_main.cpp @@ -542,8 +542,10 @@ void Sys_Init() #ifndef DEDICATED Cmd_AddCommand( "in_restart", Sys_In_Restart_f ); + Cmd_SetHelp( "in_restart", "restarts the input system" ); #endif Cmd_AddCommand( "net_restart", Sys_Net_Restart_f ); + Cmd_SetHelp( "net_restart", "restarts the network system" ); if ( !IsWindowsVistaOrGreater() ) Sys_Error( "%s requires Windows Vista or later", Q3_VERSION ); @@ -599,6 +601,8 @@ void WIN_UpdateMonitorIndexFromCvar() // r_monitor is the 1-based monitor index, 0 means primary monitor // use Cvar_Get to enforce the latched change, if any const int monitor = Cvar_Get( "r_monitor", "0", CVAR_ARCHIVE | CVAR_LATCH )->integer; + Cvar_SetRange( "r_monitor", CVART_INTEGER, "0", va("%d", g_wv.monitorCount) ); + Cvar_SetHelp( "r_monitor", "1-based monitor index, 0=primary" ); if ( monitor <= 0 || monitor > g_wv.monitorCount ) { g_wv.monitor = g_wv.primaryMonitor; diff --git a/makefiles/vs2013/cnq3-server.vcxproj b/makefiles/vs2013/cnq3-server.vcxproj index 64cce38..f0ecd45 100644 --- a/makefiles/vs2013/cnq3-server.vcxproj +++ b/makefiles/vs2013/cnq3-server.vcxproj @@ -267,6 +267,7 @@ copy "..\..\.bin\release_x64\cnq3-server-x64.pdb" "$(QUAKE3DIR)" + @@ -278,6 +279,7 @@ copy "..\..\.bin\release_x64\cnq3-server-x64.pdb" "$(QUAKE3DIR)" + @@ -297,6 +299,7 @@ copy "..\..\.bin\release_x64\cnq3-server-x64.pdb" "$(QUAKE3DIR)" + diff --git a/makefiles/vs2013/cnq3-server.vcxproj.filters b/makefiles/vs2013/cnq3-server.vcxproj.filters index 19fce0e..673d5f1 100644 --- a/makefiles/vs2013/cnq3-server.vcxproj.filters +++ b/makefiles/vs2013/cnq3-server.vcxproj.filters @@ -123,6 +123,9 @@ client + + client + client @@ -156,6 +159,9 @@ qcommon + + qcommon + qcommon @@ -213,6 +219,9 @@ win32 + + win32 + win32 diff --git a/makefiles/vs2013/cnq3.vcxproj b/makefiles/vs2013/cnq3.vcxproj index 5922800..7f5429c 100644 --- a/makefiles/vs2013/cnq3.vcxproj +++ b/makefiles/vs2013/cnq3.vcxproj @@ -271,6 +271,7 @@ copy "..\..\.bin\release_x64\cnq3-x64.pdb" "$(QUAKE3DIR)" + @@ -282,6 +283,7 @@ copy "..\..\.bin\release_x64\cnq3-x64.pdb" "$(QUAKE3DIR)" + @@ -299,6 +301,7 @@ copy "..\..\.bin\release_x64\cnq3-x64.pdb" "$(QUAKE3DIR)" + @@ -306,6 +309,7 @@ copy "..\..\.bin\release_x64\cnq3-x64.pdb" "$(QUAKE3DIR)" + diff --git a/makefiles/vs2013/cnq3.vcxproj.filters b/makefiles/vs2013/cnq3.vcxproj.filters index 2d3df46..17234ab 100644 --- a/makefiles/vs2013/cnq3.vcxproj.filters +++ b/makefiles/vs2013/cnq3.vcxproj.filters @@ -126,6 +126,9 @@ client + + client + client @@ -159,6 +162,9 @@ qcommon + + qcommon + qcommon @@ -210,6 +216,9 @@ renderer + + renderer + renderer @@ -231,6 +240,9 @@ win32 + + win32 + win32 diff --git a/makefiles/vs2013/renderer.vcxproj b/makefiles/vs2013/renderer.vcxproj index 67f8cec..ea98c7f 100644 --- a/makefiles/vs2013/renderer.vcxproj +++ b/makefiles/vs2013/renderer.vcxproj @@ -208,6 +208,7 @@ +