From: havoc Date: Mon, 16 Apr 2007 07:57:51 +0000 (+0000) Subject: sv.datagram is now flushed to client->unreliablemsg buffers, along with X-Git-Tag: xonotic-v0.1.0preview~3325 X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=5c00b1379d819146fb18968fd9b5fa84bf4a770a sv.datagram is now flushed to client->unreliablemsg buffers, along with logging of good split points so that each effect can be issued to different packets as space allows (sending some each packet), this makes effects finally obey the rate limit cleaned up sending of csqc stats in pre-DP6 protocols and renamed the autosentstats stuff to customstats to better represent what it does implemented stats updates in pre-DP6 protocols (mostly for sake of customstats code cleanlyness) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7105 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/host.c b/host.c index 2ce7a994..b81f181c 100644 --- a/host.c +++ b/host.c @@ -734,9 +734,6 @@ void Host_Main(void) // send all messages to the clients SV_SendClientMessages(); - // clear the general datagram - SV_ClearDatagram(); - // if this server frame took too long, break out of the loop if (framelimit > 1 && Sys_DoubleTime() >= aborttime) break; diff --git a/protocol.c b/protocol.c index 9786497e..2b5c8197 100644 --- a/protocol.c +++ b/protocol.c @@ -419,6 +419,56 @@ void EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int numstates, const entity_sta sv2csqcbuf = NULL; } +void Protocol_UpdateClientStats(const int *stats) +{ + int i; + // update the stats array and set deltabits for any changed stats + for (i = 0;i < MAX_CL_STATS;i++) + { + if (host_client->stats[i] != stats[i]) + { + host_client->statsdeltabits[i >> 3] |= 1 << (i & 7); + host_client->stats[i] = stats[i]; + } + } +} + +void Protocol_WriteStatsReliable(void) +{ + int i; + if (!host_client->netconnection) + return; + // detect changes in stats and write reliable messages + for (i = 0;i < MAX_CL_STATS;i++) + { + // quickly skip zero bytes + if (!host_client->statsdeltabits[i >> 3]) + { + i |= 7; + continue; + } + // check if this bit is set + if (host_client->statsdeltabits[i >> 3] & (1 << (i & 7))) + { + host_client->statsdeltabits[i >> 3] -= (1 << (i & 7)); + // send the stat as a byte if possible + if (host_client->stats[i] >= 0 && host_client->stats[i] < 256) + { + MSG_WriteByte(&host_client->netconnection->message, svc_updatestatubyte); + MSG_WriteByte(&host_client->netconnection->message, i); + MSG_WriteByte(&host_client->netconnection->message, host_client->stats[i]); + } + else + { + MSG_WriteByte(&host_client->netconnection->message, svc_updatestat); + MSG_WriteByte(&host_client->netconnection->message, i); + MSG_WriteLong(&host_client->netconnection->message, host_client->stats[i]); + } + } + } +} + + void EntityFrameQuake_WriteFrame(sizebuf_t *msg, int numstates, const entity_state_t *states) { const entity_state_t *s; @@ -2184,13 +2234,13 @@ void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum) for (j = 0;j < MAX_CL_STATS;j++) { for (l = 0;l < (MAX_CL_STATS+7)/8;l++) - statsdeltabits[l] = p->statsdeltabits[l] & ~d->statsdeltabits[l]; + statsdeltabits[l] = p->statsdeltabits[l] & ~host_client->statsdeltabits[l]; for (k = 0, p2 = d->packetlog;k < ENTITYFRAME5_MAXPACKETLOGS;k++, p2++) if (p2->packetnumber > framenum) for (l = 0;l < (MAX_CL_STATS+7)/8;l++) statsdeltabits[l] = p->statsdeltabits[l] & ~p2->statsdeltabits[l]; for (l = 0;l < (MAX_CL_STATS+7)/8;l++) - d->statsdeltabits[l] |= statsdeltabits[l]; + host_client->statsdeltabits[l] |= statsdeltabits[l]; } // delete this packet log as it is now obsolete p->packetnumber = 0; @@ -2207,7 +2257,7 @@ void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum) d->packetlog[i].packetnumber = 0; } -void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats, int movesequence) +void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int movesequence) { const entity_state_t *n; int i, num, l, framenum, packetlognumber, priority; @@ -2238,16 +2288,6 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num buf.data = data; buf.maxsize = sizeof(data); - // detect changes in stats - for (i = 0;i < MAX_CL_STATS;i++) - { - if (d->stats[i] != stats[i]) - { - d->statsdeltabits[i>>3] |= (1<<(i&7)); - d->stats[i] = stats[i]; - } - } - // detect changes in states num = 1; for (i = 0, n = states;i < numstates;i++, n++) @@ -2326,21 +2366,21 @@ void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int num { for (i = 0;i < MAX_CL_STATS && msg->cursize + 6 + 11 <= msg->maxsize;i++) { - if (d->statsdeltabits[i>>3] & (1<<(i&7))) + if (host_client->statsdeltabits[i>>3] & (1<<(i&7))) { - d->statsdeltabits[i>>3] &= ~(1<<(i&7)); + host_client->statsdeltabits[i>>3] &= ~(1<<(i&7)); packetlog->statsdeltabits[i>>3] |= (1<<(i&7)); - if (d->stats[i] >= 0 && d->stats[i] < 256) + if (host_client->stats[i] >= 0 && host_client->stats[i] < 256) { MSG_WriteByte(msg, svc_updatestatubyte); MSG_WriteByte(msg, i); - MSG_WriteByte(msg, d->stats[i]); + MSG_WriteByte(msg, host_client->stats[i]); } else { MSG_WriteByte(msg, svc_updatestat); MSG_WriteByte(msg, i); - MSG_WriteLong(msg, d->stats[i]); + MSG_WriteLong(msg, host_client->stats[i]); } } } diff --git a/protocol.h b/protocol.h index 95bab550..fd794ce8 100644 --- a/protocol.h +++ b/protocol.h @@ -363,6 +363,13 @@ entity_state_t; extern entity_state_t defaultstate; // reads a quake entity from the network stream void EntityFrameQuake_ReadEntity(int bits); +// checks for stats changes and sets corresponding host_client->statsdeltabits +// (also updates host_client->stats array) +void Protocol_UpdateClientStats(const int *stats); +// writes reliable messages updating stats (not used by DP6 and later +// protocols which send updates in their WriteFrame function using a different +// method of reliable messaging) +void Protocol_WriteStatsReliable(void); // writes a list of quake entities to the network stream // (or as many will fit) void EntityFrameQuake_WriteFrame(sizebuf_t *msg, int numstates, const entity_state_t *states); @@ -734,10 +741,6 @@ typedef struct entityframe5_database_s // (derived from states) unsigned char *visiblebits; // [(maxedicts+7)/8] - // delta compression of stats - unsigned char statsdeltabits[(MAX_CL_STATS+7)/8]; - int stats[MAX_CL_STATS]; - // old notes // this is used to decide which changestates to set each frame @@ -760,7 +763,7 @@ int EntityState5_DeltaBitsForState(entity_state_t *o, entity_state_t *n); void EntityFrame5_CL_ReadFrame(void); void EntityFrame5_LostFrame(entityframe5_database_t *d, int framenum); void EntityFrame5_AckFrame(entityframe5_database_t *d, int framenum); -void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int *stats, int movesequence); +void EntityFrame5_WriteFrame(sizebuf_t *msg, entityframe5_database_t *d, int numstates, const entity_state_t *states, int viewentnum, int movesequence); extern cvar_t developer_networkentities; diff --git a/prvm_exec.c b/prvm_exec.c index 74811148..2a6d44aa 100644 --- a/prvm_exec.c +++ b/prvm_exec.c @@ -598,4 +598,6 @@ cleanup: Con_Printf("PRVM_ExecuteProgram: %s used %i bytes of tempstrings\n", PRVM_GetString(prog->functions[fnum].s_name), vm_tempstringsbuf.cursize - restorevm_tempstringsbuf_cursize); // delete tempstrings created by this function vm_tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; + + SV_FlushBroadcastMessages(); } diff --git a/server.h b/server.h index b977a63a..bd2aabb2 100644 --- a/server.h +++ b/server.h @@ -193,6 +193,15 @@ typedef struct client_s entityframe4_database_t *entitydatabase4; entityframe5_database_t *entitydatabase5; + // delta compression of stats + unsigned char statsdeltabits[(MAX_CL_STATS+7)/8]; + int stats[MAX_CL_STATS]; + + unsigned char unreliablemsg_data[NET_MAXMESSAGE]; + sizebuf_t unreliablemsg; + int unreliablemsg_splitpoints; + int unreliablemsg_splitpoint[NET_MAXMESSAGE/16]; + // information on an active download if any qfile_t *download_file; int download_expectedposition; // next position the client should ack @@ -337,7 +346,6 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection); void SV_DropClient (qboolean crash); void SV_SendClientMessages (void); -void SV_ClearDatagram (void); void SV_ReadClientMessage(void); @@ -381,6 +389,7 @@ trace_t SV_Move(const vec3_t start, const vec3_t mins, const vec3_t maxs, const #define SV_PointSuperContents(point) (SV_Move((point), vec3_origin, vec3_origin, (point), sv_gameplayfix_swiminbmodels.integer ? MOVE_NOMONSTERS : MOVE_WORLDONLY, NULL, 0).startsupercontents) +void SV_FlushBroadcastMessages(void); void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats); void SV_MoveToGoal (void); diff --git a/sv_main.c b/sv_main.c index 8ebe87e0..5a09477d 100644 --- a/sv_main.c +++ b/sv_main.c @@ -25,10 +25,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void SV_VM_Init(); void SV_VM_Setup(); -void VM_AutoSentStats_Clear (void); +void VM_CustomStats_Clear (void); void EntityFrameCSQC_ClearVersions (void); void EntityFrameCSQC_InitClientVersions (int client, qboolean clear); -void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats); +void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats); void EntityFrameCSQC_WriteFrame (sizebuf_t *msg, int numstates, const entity_state_t *states); @@ -209,6 +209,7 @@ void SV_StartParticle (vec3_t org, vec3_t dir, int color, int count) MSG_WriteChar (&sv.datagram, (int)bound(-128, dir[i]*16, 127)); MSG_WriteByte (&sv.datagram, count); MSG_WriteByte (&sv.datagram, color); + SV_FlushBroadcastMessages(); } /* @@ -246,6 +247,7 @@ void SV_StartEffect (vec3_t org, int modelindex, int startframe, int framecount, MSG_WriteByte (&sv.datagram, framecount); MSG_WriteByte (&sv.datagram, framerate); } + SV_FlushBroadcastMessages(); } /* @@ -325,6 +327,7 @@ void SV_StartSound (prvm_edict_t *entity, int channel, const char *sample, int v MSG_WriteByte (&sv.datagram, sound_num); for (i = 0;i < 3;i++) MSG_WriteCoord (&sv.datagram, entity->fields.server->origin[i]+0.5*(entity->fields.server->mins[i]+entity->fields.server->maxs[i]), sv.protocol); + SV_FlushBroadcastMessages(); } /* @@ -495,6 +498,9 @@ void SV_ConnectClient (int clientnum, netconn_t *netconnection) client->edict = PRVM_EDICT_NUM(clientnum+1); if (client->netconnection) client->netconnection->message.allowoverflow = true; // we can catch it + // prepare the unreliable message buffer + client->unreliablemsg.data = client->unreliablemsg_data; + client->unreliablemsg.maxsize = sizeof(client->unreliablemsg_data); // updated by receiving "rate" command from client client->rate = NET_MINRATE; // no limits for local player @@ -534,17 +540,6 @@ FRAME UPDATES =============================================================================== */ -/* -================== -SV_ClearDatagram - -================== -*/ -void SV_ClearDatagram (void) -{ - SZ_Clear (&sv.datagram); -} - /* ============================================================================= @@ -977,7 +972,7 @@ void SV_MarkWriteEntityStateToClient(entity_state_t *s) entity_state_t sendstates[MAX_EDICTS]; extern int csqc_clientnum; -void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, sizebuf_t *msg, int *stats) +void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, sizebuf_t *msg) { int i, numsendstates; entity_state_t *s; @@ -1026,13 +1021,22 @@ void SV_WriteEntitiesToClient(client_t *client, prvm_edict_t *clent, sizebuf_t * EntityFrameCSQC_WriteFrame(msg, numsendstates, sendstates); if (client->entitydatabase5) - EntityFrame5_WriteFrame(msg, client->entitydatabase5, numsendstates, sendstates, client - svs.clients + 1, stats, client->movesequence); + EntityFrame5_WriteFrame(msg, client->entitydatabase5, numsendstates, sendstates, client - svs.clients + 1, client->movesequence); else if (client->entitydatabase4) + { EntityFrame4_WriteFrame(msg, client->entitydatabase4, numsendstates, sendstates); + Protocol_WriteStatsReliable(); + } else if (client->entitydatabase) + { EntityFrame_WriteFrame(msg, client->entitydatabase, numsendstates, sendstates, client - svs.clients + 1); + Protocol_WriteStatsReliable(); + } else + { EntityFrameQuake_WriteFrame(msg, numsendstates, sendstates); + Protocol_WriteStatsReliable(); + } } /* @@ -1288,6 +1292,45 @@ void SV_WriteClientdataToMessage (client_t *client, prvm_edict_t *ent, sizebuf_t } } +void SV_FlushBroadcastMessages(void) +{ + int i; + client_t *client; + if (sv.datagram.cursize <= 0) + return; + for (i = 0, client = svs.clients;i < svs.maxclients;i++, client++) + { + if (!client->spawned || !client->netconnection || client->unreliablemsg.cursize + sv.datagram.cursize > client->unreliablemsg.maxsize || client->unreliablemsg_splitpoints >= (int)(sizeof(client->unreliablemsg_splitpoint)/sizeof(client->unreliablemsg_splitpoint[0]))) + continue; + SZ_Write(&client->unreliablemsg, sv.datagram.data, sv.datagram.cursize); + client->unreliablemsg_splitpoint[client->unreliablemsg_splitpoints++] = client->unreliablemsg.cursize; + } + SZ_Clear(&sv.datagram); +} + +void SV_WriteUnreliableMessages(client_t *client, sizebuf_t *msg) +{ + // scan the splitpoints to find out how many we can fit in + int numsegments, j, split; + for (numsegments = 0;numsegments < client->unreliablemsg_splitpoints;numsegments++) + if (msg->cursize + client->unreliablemsg_splitpoint[numsegments] > msg->maxsize) + break; + if (numsegments > 0) + { + // some will fit, so add the ones that will fit + split = client->unreliablemsg_splitpoint[numsegments-1]; + SZ_Write(msg, client->unreliablemsg.data, split); + // remove the part we sent, keeping any remaining data + client->unreliablemsg.cursize -= split; + if (client->unreliablemsg.cursize > 0) + memmove(client->unreliablemsg.data, client->unreliablemsg.data + split, client->unreliablemsg.cursize); + // adjust remaining splitpoints + client->unreliablemsg_splitpoints -= numsegments; + for (j = 0;j < client->unreliablemsg_splitpoints;j++) + client->unreliablemsg_splitpoint[j] = client->unreliablemsg_splitpoint[numsegments + j] - split; + } +} + /* ======================= SV_SendClientDatagram @@ -1345,17 +1388,21 @@ void SV_SendClientDatagram (client_t *client) // add the client specific data to the datagram SV_WriteClientdataToMessage (client, client->edict, &msg, stats); - VM_SV_WriteAutoSentStats (client, client->edict, &msg, stats); - SV_WriteEntitiesToClient (client, client->edict, &msg, stats); + // now update the stats[] array using any registered custom fields + VM_SV_UpdateCustomStats (client, client->edict, &msg, stats); + // set host_client->statsdeltabits + Protocol_UpdateClientStats (stats); - // expand packet size to allow effects to go over the rate limit - // (dropping them is FAR too ugly) - msg.maxsize = maxsize2; + // add as many queued unreliable messages (effects) as we can fit + // limit effects to half of the remaining space + msg.maxsize -= (msg.maxsize - msg.cursize) / 2; + if (client->unreliablemsg.cursize) + SV_WriteUnreliableMessages (client, &msg); + + msg.maxsize = maxsize; - // copy the server datagram if there is space - // FIXME: put in delayed queue of effects to send - if (sv.datagram.cursize > 0 && msg.cursize + sv.datagram.cursize <= msg.maxsize) - SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize); + // now write as many entities as we can fit, and also sends stats + SV_WriteEntitiesToClient (client, client->edict, &msg); } else if (realtime > client->keepalivetime) { @@ -1498,6 +1545,8 @@ void SV_SendClientMessages (void) if (sv.protocol == PROTOCOL_QUAKEWORLD) Sys_Error("SV_SendClientMessages: no quakeworld support\n"); + SV_FlushBroadcastMessages(); + // update frags, names, etc SV_UpdateToReliableMessages(); @@ -2649,7 +2698,7 @@ void SV_VM_Setup(void) // OP_STATE is always supported on server (due to entvars_t) prog->flag |= PRVM_OP_STATE; - VM_AutoSentStats_Clear();//[515]: csqc + VM_CustomStats_Clear();//[515]: csqc EntityFrameCSQC_ClearVersions();//[515]: csqc PRVM_End; diff --git a/svvm_cmds.c b/svvm_cmds.c index cfe61808..6e8017ff 100644 --- a/svvm_cmds.c +++ b/svvm_cmds.c @@ -1309,102 +1309,51 @@ typedef struct { unsigned char type; // 1/2/8 or other value if isn't used int fieldoffset; -}autosentstat_t; +}customstat_t; -static autosentstat_t *vm_autosentstats = NULL; //[515]: it starts from 0, not 32 -static int vm_autosentstats_last; +static customstat_t *vm_customstats = NULL; //[515]: it starts from 0, not 32 +static int vm_customstats_last; -void VM_AutoSentStats_Clear (void) +void VM_CustomStats_Clear (void) { - if(vm_autosentstats) + if(vm_customstats) { - Z_Free(vm_autosentstats); - vm_autosentstats = NULL; - vm_autosentstats_last = -1; + Z_Free(vm_customstats); + vm_customstats = NULL; + vm_customstats_last = -1; } } -//[515]: add check if even bigger ? "try to use two stats, cause it's too big" ? -#define VM_SENDSTAT(a,b,c)\ -{\ -/* if((c))*/\ - if((c)==(unsigned char)(c))\ - {\ - MSG_WriteByte((a), svc_updatestatubyte);\ - MSG_WriteByte((a), (b));\ - MSG_WriteByte((a), (c));\ - }\ - else\ - {\ - MSG_WriteByte((a), svc_updatestat);\ - MSG_WriteByte((a), (b));\ - MSG_WriteLong((a), (c));\ - }\ -}\ - -void VM_SV_WriteAutoSentStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats) +void VM_SV_UpdateCustomStats (client_t *client, prvm_edict_t *ent, sizebuf_t *msg, int *stats) { - int i, v, *si; + int i; char s[17]; - const char *t; - qboolean send; - union - { - float f; - int i; - }k; - if(!vm_autosentstats) + if(!vm_customstats) return; - send = (sv.protocol != PROTOCOL_QUAKE && sv.protocol != PROTOCOL_QUAKEDP && sv.protocol != PROTOCOL_NEHAHRAMOVIE && sv.protocol != PROTOCOL_DARKPLACES1 && sv.protocol != PROTOCOL_DARKPLACES2 && sv.protocol != PROTOCOL_DARKPLACES3 && sv.protocol != PROTOCOL_DARKPLACES4 && sv.protocol != PROTOCOL_DARKPLACES5); - - for(i=0; i (MAX_CL_STATS-4) with string\n"); return; } - vm_autosentstats[i].type = type; - vm_autosentstats[i].fieldoffset = off; - if(vm_autosentstats_last < i) - vm_autosentstats_last = i; + vm_customstats[i].type = type; + vm_customstats[i].fieldoffset = off; + if(vm_customstats_last < i) + vm_customstats_last = i; } /* @@ -1602,6 +1551,7 @@ static void VM_SV_te_blood (void) MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127)); // count MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255)); + SV_FlushBroadcastMessages(); } static void VM_SV_te_bloodshower (void) @@ -1623,6 +1573,7 @@ static void VM_SV_te_bloodshower (void) MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM2), sv.protocol); // count MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); + SV_FlushBroadcastMessages(); } static void VM_SV_te_explosionrgb (void) @@ -1638,6 +1589,7 @@ static void VM_SV_te_explosionrgb (void) MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[0] * 255), 255)); MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[1] * 255), 255)); MSG_WriteByte(&sv.datagram, bound(0, (int) (PRVM_G_VECTOR(OFS_PARM1)[2] * 255), 255)); + SV_FlushBroadcastMessages(); } static void VM_SV_te_particlecube (void) @@ -1667,6 +1619,7 @@ static void VM_SV_te_particlecube (void) MSG_WriteByte(&sv.datagram, ((int) PRVM_G_FLOAT(OFS_PARM5)) != 0); // randomvel MSG_WriteCoord(&sv.datagram, PRVM_G_FLOAT(OFS_PARM6), sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_particlerain (void) @@ -1692,6 +1645,7 @@ static void VM_SV_te_particlerain (void) MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4)); + SV_FlushBroadcastMessages(); } static void VM_SV_te_particlesnow (void) @@ -1717,6 +1671,7 @@ static void VM_SV_te_particlesnow (void) MSG_WriteShort(&sv.datagram, (int)bound(0, PRVM_G_FLOAT(OFS_PARM3), 65535)); // color MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM4)); + SV_FlushBroadcastMessages(); } static void VM_SV_te_spark (void) @@ -1736,6 +1691,7 @@ static void VM_SV_te_spark (void) MSG_WriteByte(&sv.datagram, bound(-128, (int) PRVM_G_VECTOR(OFS_PARM1)[2], 127)); // count MSG_WriteByte(&sv.datagram, bound(0, (int) PRVM_G_FLOAT(OFS_PARM2), 255)); + SV_FlushBroadcastMessages(); } static void VM_SV_te_gunshotquad (void) @@ -1747,6 +1703,7 @@ static void VM_SV_te_gunshotquad (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_spikequad (void) @@ -1758,6 +1715,7 @@ static void VM_SV_te_spikequad (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_superspikequad (void) @@ -1769,6 +1727,7 @@ static void VM_SV_te_superspikequad (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_explosionquad (void) @@ -1780,6 +1739,7 @@ static void VM_SV_te_explosionquad (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_smallflash (void) @@ -1791,6 +1751,7 @@ static void VM_SV_te_smallflash (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_customflash (void) @@ -1812,6 +1773,7 @@ static void VM_SV_te_customflash (void) MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[0] * 255, 255)); MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[1] * 255, 255)); MSG_WriteByte(&sv.datagram, (int)bound(0, PRVM_G_VECTOR(OFS_PARM3)[2] * 255, 255)); + SV_FlushBroadcastMessages(); } static void VM_SV_te_gunshot (void) @@ -1823,6 +1785,7 @@ static void VM_SV_te_gunshot (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_spike (void) @@ -1834,6 +1797,7 @@ static void VM_SV_te_spike (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_superspike (void) @@ -1845,6 +1809,7 @@ static void VM_SV_te_superspike (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_explosion (void) @@ -1856,6 +1821,7 @@ static void VM_SV_te_explosion (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_tarexplosion (void) @@ -1867,6 +1833,7 @@ static void VM_SV_te_tarexplosion (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_wizspike (void) @@ -1878,6 +1845,7 @@ static void VM_SV_te_wizspike (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_knightspike (void) @@ -1889,6 +1857,7 @@ static void VM_SV_te_knightspike (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_lavasplash (void) @@ -1900,6 +1869,7 @@ static void VM_SV_te_lavasplash (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_teleport (void) @@ -1911,6 +1881,7 @@ static void VM_SV_te_teleport (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_explosion2 (void) @@ -1925,6 +1896,7 @@ static void VM_SV_te_explosion2 (void) // color MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1)); MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2)); + SV_FlushBroadcastMessages(); } static void VM_SV_te_lightning1 (void) @@ -1942,6 +1914,7 @@ static void VM_SV_te_lightning1 (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_lightning2 (void) @@ -1959,6 +1932,7 @@ static void VM_SV_te_lightning2 (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_lightning3 (void) @@ -1976,6 +1950,7 @@ static void VM_SV_te_lightning3 (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_beam (void) @@ -1993,6 +1968,7 @@ static void VM_SV_te_beam (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_plasmaburn (void) @@ -2003,6 +1979,7 @@ static void VM_SV_te_plasmaburn (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[0], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[1], sv.protocol); MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM0)[2], sv.protocol); + SV_FlushBroadcastMessages(); } static void VM_SV_te_flamejet (void) @@ -2020,6 +1997,7 @@ static void VM_SV_te_flamejet (void) MSG_WriteCoord(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1)[2], sv.protocol); // count MSG_WriteByte(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM2)); + SV_FlushBroadcastMessages(); } void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out) @@ -2658,6 +2636,7 @@ static void VM_SV_trailparticles (void) MSG_WriteShort(&sv.datagram, (int)PRVM_G_FLOAT(OFS_PARM1)); MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol); MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM3), sv.protocol); + SV_FlushBroadcastMessages(); } //#337 void(float effectnum, vector origin, vector dir, float count) pointparticles (EXT_CSQC) @@ -2670,6 +2649,7 @@ static void VM_SV_pointparticles (void) MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM1), sv.protocol); MSG_WriteVector(&sv.datagram, PRVM_G_VECTOR(OFS_PARM2), sv.protocol); MSG_WriteShort(&sv.datagram, bound(0, (int)PRVM_G_FLOAT(OFS_PARM3), 65535)); + SV_FlushBroadcastMessages(); } prvm_builtin_t vm_sv_builtins[] = {