X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=protocol.c;h=837ad97bed27445f804927f334b6b94440882747;hp=be3d0d39d49734d19c46a6e0c8dbd67d4fa33d4f;hb=819ea19a0017f7af07baf3e65824d81379818d7b;hpb=c0959fa7bef17f6cdd4b7be3f78c903ee9aba508 diff --git a/protocol.c b/protocol.c index be3d0d39..837ad97b 100644 --- a/protocol.c +++ b/protocol.c @@ -47,6 +47,7 @@ struct protocolversioninfo_s } protocolversioninfo[] = { + { 3505, PROTOCOL_DARKPLACES8 , "DP8"}, { 3504, PROTOCOL_DARKPLACES7 , "DP7"}, { 3503, PROTOCOL_DARKPLACES6 , "DP6"}, { 3502, PROTOCOL_DARKPLACES5 , "DP5"}, @@ -108,7 +109,7 @@ void Protocol_Names(char *buffer, size_t buffersize) buffer[0] = 0; for (i = 0;protocolversioninfo[i].name;i++) { - if (i > 1) + if (i > 0) strlcat(buffer, " ", buffersize); strlcat(buffer, protocolversioninfo[i].name, buffersize); } @@ -191,375 +192,3 @@ void Protocol_WriteStatsReliable(void) } } } - -entity_state_t *EntityFrame4_GetReferenceEntity(entityframe4_database_t *d, int number) -{ - if (d->maxreferenceentities <= number) - { - int oldmax = d->maxreferenceentities; - entity_state_t *oldentity = d->referenceentity; - d->maxreferenceentities = (number + 15) & ~7; - d->referenceentity = (entity_state_t *)Mem_Alloc(d->mempool, d->maxreferenceentities * sizeof(*d->referenceentity)); - if (oldentity) - { - memcpy(d->referenceentity, oldentity, oldmax * sizeof(*d->referenceentity)); - Mem_Free(oldentity); - } - // clear the newly created entities - for (;oldmax < d->maxreferenceentities;oldmax++) - { - d->referenceentity[oldmax] = defaultstate; - d->referenceentity[oldmax].number = oldmax; - } - } - return d->referenceentity + number; -} - -void EntityFrame4_AddCommitEntity(entityframe4_database_t *d, const entity_state_t *s) -{ - // resize commit's entity list if full - if (d->currentcommit->maxentities <= d->currentcommit->numentities) - { - entity_state_t *oldentity = d->currentcommit->entity; - d->currentcommit->maxentities += 8; - d->currentcommit->entity = (entity_state_t *)Mem_Alloc(d->mempool, d->currentcommit->maxentities * sizeof(*d->currentcommit->entity)); - if (oldentity) - { - memcpy(d->currentcommit->entity, oldentity, d->currentcommit->numentities * sizeof(*d->currentcommit->entity)); - Mem_Free(oldentity); - } - } - d->currentcommit->entity[d->currentcommit->numentities++] = *s; -} - -entityframe4_database_t *EntityFrame4_AllocDatabase(mempool_t *pool) -{ - entityframe4_database_t *d; - d = (entityframe4_database_t *)Mem_Alloc(pool, sizeof(*d)); - d->mempool = pool; - EntityFrame4_ResetDatabase(d); - return d; -} - -void EntityFrame4_FreeDatabase(entityframe4_database_t *d) -{ - int i; - for (i = 0;i < MAX_ENTITY_HISTORY;i++) - if (d->commit[i].entity) - Mem_Free(d->commit[i].entity); - if (d->referenceentity) - Mem_Free(d->referenceentity); - Mem_Free(d); -} - -void EntityFrame4_ResetDatabase(entityframe4_database_t *d) -{ - int i; - d->referenceframenum = -1; - for (i = 0;i < MAX_ENTITY_HISTORY;i++) - d->commit[i].numentities = 0; - for (i = 0;i < d->maxreferenceentities;i++) - d->referenceentity[i] = defaultstate; -} - -int EntityFrame4_AckFrame(entityframe4_database_t *d, int framenum, int servermode) -{ - int i, j, found; - entity_database4_commit_t *commit; - if (framenum == -1) - { - // reset reference, but leave commits alone - d->referenceframenum = -1; - for (i = 0;i < d->maxreferenceentities;i++) - { - d->referenceentity[i] = defaultstate; - // if this is the server, remove commits - for (i = 0, commit = d->commit;i < MAX_ENTITY_HISTORY;i++, commit++) - commit->numentities = 0; - } - found = true; - } - else if (d->referenceframenum == framenum) - found = true; - else - { - found = false; - for (i = 0, commit = d->commit;i < MAX_ENTITY_HISTORY;i++, commit++) - { - if (commit->numentities && commit->framenum <= framenum) - { - if (commit->framenum == framenum) - { - found = true; - d->referenceframenum = framenum; - if (developer_networkentities.integer >= 3) - { - for (j = 0;j < commit->numentities;j++) - { - entity_state_t *s = EntityFrame4_GetReferenceEntity(d, commit->entity[j].number); - if (commit->entity[j].active != s->active) - { - if (commit->entity[j].active == ACTIVE_NETWORK) - Con_Printf("commit entity %i has become active (modelindex %i)\n", commit->entity[j].number, commit->entity[j].modelindex); - else - Con_Printf("commit entity %i has become inactive (modelindex %i)\n", commit->entity[j].number, commit->entity[j].modelindex); - } - *s = commit->entity[j]; - } - } - else - for (j = 0;j < commit->numentities;j++) - *EntityFrame4_GetReferenceEntity(d, commit->entity[j].number) = commit->entity[j]; - } - commit->numentities = 0; - } - } - } - if (developer_networkentities.integer >= 1) - { - Con_Printf("ack ref:%i database updated to: ref:%i commits:", framenum, d->referenceframenum); - for (i = 0;i < MAX_ENTITY_HISTORY;i++) - if (d->commit[i].numentities) - Con_Printf(" %i", d->commit[i].framenum); - Con_Print("\n"); - } - return found; -} - -void EntityFrame4_CL_ReadFrame(void) -{ - int i, n, cnumber, referenceframenum, framenum, enumber, done, stopnumber, skip = false; - entity_state_t *s; - entityframe4_database_t *d; - if (!cl.entitydatabase4) - cl.entitydatabase4 = EntityFrame4_AllocDatabase(cls.levelmempool); - d = cl.entitydatabase4; - // read the number of the frame this refers to - referenceframenum = MSG_ReadLong(&cl_message); - // read the number of this frame - framenum = MSG_ReadLong(&cl_message); - CL_NewFrameReceived(framenum); - // read the start number - enumber = (unsigned short) MSG_ReadShort(&cl_message); - if (developer_networkentities.integer >= 10) - { - Con_Printf("recv svc_entities num:%i ref:%i database: ref:%i commits:", framenum, referenceframenum, d->referenceframenum); - for (i = 0;i < MAX_ENTITY_HISTORY;i++) - if (d->commit[i].numentities) - Con_Printf(" %i", d->commit[i].framenum); - Con_Print("\n"); - } - if (!EntityFrame4_AckFrame(d, referenceframenum, false)) - { - Con_Print("EntityFrame4_CL_ReadFrame: reference frame invalid (VERY BAD ERROR), this update will be skipped\n"); - skip = true; - } - d->currentcommit = NULL; - for (i = 0;i < MAX_ENTITY_HISTORY;i++) - { - if (!d->commit[i].numentities) - { - d->currentcommit = d->commit + i; - d->currentcommit->framenum = framenum; - d->currentcommit->numentities = 0; - } - } - if (d->currentcommit == NULL) - { - Con_Printf("EntityFrame4_CL_ReadFrame: error while decoding frame %i: database full, reading but not storing this update\n", framenum); - skip = true; - } - done = false; - while (!done && !cl_message.badread) - { - // read the number of the modified entity - // (gaps will be copied unmodified) - n = (unsigned short)MSG_ReadShort(&cl_message); - if (n == 0x8000) - { - // no more entities in this update, but we still need to copy the - // rest of the reference entities (final gap) - done = true; - // read end of range number, then process normally - n = (unsigned short)MSG_ReadShort(&cl_message); - } - // high bit means it's a remove message - cnumber = n & 0x7FFF; - // if this is a live entity we may need to expand the array - if (cl.num_entities <= cnumber && !(n & 0x8000)) - { - cl.num_entities = cnumber + 1; - if (cnumber >= cl.max_entities) - CL_ExpandEntities(cnumber); - } - // add one (the changed one) if not done - stopnumber = cnumber + !done; - // process entities in range from the last one to the changed one - for (;enumber < stopnumber;enumber++) - { - if (skip || enumber >= cl.num_entities) - { - if (enumber == cnumber && (n & 0x8000) == 0) - { - entity_state_t tempstate; - EntityState_ReadFields(&tempstate, EntityState_ReadExtendBits()); - } - continue; - } - // slide the current into the previous slot - cl.entities[enumber].state_previous = cl.entities[enumber].state_current; - // copy a new current from reference database - cl.entities[enumber].state_current = *EntityFrame4_GetReferenceEntity(d, enumber); - s = &cl.entities[enumber].state_current; - // if this is the one to modify, read more data... - if (enumber == cnumber) - { - if (n & 0x8000) - { - // simply removed - if (developer_networkentities.integer >= 2) - Con_Printf("entity %i: remove\n", enumber); - *s = defaultstate; - } - else - { - // read the changes - if (developer_networkentities.integer >= 2) - Con_Printf("entity %i: update\n", enumber); - s->active = ACTIVE_NETWORK; - EntityState_ReadFields(s, EntityState_ReadExtendBits()); - } - } - else if (developer_networkentities.integer >= 4) - Con_Printf("entity %i: copy\n", enumber); - // set the cl.entities_active flag - cl.entities_active[enumber] = (s->active == ACTIVE_NETWORK); - // set the update time - s->time = cl.mtime[0]; - // fix the number (it gets wiped occasionally by copying from defaultstate) - s->number = enumber; - // check if we need to update the lerp stuff - if (s->active == ACTIVE_NETWORK) - CL_MoveLerpEntityStates(&cl.entities[enumber]); - // add this to the commit entry whether it is modified or not - if (d->currentcommit) - EntityFrame4_AddCommitEntity(d, &cl.entities[enumber].state_current); - // print extra messages if desired - if (developer_networkentities.integer >= 2 && cl.entities[enumber].state_current.active != cl.entities[enumber].state_previous.active) - { - if (cl.entities[enumber].state_current.active == ACTIVE_NETWORK) - Con_Printf("entity #%i has become active\n", enumber); - else if (cl.entities[enumber].state_previous.active) - Con_Printf("entity #%i has become inactive\n", enumber); - } - } - } - d->currentcommit = NULL; - if (skip) - EntityFrame4_ResetDatabase(d); -} - -qboolean EntityFrame4_WriteFrame(sizebuf_t *msg, int maxsize, entityframe4_database_t *d, int numstates, const entity_state_t **states) -{ - prvm_prog_t *prog = SVVM_prog; - const entity_state_t *e, *s; - entity_state_t inactiveentitystate; - int i, n, startnumber; - sizebuf_t buf; - unsigned char data[128]; - - // if there isn't enough space to accomplish anything, skip it - if (msg->cursize + 24 > maxsize) - return false; - - // prepare the buffer - memset(&buf, 0, sizeof(buf)); - buf.data = data; - buf.maxsize = sizeof(data); - - for (i = 0;i < MAX_ENTITY_HISTORY;i++) - if (!d->commit[i].numentities) - break; - // if commit buffer full, just don't bother writing an update this frame - if (i == MAX_ENTITY_HISTORY) - return false; - d->currentcommit = d->commit + i; - - // this state's number gets played around with later - inactiveentitystate = defaultstate; - - d->currentcommit->numentities = 0; - d->currentcommit->framenum = ++d->latestframenumber; - MSG_WriteByte(msg, svc_entities); - MSG_WriteLong(msg, d->referenceframenum); - MSG_WriteLong(msg, d->currentcommit->framenum); - if (developer_networkentities.integer >= 10) - { - Con_Printf("send svc_entities num:%i ref:%i (database: ref:%i commits:", d->currentcommit->framenum, d->referenceframenum, d->referenceframenum); - for (i = 0;i < MAX_ENTITY_HISTORY;i++) - if (d->commit[i].numentities) - Con_Printf(" %i", d->commit[i].framenum); - Con_Print(")\n"); - } - if (d->currententitynumber >= prog->max_edicts) - startnumber = 1; - else - startnumber = bound(1, d->currententitynumber, prog->max_edicts - 1); - MSG_WriteShort(msg, startnumber); - // reset currententitynumber so if the loop does not break it we will - // start at beginning next frame (if it does break, it will set it) - d->currententitynumber = 1; - for (i = 0, n = startnumber;n < prog->max_edicts;n++) - { - if (PRVM_serveredictfunction((&prog->edicts[n]), SendEntity)) - continue; - // find the old state to delta from - e = EntityFrame4_GetReferenceEntity(d, n); - // prepare the buffer - SZ_Clear(&buf); - // entity exists, build an update (if empty there is no change) - // find the state in the list - for (;i < numstates && states[i]->number < n;i++); - // make the message - s = states[i]; - if (s->number == n) - { - // build the update - EntityState_WriteUpdate(s, &buf, e); - } - else - { - inactiveentitystate.number = n; - s = &inactiveentitystate; - if (e->active == ACTIVE_NETWORK) - { - // entity used to exist but doesn't anymore, send remove - MSG_WriteShort(&buf, n | 0x8000); - } - } - // if the commit is full, we're done this frame - if (msg->cursize + buf.cursize > maxsize - 4) - { - // next frame we will continue where we left off - break; - } - // add the entity to the commit - EntityFrame4_AddCommitEntity(d, s); - // if the message is empty, skip out now - if (buf.cursize) - { - // write the message to the packet - SZ_Write(msg, buf.data, buf.cursize); - } - } - d->currententitynumber = n; - - // remove world message (invalid, and thus a good terminator) - MSG_WriteShort(msg, 0x8000); - // write the number of the end entity - MSG_WriteShort(msg, d->currententitynumber); - // just to be sure - d->currentcommit = NULL; - - return true; -}