2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-02-05 18:20:45 +03:00

Minor refactoring and improve readability

This commit is contained in:
s1lentq 2024-08-01 02:56:20 +07:00
parent c8308a2c60
commit 2834fb8494
5 changed files with 300 additions and 261 deletions

View File

@ -1060,15 +1060,18 @@ void World::ParseClientData(BitBuffer *stream, unsigned int deltaSeqNr, BitBuffe
} }
} }
// When a delta command is received from the server
// We need to grab the entity # out of it any the bit settings, too
int World::ParseDeltaHeader(BitBuffer *stream, bool &remove, bool &custom, int &numbase, bool &newbl, int &newblindex, bool full, int &offset) int World::ParseDeltaHeader(BitBuffer *stream, bool &remove, bool &custom, int &numbase, bool &newbl, int &newblindex, bool full, int &offset)
{ {
int num; int num;
bool isdelta, isnext; bool isdelta;
offset = 0; offset = 0;
custom = false; custom = false;
newbl = false; newbl = false;
// This full update (non-delta)
if (full) if (full)
{ {
isdelta = stream->ReadBit() ? true : false; isdelta = stream->ReadBit() ? true : false;
@ -1077,6 +1080,8 @@ int World::ParseDeltaHeader(BitBuffer *stream, bool &remove, bool &custom, int &
else else
{ {
isdelta = false; isdelta = false;
// the entity was removed from server or not
remove = stream->ReadBit() ? true : false; remove = stream->ReadBit() ? true : false;
} }
@ -1088,11 +1093,11 @@ int World::ParseDeltaHeader(BitBuffer *stream, bool &remove, bool &custom, int &
{ {
if (stream->ReadBit()) if (stream->ReadBit())
{ {
num = stream->ReadBits(11); num = stream->ReadBits(MAX_EDICT_BITS);
} }
else else
{ {
int delta = stream->ReadBits(6); int delta = stream->ReadBits(DELTA_OFFSET_BITS);
num = delta + numbase; num = delta + numbase;
} }
} }
@ -1105,20 +1110,19 @@ int World::ParseDeltaHeader(BitBuffer *stream, bool &remove, bool &custom, int &
if (m_MaxInstanced_BaseLine) if (m_MaxInstanced_BaseLine)
{ {
isnext = stream->ReadBit() ? true : false; newbl = stream->ReadBit() ? true : false;
if (isnext)
if (newbl)
{ {
newbl = true; newblindex = stream->ReadBits(MAX_BASELINE_BITS);
newblindex = stream->ReadBits(6);
} }
} }
if (full && !newbl) if (full && !newbl)
{ {
isnext = stream->ReadBit() ? true : false; if (stream->ReadBit() != 0)
if (isnext)
{ {
offset = stream->ReadBits(6); offset = stream->ReadBits(MAX_BASELINE_BITS);
} }
} }
} }
@ -1273,15 +1277,14 @@ bool World::GetDeltaFromCache(unsigned int seqNr, unsigned int deltaNr, BitBuffe
return 0; return 0;
} }
// marker an entity index that not in an old packet (for svc_packetentities)
#define ENTITY_SENTINEL 9999
void World::WritePacketEntities(BitBuffer *stream, frame_t *frame, frame_t *deltaframe) void World::WritePacketEntities(BitBuffer *stream, frame_t *frame, frame_t *deltaframe)
{ {
int oldmax; unsigned int oldmax, oldindex, newindex;
int oldindex; int newnum, oldnum;
int newindex; entity_state_t *frameEntities, *deltaEntities;
int newnum;
int oldnum;
entity_state_t *frameEntities;
entity_state_t *deltaEntities;
deltacallback_t header; deltacallback_t header;
header.instanced_baseline = (m_MaxInstanced_BaseLine > 0) ? true : false; header.instanced_baseline = (m_MaxInstanced_BaseLine > 0) ? true : false;
@ -1289,9 +1292,9 @@ void World::WritePacketEntities(BitBuffer *stream, frame_t *frame, frame_t *delt
header.offset = 0; header.offset = 0;
header.numbase = 0; header.numbase = 0;
header.newblindex = 0; header.newblindex = 0;
header.full = false;
header.newbl = false; header.newbl = false;
header.remove = false; header.remove = false;
header.full = false;
header.custom = false; header.custom = false;
if (frame->delta || deltaframe->delta) { if (frame->delta || deltaframe->delta) {
@ -1302,79 +1305,82 @@ void World::WritePacketEntities(BitBuffer *stream, frame_t *frame, frame_t *delt
m_Delta.SetTime(frame->time); m_Delta.SetTime(frame->time);
oldmax = deltaframe->entitynum; oldmax = deltaframe->entitynum;
newnum = 0; // index in frame->entities newindex = 0; // index in frame->entities
oldnum = 0; // index in deltaframe->entities oldindex = 0; // index in deltaframe->entities
frameEntities = (entity_state_t *)frame->entities; frameEntities = (entity_state_t *)frame->entities;
deltaEntities = (entity_state_t *)deltaframe->entities; deltaEntities = (entity_state_t *)deltaframe->entities;
stream->StartBitMode(); stream->StartBitMode();
while (true)
{
if ((unsigned)newnum < frame->entitynum)
{
newindex = frameEntities[newnum].number;
}
else
{
if (oldnum >= oldmax)
break;
// TODO: Unreachable code while (newindex < frame->entitynum || oldindex < oldmax)
if ((unsigned)newnum < frame->entitynum)
newindex = frameEntities[newnum].number;
else
newindex = 9999;
}
if (oldnum < oldmax)
oldindex = deltaEntities[oldnum].number;
else
oldindex = 9999;
if (newindex == oldindex)
{ {
header.custom = (frameEntities[newnum].entityType & ENTITY_BEAM) == ENTITY_BEAM; newnum = (newindex >= frame->entitynum) ? ENTITY_SENTINEL : frameEntities[newindex].number;
header.num = newindex; oldnum = (oldindex >= oldmax) ? ENTITY_SENTINEL : deltaEntities[oldindex].number;
// this is a delta update of the entity from previous position
if (newnum == oldnum)
{
// delta update from old position
// because the force parm is false, this will not result
// in any bytes being emitted if the entity has not changed at all
// note that players are always 'newentities', this updates their oldorigin always
// and prevents warping
header.custom = (frameEntities[newindex].entityType & ENTITY_BEAM) == ENTITY_BEAM;
header.num = newnum;
header.newblindex = 0; header.newblindex = 0;
header.newbl = false; header.newbl = false;
header.remove = false; header.remove = false;
delta_t *delta = GetDeltaEncoder(newindex, header.custom); delta_t *delta = GetDeltaEncoder(newnum, header.custom);
m_Delta.WriteDelta(stream, (byte *)&deltaEntities[newindex], (byte *)&frameEntities[newnum], false, delta, &header); m_Delta.WriteDelta(stream, (byte *)&deltaEntities[oldindex], (byte *)&frameEntities[newindex], false, delta, &header);
oldnum++; oldindex++;
newnum++; newindex++;
continue; continue;
} }
if (newindex >= oldindex) // Figure out how we want to update the entity
// This is a new entity, send it from the baseline
if (newnum < oldnum)
{ {
if (newindex > oldindex) //
{ // If the entity was not in the old packet (oldnum == 9999),
header.num = oldindex; // then delta from the baseline since this is a new entity
header.remove = true; header.custom = (frameEntities[newindex].entityType & ENTITY_BEAM) == ENTITY_BEAM;
header.newbl = false; header.num = newnum;
header.newblindex = 0; header.newblindex = 0;
header.newbl = false;
header.remove = false;
delta_t *delta = GetDeltaEncoder(newnum, header.custom);
m_Delta.WriteDelta(stream, (byte *)&m_BaseLines[newnum], (byte *)&frameEntities[newindex], true, delta, &header);
newindex++;
continue;
}
// the old entity isn't present in the new message
if (newnum > oldnum)
{
//
// If the entity was in the old list, but is not in the new list (newindex == 9999),
// then construct a special remove message
header.num = oldnum;
header.newblindex = 0;
header.newbl = false;
header.remove = true; // tell the client that entity was removed from server
m_Delta.WriteHeader(stream, &header); m_Delta.WriteHeader(stream, &header);
++oldnum; oldindex++;
}
continue; continue;
} }
header.custom = (frameEntities[newnum].entityType & ENTITY_BEAM) == ENTITY_BEAM;
header.newblindex = 0;
header.num = newindex;
header.remove = false;
header.newbl = false;
delta_t *delta = GetDeltaEncoder(newindex, header.custom);
m_Delta.WriteDelta(stream, (byte *)&m_BaseLines[oldnum], (byte *)&frameEntities[newnum], true, delta, &header);
newnum++;
} }
// No more entities.. (end of packet entities)
stream->WriteBits(0, 16); stream->WriteBits(0, 16);
stream->EndBitMode(); stream->EndBitMode();
} }
@ -1467,10 +1473,11 @@ double World::GetTime()
return m_WorldTime; return m_WorldTime;
} }
// An svc_packetentities has just been parsed, deal with the rest of the data stream
bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsigned int from) bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsigned int from)
{ {
int newnum, oldnum; int newnum, oldnum;
int oldindex, newindex; unsigned int oldindex, newindex;
bool remove, custom, newbl; bool remove, custom, newbl;
int newblindex, numbase, offset; int newblindex, numbase, offset;
@ -1485,11 +1492,15 @@ bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsi
oldindex = 0; oldindex = 0;
newindex = 0; newindex = 0;
numbase = 0;
newblindex = 0;
newbl = false;
remove = false; remove = false;
custom = false; custom = false;
newbl = false;
newblindex = 0; //
numbase = 0; // Parse uncompress entities
//
m_Delta.SetTime(frame->time); m_Delta.SetTime(frame->time);
stream->StartBitMode(); stream->StartBitMode();
@ -1500,60 +1511,75 @@ bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsi
while (stream->PeekBits(16)) while (stream->PeekBits(16))
{ {
newnum = ParseDeltaHeader(stream, remove, custom, numbase, newbl, newblindex, false, offset); newnum = ParseDeltaHeader(stream, remove, custom, numbase, newbl, newblindex, false, offset);
oldnum = (oldindex >= deltaFrame.entitynum) ? ENTITY_SENTINEL : deltaEntity[oldindex].number;
if ((unsigned)oldindex < deltaFrame.entitynum) while (oldnum < newnum)
oldnum = deltaEntity[oldindex].number;
else
oldnum = 9999;
while (newnum > oldnum)
{ {
//
// one or more entities from the old packet are unchanged
if (newindex >= MAX_PACKET_ENTITIES) if (newindex >= MAX_PACKET_ENTITIES)
{ {
m_System->DPrintf("WARNING!World::UncompressEntitiesFromStream: newindex >= MAX_PACKET_ENTITIES.\n"); m_System->DPrintf("WARNING!World::UncompressEntitiesFromStream: newindex >= MAX_PACKET_ENTITIES.\n");
stream->m_Overflowed = true; stream->m_Overflowed = true;
} }
// copy one of the old entities over to the new packet unchanged
Q_memcpy(&entity[newindex], &deltaEntity[oldindex], sizeof(entity[newindex])); Q_memcpy(&entity[newindex], &deltaEntity[oldindex], sizeof(entity[newindex]));
newindex++; newindex++;
oldindex++; oldindex++;
if ((unsigned)oldindex < deltaFrame.entitynum) // lookup next index
oldnum = deltaEntity[oldindex].number; oldnum = (oldindex >= deltaFrame.entitynum) ? ENTITY_SENTINEL : deltaEntity[oldindex].number;
else
oldnum = 9999;
} }
if (newnum >= oldnum) // delta from previous state
{
if (newnum == oldnum) if (newnum == oldnum)
{ {
if (remove) if (remove)
{ {
++oldindex; oldindex++;
continue;
} }
else
{ //
// Insert new the entity to frame
entity[newindex].entityType = custom ? ENTITY_BEAM : ENTITY_NORMAL; entity[newindex].entityType = custom ? ENTITY_BEAM : ENTITY_NORMAL;
delta_t *delta = GetDeltaEncoder(newnum, custom); delta_t *delta = GetDeltaEncoder(newnum, custom);
m_Delta.ParseDelta(stream, (byte *)&deltaEntity[oldindex], (byte *)&entity[newindex], delta); m_Delta.ParseDelta(stream, (byte *)&deltaEntity[oldindex], (byte *)&entity[newindex], delta);
entity[newindex].number = newnum; entity[newindex].number = newnum;
++newindex; newindex++;
++oldindex; oldindex++;
continue;
} }
}
} // Figure out how we want to update the entity
else if (!remove) // This is a new entity, sent it from the baseline
if (newnum < oldnum)
{ {
//
// If the entity was not in the old packet (oldnum == 9999),
// then delta from the baseline since this is a new entity
if (remove)
{
continue;
}
if (newindex >= MAX_PACKET_ENTITIES) if (newindex >= MAX_PACKET_ENTITIES)
{ {
m_System->DPrintf("World::UncompressEntitiesFromStream: newindex >= MAX_PACKET_ENTITIES.\n"); m_System->DPrintf("World::UncompressEntitiesFromStream: newindex >= MAX_PACKET_ENTITIES.\n");
stream->m_Overflowed = true; stream->m_Overflowed = true;
} }
//
// Insert new the entity to frame
entity_state_t *baseline; entity_state_t *baseline;
if (newbl) if (newbl)
{ {
@ -1574,9 +1600,12 @@ bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsi
m_Delta.ParseDelta(stream, (byte *)baseline, (byte *)&entity[newindex], delta); m_Delta.ParseDelta(stream, (byte *)baseline, (byte *)&entity[newindex], delta);
entity[newindex].number = newnum; entity[newindex].number = newnum;
newindex++; newindex++;
continue;
} }
} }
// peek bit == 0 end of packet entities
if (stream->ReadShort()) if (stream->ReadShort())
{ {
m_System->DPrintf("WARNING! World::UncompressEntitiesFromStream: missing end tag.\n"); m_System->DPrintf("WARNING! World::UncompressEntitiesFromStream: missing end tag.\n");
@ -1585,7 +1614,10 @@ bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsi
stream->EndBitMode(); stream->EndBitMode();
while ((unsigned)oldindex < deltaFrame.entitynum) // Copy all the rest of the entities from the old packet
//
while (oldindex != ENTITY_SENTINEL && oldindex < deltaFrame.entitynum)
{ {
if (newindex >= MAX_PACKET_ENTITIES) if (newindex >= MAX_PACKET_ENTITIES)
{ {
@ -1593,33 +1625,22 @@ bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsi
stream->m_Overflowed = true; stream->m_Overflowed = true;
} }
// copy everything to the new state we are delta'ing
Q_memcpy(&entity[newindex], &deltaEntity[oldindex], sizeof(entity[newindex])); Q_memcpy(&entity[newindex], &deltaEntity[oldindex], sizeof(entity[newindex]));
newindex++; newindex++;
oldindex++; oldindex++;
} }
if (newindex != frame->entitynum) {
m_System->DPrintf("WARNING! World::UncompressEntitiesFromStream: newindex != frame->entitynum.\n");
}
return true; return true;
} }
bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream) bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream)
{ {
int num; int num, newindex = 0;
int newindex = 0;
int entnum = frame->entitynum; int entnum = frame->entitynum;
entity_state_t *baseline; entity_state_t *baseline;
bool remove, custom, newbl; bool remove = false, custom = false, newbl = false;
int newblindex, numbase, offset; int newblindex = 0, numbase = 0, offset;
newblindex = 0;
numbase = 0;
remove = false;
custom = false;
newbl = false;
entity_state_t *entities = (entity_state_t *)frame->entities; entity_state_t *entities = (entity_state_t *)frame->entities;
m_Delta.SetTime(frame->time); m_Delta.SetTime(frame->time);
@ -2240,8 +2261,8 @@ void World::RearrangeFrame(frame_t *frame, int seqNrOffset, float timeOffset)
BitBuffer tempStream(frame->entities, frame->entitiesSize); BitBuffer tempStream(frame->entities, frame->entitiesSize);
Q_memset(frame->entities, 0, frame->entitiesSize); Q_memset(frame->entities, 0, frame->entitiesSize);
int newsize = CompressFrame(&fullFrame, &tempStream); unsigned int newsize = CompressFrame(&fullFrame, &tempStream);
if ((unsigned)newsize > frame->entitiesSize || tempStream.IsOverflowed()) { if (newsize > frame->entitiesSize || tempStream.IsOverflowed()) {
m_System->Printf("WARNING! World::RearrangeFrame: wrong entities size (%i != %i).\n", frame->entitiesSize, newsize); m_System->Printf("WARNING! World::RearrangeFrame: wrong entities size (%i != %i).\n", frame->entitiesSize, newsize);
return; return;
} }

View File

@ -39,6 +39,9 @@
#define RESOURCE_INDEX_BITS 12 #define RESOURCE_INDEX_BITS 12
#define RESOURCE_MAX_COUNT (1 << RESOURCE_INDEX_BITS) #define RESOURCE_MAX_COUNT (1 << RESOURCE_INDEX_BITS)
#define MAX_BASELINE_BITS 6
#define MAX_BASELINES (1 << MAX_BASELINE_BITS)
class World: public IWorld, public BaseSystemModule { class World: public IWorld, public BaseSystemModule {
public: public:
World() {} World() {}

View File

@ -98,6 +98,9 @@
// Max size of udp packet payload // Max size of udp packet payload
#define MAX_UDP_PACKET 4010 // 9 bytes SPLITHEADER + 4000 payload? #define MAX_UDP_PACKET 4010 // 9 bytes SPLITHEADER + 4000 payload?
#define DELTA_OFFSET_BITS 6
#define DELTA_OFFSET_MAX ((1 << DELTA_OFFSET_BITS) - 1)
enum svc_commands_e enum svc_commands_e
{ {
svc_bad, svc_bad,

View File

@ -30,6 +30,9 @@
#include "entity_state.h" #include "entity_state.h"
// marker an entity index that not in an old packet (for svc_packetentities)
#define ENTITY_SENTINEL 9999
typedef struct packet_entities_s typedef struct packet_entities_s
{ {
int num_entities; int num_entities;

View File

@ -4529,15 +4529,20 @@ int SV_CreatePacketEntities(sv_delta_t type, client_t *client, packet_entities_t
return g_RehldsHookchains.m_SV_CreatePacketEntities.callChain(SV_CreatePacketEntities_api, type, GetRehldsApiClient(client), to, msg); return g_RehldsHookchains.m_SV_CreatePacketEntities.callChain(SV_CreatePacketEntities_api, type, GetRehldsApiClient(client), to, msg);
} }
// Computes either a compressed, or uncompressed delta buffer for the client
// Returns the size IN BITS of the message buffer created
int SV_CreatePacketEntities_internal(sv_delta_t type, client_t *client, packet_entities_t *to, sizebuf_t *msg) int SV_CreatePacketEntities_internal(sv_delta_t type, client_t *client, packet_entities_t *to, sizebuf_t *msg)
{ {
packet_entities_t *from; edict_t *ent;
int oldindex; client_frame_t *fromframe;
int newindex; packet_entities_t *from; // Entity packet for that frame
int oldnum; delta_t *delta;
int newnum; int oldindex, newindex;
int oldnum, newnum;
int oldmax; int oldmax;
int numbase; qboolean custom = FALSE;
int offset;
int numbase = 0;
// fix for https://github.com/dreamstalker/rehlds/issues/24 // fix for https://github.com/dreamstalker/rehlds/issues/24
#ifdef REHLDS_FIXES #ifdef REHLDS_FIXES
@ -4545,129 +4550,116 @@ int SV_CreatePacketEntities_internal(sv_delta_t type, client_t *client, packet_e
uint64 toBaselinesForceMask[MAX_PACKET_ENTITIES]; uint64 toBaselinesForceMask[MAX_PACKET_ENTITIES];
#endif #endif
numbase = 0; // See if this is a full update
if (type == sv_packet_delta) if (type == sv_packet_delta)
{ {
client_frame_t *fromframe = &client->frames[SV_UPDATE_MASK & client->delta_sequence]; // This is the frame that we are going to delta update from
fromframe = &client->frames[SV_UPDATE_MASK & client->delta_sequence];
from = &fromframe->entities; from = &fromframe->entities;
_mm_prefetch((const char*)&from->entities[0], _MM_HINT_T0); _mm_prefetch((const char*)&from->entities[0], _MM_HINT_T0);
_mm_prefetch(((const char*)&from->entities[0]) + 64, _MM_HINT_T0); _mm_prefetch(((const char*)&from->entities[0]) + 64, _MM_HINT_T0);
oldmax = from->num_entities; oldmax = fromframe->entities.num_entities;
MSG_WriteByte(msg, svc_deltapacketentities);
MSG_WriteShort(msg, to->num_entities); MSG_WriteByte(msg, svc_deltapacketentities); // This is a delta
MSG_WriteByte(msg, client->delta_sequence); MSG_WriteShort(msg, to->num_entities); // This is how many ents are in the new packet
MSG_WriteByte(msg, client->delta_sequence); // This is the sequence # that we are updating from
} }
else else
{ {
oldmax = 0; oldmax = 0; // no delta update
from = NULL; from = NULL;
MSG_WriteByte(msg, svc_packetentities);
MSG_WriteShort(msg, to->num_entities); MSG_WriteByte(msg, svc_packetentities); // Just a packet update.
MSG_WriteShort(msg, to->num_entities); // This is the # of entities we are sending.
} }
newnum = 0; //index in to->entities newindex = 0; // index in to->entities
oldnum = 0; //index in from->entities oldindex = 0; // index in from->entities
MSG_StartBitWriting(msg); MSG_StartBitWriting(msg);
while (1)
{
if (newnum < to->num_entities)
{
newindex = to->entities[newnum].number;
}
else
{
if (oldnum >= oldmax)
break;
if (newnum < to->num_entities) while (newindex < to->num_entities || oldindex < oldmax)
newindex = to->entities[newnum].number;
else
newindex = 9999;
}
#ifdef REHLDS_FIXES
if (oldnum < oldmax && from)
#else
if (oldnum < oldmax)
#endif
oldindex = from->entities[oldnum].number;
else
oldindex = 9999;
if (newindex == oldindex)
{ {
entity_state_t *baseline_ = &to->entities[newnum]; newnum = (newindex >= to->num_entities) ? ENTITY_SENTINEL : to->entities[newindex].number;
qboolean custom = baseline_->entityType & 0x2 ? TRUE : FALSE; oldnum = (!from || oldindex >= oldmax) ? ENTITY_SENTINEL : from->entities[oldindex].number; // FIXED: from can be null
SV_SetCallback(newindex, FALSE, custom, &numbase, FALSE, 0);
DELTA_WriteDelta((uint8 *)&from->entities[oldnum], (uint8 *)baseline_, FALSE, custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newindex) ? g_pplayerdelta : g_pentitydelta), &SV_InvokeCallback); // this is a delta update of the entity from old position
++oldnum; if (newnum == oldnum)
_mm_prefetch((const char*)&from->entities[oldnum], _MM_HINT_T0); {
_mm_prefetch(((const char*)&from->entities[oldnum]) + 64, _MM_HINT_T0); // delta update from old position
++newnum; // because the force parm is false, this will not result
// in any bytes being emitted if the entity has not changed at all
// note that players are always 'newentities', this updates their oldorigin always
// and prevents warping
entity_state_t *baseline = &to->entities[newindex];
custom = (baseline->entityType == ENTITY_BEAM) ? TRUE : FALSE;
SV_SetCallback(newnum, FALSE, custom, &numbase, FALSE, 0);
DELTA_WriteDelta((uint8 *)&from->entities[oldindex], (uint8 *)baseline, FALSE, custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newnum) ? g_pplayerdelta : g_pentitydelta), &SV_InvokeCallback);
oldindex++;
_mm_prefetch((const char*)&from->entities[oldindex], _MM_HINT_T0);
_mm_prefetch(((const char*)&from->entities[oldindex]) + 64, _MM_HINT_T0);
newindex++;
continue; continue;
} }
if (newindex >= oldindex) // Figure out how we want to update the entity
// This is a new entity, send it from the baseline
if (newnum < oldnum)
{ {
if (newindex > oldindex) //
{ // If the entity was not in the old packet (oldnum == 9999),
SV_WriteDeltaHeader(oldindex, TRUE, FALSE, &numbase, FALSE, 0, FALSE, 0); // then delta from the baseline since this is a new entity
++oldnum;
_mm_prefetch((const char*)&from->entities[oldnum], _MM_HINT_T0);
_mm_prefetch(((const char*)&from->entities[oldnum]) + 64, _MM_HINT_T0);
}
continue;
}
edict_t *ent = EDICT_NUM(newindex); ent = EDICT_NUM(newnum);
qboolean custom = to->entities[newnum].entityType & 0x2 ? TRUE : FALSE; custom = (to->entities[newindex].entityType == ENTITY_BEAM) ? TRUE : FALSE;
SV_SetCallback(
newindex,
FALSE,
custom,
&numbase,
from == NULL,
0);
entity_state_t *baseline_ = &g_psv.baselines[newindex]; if (from == NULL)
if (sv_instancedbaseline.value != 0.0f && g_psv.instance_baselines->number != 0 && newindex > sv_lastnum) SV_SetCallback(newnum, FALSE, custom, &numbase, TRUE, 0);
else
SV_SetCallback(newnum, FALSE, custom, &numbase, FALSE, 0);
// this is a new entity, send it from the baseline
entity_state_t *baseline = &g_psv.baselines[newnum];
if (sv_instancedbaseline.value && g_psv.instance_baselines->number != 0 && newnum > sv_lastnum)
{ {
for (int i = 0; i < g_psv.instance_baselines->number; i++) for (int i = 0; i < g_psv.instance_baselines->number; i++)
{ {
if (g_psv.instance_baselines->classname[i] == ent->v.classname) if (g_psv.instance_baselines->classname[i] == ent->v.classname)
{ {
SV_SetNewInfo(i); SV_SetNewInfo(i);
baseline_ = &g_psv.instance_baselines->baseline[i]; baseline = &g_psv.instance_baselines->baseline[i];
break; break;
} }
} }
} }
else else
{ {
// If this is full update
if (!from) if (!from)
{ {
int offset = SV_FindBestBaseline(newnum, &baseline_, to->entities, newindex, custom); offset = SV_FindBestBaseline(newindex, &baseline, to->entities, newnum, custom);
_mm_prefetch((const char*)baseline_, _MM_HINT_T0); _mm_prefetch((const char*)baseline, _MM_HINT_T0);
_mm_prefetch(((const char*)baseline_) + 64, _MM_HINT_T0); _mm_prefetch(((const char*)baseline) + 64, _MM_HINT_T0);
if (offset) if (offset)
SV_SetCallback(newindex, FALSE, custom, &numbase, TRUE, offset); SV_SetCallback(newnum, FALSE, custom, &numbase, TRUE, offset);
// fix for https://github.com/dreamstalker/rehlds/issues/24 // fix for https://github.com/dreamstalker/rehlds/issues/24
#ifdef REHLDS_FIXES #ifdef REHLDS_FIXES
if (offset) if (offset)
baselineToIdx = newnum - offset; baselineToIdx = newindex - offset;
#endif #endif
} }
} }
delta = custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newnum) ? g_pplayerdelta : g_pentitydelta);
delta_t* delta = custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newindex) ? g_pplayerdelta : g_pentitydelta);
// fix for https://github.com/dreamstalker/rehlds/issues/24 // fix for https://github.com/dreamstalker/rehlds/issues/24
#ifdef REHLDS_FIXES #ifdef REHLDS_FIXES
DELTA_WriteDeltaForceMask( DELTA_WriteDeltaForceMask(
(uint8 *)baseline_, (uint8 *)baseline,
(uint8 *)&to->entities[newnum], (uint8 *)&to->entities[newindex],
TRUE, TRUE,
delta, delta,
&SV_InvokeCallback, &SV_InvokeCallback,
@ -4680,24 +4672,41 @@ int SV_CreatePacketEntities_internal(sv_delta_t type, client_t *client, packet_e
uint64 diffMask = origMask ^ usedMask; uint64 diffMask = origMask ^ usedMask;
// Remember changed fields that was marked in original mask, but unmarked by the conditional encoder // Remember changed fields that was marked in original mask, but unmarked by the conditional encoder
toBaselinesForceMask[newnum] = diffMask & origMask; toBaselinesForceMask[newindex] = diffMask & origMask;
#else // REHLDS_FIXES #else // REHLDS_FIXES
DELTA_WriteDelta( DELTA_WriteDelta(
(uint8 *)baseline_, (uint8 *)baseline,
(uint8 *)&to->entities[newnum], (uint8 *)&to->entities[newindex],
TRUE, TRUE,
delta, delta,
&SV_InvokeCallback &SV_InvokeCallback
); );
#endif // REHLDS_FIXES #endif // REHLDS_FIXES
++newnum; newindex++;
continue;
} }
// the old entity isn't present in the new message
if (newnum > oldnum)
{
//
// If the entity was in the old list, but is not in the new list (newnum == 9999),
// then construct a special remove message
// remove = TRUE, tell the client that entity was removed from server
SV_WriteDeltaHeader(oldnum, TRUE, FALSE, &numbase, FALSE, 0, FALSE, 0);
oldindex++;
_mm_prefetch((const char*)&from->entities[oldindex], _MM_HINT_T0);
_mm_prefetch(((const char*)&from->entities[oldindex]) + 64, _MM_HINT_T0);
continue;
}
}
// No more entities.. (end of packet entities)
MSG_WriteBits(0, 16); MSG_WriteBits(0, 16);
MSG_EndBitWriting(msg); MSG_EndBitWriting(msg);
return msg->cursize; return msg->cursize;
} }