mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2025-02-22 12:01:05 +00:00
- Implement dual protocol support (#4962)
- Fix several UDP spoofing security issues
This commit is contained in:
parent
309c322b80
commit
e06c117e9e
13 changed files with 550 additions and 247 deletions
384
README
384
README
|
@ -185,6 +185,10 @@ New cvars
|
||||||
standalone mode
|
standalone mode
|
||||||
com_homepath - Specify name that is to be appended to the
|
com_homepath - Specify name that is to be appended to the
|
||||||
home path
|
home path
|
||||||
|
com_legacyprotocol - Specify protocol version number for
|
||||||
|
legacy Quake3 1.32c protocol, see
|
||||||
|
"Network protocols" section below
|
||||||
|
(startup only)
|
||||||
com_maxfpsUnfocused - Maximum frames per second when unfocused
|
com_maxfpsUnfocused - Maximum frames per second when unfocused
|
||||||
com_maxfpsMinimized - Maximum frames per second when minimized
|
com_maxfpsMinimized - Maximum frames per second when minimized
|
||||||
com_busyWait - Will use a busy loop to wait for rendering
|
com_busyWait - Will use a busy loop to wait for rendering
|
||||||
|
@ -193,6 +197,10 @@ New cvars
|
||||||
through which other processes can control
|
through which other processes can control
|
||||||
the server while it is running.
|
the server while it is running.
|
||||||
Nonfunctional on Windows.
|
Nonfunctional on Windows.
|
||||||
|
com_protocol - Specify protocol version number for
|
||||||
|
current ioquake3 protocol, see
|
||||||
|
"Network protocols" section below
|
||||||
|
(startup only)
|
||||||
|
|
||||||
in_joystickNo - select which joystick to use
|
in_joystickNo - select which joystick to use
|
||||||
in_availableJoysticks - list of available Joysticks
|
in_availableJoysticks - list of available Joysticks
|
||||||
|
@ -218,9 +226,6 @@ New cvars
|
||||||
ipv6 servers on the local network
|
ipv6 servers on the local network
|
||||||
net_mcastiface - outgoing interface to use for scan
|
net_mcastiface - outgoing interface to use for scan
|
||||||
|
|
||||||
protocol - Allow changing protocol version
|
|
||||||
(startup only)
|
|
||||||
|
|
||||||
r_allowResize - make window resizable (SDL only)
|
r_allowResize - make window resizable (SDL only)
|
||||||
r_ext_texture_filter_anisotropic - anisotropic texture filtering
|
r_ext_texture_filter_anisotropic - anisotropic texture filtering
|
||||||
r_zProj - distance of observer camera to projection
|
r_zProj - distance of observer camera to projection
|
||||||
|
@ -281,7 +286,8 @@ New commands
|
||||||
|
|
||||||
which <filename/path> - print out the path on disk to a loaded item
|
which <filename/path> - print out the path on disk to a loaded item
|
||||||
|
|
||||||
------------------------------------------------------------ Miscellaneous -----
|
|
||||||
|
--------------------------------------------------------- README for Users -----
|
||||||
|
|
||||||
Using shared libraries instead of qvm
|
Using shared libraries instead of qvm
|
||||||
To force Q3 to use shared libraries instead of qvms run it with the following
|
To force Q3 to use shared libraries instead of qvms run it with the following
|
||||||
|
@ -309,175 +315,6 @@ 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
|
In this case you can always revert back to the old behaviour by setting the
|
||||||
cvar com_busyWait to 1.
|
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 <stdint.h>
|
|
||||||
#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 <yournewbase>
|
|
||||||
|
|
||||||
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 <homedirname>
|
|
||||||
|
|
||||||
to the command line. Then you can control which kind of messages to send to
|
|
||||||
the master server:
|
|
||||||
|
|
||||||
+set sv_heartbeat <heartbeat> +set sv_flatline <flatline>
|
|
||||||
+set cl_gamename <gamename>
|
|
||||||
|
|
||||||
The <heartbeat> and <flatline> 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)
|
Using HTTP/FTP Download Support (Server)
|
||||||
You can enable redirected downloads on your server even if it's not
|
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
|
an ioquake3 server. You simply need to use the 'sets' command to put
|
||||||
|
@ -586,6 +423,207 @@ SDL Keyboard Differences
|
||||||
text. Also, in addition to the nominated console keys, Shift-ESC is hard
|
text. Also, in addition to the nominated console keys, Shift-ESC is hard
|
||||||
coded to always toggle the console.
|
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 <stdint.h>
|
||||||
|
#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 <yournewbase>
|
||||||
|
|
||||||
|
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 <homedirname>
|
||||||
|
|
||||||
|
to the command line. You can also control which kind of messages to send to
|
||||||
|
the master server:
|
||||||
|
|
||||||
|
+set sv_heartbeat <heartbeat> +set sv_flatline <flatline>
|
||||||
|
+set cl_gamename <gamename>
|
||||||
|
|
||||||
|
The <heartbeat> and <flatline> 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: "com_protocol" and
|
||||||
|
"com_legacyprotocol".
|
||||||
|
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 harden the network protocol against UDP spoofing attacks 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 "com_protocol" denotes the protocol version for the new hardened
|
||||||
|
protocol, whereas the "com_legacyprotocol" cvar denotes the protocol version
|
||||||
|
for the legacy protocol.
|
||||||
|
If the value for "com_protocol" and "com_legacyprotocol" is identical, then
|
||||||
|
the legacy protocol is always used. If "com_legacyprotocol" 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. If you desire backwards compatibility to older versions of your
|
||||||
|
game you can still enable it in q_shared.h by defining
|
||||||
|
LEGACY_PROTOCOL.
|
||||||
|
|
||||||
|
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
|
PNG support
|
||||||
ioquake3 supports the use of PNG (Portable Network Graphic) images as
|
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
|
textures. It should be noted that the use of such images in a map will
|
||||||
|
|
|
@ -533,7 +533,6 @@ void CL_WriteDemoMessage ( msg_t *msg, int headerBytes ) {
|
||||||
len = clc.serverMessageSequence;
|
len = clc.serverMessageSequence;
|
||||||
swlen = LittleLong( len );
|
swlen = LittleLong( len );
|
||||||
FS_Write (&swlen, 4, clc.demofile);
|
FS_Write (&swlen, 4, clc.demofile);
|
||||||
|
|
||||||
// skip the packet sequencing information
|
// skip the packet sequencing information
|
||||||
len = msg->cursize - headerBytes;
|
len = msg->cursize - headerBytes;
|
||||||
swlen = LittleLong(len);
|
swlen = LittleLong(len);
|
||||||
|
@ -636,14 +635,24 @@ void CL_Record_f( void ) {
|
||||||
if ( Cmd_Argc() == 2 ) {
|
if ( Cmd_Argc() == 2 ) {
|
||||||
s = Cmd_Argv(1);
|
s = Cmd_Argv(1);
|
||||||
Q_strncpyz( demoName, s, sizeof( demoName ) );
|
Q_strncpyz( demoName, s, sizeof( demoName ) );
|
||||||
Com_sprintf (name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer );
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(clc.compat)
|
||||||
|
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_legacyprotocol->integer);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer);
|
||||||
} else {
|
} else {
|
||||||
int number;
|
int number;
|
||||||
|
|
||||||
// scan for a free demo name
|
// scan for a free demo name
|
||||||
for ( number = 0 ; number <= 9999 ; number++ ) {
|
for ( number = 0 ; number <= 9999 ; number++ ) {
|
||||||
CL_DemoFilename( number, demoName );
|
CL_DemoFilename( number, demoName );
|
||||||
Com_sprintf (name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer );
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(clc.compat)
|
||||||
|
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_legacyprotocol->integer);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer);
|
||||||
|
|
||||||
if (!FS_FileExists(name))
|
if (!FS_FileExists(name))
|
||||||
break; // file doesn't exist
|
break; // file doesn't exist
|
||||||
|
@ -665,7 +674,6 @@ void CL_Record_f( void ) {
|
||||||
clc.spDemoRecording = qfalse;
|
clc.spDemoRecording = qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Q_strncpyz( clc.demoName, demoName, sizeof( clc.demoName ) );
|
Q_strncpyz( clc.demoName, demoName, sizeof( clc.demoName ) );
|
||||||
|
|
||||||
// don't start saving messages until a non-delta compressed message is received
|
// don't start saving messages until a non-delta compressed message is received
|
||||||
|
@ -889,36 +897,62 @@ void CL_ReadDemoMessage( void ) {
|
||||||
CL_WalkDemoExt
|
CL_WalkDemoExt
|
||||||
====================
|
====================
|
||||||
*/
|
*/
|
||||||
static void CL_WalkDemoExt(char *arg, char *name, int *demofile)
|
static int CL_WalkDemoExt(char *arg, char *name, int *demofile)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
*demofile = 0;
|
*demofile = 0;
|
||||||
|
|
||||||
Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_protocol->integer);
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(com_legacyprotocol->integer > 0)
|
||||||
FS_FOpenFileRead( name, demofile, qtrue );
|
{
|
||||||
|
Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_legacyprotocol->integer);
|
||||||
|
FS_FOpenFileRead(name, demofile, qtrue);
|
||||||
|
|
||||||
if (*demofile)
|
if (*demofile)
|
||||||
{
|
{
|
||||||
Com_Printf("Demo file: %s\n", name);
|
Com_Printf("Demo file: %s\n", name);
|
||||||
return;
|
return com_legacyprotocol->integer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(com_protocol->integer != com_legacyprotocol->integer)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_protocol->integer);
|
||||||
|
FS_FOpenFileRead(name, demofile, qtrue);
|
||||||
|
|
||||||
|
if (*demofile)
|
||||||
|
{
|
||||||
|
Com_Printf("Demo file: %s\n", name);
|
||||||
|
return com_protocol->integer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Com_Printf("Not found: %s\n", name);
|
Com_Printf("Not found: %s\n", name);
|
||||||
|
|
||||||
while(demo_protocols[i])
|
while(demo_protocols[i])
|
||||||
{
|
{
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(demo_protocols[i] == com_legacyprotocol->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]);
|
Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, demo_protocols[i]);
|
||||||
FS_FOpenFileRead( name, demofile, qtrue );
|
FS_FOpenFileRead( name, demofile, qtrue );
|
||||||
if (*demofile)
|
if (*demofile)
|
||||||
{
|
{
|
||||||
Com_Printf("Demo file: %s\n", name);
|
Com_Printf("Demo file: %s\n", name);
|
||||||
break;
|
|
||||||
|
return demo_protocols[i];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Com_Printf("Not found: %s\n", name);
|
Com_Printf("Not found: %s\n", name);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -978,7 +1012,11 @@ void CL_PlayDemo_f( void ) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(demo_protocols[i] || protocol == com_protocol->integer)
|
if(demo_protocols[i] || protocol == com_protocol->integer
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
|| protocol == com_legacyprotocol->integer
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
Com_sprintf(name, sizeof(name), "demos/%s", arg);
|
Com_sprintf(name, sizeof(name), "demos/%s", arg);
|
||||||
FS_FOpenFileRead(name, &clc.demofile, qtrue);
|
FS_FOpenFileRead(name, &clc.demofile, qtrue);
|
||||||
|
@ -995,11 +1033,11 @@ void CL_PlayDemo_f( void ) {
|
||||||
|
|
||||||
Q_strncpyz(retry, arg, len + 1);
|
Q_strncpyz(retry, arg, len + 1);
|
||||||
retry[len] = '\0';
|
retry[len] = '\0';
|
||||||
CL_WalkDemoExt(retry, name, &clc.demofile);
|
protocol = CL_WalkDemoExt(retry, name, &clc.demofile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CL_WalkDemoExt(arg, name, &clc.demofile);
|
protocol = CL_WalkDemoExt(arg, name, &clc.demofile);
|
||||||
|
|
||||||
if (!clc.demofile) {
|
if (!clc.demofile) {
|
||||||
Com_Error( ERR_DROP, "couldn't open %s", name);
|
Com_Error( ERR_DROP, "couldn't open %s", name);
|
||||||
|
@ -1013,6 +1051,13 @@ void CL_PlayDemo_f( void ) {
|
||||||
clc.demoplaying = qtrue;
|
clc.demoplaying = qtrue;
|
||||||
Q_strncpyz( clc.servername, Cmd_Argv(1), sizeof( clc.servername ) );
|
Q_strncpyz( clc.servername, Cmd_Argv(1), sizeof( clc.servername ) );
|
||||||
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(protocol <= com_legacyprotocol->integer)
|
||||||
|
clc.compat = qtrue;
|
||||||
|
else
|
||||||
|
clc.compat = qfalse;
|
||||||
|
#endif
|
||||||
|
|
||||||
// read demo messages until connected
|
// read demo messages until connected
|
||||||
while ( clc.state >= CA_CONNECTED && clc.state < CA_PRIMED ) {
|
while ( clc.state >= CA_CONNECTED && clc.state < CA_PRIMED ) {
|
||||||
CL_ReadDemoMessage();
|
CL_ReadDemoMessage();
|
||||||
|
@ -2180,7 +2225,9 @@ void CL_CheckForResend( void ) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The challenge request shall be followed by a client challenge so no malicious server can hijack this connection.
|
// The challenge request shall be followed by a client challenge so no malicious server can hijack this connection.
|
||||||
Com_sprintf(data, sizeof(data), "getchallenge %d", clc.challenge);
|
// Add the heartbeat gamename so the server knows we're running the correct game and can reject the client
|
||||||
|
// with a meaningful message
|
||||||
|
Com_sprintf(data, sizeof(data), "getchallenge %d %s", clc.challenge, Cvar_VariableString("sv_heartbeat"));
|
||||||
|
|
||||||
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "%s", data);
|
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "%s", data);
|
||||||
break;
|
break;
|
||||||
|
@ -2190,7 +2237,16 @@ void CL_CheckForResend( void ) {
|
||||||
port = Cvar_VariableValue ("net_qport");
|
port = Cvar_VariableValue ("net_qport");
|
||||||
|
|
||||||
Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) );
|
Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) );
|
||||||
Info_SetValueForKey( info, "protocol", va("%i", com_protocol->integer ) );
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(com_legacyprotocol->integer == com_protocol->integer)
|
||||||
|
clc.compat = qtrue;
|
||||||
|
|
||||||
|
if(clc.compat)
|
||||||
|
Info_SetValueForKey(info, "protocol", va("%i", com_legacyprotocol->integer));
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
Info_SetValueForKey(info, "protocol", va("%i", com_protocol->integer));
|
||||||
Info_SetValueForKey( info, "qport", va("%i", port ) );
|
Info_SetValueForKey( info, "qport", va("%i", port ) );
|
||||||
Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) );
|
Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) );
|
||||||
|
|
||||||
|
@ -2431,6 +2487,7 @@ Responses to broadcasts, etc
|
||||||
void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
||||||
char *s;
|
char *s;
|
||||||
char *c;
|
char *c;
|
||||||
|
int challenge;
|
||||||
|
|
||||||
MSG_BeginReadingOOB( msg );
|
MSG_BeginReadingOOB( msg );
|
||||||
MSG_ReadLong( msg ); // skip the -1
|
MSG_ReadLong( msg ); // skip the -1
|
||||||
|
@ -2446,26 +2503,73 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
||||||
// challenge from the server we are connecting to
|
// challenge from the server we are connecting to
|
||||||
if (!Q_stricmp(c, "challengeResponse"))
|
if (!Q_stricmp(c, "challengeResponse"))
|
||||||
{
|
{
|
||||||
|
char *strver;
|
||||||
|
int ver;
|
||||||
|
|
||||||
if (clc.state != CA_CONNECTING)
|
if (clc.state != CA_CONNECTING)
|
||||||
{
|
{
|
||||||
Com_DPrintf("Unwanted challenge response received. Ignored.\n");
|
Com_DPrintf("Unwanted challenge response received. Ignored.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c = Cmd_Argv(2);
|
||||||
|
if(*c)
|
||||||
|
challenge = atoi(c);
|
||||||
|
|
||||||
|
strver = Cmd_Argv(3);
|
||||||
|
if(*strver)
|
||||||
|
{
|
||||||
|
ver = atoi(strver);
|
||||||
|
|
||||||
|
if(ver != com_protocol->integer)
|
||||||
|
{
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(com_legacyprotocol->integer > 0)
|
||||||
|
{
|
||||||
|
// Server is ioq3 but has a different protocol than we do.
|
||||||
|
// Fall back to idq3 protocol.
|
||||||
|
clc.compat = qtrue;
|
||||||
|
|
||||||
|
Com_Printf(S_COLOR_YELLOW "Warning: Server reports protocol version %d, "
|
||||||
|
"we have %d. Trying legacy protocol %d.\n",
|
||||||
|
ver, com_protocol->integer, com_legacyprotocol->integer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
Com_Printf(S_COLOR_YELLOW "Warning: Server reports protocol version %d, we have %d. "
|
||||||
|
"Trying anyways.\n", ver, com_protocol->integer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
else
|
||||||
|
clc.compat = qtrue;
|
||||||
|
|
||||||
|
if(clc.compat)
|
||||||
|
{
|
||||||
if(!NET_CompareAdr(from, clc.serverAddress))
|
if(!NET_CompareAdr(from, clc.serverAddress))
|
||||||
{
|
{
|
||||||
// This challenge response is not coming from the expected address.
|
// This challenge response is not coming from the expected address.
|
||||||
// Check whether we have a matching client challenge to prevent
|
// Check whether we have a matching client challenge to prevent
|
||||||
// connection hi-jacking.
|
// connection hi-jacking.
|
||||||
|
|
||||||
c = Cmd_Argv(2);
|
if(!*c || challenge != clc.challenge)
|
||||||
|
|
||||||
if(!*c || atoi(c) != clc.challenge)
|
|
||||||
{
|
{
|
||||||
Com_DPrintf("Challenge response received from unexpected source. Ignored.\n");
|
Com_DPrintf("Challenge response received from unexpected source. Ignored.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if(!*c || challenge != clc.challenge)
|
||||||
|
{
|
||||||
|
Com_Printf("Bad challenge for challengeResponse. Ignored.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// start sending challenge response instead of challenge request packets
|
// start sending challenge response instead of challenge request packets
|
||||||
clc.challenge = atoi(Cmd_Argv(1));
|
clc.challenge = atoi(Cmd_Argv(1));
|
||||||
|
@ -2494,7 +2598,36 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
||||||
Com_Printf( "connectResponse from wrong address. Ignored.\n" );
|
Com_Printf( "connectResponse from wrong address. Ignored.\n" );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) );
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(!clc.compat)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
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, qfalse);
|
||||||
|
#endif
|
||||||
|
|
||||||
clc.state = CA_CONNECTED;
|
clc.state = CA_CONNECTED;
|
||||||
clc.lastPacketSentTime = -9999; // send first packet immediately
|
clc.lastPacketSentTime = -9999; // send first packet immediately
|
||||||
return;
|
return;
|
||||||
|
@ -2512,13 +2645,6 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
||||||
return;
|
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
|
// echo request from server
|
||||||
if ( !Q_stricmp(c, "echo") ) {
|
if ( !Q_stricmp(c, "echo") ) {
|
||||||
NET_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) );
|
NET_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) );
|
||||||
|
@ -2538,10 +2664,12 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// echo request from server
|
// echo request from server
|
||||||
if ( !Q_stricmp(c, "print") ) {
|
if(!Q_stricmp(c, "print")){
|
||||||
s = MSG_ReadString( msg );
|
s = MSG_ReadString( msg );
|
||||||
|
|
||||||
Q_strncpyz( clc.serverMessage, s, sizeof( clc.serverMessage ) );
|
Q_strncpyz( clc.serverMessage, s, sizeof( clc.serverMessage ) );
|
||||||
Com_Printf( "%s", s );
|
Com_Printf( "%s", s );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3492,7 +3620,13 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
|
||||||
|
|
||||||
// if this isn't the correct protocol version, ignore it
|
// if this isn't the correct protocol version, ignore it
|
||||||
prot = atoi( Info_ValueForKey( infoString, "protocol" ) );
|
prot = atoi( Info_ValueForKey( infoString, "protocol" ) );
|
||||||
if ( prot != com_protocol->integer ) {
|
|
||||||
|
if(prot != com_protocol->integer
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
&& prot != com_legacyprotocol->integer
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
Com_DPrintf( "Different protocol info packet: %s\n", infoString );
|
Com_DPrintf( "Different protocol info packet: %s\n", infoString );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,9 +147,6 @@ void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) {
|
||||||
Netchan_Transmit( chan, msg->cursize, msg->data );
|
Netchan_Transmit( chan, msg->cursize, msg->data );
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int oldsize;
|
|
||||||
int newsize = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
CL_Netchan_Process
|
CL_Netchan_Process
|
||||||
|
@ -161,7 +158,8 @@ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) {
|
||||||
ret = Netchan_Process( chan, msg );
|
ret = Netchan_Process( chan, msg );
|
||||||
if (!ret)
|
if (!ret)
|
||||||
return qfalse;
|
return qfalse;
|
||||||
|
|
||||||
CL_Netchan_Decode( msg );
|
CL_Netchan_Decode( msg );
|
||||||
newsize += msg->cursize;
|
|
||||||
return qtrue;
|
return qtrue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,6 +263,10 @@ typedef struct {
|
||||||
float voipPower;
|
float voipPower;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
qboolean compat;
|
||||||
|
#endif
|
||||||
|
|
||||||
// big stuff at end of structure so most offsets are 15 bits or less
|
// big stuff at end of structure so most offsets are 15 bits or less
|
||||||
netchan_t netchan;
|
netchan_t netchan;
|
||||||
} clientConnection_t;
|
} clientConnection_t;
|
||||||
|
|
|
@ -42,8 +42,8 @@ DEMOS MENU
|
||||||
#define ART_ARROWLEFT "menu/art/arrows_horz_left"
|
#define ART_ARROWLEFT "menu/art/arrows_horz_left"
|
||||||
#define ART_ARROWRIGHT "menu/art/arrows_horz_right"
|
#define ART_ARROWRIGHT "menu/art/arrows_horz_right"
|
||||||
|
|
||||||
#define MAX_DEMOS 128
|
#define MAX_DEMOS 1024
|
||||||
#define NAMEBUFSIZE ( MAX_DEMOS * 16 )
|
#define NAMEBUFSIZE (MAX_DEMOS * 32)
|
||||||
|
|
||||||
#define ID_BACK 10
|
#define ID_BACK 10
|
||||||
#define ID_GO 11
|
#define ID_GO 11
|
||||||
|
@ -72,6 +72,9 @@ typedef struct {
|
||||||
|
|
||||||
int numDemos;
|
int numDemos;
|
||||||
char names[NAMEBUFSIZE];
|
char names[NAMEBUFSIZE];
|
||||||
|
int numLegacyDemos;
|
||||||
|
char namesLegacy[NAMEBUFSIZE];
|
||||||
|
|
||||||
char *demolist[MAX_DEMOS];
|
char *demolist[MAX_DEMOS];
|
||||||
} demos_t;
|
} demos_t;
|
||||||
|
|
||||||
|
@ -133,6 +136,7 @@ static void Demos_MenuInit( void ) {
|
||||||
int i;
|
int i;
|
||||||
int len;
|
int len;
|
||||||
char *demoname, extension[32];
|
char *demoname, extension[32];
|
||||||
|
int protocol, protocolLegacy;
|
||||||
|
|
||||||
memset( &s_demos, 0 ,sizeof(demos_t) );
|
memset( &s_demos, 0 ,sizeof(demos_t) );
|
||||||
s_demos.menu.key = UI_DemosMenu_Key;
|
s_demos.menu.key = UI_DemosMenu_Key;
|
||||||
|
@ -223,11 +227,34 @@ static void Demos_MenuInit( void ) {
|
||||||
s_demos.list.generic.y = 130;
|
s_demos.list.generic.y = 130;
|
||||||
s_demos.list.width = 16;
|
s_demos.list.width = 16;
|
||||||
s_demos.list.height = 14;
|
s_demos.list.height = 14;
|
||||||
Com_sprintf(extension, sizeof(extension), ".%s%d", DEMOEXT, (int) trap_Cvar_VariableValue("protocol"));
|
|
||||||
s_demos.list.numitems = trap_FS_GetFileList( "demos", extension, s_demos.names, NAMEBUFSIZE );
|
|
||||||
s_demos.list.itemnames = (const char **)s_demos.demolist;
|
s_demos.list.itemnames = (const char **)s_demos.demolist;
|
||||||
s_demos.list.columns = 3;
|
s_demos.list.columns = 3;
|
||||||
|
|
||||||
|
protocolLegacy = trap_Cvar_VariableValue("com_legacyprotocol");
|
||||||
|
protocol = trap_Cvar_VariableValue("com_protocol");
|
||||||
|
|
||||||
|
if(!protocol)
|
||||||
|
protocol = trap_Cvar_VariableValue("protocol");
|
||||||
|
if(protocolLegacy == protocol)
|
||||||
|
protocolLegacy = 0;
|
||||||
|
|
||||||
|
Com_sprintf(extension, sizeof(extension), ".%s%d", DEMOEXT, protocol);
|
||||||
|
s_demos.numDemos = trap_FS_GetFileList("demos", extension, s_demos.names, NAMEBUFSIZE);
|
||||||
|
|
||||||
|
if(s_demos.numDemos > MAX_DEMOS)
|
||||||
|
s_demos.numDemos = MAX_DEMOS;
|
||||||
|
|
||||||
|
if(protocolLegacy > 0)
|
||||||
|
{
|
||||||
|
Com_sprintf(extension, sizeof(extension), ".%s%d", DEMOEXT, protocolLegacy);
|
||||||
|
s_demos.numLegacyDemos = trap_FS_GetFileList("demos", extension, s_demos.namesLegacy, NAMEBUFSIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s_demos.numLegacyDemos = 0;
|
||||||
|
|
||||||
|
s_demos.list.numitems = s_demos.numDemos + s_demos.numLegacyDemos;
|
||||||
|
|
||||||
|
|
||||||
if (!s_demos.list.numitems) {
|
if (!s_demos.list.numitems) {
|
||||||
strcpy( s_demos.names, "No Demos Found." );
|
strcpy( s_demos.names, "No Demos Found." );
|
||||||
s_demos.list.numitems = 1;
|
s_demos.list.numitems = 1;
|
||||||
|
@ -239,15 +266,21 @@ static void Demos_MenuInit( void ) {
|
||||||
s_demos.list.numitems = MAX_DEMOS;
|
s_demos.list.numitems = MAX_DEMOS;
|
||||||
|
|
||||||
demoname = s_demos.names;
|
demoname = s_demos.names;
|
||||||
for ( i = 0; i < s_demos.list.numitems; i++ ) {
|
for(i = 0; i < s_demos.numDemos; i++)
|
||||||
|
{
|
||||||
s_demos.list.itemnames[i] = demoname;
|
s_demos.list.itemnames[i] = demoname;
|
||||||
|
|
||||||
// strip extension
|
len = strlen(demoname);
|
||||||
len = strlen( demoname );
|
|
||||||
if (!Q_stricmp(demoname + len - 4,".dm3"))
|
|
||||||
demoname[len-4] = '\0';
|
|
||||||
|
|
||||||
// Q_strupr(demoname);
|
demoname += len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
demoname = s_demos.namesLegacy;
|
||||||
|
for(; i < s_demos.list.numitems; i++)
|
||||||
|
{
|
||||||
|
s_demos.list.itemnames[i] = demoname;
|
||||||
|
|
||||||
|
len = strlen(demoname);
|
||||||
|
|
||||||
demoname += len + 1;
|
demoname += len + 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int demo_protocols[] =
|
int demo_protocols[] =
|
||||||
{ 66, 67, 68, 0 };
|
{ 67, 66, 0 };
|
||||||
|
|
||||||
#define MAX_NUM_ARGVS 50
|
#define MAX_NUM_ARGVS 50
|
||||||
|
|
||||||
|
@ -87,6 +87,9 @@ cvar_t *com_maxfpsMinimized;
|
||||||
cvar_t *com_abnormalExit;
|
cvar_t *com_abnormalExit;
|
||||||
cvar_t *com_standalone;
|
cvar_t *com_standalone;
|
||||||
cvar_t *com_protocol;
|
cvar_t *com_protocol;
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
cvar_t *com_legacyprotocol;
|
||||||
|
#endif
|
||||||
cvar_t *com_basegame;
|
cvar_t *com_basegame;
|
||||||
cvar_t *com_homepath;
|
cvar_t *com_homepath;
|
||||||
cvar_t *com_busyWait;
|
cvar_t *com_busyWait;
|
||||||
|
@ -2796,7 +2799,16 @@ void Com_Init( char *commandLine ) {
|
||||||
|
|
||||||
s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ );
|
s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ );
|
||||||
com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO );
|
com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO );
|
||||||
com_protocol = Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_INIT);
|
com_protocol = Cvar_Get("com_protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_INIT);
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
com_legacyprotocol = Cvar_Get("com_legacyprotocol", va("%i", PROTOCOL_LEGACY_VERSION), CVAR_INIT);
|
||||||
|
|
||||||
|
// Keep for compatibility with old mods / mods that haven't updated yet.
|
||||||
|
if(com_legacyprotocol->integer > 0)
|
||||||
|
Cvar_Get("protocol", com_legacyprotocol->string, CVAR_ROM);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
Cvar_Get("protocol", com_protocol->string, CVAR_ROM);
|
||||||
|
|
||||||
Sys_Init();
|
Sys_Init();
|
||||||
|
|
||||||
|
|
|
@ -1056,6 +1056,11 @@ qboolean FS_IsDemoExt(const char *filename, int namelen)
|
||||||
if(protocol == com_protocol->integer)
|
if(protocol == com_protocol->integer)
|
||||||
return qtrue;
|
return qtrue;
|
||||||
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(protocol == com_legacyprotocol->integer)
|
||||||
|
return qtrue;
|
||||||
|
#endif
|
||||||
|
|
||||||
for(index = 0; demo_protocols[index]; index++)
|
for(index = 0; demo_protocols[index]; index++)
|
||||||
{
|
{
|
||||||
if(demo_protocols[index] == protocol)
|
if(demo_protocols[index] == protocol)
|
||||||
|
|
|
@ -83,7 +83,8 @@ Netchan_Setup
|
||||||
called to open a channel to a remote system
|
called to open a channel to a remote system
|
||||||
==============
|
==============
|
||||||
*/
|
*/
|
||||||
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ) {
|
void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge, qboolean compat)
|
||||||
|
{
|
||||||
Com_Memset (chan, 0, sizeof(*chan));
|
Com_Memset (chan, 0, sizeof(*chan));
|
||||||
|
|
||||||
chan->sock = sock;
|
chan->sock = sock;
|
||||||
|
@ -91,6 +92,11 @@ void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ) {
|
||||||
chan->qport = qport;
|
chan->qport = qport;
|
||||||
chan->incomingSequence = 0;
|
chan->incomingSequence = 0;
|
||||||
chan->outgoingSequence = 1;
|
chan->outgoingSequence = 1;
|
||||||
|
chan->challenge = challenge;
|
||||||
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
chan->compat = compat;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// TTimo: unused, commenting out to make gcc happy
|
// TTimo: unused, commenting out to make gcc happy
|
||||||
|
@ -190,17 +196,24 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) {
|
||||||
msg_t send;
|
msg_t send;
|
||||||
byte send_buf[MAX_PACKETLEN];
|
byte send_buf[MAX_PACKETLEN];
|
||||||
int fragmentLength;
|
int fragmentLength;
|
||||||
|
int outgoingSequence;
|
||||||
|
|
||||||
// write the packet header
|
// write the packet header
|
||||||
MSG_InitOOB (&send, send_buf, sizeof(send_buf)); // <-- only do the oob here
|
MSG_InitOOB (&send, send_buf, sizeof(send_buf)); // <-- only do the oob here
|
||||||
|
|
||||||
MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT );
|
outgoingSequence = chan->outgoingSequence | FRAGMENT_BIT;
|
||||||
|
MSG_WriteLong(&send, outgoingSequence);
|
||||||
|
|
||||||
// send the qport if we are a client
|
// send the qport if we are a client
|
||||||
if ( chan->sock == NS_CLIENT ) {
|
if ( chan->sock == NS_CLIENT ) {
|
||||||
MSG_WriteShort( &send, qport->integer );
|
MSG_WriteShort( &send, qport->integer );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(!chan->compat)
|
||||||
|
#endif
|
||||||
|
MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence));
|
||||||
|
|
||||||
// copy the reliable message to the packet first
|
// copy the reliable message to the packet first
|
||||||
fragmentLength = FRAGMENT_SIZE;
|
fragmentLength = FRAGMENT_SIZE;
|
||||||
if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) {
|
if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) {
|
||||||
|
@ -268,12 +281,17 @@ void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) {
|
||||||
MSG_InitOOB (&send, send_buf, sizeof(send_buf));
|
MSG_InitOOB (&send, send_buf, sizeof(send_buf));
|
||||||
|
|
||||||
MSG_WriteLong( &send, chan->outgoingSequence );
|
MSG_WriteLong( &send, chan->outgoingSequence );
|
||||||
chan->outgoingSequence++;
|
|
||||||
|
|
||||||
// send the qport if we are a client
|
// send the qport if we are a client
|
||||||
if ( chan->sock == NS_CLIENT ) {
|
if(chan->sock == NS_CLIENT)
|
||||||
MSG_WriteShort( &send, qport->integer );
|
MSG_WriteShort(&send, qport->integer);
|
||||||
}
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(!chan->compat)
|
||||||
|
#endif
|
||||||
|
MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence));
|
||||||
|
|
||||||
|
chan->outgoingSequence++;
|
||||||
|
|
||||||
MSG_WriteData( &send, data, length );
|
MSG_WriteData( &send, data, length );
|
||||||
|
|
||||||
|
@ -327,6 +345,17 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
|
||||||
qport = MSG_ReadShort( msg );
|
qport = MSG_ReadShort( msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
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
|
// read the fragment information
|
||||||
if ( fragmented ) {
|
if ( fragmented ) {
|
||||||
fragmentStart = MSG_ReadShort( msg );
|
fragmentStart = MSG_ReadShort( msg );
|
||||||
|
|
|
@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#define HOMEPATH_NAME_UNIX ".foo"
|
#define HOMEPATH_NAME_UNIX ".foo"
|
||||||
#define HOMEPATH_NAME_WIN "FooBar"
|
#define HOMEPATH_NAME_WIN "FooBar"
|
||||||
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
||||||
|
// #define LEGACY_PROTOCOL // You probably don't need this for your standalone game
|
||||||
#else
|
#else
|
||||||
#define PRODUCT_NAME "ioq3"
|
#define PRODUCT_NAME "ioq3"
|
||||||
#define BASEGAME "baseq3"
|
#define BASEGAME "baseq3"
|
||||||
|
@ -48,6 +49,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
#define HOMEPATH_NAME_UNIX ".q3a"
|
#define HOMEPATH_NAME_UNIX ".q3a"
|
||||||
#define HOMEPATH_NAME_WIN "Quake3"
|
#define HOMEPATH_NAME_WIN "Quake3"
|
||||||
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
|
||||||
|
#define LEGACY_PROTOCOL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BASETA "missionpack"
|
#define BASETA "missionpack"
|
||||||
|
|
|
@ -196,6 +196,7 @@ void NET_Sleep(int msec);
|
||||||
// will overflow the reliable commands buffer
|
// will overflow the reliable commands buffer
|
||||||
#define MAX_DOWNLOAD_BLKSIZE 1024 // 896 byte block chunks
|
#define MAX_DOWNLOAD_BLKSIZE 1024 // 896 byte block chunks
|
||||||
|
|
||||||
|
#define NETCHAN_GENCHECKSUM(challenge, sequence) ((challenge) ^ ((sequence) * (challenge)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Netchan handles packet fragmentation and out of order / duplicate suppression
|
Netchan handles packet fragmentation and out of order / duplicate suppression
|
||||||
|
@ -224,10 +225,16 @@ typedef struct {
|
||||||
int unsentFragmentStart;
|
int unsentFragmentStart;
|
||||||
int unsentLength;
|
int unsentLength;
|
||||||
byte unsentBuffer[MAX_MSGLEN];
|
byte unsentBuffer[MAX_MSGLEN];
|
||||||
|
|
||||||
|
int challenge;
|
||||||
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
qboolean compat;
|
||||||
|
#endif
|
||||||
} netchan_t;
|
} netchan_t;
|
||||||
|
|
||||||
void Netchan_Init( int qport );
|
void Netchan_Init( int qport );
|
||||||
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport );
|
void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge, qboolean compat);
|
||||||
|
|
||||||
void Netchan_Transmit( netchan_t *chan, int length, const byte *data );
|
void Netchan_Transmit( netchan_t *chan, int length, const byte *data );
|
||||||
void Netchan_TransmitNextFragment( netchan_t *chan );
|
void Netchan_TransmitNextFragment( netchan_t *chan );
|
||||||
|
@ -243,7 +250,8 @@ PROTOCOL
|
||||||
==============================================================
|
==============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PROTOCOL_VERSION 68
|
#define PROTOCOL_VERSION 69
|
||||||
|
#define PROTOCOL_LEGACY_VERSION 68
|
||||||
// 1.31 - 67
|
// 1.31 - 67
|
||||||
|
|
||||||
// maintain a list of compatible protocols for demo playing
|
// maintain a list of compatible protocols for demo playing
|
||||||
|
@ -863,6 +871,9 @@ extern cvar_t *cl_packetdelay;
|
||||||
extern cvar_t *sv_packetdelay;
|
extern cvar_t *sv_packetdelay;
|
||||||
|
|
||||||
extern cvar_t *com_protocol;
|
extern cvar_t *com_protocol;
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
extern cvar_t *com_legacyprotocol;
|
||||||
|
#endif
|
||||||
|
|
||||||
// com_speeds times
|
// com_speeds times
|
||||||
extern int time_game;
|
extern int time_game;
|
||||||
|
|
|
@ -189,6 +189,10 @@ typedef struct client_s {
|
||||||
|
|
||||||
int oldServerTime;
|
int oldServerTime;
|
||||||
qboolean csUpdated[MAX_CONFIGSTRINGS+1];
|
qboolean csUpdated[MAX_CONFIGSTRINGS+1];
|
||||||
|
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
qboolean compat;
|
||||||
|
#endif
|
||||||
} client_t;
|
} client_t;
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
|
@ -59,12 +59,25 @@ void SV_GetChallenge(netadr_t from)
|
||||||
int clientChallenge;
|
int clientChallenge;
|
||||||
challenge_t *challenge;
|
challenge_t *challenge;
|
||||||
qboolean wasfound = qfalse;
|
qboolean wasfound = qfalse;
|
||||||
|
char *gameName;
|
||||||
|
|
||||||
// ignore if we are in single player
|
// ignore if we are in single player
|
||||||
if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) {
|
if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gameName = Cmd_Argv(2);
|
||||||
|
if(gameName && *gameName)
|
||||||
|
{
|
||||||
|
// reject client if the heartbeat string sent by the client doesn't match ours
|
||||||
|
if(strcmp(gameName, sv_heartbeat->string))
|
||||||
|
{
|
||||||
|
NET_OutOfBandPrint(NS_SERVER, from, "print\nGame mismatch: This is a %s server\n",
|
||||||
|
sv_heartbeat->string);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
oldest = 0;
|
oldest = 0;
|
||||||
oldestClientTime = oldestTime = 0x7fffffff;
|
oldestClientTime = oldestTime = 0x7fffffff;
|
||||||
|
|
||||||
|
@ -302,6 +315,9 @@ void SV_DirectConnect( netadr_t from ) {
|
||||||
intptr_t denied;
|
intptr_t denied;
|
||||||
int count;
|
int count;
|
||||||
char *ip;
|
char *ip;
|
||||||
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
qboolean compat = qfalse;
|
||||||
|
#endif
|
||||||
|
|
||||||
Com_DPrintf ("SVC_DirectConnect ()\n");
|
Com_DPrintf ("SVC_DirectConnect ()\n");
|
||||||
|
|
||||||
|
@ -314,12 +330,22 @@ void SV_DirectConnect( netadr_t from ) {
|
||||||
|
|
||||||
Q_strncpyz( userinfo, Cmd_Argv(1), sizeof(userinfo) );
|
Q_strncpyz( userinfo, Cmd_Argv(1), sizeof(userinfo) );
|
||||||
|
|
||||||
version = atoi( Info_ValueForKey( userinfo, "protocol" ) );
|
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 );
|
#ifdef LEGACY_PROTOCOL
|
||||||
Com_DPrintf (" rejected connect from version %i\n", version);
|
if(version > 0 && com_legacyprotocol->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;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
challenge = atoi( Info_ValueForKey( userinfo, "challenge" ) );
|
challenge = atoi( Info_ValueForKey( userinfo, "challenge" ) );
|
||||||
qport = atoi( Info_ValueForKey( userinfo, "qport" ) );
|
qport = atoi( Info_ValueForKey( userinfo, "qport" ) );
|
||||||
|
@ -500,7 +526,12 @@ gotnewcl:
|
||||||
newcl->challenge = challenge;
|
newcl->challenge = challenge;
|
||||||
|
|
||||||
// save the address
|
// save the address
|
||||||
Netchan_Setup (NS_SERVER, &newcl->netchan , from, qport);
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
newcl->compat = compat;
|
||||||
|
Netchan_Setup(NS_SERVER, &newcl->netchan, from, qport, challenge, compat);
|
||||||
|
#else
|
||||||
|
Netchan_Setup(NS_SERVER, &newcl->netchan, from, qport, challenge, qfalse);
|
||||||
|
#endif
|
||||||
// init the netchan queue
|
// init the netchan queue
|
||||||
newcl->netchan_end_queue = &newcl->netchan_start_queue;
|
newcl->netchan_end_queue = &newcl->netchan_start_queue;
|
||||||
|
|
||||||
|
@ -521,7 +552,7 @@ gotnewcl:
|
||||||
SV_UserinfoChanged( newcl );
|
SV_UserinfoChanged( newcl );
|
||||||
|
|
||||||
// send the connect packet to the client
|
// send the connect packet to the client
|
||||||
NET_OutOfBandPrint( NS_SERVER, from, "connectResponse" );
|
NET_OutOfBandPrint(NS_SERVER, from, "connectResponse %d", challenge);
|
||||||
|
|
||||||
Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name );
|
Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name );
|
||||||
|
|
||||||
|
|
|
@ -643,7 +643,13 @@ void SVC_Info( netadr_t from ) {
|
||||||
// to prevent timed spoofed reply packets that add ghost servers
|
// to prevent timed spoofed reply packets that add ghost servers
|
||||||
Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
|
Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) );
|
||||||
|
|
||||||
Info_SetValueForKey( infostring, "protocol", va("%i", com_protocol->integer) );
|
#ifdef LEGACY_PROTOCOL
|
||||||
|
if(com_legacyprotocol->integer > 0)
|
||||||
|
Info_SetValueForKey(infostring, "protocol", va("%i", com_legacyprotocol->integer));
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
Info_SetValueForKey(infostring, "protocol", va("%i", com_protocol->integer));
|
||||||
|
|
||||||
Info_SetValueForKey( infostring, "hostname", sv_hostname->string );
|
Info_SetValueForKey( infostring, "hostname", sv_hostname->string );
|
||||||
Info_SetValueForKey( infostring, "mapname", sv_mapname->string );
|
Info_SetValueForKey( infostring, "mapname", sv_mapname->string );
|
||||||
Info_SetValueForKey( infostring, "clients", va("%i", count) );
|
Info_SetValueForKey( infostring, "clients", va("%i", count) );
|
||||||
|
@ -868,10 +874,6 @@ void SV_PacketEvent( netadr_t from, msg_t *msg ) {
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we received a sequenced packet from an address we don't recognize,
|
|
||||||
// send an out of band disconnect packet to it
|
|
||||||
NET_OutOfBandPrint( NS_SERVER, from, "disconnect" );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue