Add lerptime protocol extension. Still WIP, don't record to demos.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6247 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2022-05-28 17:59:26 +00:00
parent 255ce795a0
commit 0f8d07b8e8
8 changed files with 293 additions and 137 deletions

View File

@ -630,6 +630,8 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
bits |= MSG_ReadByte()<<16;
if (bits & UF_EXTEND3)
bits |= MSG_ReadByte()<<24;
if (bits & UF_EXTEND4)
Host_EndGame("ent update bit %#x\n", UF_EXTEND4);
if (cl_shownet.ival >= 3)
Con_Printf("%3i: Update %4i 0x%x\n", MSG_GetReadCount(), entnum, bits);
@ -653,10 +655,15 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
if (bits & UF_FRAME)
{
if (bits & UF_16BIT)
news->frame = MSG_ReadShort();
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
news->frame = MSG_ReadULEB128();
else
news->frame = MSG_ReadByte();
{
if (bits & UF_16BIT_LERPTIME)
news->frame = MSG_ReadShort();
else
news->frame = MSG_ReadByte();
}
}
if (cls.ezprotocolextensions1 & EZPEXT1_FLOATENTCOORDS)
@ -702,12 +709,24 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
news->angles[1] = MSG_ReadAngle();
}
if ((bits & (UF_EFFECTS | UF_EFFECTS2)) == (UF_EFFECTS | UF_EFFECTS2))
news->effects = MSG_ReadLong();
else if (bits & UF_EFFECTS2)
news->effects = (unsigned short)MSG_ReadShort();
else if (bits & UF_EFFECTS)
news->effects = MSG_ReadByte();
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
{
if (bits & UF_16BIT_LERPTIME)
news->lerpend = cl.gametime + MSG_ReadULEB128()*(1/1000.0); //most things will animate at 100ms, so this will usually fit a single byte, without capping out.
if (bits & UF_EFFECTS)
news->effects = MSG_ReadULEB128();
if (bits & UF_EFFECTS2_OLD)
Host_EndGame("Received unexpected (redefined) bit %#x\n", UF_EFFECTS2_OLD);
}
else
{
if ((bits & (UF_EFFECTS | UF_EFFECTS2_OLD)) == (UF_EFFECTS | UF_EFFECTS2_OLD))
news->effects = MSG_ReadLong();
else if (bits & UF_EFFECTS2_OLD)
news->effects = (unsigned short)MSG_ReadShort();
else if (bits & UF_EFFECTS)
news->effects = MSG_ReadByte();
}
news->u.q1.movement[0] = 0;
news->u.q1.movement[1] = 0;
@ -792,20 +811,35 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
if (bits & UF_MODEL)
{
if (bits & UF_16BIT)
news->modelindex = MSG_ReadShort();
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
news->modelindex = MSG_ReadULEB128();
else
news->modelindex = MSG_ReadByte();
{
if (bits & UF_16BIT_LERPTIME)
news->modelindex = MSG_ReadShort();
else
news->modelindex = MSG_ReadByte();
}
}
if (bits & UF_SKIN)
{
if (bits & UF_16BIT)
news->skinnum = MSG_ReadShort();
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
news->skinnum = MSG_ReadULEB128()-64; //biased for content overrides
else
news->skinnum = MSG_ReadByte();
{
if (bits & UF_16BIT_LERPTIME)
news->skinnum = MSG_ReadShort();
else
news->skinnum = MSG_ReadByte();
}
}
if (bits & UF_COLORMAP)
news->colormap = MSG_ReadByte();
{
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
news->colormap = MSG_ReadULEB128();
else
news->colormap = MSG_ReadByte();
}
if (bits & UF_SOLID)
{
@ -832,7 +866,12 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
}
if (bits & UF_FLAGS)
news->dpflags = MSG_ReadByte();
{
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
news->dpflags = MSG_ReadULEB128();
else
news->dpflags = MSG_ReadByte();
}
if (bits & UF_ALPHA)
news->trans = MSG_ReadByte();
@ -855,8 +894,16 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
news->bonecount = 0; //oo, it went away.
if (fl & 0x40)
{
news->basebone = MSG_ReadByte();
news->baseframe = MSG_ReadShort();
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
{
news->basebone = MSG_ReadULEB128();
news->baseframe = MSG_ReadULEB128();
}
else
{
news->basebone = MSG_ReadByte();
news->baseframe = MSG_ReadShort();
}
}
else
{
@ -885,9 +932,14 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
if (bits & UF_TAGINFO)
{
news->tagentity = MSGCL_ReadEntity();
news->tagindex = MSG_ReadByte();
if (news->tagindex == 0xff)
news->tagindex = ~0;
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
news->tagindex = MSG_ReadULEB128()-1; //biased for q3-like portals.
else
{
news->tagindex = MSG_ReadByte();
if (news->tagindex == 0xff)
news->tagindex = ~0;
}
}
if (bits & UF_LIGHT)
{
@ -895,20 +947,32 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
news->light[1] = MSG_ReadShort();
news->light[2] = MSG_ReadShort();
news->light[3] = MSG_ReadShort();
news->lightstyle = MSG_ReadByte();
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
news->lightstyle = MSG_ReadULEB128();
else
news->lightstyle = MSG_ReadByte();
news->lightpflags = MSG_ReadByte();
}
if (bits & UF_TRAILEFFECT)
{
unsigned short s;
s = MSG_ReadShort();
news->u.q1.traileffectnum = s & 0x3fff;
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
{
news->u.q1.traileffectnum = MSG_ReadULEB128();
news->u.q1.emiteffectnum = MSG_ReadULEB128();
}
else
{
unsigned short s;
s = MSG_ReadShort();
news->u.q1.traileffectnum = s & 0x3fff;
if (s & 0x8000)
news->u.q1.emiteffectnum = MSG_ReadShort() & 0x3fff;
else
news->u.q1.emiteffectnum = 0;
}
if (news->u.q1.traileffectnum >= countof(cl.particle_ssprecache))
news->u.q1.traileffectnum = 0;
if (s & 0x8000)
news->u.q1.emiteffectnum = MSG_ReadShort() & 0x3fff;
else
news->u.q1.emiteffectnum = 0;
if (news->u.q1.emiteffectnum >= countof(cl.particle_ssprecache))
news->u.q1.emiteffectnum = 0;
}
@ -931,23 +995,24 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t *
news->fatness = MSG_ReadByte();
if (bits & UF_MODELINDEX2)
{
if (bits & UF_16BIT)
news->modelindex2 = MSG_ReadShort();
if (cls.fteprotocolextensions2 & PEXT2_LERPTIME)
news->modelindex2 = MSG_ReadULEB128();
else
news->modelindex2 = MSG_ReadByte();
{
if (bits & UF_16BIT_LERPTIME)
news->modelindex2 = MSG_ReadShort();
else
news->modelindex2 = MSG_ReadByte();
}
}
if (bits & UF_GRAVITYDIR)
{
news->u.q1.gravitydir[0] = MSG_ReadByte();
news->u.q1.gravitydir[1] = MSG_ReadByte();
}
if (bits & UF_UNUSED2)
{
Host_EndGame("UF_UNUSED2 bit\n");
}
if (bits & UF_UNUSED1)
{
Host_EndGame("UF_UNUSED1 bit\n");
Host_EndGame("ent update bit %#x\n", UF_UNUSED1);
}
}

View File

@ -90,6 +90,7 @@ cvar_t net_mtu = CVARD("net_mtu", "1440", "Specifies a maximum udp payload size,
cvar_t net_compress = CVARD("net_compress", "0", "Enables huffman compression of network packets.");
cvar_t pext_vrinputs = CVARD("_pext_vrinputs", "0", "RENAME ME WHEN STABLE. Networks player inputs slightly differently, allowing for greater capabilities, particuarly vr controller info.");
cvar_t pext_lerptime = CVARD("_pext_lerptime", "0", "RENAME ME WHEN STABLE. Sends timing hints for interpolation.");
cvar_t pext_infoblobs = CVARD("_pext_infoblobs", "0", "RENAME ME WHEN STABLE. Enables the use of very large infokeys containing potentially invalid chars. Note that the userinfo is still limited by sv_userinfo_bytelimit and sv_userinfo_keylimit.");
cvar_t pext_replacementdeltas = CVARD("pext_replacementdeltas", "1", "Enables the use of alternative nack-based entity deltas");
cvar_t pext_predinfo = CVARD("pext_predinfo", "1", "Enables some extra things to support prediction over NQ protocols.");
@ -225,6 +226,9 @@ unsigned int Net_PextMask(unsigned int protover, qboolean fornq)
if (pext_vrinputs.ival)
mask |= PEXT2_VRINPUTS;
if (pext_lerptime.ival)
mask |= PEXT2_LERPTIME;
if (MAX_CLIENTS != QWMAX_CLIENTS)
mask |= PEXT2_MAXPLAYERS;
@ -236,7 +240,7 @@ unsigned int Net_PextMask(unsigned int protover, qboolean fornq)
if (fornq)
{
//only ones that are tested
mask &= PEXT2_PRYDONCURSOR | PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_REPLACEMENTDELTAS | PEXT2_MAXPLAYERS | PEXT2_PREDINFO | PEXT2_NEWSIZEENCODING | PEXT2_VRINPUTS;
mask &= PEXT2_PRYDONCURSOR | PEXT2_VOICECHAT | PEXT2_SETANGLEDELTA | PEXT2_REPLACEMENTDELTAS | PEXT2_MAXPLAYERS | PEXT2_PREDINFO | PEXT2_NEWSIZEENCODING | PEXT2_VRINPUTS | PEXT2_LERPTIME;
}
// else
// mask &= ~PEXT2_PREDINFO;
@ -281,6 +285,7 @@ void Netchan_Init (void)
Cvar_Register (&pext_replacementdeltas, "Protocol Extensions");
Cvar_Register (&pext_infoblobs, "Protocol Extensions");
Cvar_Register (&pext_vrinputs, "Protocol Extensions");
Cvar_Register (&pext_lerptime, "Protocol Extensions");
Cvar_Register (&showpackets, "Networking");
Cvar_Register (&showdrop, "Networking");
Cvar_Register (&qport, "Networking");

View File

@ -56,6 +56,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PEXT_CHUNKEDDOWNLOADS 0x20000000 //alternate file download method. Hopefully it'll give quadroupled download speed, especially on higher pings.
#define PEXT_CSQC 0x40000000 //csqc additions
#define PEXT_DPFLAGS 0x80000000 //extra flags for viewmodel/externalmodel and possible other persistant style flags.
#define PEXT_SERVERADVERTISE ~0u
#define PEXT_CLIENTSUPPORT (PEXT_SETVIEW|PEXT_SCALE|PEXT_LIGHTSTYLECOL|PEXT_TRANS|PEXT_VIEW2_|PEXT_ACCURATETIMINGS|PEXT_SOUNDDBL|PEXT_FATNESS|PEXT_HLBSP|PEXT_TE_BULLET|PEXT_HULLSIZE|PEXT_MODELDBL|PEXT_ENTITYDBL|PEXT_ENTITYDBL2|PEXT_FLOATCOORDS|PEXT_Q2BSP_|PEXT_Q3BSP_|PEXT_COLOURMOD|PEXT_SPLITSCREEN|PEXT_HEXEN2|PEXT_SPAWNSTATIC2|PEXT_CUSTOMTEMPEFFECTS|PEXT_256PACKETENTITIES|PEXT_SHOWPIC|PEXT_SETATTACHMENT|PEXT_CHUNKEDDOWNLOADS|PEXT_CSQC|PEXT_DPFLAGS)
#ifdef CSQC_DAT
@ -84,7 +85,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define PEXT2_INFOBLOBS 0x00000080 //serverinfo+userinfo lengths can be MUCH higher (protocol is unbounded, but expect low sanity limits on userinfo), and contain nulls etc.
#define PEXT2_STUNAWARE 0x00000100 //changes the netchan to biased-bigendian (so lead two bits are 1 and not stun's 0, so we don't get confused)
#define PEXT2_VRINPUTS 0x00000200 //clc_move changes, more buttons etc. vr stuff!
#define PEXT2_CLIENTSUPPORT (PEXT2_PRYDONCURSOR|PEXT2_VOICECHAT|PEXT2_SETANGLEDELTA|PEXT2_REPLACEMENTDELTAS|PEXT2_MAXPLAYERS|PEXT2_PREDINFO|PEXT2_NEWSIZEENCODING|PEXT2_INFOBLOBS|PEXT2_STUNAWARE|PEXT2_VRINPUTS)
#define PEXT2_LERPTIME 0x00000400 //fitz-bloat parity. redefines UF_16BIT as UF_LERPEND in favour of length coding.
#define PEXT2_SERVERADVERTISE ~0u
#define PEXT2_CLIENTSUPPORT (PEXT2_PRYDONCURSOR|PEXT2_VOICECHAT|PEXT2_SETANGLEDELTA|PEXT2_REPLACEMENTDELTAS|PEXT2_MAXPLAYERS|PEXT2_PREDINFO|PEXT2_NEWSIZEENCODING|PEXT2_INFOBLOBS|PEXT2_STUNAWARE|PEXT2_VRINPUTS|PEXT2_LERPTIME) //warn if we see bits not listed here.
//EzQuake/Mvdsv extensions. (use ezquake name, to avoid confusion about .mvd format and its protocol differences)
#define EZPEXT1_FLOATENTCOORDS 0x00000001 //quirky - doesn't apply to broadcasts, just players+ents. this gives more precision, but will bug out if you try using it to increase map bounds in ways that may not be immediately apparent. iiuc this was added instead of fixing some inconsistent rounding...
@ -714,8 +717,8 @@ enum {
#define UF_EXTEND1 (1u<<7)
/*stuff which is common on ent spawning*/
#define UF_RESET (1u<<8)
#define UF_16BIT (1u<<9) /*within this update, frame/skin/model is 16bit, not part of the deltaing itself*/
#define UF_RESET (1u<<8) /*client will reset entire strict to its baseline*/
#define UF_16BIT_LERPTIME (1u<<9) /*either included frame/skin/model is 16bit (not part of the deltaing itself), or there's nextthink info*/
#define UF_MODEL (1u<<10)
#define UF_SKIN (1u<<11)
#define UF_COLORMAP (1u<<12)
@ -738,9 +741,9 @@ enum {
#define UF_FATNESS (1u<<26)
#define UF_MODELINDEX2 (1u<<27)
#define UF_GRAVITYDIR (1u<<28)
#define UF_EFFECTS2 (1u<<29)
#define UF_UNUSED2 (1u<<30)
#define UF_UNUSED1 (1u<<31)
#define UF_EFFECTS2_OLD (1u<<29) /*specified >8bit effects, replaced with variable length*/
#define UF_UNUSED1 (1u<<30)
#define UF_EXTEND4 (1u<<31)
/*these flags are generally not deltaed as they're changing constantly*/
#define UFP_FORWARD (1u<<0)
@ -753,7 +756,7 @@ enum {
#define UFP_WEAPONFRAME_OLD (1u<<7) //no longer used. just a stat now that I rewrote stat deltas.
#define UFP_VIEWANGLE (1u<<7)
#define UF_REMOVE UF_16BIT /*special flag, slightly more compact (we can reuse the 16bit flag as its not important)*/
#define UF_SV_REMOVE UF_16BIT_LERPTIME /*special flag - lerptime isn't delta tracked serverside (reset sent as required with other fields)*/
@ -1220,7 +1223,7 @@ typedef struct entity_state_s
qbyte lightstyle;
qbyte lightpflags;
unsigned short tagindex;
unsigned short tagindex; //~0 == weird portal thing.
unsigned int tagentity;

View File

@ -7290,7 +7290,7 @@ static void QCBUILTIN PF_checkextension (pubprogfuncs_t *prinst, struct globalva
}
else if (ext->extensioncheck)
{
extcheck_t check = {prinst->parms->user, Net_PextMask(PROTOCOL_VERSION_FTE1, false), Net_PextMask(PROTOCOL_VERSION_FTE2, false)};
extcheck_t check = {prinst->parms->user, Net_PextMask(PROTOCOL_VERSION_FTE1, false)&PEXT_SERVERADVERTISE, Net_PextMask(PROTOCOL_VERSION_FTE2, false)&PEXT2_SERVERADVERTISE};
if (!ext->extensioncheck(&check))
return; //blocked by some setting somewhere, somehow.
}
@ -12334,7 +12334,7 @@ void PR_SVExtensionList_f(void)
int num;
char biissues[8192];
extcheck_t extcheck = {&sv.world, Net_PextMask(PROTOCOL_VERSION_FTE1, false), Net_PextMask(PROTOCOL_VERSION_FTE2, false)};
extcheck_t extcheck = {&sv.world, Net_PextMask(PROTOCOL_VERSION_FTE1, false)&PEXT_SERVERADVERTISE, Net_PextMask(PROTOCOL_VERSION_FTE2, false)&PEXT2_SERVERADVERTISE};
#define SHOW_ACTIVEEXT 1
#define SHOW_ACTIVEBI 2

View File

@ -1069,7 +1069,7 @@ void SV_Map_f (void)
host_client->sentents.num_entities = 0;
host_client->ratetime = 0;
if (host_client->pendingdeltabits)
host_client->pendingdeltabits[0] = UF_REMOVE;
host_client->pendingdeltabits[0] = UF_SV_REMOVE;
if (flushparms)
{
@ -2156,7 +2156,15 @@ static void SV_Status_f (void)
if (NET_GetRates(svs.sockets, &pi, &po, &bi, &bo))
Con_TPrintf("packets,bytes/sec: in: %g %g out: %g %g\n", pi, bi, po, bo); //not relevent as a limit.
Con_TPrintf("server uptime : %s\n", ShowTime(realtime));
Con_TPrintf("public : %s\n", sv_public.value?"yes":"no");
if (sv_public.ival < 0)
s = "hidden";
else if (sv_public.ival == 2)
s = "hole punching";
else if (sv_public.ival)
s = "direct";
else
s = "private";
Con_TPrintf("public : %s\n", s);
switch(svs.gametype)
{
#ifdef Q3SERVER

View File

@ -937,13 +937,14 @@ void SVQW_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg,
MSG_WriteByte (msg, (to->effects&0xff00)>>8);
}
/*special flags which are slightly more compact. these are 'wasted' as part of the delta itself*/
#define UF_REMOVE UF_16BIT /*says we removed the entity in this frame*/
#define UF_MOVETYPE UF_EFFECTS2 /*this flag isn't present in the header itself*/
#define UF_RESET2 UF_EXTEND1 /*so new ents are reset 3 times to avoid weird baselines*/
//#define UF_UNUSED UF_EXTEND2 /**/
#define UF_WEAPONFRAME_OLD UF_EXTEND2
#define UF_VIEWANGLES UF_EXTEND3 /**/
/*special flags which are slightly more compact. these are 'wasted' as part of the delta itself. These meanings will not be transmitted.*/
#define UF_SV_REMOVE UF_16BIT_LERPTIME /*says we removed the entity in this frame*/
#define UF_SV_RESET2 UF_EXTEND1 /*so new ents are reset 3 times to avoid weird baselines*/
/*we need some extra bits for the predinfo section too...*/
#define UF_SV_WEAPONFRAME_OLD UF_EXTEND2
#define UF_SV_VIEWANGLES UF_EXTEND3 /**/
#define UF_SV_MOVETYPE UF_EXTEND4 /*this flag isn't present in the header itself*/
#define UF_SV_ALLFLAGS (UF_SV_REMOVE|UF_SV_RESET2|UF_SV_WEAPONFRAME_OLD|UF_SV_VIEWANGLES|UF_SV_MOVETYPE)
static unsigned int SVFTE_DeltaPredCalcBits(entity_state_t *from, entity_state_t *to)
{
@ -969,14 +970,14 @@ static unsigned int SVFTE_DeltaPredCalcBits(entity_state_t *from, entity_state_t
return bits;
}
static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, qbyte *frombonedata, entity_state_t *to, qbyte *tobonedata)
static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, qbyte *frombonedata, entity_state_t *to, qbyte *tobonedata, unsigned int pext2)
{
unsigned int bits = 0;
if (from->u.q1.pmovetype != to->u.q1.pmovetype)
bits |= UF_PREDINFO|UF_MOVETYPE;
if (from->u.q1.weaponframe != to->u.q1.weaponframe)
bits |= UF_PREDINFO|UF_WEAPONFRAME_OLD;
bits |= UF_PREDINFO|UF_SV_MOVETYPE;
if (from->u.q1.weaponframe != to->u.q1.weaponframe && !(pext2 & PEXT2_PREDINFO))
bits |= UF_PREDINFO|UF_SV_WEAPONFRAME_OLD;
if (to->u.q1.pmovetype)
{
if (SVFTE_DeltaPredCalcBits(from, to))
@ -1033,10 +1034,13 @@ static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, qbyte *frombonedat
if (to->hexen2flags != from->hexen2flags || to->abslight != from->abslight)
bits |= UF_DRAWFLAGS;
if (to->bonecount != from->bonecount || (to->bonecount && memcmp(frombonedata+from->boneoffset, tobonedata+to->boneoffset, to->bonecount*sizeof(short)*7)))
bits |= UF_BONEDATA;
if (!to->bonecount && (to->basebone != from->basebone || to->baseframe != from->baseframe))
bits |= UF_BONEDATA;
if (pext2 & PEXT2_NEWSIZEENCODING)
{ //don't flag it unless its actually present.
if (to->bonecount != from->bonecount || (to->bonecount && memcmp(frombonedata+from->boneoffset, tobonedata+to->boneoffset, to->bonecount*sizeof(short)*7)))
bits |= UF_BONEDATA;
if (!to->bonecount && (to->basebone != from->basebone || to->baseframe != from->baseframe))
bits |= UF_BONEDATA;
}
if (to->colormod[0]!=from->colormod[0]||to->colormod[1]!=from->colormod[1]||to->colormod[2]!=from->colormod[2])
bits |= UF_COLORMOD;
@ -1065,30 +1069,30 @@ static unsigned int SVFTE_DeltaCalcBits(entity_state_t *from, qbyte *frombonedat
static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_t *msg, unsigned int pext2, unsigned int ezext1, qbyte *boneptr)
{
unsigned int predbits = 0;
if (bits & UF_MOVETYPE)
if (bits & UF_SV_MOVETYPE)
{
bits &= ~UF_MOVETYPE;
bits &= ~UF_SV_MOVETYPE;
predbits |= UFP_MOVETYPE;
}
if (pext2 & PEXT2_PREDINFO)
{
if (bits & UF_VIEWANGLES)
if (bits & UF_SV_VIEWANGLES)
{
bits &= ~UF_VIEWANGLES;
bits &= ~UF_SV_VIEWANGLES;
bits |= UF_PREDINFO;
predbits |= UFP_VIEWANGLE;
}
}
else
{
if (bits & UF_VIEWANGLES)
if (bits & UF_SV_VIEWANGLES)
{
bits &= ~UF_VIEWANGLES;
bits &= ~UF_SV_VIEWANGLES;
bits |= UF_PREDINFO;
}
if (bits & UF_WEAPONFRAME_OLD)
if (bits & UF_SV_WEAPONFRAME_OLD)
{
bits &= ~UF_WEAPONFRAME_OLD;
bits &= ~UF_SV_WEAPONFRAME_OLD;
predbits |= UFP_WEAPONFRAME_OLD;
}
}
@ -1096,21 +1100,37 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
if (!(pext2 & PEXT2_NEWSIZEENCODING)) //was added at the same time
bits &= ~UF_BONEDATA;
/*check if we need more precision*/
if ((bits & UF_MODEL) && state->modelindex > 255)
bits |= UF_16BIT;
if ((bits & UF_SKIN) && state->skinnum > 255)
bits |= UF_16BIT;
if ((bits & UF_FRAME) && state->frame > 255)
bits |= UF_16BIT;
#ifdef _DEBUG
if (bits & UF_SV_ALLFLAGS) //if any of these are set here then we're bloating where we shouldn't be.
Host_EndGame("Server-Only bits shouldn't be set - %#x\n", bits & UF_SV_ALLFLAGS);
#endif
/*convert effects bits to higher lengths if needed*/
if (bits & UF_EFFECTS)
if (pext2 & PEXT2_LERPTIME)
{
if (state->effects & 0xffff0000) /*both*/
bits |= UF_EFFECTS | UF_EFFECTS2;
else if (state->effects & 0x0000ff00) /*2 only*/
bits = (bits & ~UF_EFFECTS) | UF_EFFECTS2;
if (bits & (UF_FRAME|UF_MODEL|UF_RESET|UF_ANGLESXZ|UF_ANGLESY))
if (state->lerpend > sv.world.physicstime)
bits |= UF_16BIT_LERPTIME;
}
else
{
/*check if we need more precision*/
if ((bits & UF_MODEL) && state->modelindex > 255)
bits |= UF_16BIT_LERPTIME;
if ((bits & UF_MODELINDEX2) && state->modelindex2 > 255)
bits |= UF_16BIT_LERPTIME;
if ((bits & UF_SKIN) && state->skinnum > 255)
bits |= UF_16BIT_LERPTIME;
if ((bits & UF_FRAME) && state->frame > 255)
bits |= UF_16BIT_LERPTIME;
/*convert effects bits to higher lengths if needed*/
if (bits & UF_EFFECTS)
{
if (state->effects & 0xffff0000) /*both*/
bits |= UF_EFFECTS | UF_EFFECTS2_OLD;
else if (state->effects & 0x0000ff00) /*2 only*/
bits = (bits & ~UF_EFFECTS) | UF_EFFECTS2_OLD;
}
}
if (bits & 0xff000000)
bits |= UF_EXTEND3;
@ -1129,7 +1149,9 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
if (bits & UF_FRAME)
{
if (bits & UF_16BIT)
if (pext2 & PEXT2_LERPTIME)
MSG_WriteULEB128(msg, state->frame);
else if (bits & UF_16BIT_LERPTIME)
MSG_WriteShort(msg, state->frame);
else
MSG_WriteByte(msg, state->frame);
@ -1177,12 +1199,27 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
MSG_WriteAngle(msg, state->angles[1]);
}
if ((bits & (UF_EFFECTS|UF_EFFECTS2)) == (UF_EFFECTS|UF_EFFECTS2))
MSG_WriteLong(msg, state->effects);
else if (bits & UF_EFFECTS2)
MSG_WriteShort(msg, state->effects);
else if (bits & UF_EFFECTS)
MSG_WriteByte(msg, state->effects);
if (pext2 & PEXT2_LERPTIME)
{
if (bits & UF_16BIT_LERPTIME)
{
int t = (state->lerpend - sv.world.physicstime)*1000;
MSG_WriteULEB128(msg, max(0, t));
}
if (bits & UF_EFFECTS)
MSG_WriteULEB128(msg, state->effects);
// if (bits & UF_EFFECTS2)
// MSG_WriteSomething(msg, state->something);
}
else
{
if ((bits & (UF_EFFECTS|UF_EFFECTS2_OLD)) == (UF_EFFECTS|UF_EFFECTS2_OLD))
MSG_WriteLong(msg, state->effects);
else if (bits & UF_EFFECTS2_OLD)
MSG_WriteShort(msg, state->effects);
else if (bits & UF_EFFECTS)
MSG_WriteByte(msg, state->effects);
}
if (bits & UF_PREDINFO)
{
@ -1237,20 +1274,29 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
if (bits & UF_MODEL)
{
if (bits & UF_16BIT)
if (pext2 & PEXT2_LERPTIME)
MSG_WriteULEB128(msg, state->modelindex);
else if (bits & UF_16BIT_LERPTIME)
MSG_WriteShort(msg, state->modelindex);
else
MSG_WriteByte(msg, state->modelindex);
}
if (bits & UF_SKIN)
{
if (bits & UF_16BIT)
if (pext2 & PEXT2_LERPTIME)
MSG_WriteULEB128(msg, state->skinnum+64); //biased for negative content overrides.
else if (bits & UF_16BIT_LERPTIME)
MSG_WriteShort(msg, state->skinnum);
else
MSG_WriteByte(msg, state->skinnum);
}
if (bits & UF_COLORMAP)
MSG_WriteByte(msg, state->colormap & 0xff);
{
if (pext2 & PEXT2_LERPTIME)
MSG_WriteULEB128(msg, state->colormap);
else
MSG_WriteByte(msg, state->colormap & 0xff);
}
if (bits & UF_SOLID)
{
@ -1280,7 +1326,12 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
}
if (bits & UF_FLAGS)
MSG_WriteByte(msg, state->dpflags);
{
if (pext2 & PEXT2_LERPTIME)
MSG_WriteULEB128(msg, state->dpflags);
else
MSG_WriteByte(msg, state->dpflags);
}
if (bits & UF_ALPHA)
MSG_WriteByte(msg, state->trans);
@ -1306,8 +1357,16 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
}
if (bfl & 0x40)
{
MSG_WriteByte(msg, state->basebone);
MSG_WriteShort(msg, state->baseframe);
if (pext2 & PEXT2_LERPTIME)
{
MSG_WriteULEB128(msg, state->basebone);
MSG_WriteULEB128(msg, state->baseframe);
}
else
{
MSG_WriteByte(msg, state->basebone);
MSG_WriteShort(msg, state->baseframe);
}
}
}
if (bits & UF_DRAWFLAGS)
@ -1319,7 +1378,10 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
if (bits & UF_TAGINFO)
{
MSG_WriteEntity(msg, state->tagentity);
MSG_WriteByte(msg, state->tagindex&0xff);
if (pext2 & PEXT2_LERPTIME)
MSG_WriteULEB128(msg, state->tagindex+1); //biased when sending to allow for our -1==portal thing
else
MSG_WriteByte(msg, state->tagindex&0xff);
}
if (bits & UF_LIGHT)
{
@ -1327,12 +1389,20 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
MSG_WriteShort (msg, state->light[1]);
MSG_WriteShort (msg, state->light[2]);
MSG_WriteShort (msg, state->light[3]);
MSG_WriteByte (msg, state->lightstyle);
if (pext2 & PEXT2_LERPTIME)
MSG_WriteULEB128(msg, state->lightstyle);
else
MSG_WriteByte (msg, state->lightstyle);
MSG_WriteByte (msg, state->lightpflags);
}
if (bits & UF_TRAILEFFECT)
{
if (state->u.q1.emiteffectnum)
if (pext2 & PEXT2_LERPTIME)
{
MSG_WriteULEB128(msg, state->u.q1.traileffectnum);
MSG_WriteULEB128(msg, state->u.q1.emiteffectnum);
}
else if (state->u.q1.emiteffectnum)
{
MSG_WriteShort(msg, (state->u.q1.traileffectnum & 0x3fff) | 0x8000);
MSG_WriteShort(msg, (state->u.q1.emiteffectnum & 0x3fff));
@ -1356,10 +1426,12 @@ static void SVFTE_WriteUpdate(unsigned int bits, entity_state_t *state, sizebuf_
MSG_WriteByte(msg, state->glowmod[2]);
}
if (bits & UF_FATNESS)
MSG_WriteByte(msg, state->fatness);
MSG_WriteChar(msg, state->fatness);
if (bits & UF_MODELINDEX2)
{
if (bits & UF_16BIT)
if (pext2 & PEXT2_LERPTIME)
MSG_WriteULEB128(msg, state->modelindex2);
else if (bits & UF_16BIT_LERPTIME)
MSG_WriteShort(msg, state->modelindex2);
else
MSG_WriteByte(msg, state->modelindex2);
@ -1378,7 +1450,7 @@ void SVFTE_EmitBaseline(entity_state_t *to, qboolean numberisimportant, sizebuf_
unsigned int bits;
if (numberisimportant)
MSG_WriteEntity(msg, to->number);
bits = UF_RESET | SVFTE_DeltaCalcBits(&nullentitystate, NULL, to, NULL);
bits = UF_RESET | SVFTE_DeltaCalcBits(&nullentitystate, NULL, to, NULL, pext2);
SVFTE_WriteUpdate(bits, to, msg, pext2, ezext, NULL);
}
@ -1408,17 +1480,17 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
return false;
if (client->delta_sequence < 0)
client->pendingdeltabits[0] = UF_REMOVE;
client->pendingdeltabits[0] = UF_SV_REMOVE;
//if we're clearing the list and starting from scratch, just wipe all lingering state
if (client->pendingdeltabits[0] & UF_REMOVE)
if (client->pendingdeltabits[0] & UF_SV_REMOVE)
{
for (j = 0; j < client->sentents.num_entities; j++)
{
client->sentents.entities[j].number = 0;
client->pendingdeltabits[j] = 0;
}
client->pendingdeltabits[0] = UF_REMOVE;
client->pendingdeltabits[0] = UF_SV_REMOVE;
}
//expand client's entstate list
@ -1467,7 +1539,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
e = EDICT_NUM_PB(svprogfuncs, o->number);
if (!((int)e->xv->pvsflags & PVSF_NOREMOVE))
{
client->pendingdeltabits[j] = UF_REMOVE;
client->pendingdeltabits[j] = UF_SV_REMOVE;
o->number = 0; /*dead*/
o->bonecount = 0; /*don't waste cycles*/
}
@ -1484,14 +1556,14 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
if (!o->number)
{
/*flag it for reset, we can add the extra bits later once we get around to sending it*/
client->pendingdeltabits[j] = UF_RESET | UF_RESET2;
client->pendingdeltabits[j] = UF_RESET | UF_SV_RESET2;
}
else
{
//its valid, make sure we don't have a stale/resent remove, and do a cheap reset due to uncertainty.
if (client->pendingdeltabits[j] & UF_REMOVE)
client->pendingdeltabits[j] = (client->pendingdeltabits[j] & ~UF_REMOVE) | UF_RESET2;
client->pendingdeltabits[j] |= SVFTE_DeltaCalcBits(o, oldbonedata, n, to->bonedata);
if (client->pendingdeltabits[j] & UF_SV_REMOVE)
client->pendingdeltabits[j] = (client->pendingdeltabits[j] & ~UF_SV_REMOVE) | UF_SV_RESET2;
client->pendingdeltabits[j] |= SVFTE_DeltaCalcBits(o, oldbonedata, n, to->bonedata, client->fteprotocolextensions2);
//even if prediction is disabled, we want to force velocity info to be sent for the local player. This is used by view bob and things.
if (client->edict && j == client->edict->entnum && (n->u.q1.velocity[0] || n->u.q1.velocity[1] || n->u.q1.velocity[2]))
client->pendingdeltabits[j] |= UF_PREDINFO;
@ -1504,7 +1576,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
client->pendingdeltabits[j] |= UF_ANGLESXZ;
if (o->u.q1.vangle[1] != n->u.q1.vangle[1])
client->pendingdeltabits[j] |= UF_ANGLESY;
client->pendingdeltabits[j] |= UF_VIEWANGLES;
client->pendingdeltabits[j] |= UF_SV_VIEWANGLES;
}
}
*o = *n;
@ -1526,7 +1598,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
e = EDICT_NUM_PB(svprogfuncs, o->number);
if (!((int)e->xv->pvsflags & PVSF_NOREMOVE))
{
client->pendingdeltabits[j] = UF_REMOVE;
client->pendingdeltabits[j] = UF_SV_REMOVE;
o->number = 0; /*dead*/
o->bonecount = 0; /*don't waste cycles*/
}
@ -1602,19 +1674,19 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
// Con_Printf("Gen sequence %i\n", sequence);
MSG_WriteFloat(msg, sv.world.physicstime);
if (client->pendingdeltabits[0] & UF_REMOVE)
if (client->pendingdeltabits[0] & UF_SV_REMOVE)
{
SV_EmitDeltaEntIndex(msg, 0, true, true);
resend[outno].bits = UF_REMOVE;
resend[outno].bits = UF_SV_REMOVE;
resend[outno].flags = 0;
resend[outno++].entnum = 0;
client->pendingdeltabits[0] &= ~UF_REMOVE;
client->pendingdeltabits[0] &= ~UF_SV_REMOVE;
}
for(j = 1; j < client->sentents.num_entities; j++)
{
bits = client->pendingdeltabits[j];
if (!(bits & ~UF_RESET2)) //skip while there's nothing to send (skip reset2 if there's no other changes, its only to reduce chances of the client getting 'new' entities containing just an origin)*/
if (!(bits & ~UF_SV_RESET2)) //skip while there's nothing to send (skip reset2 if there's no other changes, its only to reduce chances of the client getting 'new' entities containing just an origin)*/
continue;
if (msg->cursize + 52 > msg->maxsize)
{
@ -1630,10 +1702,10 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
outmax = frame->maxresend;
}
if (bits & UF_REMOVE)
if (bits & UF_SV_REMOVE)
{ //if reset is set, then reset was set eroneously.
SV_EmitDeltaEntIndex(msg, j, true, true);
resend[outno].bits = UF_REMOVE;
resend[outno].bits = UF_SV_REMOVE;
// Con_Printf("REMOVE %i @ %i\n", j, sequence);
}
else if (client->sentents.entities[j].number) /*only send a new copy of the ent if they actually have one already*/
@ -1643,18 +1715,18 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
if (j < client->nextdeltaindex && j > svs.allocated_client_slots)
continue;
if (bits & UF_RESET2)
if (bits & UF_SV_RESET2)
{
/*if reset2, then this is the second packet sent to the client and should have a forced reset (but which isn't tracked)*/
resend[outno].bits = bits & ~UF_RESET2;
bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM_PB(svprogfuncs, j)->baseline, NULL, &client->sentents.entities[j], client->sentents.bonedata);
resend[outno].bits = bits & ~UF_SV_RESET2;
bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM_PB(svprogfuncs, j)->baseline, NULL, &client->sentents.entities[j], client->sentents.bonedata, client->fteprotocolextensions2);
// Con_Printf("RESET2 %i @ %i\n", j, sequence);
}
else if (bits & UF_RESET)
{
/*flag the entity for the next packet, so we always get two resets when it appears, to reduce the effects of packetloss on seeing rockets etc*/
client->pendingdeltabits[j] = UF_RESET2;
bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM_PB(svprogfuncs, j)->baseline, NULL, &client->sentents.entities[j], client->sentents.bonedata);
client->pendingdeltabits[j] = UF_SV_RESET2;
bits = UF_RESET | SVFTE_DeltaCalcBits(&EDICT_NUM_PB(svprogfuncs, j)->baseline, NULL, &client->sentents.entities[j], client->sentents.bonedata, client->fteprotocolextensions2);
resend[outno].bits = UF_RESET;
// Con_Printf("RESET %i @ %i\n", j, sequence);
}
@ -3551,6 +3623,9 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli
if (state->effects & EF_FULLBRIGHT) //wrap the field for fte clients (this is horrible)
state->hexen2flags |= MLS_FULLBRIGHT;
if (ent->v->nextthink>sv.world.physicstime)
state->lerpend = ent->v->nextthink;
#ifdef NQPROT
if (client && !ISQWCLIENT(client))
{

View File

@ -1626,7 +1626,7 @@ qboolean SVC_GetChallenge (qboolean respond_dp)
{
unsigned int mask;
//tell the client what fte extensions we support
mask = Net_PextMask(PROTOCOL_VERSION_FTE1, false);
mask = Net_PextMask(PROTOCOL_VERSION_FTE1, false)&PEXT_SERVERADVERTISE;
if (mask)
{
lng = LittleLong(PROTOCOL_VERSION_FTE1);
@ -1638,7 +1638,7 @@ qboolean SVC_GetChallenge (qboolean respond_dp)
over+=sizeof(lng);
}
//tell the client what fte extensions we support
mask = Net_PextMask(PROTOCOL_VERSION_FTE2, false);
mask = Net_PextMask(PROTOCOL_VERSION_FTE2, false)&PEXT2_SERVERADVERTISE;
if (mask)
{
lng = LittleLong(PROTOCOL_VERSION_FTE2);
@ -2029,8 +2029,8 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
}
}
client->fteprotocolextensions &= Net_PextMask(PROTOCOL_VERSION_FTE1, ISNQCLIENT(client));
client->fteprotocolextensions2 &= Net_PextMask(PROTOCOL_VERSION_FTE2, ISNQCLIENT(client));
client->fteprotocolextensions &= Net_PextMask(PROTOCOL_VERSION_FTE1, ISNQCLIENT(client)) & PEXT_SERVERADVERTISE;
client->fteprotocolextensions2 &= Net_PextMask(PROTOCOL_VERSION_FTE2, ISNQCLIENT(client)) & PEXT2_SERVERADVERTISE;
client->ezprotocolextensions1 &= Net_PextMask(PROTOCOL_VERSION_EZQUAKE1, ISNQCLIENT(client)) & EZPEXT1_SERVERADVERTISE;
client->zquake_extensions &= SERVER_SUPPORTED_Z_EXTENSIONS;
@ -2217,7 +2217,7 @@ void SV_ClientProtocolExtensionsChanged(client_t *client)
}
//make sure the reset is sent.
client->pendingdeltabits[0] = UF_REMOVE;
client->pendingdeltabits[0] = UF_SV_REMOVE;
}
else if (ISNQCLIENT(client))
{

View File

@ -6257,10 +6257,10 @@ void SV_Pext_f(void)
switch(strtoul(tag, NULL, 0))
{
case PROTOCOL_VERSION_FTE1:
host_client->fteprotocolextensions = strtoul(val, NULL, 0) & Net_PextMask(PROTOCOL_VERSION_FTE1, ISNQCLIENT(host_client));
host_client->fteprotocolextensions = strtoul(val, NULL, 0) & Net_PextMask(PROTOCOL_VERSION_FTE1, ISNQCLIENT(host_client)) & PEXT_SERVERADVERTISE;
break;
case PROTOCOL_VERSION_FTE2:
host_client->fteprotocolextensions2 = strtoul(val, NULL, 0) & Net_PextMask(PROTOCOL_VERSION_FTE2, ISNQCLIENT(host_client));
host_client->fteprotocolextensions2 = strtoul(val, NULL, 0) & Net_PextMask(PROTOCOL_VERSION_FTE2, ISNQCLIENT(host_client)) & PEXT2_SERVERADVERTISE;
break;
case PROTOCOL_VERSION_EZQUAKE1:
host_client->ezprotocolextensions1 = strtoul(val, NULL, 0) & Net_PextMask(PROTOCOL_VERSION_EZQUAKE1, ISNQCLIENT(host_client)) & EZPEXT1_SERVERADVERTISE;
@ -7979,7 +7979,7 @@ static double SVFTE_ExecuteClientMove(client_t *controller)
{
unsigned int e;
if (controller->pendingdeltabits)
controller->pendingdeltabits[0] = UF_REMOVE;
controller->pendingdeltabits[0] = UF_SV_REMOVE;
if (host_client->pendingcsqcbits)
for (e = 1; e < host_client->max_net_ents; e++)
if (host_client->pendingcsqcbits[e] & SENDFLAGS_PRESENT)
@ -8421,7 +8421,7 @@ void SV_ExecuteClientMessage (client_t *cl)
{
unsigned int e;
if (cl->pendingdeltabits)
cl->pendingdeltabits[0] = UF_REMOVE;
cl->pendingdeltabits[0] = UF_SV_REMOVE;
if (host_client->pendingcsqcbits)
for (e = 1; e < host_client->max_net_ents; e++)
if (host_client->pendingcsqcbits[e] & SENDFLAGS_PRESENT)
@ -9046,7 +9046,7 @@ void SVNQ_ExecuteClientMessage (client_t *cl)
{
unsigned int e;
if (cl->pendingdeltabits)
cl->pendingdeltabits[0] = UF_REMOVE;
cl->pendingdeltabits[0] = UF_SV_REMOVE;
if (host_client->pendingcsqcbits)
for (e = 1; e < host_client->max_net_ents; e++)
if (host_client->pendingcsqcbits[e] & SENDFLAGS_PRESENT)