Add setsendneeded builtin for setting per-player SendFlags.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6064 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2021-10-05 05:04:59 +00:00
parent bca422ab08
commit 7da9b4fcc4
3 changed files with 56 additions and 12 deletions

View File

@ -10140,6 +10140,30 @@ static void QCBUILTIN PF_pointerstat(pubprogfuncs_t *prinst, struct globalvars_s
SV_QCStatPtr(type, prinst->stringtable+addr, num);
}
//void(entity e, vector flags, entity target) setsendneeded
static void QCBUILTIN PF_setsendneeded(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
unsigned int subject = G_EDICTNUM(svprogfuncs, OFS_PARM0);
quint64_t fl = (((quint64_t)G_FLOAT(OFS_PARM1+0)&0xffffff)<<(SENDFLAGS_SHIFT+ 0))
| (((quint64_t)G_FLOAT(OFS_PARM1+1)&0xffffff)<<(SENDFLAGS_SHIFT+24))
| (((quint64_t)G_FLOAT(OFS_PARM1+2)&0xffffff)<<(SENDFLAGS_SHIFT+48));
unsigned int to = G_EDICTNUM(svprogfuncs, OFS_PARM2);
if (!to)
{ //broadcast
for (to = 0; to < sv.allocated_client_slots; to++)
if (svs.clients[to].pendingcsqcbits)
svs.clients[to].pendingcsqcbits[subject] |= fl;
}
else
{
to--;
if (to >= sv.allocated_client_slots || !svs.clients[to].pendingcsqcbits)
return; //some kind of error.
else
svs.clients[to].pendingcsqcbits[subject] |= fl;
}
}
//EXT_CSQC_1
static void QCBUILTIN PF_runclientphys(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
@ -11312,6 +11336,7 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"clientstat", PF_clientstat, 0, 0, 0, 232, D("void(float num, float type, .__variant fld)", "Specifies what data to use in order to send various stats, in a client-specific way.\n'num' should be a value between 32 and 127, other values are reserved.\n'type' must be set to one of the EV_* constants, one of EV_FLOAT, EV_STRING, EV_INTEGER, EV_ENTITY.\nfld must be a reference to the field used, each player will be sent only their own copy of these fields.")}, //EXT_CSQC
{"globalstat", PF_globalstat, 0, 0, 0, 233, D("void(float num, float type, string name)", "Specifies what data to use in order to send various stats, in a non-client-specific way. num and type are as in clientstat, name however, is the name of the global to read in the form of a string (pass \"foo\").")}, //EXT_CSQC_1 actually
{"pointerstat", PF_pointerstat, 0, 0, 0, 0, D("void(float num, float type, __variant *address)", "Specifies what data to use in order to send various stats, in a non-client-specific way. num and type are as in clientstat, address however, is the address of the variable you would like to use (pass &foo).")},
{"setsendneeded", PF_setsendneeded, 0, 0, 0, 0, D("void(entity ent, vector sendflags, entity unicastplayer)", "Flags the entity as needing to be resent. This builtin allows for more bits than supported by the SendEntity field, as well as allows flagging sends to specific players.")},
//END EXT_CSQC
{"isbackbuffered", PF_isbackbuffered, 0, 0, 0, 234, D("float(entity player)", "Returns if the given player's network buffer will take multiple network frames in order to clear. If this builtin returns non-zero, you should delay or reduce the amount of reliable (and also unreliable) data that you are sending to that client.")},
{"rotatevectorsbyangle",PF_rotatevectorsbyangles,0,0, 0, 235, D("void(vector angle)", "rotates the v_forward,v_right,v_up matrix by the specified angles.")}, // #235

View File

@ -352,7 +352,7 @@ typedef struct
{
unsigned int entnum;
unsigned int bits; //delta (fte or dpp5+)
unsigned int flags; //csqc
quint64_t flags; //csqc
} *resend;
unsigned int numresend;
unsigned int maxresend;
@ -589,12 +589,14 @@ typedef struct client_s
} frameunion;
packet_entities_t sentents;
unsigned int *pendingdeltabits;
unsigned int *pendingcsqcbits;
quint64_t *pendingcsqcbits;
unsigned int nextdeltaindex; //splurged round-robin to deal with overflows
unsigned int nextcsqcindex; //splurged round-robin
#define SENDFLAGS_USABLE 0x3fffffffu //this number of bits are actually safe in a float. not all together, but otherwise safe.
#define SENDFLAGS_PRESENT 0x80000000u //this entity is present on that client
#define SENDFLAGS_REMOVED 0x40000000u //to handle remove packetloss
#define SENDFLAGS_PRESENT 0x1u //this entity is present on that client
#define SENDFLAGS_REMOVED 0x2u //to handle remove packetloss
#define SENDFLAGS_RESERVED (SENDFLAGS_PRESENT|SENDFLAGS_REMOVED)
#define SENDFLAGS_SHIFT 2u
#define SENDFLAGS_USABLE (~(quint64_t)SENDFLAGS_RESERVED) //this number of bits are actually safe in a float. not all together, but otherwise safe.
#ifdef HAVE_LEGACY
char *dlqueue; //name\name delimited list of files to ask the client to download.

View File

@ -303,6 +303,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
int entnum;
client_frame_t *frame = &client->frameunion.frames[currentsequence & UPDATE_MASK];
int lognum = frame->numresend;
quint64_t bits;
struct resendinfo_s *resend = frame->resend;
int maxlog = frame->maxresend;
@ -385,11 +386,16 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
if (!(client->pendingcsqcbits[entnum] & SENDFLAGS_PRESENT))
client->pendingcsqcbits[entnum] = SENDFLAGS_USABLE; //this entity appears new. make sure its fully transmitted.
bits = client->pendingcsqcbits[entnum];
client->pendingcsqcbits[entnum] = 0;
csqcmsgbuffer.cursize = 0;
csqcmsgbuffer.currentbit = 0;
//Ask CSQC to write a buffer for it.
G_INT(OFS_PARM0) = viewerent;
G_FLOAT(OFS_PARM1) = (int)(client->pendingcsqcbits[entnum] & 0xffffff);
G_FLOAT(OFS_PARM1+0) = (int)((bits>>(SENDFLAGS_SHIFT+ 0)) & 0xffffff); //each float can only hold 24 bits before it forgets its lower bits.
G_FLOAT(OFS_PARM1+1) = (int)((bits>>(SENDFLAGS_SHIFT+24)) & 0xffffff);
G_FLOAT(OFS_PARM1+2) = (int)((bits>>(SENDFLAGS_SHIFT+48)) & 0xffffff);
pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent);
PR_ExecuteProgram(svprogfuncs, ent->xv->SendEntity);
@ -401,22 +407,27 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
//warn when the message is larger than the user's max size..
if (csqcmsgbuffer.cursize+5 > msg->maxsize)
Con_ThrottlePrintf(&throttle, 0, "CSQC update of entity %i(%s) is larger than user %s's maximum datagram size (%u > %u).\n", entnum, PR_GetString(svprogfuncs, ent->v->classname), client->name, csqcmsgbuffer.cursize, msg->maxsize-5);
client->pendingcsqcbits[entnum] = bits;
if (csqcmsgbuffer.cursize < 32)
break;
continue;
continue; //might be able to fit a different ent in there.
}
if (lognum > maxlog)
{
if (maxlog == client->max_net_ents)
{
client->pendingcsqcbits[entnum] = bits;
break;
}
SV_ExpandNackFrames(client, lognum+1, &frame);
resend = frame->resend;
maxlog = frame->maxresend;
}
resend[lognum].entnum = entnum;
resend[lognum].bits = 0;
resend[lognum].flags = SENDFLAGS_PRESENT|client->pendingcsqcbits[entnum];
resend[lognum].flags = SENDFLAGS_PRESENT|bits;
lognum++;
if (!writtenheader)
@ -433,20 +444,26 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
}
SZ_Write(msg, csqcmsgbuffer.data, csqcmsgbuffer.cursize);
client->pendingcsqcbits[entnum] = SENDFLAGS_PRESENT;
client->pendingcsqcbits[entnum] |= SENDFLAGS_PRESENT;
// Con_Printf("Sending update packet %i\n", ent->entnum);
}
else if ((client->pendingcsqcbits[entnum] & SENDFLAGS_PRESENT) && !((int)ent->xv->pvsflags & PVSF_NOREMOVE))
else if ((bits & SENDFLAGS_PRESENT) && !((int)ent->xv->pvsflags & PVSF_NOREMOVE))
{ //Don't want to send, but they have it already
if (msg->cursize + 5 >= msg->maxsize)
{
client->pendingcsqcbits[entnum] = bits;
break; //we're overflowing, try removing next frame instead.
}
if (lognum > maxlog)
{
if (maxlog == client->max_net_ents)
{
client->pendingcsqcbits[entnum] = bits;
break;
}
SV_ExpandNackFrames(client, lognum+1, &frame);
resend = frame->resend;
maxlog = frame->maxresend;
@ -465,7 +482,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber)
SV_EmitDeltaEntIndex(msg, entnum, true, client->fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS);
// Con_Printf("Sending remove 2 packet\n");
client->pendingcsqcbits[entnum] = 0;
// client->pendingcsqcbits[entnum] = 0;
}
}
@ -4279,7 +4296,7 @@ void SV_ProcessSendFlags(client_t *c)
continue;
if (ent->xv->SendFlags)
{
c->pendingcsqcbits[e] |= (int)ent->xv->SendFlags & SENDFLAGS_USABLE;
c->pendingcsqcbits[e] |= (qint64_t)ent->xv->SendFlags << SENDFLAGS_SHIFT;
h = e;
}
}