diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 29887bcdf..fd5293ab1 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -4204,7 +4204,13 @@ static void QCBUILTIN PF_cvar (pubprogfuncs_t *prinst, struct globalvars_s *pr_g str = PR_GetStringOfs(prinst, OFS_PARM0); if (!strcmp(str, "pr_checkextension")) //no console changing - G_FLOAT(OFS_RETURN) = PR_EnableEBFSBuiltin("checkextension", 0); + { + cvar_t *var = Cvar_FindVar(str); + if (var && !var->ival) + G_FLOAT(OFS_RETURN) = false; + else + G_FLOAT(OFS_RETURN) = PR_EnableEBFSBuiltin("checkextension", 0); + } else if (!strcmp(str, "pr_builtin_find")) G_FLOAT(OFS_RETURN) = PR_EnableEBFSBuiltin("builtin_find", 0); else if (!strcmp(str, "pr_map_builtin")) @@ -10124,13 +10130,13 @@ static void QCBUILTIN PF_setsendneeded(pubprogfuncs_t *prinst, struct globalvars if (!to) { //broadcast for (to = 0; to < sv.allocated_client_slots; to++) - if (svs.clients[to].pendingcsqcbits) + if (svs.clients[to].pendingcsqcbits && subject < svs.clients[to].max_net_ents) svs.clients[to].pendingcsqcbits[subject] |= fl; } else { to--; - if (to >= sv.allocated_client_slots || !svs.clients[to].pendingcsqcbits) + if (to >= sv.allocated_client_slots || !svs.clients[to].pendingcsqcbits || subject >= svs.clients[to].max_net_ents) return; //some kind of error. else svs.clients[to].pendingcsqcbits[subject] |= fl; diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 81c1e7867..0b1d8457f 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -210,6 +210,8 @@ typedef enum GAME_PAUSED_TIC, //(int milliseconds) GAME_CLEAR_EDICT, //v15 (sets self.fields to safe values after they're cleared) + + GAME_EDICT_CSQCSEND=200, //fte entrypoint, called when using SendEntity. } q1qvmgameExport_t; @@ -1872,6 +1874,29 @@ static qintptr_t QVM_pointerstat (void *offset, quintptr_t mask, const qintptr_t return 0; } +//void(entity e, vector flags, entity target) setsendneeded +static qintptr_t QVM_SetSendNeeded(void *offset, quintptr_t mask, const qintptr_t *arg) +{ + unsigned int subject = VM_LONG(arg[0]); + quint64_t fl = arg[1]; + unsigned int to = VM_LONG(arg[2]); + if (!to) + { //broadcast + for (to = 0; to < sv.allocated_client_slots; to++) + if (svs.clients[to].pendingcsqcbits && subject < svs.clients[to].max_net_ents) + svs.clients[to].pendingcsqcbits[subject] |= fl; + } + else + { + to--; + if (to >= sv.allocated_client_slots || !svs.clients[to].pendingcsqcbits || subject >= svs.clients[to].max_net_ents) + ; //some kind of error. + else + svs.clients[to].pendingcsqcbits[subject] |= fl; + } + return 0; +} + static qintptr_t QVM_VisibleTo (void *offset, quintptr_t mask, const qintptr_t *arg) { unsigned int a0 = VM_LONG(arg[0]); @@ -2014,6 +2039,7 @@ struct {"pointparticles", QVM_pointparticles}, {"clientstat", QVM_clientstat}, //csqc extension {"pointerstat", QVM_pointerstat}, //csqc extension + {"setsendneeded", QVM_SetSendNeeded}, //csqc extension {"VisibleTo", QVM_VisibleTo}, //alternative to mvdsv's visclients hack //sql? @@ -2622,6 +2648,11 @@ void Q1QVM_StartFrame(qboolean botsarespecialsnowflakes) VM_Call(q1qvm, GAME_START_FRAME, (qintptr_t)(sv.time*1000), botsarespecialsnowflakes, 0, 0); } +void Q1QVM_SendEntity(quint64_t sendflags) +{ + VM_Call(q1qvm, GAME_EDICT_CSQCSEND, sendflags, 0, 0, 0); +} + void Q1QVM_Blocked(void) { VM_Call(q1qvm, GAME_EDICT_BLOCKED, 0, 0, 0); diff --git a/engine/server/progs.h b/engine/server/progs.h index 781deb5e8..7b6967b7a 100644 --- a/engine/server/progs.h +++ b/engine/server/progs.h @@ -155,6 +155,7 @@ void Q1QVM_RunPlayerThink(void); void Q1QVM_PostThink(void); void Q1QVM_StartFrame(qboolean botsarespecialsnowflakes); void Q1QVM_Blocked(void); +void Q1QVM_SendEntity(quint64_t sendflags); void Q1QVM_SetNewParms(void); void Q1QVM_SetChangeParms(void); qboolean Q1QVM_ClientCommand(void); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index ed9c68a3c..199997224 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -391,14 +391,25 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg, qbyte svcnumber) csqcmsgbuffer.cursize = 0; csqcmsgbuffer.currentbit = 0; - //Ask CSQC to write a buffer for it. - G_INT(OFS_PARM0) = viewerent; - 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); +#ifdef VM_Q1 + if (svs.gametype == GT_Q1QVM) + { + pr_global_struct->other = viewerent; + Q1QVM_SendEntity(bits); + } + else +#endif + { + //Ask CSQC to write a buffer for it. + G_INT(OFS_PARM0) = viewerent; + 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_ExecuteProgram(svprogfuncs, ent->xv->SendEntity); + } + if (G_INT(OFS_RETURN)) //0 means not to tell the client about it. { //FIXME: don't overflow MAX_DATAGRAM... unless its too big anyway...