From: lordhavoc Date: Mon, 18 Feb 2002 06:35:09 +0000 (+0000) Subject: new entity protocol, GREATLY improved over quake, massive net traffic reduction X-Git-Tag: RELEASE_0_2_0_RC1~636 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=eb3d71b9feaefca24fe80b9970eb11d07fd295b5 new entity protocol, GREATLY improved over quake, massive net traffic reduction git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1534 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/chase.c b/chase.c index 13c9aa5b..1a9da003 100644 --- a/chase.c +++ b/chase.c @@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" cvar_t chase_back = {CVAR_SAVE, "chase_back", "48"}; -cvar_t chase_up = {CVAR_SAVE, "chase_up", "48"}; +cvar_t chase_up = {CVAR_SAVE, "chase_up", "24"}; cvar_t chase_active = {CVAR_SAVE, "chase_active", "0"}; void Chase_Init (void) diff --git a/cl_input.c b/cl_input.c index 481f843d..11975ce4 100644 --- a/cl_input.c +++ b/cl_input.c @@ -392,7 +392,7 @@ void CL_SendMove (usercmd_t *cmd) for (i=0 ; i<3 ; i++) MSG_WriteAngle (&buf, cl.viewangles[i]); } - + MSG_WriteShort (&buf, forwardmove); MSG_WriteShort (&buf, sidemove); MSG_WriteShort (&buf, upmove); @@ -402,11 +402,11 @@ void CL_SendMove (usercmd_t *cmd) // send button bits // bits = 0; - + if ( in_attack.state & 3 ) bits |= 1; in_attack.state &= ~2; - + if (in_jump.state & 3) bits |= 2; in_jump.state &= ~2; @@ -417,12 +417,20 @@ void CL_SendMove (usercmd_t *cmd) if (in_button6.state & 3) bits |= 32;in_button6.state &= ~2; if (in_button7.state & 3) bits |= 64;in_button7.state &= ~2; if (in_button8.state & 3) bits |= 128;in_button8.state &= ~2; - + MSG_WriteByte (&buf, bits); MSG_WriteByte (&buf, in_impulse); in_impulse = 0; + // LordHavoc: should we ack this on receipt instead? would waste net bandwidth though + i = EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase); + if (i > 0) + { + MSG_WriteByte (&buf, clc_ackentities); + MSG_WriteLong (&buf, i); + } + // // deliver the message // diff --git a/cl_main.c b/cl_main.c index c2f433c6..8eab4358 100644 --- a/cl_main.c +++ b/cl_main.c @@ -287,44 +287,24 @@ should be put at. */ static float CL_LerpPoint (void) { - float f, frac; + float f; - f = cl.mtime[0] - cl.mtime[1]; + // dropped packet, or start of demo + if (cl.mtime[1] < cl.mtime[0] - 0.1) + cl.mtime[1] = cl.mtime[0] - 0.1; + + cl.time = bound(cl.mtime[1], cl.time, cl.mtime[0]); // LordHavoc: lerp in listen games as the server is being capped below the client (usually) + f = cl.mtime[0] - cl.mtime[1]; if (!f || cl_nolerp.integer || cls.timedemo || (sv.active && svs.maxclients == 1)) { cl.time = cl.mtime[0]; return 1; } - if (f > 0.1) - { // dropped packet, or start of demo - cl.mtime[1] = cl.mtime[0] - 0.1; - f = 0.1; - } - frac = (cl.time - cl.mtime[1]) / f; -// Con_Printf ("frac: %f\n",frac); - if (frac < 0) - { - if (frac < -0.01) - { - cl.time = cl.mtime[1]; -// Con_Printf ("low frac\n"); - } - frac = 0; - } - else if (frac > 1) - { - if (frac > 1.01) - { - cl.time = cl.mtime[0]; -// Con_Printf ("high frac\n"); - } - frac = 1; - } - - return frac; + f = (cl.time - cl.mtime[1]) / f; + return bound(0, f, 1); } static void CL_RelinkStaticEntities(void) @@ -355,8 +335,6 @@ static void CL_RelinkNetworkEntities() else bobjoffset = 0; - CL_RelinkStaticEntities(); - // start on the entity after the world for (i = 1, ent = cl_entities + 1;i < MAX_EDICTS /*cl.num_entities*/;i++, ent++) { @@ -648,13 +626,22 @@ static void CL_RelinkNetworkEntities() } } -static void CL_LerpPlayerVelocity (void) +void CL_LerpPlayerEye(float frac) { - int i; - float frac, d; + if (cl.entitydatabase.numframes) + { + cl.viewentorigin[0] = cl.viewentoriginold[0] + frac * (cl.viewentoriginnew[0] - cl.viewentoriginold[0]); + cl.viewentorigin[1] = cl.viewentoriginold[1] + frac * (cl.viewentoriginnew[1] - cl.viewentoriginold[1]); + cl.viewentorigin[2] = cl.viewentoriginold[2] + frac * (cl.viewentoriginnew[2] - cl.viewentoriginold[2]); + } + else + VectorCopy (cl_entities[cl.viewentity].render.origin, cl.viewentorigin); +} - // fraction from previous network update to current - frac = CL_LerpPoint (); +static void CL_LerpPlayerVelocity (float frac) +{ + int i; + float d; for (i = 0;i < 3;i++) cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); @@ -751,13 +738,21 @@ static void CL_RelinkEffects() void CL_RelinkEntities (void) { + float frac; + + // fraction from previous network update to current + frac = CL_LerpPoint (); + CL_DecayLights (); - CL_LerpPlayerVelocity(); + CL_RelinkStaticEntities(); CL_RelinkNetworkEntities(); TraceLine_ScanForBModels(); CL_RelinkEffects(); CL_MoveParticles(); CL_UpdateTEnts(); + + CL_LerpPlayerEye(frac); + CL_LerpPlayerVelocity(frac); } diff --git a/cl_parse.c b/cl_parse.c index 4719d726..aac1a732 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -48,7 +48,7 @@ char *svc_strings[128] = "svc_updatecolors", // [byte] [byte] "svc_particle", // [vec3] "svc_damage", // [byte] impact [byte] blood [vec3] from - + "svc_spawnstatic", "OBSOLETE svc_spawnbinary", "svc_spawnbaseline", @@ -99,7 +99,7 @@ void CL_Parse_Init(void) } qboolean Nehahrademcompatibility; // LordHavoc: to allow playback of the early Nehahra movie segments -qboolean dpprotocol; // LordHavoc: whether or not the current network stream is the enhanced DarkPlaces protocol +int dpprotocol; // LordHavoc: version of network protocol, or 0 if not DarkPlaces /* =============== @@ -360,9 +360,9 @@ void CL_ParseServerInfo (void) // parse protocol version number i = MSG_ReadLong (); - if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION && i != 250) + if (i != PROTOCOL_VERSION && i != DPPROTOCOL_VERSION1 && i != DPPROTOCOL_VERSION2 && i != 250) { - Con_Printf ("Server returned version %i, not %i or %i", i, DPPROTOCOL_VERSION, PROTOCOL_VERSION); + Con_Printf ("Server is protocol %i, not %i, %i or %i", i, DPPROTOCOL_VERSION1, DPPROTOCOL_VERSION2, PROTOCOL_VERSION); return; } Nehahrademcompatibility = false; @@ -370,7 +370,9 @@ void CL_ParseServerInfo (void) Nehahrademcompatibility = true; if (cls.demoplayback && demo_nehahra.integer) Nehahrademcompatibility = true; - dpprotocol = i == DPPROTOCOL_VERSION; + dpprotocol = i; + if (dpprotocol != DPPROTOCOL_VERSION1 && dpprotocol != DPPROTOCOL_VERSION2) + dpprotocol = 0; // parse maxclients cl.maxclients = MSG_ReadByte (); @@ -533,12 +535,6 @@ void CL_ParseUpdate (int bits) entity_t *ent; entity_state_t new; - if (cls.signon == SIGNONS - 1) - { // first update is the final signon stage - cls.signon = SIGNONS; - CL_SignonReply (); - } - if (bits & U_MOREBITS) bits |= (MSG_ReadByte()<<8); if ((bits & U_EXTEND1) && (!Nehahrademcompatibility)) @@ -660,6 +656,27 @@ void CL_ParseUpdate (int bits) } } +void CL_ReadEntityFrame(void) +{ + entity_t *ent; + entity_state_t *s; + entity_frame_t entityframe; + int i; + EntityFrame_Read(&cl.entitydatabase); + EntityFrame_FetchFrame(&cl.entitydatabase, EntityFrame_MostRecentlyRecievedFrameNum(&cl.entitydatabase), &entityframe); + for (i = 0;i < entityframe.numentities;i++) + { + s = &entityframe.entitydata[i]; + entkill[s->number] = 0; + ent = &cl_entities[s->number]; + memcpy(&ent->state_previous, &ent->state_current, sizeof(*s)); + memcpy(&ent->state_current, s, sizeof(*s)); + ent->state_current.time = cl.mtime[0]; + } + VectorCopy(cl.viewentoriginnew, cl.viewentoriginold); + VectorCopy(entityframe.eye, cl.viewentoriginnew); +} + char *bitprofilenames[32] = { "U_MOREBITS", @@ -801,7 +818,7 @@ void CL_ParseClientdata (int bits) else cl.punchangle[i] = 0; if (bits & (SU_PUNCHVEC1<= MAX_LIGHTSTYLES) @@ -1115,7 +1139,7 @@ void CL_ParseServerMessage (void) if (i >= cl.maxclients) Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD"); cl.scores[i].frags = MSG_ReadShort (); - break; + break; case svc_updatecolors: i = MSG_ReadByte (); @@ -1123,7 +1147,7 @@ void CL_ParseServerMessage (void) Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD"); cl.scores[i].colors = MSG_ReadByte (); break; - + case svc_particle: CL_ParseParticleEffect (); break; @@ -1163,7 +1187,7 @@ void CL_ParseServerMessage (void) else CDAudio_Resume (); break; - + case svc_signonnum: i = MSG_ReadByte (); if (i <= cls.signon) @@ -1221,7 +1245,7 @@ void CL_ParseServerMessage (void) cl.intermission = 3; cl.completed_time = cl.time; // vid.recalc_refdef = true; // go to full screen - SCR_CenterPrint (MSG_ReadString ()); + SCR_CenterPrint (MSG_ReadString ()); break; case svc_sellscreen: @@ -1255,6 +1279,14 @@ void CL_ParseServerMessage (void) CL_CGVM_ParseNetwork(cgamenetbuffer, length); } break; + case svc_entities: + if (cls.signon == SIGNONS - 1) + { // first update is the final signon stage + cls.signon = SIGNONS; + CL_SignonReply (); + } + CL_ReadEntityFrame(); + break; } } diff --git a/client.h b/client.h index 5e2831d5..afc49452 100644 --- a/client.h +++ b/client.h @@ -274,6 +274,12 @@ typedef struct // frag scoreboard scoreboard_t *scores; // [cl.maxclients] + + vec3_t viewentorigin; + + // entity database stuff + vec3_t viewentoriginold, viewentoriginnew; + entity_database_t entitydatabase; } client_state_t; diff --git a/common.c b/common.c index 404d73ef..4468bba6 100644 --- a/common.c +++ b/common.c @@ -549,19 +549,26 @@ void MSG_WriteString (sizebuf_t *sb, char *s) SZ_Write (sb, s, strlen(s)+1); } -// used by server (always dpprotocol) -// moved to common.h as #define -/* -void MSG_WriteFloatCoord (sizebuf_t *sb, float f) +// used by server (always latest dpprotocol) +void MSG_WriteDPCoord (sizebuf_t *sb, float f) { - MSG_WriteFloat(sb, f); + if (f >= 0) + MSG_WriteShort (sb, (int)(f + 0.5f)); + else + MSG_WriteShort (sb, (int)(f - 0.5f)); } -*/ // used by client void MSG_WriteCoord (sizebuf_t *sb, float f) { - if (dpprotocol) + if (dpprotocol == DPPROTOCOL_VERSION2) + { + if (f >= 0) + MSG_WriteShort (sb, (int)(f + 0.5f)); + else + MSG_WriteShort (sb, (int)(f - 0.5f)); + } + else if (dpprotocol == DPPROTOCOL_VERSION1) MSG_WriteFloat(sb, f); else { @@ -606,7 +613,7 @@ void MSG_BeginReading (void) int MSG_ReadChar (void) { int c; - + // LordHavoc: minor optimization if (msg_readcount >= net_message.cursize) // if (msg_readcount+1 > net_message.cursize) @@ -614,7 +621,7 @@ int MSG_ReadChar (void) msg_badread = true; return -1; } - + c = (signed char)net_message.data[msg_readcount]; msg_readcount++; @@ -624,7 +631,7 @@ int MSG_ReadChar (void) int MSG_ReadByte (void) { int c; - + // LordHavoc: minor optimization if (msg_readcount >= net_message.cursize) // if (msg_readcount+1 > net_message.cursize) @@ -635,7 +642,7 @@ int MSG_ReadByte (void) c = (unsigned char)net_message.data[msg_readcount]; msg_readcount++; - + return c; } */ @@ -649,19 +656,19 @@ int MSG_ReadShort (void) msg_badread = true; return -1; } - + c = (short)(net_message.data[msg_readcount] + (net_message.data[msg_readcount+1]<<8)); - + msg_readcount += 2; - + return c; } int MSG_ReadLong (void) { int c; - + if (msg_readcount+4 > net_message.cursize) { msg_badread = true; @@ -672,9 +679,9 @@ int MSG_ReadLong (void) + (net_message.data[msg_readcount+1]<<8) + (net_message.data[msg_readcount+2]<<16) + (net_message.data[msg_readcount+3]<<24); - + msg_readcount += 4; - + return c; } @@ -686,23 +693,23 @@ float MSG_ReadFloat (void) float f; int l; } dat; - + dat.b[0] = net_message.data[msg_readcount]; dat.b[1] = net_message.data[msg_readcount+1]; dat.b[2] = net_message.data[msg_readcount+2]; dat.b[3] = net_message.data[msg_readcount+3]; msg_readcount += 4; - + dat.l = LittleLong (dat.l); - return dat.f; + return dat.f; } char *MSG_ReadString (void) { static char string[2048]; int l,c; - + l = 0; do { @@ -712,25 +719,24 @@ char *MSG_ReadString (void) string[l] = c; l++; } while (l < sizeof(string)-1); - + string[l] = 0; - + return string; } -// used by server (always dpprotocol) -// moved to common.h as #define -/* -float MSG_ReadFloatCoord (void) +// used by server (always latest dpprotocol) +float MSG_ReadDPCoord (void) { - return MSG_ReadFloat(); + return (signed short) MSG_ReadShort(); } -*/ // used by client float MSG_ReadCoord (void) { - if (dpprotocol) + if (dpprotocol == DPPROTOCOL_VERSION2) + return (signed short) MSG_ReadShort(); + else if (dpprotocol == DPPROTOCOL_VERSION1) return MSG_ReadFloat(); else return MSG_ReadShort() * (1.0f/8.0f); diff --git a/common.h b/common.h index 7d084f47..85aba74d 100644 --- a/common.h +++ b/common.h @@ -93,8 +93,7 @@ void MSG_WriteString (sizebuf_t *sb, char *s); void MSG_WriteCoord (sizebuf_t *sb, float f); void MSG_WriteAngle (sizebuf_t *sb, float f); void MSG_WritePreciseAngle (sizebuf_t *sb, float f); - -#define MSG_WriteFloatCoord MSG_WriteFloat +void MSG_WriteDPCoord (sizebuf_t *sb, float f); extern int msg_readcount; extern qboolean msg_badread; // set if a read goes beyond end of message @@ -115,14 +114,14 @@ char *MSG_ReadString (void); float MSG_ReadCoord (void); //float MSG_ReadAngle (void); -#define MSG_ReadFloatCoord MSG_ReadFloat +float MSG_ReadDPCoord (void); #define MSG_ReadAngle() (MSG_ReadByte() * (360.0f / 256.0f)) #define MSG_ReadPreciseAngle() (MSG_ReadShort() * (360.0f / 65536.0f)) #define MSG_ReadVector(v) {(v)[0] = MSG_ReadCoord();(v)[1] = MSG_ReadCoord();(v)[2] = MSG_ReadCoord();} -extern qboolean dpprotocol; +extern int dpprotocol; //============================================================================ diff --git a/pr_cmds.c b/pr_cmds.c index 9bafca0b..1665e497 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -665,7 +665,7 @@ void PF_ambientsound (void) MSG_WriteByte (&sv.signon, svc_spawnstaticsound); for (i=0 ; i<3 ; i++) - MSG_WriteFloatCoord(&sv.signon, pos[i]); + MSG_WriteDPCoord(&sv.signon, pos[i]); if (large) MSG_WriteShort (&sv.signon, soundnum); @@ -1813,7 +1813,7 @@ void PF_WriteAngle (void) void PF_WriteCoord (void) { - MSG_WriteFloatCoord (WriteDest(), G_FLOAT(OFS_PARM1)); + MSG_WriteDPCoord (WriteDest(), G_FLOAT(OFS_PARM1)); } void PF_WriteString (void) @@ -1859,7 +1859,7 @@ void PF_makestatic (void) MSG_WriteByte (&sv.signon, ent->v.skin); for (i=0 ; i<3 ; i++) { - MSG_WriteFloatCoord(&sv.signon, ent->v.origin[i]); + MSG_WriteDPCoord(&sv.signon, ent->v.origin[i]); MSG_WriteAngle(&sv.signon, ent->v.angles[i]); } @@ -2163,9 +2163,9 @@ void PF_te_blood (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_BLOOD); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // velocity MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127)); MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127)); @@ -2181,15 +2181,15 @@ void PF_te_bloodshower (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_BLOODSHOWER); // min - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // max - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); // speed - MSG_WriteFloatCoord(&sv.datagram, G_FLOAT(OFS_PARM2)); + MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM2)); // count MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); } @@ -2199,9 +2199,9 @@ void PF_te_explosionrgb (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSIONRGB); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // color MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[0] * 255), 255)); MSG_WriteByte(&sv.datagram, bound(0, (int) (G_VECTOR(OFS_PARM1)[1] * 255), 255)); @@ -2215,17 +2215,17 @@ void PF_te_particlecube (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PARTICLECUBE); // min - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // max - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); // velocity - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); // count MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); // color @@ -2233,7 +2233,7 @@ void PF_te_particlecube (void) // gravity true/false MSG_WriteByte(&sv.datagram, ((int) G_FLOAT(OFS_PARM5)) != 0); // randomvel - MSG_WriteFloatCoord(&sv.datagram, G_FLOAT(OFS_PARM6)); + MSG_WriteDPCoord(&sv.datagram, G_FLOAT(OFS_PARM6)); } void PF_te_particlerain (void) @@ -2243,17 +2243,17 @@ void PF_te_particlerain (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PARTICLERAIN); // min - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // max - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); // velocity - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); // count MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); // color @@ -2267,17 +2267,17 @@ void PF_te_particlesnow (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PARTICLESNOW); // min - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // max - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); // velocity - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); // count MSG_WriteShort(&sv.datagram, bound(0, G_FLOAT(OFS_PARM3), 65535)); // color @@ -2291,9 +2291,9 @@ void PF_te_spark (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPARK); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // velocity MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[0], 127)); MSG_WriteByte(&sv.datagram, bound(-128, (int) G_VECTOR(OFS_PARM1)[1], 127)); @@ -2307,9 +2307,9 @@ void PF_te_gunshotquad (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_GUNSHOTQUAD); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_spikequad (void) @@ -2317,9 +2317,9 @@ void PF_te_spikequad (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPIKEQUAD); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_superspikequad (void) @@ -2327,9 +2327,9 @@ void PF_te_superspikequad (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SUPERSPIKEQUAD); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_explosionquad (void) @@ -2337,9 +2337,9 @@ void PF_te_explosionquad (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSIONQUAD); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_smallflash (void) @@ -2347,9 +2347,9 @@ void PF_te_smallflash (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SMALLFLASH); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_customflash (void) @@ -2359,9 +2359,9 @@ void PF_te_customflash (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_CUSTOMFLASH); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // radius MSG_WriteByte(&sv.datagram, bound(0, G_FLOAT(OFS_PARM1) / 8 - 1, 255)); // lifetime @@ -2377,9 +2377,9 @@ void PF_te_gunshot (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_GUNSHOT); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_spike (void) @@ -2387,9 +2387,9 @@ void PF_te_spike (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SPIKE); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_superspike (void) @@ -2397,9 +2397,9 @@ void PF_te_superspike (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_SUPERSPIKE); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_explosion (void) @@ -2407,9 +2407,9 @@ void PF_te_explosion (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSION); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_tarexplosion (void) @@ -2417,9 +2417,9 @@ void PF_te_tarexplosion (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_TAREXPLOSION); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_wizspike (void) @@ -2427,9 +2427,9 @@ void PF_te_wizspike (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_WIZSPIKE); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_knightspike (void) @@ -2437,9 +2437,9 @@ void PF_te_knightspike (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_KNIGHTSPIKE); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_lavasplash (void) @@ -2447,9 +2447,9 @@ void PF_te_lavasplash (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_LAVASPLASH); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_teleport (void) @@ -2457,9 +2457,9 @@ void PF_te_teleport (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_TELEPORT); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_te_explosion2 (void) @@ -2467,9 +2467,9 @@ void PF_te_explosion2 (void) MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_EXPLOSION2); // origin - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); // color MSG_WriteByte(&sv.datagram, G_FLOAT(OFS_PARM1)); } @@ -2481,13 +2481,13 @@ void PF_te_lightning1 (void) // owner entity MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); // end - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); } void PF_te_lightning2 (void) @@ -2497,13 +2497,13 @@ void PF_te_lightning2 (void) // owner entity MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); // end - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); } void PF_te_lightning3 (void) @@ -2513,13 +2513,13 @@ void PF_te_lightning3 (void) // owner entity MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); // end - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); } void PF_te_beam (void) @@ -2529,22 +2529,22 @@ void PF_te_beam (void) // owner entity MSG_WriteShort(&sv.datagram, G_EDICTNUM(OFS_PARM0)); // start - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM1)[2]); // end - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM2)[2]); } void PF_te_plasmaburn (void) { MSG_WriteByte(&sv.datagram, svc_temp_entity); MSG_WriteByte(&sv.datagram, TE_PLASMABURN); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); - MSG_WriteFloatCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[0]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[1]); + MSG_WriteDPCoord(&sv.datagram, G_VECTOR(OFS_PARM0)[2]); } void PF_Fixme (void) diff --git a/progs.h b/progs.h index c1b60e70..bf960584 100644 --- a/progs.h +++ b/progs.h @@ -43,8 +43,10 @@ typedef struct edict_s qboolean free; link_t area; +#ifdef QUAKEENTITIES entity_state_t baseline; entity_state_t deltabaseline; // LordHavoc: previous frame +#endif float freetime; // sv.time when the object was freed entvars_t v; // C exported fields from progs diff --git a/protocol.c b/protocol.c index fc5981aa..be9c9e79 100644 --- a/protocol.c +++ b/protocol.c @@ -3,6 +3,7 @@ void ClearStateToDefault(entity_state_t *s) { + s->active = 0; s->time = 0; VectorClear(s->origin); VectorClear(s->angles); @@ -16,29 +17,28 @@ void ClearStateToDefault(entity_state_t *s) s->glowsize = 0; s->glowcolor = 254; s->flags = 0; - s->active = 0; } // (server) clears the database to contain no frames (thus delta compression compresses against nothing) void EntityFrame_ClearDatabase(entity_database_t *d) { memset(d, 0, sizeof(*d)); - d->ackframe = -1; } // (server and client) removes frames older than 'frame' from database void EntityFrame_AckFrame(entity_database_t *d, int frame) { int i; - for (i = 0;i < d->numframes && d->frames[i].framenum >= frame;i++); + if (d->ackframe < frame) + d->ackframe = frame; + for (i = 0;i < d->numframes && d->frames[i].framenum < frame;i++); // ignore outdated frame acks (out of order packets) if (i == 0) return; - d->ackframe = frame; d->numframes -= i; // if some queue is left, slide it down to beginning of array if (d->numframes) - memcpy(&d->frames[0], &d->frames[i], sizeof(d->frames[0]) * d->numframes); + memmove(&d->frames[0], &d->frames[i], sizeof(d->frames[0]) * d->numframes); } // (server) clears frame, to prepare for adding entities @@ -60,12 +60,13 @@ entity_state_t *EntityFrame_NewEntity(entity_frame_t *f, int number) return e; } +// (server and client) reads a frame from the database void EntityFrame_FetchFrame(entity_database_t *d, int framenum, entity_frame_t *f) { int i, n; memset(f, 0, sizeof(*f)); for (i = 0;i < d->numframes && d->frames[i].framenum < framenum;i++); - if (framenum == d->frames[i].framenum) + if (i < d->numframes && framenum == d->frames[i].framenum) { f->framenum = framenum; f->numentities = d->frames[i].endentity - d->frames[i].firstentity; @@ -75,6 +76,7 @@ void EntityFrame_FetchFrame(entity_database_t *d, int framenum, entity_frame_t * memcpy(f->entitydata, d->entitydata + d->frames[i].firstentity % MAX_ENTITY_DATABASE, sizeof(*f->entitydata) * n); if (f->numentities > n) memcpy(f->entitydata + n, d->entitydata, sizeof(*f->entitydata) * (f->numentities - n)); + VectorCopy(d->eye, f->eye); } else f->framenum = -1; @@ -85,6 +87,9 @@ void EntityFrame_AddFrame(entity_database_t *d, entity_frame_t *f) { int n, e; entity_frameinfo_t *info; + + VectorCopy(f->eye, d->eye); + // figure out how many entity slots are used already if (d->numframes) { @@ -98,12 +103,27 @@ void EntityFrame_AddFrame(entity_database_t *d, entity_frame_t *f) info = &d->frames[d->numframes]; info->framenum = f->framenum; + e = -1000; + // make sure we check the newly added frame as well, but we haven't incremented numframes yet + for (n = 0;n <= d->numframes;n++) + { + if (e >= d->frames[n].framenum) + { + if (e == f->framenum) + Con_Printf("EntityFrame_AddFrame: tried to add out of sequence frame to database\n"); + else + Con_Printf("EntityFrame_AddFrame: out of sequence frames in database\n"); + return; + } + e = d->frames[n].framenum; + } // if database still has frames after that... if (d->numframes) info->firstentity = d->frames[d->numframes - 1].endentity; else info->firstentity = 0; info->endentity = info->firstentity + f->numentities; + d->numframes++; n = info->firstentity % MAX_ENTITY_DATABASE; e = MAX_ENTITY_DATABASE - n; @@ -115,7 +135,7 @@ void EntityFrame_AddFrame(entity_database_t *d, entity_frame_t *f) } // (server) writes a frame to network stream -void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, int newframe, sizebuf_t *msg) +void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, sizebuf_t *msg) { int i, onum, bits, number; entity_frame_t deltaframe, *o = &deltaframe; @@ -124,10 +144,10 @@ void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, int newframe, si EntityFrame_AddFrame(d, f); ClearStateToDefault(&baseline); - EntityFrame_FetchFrame(d, d->ackframe, o); + EntityFrame_FetchFrame(d, d->ackframe > 0 ? d->ackframe : -1, o); MSG_WriteByte (msg, svc_entities); MSG_WriteLong (msg, o->framenum); - MSG_WriteLong (msg, newframe); + MSG_WriteLong (msg, f->framenum); MSG_WriteFloat (msg, f->eye[0]); MSG_WriteFloat (msg, f->eye[1]); MSG_WriteFloat (msg, f->eye[2]); @@ -155,17 +175,17 @@ void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, int newframe, si delta = &baseline; } bits = 0; - if (ent->origin[0] != delta->origin[0]) + if ((int) ent->origin[0] != (int) delta->origin[0]) bits |= E_ORIGIN1; - if (ent->origin[1] != delta->origin[1]) + if ((int) ent->origin[1] != (int) delta->origin[1]) bits |= E_ORIGIN2; - if (ent->origin[2] != delta->origin[2]) + if ((int) ent->origin[2] != (int) delta->origin[2]) bits |= E_ORIGIN3; - if (ent->angles[0] != delta->angles[0]) + if ((byte) (ent->angles[0] * (256.0f / 360.0f)) != (byte) (delta->angles[0] * (256.0f / 360.0f))) bits |= E_ANGLE1; - if (ent->angles[1] != delta->angles[1]) + if ((byte) (ent->angles[1] * (256.0f / 360.0f)) != (byte) (delta->angles[1] * (256.0f / 360.0f))) bits |= E_ANGLE2; - if (ent->angles[2] != delta->angles[2]) + if ((byte) (ent->angles[2] * (256.0f / 360.0f)) != (byte) (delta->angles[2] * (256.0f / 360.0f))) bits |= E_ANGLE3; if ((ent->modelindex ^ delta->modelindex) & 0x00FF) bits |= E_MODEL1; @@ -216,11 +236,11 @@ void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, int newframe, si } } if (bits & E_ORIGIN1) - MSG_WriteFloat(msg, ent->origin[0]); + MSG_WriteShort(msg, ent->origin[0]); if (bits & E_ORIGIN2) - MSG_WriteFloat(msg, ent->origin[1]); + MSG_WriteShort(msg, ent->origin[1]); if (bits & E_ORIGIN3) - MSG_WriteFloat(msg, ent->origin[2]); + MSG_WriteShort(msg, ent->origin[2]); if (bits & E_ANGLE1) MSG_WriteAngle(msg, ent->angles[0]); if (bits & E_ANGLE2) @@ -266,26 +286,25 @@ void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, int newframe, si // (client) reads a frame from network stream void EntityFrame_Read(entity_database_t *d) { - int newframenum, deltaframenum, onum, number, removed, bits; + int number, removed, bits; entity_frame_t framedata, *f = &framedata, deltaframedata, *delta = &deltaframedata; - entity_state_t *e, baseline; + entity_state_t *e, baseline, *old, *oldend; ClearStateToDefault(&baseline); memset(f, 0, sizeof(*f)); // read the frame header info f->time = cl.mtime[0]; - deltaframenum = MSG_ReadLong(); - newframenum = MSG_ReadLong(); + number = MSG_ReadLong(); + f->framenum = MSG_ReadLong(); f->eye[0] = MSG_ReadFloat(); f->eye[1] = MSG_ReadFloat(); f->eye[2] = MSG_ReadFloat(); - EntityFrame_AckFrame(d, deltaframenum); - EntityFrame_FetchFrame(d, deltaframenum, delta); - f->framenum = newframenum; - onum = 0; - f->numentities = 0; + EntityFrame_AckFrame(d, number); + EntityFrame_FetchFrame(d, number, delta); + old = delta->entitydata; + oldend = old + delta->numentities; // read entities until we hit the magic 0xFFFF end tag - while ((number = MSG_ReadShort()) != 0xFFFF) + while ((number = (unsigned short) MSG_ReadShort()) != 0xFFFF) { if (msg_badread) Host_Error("EntityFrame_Read: read error\n"); @@ -295,41 +314,44 @@ void EntityFrame_Read(entity_database_t *d) Host_Error("EntityFrame_Read: number (%i) >= MAX_EDICTS (%i)\n", number, MAX_EDICTS); // seek to entity, while copying any skipped entities (assume unchanged) - while (onum < delta->numentities && delta->entitydata[onum].number < number) + while (old < oldend && old->number < number) { if (f->numentities >= MAX_ENTITY_DATABASE) Host_Error("EntityFrame_Read: entity list too big\n"); - memcpy(f->entitydata + f->numentities, delta->entitydata + onum, sizeof(entity_state_t)); - onum++; + memcpy(f->entitydata + f->numentities, old, sizeof(entity_state_t)); + f->entitydata[f->numentities].time = cl.mtime[0]; + old++; f->numentities++; } if (removed) { - if (onum < delta->numentities && delta->entitydata[onum].number == number) - onum++; + if (old < oldend && old->number == number) + old++; else - Con_Printf("EntityFrame_Read: REMOVE on unused entity!\n"); + Con_Printf("EntityFrame_Read: REMOVE on unused entity %i\n", number); } else { if (f->numentities >= MAX_ENTITY_DATABASE) Host_Error("EntityFrame_Read: entity list too big\n"); - if (onum < delta->numentities && delta->entitydata[onum].number == number) + + // reserve this slot + e = f->entitydata + f->numentities++; + + if (old < oldend && old->number == number) { // delta from old entity - memcpy(f->entitydata + f->numentities, delta->entitydata + onum++, sizeof(*e)); + memcpy(e, old++, sizeof(*e)); } else { // delta from baseline - memcpy(f->entitydata + f->numentities, &baseline, sizeof(*e)); + memcpy(e, &baseline, sizeof(*e)); } - // reserve this slot - e = f->entitydata + f->numentities++; - e->active = true; e->time = cl.mtime[0]; + e->number = number; bits = MSG_ReadByte(); if (bits & E_EXTEND1) @@ -344,11 +366,11 @@ void EntityFrame_Read(entity_database_t *d) } if (bits & E_ORIGIN1) - e->origin[0] = MSG_ReadFloat(); + e->origin[0] = (signed short) MSG_ReadShort(); if (bits & E_ORIGIN2) - e->origin[1] = MSG_ReadFloat(); + e->origin[1] = (signed short) MSG_ReadShort(); if (bits & E_ORIGIN3) - e->origin[2] = MSG_ReadFloat(); + e->origin[2] = (signed short) MSG_ReadShort(); if (bits & E_ANGLE1) e->angles[0] = MSG_ReadAngle(); if (bits & E_ANGLE2) @@ -383,22 +405,27 @@ void EntityFrame_Read(entity_database_t *d) e->flags = MSG_ReadByte(); } } - while (onum < delta->numentities) + while (old < oldend) { if (f->numentities >= MAX_ENTITY_DATABASE) Host_Error("EntityFrame_Read: entity list too big\n"); - memcpy(f->entitydata + f->numentities, delta->entitydata + onum, sizeof(entity_state_t)); - onum++; + memcpy(f->entitydata + f->numentities, old, sizeof(entity_state_t)); + f->entitydata[f->numentities].time = cl.mtime[0]; + old++; f->numentities++; } EntityFrame_AddFrame(d, f); } -void EntityFrame_FetchEye(entity_database_t *d, vec3_t eye, double time) +/* +// (client) reads (and interpolates) the eye location from the database, +// given a current time +int EntityFrame_FetchEye(entity_database_t *d, vec3_t eye, double time) { float frac; if (d->numframes == 0) - Host_Error("EntityFrame_FetchEye: no frames\n"); + return false; +// Host_Error("EntityFrame_FetchEye: no frames\n"); if (d->numframes > 1 && d->frames[d->numframes - 2].time != d->frames[d->numframes - 1].time) { frac = (time - d->frames[d->numframes - 2].time) / (d->frames[d->numframes - 1].time - d->frames[d->numframes - 2].time); @@ -408,6 +435,7 @@ void EntityFrame_FetchEye(entity_database_t *d, vec3_t eye, double time) } else VectorCopy(d->frames[0].eye, eye); + return true; } // (client) fetchs an entity from a frame, index is the index into the frame's entity list, returns false if index is out of bounds @@ -433,3 +461,13 @@ int EntityFrame_FetchEntityByNumber(entity_frame_t *f, entity_state_t *e, int nu ClearStateToDefault(e); return false; } +*/ + +// (client) returns the frame number of the most recent frame recieved +int EntityFrame_MostRecentlyRecievedFrameNum(entity_database_t *d) +{ + if (d->numframes) + return d->frames[d->numframes - 1].framenum; + else + return -1; +} diff --git a/protocol.h b/protocol.h index 0df3b283..f07830f9 100644 --- a/protocol.h +++ b/protocol.h @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -20,7 +20,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // protocol.h -- communications protocols #define PROTOCOL_VERSION 15 -#define DPPROTOCOL_VERSION 96 +#define DPPROTOCOL_VERSION1 96 +#define DPPROTOCOL_VERSION2 97 // model effects #define EF_ROCKET 1 // leave a trail @@ -202,6 +203,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svc_hidelmp 36 // [string] slotname #define svc_skybox 37 // [string] skyname +// LordHavoc: my svc_ range, 50-59 #define svc_cgame 50 // [short] length [bytes] data #define svc_fog 51 // unfinished and obsolete #define svc_effect 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate @@ -222,6 +224,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define clc_move 3 // [usercmd_t] #define clc_stringcmd 4 // [string] message +// LordHavoc: my clc_ range, 50-59 +#define clc_ackentities 50 // [int] framenumber +#define clc_unusedlh1 51 +#define clc_unusedlh2 52 +#define clc_unusedlh3 53 +#define clc_unusedlh4 54 +#define clc_unusedlh5 55 +#define clc_unusedlh6 56 +#define clc_unusedlh7 57 +#define clc_unusedlh8 58 +#define clc_unusedlh9 59 // // temp entity events @@ -240,7 +253,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define TE_TELEPORT 11 // [vector] origin #define TE_EXPLOSION2 12 // [vector] origin [byte] startcolor [byte] colorcount -// PGM 01/21/97 +// PGM 01/21/97 #define TE_BEAM 13 // [entity] entity [vector] start [vector] end // PGM 01/21/97 @@ -296,7 +309,6 @@ entity_state_t; typedef struct { double time; - vec3_t eye; int framenum; int firstentity; // index into entitydata, modulo MAX_ENTITY_DATABASE int endentity; // index into entitydata, firstentity + numentities @@ -318,6 +330,7 @@ typedef struct // the only reason this system is used is to avoid copying memory when frames are removed int numframes; int ackframe; // server only: last acknowledged frame + vec3_t eye; entity_frameinfo_t frames[MAX_ENTITY_HISTORY]; entity_state_t entitydata[MAX_ENTITY_DATABASE]; } @@ -389,14 +402,21 @@ void EntityFrame_AckFrame(entity_database_t *d, int frame); void EntityFrame_Clear(entity_frame_t *f, vec3_t eye); // (server) allocates an entity slot in frame, returns NULL if full entity_state_t *EntityFrame_NewEntity(entity_frame_t *f, int number); +// (server and client) reads a frame from the database +void EntityFrame_FetchFrame(entity_database_t *d, int framenum, entity_frame_t *f); // (server and client) adds a entity_frame to the database, for future // reference void EntityFrame_AddFrame(entity_database_t *d, entity_frame_t *f); // (server) writes a frame to network stream -void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, int newframe, sizebuf_t *msg); +void EntityFrame_Write(entity_database_t *d, entity_frame_t *f, sizebuf_t *msg); // (client) reads a frame from network stream void EntityFrame_Read(entity_database_t *d); +// (client) reads (and interpolates) the eye location from the database, +// given a current time +//int EntityFrame_FetchEye(entity_database_t *d, vec3_t eye, double time); // (client) fetchs an entity from the frame by index into the entity list -int EntityFrame_FetchEntityByIndex(entity_frame_t *f, entity_state_t *e, int index); +//int EntityFrame_FetchEntityByIndex(entity_frame_t *f, entity_state_t *e, int index); // (client) fetchs an entity from the frame by entity number -int EntityFrame_FetchEntityByNumber(entity_frame_t *f, entity_state_t *e, int number); +//int EntityFrame_FetchEntityByNumber(entity_frame_t *f, entity_state_t *e, int number); +// (client) returns the frame number of the most recent frame recieved +int EntityFrame_MostRecentlyRecievedFrameNum(entity_database_t *d); diff --git a/server.h b/server.h index 69be0431..273b3de9 100644 --- a/server.h +++ b/server.h @@ -108,9 +108,17 @@ typedef struct client_s int old_frags; int pmodel; +#ifdef QUAKEENTITIES // delta compression state float nextfullupdate[MAX_EDICTS]; - float lastvisible[MAX_EDICTS]; +#endif + // visibility state + float visibletime[MAX_EDICTS]; + +#ifndef QUAKEENTITIES + entity_database_t entitydatabase; + int entityframenumber; // incremented each time an entity frame is sent +#endif } client_t; diff --git a/sv_main.c b/sv_main.c index 34ac5460..1ea395fa 100644 --- a/sv_main.c +++ b/sv_main.c @@ -89,9 +89,9 @@ void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count) if (sv.datagram.cursize > MAX_DATAGRAM-16) return; MSG_WriteByte (&sv.datagram, svc_particle); - MSG_WriteFloatCoord (&sv.datagram, org[0]); - MSG_WriteFloatCoord (&sv.datagram, org[1]); - MSG_WriteFloatCoord (&sv.datagram, org[2]); + MSG_WriteDPCoord (&sv.datagram, org[0]); + MSG_WriteDPCoord (&sv.datagram, org[1]); + MSG_WriteDPCoord (&sv.datagram, org[2]); for (i=0 ; i<3 ; i++) { v = dir[i]*16; @@ -119,9 +119,9 @@ void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, if (modelindex >= 256 || startframe >= 256) { MSG_WriteByte (&sv.datagram, svc_effect2); - MSG_WriteFloatCoord (&sv.datagram, org[0]); - MSG_WriteFloatCoord (&sv.datagram, org[1]); - MSG_WriteFloatCoord (&sv.datagram, org[2]); + MSG_WriteDPCoord (&sv.datagram, org[0]); + MSG_WriteDPCoord (&sv.datagram, org[1]); + MSG_WriteDPCoord (&sv.datagram, org[2]); MSG_WriteShort (&sv.datagram, modelindex); MSG_WriteShort (&sv.datagram, startframe); MSG_WriteByte (&sv.datagram, framecount); @@ -130,9 +130,9 @@ void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, else { MSG_WriteByte (&sv.datagram, svc_effect); - MSG_WriteFloatCoord (&sv.datagram, org[0]); - MSG_WriteFloatCoord (&sv.datagram, org[1]); - MSG_WriteFloatCoord (&sv.datagram, org[2]); + MSG_WriteDPCoord (&sv.datagram, org[0]); + MSG_WriteDPCoord (&sv.datagram, org[1]); + MSG_WriteDPCoord (&sv.datagram, org[2]); MSG_WriteByte (&sv.datagram, modelindex); MSG_WriteByte (&sv.datagram, startframe); MSG_WriteByte (&sv.datagram, framecount); @@ -213,7 +213,7 @@ void SV_StartSound (edict_t *entity, int channel, char *sample, int volume, else MSG_WriteByte (&sv.datagram, sound_num); for (i=0 ; i<3 ; i++) - MSG_WriteFloatCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i])); + MSG_WriteDPCoord (&sv.datagram, entity->v.origin[i]+0.5*(entity->v.mins[i]+entity->v.maxs[i])); } /* @@ -237,12 +237,16 @@ void SV_SendServerinfo (client_t *client) char **s; char message[2048]; + // LordHavoc: clear entityframe tracking + client->entityframenumber = 0; + EntityFrame_ClearDatabase(&client->entitydatabase); + MSG_WriteByte (&client->message, svc_print); sprintf (message, "\002\nServer: %s build %s (progs %i crc)", gamename, buildstring, pr_crc); MSG_WriteString (&client->message,message); MSG_WriteByte (&client->message, svc_serverinfo); - MSG_WriteLong (&client->message, DPPROTOCOL_VERSION); + MSG_WriteLong (&client->message, DPPROTOCOL_VERSION2); MSG_WriteByte (&client->message, svs.maxclients); if (!coop.integer && deathmatch.integer) @@ -498,6 +502,7 @@ SV_WriteEntitiesToClient ============= */ +#ifdef QUAKEENTITIES void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) { int e, clentnum, bits, alpha, glowcolor, glowsize, scale, effects; @@ -669,10 +674,10 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) SV_RecursiveHullCheck (sv.worldmodel->hulls->firstclipnode, 0, 1, testeye, testorigin); if (trace.fraction == 1) - client->lastvisible[e] = realtime; + client->visibletime[e] = realtime + 1; else { - if (realtime - client->lastvisible[e] >= 1) + if (realtime > client->visibletime[e]) { culled_trace++; continue; @@ -735,7 +740,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) for (;e < sv.num_edicts;e++) { client->nextfullupdate[e] = -1; - client->lastvisible[e] = -1; + client->visibletime[e] = -1; } return; } @@ -835,11 +840,11 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (bits & U_COLORMAP) MSG_WriteByte (msg, ent->v.colormap); if (bits & U_SKIN) MSG_WriteByte (msg, ent->v.skin); if (bits & U_EFFECTS) MSG_WriteByte (msg, ent->v.effects); - if (bits & U_ORIGIN1) MSG_WriteFloatCoord (msg, origin[0]); + if (bits & U_ORIGIN1) MSG_WriteDPCoord (msg, origin[0]); if (bits & U_ANGLE1) MSG_WriteAngle(msg, angles[0]); - if (bits & U_ORIGIN2) MSG_WriteFloatCoord (msg, origin[1]); + if (bits & U_ORIGIN2) MSG_WriteDPCoord (msg, origin[1]); if (bits & U_ANGLE2) MSG_WriteAngle(msg, angles[1]); - if (bits & U_ORIGIN3) MSG_WriteFloatCoord (msg, origin[2]); + if (bits & U_ORIGIN3) MSG_WriteDPCoord (msg, origin[2]); if (bits & U_ANGLE3) MSG_WriteAngle(msg, angles[2]); // LordHavoc: new stuff @@ -855,6 +860,259 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) if (sv_cullentities_stats.integer) Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d portal %d trace\n", client->name, totalentities, visibleentities, culled_pvs + culled_portal + culled_trace, culled_pvs, culled_portal, culled_trace); } +#else +void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg) +{ + int e, clentnum, flags, alpha, glowcolor, glowsize, scale, effects; + int culled_pvs, culled_portal, culled_trace, visibleentities, totalentities; + byte *pvs; + vec3_t org, origin, angles, entmins, entmaxs; + edict_t *ent; + eval_t *val; + trace_t trace; + model_t *model; + double testeye[3]; + double testorigin[3]; + entity_frame_t entityframe; + entity_state_t *s; + + if (client->sendsignon) + return; + + Mod_CheckLoaded(sv.worldmodel); + +// find the client's PVS + VectorAdd (clent->v.origin, clent->v.view_ofs, testeye); + VectorCopy (testeye, org); + pvs = SV_FatPVS (org); + EntityFrame_Clear(&entityframe, org); + + culled_pvs = 0; + culled_portal = 0; + culled_trace = 0; + visibleentities = 0; + totalentities = 0; + + clentnum = EDICT_TO_PROG(clent); // LordHavoc: for comparison purposes + // send all entities that touch the pvs + ent = NEXT_EDICT(sv.edicts); + for (e = 1;e < sv.num_edicts;e++, ent = NEXT_EDICT(ent)) + { + flags = 0; + + if (ent != clent) // LordHavoc: always send player + { + if ((val = GETEDICTFIELDVALUE(ent, eval_viewmodelforclient)) && val->edict) + { + if (val->edict == clentnum) + flags |= RENDER_VIEWMODEL; // show relative to the view + else + { + // don't show to anyone else + continue; + } + } + else + { + // LordHavoc: never draw something told not to display to this client + if ((val = GETEDICTFIELDVALUE(ent, eval_nodrawtoclient)) && val->edict == clentnum) + continue; + if ((val = GETEDICTFIELDVALUE(ent, eval_drawonlytoclient)) && val->edict && val->edict != clentnum) + continue; + } + } + + glowsize = 0; + + if ((val = GETEDICTFIELDVALUE(ent, eval_glow_size))) + glowsize = (int) val->_float >> 2; + glowsize = bound(0, glowsize, 255); + + if ((val = GETEDICTFIELDVALUE(ent, eval_glow_trail))) + if (val->_float != 0) + flags |= RENDER_GLOWTRAIL; + + if (ent->v.modelindex >= 0 && ent->v.modelindex < MAX_MODELS && pr_strings[ent->v.model]) + { + model = sv.models[(int)ent->v.modelindex]; + Mod_CheckLoaded(model); + } + else + { + model = NULL; + if (ent != clent) // LordHavoc: always send player + if (glowsize == 0 && (flags & RENDER_GLOWTRAIL) == 0) // no effects + continue; + } + + VectorCopy(ent->v.angles, angles); + if (DotProduct(ent->v.velocity, ent->v.velocity) >= 1.0f && host_client->latency >= 0.01f) + { + VectorMA(ent->v.origin, host_client->latency, ent->v.velocity, origin); + // LordHavoc: trace predicted movement to avoid putting things in walls + trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, origin, MOVE_NORMAL, ent); + VectorCopy(trace.endpos, origin); + } + else + { + VectorCopy(ent->v.origin, origin); + } + + // ent has survived every check so far, check if it is visible + // always send embedded brush models, they don't generate much traffic + if (ent != clent && ((flags & RENDER_VIEWMODEL) == 0) && (model == NULL || model->type != mod_brush || model->name[0] != '*')) + { + // use the predicted origin + entmins[0] = origin[0] - 1.0f; + entmins[1] = origin[1] - 1.0f; + entmins[2] = origin[2] - 1.0f; + entmaxs[0] = origin[0] + 1.0f; + entmaxs[1] = origin[1] + 1.0f; + entmaxs[2] = origin[2] + 1.0f; + // using the model's bounding box to ensure things are visible regardless of their physics box + if (model) + { + if (ent->v.angles[0] || ent->v.angles[2]) // pitch and roll + { + VectorAdd(entmins, model->rotatedmins, entmins); + VectorAdd(entmaxs, model->rotatedmaxs, entmaxs); + } + else if (ent->v.angles[1]) + { + VectorAdd(entmins, model->yawmins, entmins); + VectorAdd(entmaxs, model->yawmaxs, entmaxs); + } + else + { + VectorAdd(entmins, model->normalmins, entmins); + VectorAdd(entmaxs, model->normalmaxs, entmaxs); + } + } + + totalentities++; + + // if not touching a visible leaf + if (sv_cullentities_pvs.integer && !SV_BoxTouchingPVS(pvs, entmins, entmaxs, sv.worldmodel->nodes)) + { + culled_pvs++; + continue; + } + + // or not visible through the portals + if (sv_cullentities_portal.integer && !Portal_CheckBox(sv.worldmodel, org, entmins, entmaxs)) + { + culled_portal++; + continue; + } + + if (sv_cullentities_trace.integer) + { + // LordHavoc: test random offsets, to maximize chance of detection + testorigin[0] = lhrandom(entmins[0], entmaxs[0]); + testorigin[1] = lhrandom(entmins[1], entmaxs[1]); + testorigin[2] = lhrandom(entmins[2], entmaxs[2]); + + memset (&trace, 0, sizeof(trace_t)); + trace.fraction = 1; + trace.allsolid = true; + VectorCopy(testorigin, trace.endpos); + + VectorCopy(org, RecursiveHullCheckInfo.start); + VectorSubtract(testorigin, testeye, RecursiveHullCheckInfo.dist); + RecursiveHullCheckInfo.hull = sv.worldmodel->hulls; + RecursiveHullCheckInfo.trace = &trace; + SV_RecursiveHullCheck (sv.worldmodel->hulls->firstclipnode, 0, 1, testeye, testorigin); + + if (trace.fraction == 1) + client->visibletime[e] = realtime + 1; + else + { + if (realtime > client->visibletime[e]) + { + culled_trace++; + continue; + } + } + } + visibleentities++; + } + + alpha = 255; + scale = 16; + glowcolor = 254; + effects = ent->v.effects; + + if ((val = GETEDICTFIELDVALUE(ent, eval_alpha))) + if (val->_float != 0) + alpha = (int) (val->_float * 255.0); + + // HalfLife support + if ((val = GETEDICTFIELDVALUE(ent, eval_renderamt))) + if (val->_float != 0) + alpha = (int) val->_float; + + if (alpha == 0) + alpha = 255; + alpha = bound(0, alpha, 255); + + if ((val = GETEDICTFIELDVALUE(ent, eval_scale))) + if ((scale = (int) (val->_float * 16.0)) == 0) scale = 16; + if (scale < 0) scale = 0; + if (scale > 255) scale = 255; + + if ((val = GETEDICTFIELDVALUE(ent, eval_glow_color))) + if (val->_float != 0) + glowcolor = (int) val->_float; + + if ((val = GETEDICTFIELDVALUE(ent, eval_fullbright))) + if (val->_float != 0) + effects |= EF_FULLBRIGHT; + + if (ent != clent) + { + if (glowsize == 0 && (flags & RENDER_GLOWTRAIL) == 0) // no effects + { + if (model) // model + { + // don't send if flagged for NODRAW and there are no effects + if (model->flags == 0 && ((effects & EF_NODRAW) || scale <= 0 || alpha <= 0)) + continue; + } + else // no model and no effects + continue; + } + } + + if ((val = GETEDICTFIELDVALUE(ent, eval_exteriormodeltoclient)) && val->edict == clentnum) + flags |= RENDER_EXTERIORMODEL; + + if (ent->v.movetype == MOVETYPE_STEP) + flags |= RENDER_STEP; + + s = EntityFrame_NewEntity(&entityframe, e); + // if we run out of space, abort + if (!s) + break; + VectorCopy(origin, s->origin); + VectorCopy(angles, s->angles); + s->colormap = ent->v.colormap; + s->skin = ent->v.skin; + s->frame = ent->v.frame; + s->modelindex = ent->v.modelindex; + s->effects = effects; + s->alpha = alpha; + s->scale = scale; + s->glowsize = glowsize; + s->glowcolor = glowcolor; + s->flags = flags; + } + entityframe.framenum = ++client->entityframenumber; + EntityFrame_Write(&client->entitydatabase, &entityframe, msg); + + if (sv_cullentities_stats.integer) + Con_Printf("client \"%s\" entities: %d total, %d visible, %d culled by: %d pvs %d portal %d trace\n", client->name, totalentities, visibleentities, culled_pvs + culled_portal + culled_trace, culled_pvs, culled_portal, culled_trace); +} +#endif /* ============= @@ -897,7 +1155,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) MSG_WriteByte (msg, ent->v.dmg_save); MSG_WriteByte (msg, ent->v.dmg_take); for (i=0 ; i<3 ; i++) - MSG_WriteFloatCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i])); + MSG_WriteDPCoord (msg, other->v.origin[i] + 0.5*(other->v.mins[i] + other->v.maxs[i])); ent->v.dmg_take = 0; ent->v.dmg_save = 0; @@ -919,7 +1177,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) bits = 0; - if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT) + //if (ent->v.view_ofs[2] != DEFAULT_VIEWHEIGHT) bits |= SU_VIEWHEIGHT; if (ent->v.idealpitch) @@ -981,7 +1239,8 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) MSG_WriteByte(msg, bits >> 24); if (bits & SU_VIEWHEIGHT) - MSG_WriteChar (msg, ent->v.view_ofs[2]); + //MSG_WriteChar (msg, ent->v.view_ofs[2]); + MSG_WriteChar (msg, 0); if (bits & SU_IDEALPITCH) MSG_WriteChar (msg, ent->v.idealpitch); @@ -991,7 +1250,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) if (bits & (SU_PUNCH1<v.punchangle[i]); // dpprotocol if (bits & (SU_PUNCHVEC1<v.velocity[i]/16); } @@ -1233,6 +1492,7 @@ int SV_ModelIndex (char *name) return i; } +#ifdef SV_QUAKEENTITIES /* ================ SV_CreateBaseline @@ -1299,11 +1559,12 @@ void SV_CreateBaseline (void) MSG_WriteByte (&sv.signon, svent->baseline.skin); for (i=0 ; i<3 ; i++) { - MSG_WriteFloatCoord(&sv.signon, svent->baseline.origin[i]); + MSG_WriteDPCoord(&sv.signon, svent->baseline.origin[i]); MSG_WriteAngle(&sv.signon, svent->baseline.angles[i]); } } } +#endif /* @@ -1504,8 +1765,10 @@ void SV_SpawnServer (char *server) Mod_PurgeUnused(); +#ifdef QUAKEENTITIES // create a baseline for more efficient communications SV_CreateBaseline (); +#endif // send serverinfo to all connected clients for (i=0,host_client = svs.clients ; iv.punchangle); - + len -= 10*sv.frametime; if (len < 0) len = 0; @@ -607,6 +607,10 @@ nextmsg: case clc_move: SV_ReadClientMove (&host_client->cmd); break; + + case clc_ackentities: + EntityFrame_AckFrame(&host_client->entitydatabase, MSG_ReadLong()); + break; } } } while (ret == 1); diff --git a/view.c b/view.c index 0dd06769..9ca72092 100644 --- a/view.c +++ b/view.c @@ -76,7 +76,7 @@ float V_CalcRoll (vec3_t angles, vec3_t velocity) side = DotProduct (velocity, right); sign = side < 0 ? -1 : 1; side = fabs(side); - + value = cl_rollangle.value; // if (cl.inwater) // value *= 6; @@ -499,17 +499,19 @@ void V_CalcRefdef (void) V_DriftPitch (); - VectorCopy (ent->render.origin, r_refdef.vieworg); + VectorCopy (cl.viewentorigin, r_refdef.vieworg); if (!intimerefresh) VectorCopy (cl.viewangles, r_refdef.viewangles); if (cl.intermission) { view->render.model = NULL; + VectorCopy (ent->render.angles, r_refdef.viewangles); V_AddIdle (1); } else if (chase_active.value) { + r_refdef.vieworg[2] += cl.viewheight; Chase_Update (); V_AddIdle (v_idlescale.value); } @@ -544,9 +546,10 @@ void V_CalcRefdef (void) // set up gun view->state_current.modelindex = cl.stats[STAT_WEAPON]; view->state_current.frame = cl.stats[STAT_WEAPONFRAME]; - view->render.origin[0] = ent->render.origin[0] + bob * 0.4 * forward[0]; - view->render.origin[1] = ent->render.origin[1] + bob * 0.4 * forward[1]; - view->render.origin[2] = ent->render.origin[2] + bob * 0.4 * forward[2] + cl.viewheight + bob; + VectorCopy(r_refdef.vieworg, view->render.origin); + //view->render.origin[0] = ent->render.origin[0] + bob * 0.4 * forward[0]; + //view->render.origin[1] = ent->render.origin[1] + bob * 0.4 * forward[1]; + //view->render.origin[2] = ent->render.origin[2] + bob * 0.4 * forward[2] + cl.viewheight + bob; view->render.angles[PITCH] = -r_refdef.viewangles[PITCH] - v_idlescale.value * sin(cl.time*v_iyaw_cycle.value) * v_iyaw_level.value; view->render.angles[YAW] = r_refdef.viewangles[YAW] - v_idlescale.value * sin(cl.time*v_ipitch_cycle.value) * v_ipitch_level.value; view->render.angles[ROLL] = r_refdef.viewangles[ROLL] - v_idlescale.value * sin(cl.time*v_iroll_cycle.value) * v_iroll_level.value;