Skip to content

Commit

Permalink
Merged pull request "Sync with Q2PRO: Network/protocol changes": NVID…
Browse files Browse the repository at this point in the history
  • Loading branch information
apanteleev committed Jan 23, 2024
2 parents 8106efa + 8b12324 commit 32d0fe4
Show file tree
Hide file tree
Showing 26 changed files with 474 additions and 501 deletions.
19 changes: 19 additions & 0 deletions doc/server.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ Otherwise clients will be unable to connect.
If set to 0, server will skip cinematics even if they exist. Default value
is 1.

#### `sv_max_packet_entities`
Maximum number of entities in client frame. 0 means unlimited. Default
value is 128. Some non-standard maps with large open areas may need this
value increased. Consider however that default Quake 2 client can only
render 128 entities maximum. Other clients may support more.

#### `sv_reserved_slots`
Number of client slots reserved for clients who know `sv_reserved_password`
or `sv_password`. Must be less than `maxclients` value. Default value is 0
Expand All @@ -157,6 +163,15 @@ When enabled, do not enforce any rate limits on clients whose IP is from
private address space (`127.x.x.x`, `10.x.x.x`, `192.168.x.x`, `172.16.x.x`).
Default value is 0 (disabled).

#### `sv_min_rate``
Server clamps minimum value of `rate` userinfo parameter to this value.
Default value is 1500 bytes/sec. This parameter can't be greater than
`sv_max_rate` value or less than 1500 bytes/sec.

#### `sv_max_rate``
Server clamps maximum value of `rate` userinfo parameter to this value.
Default value is 15000 bytes/sec.

#### `sv_calcpings_method`
Specifies the way client pings are calculated. Default ping calculation
algorithm is very client frame and packet rate dependent, and may give
Expand Down Expand Up @@ -299,6 +314,10 @@ Default value is 1.
Enables downloading of files from any subdirectory other than those listed
above. Default value is 0.

#### `sv_max_download_size`
Maximum size of UDP download in bytes. Value of 0 disables the limit.
Default value is 8388608 (8 MiB).


### MVD/GTV server

Expand Down
42 changes: 23 additions & 19 deletions inc/common/msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/protocol.h"
#include "common/sizebuf.h"

#define MAX_PACKETENTITY_BYTES 64 // rough estimate

// entity and player states are pre-quantized before sending to make delta
// comparsion easier
typedef struct {
Expand Down Expand Up @@ -58,25 +60,25 @@ typedef struct {
} player_packed_t;

typedef enum {
MSG_PS_IGNORE_GUNINDEX = (1 << 0),
MSG_PS_IGNORE_GUNFRAMES = (1 << 1),
MSG_PS_IGNORE_BLEND = (1 << 2),
MSG_PS_IGNORE_VIEWANGLES = (1 << 3),
MSG_PS_IGNORE_DELTAANGLES = (1 << 4),
MSG_PS_IGNORE_PREDICTION = (1 << 5), // mutually exclusive with IGNORE_VIEWANGLES
MSG_PS_FORCE = (1 << 7),
MSG_PS_REMOVE = (1 << 8)
MSG_PS_IGNORE_GUNINDEX = (1 << 0), // ignore gunindex
MSG_PS_IGNORE_GUNFRAMES = (1 << 1), // ignore gunframe/gunoffset/gunangles
MSG_PS_IGNORE_BLEND = (1 << 2), // ignore blend
MSG_PS_IGNORE_VIEWANGLES = (1 << 3), // ignore viewangles
MSG_PS_IGNORE_DELTAANGLES = (1 << 4), // ignore delta_angles
MSG_PS_IGNORE_PREDICTION = (1 << 5), // mutually exclusive with IGNORE_VIEWANGLES
MSG_PS_FORCE = (1 << 7), // send even if unchanged (MVD stream only)
MSG_PS_REMOVE = (1 << 8), // player is removed (MVD stream only)
} msgPsFlags_t;

typedef enum {
MSG_ES_FORCE = (1 << 0),
MSG_ES_NEWENTITY = (1 << 1),
MSG_ES_FIRSTPERSON = (1 << 2),
MSG_ES_LONGSOLID = (1 << 3),
MSG_ES_UMASK = (1 << 4),
MSG_ES_BEAMORIGIN = (1 << 5),
MSG_ES_SHORTANGLES = (1 << 6),
MSG_ES_REMOVE = (1 << 7)
MSG_ES_FORCE = (1 << 0), // send even if unchanged
MSG_ES_NEWENTITY = (1 << 1), // send old_origin
MSG_ES_FIRSTPERSON = (1 << 2), // ignore origin/angles
MSG_ES_LONGSOLID = (1 << 3), // higher precision bbox encoding
MSG_ES_UMASK = (1 << 4), // client has 16-bit mask MSB fix
MSG_ES_BEAMORIGIN = (1 << 5), // client has RF_BEAM old_origin fix
MSG_ES_SHORTANGLES = (1 << 6), // higher precision angles encoding
MSG_ES_REMOVE = (1 << 7), // entity is removed (MVD stream only)
} msgEsFlags_t;

extern sizebuf_t msg_write;
Expand All @@ -96,17 +98,18 @@ void MSG_WriteChar(int c);
void MSG_WriteByte(int c);
void MSG_WriteShort(int c);
void MSG_WriteLong(int c);
void MSG_WriteLong64(int64_t c);
void MSG_WriteString(const char *s);
void MSG_WritePos(const vec3_t pos);
void MSG_WriteAngle(float f);
#if USE_CLIENT
void MSG_FlushBits(void);
void MSG_WriteBits(int value, int bits);
int MSG_WriteDeltaUsercmd(const usercmd_t *from, const usercmd_t *cmd, int version);
int MSG_WriteDeltaUsercmd_Enhanced(const usercmd_t *from, const usercmd_t *cmd, int version);
int MSG_WriteDeltaUsercmd_Enhanced(const usercmd_t *from, const usercmd_t *cmd);
#endif
void MSG_WriteDir(const vec3_t vector);
void MSG_PackEntity(entity_packed_t *out, const entity_state_t *in, bool short_angles);
void MSG_PackEntity(entity_packed_t *out, const entity_state_t *in);
void MSG_WriteDeltaEntity(const entity_packed_t *from, const entity_packed_t *to, msgEsFlags_t flags);
void MSG_PackPlayer(player_packed_t *out, const player_state_t *in);
void MSG_WriteDeltaPlayerstate_Default(const player_packed_t *from, const player_packed_t *to);
Expand All @@ -131,6 +134,7 @@ int MSG_ReadByte(void);
int MSG_ReadShort(void);
int MSG_ReadWord(void);
int MSG_ReadLong(void);
int64_t MSG_ReadLong64(void);
size_t MSG_ReadString(char *dest, size_t size);
size_t MSG_ReadStringLine(char *dest, size_t size);
#if USE_CLIENT
Expand All @@ -140,7 +144,7 @@ void MSG_ReadDir(vec3_t vector);
int MSG_ReadBits(int bits);
void MSG_ReadDeltaUsercmd(const usercmd_t *from, usercmd_t *cmd);
void MSG_ReadDeltaUsercmd_Hacked(const usercmd_t *from, usercmd_t *to);
void MSG_ReadDeltaUsercmd_Enhanced(const usercmd_t *from, usercmd_t *to, int version);
void MSG_ReadDeltaUsercmd_Enhanced(const usercmd_t *from, usercmd_t *to);
int MSG_ParseEntityBits(int *bits);
void MSG_ParseDeltaEntity(const entity_state_t *from, entity_state_t *to, int number, int bits, msgEsFlags_t flags);
#if USE_CLIENT
Expand Down
14 changes: 7 additions & 7 deletions inc/common/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define PROTOCOL_VERSION_R1Q2_LONG_SOLID 1905 // b7759
#define PROTOCOL_VERSION_R1Q2_CURRENT 1905 // b7759

#define PROTOCOL_VERSION_Q2PRO_MINIMUM 1011 // r161
#define PROTOCOL_VERSION_Q2PRO_UCMD 1012 // r179
#define PROTOCOL_VERSION_Q2PRO_CLIENTNUM_FIX 1013 // r226
#define PROTOCOL_VERSION_Q2PRO_LONG_SOLID 1014 // r243
#define PROTOCOL_VERSION_Q2PRO_WATERJUMP_HACK 1015 // r335
#define PROTOCOL_VERSION_Q2PRO_MINIMUM 1015 // r335
#define PROTOCOL_VERSION_Q2PRO_RESERVED 1016 // r364
#define PROTOCOL_VERSION_Q2PRO_BEAM_ORIGIN 1017 // r1037-8
#define PROTOCOL_VERSION_Q2PRO_SHORT_ANGLES 1018 // r1037-44
Expand Down Expand Up @@ -339,10 +335,14 @@ typedef enum {
#define U_SOUND (1<<26)
#define U_SOLID (1<<27)

#define U_SKIN32 (U_SKIN8 | U_SKIN16) // used for laser colors
#define U_EFFECTS32 (U_EFFECTS8 | U_EFFECTS16)
#define U_RENDERFX32 (U_RENDERFX8 | U_RENDERFX16)

// ==============================================================

#define CLIENTNUM_NONE (MAX_CLIENTS - 1)
#define CLIENTNUM_RESERVED (MAX_CLIENTS - 1)
// a client with this number will never be included in MVD stream
#define CLIENTNUM_NONE (MAX_CLIENTS - 1)

// a SOLID_BBOX will never create this value
#define PACKED_BSP 31
Expand Down
4 changes: 2 additions & 2 deletions src/client/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,19 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common/cvar.h"
#include "common/field.h"
#include "common/files.h"
#include "common/pmove.h"
#include "common/math.h"
#include "common/msg.h"
#include "common/net/chan.h"
#include "common/net/net.h"
#include "common/pmove.h"
#include "common/prompt.h"
#include "common/protocol.h"
#include "common/sizebuf.h"
#include "common/zone.h"

#include "system/system.h"
#include "refresh/refresh.h"
#include "server/server.h"
#include "system/system.h"

#include "client/client.h"
#include "client/input.h"
Expand Down
20 changes: 10 additions & 10 deletions src/client/demo.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ static void emit_packet_entities(server_frame_t *from, server_frame_t *to)
// not changed at all. Note that players are always 'newentities',
// this updates their old_origin always and prevents warping in case
// of packet loss.
MSG_PackEntity(&oldpack, oldent, false);
MSG_PackEntity(&newpack, newent, false);
MSG_PackEntity(&oldpack, oldent);
MSG_PackEntity(&newpack, newent);
MSG_WriteDeltaEntity(&oldpack, &newpack,
newent->number <= cl.maxclients ? MSG_ES_NEWENTITY : 0);
oldindex++;
Expand All @@ -123,16 +123,16 @@ static void emit_packet_entities(server_frame_t *from, server_frame_t *to)

if (newnum < oldnum) {
// this is a new entity, send it from the baseline
MSG_PackEntity(&oldpack, &cl.baselines[newnum], false);
MSG_PackEntity(&newpack, newent, false);
MSG_PackEntity(&oldpack, &cl.baselines[newnum]);
MSG_PackEntity(&newpack, newent);
MSG_WriteDeltaEntity(&oldpack, &newpack, MSG_ES_FORCE | MSG_ES_NEWENTITY);
newindex++;
continue;
}

if (newnum > oldnum) {
// the old entity isn't present in the new message
MSG_PackEntity(&oldpack, oldent, false);
MSG_PackEntity(&oldpack, oldent);
MSG_WriteDeltaEntity(&oldpack, NULL, MSG_ES_FORCE);
oldindex++;
continue;
Expand Down Expand Up @@ -428,13 +428,13 @@ static void CL_Record_f(void)
if (!ent->number)
continue;

if (msg_write.cursize + 64 > size) {
if (msg_write.cursize + MAX_PACKETENTITY_BYTES > size) {
if (!CL_WriteDemoMessage(&msg_write))
return;
}

MSG_WriteByte(svc_spawnbaseline);
MSG_PackEntity(&pack, ent, false);
MSG_PackEntity(&pack, ent);
MSG_WriteDeltaEntity(NULL, &pack, MSG_ES_FORCE);
}

Expand Down Expand Up @@ -1111,7 +1111,7 @@ demoInfo_t *CL_GetDemoInfo(const char *path, demoInfo_t *info)
if (c != svc_configstring) {
break;
}
index = MSG_ReadShort();
index = MSG_ReadWord();
if (index < 0 || index >= MAX_CONFIGSTRINGS) {
goto fail;
}
Expand All @@ -1127,13 +1127,13 @@ demoInfo_t *CL_GetDemoInfo(const char *path, demoInfo_t *info)
if (MSG_ReadLong() != PROTOCOL_VERSION_MVD) {
goto fail;
}
MSG_ReadShort();
MSG_ReadWord();
MSG_ReadLong();
MSG_ReadString(NULL, 0);
clientNum = MSG_ReadShort();

while (1) {
index = MSG_ReadShort();
index = MSG_ReadWord();
if (index == MAX_CONFIGSTRINGS) {
break;
}
Expand Down
14 changes: 4 additions & 10 deletions src/client/entities.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,12 @@ FRAME PARSING
=========================================================================
*/

// returns true if origin/angles update has been optimized out
static inline bool entity_is_optimized(const entity_state_t *state)
{
if (cls.serverProtocol != PROTOCOL_VERSION_Q2PRO)
return false;

if (state->number != cl.frame.clientNum + 1)
return false;

if (cl.frame.ps.pmove.pm_type >= PM_DEAD)
return false;

return true;
return cls.serverProtocol == PROTOCOL_VERSION_Q2PRO
&& state->number == cl.frame.clientNum + 1
&& cl.frame.ps.pmove.pm_type < PM_DEAD;
}

static inline void
Expand Down
14 changes: 5 additions & 9 deletions src/client/gtv.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
//

#include "client.h"
#include "common/intreadwrite.h"
#include "server/mvd/protocol.h"

static byte gtv_recv_buffer[MAX_GTC_MSGLEN];
Expand All @@ -46,7 +47,7 @@ static void build_gamestate(void)
continue;
}

MSG_PackEntity(&cls.gtv.entities[i], &ent->current, false);
MSG_PackEntity(&cls.gtv.entities[i], &ent->current);
}
}

Expand Down Expand Up @@ -155,7 +156,7 @@ void CL_GTV_EmitFrame(void)
}

// quantize
MSG_PackEntity(&newes, &ent->current, false);
MSG_PackEntity(&newes, &ent->current);

MSG_WriteDeltaEntity(oldes, &newes, flags);

Expand Down Expand Up @@ -200,10 +201,8 @@ static void write_stream(void *data, size_t len)
static void write_message(gtv_serverop_t op)
{
byte header[3];
size_t len = msg_write.cursize + 1;

header[0] = len & 255;
header[1] = (len >> 8) & 255;
WL16(header, msg_write.cursize + 1);
header[2] = op;
write_stream(header, sizeof(header));

Expand Down Expand Up @@ -274,7 +273,6 @@ void CL_GTV_Suspend(void)
void CL_GTV_Transmit(void)
{
byte header[3];
size_t total;

if (cls.gtv.state != ca_active)
return;
Expand All @@ -294,9 +292,7 @@ void CL_GTV_Transmit(void)
return;

// build message header
total = cls.gtv.message.cursize + 1;
header[0] = total & 255;
header[1] = (total >> 8) & 255;
WL16(header, cls.gtv.message.cursize + 1);
header[2] = GTS_STREAM_DATA;

// send frame to client
Expand Down
12 changes: 8 additions & 4 deletions src/client/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -872,6 +872,7 @@ static void CL_SendDefaultCmd(void)
size_t cursize q_unused, checksumIndex;
usercmd_t *cmd, *oldcmd;
client_history_t *history;
int version;

// archive this packet
history = &cl.history[cls.netchan.outgoing_sequence & CMD_MASK];
Expand All @@ -895,9 +896,12 @@ static void CL_SendDefaultCmd(void)

// save the position for a checksum byte
checksumIndex = 0;
version = 0;
if (cls.serverProtocol <= PROTOCOL_VERSION_DEFAULT) {
checksumIndex = msg_write.cursize;
SZ_GetSpace(&msg_write, 1);
} else if (cls.serverProtocol == PROTOCOL_VERSION_R1Q2) {
version = cls.protocolVersion;
}

// let the server know what the last frame we
Expand All @@ -911,17 +915,17 @@ static void CL_SendDefaultCmd(void)
// send this and the previous cmds in the message, so
// if the last packet was dropped, it can be recovered
cmd = &cl.cmds[(cl.cmdNumber - 2) & CMD_MASK];
MSG_WriteDeltaUsercmd(NULL, cmd, cls.protocolVersion);
MSG_WriteDeltaUsercmd(NULL, cmd, version);
MSG_WriteByte(cl.lightlevel);
oldcmd = cmd;

cmd = &cl.cmds[(cl.cmdNumber - 1) & CMD_MASK];
MSG_WriteDeltaUsercmd(oldcmd, cmd, cls.protocolVersion);
MSG_WriteDeltaUsercmd(oldcmd, cmd, version);
MSG_WriteByte(cl.lightlevel);
oldcmd = cmd;

cmd = &cl.cmds[cl.cmdNumber & CMD_MASK];
MSG_WriteDeltaUsercmd(oldcmd, cmd, cls.protocolVersion);
MSG_WriteDeltaUsercmd(oldcmd, cmd, version);
MSG_WriteByte(cl.lightlevel);

if (cls.serverProtocol <= PROTOCOL_VERSION_DEFAULT) {
Expand Down Expand Up @@ -1020,7 +1024,7 @@ static void CL_SendBatchedCmd(void)
for (j = oldest->cmdNumber + 1; j <= history->cmdNumber; j++) {
cmd = &cl.cmds[j & CMD_MASK];
totalMsec += cmd->msec;
bits = MSG_WriteDeltaUsercmd_Enhanced(oldcmd, cmd, cls.protocolVersion);
bits = MSG_WriteDeltaUsercmd_Enhanced(oldcmd, cmd);
#if USE_DEBUG
if (cl_showpackets->integer == 3) {
MSG_ShowDeltaUsercmdBits_Enhanced(bits);
Expand Down
Loading

0 comments on commit 32d0fe4

Please sign in to comment.