int crouch;
int onground;
double edgefriction;
- double simulatedtime;
double frametime;
double t;
vec_t wishspeed;
// remove stale queue items
n = cl.movement_numqueue;
cl.movement_numqueue = 0;
- // calculate time to execute for
- simulatedtime = cl.mtime[0] + cl_movement_latency.value / 1000.0;
- for (i = 0;i < n;i++)
- if (cl.movement_queue[i].time >= cl.mtime[0] && cl.movement_queue[i].time <= simulatedtime)
- cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+ if (cl.servermovesequence)
+ {
+ for (i = 0;i < n;i++)
+ if (cl.movement_queue[i].sequence > cl.servermovesequence)
+ cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+ }
+ else
+ {
+ double simulatedtime = cl.mtime[0] + cl_movement_latency.value / 1000.0;
+ for (i = 0;i < n;i++)
+ if (cl.movement_queue[i].time >= cl.mtime[0] && cl.movement_queue[i].time <= simulatedtime)
+ cl.movement_queue[cl.movement_numqueue++] = cl.movement_queue[i];
+ }
// add to input queue if there is room
- if (cl.movement_numqueue < sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0]) && cl.mtime[0] > cl.mtime[1])
+ if (cl_movement.integer && cl.movement_numqueue < sizeof(cl.movement_queue)/sizeof(cl.movement_queue[0]) && cl.mtime[0] > cl.mtime[1])
{
// add to input queue
- cl.movement_queue[cl.movement_numqueue].time = simulatedtime;
+ cl.movement_queue[cl.movement_numqueue].sequence = cl.movesequence;
+ cl.movement_queue[cl.movement_numqueue].time = cl.mtime[0] + cl_movement_latency.value / 1000.0;
cl.movement_queue[cl.movement_numqueue].frametime = cl.mtime[0] - cl.mtime[1];
VectorCopy(cl.viewangles, cl.movement_queue[cl.movement_numqueue].viewangles);
cl.movement_queue[cl.movement_numqueue].move[0] = cl.cmd.forwardmove;
// replay input queue, and remove any stale queue items
// note: this relies on the fact there's always one queue item at the end
// abort if client movement is disabled
- cl.movement = cl_movement.integer && cl.stats[STAT_HEALTH] > 0 && !cls.demoplayback;
+ cl.movement = /*cl_movement.integer && */cl.stats[STAT_HEALTH] > 0 && !cls.demoplayback;
if (!cl.movement)
cl.movement_numqueue = 0;
for (i = 0;i < cl.movement_numqueue;i++)
if (++cl.movemessages >= 2)
{
// send the movement message
- // PROTOCOL_QUAKE clc_move = 16 bytes total
- // PROTOCOL_DARKPLACES1 clc_move = 19 bytes total
- // PROTOCOL_DARKPLACES2 clc_move = 25 bytes total
- // PROTOCOL_DARKPLACES3 clc_move = 25 bytes total
- // PROTOCOL_DARKPLACES4 clc_move = 19 bytes total
- // PROTOCOL_DARKPLACES5 clc_move = 19 bytes total
- // PROTOCOL_DARKPLACES6 clc_move = 52 bytes total
- // 5 bytes
- MSG_WriteByte (&buf, clc_move);
- MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
- if (cl.protocol == PROTOCOL_DARKPLACES6)
+ // PROTOCOL_QUAKE clc_move = 16 bytes total
+ // PROTOCOL_QUAKEDP clc_move = 16 bytes total
+ // PROTOCOL_NEHAHRAMOVIE clc_move = 16 bytes total
+ // PROTOCOL_DARKPLACES1 clc_move = 19 bytes total
+ // PROTOCOL_DARKPLACES2 clc_move = 25 bytes total
+ // PROTOCOL_DARKPLACES3 clc_move = 25 bytes total
+ // PROTOCOL_DARKPLACES4 clc_move = 19 bytes total
+ // PROTOCOL_DARKPLACES5 clc_move = 19 bytes total
+ // PROTOCOL_DARKPLACES6 clc_move = 52 bytes total
+ // PROTOCOL_DARKPLACES7 clc_move = 56 bytes total
+ if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_QUAKEDP || cl.protocol == PROTOCOL_NEHAHRAMOVIE)
+ {
+ // 5 bytes
+ MSG_WriteByte (&buf, clc_move);
+ MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
+ // 3 bytes
+ for (i = 0;i < 3;i++)
+ MSG_WriteAngle8i (&buf, cl.viewangles[i]);
+ // 6 bytes
+ MSG_WriteCoord16i (&buf, forwardmove);
+ MSG_WriteCoord16i (&buf, sidemove);
+ MSG_WriteCoord16i (&buf, upmove);
+ // 2 bytes
+ MSG_WriteByte (&buf, bits);
+ MSG_WriteByte (&buf, in_impulse);
+ }
+ else if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
+ {
+ // 5 bytes
+ MSG_WriteByte (&buf, clc_move);
+ MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
+ // 12 bytes
+ for (i = 0;i < 3;i++)
+ MSG_WriteAngle32f (&buf, cl.viewangles[i]);
+ // 6 bytes
+ MSG_WriteCoord16i (&buf, forwardmove);
+ MSG_WriteCoord16i (&buf, sidemove);
+ MSG_WriteCoord16i (&buf, upmove);
+ // 2 bytes
+ MSG_WriteByte (&buf, bits);
+ MSG_WriteByte (&buf, in_impulse);
+ }
+ else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
+ {
+ // 5 bytes
+ MSG_WriteByte (&buf, clc_move);
+ MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
+ // 6 bytes
+ for (i = 0;i < 3;i++)
+ MSG_WriteAngle16i (&buf, cl.viewangles[i]);
+ // 6 bytes
+ MSG_WriteCoord16i (&buf, forwardmove);
+ MSG_WriteCoord16i (&buf, sidemove);
+ MSG_WriteCoord16i (&buf, upmove);
+ // 2 bytes
+ MSG_WriteByte (&buf, bits);
+ MSG_WriteByte (&buf, in_impulse);
+ }
+ else
{
+ // 5 bytes
+ MSG_WriteByte (&buf, clc_move);
+ if (cl.protocol != PROTOCOL_DARKPLACES6)
+ {
+ if (cl_movement.integer)
+ {
+ cl.movesequence++;
+ MSG_WriteLong (&buf, cl.movesequence);
+ }
+ else
+ MSG_WriteLong (&buf, 0);
+ }
+ MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times
// 6 bytes
for (i = 0;i < 3;i++)
MSG_WriteAngle16i (&buf, cl.viewangles[i]);
MSG_WriteFloat (&buf, cl.cmd.cursor_impact[2]);
MSG_WriteShort (&buf, cl.cmd.cursor_entitynumber);
}
- else
- {
- if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_NEHAHRAMOVIE)
- {
- // 3 bytes
- for (i = 0;i < 3;i++)
- MSG_WriteAngle8i (&buf, cl.viewangles[i]);
- }
- else if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3)
- {
- // 12 bytes
- for (i = 0;i < 3;i++)
- MSG_WriteAngle32f (&buf, cl.viewangles[i]);
- }
- else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
- {
- // 6 bytes
- for (i = 0;i < 3;i++)
- MSG_WriteAngle16i (&buf, cl.viewangles[i]);
- }
- else
- Host_Error("CL_SendMove: unknown cl.protocol %i\n", cl.protocol);
- // 6 bytes
- MSG_WriteCoord16i (&buf, forwardmove);
- MSG_WriteCoord16i (&buf, sidemove);
- MSG_WriteCoord16i (&buf, upmove);
- // 2 bytes
- MSG_WriteByte (&buf, bits);
- MSG_WriteByte (&buf, in_impulse);
- }
}
#if MOVEAVERAGING
}
// PROTOCOL_DARKPLACES6 = 67 bytes per packet
+ // PROTOCOL_DARKPLACES7 = 71 bytes per packet
// deliver the message
if (cls.demoplayback)
{
char *str;
int i;
+ protocolversion_t protocol;
int nummodels, numsounds;
entity_t *ent;
// parse protocol version number
i = MSG_ReadLong ();
- // hack for unmarked Nehahra movie demos which had a custom protocol
- if (i == PROTOCOL_QUAKE && cls.demoplayback && demo_nehahra.integer)
- i = PROTOCOL_NEHAHRAMOVIE;
- if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_DARKPLACES6 && i != PROTOCOL_NEHAHRAMOVIE)
+ protocol = Protocol_EnumForNumber(i);
+ if (protocol == PROTOCOL_UNKNOWN)
{
- Host_Error("CL_ParseServerInfo: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), %i (DP6), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_DARKPLACES6, PROTOCOL_NEHAHRAMOVIE);
+ Host_Error("CL_ParseServerInfo: Server is unrecognized protocol number (%i)\n", i);
return;
}
- cl.protocol = i;
- Con_DPrintf("Server protocol is %i\n", cl.protocol);
+ // hack for unmarked Nehahra movie demos which had a custom protocol
+ if (protocol == PROTOCOL_QUAKEDP && cls.demoplayback && demo_nehahra.integer)
+ protocol = PROTOCOL_NEHAHRAMOVIE;
+ cl.protocol = protocol;
+ Con_DPrintf("Server protocol is %s\n", Protocol_NameForEnum(cl.protocol));
// parse maxclients
cl.maxclients = MSG_ReadByte ();
VectorCopy (cl.mvelocity[0], cl.mvelocity[1]);
cl.mviewzoom[1] = cl.mviewzoom[0];
- if (cl.protocol != PROTOCOL_DARKPLACES6)
+ if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_QUAKEDP || cl.protocol == PROTOCOL_NEHAHRAMOVIE || cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
{
cl.stats[STAT_VIEWHEIGHT] = DEFAULT_VIEWHEIGHT;
cl.stats[STAT_ITEMS] = 0;
{
if (bits & (SU_PUNCH1<<i) )
{
- if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
- cl.mpunchangle[0][i] = MSG_ReadAngle16i();
- else if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_NEHAHRAMOVIE)
+ if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_QUAKEDP || cl.protocol == PROTOCOL_NEHAHRAMOVIE)
cl.mpunchangle[0][i] = MSG_ReadChar();
else
- Host_Error("CL_ParseClientData: unknown cl.protocol %i\n", cl.protocol);
+ cl.mpunchangle[0][i] = MSG_ReadAngle16i();
}
if (bits & (SU_PUNCHVEC1<<i))
{
if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4)
cl.mpunchvector[0][i] = MSG_ReadCoord16i();
- else if (cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
- cl.mpunchvector[0][i] = MSG_ReadCoord32f();
else
- Host_Error("CL_ParseClientData: unknown cl.protocol %i\n", cl.protocol);
+ cl.mpunchvector[0][i] = MSG_ReadCoord32f();
}
if (bits & (SU_VELOCITY1<<i) )
{
- if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_NEHAHRAMOVIE || cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4)
+ if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_QUAKEDP || cl.protocol == PROTOCOL_NEHAHRAMOVIE || cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4)
cl.mvelocity[0][i] = MSG_ReadChar()*16;
- else if (cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
- cl.mvelocity[0][i] = MSG_ReadCoord32f();
else
- Host_Error("CL_ParseClientData: unknown cl.protocol %i\n", cl.protocol);
+ cl.mvelocity[0][i] = MSG_ReadCoord32f();
}
}
// LordHavoc: hipnotic demos don't have this bit set but should
- if (bits & SU_ITEMS || cl.protocol != PROTOCOL_DARKPLACES6)
+ if (bits & SU_ITEMS || cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_QUAKEDP || cl.protocol == PROTOCOL_NEHAHRAMOVIE || cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5)
cl.stats[STAT_ITEMS] = MSG_ReadLong ();
cl.onground = (bits & SU_ONGROUND) != 0;
cl.inwater = (bits & SU_INWATER) != 0;
- if (cl.protocol == PROTOCOL_DARKPLACES6)
- {
- }
- else if (cl.protocol == PROTOCOL_DARKPLACES5)
+ if (cl.protocol == PROTOCOL_DARKPLACES5)
{
cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadShort() : 0;
cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadShort() : 0;
cl.stats[STAT_CELLS] = MSG_ReadShort();
cl.stats[STAT_ACTIVEWEAPON] = (unsigned short) MSG_ReadShort ();
}
- else
+ else if (cl.protocol == PROTOCOL_QUAKE || cl.protocol == PROTOCOL_QUAKEDP || cl.protocol == PROTOCOL_NEHAHRAMOVIE || cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4)
{
cl.stats[STAT_WEAPONFRAME] = (bits & SU_WEAPONFRAME) ? MSG_ReadByte() : 0;
cl.stats[STAT_ARMOR] = (bits & SU_ARMOR) ? MSG_ReadByte() : 0;
if (bits & SU_VIEWZOOM)
{
- if (cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
- cl.stats[STAT_VIEWZOOM] = (unsigned short) MSG_ReadShort();
- else
+ if (cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4)
cl.stats[STAT_VIEWZOOM] = MSG_ReadByte();
+ else
+ cl.stats[STAT_VIEWZOOM] = (unsigned short) MSG_ReadShort();
}
// check for important changes
{
int cmd;
int i;
+ protocolversion_t protocol;
qbyte cmdlog[32];
char *cmdlogname[32], *temp;
int cmdindex, cmdcount = 0;
case svc_version:
i = MSG_ReadLong ();
+ protocol = Protocol_EnumForNumber(i);
+ if (protocol == PROTOCOL_UNKNOWN)
+ Host_Error("CL_ParseServerMessage: Server is unrecognized protocol number (%i)\n", i);
// hack for unmarked Nehahra movie demos which had a custom protocol
- if (i == PROTOCOL_QUAKE && cls.demoplayback && demo_nehahra.integer)
- i = PROTOCOL_NEHAHRAMOVIE;
- if (i != PROTOCOL_QUAKE && i != PROTOCOL_DARKPLACES1 && i != PROTOCOL_DARKPLACES2 && i != PROTOCOL_DARKPLACES3 && i != PROTOCOL_DARKPLACES4 && i != PROTOCOL_DARKPLACES5 && i != PROTOCOL_DARKPLACES6 && i != PROTOCOL_NEHAHRAMOVIE)
- Host_Error("CL_ParseServerMessage: Server is protocol %i, not %i (Quake), %i (DP1), %i (DP2), %i (DP3), %i (DP4), %i (DP5), %i (DP6), or %i (Nehahra movie)", i, PROTOCOL_QUAKE, PROTOCOL_DARKPLACES1, PROTOCOL_DARKPLACES2, PROTOCOL_DARKPLACES3, PROTOCOL_DARKPLACES4, PROTOCOL_DARKPLACES5, PROTOCOL_DARKPLACES6, PROTOCOL_NEHAHRAMOVIE);
- cl.protocol = i;
+ if (protocol == PROTOCOL_QUAKEDP && cls.demoplayback && demo_nehahra.integer)
+ protocol = PROTOCOL_NEHAHRAMOVIE;
+ cl.protocol = protocol;
break;
case svc_disconnect:
EntityFrame_CL_ReadFrame();
else if (cl.protocol == PROTOCOL_DARKPLACES4)
EntityFrame4_CL_ReadFrame();
- else if (cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
- EntityFrame5_CL_ReadFrame();
else
- Host_Error("CL_ParseServerMessage: svc_entities: unknown cl.protocol %i\n", cl.protocol);
+ EntityFrame5_CL_ReadFrame();
break;
}
}
double receivetime;
int buttons;
int impulse;
+ int sequence;
} usercmd_t;
typedef struct
{
double time;
float frametime;
+ int sequence;
float viewangles[3];
float move[3];
qboolean jump;
// queue of proposed moves
int movement_numqueue;
client_movementqueue_t movement_queue[256];
+ int movesequence;
+ int servermovesequence;
// pitch drifting vars
float idealpitch;
scoreboard_t *scores;
// protocol version of the server we're connected to
- int protocol;
+ protocolversion_t protocol;
// entity database stuff
// latest received entity frame numbers
MSG_WriteFloat (sb, f);
}
-void MSG_WriteCoord (sizebuf_t *sb, float f, int protocol)
+void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol)
{
- if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_NEHAHRAMOVIE)
+ if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE)
MSG_WriteCoord13i (sb, f);
- else if (protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6)
+ else if (protocol == PROTOCOL_DARKPLACES1)
MSG_WriteCoord32f (sb, f);
else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
MSG_WriteCoord16i (sb, f);
else
- Host_Error("MSG_WriteCoord: unknown protocol\n");
+ MSG_WriteCoord32f (sb, f);
+ //else
+ // Host_Error("MSG_WriteCoord: unknown protocol\n");
}
-void MSG_WriteVector (sizebuf_t *sb, float *v, int protocol)
+void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol)
{
MSG_WriteCoord (sb, v[0], protocol);
MSG_WriteCoord (sb, v[1], protocol);
MSG_WriteFloat (sb, f);
}
-void MSG_WriteAngle (sizebuf_t *sb, float f, int protocol)
+void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol)
{
- if (protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6)
- MSG_WriteAngle16i (sb, f);
- else
+ if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
MSG_WriteAngle8i (sb, f);
+ else
+ MSG_WriteAngle16i (sb, f);
}
//
return MSG_ReadLittleFloat();
}
-float MSG_ReadCoord (int protocol)
+float MSG_ReadCoord (protocolversion_t protocol)
{
- if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_NEHAHRAMOVIE)
+ if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE)
return MSG_ReadCoord13i();
- else if (protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6)
+ else if (protocol == PROTOCOL_DARKPLACES1)
return MSG_ReadCoord32f();
else if (protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
return MSG_ReadCoord16i();
- Host_Error("MSG_ReadCoord: unknown protocol\n");
- return 0;
+ else
+ return MSG_ReadCoord32f();
}
-void MSG_ReadVector (float *v, int protocol)
+void MSG_ReadVector (float *v, protocolversion_t protocol)
{
v[0] = MSG_ReadCoord(protocol);
v[1] = MSG_ReadCoord(protocol);
return MSG_ReadFloat ();
}
-float MSG_ReadAngle (int protocol)
+float MSG_ReadAngle (protocolversion_t protocol)
{
- if (protocol == PROTOCOL_DARKPLACES5 || protocol == PROTOCOL_DARKPLACES6)
- return MSG_ReadAngle16i ();
- else
+ if (protocol == PROTOCOL_QUAKE || protocol == PROTOCOL_QUAKEDP || protocol == PROTOCOL_NEHAHRAMOVIE || protocol == PROTOCOL_DARKPLACES1 || protocol == PROTOCOL_DARKPLACES2 || protocol == PROTOCOL_DARKPLACES3 || protocol == PROTOCOL_DARKPLACES4)
return MSG_ReadAngle8i ();
+ else
+ return MSG_ReadAngle16i ();
}
//============================================================================
+// these versions are purely for internal use, never sent in network protocol
+// (use Protocol_EnumForNumber and Protocol_NumberToEnum to convert)
+typedef enum protocolversion_e
+{
+ PROTOCOL_UNKNOWN,
+ PROTOCOL_QUAKE, // quake (aka netquake/normalquake/nq) protocol
+ PROTOCOL_QUAKEDP, // darkplaces extended quake protocol (used by TomazQuake and others), backwards compatible as long as no extended features are used
+ PROTOCOL_NEHAHRAMOVIE, // Nehahra movie protocol, a big nasty hack dating back to early days of the Quake Standards Group (but only ever used by neh_gl.exe), this is potentially backwards compatible with quake protocol as long as no extended features are used (but in actuality the neh_gl.exe which wrote this protocol ALWAYS wrote the extended information)
+ PROTOCOL_DARKPLACES1, // uses EntityFrame_ entity snapshot encoder/decoder which is a QuakeWorld-like entity snapshot delta compression method
+ PROTOCOL_DARKPLACES2, // various changes
+ PROTOCOL_DARKPLACES3, // uses EntityFrame4 entity snapshot encoder/decoder which is broken, this attempted to do partial snapshot updates on a QuakeWorld-like protocol, but it is broken and impossible to fix
+ PROTOCOL_DARKPLACES4, // various changes
+ PROTOCOL_DARKPLACES5, // uses EntityFrame5 entity snapshot encoder/decoder which is based on a Tribes networking article at http://www.garagegames.com/articles/networking1/
+ PROTOCOL_DARKPLACES6, // various changes
+ PROTOCOL_DARKPLACES7, // added QuakeWorld-style movement protocol to allow more consistent prediction
+}
+protocolversion_t;
+
void MSG_WriteChar (sizebuf_t *sb, int c);
void MSG_WriteByte (sizebuf_t *sb, int c);
void MSG_WriteShort (sizebuf_t *sb, int c);
void MSG_WriteCoord13i (sizebuf_t *sb, float f);
void MSG_WriteCoord16i (sizebuf_t *sb, float f);
void MSG_WriteCoord32f (sizebuf_t *sb, float f);
-void MSG_WriteCoord (sizebuf_t *sb, float f, int protocol);
-void MSG_WriteVector (sizebuf_t *sb, float *v, int protocol);
-void MSG_WriteAngle (sizebuf_t *sb, float f, int protocol);
+void MSG_WriteCoord (sizebuf_t *sb, float f, protocolversion_t protocol);
+void MSG_WriteVector (sizebuf_t *sb, float *v, protocolversion_t protocol);
+void MSG_WriteAngle (sizebuf_t *sb, float f, protocolversion_t protocol);
extern int msg_readcount;
extern qboolean msg_badread; // set if a read goes beyond end of message
float MSG_ReadCoord13i (void);
float MSG_ReadCoord16i (void);
float MSG_ReadCoord32f (void);
-float MSG_ReadCoord (int protocol);
-void MSG_ReadVector (float *v, int protocol);
-float MSG_ReadAngle (int protocol);
+float MSG_ReadCoord (protocolversion_t protocol);
+void MSG_ReadVector (float *v, protocolversion_t protocol);
+float MSG_ReadAngle (protocolversion_t protocol);
//============================================================================
if (sv.paused || (cl.islocalgame && (key_dest != key_game || key_consoleactive)))
sv.frametime = 0;
- pr_global_struct->frametime = sv.frametime;
-
// set the time and clear the general datagram
SV_ClearDatagram();
*/
void Host_Status_f (void)
{
- const char *protocolname;
client_t *client;
int seconds, minutes, hours = 0, j, players;
void (*print) (const char *fmt, ...);
players++;
print ("host: %s\n", Cvar_VariableString ("hostname"));
print ("version: %s build %s\n", gamename, buildstring);
- switch(sv.protocol)
- {
- case PROTOCOL_QUAKE: protocolname = sv.netquakecompatible ? "QUAKE" : "QUAKEDP";break;
- case PROTOCOL_DARKPLACES1: protocolname = "PROTOCOL_DARKPLACES1";break;
- case PROTOCOL_DARKPLACES2: protocolname = "PROTOCOL_DARKPLACES2";break;
- case PROTOCOL_DARKPLACES3: protocolname = "PROTOCOL_DARKPLACES3";break;
- case PROTOCOL_DARKPLACES4: protocolname = "PROTOCOL_DARKPLACES4";break;
- case PROTOCOL_DARKPLACES5: protocolname = "PROTOCOL_DARKPLACES5";break;
- case PROTOCOL_DARKPLACES6: protocolname = "PROTOCOL_DARKPLACES6";break;
- default: protocolname = "PROTOCOL_UNKNOWN";break;
- }
- print ("protocol: %i (%s)\n", sv.protocol, protocolname);
+ print ("protocol: %i (%s)\n", Protocol_NumberForEnum(sv.protocol), Protocol_NameForEnum(sv.protocol));
print ("map: %s\n", sv.name);
print ("players: %i active (%i max)\n\n", players, svs.maxclients);
for (j = 0, client = svs.clients;j < svs.maxclients;j++, client++)
lhnetsocket_t *mysocket;
lhnetaddress_t peeraddress;
-
+
// this is mostly identical to qsocket_t from quake
// if this time is reached, kick off peer
#define SERVERLIST_ANDMASKCOUNT 5
#define SERVERLIST_ORMASKCOUNT 5
-typedef enum
+typedef enum
{
// SLMO_CONTAINS is the default for strings
// SLMO_GREATEREQUAL is the default for numbers (also used when OP == CONTAINS or NOTCONTAINS
int protocol;
} serverlist_info_t;
-typedef enum
+typedef enum
{
SLIF_CNAME,
SLIF_PING,
typedef struct
{
// used to determine whether this entry should be included into the final view
- qboolean finished;
+ qboolean finished;
// used to calculate ping when update comes in
double querytime;
serverlist_info_t info;
-
+
// legacy stuff
char line1[128];
char line2[128];
extern int serverlist_viewcount;
extern serverlist_entry_t *serverlist_viewlist[SERVERLIST_VIEWLISTSIZE];
-extern int serverlist_cachecount;
+extern int serverlist_cachecount;
extern qboolean serverlist_consoleoutput;
// we should avoid extensive checking on entities already encountered
int areagridmarknumber;
- // PROTOCOL_QUAKE
+ // PROTOCOL_QUAKE, PROTOCOL_QUAKEDP, PROTOCOL_NEHAHRAMOVIE
// baseline values
entity_state_t baseline;
{0,0}//unsigned char unused[2]; // !
};
+// LordHavoc: I own protocol ranges 96, 97, 3500-3599
+
+struct
+{
+ int number;
+ const char *name;
+}
+protocolversioninfo[] =
+{
+ {0, "UNKNOWN"},
+ {15, "QUAKE"},
+ {15, "QUAKEDP"},
+ {250, "NEHAHRAMOVIE"},
+ {96, "DARKPLACES1"},
+ {97, "DARKPLACES2"},
+ {3500, "DARKPLACES3"},
+ {3501, "DARKPLACES4"},
+ {3502, "DARKPLACES5"},
+ {3503, "DARKPLACES6"},
+ {3504, "DARKPLACES7"},
+ {0, NULL}
+};
+
+protocolversion_t Protocol_EnumForName(const char *s)
+{
+ int i;
+ for (i = 1;protocolversioninfo[i].name;i++)
+ if (!strcasecmp(s, protocolversioninfo[i].name))
+ return i;
+ return PROTOCOL_UNKNOWN;
+}
+
+const char *Protocol_NameForEnum(protocolversion_t p)
+{
+ return protocolversioninfo[p].name;
+}
+
+protocolversion_t Protocol_EnumForNumber(int n)
+{
+ int i;
+ for (i = 1;protocolversioninfo[i].name;i++)
+ if (protocolversioninfo[i].number == n)
+ return i;
+ return PROTOCOL_UNKNOWN;
+}
+
+int Protocol_NumberForEnum(protocolversion_t p)
+{
+ return protocolversioninfo[p].number;
+}
+
+void Protocol_Names(char *buffer, size_t buffersize)
+{
+ int i;
+ if (buffersize < 1)
+ return;
+ buffer[0] = 0;
+ for (i = 1;protocolversioninfo[i].name;i++)
+ {
+ if (i > 1)
+ strlcat(buffer, " ", sizeof(buffer));
+ strlcat(buffer, protocolversioninfo[i].name, sizeof(buffer));
+ }
+}
+
// keep track of quake entities because they need to be killed if they get stale
int cl_lastquakeentity = 0;
qbyte cl_isquakeentity[MAX_EDICTS];
bits |= U_GLOWCOLOR;
// if extensions are disabled, clear the relevant update flags
- if (sv.netquakecompatible)
+ if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_NEHAHRAMOVIE)
bits &= 0x7FFF;
+ if (sv.protocol == PROTOCOL_NEHAHRAMOVIE)
+ if (s->alpha != 255 || s->effects & EF_FULLBRIGHT)
+ bits |= U_EXTEND1;
// write the message
if (bits >= 16777216)
if (bits & U_FRAME2) MSG_WriteByte(&buf, s->frame >> 8);
if (bits & U_MODEL2) MSG_WriteByte(&buf, s->modelindex >> 8);
+ // the nasty protocol
+ if ((bits & U_EXTEND1) && sv.protocol == PROTOCOL_NEHAHRAMOVIE)
+ {
+ if (s->effects & EF_FULLBRIGHT)
+ {
+ MSG_WriteFloat(&buf, 2); // QSG protocol version
+ MSG_WriteFloat(&buf, s->alpha <= 0 ? 0 : (s->alpha >= 255 ? 1 : s->alpha * (1.0f / 255.0f))); // alpha
+ MSG_WriteFloat(&buf, 1); // fullbright
+ }
+ else
+ {
+ MSG_WriteFloat(&buf, 1); // QSG protocol version
+ MSG_WriteFloat(&buf, s->alpha <= 0 ? 0 : (s->alpha >= 255 ? 1 : s->alpha * (1.0f / 255.0f))); // alpha
+ }
+ }
+
// if the commit is full, we're done this frame
if (msg->cursize + buf.cursize > msg->maxsize)
{
if (bits & E_ORIGIN3)
MSG_WriteCoord16i(msg, ent->origin[2]);
}
- else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
+ else
{
// LordHavoc: have to write flags first, as they can modify protocol
if (bits & E_FLAGS)
MSG_WriteCoord32f(msg, ent->origin[2]);
}
}
- if ((sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6) && !(ent->flags & RENDER_LOWPRECISION))
+ if ((sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4) && (ent->flags & RENDER_LOWPRECISION))
{
if (bits & E_ANGLE1)
- MSG_WriteAngle16i(msg, ent->angles[0]);
+ MSG_WriteAngle8i(msg, ent->angles[0]);
if (bits & E_ANGLE2)
- MSG_WriteAngle16i(msg, ent->angles[1]);
+ MSG_WriteAngle8i(msg, ent->angles[1]);
if (bits & E_ANGLE3)
- MSG_WriteAngle16i(msg, ent->angles[2]);
+ MSG_WriteAngle8i(msg, ent->angles[2]);
}
else
{
if (bits & E_ANGLE1)
- MSG_WriteAngle8i(msg, ent->angles[0]);
+ MSG_WriteAngle16i(msg, ent->angles[0]);
if (bits & E_ANGLE2)
- MSG_WriteAngle8i(msg, ent->angles[1]);
+ MSG_WriteAngle16i(msg, ent->angles[1]);
if (bits & E_ANGLE3)
- MSG_WriteAngle8i(msg, ent->angles[2]);
+ MSG_WriteAngle16i(msg, ent->angles[2]);
}
if (bits & E_MODEL1)
MSG_WriteByte(msg, ent->modelindex & 0xFF);
if (bits & E_ORIGIN3)
e->origin[2] = MSG_ReadCoord16i();
}
- else if (cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4 || cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6)
+ else
{
if (bits & E_FLAGS)
e->flags = MSG_ReadByte();
e->origin[2] = MSG_ReadCoord32f();
}
}
- else
- Host_Error("EntityState_ReadFields: unknown cl.protocol %i\n", cl.protocol);
- if ((cl.protocol == PROTOCOL_DARKPLACES5 || cl.protocol == PROTOCOL_DARKPLACES6) && !(e->flags & RENDER_LOWPRECISION))
+ if ((cl.protocol == PROTOCOL_DARKPLACES1 || cl.protocol == PROTOCOL_DARKPLACES2 || cl.protocol == PROTOCOL_DARKPLACES3 || cl.protocol == PROTOCOL_DARKPLACES4) && (e->flags & RENDER_LOWPRECISION))
{
if (bits & E_ANGLE1)
- e->angles[0] = MSG_ReadAngle16i();
+ e->angles[0] = MSG_ReadAngle8i();
if (bits & E_ANGLE2)
- e->angles[1] = MSG_ReadAngle16i();
+ e->angles[1] = MSG_ReadAngle8i();
if (bits & E_ANGLE3)
- e->angles[2] = MSG_ReadAngle16i();
+ e->angles[2] = MSG_ReadAngle8i();
}
else
{
if (bits & E_ANGLE1)
- e->angles[0] = MSG_ReadAngle8i();
+ e->angles[0] = MSG_ReadAngle16i();
if (bits & E_ANGLE2)
- e->angles[1] = MSG_ReadAngle8i();
+ e->angles[1] = MSG_ReadAngle16i();
if (bits & E_ANGLE3)
- e->angles[2] = MSG_ReadAngle8i();
+ e->angles[2] = MSG_ReadAngle16i();
}
if (bits & E_MODEL1)
e->modelindex = (e->modelindex & 0xFF00) | (unsigned int) MSG_ReadByte();
for (i = 0;i < LATESTFRAMENUMS-1;i++)
cl.latestframenums[i] = cl.latestframenums[i+1];
cl.latestframenums[LATESTFRAMENUMS-1] = MSG_ReadLong();
+ if (cl.protocol != PROTOCOL_QUAKE && cl.protocol != PROTOCOL_QUAKEDP && cl.protocol != PROTOCOL_NEHAHRAMOVIE && cl.protocol != PROTOCOL_DARKPLACES1 && cl.protocol != PROTOCOL_DARKPLACES2 && cl.protocol != PROTOCOL_DARKPLACES3 && cl.protocol != PROTOCOL_DARKPLACES4 && cl.protocol != PROTOCOL_DARKPLACES5 && cl.protocol != PROTOCOL_DARKPLACES6)
+ cl.servermovesequence = MSG_ReadLong();
// read entity numbers until we find a 0x8000
// (which would be remove world entity, but is actually a terminator)
while ((n = (unsigned short)MSG_ReadShort()) != 0x8000 && !msg_badread)
int entityframe5_prioritychaincounts[E5_PROTOCOL_PRIORITYLEVELS];
unsigned short entityframe5_prioritychains[E5_PROTOCOL_PRIORITYLEVELS][ENTITYFRAME5_MAXSTATES];
-void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats)
+void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats, int movesequence)
{
const entity_state_t *n;
int i, num, l, framenum, packetlognumber, priority;
packetlog->packetnumber = framenum;
packetlog->numstates = 0;
// write stat updates
- if (sv.protocol == PROTOCOL_DARKPLACES6)
+ if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5)
{
for (i = 0;i < MAX_CL_STATS;i++)
{
d->latestframenum = framenum;
MSG_WriteByte(msg, svc_entities);
MSG_WriteLong(msg, framenum);
+ if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5 && sv.protocol != PROTOCOL_DARKPLACES6)
+ MSG_WriteLong(msg, movesequence);
for (priority = E5_PROTOCOL_PRIORITYLEVELS - 1;priority >= 0 && packetlog->numstates < ENTITYFRAME5_MAXSTATES;priority--)
{
for (i = 0;i < entityframe5_prioritychaincounts[priority] && packetlog->numstates < ENTITYFRAME5_MAXSTATES;i++)
#ifndef PROTOCOL_H
#define PROTOCOL_H
-// LordHavoc: I own protocol ranges 96, 97, 3500-3599
+// protocolversion_t is defined in common.h
-// quake or darkplaces extended quake entity protocol
-// (still used by TomazQuake and others)
-#define PROTOCOL_QUAKE 15
-
-// neh_gl entity protocol
-// (failed QSG protocol, used only by nehahra movie)
-#define PROTOCOL_NEHAHRAMOVIE 250
-
-// entityframe protocol
-#define PROTOCOL_DARKPLACES1 96
-#define PROTOCOL_DARKPLACES2 97
-
-// entityframe4 protocol
-#define PROTOCOL_DARKPLACES3 3500
-#define PROTOCOL_DARKPLACES4 3501
-
-// entityframe5 protocol
-#define PROTOCOL_DARKPLACES5 3502
-#define PROTOCOL_DARKPLACES6 3503
+protocolversion_t Protocol_EnumForName(const char *s);
+const char *Protocol_NameForEnum(protocolversion_t p);
+protocolversion_t Protocol_EnumForNumber(int n);
+int Protocol_NumberForEnum(protocolversion_t p);
+void Protocol_Names(char *buffer, size_t buffersize);
// model effects
#define EF_ROCKET 1 // leave a trail
void EntityFrame5_CL_ReadFrame(void);
void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum);
void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum);
-void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats);
+void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats, int movesequence);
extern cvar_t developer_networkentities;
qboolean loadgame;
// one of the PROTOCOL_ values
- int protocol;
- // this disables extensions when using PROTOCOL_QUAKE
- qboolean netquakecompatible;
+ protocolversion_t protocol;
// used for running multiple steps in one frame, etc
double timer;
// communications handle
netconn_t *netconnection;
+ int movesequence;
// movement
usercmd_t cmd;
// intended motion calced from cmd
#include "quakedef.h"
-// select which protocol to host, by name
-// this is named the same as PROTOCOL_DARKPLACES6 for example, minus the PROTOCOL_ prefix
-cvar_t sv_protocolname = {0, "sv_protocolname", "DARKPLACES6"};
+// select which protocol to host, this is fed to Protocol_EnumForName
+cvar_t sv_protocolname = {0, "sv_protocolname", "DARKPLACES7"};
cvar_t sv_ratelimitlocalplayer = {0, "sv_ratelimitlocalplayer", "0"};
cvar_t sv_maxrate = {CVAR_SAVE | CVAR_NOTIFY, "sv_maxrate", "10000"};
if (client->entitydatabase5)
EntityFrame5_FreeDatabase(client->entitydatabase5);
- if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)
- client->entitydatabase = EntityFrame_AllocDatabase(sv_mempool);
- if (sv.protocol == PROTOCOL_DARKPLACES4)
- client->entitydatabase4 = EntityFrame4_AllocDatabase(sv_mempool);
- if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
- client->entitydatabase5 = EntityFrame5_AllocDatabase(sv_mempool);
+ if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE)
+ {
+ if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)
+ client->entitydatabase = EntityFrame_AllocDatabase(sv_mempool);
+ else if (sv.protocol == PROTOCOL_DARKPLACES4)
+ client->entitydatabase4 = EntityFrame4_AllocDatabase(sv_mempool);
+ else
+ client->entitydatabase5 = EntityFrame5_AllocDatabase(sv_mempool);
+ }
SZ_Clear (&client->message);
MSG_WriteByte (&client->message, svc_print);
MSG_WriteString (&client->message,message);
MSG_WriteByte (&client->message, svc_serverinfo);
- MSG_WriteLong (&client->message, sv.protocol);
+ MSG_WriteLong (&client->message, Protocol_NumberForEnum(sv.protocol));
MSG_WriteByte (&client->message, svs.maxclients);
if (!coop.integer && deathmatch.integer)
return;
// always send world submodels, they don't generate much traffic
// except in PROTOCOL_QUAKE where they hog bandwidth like crazy
- else if (!(s->effects & EF_NODEPTHTEST) && (!(isbmodel = (model = sv.models[s->modelindex]) != NULL && model->name[0] == '*') || sv.protocol == PROTOCOL_QUAKE))
+ else if (!(s->effects & EF_NODEPTHTEST) && (!(isbmodel = (model = sv.models[s->modelindex]) != NULL && model->name[0] == '*') || (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE)))
{
Mod_CheckLoaded(model);
// entity has survived every check so far, check if visible
Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d trace\n", client->name, sv_writeentitiestoclient_totalentities, sv_writeentitiestoclient_visibleentities, sv_writeentitiestoclient_culled_pvs + sv_writeentitiestoclient_culled_trace, sv_writeentitiestoclient_culled_pvs, sv_writeentitiestoclient_culled_trace);
if (client->entitydatabase5)
- EntityFrame5_WriteFrame(msg, client->entitydatabase5, numsendstates, sendstates, client - svs.clients + 1, stats);
+ EntityFrame5_WriteFrame(msg, client->entitydatabase5, numsendstates, sendstates, client - svs.clients + 1, stats, client->movesequence);
else if (client->entitydatabase4)
EntityFrame4_WriteFrame(msg, client->entitydatabase4, numsendstates, sendstates);
else if (client->entitydatabase)
{
if (ent->v->punchangle[i])
bits |= (SU_PUNCH1<<i);
- if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
+ if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE)
if (punchvector[i])
bits |= (SU_PUNCHVEC1<<i);
if (ent->v->velocity[i])
//stats[STAT_SECRETS] = pr_global_struct->found_secrets;
//stats[STAT_MONSTERS] = pr_global_struct->killed_monsters;
- if (sv.protocol != PROTOCOL_DARKPLACES6)
+ if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
{
if (stats[STAT_VIEWHEIGHT] != DEFAULT_VIEWHEIGHT) bits |= SU_VIEWHEIGHT;
bits |= SU_ITEMS;
if (stats[STAT_ARMOR]) bits |= SU_ARMOR;
bits |= SU_WEAPON;
// FIXME: which protocols support this? does PROTOCOL_DARKPLACES3 support viewzoom?
- if (sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
+ if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
if (viewzoom != 255)
bits |= SU_VIEWZOOM;
}
{
if (bits & (SU_PUNCH1<<i))
{
- if (sv.protocol == PROTOCOL_QUAKE)
+ if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE)
MSG_WriteChar(msg, ent->v->punchangle[i]);
- else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
+ else
MSG_WriteAngle16i(msg, ent->v->punchangle[i]);
}
- if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
+ if (bits & (SU_PUNCHVEC1<<i))
{
- if (bits & (SU_PUNCHVEC1<<i))
- {
- if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
- MSG_WriteCoord16i(msg, punchvector[i]);
- else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
- MSG_WriteCoord32f(msg, punchvector[i]);
- }
+ if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
+ MSG_WriteCoord16i(msg, punchvector[i]);
+ else
+ MSG_WriteCoord32f(msg, punchvector[i]);
}
if (bits & (SU_VELOCITY1<<i))
{
if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
MSG_WriteChar(msg, ent->v->velocity[i] * (1.0f / 16.0f));
- else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
+ else
MSG_WriteCoord32f(msg, ent->v->velocity[i]);
}
}
if (bits & SU_VIEWZOOM)
MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
}
- else if (sv.protocol != PROTOCOL_DARKPLACES6)
+ else if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
{
if (bits & SU_WEAPONFRAME)
MSG_WriteByte (msg, stats[STAT_WEAPONFRAME]);
MSG_WriteByte (msg, stats[STAT_WEAPON]);
if (bits & SU_VIEWZOOM)
{
- if (sv.protocol == PROTOCOL_DARKPLACES4)
+ if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
MSG_WriteByte (msg, min(stats[STAT_VIEWZOOM], 255));
- else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
+ else
MSG_WriteShort (msg, min(stats[STAT_VIEWZOOM], 65535));
}
}
maxsize = sizeof(sv_sendclientdatagram_buf);
maxsize2 = sizeof(sv_sendclientdatagram_buf);
}
- else if (sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
+ else if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4)
{
- // PROTOCOL_DARKPLACES5 supports packet size limiting of updates
+ // no rate limiting support on older protocols because dp protocols
+ // 1-4 kick the client off if they overflow, and quake protocol shows
+ // less than the full entity set if rate limited
+ maxsize = 1400;
+ maxsize2 = 1400;
+ }
+ else
+ {
+ // PROTOCOL_DARKPLACES5 and later support packet size limiting of updates
maxrate = bound(NET_MINRATE, sv_maxrate.integer, NET_MAXRATE);
if (sv_maxrate.integer != maxrate)
Cvar_SetValueQuick(&sv_maxrate, maxrate);
maxsize = bound(100, rate, 1400);
maxsize2 = 1400;
}
- else
- {
- // no rate limiting support on older protocols because dp protocols
- // 1-4 kick the client off if they overflow, and quake protocol shows
- // less than the full entity set if rate limited
- maxsize = 1400;
- maxsize2 = 1400;
- }
msg.data = sv_sendclientdatagram_buf;
msg.maxsize = maxsize;
*/
int SV_ModelIndex(const char *s, int precachemode)
{
- int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_MODELS);
+ int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE) ? 256 : MAX_MODELS);
char filename[MAX_QPATH];
if (!s || !*s)
return 0;
{
if (precachemode)
{
- if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5))
+ if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5))
{
Con_Printf("SV_ModelIndex(\"%s\"): precache_model can only be done in spawn functions\n", filename);
return 0;
Con_Printf("SV_ModelIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
strlcpy(sv.model_precache[i], filename, sizeof(sv.model_precache[i]));
sv.models[i] = Mod_ForName (sv.model_precache[i], true, false, false);
- if (sv.protocol == PROTOCOL_DARKPLACES6 && sv.state != ss_loading)
+ if (sv.state != ss_loading)
{
MSG_WriteByte(&sv.reliable_datagram, svc_precache);
MSG_WriteShort(&sv.reliable_datagram, i);
*/
int SV_SoundIndex(const char *s, int precachemode)
{
- int i, limit = (sv.protocol == PROTOCOL_QUAKE ? 256 : MAX_SOUNDS);
+ int i, limit = ((sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE) ? 256 : MAX_SOUNDS);
char filename[MAX_QPATH];
if (!s || !*s)
return 0;
{
if (precachemode)
{
- if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5))
+ if (sv.state != ss_loading && (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5))
{
Con_Printf("SV_SoundIndex(\"%s\"): precache_sound can only be done in spawn functions\n", filename);
return 0;
if (precachemode == 1)
Con_Printf("SV_SoundIndex(\"%s\"): not precached (fix your code), precaching anyway\n", filename);
strlcpy(sv.sound_precache[i], filename, sizeof(sv.sound_precache[i]));
- if (sv.protocol == PROTOCOL_DARKPLACES6 && sv.state != ss_loading)
+ if (sv.state != ss_loading)
{
MSG_WriteByte(&sv.reliable_datagram, svc_precache);
MSG_WriteShort(&sv.reliable_datagram, i + 32768);
strlcpy (sv.name, server, sizeof (sv.name));
- sv.netquakecompatible = false;
- if (!strcasecmp(sv_protocolname.string, "QUAKE"))
+ sv.protocol = Protocol_EnumForName(sv_protocolname.string);
+ if (sv.protocol == PROTOCOL_UNKNOWN)
{
+ char buffer[1024];
+ Protocol_Names(buffer, sizeof(buffer));
+ Con_Printf("Unknown sv_protocolname \"%s\", valid values are:\n%s\n", sv_protocolname.string, buffer);
sv.protocol = PROTOCOL_QUAKE;
- sv.netquakecompatible = true;
- }
- else if (!strcasecmp(sv_protocolname.string, "QUAKEDP"))
- sv.protocol = PROTOCOL_QUAKE;
- else if (!strcasecmp(sv_protocolname.string, "DARKPLACES1"))
- sv.protocol = PROTOCOL_DARKPLACES1;
- else if (!strcasecmp(sv_protocolname.string, "DARKPLACES2"))
- sv.protocol = PROTOCOL_DARKPLACES2;
- else if (!strcasecmp(sv_protocolname.string, "DARKPLACES3"))
- sv.protocol = PROTOCOL_DARKPLACES3;
- else if (!strcasecmp(sv_protocolname.string, "DARKPLACES4"))
- sv.protocol = PROTOCOL_DARKPLACES4;
- else if (!strcasecmp(sv_protocolname.string, "DARKPLACES5"))
- sv.protocol = PROTOCOL_DARKPLACES5;
- else if (!strcasecmp(sv_protocolname.string, "DARKPLACES6"))
- sv.protocol = PROTOCOL_DARKPLACES6;
- else
- {
- sv.protocol = PROTOCOL_DARKPLACES6;
- Con_Printf("Unknown sv_protocolname \"%s\", valid values are QUAKE, QUAKEDP, DARKPLACES1, DARKPLACES2, DARKPLACES3, DARKPLACES4, DARKPLACES5, DARKPLACES6, falling back to DARKPLACES6 protocol\n", sv_protocolname.string);
}
// load progs to get entity field count
// run two frames to allow everything to settle
for (i = 0;i < 2;i++)
{
- sv.frametime = pr_global_struct->frametime = host_frametime = 0.1;
+ sv.frametime = host_frametime = 0.1;
SV_Physics ();
}
Mod_PurgeUnused();
// create a baseline for more efficient communications
- if (sv.protocol == PROTOCOL_QUAKE)
+ if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE)
SV_CreateBaseline ();
// send serverinfo to all connected clients
//============================================================================
+void SV_Physics_Entity (edict_t *ent, qboolean runmove)
+{
+ int i = ent - sv.edicts;
+ if (i >= 1 && i <= svs.maxclients)
+ {
+ // apply the latest accepted move to the entity fields
+ SV_ApplyClientMove();
+ // make sure the velocity is sane (not a NaN)
+ SV_CheckVelocity(ent);
+ // LordHavoc: QuakeC replacement for SV_ClientThink (player movement)
+ if (SV_PlayerPhysicsQC)
+ {
+ pr_global_struct->time = sv.time;
+ pr_global_struct->self = EDICT_TO_PROG(ent);
+ PR_ExecuteProgram ((func_t)(SV_PlayerPhysicsQC - pr_functions), "QC function SV_PlayerPhysics is missing");
+ }
+ else
+ SV_ClientThink ();
+ // make sure the velocity is sane (not a NaN)
+ SV_CheckVelocity(ent);
+ // LordHavoc: a hack to ensure that the (rather silly) id1 quakec
+ // player_run/player_stand1 does not horribly malfunction if the
+ // velocity becomes a number that is both == 0 and != 0
+ // (sounds to me like NaN but to be absolutely safe...)
+ if (DotProduct(ent->v->velocity, ent->v->velocity) < 0.0001)
+ VectorClear(ent->v->velocity);
+ // call standard client pre-think
+ pr_global_struct->time = sv.time;
+ pr_global_struct->self = EDICT_TO_PROG(ent);
+ PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
+ SV_CheckVelocity (ent);
+ }
+
+ // LordHavoc: merged client and normal entity physics
+ switch ((int) ent->v->movetype)
+ {
+ case MOVETYPE_PUSH:
+ case MOVETYPE_FAKEPUSH:
+ SV_Physics_Pusher (ent);
+ break;
+ case MOVETYPE_NONE:
+ // LordHavoc: manually inlined the thinktime check here because MOVETYPE_NONE is used on so many objects
+ if (ent->v->nextthink > 0 && ent->v->nextthink <= sv.time + sv.frametime)
+ SV_RunThink (ent);
+ break;
+ case MOVETYPE_FOLLOW:
+ SV_Physics_Follow (ent);
+ break;
+ case MOVETYPE_NOCLIP:
+ if (SV_RunThink(ent))
+ {
+ SV_CheckWater(ent);
+ VectorMA(ent->v->origin, sv.frametime, ent->v->velocity, ent->v->origin);
+ VectorMA(ent->v->angles, sv.frametime, ent->v->avelocity, ent->v->angles);
+ }
+ // relink normal entities here, players always get relinked so don't relink twice
+ if (!(i > 0 && i <= svs.maxclients))
+ SV_LinkEdict(ent, false);
+ break;
+ case MOVETYPE_STEP:
+ SV_Physics_Step (ent);
+ break;
+ case MOVETYPE_WALK:
+ if (SV_RunThink (ent))
+ {
+ if (!SV_CheckWater (ent) && ! ((int)ent->v->flags & FL_WATERJUMP) )
+ SV_AddGravity (ent);
+ SV_CheckStuck (ent);
+ SV_WalkMove (ent);
+ // relink normal entities here, players always get relinked so don't relink twice
+ if (!(i > 0 && i <= svs.maxclients))
+ SV_LinkEdict (ent, true);
+ }
+ break;
+ case MOVETYPE_TOSS:
+ case MOVETYPE_BOUNCE:
+ case MOVETYPE_BOUNCEMISSILE:
+ case MOVETYPE_FLYMISSILE:
+ // regular thinking
+ if (SV_RunThink (ent) && runmove)
+ SV_Physics_Toss (ent);
+ break;
+ case MOVETYPE_FLY:
+ if (SV_RunThink (ent) && runmove)
+ {
+ if (i > 0 && i <= svs.maxclients)
+ {
+ SV_CheckWater (ent);
+ SV_WalkMove (ent);
+ }
+ else
+ SV_Physics_Toss (ent);
+ }
+ break;
+ default:
+ Host_Error ("SV_Physics: bad movetype %i", (int)ent->v->movetype);
+ break;
+ }
+
+ if (i >= 1 && i <= svs.maxclients)
+ {
+ SV_CheckVelocity (ent);
+
+ // call standard player post-think
+ SV_LinkEdict (ent, true);
+
+ SV_CheckVelocity (ent);
+
+ pr_global_struct->time = sv.time;
+ pr_global_struct->self = EDICT_TO_PROG(ent);
+ PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
+ }
+}
+
+
/*
================
SV_Physics
pr_global_struct->self = EDICT_TO_PROG(sv.edicts);
pr_global_struct->other = EDICT_TO_PROG(sv.edicts);
pr_global_struct->time = sv.time;
+ pr_global_struct->frametime = sv.frametime;
PR_ExecuteProgram (pr_global_struct->StartFrame, "QC function StartFrame is missing");
newnum_edicts = 0;
continue;
}
// connected slot
- // apply the latest accepted move to the entity fields
- SV_ApplyClientMove();
- // make sure the velocity is sane (not a NaN)
- SV_CheckVelocity(ent);
- // LordHavoc: QuakeC replacement for SV_ClientThink (player movement)
- if (SV_PlayerPhysicsQC)
- {
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram ((func_t)(SV_PlayerPhysicsQC - pr_functions), "QC function SV_PlayerPhysics is missing");
- }
- else
- SV_ClientThink ();
- // make sure the velocity is sane (not a NaN)
- SV_CheckVelocity(ent);
- // LordHavoc: a hack to ensure that the (rather silly) id1 quakec
- // player_run/player_stand1 does not horribly malfunction if the
- // velocity becomes a number that is both == 0 and != 0
- // (sounds to me like NaN but to be absolutely safe...)
- if (DotProduct(ent->v->velocity, ent->v->velocity) < 0.0001)
- VectorClear(ent->v->velocity);
- // call standard client pre-think
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing");
- SV_CheckVelocity (ent);
+ if (host_client->movesequence)
+ continue; // return if running asynchronously
}
else if (sv_freezenonclients.integer)
continue;
- // LordHavoc: merged client and normal entity physics
- switch ((int) ent->v->movetype)
- {
- case MOVETYPE_PUSH:
- case MOVETYPE_FAKEPUSH:
- SV_Physics_Pusher (ent);
- break;
- case MOVETYPE_NONE:
- // LordHavoc: manually inlined the thinktime check here because MOVETYPE_NONE is used on so many objects
- if (ent->v->nextthink > 0 && ent->v->nextthink <= sv.time + sv.frametime)
- SV_RunThink (ent);
- break;
- case MOVETYPE_FOLLOW:
- SV_Physics_Follow (ent);
- break;
- case MOVETYPE_NOCLIP:
- if (SV_RunThink(ent))
- {
- SV_CheckWater(ent);
- VectorMA(ent->v->origin, sv.frametime, ent->v->velocity, ent->v->origin);
- VectorMA(ent->v->angles, sv.frametime, ent->v->avelocity, ent->v->angles);
- }
- // relink normal entities here, players always get relinked so don't relink twice
- if (!(i > 0 && i <= svs.maxclients))
- SV_LinkEdict(ent, false);
- break;
- case MOVETYPE_STEP:
- SV_Physics_Step (ent);
- break;
- case MOVETYPE_WALK:
- if (SV_RunThink (ent))
- {
- if (!SV_CheckWater (ent) && ! ((int)ent->v->flags & FL_WATERJUMP) )
- SV_AddGravity (ent);
- SV_CheckStuck (ent);
- SV_WalkMove (ent);
- // relink normal entities here, players always get relinked so don't relink twice
- if (!(i > 0 && i <= svs.maxclients))
- SV_LinkEdict (ent, true);
- }
- break;
- case MOVETYPE_TOSS:
- case MOVETYPE_BOUNCE:
- case MOVETYPE_BOUNCEMISSILE:
- case MOVETYPE_FLYMISSILE:
- // regular thinking
- if (SV_RunThink (ent) && runmove[i])
- SV_Physics_Toss (ent);
- break;
- case MOVETYPE_FLY:
- if (SV_RunThink (ent) && runmove[i])
- {
- if (i > 0 && i <= svs.maxclients)
- {
- SV_CheckWater (ent);
- SV_WalkMove (ent);
- }
- else
- SV_Physics_Toss (ent);
- }
- break;
- default:
- Host_Error ("SV_Physics: bad movetype %i", (int)ent->v->movetype);
- break;
- }
-
- if (i >= 1 && i <= svs.maxclients)
- {
- SV_CheckVelocity (ent);
-
- // call standard player post-think
- SV_LinkEdict (ent, true);
-
- SV_CheckVelocity (ent);
-
- pr_global_struct->time = sv.time;
- pr_global_struct->self = EDICT_TO_PROG(ent);
- PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing");
- }
+ SV_Physics_Entity(ent, runmove[i]);
}
if (pr_global_struct->force_retouch > 0)
SV_ReadClientMove
===================
*/
-extern cvar_t cl_movement_latency;
+extern void SV_Physics_Entity (edict_t *ent, qboolean runmove);
void SV_ReadClientMove (void)
{
int i;
+ double oldmovetime;
usercmd_t *move = &host_client->cmd;
+ oldmovetime = move->time;
memset(move, 0, sizeof(usercmd_t));
if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
// read ping time
+ if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5 && sv.protocol != PROTOCOL_DARKPLACES6)
+ move->sequence = MSG_ReadLong ();
move->time = MSG_ReadFloat ();
if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
move->receivetime = sv.time;
// read current angles
for (i = 0;i < 3;i++)
{
- if (sv.protocol == PROTOCOL_QUAKE)
+ if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE)
move->viewangles[i] = MSG_ReadAngle8i();
+ else if (sv.protocol == PROTOCOL_DARKPLACES1)
+ move->viewangles[i] = MSG_ReadAngle16i();
else if (sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3)
move->viewangles[i] = MSG_ReadAngle32f();
- else if (sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5 || sv.protocol == PROTOCOL_DARKPLACES6)
+ else
move->viewangles[i] = MSG_ReadAngle16i();
}
if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
// read buttons
- if (sv.protocol == PROTOCOL_DARKPLACES6)
- move->buttons = MSG_ReadLong ();
- else
+ if (sv.protocol == PROTOCOL_QUAKE || sv.protocol == PROTOCOL_QUAKEDP || sv.protocol == PROTOCOL_NEHAHRAMOVIE || sv.protocol == PROTOCOL_DARKPLACES1 || sv.protocol == PROTOCOL_DARKPLACES2 || sv.protocol == PROTOCOL_DARKPLACES3 || sv.protocol == PROTOCOL_DARKPLACES4 || sv.protocol == PROTOCOL_DARKPLACES5)
move->buttons = MSG_ReadByte ();
+ else
+ move->buttons = MSG_ReadLong ();
if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
// read impulse
if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
// PRYDON_CLIENTCURSOR
- if (sv.protocol == PROTOCOL_DARKPLACES6)
+ if (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5)
{
// 30 bytes
move->cursor_screen[0] = MSG_ReadShort() * (1.0f / 32767.0f);
move->cursor_entitynumber = 0;
if (msg_badread) Con_Printf("SV_ReadClientMessage: badread at %s:%i\n", __FILE__, __LINE__);
}
+
+ if (!host_client->spawned)
+ memset(move, 0, sizeof(*move));
+ else
+ {
+ host_client->movesequence = move->sequence;
+ if (host_client->movesequence)
+ {
+ double frametime = move->time - oldmovetime;
+ double oldframetime = pr_global_struct->frametime;
+ if (frametime > 0.1)
+ frametime = 0.1;
+ pr_global_struct->frametime = frametime;
+ SV_Physics_Entity(host_client->edict, true);
+ pr_global_struct->frametime = oldframetime;
+ }
+ }
}
void SV_ApplyClientMove (void)