X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=protocol.c;h=e9d9489fa65699ff6ceb66bb474a9fd3aafae519;hb=fae56f5debe83e993f8923fe52a86f27c997ea47;hp=7120e5460d2f5cf3f77c3281c08636f3f69aea91;hpb=b495453bb1678e02e9249f33558334415ec72fcb;p=xonotic%2Fdarkplaces.git diff --git a/protocol.c b/protocol.c index 7120e546..e9d9489f 100644 --- a/protocol.c +++ b/protocol.c @@ -6,14 +6,16 @@ #define ENTITYSIZEPROFILING_END(msg, num, flags) \ if(developer_networkentities.integer >= 2) \ { \ - prvm_edict_t *ed = prog->edicts + num; \ - Con_Printf("sent entity update of size %u for %d classname %s flags %d\n", (msg->cursize - entityprofiling_startsize), num, PRVM_serveredictstring(ed, classname) ? PRVM_GetString(prog, PRVM_serveredictstring(ed, classname)) : "(no classname)", flags); \ + prvm_edict_t *edict = prog->edicts + num; \ + Con_Printf("sent entity update of size %u for %d classname %s flags %d\n", (msg->cursize - entityprofiling_startsize), num, PRVM_serveredictstring(edict, classname) ? PRVM_GetString(prog, PRVM_serveredictstring(edict, classname)) : "(no classname)", flags); \ } -// CSQC entity scope values. -#define SCOPE_IGNORE 0 -#define SCOPE_REMOVE 1 -#define SCOPE_UPDATE 2 +// CSQC entity scope values. Bitflags! +#define SCOPE_WANTREMOVE 1 // Set if a remove has been scheduled. Never set together with WANTUPDATE. +#define SCOPE_WANTUPDATE 2 // Set if an update has been scheduled. +#define SCOPE_WANTSEND (SCOPE_WANTREMOVE | SCOPE_WANTUPDATE) +#define SCOPE_EXISTED_ONCE 4 // Set if the entity once existed. All these get resent on a full loss. +#define SCOPE_ASSUMED_EXISTING 8 // Set if the entity is currently assumed existing and therefore needs removes. // this is 88 bytes (must match entity_state_t in protocol.h) entity_state_t defaultstate = @@ -284,16 +286,12 @@ static void EntityFrameCSQC_LostAllFrames(client_t *client) n = client->csqcnumedicts; for(i = 0; i < n; ++i) { - if(client->csqcentityglobalhistory[i]) + if(client->csqcentityscope[i] & SCOPE_EXISTED_ONCE) { ed = prog->edicts + i; - if (PRVM_serveredictfunction(ed, SendEntity)) - client->csqcentitysendflags[i] |= 0xFFFFFF; // FULL RESEND - else // if it was ever sent to that client as a CSQC entity - { - client->csqcentityscope[i] = SCOPE_REMOVE; - client->csqcentitysendflags[i] |= 0xFFFFFF; - } + client->csqcentitysendflags[i] |= 0xFFFFFF; // FULL RESEND. We can't clear SCOPE_ASSUMED_EXISTING yet as this would cancel removes on a rejected send attempt. + if (!PRVM_serveredictfunction(ed, SendEntity)) // If it was ever sent to that client as a CSQC entity... + client->csqcentityscope[i] |= SCOPE_ASSUMED_EXISTING; // FORCE REMOVE. } } } @@ -400,12 +398,7 @@ void EntityFrameCSQC_LostFrame(client_t *client, int framenum) for(i = 0; i < client->csqcnumedicts; ++i) { if(recoversendflags[i] < 0) - { - // a remove got lost, then either send a remove or - if it was - // recreated later - a FULL update to make totally sure - client->csqcentityscope[i] = SCOPE_REMOVE; - client->csqcentitysendflags[i] = 0xFFFFFF; - } + client->csqcentityscope[i] |= SCOPE_ASSUMED_EXISTING; // FORCE REMOVE. else client->csqcentitysendflags[i] |= recoversendflags[i]; } @@ -466,18 +459,19 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers end = *n; for (;number < end;number++) { - if (client->csqcentityscope[number] != SCOPE_IGNORE) - { - client->csqcentityscope[number] = SCOPE_REMOVE; - client->csqcentitysendflags[number] = 0xFFFFFF; - } + client->csqcentityscope[number] &= ~SCOPE_WANTSEND; + if (client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING) + client->csqcentityscope[number] |= SCOPE_WANTREMOVE; + client->csqcentitysendflags[number] = 0xFFFFFF; } ed = prog->edicts + number; + client->csqcentityscope[number] &= ~SCOPE_WANTSEND; if (PRVM_serveredictfunction(ed, SendEntity)) - client->csqcentityscope[number] = SCOPE_UPDATE; - else if (client->csqcentityscope[number] != SCOPE_IGNORE) + client->csqcentityscope[number] |= SCOPE_WANTUPDATE; + else { - client->csqcentityscope[number] = SCOPE_REMOVE; + if (client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING) + client->csqcentityscope[number] |= SCOPE_WANTREMOVE; client->csqcentitysendflags[number] = 0xFFFFFF; } number++; @@ -485,11 +479,10 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers end = client->csqcnumedicts; for (;number < end;number++) { - if (client->csqcentityscope[number] != SCOPE_IGNORE) - { - client->csqcentityscope[number] = SCOPE_REMOVE; - client->csqcentitysendflags[number] = 0xFFFFFF; - } + client->csqcentityscope[number] &= ~SCOPE_WANTSEND; + if (client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING) + client->csqcentityscope[number] |= SCOPE_WANTREMOVE; + client->csqcentitysendflags[number] = 0xFFFFFF; } // now try to emit the entity updates @@ -497,17 +490,14 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers end = client->csqcnumedicts; for (number = 1;number < end;number++) { - if (client->csqcentityscope[number] == SCOPE_IGNORE) - continue; - sendflags = client->csqcentitysendflags[number]; - if (!sendflags) + if (!(client->csqcentityscope[number] & SCOPE_WANTSEND)) continue; if(db->num >= NUM_CSQCENTITIES_PER_FRAME) break; ed = prog->edicts + number; - // entity scope is either update (2) or remove (1) - if (client->csqcentityscope[number] == SCOPE_REMOVE) + if (client->csqcentityscope[number] & SCOPE_WANTREMOVE) // Also implies ASSUMED_EXISTING. { + // A removal. SendFlags have no power here. // write a remove message // first write the message identifier if needed if(!sectionstarted) @@ -516,16 +506,14 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers MSG_WriteByte(msg, svc_csqcentities); } // write the remove message - //FIXME implement this if(client has this entity) { ENTITYSIZEPROFILING_START(msg, number, 0); MSG_WriteShort(msg, (unsigned short)number | 0x8000); - client->csqcentityscope[number] = SCOPE_IGNORE; + client->csqcentityscope[number] &= ~(SCOPE_WANTSEND | SCOPE_ASSUMED_EXISTING); client->csqcentitysendflags[number] = 0xFFFFFF; // resend completely if it becomes active again db->entno[db->num] = number; db->sendflags[db->num] = -1; db->num += 1; - client->csqcentityglobalhistory[number] = 1; ENTITYSIZEPROFILING_END(msg, number, 0); } if (msg->cursize + 17 >= maxsize) @@ -533,15 +521,25 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers } else { - // write an update // save the cursize value in case we overflow and have to rollback int oldcursize = msg->cursize; - client->csqcentityscope[number] = SCOPE_REMOVE; + + // An update. + sendflags = client->csqcentitysendflags[number]; + // Nothing to send? FINE. + if (!sendflags) + continue; + // If it's a new entity, always assume sendflags 0xFFFFFF. + if (!(client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING)) + sendflags = 0xFFFFFF; + + // write an update if (PRVM_serveredictfunction(ed, SendEntity)) { if(!sectionstarted) MSG_WriteByte(msg, svc_csqcentities); { + int oldcursize2 = msg->cursize; ENTITYSIZEPROFILING_START(msg, number, sendflags); MSG_WriteShort(msg, number); msg->allowoverflow = true; @@ -552,21 +550,18 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers msg->allowoverflow = false; if(!PRVM_G_FLOAT(OFS_RETURN)) { - msg->cursize = oldcursize; - msg->overflowed = false; + // Send rejected by CSQC. This means we want to remove it. // CSQC requests we remove this one. - /*FIXME implement this - if(client has this entity) + if (client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING) { - if(!sectionstarted) - MSG_WriteByte(msg, svc_csqcentities); + msg->cursize = oldcursize2; + msg->overflowed = false; MSG_WriteShort(msg, (unsigned short)number | 0x8000); - client->csqcentityscope[number] = SCOPE_IGNORE; - client->csqcentitysendflags[number] = 0xFFFFFF; // resend completely if it becomes active again + client->csqcentityscope[number] &= ~(SCOPE_WANTSEND | SCOPE_ASSUMED_EXISTING); + client->csqcentitysendflags[number] = 0; db->entno[db->num] = number; db->sendflags[db->num] = -1; db->num += 1; - client->csqcentityglobalhistory[number] = 1; // and take note that we have begun the svc_csqcentities // section of the packet sectionstarted = 1; @@ -574,7 +569,14 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers if (msg->cursize + 17 >= maxsize) break; } - */ + else + { + // Nothing to do. Just don't do it again. + msg->cursize = oldcursize; + msg->overflowed = false; + client->csqcentityscope[number] &= ~SCOPE_WANTSEND; + client->csqcentitysendflags[number] = 0; + } continue; } else if(PRVM_G_FLOAT(OFS_RETURN) && msg->cursize + 2 <= maxsize) @@ -584,7 +586,8 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers db->entno[db->num] = number; db->sendflags[db->num] = sendflags; db->num += 1; - client->csqcentityglobalhistory[number] = 1; + client->csqcentityscope[number] &= ~SCOPE_WANTSEND; + client->csqcentityscope[number] |= SCOPE_EXISTED_ONCE | SCOPE_ASSUMED_EXISTING; // and take note that we have begun the svc_csqcentities // section of the packet sectionstarted = 1; @@ -2537,8 +2540,8 @@ static void EntityState5_ReadUpdate(entity_state_t *s, int number) if (!skeleton->relativetransforms || skeleton->model != model) { skeleton->model = model; - skeleton->relativetransforms = (matrix4x4_t *) Mem_Realloc(cls.levelmempool, skeleton->relativetransforms, sizeof(*skeleton->relativetransforms) * skeleton->model->num_bones); - for (bonenum = 0;bonenum < model->num_bones;bonenum++) + skeleton->relativetransforms = (matrix4x4_t *) Mem_Realloc(cls.levelmempool, skeleton->relativetransforms, sizeof(*skeleton->relativetransforms) * numbones); + for (bonenum = 0;bonenum < numbones;bonenum++) skeleton->relativetransforms[bonenum] = identitymatrix; } for (bonenum = 0;bonenum < numbones;bonenum++) @@ -2829,7 +2832,7 @@ void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum) d->packetlog[i].packetnumber = 0; } -qboolean EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database_t *d, int numstates, const entity_state_t **states, int viewentnum, int movesequence, qboolean need_empty) +qboolean EntityFrame5_WriteFrame(sizebuf_t *msg, int maxsize, entityframe5_database_t *d, int numstates, const entity_state_t **states, int viewentnum, unsigned int movesequence, qboolean need_empty) { prvm_prog_t *prog = SVVM_prog; const entity_state_t *n;