This is my first tutorial here. Be nice.
When I started coding, my biggest aim was, well, making Quake bigger.
If you ever used noclip to walk outside the level and kept on going,
you'd soon find out your position will be wraped after not too long and
you will pop up on the other side of the level. This is because of the
network code in Quake. The coordinate system used in Quake allows you
to walk from the point [-4096, -4096] to [4096, 4096] because
coordinates are converted to SHORTs (2^16). By increasing this to
LONGs, the coordinate system will increase to [-1048576, -1048576] by
[1048576, 1048576] meaning you now have the power to walk through
256*256 Quake maps. This will mean a huge increase in potential,
however, also in bandwith usage. For single player this is not a
problem, however for Deathmatch servers it is. That's why we'll give
the server full control over what method to use.
First off, lets add the neccesary definitions to protocol.h. Under the line
#define PROTOCOL_VERSION 15
, add the following lines:
#define PROTOCOL_NEWVERSION 16
int protocolversion;
this is to keep track which protocol the current
server is using. Next up, we need to have the host check wether or not
long coordinates are used. In Host_Init, find the lines that read
if (COM_CheckParm ("-minmemory"))
parms->memsize = minimum_memory;
and add the following lines:
if (COM_CheckParm ("-longcoords"))
protocolversion = PROTOCOL_NEWVERSION;
else
protocolversion = PROTOCOL_VERSION;
Any clients that log in nead to know what protocol
to use. This is the static defined PROTOCOL_VERSION by default, however
this should be dynamic. In SV_SendServerinfo find the lines
MSG_WriteLong (&client->message, PROTOCOL_VERSION);
and replace with
MSG_WriteLong (&client->message, protocolversion);
to send the current protocol version. Now we need to send the extra data if neccesary. Replace MSG_WriteCoord with this:
void MSG_WriteCoord (sizebuf_t *sb, float f)
{
if (protocolversion == PROTOCOL_NEWVERSION)
MSG_WriteLong (sb, (int)(f*8));
else
MSG_WriteShort (sb, (int)(f*8));
}
Okay, that takes care of the server-side. The
client-side is easy: we can use the already defined protocolversion,
since we're either not the host or we're playing single-player, meaning
we set the protocolversion when the host is initialised and send it to
ourselves, meaning no change in the value of protocolversion. First
off, lets have it check what protocol the server uses. In
CL_ParseServerinfo, find the line
if (i != PROTOCOL_VERSION)
and replace with
protocolversion = i;
if (i != PROTOCOL_VERSION && i != PROTOCOL_NEWVERSION)
now, all we need to do is receive the extended packages if necessary: replace the function float MSG_ReadCoord with
float MSG_ReadCoord (void)
{
if (protocolversion == PROTOCOL_NEWVERSION)
return MSG_ReadLong() * (1.0/8);
else
return MSG_ReadShort() * (1.0/8);
}
This should take care of the coordinate system. Just start up a map and
start walking outside the level... it will take a LOT of time before
you wrap and see the map again! As a last remark, it might be usefull
to increase the cut-off distance. If you are using OpenGL, you can do
that like this: (Thank you wParam for reminding me)
find the line that reads
MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 4096);
the 4096 is the maximum view distance, but since it is calculated as a
cube around you, you can only see 50% of this distance forward. Since I
use BIG maps (think Delta Force) i have this set at least to
MYgluPerspective (r_refdef.fov_y, screenaspect, 4, 12288);
however setting it to 8192 should suffice. Remember,
the host can switch this on with the command parameter -longcoords, but
this will require a great deal of extra bandwith as all positions are
sent in 50% bigger packages, limiting the use mostly to single-player
or LAN-based play. |