2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-01-14 07:38:04 +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 num;
bool isdelta, isnext;
bool isdelta;
offset = 0;
custom = false;
newbl = false;
newbl = false;
// This full update (non-delta)
if (full)
{
isdelta = stream->ReadBit() ? true : false;
@ -1077,6 +1080,8 @@ int World::ParseDeltaHeader(BitBuffer *stream, bool &remove, bool &custom, int &
else
{
isdelta = false;
// the entity was removed from server or not
remove = stream->ReadBit() ? true : false;
}
@ -1088,11 +1093,11 @@ int World::ParseDeltaHeader(BitBuffer *stream, bool &remove, bool &custom, int &
{
if (stream->ReadBit())
{
num = stream->ReadBits(11);
num = stream->ReadBits(MAX_EDICT_BITS);
}
else
{
int delta = stream->ReadBits(6);
int delta = stream->ReadBits(DELTA_OFFSET_BITS);
num = delta + numbase;
}
}
@ -1105,20 +1110,19 @@ int World::ParseDeltaHeader(BitBuffer *stream, bool &remove, bool &custom, int &
if (m_MaxInstanced_BaseLine)
{
isnext = stream->ReadBit() ? true : false;
if (isnext)
newbl = stream->ReadBit() ? true : false;
if (newbl)
{
newbl = true;
newblindex = stream->ReadBits(6);
newblindex = stream->ReadBits(MAX_BASELINE_BITS);
}
}
if (full && !newbl)
{
isnext = stream->ReadBit() ? true : false;
if (isnext)
if (stream->ReadBit() != 0)
{
offset = stream->ReadBits(6);
offset = stream->ReadBits(MAX_BASELINE_BITS);
}
}
}
@ -1152,10 +1156,10 @@ int World::CompressFrame(frame_t *from, BitBuffer *stream)
unsigned char *start = stream->CurrentByte();
for (auto entnum = 0u; entnum < from->entitynum; entnum++)
{
header.num = entities[entnum].number;
header.custom = (entities[entnum].entityType & ENTITY_BEAM) == ENTITY_BEAM;
header.num = entities[entnum].number;
header.custom = (entities[entnum].entityType & ENTITY_BEAM) == ENTITY_BEAM;
header.newblindex = 0;
header.newbl = false;
header.newbl = false;
entity_state_t *baseline = &m_BaseLines[header.num];
header.offset = FindBestBaseline(entnum, &baseline, entities, header.num, header.custom);
@ -1273,26 +1277,25 @@ bool World::GetDeltaFromCache(unsigned int seqNr, unsigned int deltaNr, BitBuffe
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)
{
int oldmax;
int oldindex;
int newindex;
int newnum;
int oldnum;
entity_state_t *frameEntities;
entity_state_t *deltaEntities;
unsigned int oldmax, oldindex, newindex;
int newnum, oldnum;
entity_state_t *frameEntities, *deltaEntities;
deltacallback_t header;
header.instanced_baseline = (m_MaxInstanced_BaseLine > 0) ? true : false;
header.num = 0;
header.offset = 0;
header.numbase = 0;
header.num = 0;
header.offset = 0;
header.numbase = 0;
header.newblindex = 0;
header.full = false;
header.newbl = false;
header.remove = false;
header.custom = false;
header.newbl = false;
header.remove = false;
header.full = false;
header.custom = false;
if (frame->delta || deltaframe->delta) {
m_System->Errorf("World::WritePacketEntities: frame and delta frame must be uncompressed.\n");
@ -1302,79 +1305,82 @@ void World::WritePacketEntities(BitBuffer *stream, frame_t *frame, frame_t *delt
m_Delta.SetTime(frame->time);
oldmax = deltaframe->entitynum;
newnum = 0; // index in frame->entities
oldnum = 0; // index in deltaframe->entities
newindex = 0; // index in frame->entities
oldindex = 0; // index in deltaframe->entities
frameEntities = (entity_state_t *)frame->entities;
deltaEntities = (entity_state_t *)deltaframe->entities;
stream->StartBitMode();
while (true)
while (newindex < frame->entitynum || oldindex < oldmax)
{
if ((unsigned)newnum < frame->entitynum)
{
newindex = frameEntities[newnum].number;
}
else
{
if (oldnum >= oldmax)
break;
newnum = (newindex >= frame->entitynum) ? ENTITY_SENTINEL : frameEntities[newindex].number;
oldnum = (oldindex >= oldmax) ? ENTITY_SENTINEL : deltaEntities[oldindex].number;
// TODO: Unreachable code
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)
// this is a delta update of the entity from previous position
if (newnum == oldnum)
{
header.custom = (frameEntities[newnum].entityType & ENTITY_BEAM) == ENTITY_BEAM;
header.num = newindex;
// 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.newbl = false;
header.remove = false;
header.newbl = false;
header.remove = false;
delta_t *delta = GetDeltaEncoder(newindex, header.custom);
m_Delta.WriteDelta(stream, (byte *)&deltaEntities[newindex], (byte *)&frameEntities[newnum], false, delta, &header);
delta_t *delta = GetDeltaEncoder(newnum, header.custom);
m_Delta.WriteDelta(stream, (byte *)&deltaEntities[oldindex], (byte *)&frameEntities[newindex], false, delta, &header);
oldnum++;
newnum++;
oldindex++;
newindex++;
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)
{
header.num = oldindex;
header.remove = true;
header.newbl = false;
header.newblindex = 0;
//
// If the entity was not in the old packet (oldnum == 9999),
// then delta from the baseline since this is a new entity
header.custom = (frameEntities[newindex].entityType & ENTITY_BEAM) == ENTITY_BEAM;
header.num = newnum;
header.newblindex = 0;
header.newbl = false;
header.remove = false;
m_Delta.WriteHeader(stream, &header);
++oldnum;
}
delta_t *delta = GetDeltaEncoder(newnum, header.custom);
m_Delta.WriteDelta(stream, (byte *)&m_BaseLines[newnum], (byte *)&frameEntities[newindex], true, delta, &header);
newindex++;
continue;
}
header.custom = (frameEntities[newnum].entityType & ENTITY_BEAM) == ENTITY_BEAM;
header.newblindex = 0;
header.num = newindex;
header.remove = false;
header.newbl = false;
// 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
delta_t *delta = GetDeltaEncoder(newindex, header.custom);
m_Delta.WriteDelta(stream, (byte *)&m_BaseLines[oldnum], (byte *)&frameEntities[newnum], true, delta, &header);
newnum++;
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);
oldindex++;
continue;
}
}
// No more entities.. (end of packet entities)
stream->WriteBits(0, 16);
stream->EndBitMode();
}
@ -1467,13 +1473,14 @@ double World::GetTime()
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)
{
int newnum, oldnum;
int oldindex, newindex;
int newnum, oldnum;
unsigned int oldindex, newindex;
bool remove, custom, newbl;
int newblindex, numbase, offset;
bool remove, custom, newbl;
int newblindex, numbase, offset;
frame_t deltaFrame;
if (!GetUncompressedFrame(from, &deltaFrame)) {
@ -1485,11 +1492,15 @@ bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsi
oldindex = 0;
newindex = 0;
remove = false;
custom = false;
newbl = false;
numbase = 0;
newblindex = 0;
numbase = 0;
newbl = false;
remove = false;
custom = false;
//
// Parse uncompress entities
//
m_Delta.SetTime(frame->time);
stream->StartBitMode();
@ -1500,60 +1511,75 @@ bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsi
while (stream->PeekBits(16))
{
newnum = ParseDeltaHeader(stream, remove, custom, numbase, newbl, newblindex, false, offset);
oldnum = (oldindex >= deltaFrame.entitynum) ? ENTITY_SENTINEL : deltaEntity[oldindex].number;
if ((unsigned)oldindex < deltaFrame.entitynum)
oldnum = deltaEntity[oldindex].number;
else
oldnum = 9999;
while (newnum > oldnum)
while (oldnum < newnum)
{
//
// one or more entities from the old packet are unchanged
if (newindex >= MAX_PACKET_ENTITIES)
{
m_System->DPrintf("WARNING!World::UncompressEntitiesFromStream: newindex >= MAX_PACKET_ENTITIES.\n");
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]));
newindex++;
oldindex++;
if ((unsigned)oldindex < deltaFrame.entitynum)
oldnum = deltaEntity[oldindex].number;
else
oldnum = 9999;
// lookup next index
oldnum = (oldindex >= deltaFrame.entitynum) ? ENTITY_SENTINEL : deltaEntity[oldindex].number;
}
if (newnum >= oldnum)
// delta from previous state
if (newnum == oldnum)
{
if (newnum == oldnum)
if (remove)
{
if (remove)
{
++oldindex;
}
else
{
entity[newindex].entityType = custom ? ENTITY_BEAM : ENTITY_NORMAL;
delta_t *delta = GetDeltaEncoder(newnum, custom);
m_Delta.ParseDelta(stream, (byte *)&deltaEntity[oldindex], (byte *)&entity[newindex], delta);
entity[newindex].number = newnum;
++newindex;
++oldindex;
}
oldindex++;
continue;
}
//
// Insert new the entity to frame
entity[newindex].entityType = custom ? ENTITY_BEAM : ENTITY_NORMAL;
delta_t *delta = GetDeltaEncoder(newnum, custom);
m_Delta.ParseDelta(stream, (byte *)&deltaEntity[oldindex], (byte *)&entity[newindex], delta);
entity[newindex].number = newnum;
newindex++;
oldindex++;
continue;
}
else if (!remove)
// Figure out how we want to update the entity
// 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)
{
m_System->DPrintf("World::UncompressEntitiesFromStream: newindex >= MAX_PACKET_ENTITIES.\n");
stream->m_Overflowed = true;
}
//
// Insert new the entity to frame
entity_state_t *baseline;
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);
entity[newindex].number = newnum;
newindex++;
continue;
}
}
// peek bit == 0 end of packet entities
if (stream->ReadShort())
{
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();
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)
{
@ -1593,33 +1625,22 @@ bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream, unsi
stream->m_Overflowed = true;
}
// copy everything to the new state we are delta'ing
Q_memcpy(&entity[newindex], &deltaEntity[oldindex], sizeof(entity[newindex]));
newindex++;
oldindex++;
}
if (newindex != frame->entitynum) {
m_System->DPrintf("WARNING! World::UncompressEntitiesFromStream: newindex != frame->entitynum.\n");
}
return true;
}
bool World::UncompressEntitiesFromStream(frame_t *frame, BitBuffer *stream)
{
int num;
int newindex = 0;
int entnum = frame->entitynum;
int num, newindex = 0;
int entnum = frame->entitynum;
entity_state_t *baseline;
bool remove, custom, newbl;
int newblindex, numbase, offset;
newblindex = 0;
numbase = 0;
remove = false;
custom = false;
newbl = false;
bool remove = false, custom = false, newbl = false;
int newblindex = 0, numbase = 0, offset;
entity_state_t *entities = (entity_state_t *)frame->entities;
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);
Q_memset(frame->entities, 0, frame->entitiesSize);
int newsize = CompressFrame(&fullFrame, &tempStream);
if ((unsigned)newsize > frame->entitiesSize || tempStream.IsOverflowed()) {
unsigned int newsize = CompressFrame(&fullFrame, &tempStream);
if (newsize > frame->entitiesSize || tempStream.IsOverflowed()) {
m_System->Printf("WARNING! World::RearrangeFrame: wrong entities size (%i != %i).\n", frame->entitiesSize, newsize);
return;
}

View File

@ -39,6 +39,9 @@
#define RESOURCE_INDEX_BITS 12
#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 {
public:
World() {}

View File

@ -98,6 +98,9 @@
// Max size of udp packet 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
{
svc_bad,

View File

@ -30,6 +30,9 @@
#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
{
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);
}
// 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)
{
packet_entities_t *from;
int oldindex;
int newindex;
int oldnum;
int newnum;
int oldmax;
int numbase;
edict_t *ent;
client_frame_t *fromframe;
packet_entities_t *from; // Entity packet for that frame
delta_t *delta;
int oldindex, newindex;
int oldnum, newnum;
int oldmax;
qboolean custom = FALSE;
int offset;
int numbase = 0;
// fix for https://github.com/dreamstalker/rehlds/issues/24
#ifdef REHLDS_FIXES
@ -4545,159 +4550,163 @@ int SV_CreatePacketEntities_internal(sv_delta_t type, client_t *client, packet_e
uint64 toBaselinesForceMask[MAX_PACKET_ENTITIES];
#endif
numbase = 0;
// See if this is a full update
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;
_mm_prefetch((const char*)&from->entities[0], _MM_HINT_T0);
_mm_prefetch(((const char*)&from->entities[0]) + 64, _MM_HINT_T0);
oldmax = from->num_entities;
MSG_WriteByte(msg, svc_deltapacketentities);
MSG_WriteShort(msg, to->num_entities);
MSG_WriteByte(msg, client->delta_sequence);
oldmax = fromframe->entities.num_entities;
MSG_WriteByte(msg, svc_deltapacketentities); // This is a delta
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
{
oldmax = 0;
oldmax = 0; // no delta update
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
oldnum = 0; //index in from->entities
newindex = 0; // index in to->entities
oldindex = 0; // index in from->entities
MSG_StartBitWriting(msg);
while (1)
while (newindex < to->num_entities || oldindex < oldmax)
{
if (newnum < to->num_entities)
{
newindex = to->entities[newnum].number;
}
else
{
if (oldnum >= oldmax)
break;
newnum = (newindex >= to->num_entities) ? ENTITY_SENTINEL : to->entities[newindex].number;
oldnum = (!from || oldindex >= oldmax) ? ENTITY_SENTINEL : from->entities[oldindex].number; // FIXED: from can be null
if (newnum < to->num_entities)
newindex = to->entities[newnum].number;
// this is a delta update of the entity from old 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
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;
}
// Figure out how we want to update the entity
// This is a new entity, send 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
ent = EDICT_NUM(newnum);
custom = (to->entities[newindex].entityType == ENTITY_BEAM) ? TRUE : FALSE;
if (from == NULL)
SV_SetCallback(newnum, FALSE, custom, &numbase, TRUE, 0);
else
newindex = 9999;
}
SV_SetCallback(newnum, FALSE, custom, &numbase, FALSE, 0);
#ifdef REHLDS_FIXES
if (oldnum < oldmax && from)
#else
if (oldnum < oldmax)
#endif
oldindex = from->entities[oldnum].number;
else
oldindex = 9999;
// this is a new entity, send it from the baseline
entity_state_t *baseline = &g_psv.baselines[newnum];
if (newindex == oldindex)
{
entity_state_t *baseline_ = &to->entities[newnum];
qboolean custom = baseline_->entityType & 0x2 ? TRUE : FALSE;
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);
++oldnum;
_mm_prefetch((const char*)&from->entities[oldnum], _MM_HINT_T0);
_mm_prefetch(((const char*)&from->entities[oldnum]) + 64, _MM_HINT_T0);
++newnum;
continue;
}
if (newindex >= oldindex)
{
if (newindex > oldindex)
if (sv_instancedbaseline.value && g_psv.instance_baselines->number != 0 && newnum > sv_lastnum)
{
SV_WriteDeltaHeader(oldindex, TRUE, FALSE, &numbase, FALSE, 0, FALSE, 0);
++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);
qboolean custom = to->entities[newnum].entityType & 0x2 ? TRUE : FALSE;
SV_SetCallback(
newindex,
FALSE,
custom,
&numbase,
from == NULL,
0);
entity_state_t *baseline_ = &g_psv.baselines[newindex];
if (sv_instancedbaseline.value != 0.0f && g_psv.instance_baselines->number != 0 && newindex > sv_lastnum)
{
for (int i = 0; i < g_psv.instance_baselines->number; i++)
{
if (g_psv.instance_baselines->classname[i] == ent->v.classname)
for (int i = 0; i < g_psv.instance_baselines->number; i++)
{
SV_SetNewInfo(i);
baseline_ = &g_psv.instance_baselines->baseline[i];
break;
if (g_psv.instance_baselines->classname[i] == ent->v.classname)
{
SV_SetNewInfo(i);
baseline = &g_psv.instance_baselines->baseline[i];
break;
}
}
}
}
else
{
if (!from)
else
{
int offset = SV_FindBestBaseline(newnum, &baseline_, to->entities, newindex, custom);
_mm_prefetch((const char*)baseline_, _MM_HINT_T0);
_mm_prefetch(((const char*)baseline_) + 64, _MM_HINT_T0);
if (offset)
SV_SetCallback(newindex, FALSE, custom, &numbase, TRUE, offset);
// If this is full update
if (!from)
{
offset = SV_FindBestBaseline(newindex, &baseline, to->entities, newnum, custom);
_mm_prefetch((const char*)baseline, _MM_HINT_T0);
_mm_prefetch(((const char*)baseline) + 64, _MM_HINT_T0);
if (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
if (offset)
baselineToIdx = newnum - offset;
if (offset)
baselineToIdx = newindex - offset;
#endif
}
}
delta = custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newnum) ? g_pplayerdelta : g_pentitydelta);
// fix for https://github.com/dreamstalker/rehlds/issues/24
#ifdef REHLDS_FIXES
DELTA_WriteDeltaForceMask(
(uint8 *)baseline,
(uint8 *)&to->entities[newindex],
TRUE,
delta,
&SV_InvokeCallback,
baselineToIdx != -1 ? &toBaselinesForceMask[baselineToIdx] : NULL
);
baselineToIdx = -1;
uint64 origMask = DELTA_GetOriginalMask(delta);
uint64 usedMask = DELTA_GetMaskU64(delta);
uint64 diffMask = origMask ^ usedMask;
// Remember changed fields that was marked in original mask, but unmarked by the conditional encoder
toBaselinesForceMask[newindex] = diffMask & origMask;
#else // REHLDS_FIXES
DELTA_WriteDelta(
(uint8 *)baseline,
(uint8 *)&to->entities[newindex],
TRUE,
delta,
&SV_InvokeCallback
);
#endif // REHLDS_FIXES
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
delta_t* delta = custom ? g_pcustomentitydelta : (SV_IsPlayerIndex(newindex) ? g_pplayerdelta : g_pentitydelta);
// fix for https://github.com/dreamstalker/rehlds/issues/24
#ifdef REHLDS_FIXES
DELTA_WriteDeltaForceMask(
(uint8 *)baseline_,
(uint8 *)&to->entities[newnum],
TRUE,
delta,
&SV_InvokeCallback,
baselineToIdx != -1 ? &toBaselinesForceMask[baselineToIdx] : NULL
);
baselineToIdx = -1;
uint64 origMask = DELTA_GetOriginalMask(delta);
uint64 usedMask = DELTA_GetMaskU64(delta);
uint64 diffMask = origMask ^ usedMask;
//Remember changed fields that was marked in original mask, but unmarked by the conditional encoder
toBaselinesForceMask[newnum] = diffMask & origMask;
#else //REHLDS_FIXES
DELTA_WriteDelta(
(uint8 *)baseline_,
(uint8 *)&to->entities[newnum],
TRUE,
delta,
&SV_InvokeCallback
);
#endif //REHLDS_FIXES
++newnum;
// 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_EndBitWriting(msg);
return msg->cursize;
}