diff --git a/README b/README index 74bb9192..903f5158 100644 --- a/README +++ b/README @@ -214,15 +214,9 @@ New cvars ipv6 servers on the local network net_mcastiface - outgoing interface to use for scan - oldprotocol - when encountering a server/client that - only supports the version configured in - this cvar, ioquake3 will use the old and - less secure protocol from quake3 1.32c. + protocol - Allow changing protocol version (startup only) - protocol - Allow changing protocol version that is - sent to the server (startup only) - r_allowResize - make window resizable (SDL only) r_ext_texture_filter_anisotropic - anisotropic texture filtering r_zProj - distance of observer camera to projection @@ -283,8 +277,7 @@ New commands which - print out the path on disk to a loaded item - ---------------------------------------------------------- README for Users ----- +------------------------------------------------------------ Miscellaneous ----- Using shared libraries instead of qvm To force Q3 to use shared libraries instead of qvms run it with the following @@ -312,6 +305,175 @@ Help! Ioquake3 won't give me an fps of X anymore when setting com_maxfps! In this case you can always revert back to the old behaviour by setting the cvar com_busyWait to 1. +QuakeLive mouse acceleration (patch and this text written by TTimo from id) + I've been using an experimental mouse acceleration code for a while, and + decided to make it available to everyone. Don't be too worried if you don't + understand the explanations below, this is mostly intended for advanced + players: + To enable it, set cl_mouseAccelStyle 1 (0 is the default/legacy behavior) + + New style is controlled with 3 cvars: + + sensitivity + cl_mouseAccel + cl_mouseAccelOffset + + The old code (cl_mouseAccelStyle 0) can be difficult to calibrate because if + you have a base sensitivity setup, as soon as you set a non zero acceleration + your base sensitivity at low speeds will change as well. The other problem + with style 0 is that you are stuck on a square (power of two) acceleration + curve. + + The new code tries to solve both problems: + + Once you setup your sensitivity to feel comfortable and accurate enough for + low mouse deltas with no acceleration (cl_mouseAccel 0), you can start + increasing cl_mouseAccel and tweaking cl_mouseAccelOffset to get the + amplification you want for high deltas with little effect on low mouse deltas. + + cl_mouseAccel is a power value. Should be >= 1, 2 will be the same power curve + as style 0. The higher the value, the faster the amplification grows with the + mouse delta. + + cl_mouseAccelOffset sets how much base mouse delta will be doubled by + acceleration. The closer to zero you bring it, the more acceleration will + happen at low speeds. This is also very useful if you are changing to a new + mouse with higher dpi, if you go from 500 to 1000 dpi, you can divide your + cl_mouseAccelOffset by two to keep the same overall 'feel' (you will likely + gain in precision when you do that, but that is not related to mouse + acceleration). + + Mouse acceleration is tricky to configure, and when you do you'll have to + re-learn your aiming. But you will find that it's very much forth it in the + long run. + + If you try the new acceleration code and start using it, I'd be very + interested by your feedback. + +64bit mods + If you wish to compile external mods as shared libraries on a 64bit platform, + and the mod source is derived from the id Q3 SDK, you will need to modify the + interface code a little. Open the files ending in _syscalls.c and change + every instance of int to intptr_t in the declaration of the syscall function + pointer and the dllEntry function. Also find the vmMain function for each + module (usually in cg_main.c g_main.c etc.) and similarly replace the return + value in the prototype with intptr_t (arg0, arg1, ...stay int). + + Add the following code snippet to q_shared.h: + + #ifdef Q3_VM + typedef int intptr_t; + #else + #include + #endif + + Note if you simply wish to run mods on a 64bit platform you do not need to + recompile anything since by default Q3 uses a virtual machine system. + +Creating mods compatible with Q3 1.32b + If you're using this package to create mods for the last official release of + Q3, it is necessary to pass the commandline option '-vq3' to your invocation + of q3asm. This is because by default q3asm outputs an updated qvm format that + is necessary to fix a bug involving the optimizing pass of the x86 vm JIT + compiler. + +Creating standalone games + Have you finished the daunting task of removing all dependencies on the Q3 + game data? You probably now want to give your users the opportunity to play + the game without owning a copy of Q3, which consequently means removing cd-key + and authentication server checks. In addition to being a straightforward Q3 + client, ioquake3 also purports to be a reliable and stable code base on which + to base your game project. + + However, before you start compiling your own version of ioquake3, you have to + ask yourself: Have we changed or will we need to change anything of importance + in the engine? + + If your answer to this question is "no", it probably makes no sense to build + your own binaries. Instead, you can just use the pre-built binaries on the + website. Just make sure the game is called with: + + +set com_basegame + + in any links/scripts you install for your users to start the game. The + binary must not detect any original quake3 game pak files. If this + condition is met, the game will set com_standalone to 1 and is then running + in stand alone mode. + + If you want the engine to use a different directory in your homepath than + e.g. "Quake3" on Windows or ".q3a" on Linux, then set a new name at startup + by adding + + +set com_homepath + + to the command line. Then you can control which kind of messages to send to + the master server: + + +set sv_heartbeat +set sv_flatline + +set cl_gamename + + The and message can be specific to your game. The + flatline message is sent to signal the master server that the game server is + quitting. Vanilla quake3 uses "QuakeArena-1" both for the heartbeat and + flatline messages. + The cl_gamename message is for dpmaster to specify which game the client + wants a server list for. It is only used in the new ipv6 based getServersExt + query. + + Example line: + + +set com_basegame basefoo +set com_homepath .foo + +set sv_heartbeat fooalive +set sv_flatline foodead + +set cl_gamename foo + + + If you really changed parts that would make vanilla ioquake3 incompatible with + your mod, we have included another way to conveniently build a stand-alone + binary. Just run make with the option BUILD_STANDALONE=1. Don't forget to edit + the PRODUCT_NAME and subsequent #defines in qcommon/q_shared.h with + information appropriate for your project. + + While a lot of work has been put into ioquake3 that you can benefit from free + of charge, it does not mean that you have no obligations to fulfil. Please be + aware that as soon as you start distributing your game with an engine based on + our sources we expect you to fully comply with the requirements as stated in + the GPL. That includes making sources and modifications you made to the + ioquake3 engine as well as the game-code used to compile the .qvm files for + the game logic freely available to everyone. Furthermore, note that the "QIIIA + Game Source License" prohibits distribution of mods that are intended to + operate on a version of Q3 not sanctioned by id software: + + "with this Agreement, ID grants to you the non-exclusive and limited right + to distribute copies of the Software ... for operation only with the full + version of the software game QUAKE III ARENA" + + This means that if you're creating a standalone game, you cannot use said + license on any portion of the product. As the only other license this code has + been released under is the GPL, this is the only option. + + This does NOT mean that you cannot market this game commercially. The GPL does + not prohibit commercial exploitation and all assets (e.g. textures, sounds, + maps) created by yourself are your property and can be sold like every other + game you find in stores. + +cl_guid Support + cl_guid is a cvar which is part of the client's USERINFO string. Its value + is a 32 character string made up of [a-f] and [0-9] characters. This + value is pseudo-unique for every player. Id's Quake 3 Arena client also + sets cl_guid, but only if Punkbuster is enabled on the client. + + If cl_guidServerUniq is non-zero (the default), then this value is also + pseudo-unique for each server a client connects to (based on IP:PORT of + the server). + + The purpose of cl_guid is to add an identifier for each player on + a server. This value can be reset by the client at any time so it's not + useful for blocking access. However, it can have at least two uses in + your mod's game code: + 1) improve logging to allow statistical tools to index players by more + than just name + 2) granting some weak admin rights to players without requiring passwords + Using HTTP/FTP Download Support (Server) You can enable redirected downloads on your server even if it's not an ioquake3 server. You simply need to use the 'sets' command to put @@ -415,208 +577,6 @@ SDL Keyboard Differences text. Also, in addition to the nominated console keys, Shift-ESC is hard coded to always toggle the console. -QuakeLive mouse acceleration (patch and this text written by TTimo from id) - I've been using an experimental mouse acceleration code for a while, and - decided to make it available to everyone. Don't be too worried if you don't - understand the explanations below, this is mostly intended for advanced - players: - To enable it, set cl_mouseAccelStyle 1 (0 is the default/legacy behavior) - - New style is controlled with 3 cvars: - - sensitivity - cl_mouseAccel - cl_mouseAccelOffset - - The old code (cl_mouseAccelStyle 0) can be difficult to calibrate because if - you have a base sensitivity setup, as soon as you set a non zero acceleration - your base sensitivity at low speeds will change as well. The other problem - with style 0 is that you are stuck on a square (power of two) acceleration - curve. - - The new code tries to solve both problems: - - Once you setup your sensitivity to feel comfortable and accurate enough for - low mouse deltas with no acceleration (cl_mouseAccel 0), you can start - increasing cl_mouseAccel and tweaking cl_mouseAccelOffset to get the - amplification you want for high deltas with little effect on low mouse deltas. - - cl_mouseAccel is a power value. Should be >= 1, 2 will be the same power curve - as style 0. The higher the value, the faster the amplification grows with the - mouse delta. - - cl_mouseAccelOffset sets how much base mouse delta will be doubled by - acceleration. The closer to zero you bring it, the more acceleration will - happen at low speeds. This is also very useful if you are changing to a new - mouse with higher dpi, if you go from 500 to 1000 dpi, you can divide your - cl_mouseAccelOffset by two to keep the same overall 'feel' (you will likely - gain in precision when you do that, but that is not related to mouse - acceleration). - - Mouse acceleration is tricky to configure, and when you do you'll have to - re-learn your aiming. But you will find that it's very much forth it in the - long run. - - If you try the new acceleration code and start using it, I'd be very - interested by your feedback. - - ----------------------------------------------------- README for Developers ----- - -64bit mods - If you wish to compile external mods as shared libraries on a 64bit platform, - and the mod source is derived from the id Q3 SDK, you will need to modify the - interface code a little. Open the files ending in _syscalls.c and change - every instance of int to intptr_t in the declaration of the syscall function - pointer and the dllEntry function. Also find the vmMain function for each - module (usually in cg_main.c g_main.c etc.) and similarly replace the return - value in the prototype with intptr_t (arg0, arg1, ...stay int). - - Add the following code snippet to q_shared.h: - - #ifdef Q3_VM - typedef int intptr_t; - #else - #include - #endif - - Note if you simply wish to run mods on a 64bit platform you do not need to - recompile anything since by default Q3 uses a virtual machine system. - -Creating mods compatible with Q3 1.32b - If you're using this package to create mods for the last official release of - Q3, it is necessary to pass the commandline option '-vq3' to your invocation - of q3asm. This is because by default q3asm outputs an updated qvm format that - is necessary to fix a bug involving the optimizing pass of the x86 vm JIT - compiler. - -Creating standalone games - Have you finished the daunting task of removing all dependencies on the Q3 - game data? You probably now want to give your users the opportunity to play - the game without owning a copy of Q3, which consequently means removing cd-key - and authentication server checks. In addition to being a straightforward Q3 - client, ioquake3 also purports to be a reliable and stable code base on which - to base your game project. - - However, before you start compiling your own version of ioquake3, you have to - ask yourself: Have we changed or will we need to change anything of importance - in the engine? - - If your answer to this question is "no", it probably makes no sense to build - your own binaries. Instead, you can just use the pre-built binaries on the - website. Just make sure the game is called with: - - +set com_basegame - - in any links/scripts you install for your users to start the game. The - binary must not detect any original quake3 game pak files. If this - condition is met, the game will set com_standalone to 1 and is then running - in stand alone mode. - - If you want the engine to use a different directory in your homepath than - e.g. "Quake3" on Windows or ".q3a" on Linux, then set a new name at startup - by adding - - +set com_homepath - - to the command line. You can also control which kind of messages to send to - the master server: - - +set sv_heartbeat +set sv_flatline - +set cl_gamename - - The and message can be specific to your game. The - flatline message is sent to signal the master server that the game server is - quitting. Vanilla quake3 uses "QuakeArena-1" both for the heartbeat and - flatline messages. - The cl_gamename message is for dpmaster to specify which game the client - wants a server list for. It is only used in the new ipv6 based getServersExt - query. - - Example line: - - +set com_basegame basefoo +set com_homepath .foo - +set sv_heartbeat fooalive +set sv_flatline foodead - +set cl_gamename foo - - - If you really changed parts that would make vanilla ioquake3 incompatible with - your mod, we have included another way to conveniently build a stand-alone - binary. Just run make with the option BUILD_STANDALONE=1. Don't forget to edit - the PRODUCT_NAME and subsequent #defines in qcommon/q_shared.h with - information appropriate for your project. - - While a lot of work has been put into ioquake3 that you can benefit from free - of charge, it does not mean that you have no obligations to fulfil. Please be - aware that as soon as you start distributing your game with an engine based on - our sources we expect you to fully comply with the requirements as stated in - the GPL. That includes making sources and modifications you made to the - ioquake3 engine as well as the game-code used to compile the .qvm files for - the game logic freely available to everyone. Furthermore, note that the "QIIIA - Game Source License" prohibits distribution of mods that are intended to - operate on a version of Q3 not sanctioned by id software: - - "with this Agreement, ID grants to you the non-exclusive and limited right - to distribute copies of the Software ... for operation only with the full - version of the software game QUAKE III ARENA" - - This means that if you're creating a standalone game, you cannot use said - license on any portion of the product. As the only other license this code has - been released under is the GPL, this is the only option. - - This does NOT mean that you cannot market this game commercially. The GPL does - not prohibit commercial exploitation and all assets (e.g. textures, sounds, - maps) created by yourself are your property and can be sold like every other - game you find in stores. - -Network protocols - There are now two cvars that give you some degree of freedom over the reported - protocol versions between clients and servers: "protocol" and "oldprotocol". - The reason for this is that some standalone games increased the protocol - number even though nothing really changed in their protocol and the ioquake3 - engine is still fully compatible. - - In order to fix a vulnerability in the network protocol as outlined in - - http://aluigi.altervista.org/papers/q3noclient.txt - - a new network protocol was introduced that defends against such attacks. - Unfortunately, this protocol will be incompatible to the original quake3 1.32c - which is the latest official release from id. - Luckily, ioquake3 has backwards compatibility, on the client as well as on the - server. This means ioquake3 players can play on old servers just as ioquake3 - servers are able to service old clients. - - The cvar "protocol" denotes the protocol version for the new hardened - protocol, whereas the "oldprotocol" cvar denotes the protocol version for the - legacy protocol. - If the value for "oldprotocol" and "protocol" is identical, then the legacy - protocol is always used. If oldprotocol is set to 0, then support for the - legacy protocol is disabled. - - Mods that use a standalone engine obviously do not require dual protocol - support, and it is turned off if the engine is compiled with STANDALONE per - default. You can enable it in q_shared.h if desired by defining - PROTOCOL_SUPPORT_OLD. - -cl_guid Support - cl_guid is a cvar which is part of the client's USERINFO string. Its value - is a 32 character string made up of [a-f] and [0-9] characters. This - value is pseudo-unique for every player. Id's Quake 3 Arena client also - sets cl_guid, but only if Punkbuster is enabled on the client. - - If cl_guidServerUniq is non-zero (the default), then this value is also - pseudo-unique for each server a client connects to (based on IP:PORT of - the server). - - The purpose of cl_guid is to add an identifier for each player on - a server. This value can be reset by the client at any time so it's not - useful for blocking access. However, it can have at least two uses in - your mod's game code: - 1) improve logging to allow statistical tools to index players by more - than just name - 2) granting some weak admin rights to players without requiring passwords - PNG support ioquake3 supports the use of PNG (Portable Network Graphic) images as textures. It should be noted that the use of such images in a map will diff --git a/code/client/cl_main.c b/code/client/cl_main.c index f74f0c30..719902a6 100644 --- a/code/client/cl_main.c +++ b/code/client/cl_main.c @@ -533,6 +533,7 @@ void CL_WriteDemoMessage ( msg_t *msg, int headerBytes ) { len = clc.serverMessageSequence; swlen = LittleLong( len ); FS_Write (&swlen, 4, clc.demofile); + // skip the packet sequencing information len = msg->cursize - headerBytes; swlen = LittleLong(len); @@ -635,24 +636,14 @@ void CL_Record_f( void ) { if ( Cmd_Argc() == 2 ) { s = Cmd_Argv(1); Q_strncpyz( demoName, s, sizeof( demoName ) ); -#ifdef PROTOCOL_SUPPORT_OLD - if(clc.compat) - Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_oldprotocol->integer); - else -#endif - Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer); + Com_sprintf (name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer ); } else { int number; // scan for a free demo name for ( number = 0 ; number <= 9999 ; number++ ) { CL_DemoFilename( number, demoName ); -#ifdef PROTOCOL_SUPPORT_OLD - if(clc.compat) - Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_oldprotocol->integer); - else -#endif - Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer); + Com_sprintf (name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer ); if (!FS_FileExists(name)) break; // file doesn't exist @@ -674,6 +665,7 @@ void CL_Record_f( void ) { clc.spDemoRecording = qfalse; } + Q_strncpyz( clc.demoName, demoName, sizeof( clc.demoName ) ); // don't start saving messages until a non-delta compressed message is received @@ -897,62 +889,36 @@ void CL_ReadDemoMessage( void ) { CL_WalkDemoExt ==================== */ -static int CL_WalkDemoExt(char *arg, char *name, int *demofile) +static void CL_WalkDemoExt(char *arg, char *name, int *demofile) { int i = 0; *demofile = 0; -#ifdef PROTOCOL_SUPPORT_OLD - if(com_oldprotocol->integer > 0) - { - Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_oldprotocol->integer); - FS_FOpenFileRead(name, demofile, qtrue); - - if (*demofile) - { - Com_Printf("Demo file: %s\n", name); - return com_oldprotocol->integer; - } - } - - if(com_protocol->integer != com_oldprotocol->integer) -#endif - { - Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_protocol->integer); - FS_FOpenFileRead(name, demofile, qtrue); + Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_protocol->integer); - if (*demofile) - { - Com_Printf("Demo file: %s\n", name); - return com_protocol->integer; - } + FS_FOpenFileRead( name, demofile, qtrue ); + + if (*demofile) + { + Com_Printf("Demo file: %s\n", name); + return; } Com_Printf("Not found: %s\n", name); while(demo_protocols[i]) { -#ifdef PROTOCOL_SUPPORT_OLD - if(demo_protocols[i] == com_oldprotocol->integer) - continue; -#endif - if(demo_protocols[i] == com_protocol->integer) - continue; - Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, demo_protocols[i]); FS_FOpenFileRead( name, demofile, qtrue ); if (*demofile) { Com_Printf("Demo file: %s\n", name); - - return demo_protocols[i]; + break; } else Com_Printf("Not found: %s\n", name); i++; } - - return -1; } /* @@ -1012,11 +978,7 @@ void CL_PlayDemo_f( void ) { break; } - if(demo_protocols[i] || protocol == com_protocol->integer -#ifdef PROTOCOL_SUPPORT_OLD - || protocol == com_oldprotocol->integer -#endif - ) + if(demo_protocols[i] || protocol == com_protocol->integer) { Com_sprintf(name, sizeof(name), "demos/%s", arg); FS_FOpenFileRead(name, &clc.demofile, qtrue); @@ -1033,11 +995,11 @@ void CL_PlayDemo_f( void ) { Q_strncpyz(retry, arg, len + 1); retry[len] = '\0'; - protocol = CL_WalkDemoExt(retry, name, &clc.demofile); + CL_WalkDemoExt(retry, name, &clc.demofile); } } else - protocol = CL_WalkDemoExt(arg, name, &clc.demofile); + CL_WalkDemoExt(arg, name, &clc.demofile); if (!clc.demofile) { Com_Error( ERR_DROP, "couldn't open %s", name); @@ -1051,13 +1013,6 @@ void CL_PlayDemo_f( void ) { clc.demoplaying = qtrue; Q_strncpyz( cls.servername, Cmd_Argv(1), sizeof( cls.servername ) ); -#ifdef PROTOCOL_SUPPORT_OLD - if(protocol <= com_oldprotocol->integer) - clc.compat = qtrue; - else - clc.compat = qfalse; -#endif - // read demo messages until connected while ( cls.state >= CA_CONNECTED && cls.state < CA_PRIMED ) { CL_ReadDemoMessage(); @@ -2198,16 +2153,7 @@ void CL_CheckForResend( void ) { port = Cvar_VariableValue ("net_qport"); Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) ); - -#ifdef PROTOCOL_SUPPORT_OLD - if(com_oldprotocol->integer == com_protocol->integer) - clc.compat = qtrue; - - if(clc.compat) - Info_SetValueForKey(info, "protocol", va("%i", com_oldprotocol->integer)); - else -#endif - Info_SetValueForKey(info, "protocol", va("%i", com_protocol->integer)); + Info_SetValueForKey( info, "protocol", va("%i", com_protocol->integer ) ); Info_SetValueForKey( info, "qport", va("%i", port ) ); Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) ); @@ -2448,7 +2394,6 @@ Responses to broadcasts, etc void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { char *s; char *c; - int challenge; MSG_BeginReadingOOB( msg ); MSG_ReadLong( msg ); // skip the -1 @@ -2470,33 +2415,18 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { return; } - c = Cmd_Argv(2); - if(*c) - challenge = atoi(c); - -#ifdef PROTOCOL_SUPPORT_OLD - if(!clc.compat) + if(!NET_CompareAdr(from, clc.serverAddress)) { - if(!*c || challenge != clc.challenge) - { - Com_Printf("Bad challenge for challengeResponse. Ignored.\n"); - return; - } - } - else -#endif - { - if(!NET_CompareAdr(from, clc.serverAddress)) - { - // This challenge response is not coming from the expected address. - // Check whether we have a matching client challenge to prevent - // connection hi-jacking. + // This challenge response is not coming from the expected address. + // Check whether we have a matching client challenge to prevent + // connection hi-jacking. - if(!*c || challenge != clc.challenge) - { - Com_DPrintf("Challenge response received from unexpected source. Ignored.\n"); - return; - } + c = Cmd_Argv(2); + + if(!*c || atoi(c) != clc.challenge) + { + Com_DPrintf("Challenge response received from unexpected source. Ignored.\n"); + return; } } @@ -2527,34 +2457,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { Com_Printf( "connectResponse from wrong address. Ignored.\n" ); return; } - -#ifdef PROTOCOL_SUPPORT_OLD - if(!clc.compat) - { - c = Cmd_Argv(1); - - if(*c) - challenge = atoi(c); - else - { - Com_Printf("Bad connectResponse received. Ignored.\n"); - return; - } - - if(challenge != clc.challenge) - { - Com_Printf("ConnectResponse with bad challenge received. Ignored.\n"); - return; - } - } - - Netchan_Setup(NS_CLIENT, &clc.netchan, from, Cvar_VariableValue("net_qport"), - clc.challenge, clc.compat); -#else - Netchan_Setup(NS_CLIENT, &clc.netchan, from, Cvar_VariableValue("net_qport"), - clc.challenge); -#endif - + Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) ); cls.state = CA_CONNECTED; clc.lastPacketSentTime = -9999; // send first packet immediately return; @@ -2572,6 +2475,13 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { return; } + // a disconnect message from the server, which will happen if the server + // dropped the connection but it is still getting packets from us + if (!Q_stricmp(c, "disconnect")) { + CL_DisconnectPacket( from ); + return; + } + // echo request from server if ( !Q_stricmp(c, "echo") ) { NET_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) ); @@ -2591,33 +2501,10 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) { } // echo request from server - if(!Q_stricmp(c, "print")){ + if ( !Q_stricmp(c, "print") ) { s = MSG_ReadString( msg ); - - #ifdef PROTOCOL_SUPPORT_OLD - // Hack to detect legacy server protocol - if(cls.state == CA_CHALLENGING && com_oldprotocol->integer > 0) - { - char buf[128]; - int len; - - len = Com_sprintf(buf, sizeof(buf), "Server uses protocol version %d", - com_oldprotocol->integer); - - if(len < sizeof(buf) && !Q_strncmp(s, buf, len) && !isdigit(s[len])) - { - // This is an old, but compatible protocol version. - // Go back to connecting state. - clc.compat = qtrue; - cls.state = CA_CONNECTING; - return; - } - } - #endif - Q_strncpyz( clc.serverMessage, s, sizeof( clc.serverMessage ) ); Com_Printf( "%s", s ); - return; } @@ -3558,13 +3445,7 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) { // if this isn't the correct protocol version, ignore it prot = atoi( Info_ValueForKey( infoString, "protocol" ) ); - - if(prot != com_protocol->integer -#ifdef PROTOCOL_SUPPORT_OLD - && prot != com_oldprotocol->integer -#endif - ) - { + if ( prot != com_protocol->integer ) { Com_DPrintf( "Different protocol info packet: %s\n", infoString ); return; } diff --git a/code/client/cl_net_chan.c b/code/client/cl_net_chan.c index abea06d1..1433c434 100644 --- a/code/client/cl_net_chan.c +++ b/code/client/cl_net_chan.c @@ -147,6 +147,9 @@ void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) { Netchan_Transmit( chan, msg->cursize, msg->data ); } +extern int oldsize; +int newsize = 0; + /* ================= CL_Netchan_Process @@ -158,8 +161,7 @@ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { ret = Netchan_Process( chan, msg ); if (!ret) return qfalse; - CL_Netchan_Decode( msg ); - + newsize += msg->cursize; return qtrue; } diff --git a/code/client/client.h b/code/client/client.h index 828a1dc3..ac9f3aa5 100644 --- a/code/client/client.h +++ b/code/client/client.h @@ -260,10 +260,6 @@ typedef struct { float voipPower; #endif -#ifdef PROTOCOL_SUPPORT_OLD - qboolean compat; -#endif - // big stuff at end of structure so most offsets are 15 bits or less netchan_t netchan; } clientConnection_t; diff --git a/code/qcommon/common.c b/code/qcommon/common.c index c0e86f41..498614fc 100644 --- a/code/qcommon/common.c +++ b/code/qcommon/common.c @@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #endif int demo_protocols[] = -{ 67, 66, 0 }; +{ 66, 67, 68, 0 }; #define MAX_NUM_ARGVS 50 @@ -86,9 +86,6 @@ cvar_t *com_maxfpsMinimized; cvar_t *com_abnormalExit; cvar_t *com_standalone; cvar_t *com_protocol; -#ifdef PROTOCOL_SUPPORT_OLD -cvar_t *com_oldprotocol; -#endif cvar_t *com_basegame; cvar_t *com_homepath; cvar_t *com_busyWait; @@ -2713,9 +2710,6 @@ void Com_Init( char *commandLine ) { s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ ); com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO ); com_protocol = Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_INIT); -#ifdef PROTOCOL_SUPPORT_OLD - com_oldprotocol = Cvar_Get ("oldprotocol", va("%i", PROTOCOL_OLD_VERSION), CVAR_INIT); -#endif Sys_Init(); diff --git a/code/qcommon/files.c b/code/qcommon/files.c index 5ac02ab6..f6d8e3df 100644 --- a/code/qcommon/files.c +++ b/code/qcommon/files.c @@ -1030,11 +1030,6 @@ qboolean FS_IsDemoExt(const char *filename, int namelen) if(protocol == com_protocol->integer) return qtrue; -#ifdef PROTOCOL_SUPPORT_OLD - if(protocol == PROTOCOL_OLD_VERSION) - return qtrue; -#endif - for(index = 0; demo_protocols[index]; index++) { if(demo_protocols[index] == protocol) diff --git a/code/qcommon/net_chan.c b/code/qcommon/net_chan.c index 6a976872..5b359f92 100644 --- a/code/qcommon/net_chan.c +++ b/code/qcommon/net_chan.c @@ -83,12 +83,7 @@ Netchan_Setup called to open a channel to a remote system ============== */ -void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge -#ifdef PROTOCOL_SUPPORT_OLD - , qboolean compat -#endif - ) -{ +void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ) { Com_Memset (chan, 0, sizeof(*chan)); chan->sock = sock; @@ -96,10 +91,6 @@ void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int chan->qport = qport; chan->incomingSequence = 0; chan->outgoingSequence = 1; -#ifdef PROTOCOL_SUPPORT_OLD - chan->compat = compat; - chan->challenge = challenge; -#endif } // TTimo: unused, commenting out to make gcc happy @@ -199,24 +190,17 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) { msg_t send; byte send_buf[MAX_PACKETLEN]; int fragmentLength; - int outgoingSequence; // write the packet header MSG_InitOOB (&send, send_buf, sizeof(send_buf)); // <-- only do the oob here - outgoingSequence = chan->outgoingSequence | FRAGMENT_BIT; - MSG_WriteLong(&send, outgoingSequence); + MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT ); // send the qport if we are a client if ( chan->sock == NS_CLIENT ) { MSG_WriteShort( &send, qport->integer ); } -#ifdef PROTOCOL_SUPPORT_OLD - if(!chan->compat) -#endif - MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence)); - // copy the reliable message to the packet first fragmentLength = FRAGMENT_SIZE; if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) { @@ -284,17 +268,12 @@ void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) { MSG_InitOOB (&send, send_buf, sizeof(send_buf)); MSG_WriteLong( &send, chan->outgoingSequence ); + chan->outgoingSequence++; // send the qport if we are a client - if(chan->sock == NS_CLIENT) - MSG_WriteShort(&send, qport->integer); - -#ifdef PROTOCOL_SUPPORT_OLD - if(!chan->compat) -#endif - MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence)); - - chan->outgoingSequence++; + if ( chan->sock == NS_CLIENT ) { + MSG_WriteShort( &send, qport->integer ); + } MSG_WriteData( &send, data, length ); @@ -348,17 +327,6 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) { qport = MSG_ReadShort( msg ); } -#ifdef PROTOCOL_SUPPORT_OLD - if(!chan->compat) -#endif - { - int checksum = MSG_ReadLong(msg); - - // UDP spoofing protection - if(NETCHAN_GENCHECKSUM(chan->challenge, sequence) != checksum) - return qfalse; - } - // read the fragment information if ( fragmented ) { fragmentStart = MSG_ReadShort( msg ); diff --git a/code/qcommon/q_shared.c b/code/qcommon/q_shared.c index aae00879..36261335 100644 --- a/code/qcommon/q_shared.c +++ b/code/qcommon/q_shared.c @@ -962,7 +962,7 @@ int Q_CountChar(const char *string, char tocount) return count; } -int QDECL Com_sprintf(char *dest, int size, const char *fmt, ...) +void QDECL Com_sprintf(char *dest, int size, const char *fmt, ...) { int len; va_list argptr; @@ -973,8 +973,6 @@ int QDECL Com_sprintf(char *dest, int size, const char *fmt, ...) if(len >= size) Com_Printf("Com_sprintf: Output length %d too short, require %d bytes.\n", size, len); - - return len; } /* diff --git a/code/qcommon/q_shared.h b/code/qcommon/q_shared.h index 696ee53a..190791e0 100644 --- a/code/qcommon/q_shared.h +++ b/code/qcommon/q_shared.h @@ -34,7 +34,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define GAMENAME_FOR_MASTER "iofoo3" // must NOT contain whitespaces #define HEARTBEAT_FOR_MASTER GAMENAME_FOR_MASTER #define FLATLINE_FOR_MASTER GAMENAME_FOR_MASTER "dead" -// #define PROTOCOL_SUPPORT_OLD // You probably don't need this for your standalone game #else #define PRODUCT_NAME "ioq3" #define BASEGAME "baseq3" @@ -43,7 +42,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define GAMENAME_FOR_MASTER "Quake3Arena" #define HEARTBEAT_FOR_MASTER "QuakeArena-1" #define FLATLINE_FOR_MASTER HEARTBEAT_FOR_MASTER - #define PROTOCOL_SUPPORT_OLD #endif #define BASETA "missionpack" @@ -684,7 +682,7 @@ void Parse2DMatrix (char **buf_p, int y, int x, float *m); void Parse3DMatrix (char **buf_p, int z, int y, int x, float *m); int Com_HexStrToInt( const char *str ); -int QDECL Com_sprintf (char *dest, int size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); +void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); char *Com_SkipTokens( char *s, int numTokens, char *sep ); char *Com_SkipCharset( char *s, char *sep ); diff --git a/code/qcommon/qcommon.h b/code/qcommon/qcommon.h index e21126ce..c20eddec 100644 --- a/code/qcommon/qcommon.h +++ b/code/qcommon/qcommon.h @@ -194,8 +194,7 @@ void NET_Sleep(int msec); #define MAX_DOWNLOAD_WINDOW 8 // max of eight download frames #define MAX_DOWNLOAD_BLKSIZE 2048 // 2048 byte block chunks - -#define NETCHAN_GENCHECKSUM(challenge, sequence) ((challenge) ^ ((sequence) * (challenge))) + /* Netchan handles packet fragmentation and out of order / duplicate suppression @@ -224,20 +223,10 @@ typedef struct { int unsentFragmentStart; int unsentLength; byte unsentBuffer[MAX_MSGLEN]; - - int challenge; - -#ifdef PROTOCOL_SUPPORT_OLD - qboolean compat; -#endif } netchan_t; void Netchan_Init( int qport ); -void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge -#ifdef PROTOCOL_SUPPORT_OLD - , qboolean compat -#endif -); +void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ); void Netchan_Transmit( netchan_t *chan, int length, const byte *data ); void Netchan_TransmitNextFragment( netchan_t *chan ); @@ -253,8 +242,7 @@ PROTOCOL ============================================================== */ -#define PROTOCOL_VERSION 69 -#define PROTOCOL_OLD_VERSION 68 +#define PROTOCOL_VERSION 68 // 1.31 - 67 // maintain a list of compatible protocols for demo playing @@ -869,9 +857,6 @@ extern cvar_t *cl_packetdelay; extern cvar_t *sv_packetdelay; extern cvar_t *com_protocol; -#ifdef PROTOCOL_SUPPORT_OLD -extern cvar_t *com_oldprotocol; -#endif // com_speeds times extern int time_game; diff --git a/code/server/server.h b/code/server/server.h index 2497d2e2..c8e0a8ca 100644 --- a/code/server/server.h +++ b/code/server/server.h @@ -188,11 +188,7 @@ typedef struct client_s { #endif int oldServerTime; - qboolean csUpdated[MAX_CONFIGSTRINGS+1]; - -#ifdef PROTOCOL_SUPPORT_OLD - qboolean compat; -#endif + qboolean csUpdated[MAX_CONFIGSTRINGS+1]; } client_t; //============================================================================= @@ -201,11 +197,7 @@ typedef struct client_s { // MAX_CHALLENGES is made large to prevent a denial // of service attack that could cycle all of them // out before legitimate users connected -#define MAX_CHALLENGES 2048 -// Allow a certain amount of challenges to have the same IP address -// to make it a bit harder to DOS one single IP address from connecting -// while not allowing a single ip to grab all challenge resources -#define MAX_CHALLENGES_MULTI (MAX_CHALLENGES / 2) +#define MAX_CHALLENGES 1024 #define AUTHORIZE_TIMEOUT 5000 diff --git a/code/server/sv_client.c b/code/server/sv_client.c index e5f3c8eb..f4ebe60f 100644 --- a/code/server/sv_client.c +++ b/code/server/sv_client.c @@ -55,10 +55,8 @@ void SV_GetChallenge(netadr_t from) int i; int oldest; int oldestTime; - int oldestClientTime; - int clientChallenge; + const char *clientChallenge = Cmd_Argv(1); challenge_t *challenge; - qboolean wasfound = qfalse; // ignore if we are in single player if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) { @@ -66,30 +64,15 @@ void SV_GetChallenge(netadr_t from) } oldest = 0; - oldestClientTime = oldestTime = 0x7fffffff; + oldestTime = 0x7fffffff; // see if we already have a challenge for this ip challenge = &svs.challenges[0]; - clientChallenge = atoi(Cmd_Argv(1)); - - for(i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) - { - if(!challenge->connected && NET_CompareAdr(from, challenge->adr)) - { - wasfound = qtrue; - - if(challenge->time < oldestClientTime) - oldestClientTime = challenge->time; - } - - if(wasfound && i >= MAX_CHALLENGES_MULTI) - { - i = MAX_CHALLENGES; + for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) { + if (!challenge->connected && NET_CompareAdr( from, challenge->adr ) ) { break; } - - if(challenge->time < oldestTime) - { + if ( challenge->time < oldestTime ) { oldestTime = challenge->time; oldest = i; } @@ -99,16 +82,17 @@ void SV_GetChallenge(netadr_t from) { // this is the first time this client has asked for a challenge challenge = &svs.challenges[oldest]; - challenge->clientChallenge = clientChallenge; + challenge->clientChallenge = 0; challenge->adr = from; challenge->firstTime = svs.time; + challenge->time = svs.time; challenge->connected = qfalse; } // always generate a new challenge number, so the client cannot circumvent sv_maxping challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time; challenge->wasrefused = qfalse; - challenge->time = svs.time; + #ifndef STANDALONE // Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6. @@ -137,7 +121,7 @@ void SV_GetChallenge(netadr_t from) // if they have been challenging for a long time and we // haven't heard anything from the authorize server, go ahead and // let them in, assuming the id server is down - else if(svs.time - oldestClientTime > AUTHORIZE_TIMEOUT) + else if(svs.time - challenge->firstTime > AUTHORIZE_TIMEOUT) Com_DPrintf( "authorize server timed out\n" ); else { @@ -145,6 +129,10 @@ void SV_GetChallenge(netadr_t from) cvar_t *fs; char game[1024]; + // If the client provided us with a client challenge, store it... + if(*clientChallenge) + challenge->clientChallenge = atoi(clientChallenge); + Com_DPrintf( "sending getIpAuthorize for %s\n", NET_AdrToString( from )); strcpy(game, BASEGAME); @@ -165,7 +153,7 @@ void SV_GetChallenge(netadr_t from) #endif challenge->pingTime = svs.time; - NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %d", challenge->challenge, clientChallenge); + NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %s", challenge->challenge, clientChallenge); } #ifndef STANDALONE @@ -301,9 +289,6 @@ void SV_DirectConnect( netadr_t from ) { intptr_t denied; int count; char *ip; -#ifdef PROTOCOL_SUPPORT_OLD - qboolean compat = qfalse; -#endif Com_DPrintf ("SVC_DirectConnect ()\n"); @@ -316,21 +301,11 @@ void SV_DirectConnect( netadr_t from ) { Q_strncpyz( userinfo, Cmd_Argv(1), sizeof(userinfo) ); - version = atoi(Info_ValueForKey(userinfo, "protocol")); - -#ifdef PROTOCOL_SUPPORT_OLD - if(version > 0 && com_oldprotocol->integer == version) - compat = qtrue; - else -#endif - { - if(version != com_protocol->integer) - { - NET_OutOfBandPrint(NS_SERVER, from, "print\nServer uses protocol version %i " - "(yours is %i).\n", com_protocol->integer, version); - Com_DPrintf(" rejected connect from version %i\n", version); - return; - } + version = atoi( Info_ValueForKey( userinfo, "protocol" ) ); + if ( version != com_protocol->integer ) { + NET_OutOfBandPrint( NS_SERVER, from, "print\nServer uses protocol version %i (yours is %i).\n", com_protocol->integer, version ); + Com_DPrintf (" rejected connect from version %i\n", version); + return; } challenge = atoi( Info_ValueForKey( userinfo, "challenge" ) ); @@ -512,12 +487,7 @@ gotnewcl: newcl->challenge = challenge; // save the address -#ifdef PROTOCOL_SUPPORT_OLD - newcl->compat = compat; - Netchan_Setup(NS_SERVER, &newcl->netchan, from, qport, challenge, compat); -#else - Netchan_Setup(NS_SERVER, &newcl->netchan, from, qport, challenge); -#endif + Netchan_Setup (NS_SERVER, &newcl->netchan , from, qport); // init the netchan queue newcl->netchan_end_queue = &newcl->netchan_start_queue; @@ -538,7 +508,7 @@ gotnewcl: SV_UserinfoChanged( newcl ); // send the connect packet to the client - NET_OutOfBandPrint(NS_SERVER, from, "connectResponse %d", challenge); + NET_OutOfBandPrint( NS_SERVER, from, "connectResponse" ); Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name );