#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. Has priority over WANTUPDATE.
-#define SCOPE_WANTUPDATE 2 // Set if an update has been scheduled.
+#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
+#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 =
{32, 32, 32},//unsigned char glowmod[3];
};
-// LordHavoc: I own protocol ranges 96, 97, 3500-3599
+// LadyHavoc: I own protocol ranges 96, 97, 3500-3599
struct protocolversioninfo_s
{
if (bits & U_VIEWMODEL) s.flags |= RENDER_VIEWMODEL;
if (bits & U_EXTERIORMODEL) s.flags |= RENDER_EXTERIORMODEL;
- // LordHavoc: to allow playback of the Nehahra movie
+ // LadyHavoc: to allow playback of the Nehahra movie
if (cls.protocol == PROTOCOL_NEHAHRAMOVIE && (bits & U_EXTEND1))
{
- // LordHavoc: evil format
+ // LadyHavoc: evil format
int i = (int)MSG_ReadFloat(&cl_message);
int j = (int)(MSG_ReadFloat(&cl_message) * 255.0f);
if (i == 2)
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_WANTREMOVE;
- 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.
}
}
}
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_WANTREMOVE;
- client->csqcentitysendflags[i] = 0xFFFFFF;
- }
+ client->csqcentityscope[i] |= SCOPE_ASSUMED_EXISTING; // FORCE REMOVE.
else
client->csqcentitysendflags[i] |= recoversendflags[i];
}
end = *n;
for (;number < end;number++)
{
- if (client->csqcentityscope[number] & SCOPE_WANTSEND)
- {
+ client->csqcentityscope[number] &= ~SCOPE_WANTSEND;
+ if (client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING)
client->csqcentityscope[number] |= SCOPE_WANTREMOVE;
- client->csqcentitysendflags[number] = 0xFFFFFF;
- }
+ client->csqcentitysendflags[number] = 0xFFFFFF;
}
ed = prog->edicts + number;
+ client->csqcentityscope[number] &= ~SCOPE_WANTSEND;
if (PRVM_serveredictfunction(ed, SendEntity))
- {
- client->csqcentityscope[number] &= ~SCOPE_WANTREMOVE;
client->csqcentityscope[number] |= SCOPE_WANTUPDATE;
- }
- else if (client->csqcentityscope[number] & SCOPE_WANTSEND)
+ else
{
- client->csqcentityscope[number] |= SCOPE_WANTREMOVE;
+ if (client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING)
+ client->csqcentityscope[number] |= SCOPE_WANTREMOVE;
client->csqcentitysendflags[number] = 0xFFFFFF;
}
number++;
end = client->csqcnumedicts;
for (;number < end;number++)
{
- if (client->csqcentityscope[number] & SCOPE_WANTSEND)
- {
+ client->csqcentityscope[number] &= ~SCOPE_WANTSEND;
+ if (client->csqcentityscope[number] & SCOPE_ASSUMED_EXISTING)
client->csqcentityscope[number] |= SCOPE_WANTREMOVE;
- client->csqcentitysendflags[number] = 0xFFFFFF;
- }
+ client->csqcentitysendflags[number] = 0xFFFFFF;
}
// now try to emit the entity updates
{
if (!(client->csqcentityscope[number] & SCOPE_WANTSEND))
continue;
- sendflags = client->csqcentitysendflags[number];
- if (!sendflags)
- continue;
if(db->num >= NUM_CSQCENTITIES_PER_FRAME)
break;
ed = prog->edicts + number;
- if (client->csqcentityscope[number] & SCOPE_WANTREMOVE)
+ 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)
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_WANTSEND;
+ 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->csqcentityscope[number] |= SCOPE_EXISTED_ONCE;
ENTITYSIZEPROFILING_END(msg, number, 0);
}
if (msg->cursize + 17 >= maxsize)
}
else
{
- // write an update
// save the cursize value in case we overflow and have to rollback
int oldcursize = msg->cursize;
+
+ // 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;
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_WANTSEND;
- 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->csqcentityscope[number] |= SCOPE_EXISTED_ONCE;
// and take note that we have begun the svc_csqcentities
// section of the packet
sectionstarted = 1;
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)
db->entno[db->num] = number;
db->sendflags[db->num] = sendflags;
db->num += 1;
- client->csqcentityscope[number] |= SCOPE_EXISTED_ONCE;
+ 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;
if (s->flags & RENDER_EXTERIORMODEL)
bits |= U_EXTERIORMODEL;
- // LordHavoc: old stuff, but rewritten to have more exact tolerances
+ // LadyHavoc: old stuff, but rewritten to have more exact tolerances
baseline = prog->edicts[s->number].priv.server->baseline;
if (baseline.origin[0] != s->origin[0])
bits |= U_ORIGIN1;
}
else
{
- // LordHavoc: have to write flags first, as they can modify protocol
+ // LadyHavoc: have to write flags first, as they can modify protocol
if (bits & E_FLAGS)
MSG_WriteByte(msg, ent->flags);
if (ent->flags & RENDER_LOWPRECISION)
// 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)
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++)
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;
if (newnum != oldnum && !delta && !invalid)
{
cl.qw_validsequence = 0;
- Con_Printf("WARNING: U_REMOVE %i on full update\n", newnum);
+ Con_Warnf("WARNING: U_REMOVE %i on full update\n", newnum);
}
}
else