X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=protocol.c;h=e9d9489fa65699ff6ceb66bb474a9fd3aafae519;hp=fc52a03c16c78ad46d234dc2704e760fb26b93ac;hb=2075ae43356d724bae305ce8fd36ea570718b14a;hpb=53b4417a2ab67bf1e9fa91ad3c1d9daf42e92e7f diff --git a/protocol.c b/protocol.c index fc52a03c..e9d9489f 100644 --- a/protocol.c +++ b/protocol.c @@ -6,10 +6,17 @@ #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. 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 = { @@ -279,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] = 1; // 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. } } } @@ -395,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] = 1; - client->csqcentitysendflags[i] = 0xFFFFFF; - } + client->csqcentityscope[i] |= SCOPE_ASSUMED_EXISTING; // FORCE REMOVE. else client->csqcentitysendflags[i] |= recoversendflags[i]; } @@ -461,18 +459,19 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers end = *n; for (;number < end;number++) { - if (client->csqcentityscope[number]) - { - client->csqcentityscope[number] = 1; - 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] = 2; - else if (client->csqcentityscope[number]) + client->csqcentityscope[number] |= SCOPE_WANTUPDATE; + else { - client->csqcentityscope[number] = 1; + if (client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING) + client->csqcentityscope[number] |= SCOPE_WANTREMOVE; client->csqcentitysendflags[number] = 0xFFFFFF; } number++; @@ -480,44 +479,25 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers end = client->csqcnumedicts; for (;number < end;number++) { - if (client->csqcentityscope[number]) - { - client->csqcentityscope[number] = 1; - 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; } - /* - // mark all scope entities as remove - for (number = 1;number < client->csqcnumedicts;number++) - if (client->csqcentityscope[number]) - client->csqcentityscope[number] = 1; - // keep visible entities - for (i = 0, n = numbers;i < numnumbers;i++, n++) - { - number = *n; - ed = prog->edicts + number; - if (PRVM_serveredictfunction(ed, SendEntity)) - client->csqcentityscope[number] = 2; - } - */ - // now try to emit the entity updates // (FIXME: prioritize by distance?) end = client->csqcnumedicts; for (number = 1;number < end;number++) { - if (!client->csqcentityscope[number]) - 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] == 1) + 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) @@ -529,12 +509,11 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers { ENTITYSIZEPROFILING_START(msg, number, 0); MSG_WriteShort(msg, (unsigned short)number | 0x8000); - client->csqcentityscope[number] = 0; + 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) @@ -542,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] = 1; + + // 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; @@ -559,14 +548,46 @@ qboolean EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int maxsize, int numnumbers PRVM_serverglobaledict(self) = number; prog->ExecuteProgram(prog, PRVM_serveredictfunction(ed, SendEntity), "Null SendEntity\n"); msg->allowoverflow = false; - if(PRVM_G_FLOAT(OFS_RETURN) && msg->cursize + 2 <= maxsize) + if(!PRVM_G_FLOAT(OFS_RETURN)) + { + // Send rejected by CSQC. This means we want to remove it. + // CSQC requests we remove this one. + if (client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING) + { + msg->cursize = oldcursize2; + msg->overflowed = false; + MSG_WriteShort(msg, (unsigned short)number | 0x8000); + 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; + // and take note that we have begun the svc_csqcentities + // section of the packet + sectionstarted = 1; + ENTITYSIZEPROFILING_END(msg, number, 0); + 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) { // an update has been successfully written client->csqcentitysendflags[number] = 0; 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; @@ -2519,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++) @@ -2811,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;