diff options
Diffstat (limited to 'src/sv_mvd.c')
-rw-r--r-- | src/sv_mvd.c | 1433 |
1 files changed, 746 insertions, 687 deletions
diff --git a/src/sv_mvd.c b/src/sv_mvd.c index 5c06e81..3707c4c 100644 --- a/src/sv_mvd.c +++ b/src/sv_mvd.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -27,11 +27,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "net_stream.h" #include "mvd_gtv.h" -#define FOR_EACH_GTV( client ) \ - LIST_FOR_EACH( gtv_client_t, client, >v_client_list, entry ) +#define FOR_EACH_GTV(client) \ + LIST_FOR_EACH(gtv_client_t, client, >v_client_list, entry) -#define FOR_EACH_ACTIVE_GTV( client ) \ - LIST_FOR_EACH( gtv_client_t, client, >v_active_list, active ) +#define FOR_EACH_ACTIVE_GTV(client) \ + LIST_FOR_EACH(gtv_client_t, client, >v_active_list, active) typedef struct { list_t entry; @@ -42,13 +42,13 @@ typedef struct { z_stream z; #endif unsigned msglen; - unsigned lastmessage; + unsigned lastmessage; unsigned flags; unsigned maxbuf; unsigned bufcount; - byte buffer[MAX_GTC_MSGLEN+4]; // recv buffer + byte buffer[MAX_GTC_MSGLEN + 4]; // recv buffer byte *data; // send buffer char name[MAX_CLIENT_NAME]; @@ -73,7 +73,7 @@ typedef struct { entity_state_t *entities; // [MAX_EDICTS] // local recorder - qhandle_t recording; + qhandle_t recording; int numlevels; // stop after that many levels int numframes; // stop after that many frames @@ -84,10 +84,10 @@ typedef struct { static mvd_server_t mvd; // TCP client lists -static LIST_DECL( gtv_client_list ); -static LIST_DECL( gtv_active_list ); +static LIST_DECL(gtv_client_list); +static LIST_DECL(gtv_active_list); -static LIST_DECL( gtv_host_list ); +static LIST_DECL(gtv_host_list); static cvar_t *sv_mvd_enable; static cvar_t *sv_mvd_maxclients; @@ -107,20 +107,20 @@ static cvar_t *sv_mvd_disconnect_time; static cvar_t *sv_mvd_suspend_time; static cvar_t *sv_mvd_allow_stufftext; -static qboolean mvd_enable( void ); -static void mvd_disable( void ); -static void mvd_drop( gtv_serverop_t op ); +static qboolean mvd_enable(void); +static void mvd_disable(void); +static void mvd_drop(gtv_serverop_t op); -static void write_stream( gtv_client_t *client, void *data, size_t len ); -static void write_message( gtv_client_t *client, gtv_serverop_t op ); +static void write_stream(gtv_client_t *client, void *data, size_t len); +static void write_message(gtv_client_t *client, gtv_serverop_t op); #if USE_ZLIB -static void flush_stream( gtv_client_t *client, int flush ); +static void flush_stream(gtv_client_t *client, int flush); #endif -static void rec_stop( void ); -static qboolean rec_allowed( void ); -static void rec_start( qhandle_t demofile ); -static void rec_write( void ); +static void rec_stop(void); +static qboolean rec_allowed(void); +static void rec_start(qhandle_t demofile); +static void rec_write(void); /* @@ -138,73 +138,78 @@ for freefloat observers, receive scoreboard updates and text messages, etc. static cmdbuf_t dummy_buffer; static char dummy_buffer_text[MAX_STRING_CHARS]; -static void dummy_wait_f( void ) { - int count = atoi( Cmd_Argv( 1 ) ); +static void dummy_wait_f(void) +{ + int count = atoi(Cmd_Argv(1)); - if( count < 1 ) { + if (count < 1) { count = 1; } dummy_buffer.waitCount = count; } -static void dummy_command( void ) { +static void dummy_command(void) +{ sv_client = mvd.dummy; sv_player = sv_client->edict; - ge->ClientCommand( sv_player ); + ge->ClientCommand(sv_player); sv_client = NULL; sv_player = NULL; } -static void dummy_forward_f( void ) { +static void dummy_forward_f(void) +{ Cmd_Shift(); - Com_DPrintf( "dummy cmd: %s %s\n", Cmd_Argv( 0 ), Cmd_Args() ); + Com_DPrintf("dummy cmd: %s %s\n", Cmd_Argv(0), Cmd_Args()); dummy_command(); } -static void dummy_record_f( void ) { +static void dummy_record_f(void) +{ char buffer[MAX_OSPATH]; qhandle_t f; - if( !sv_mvd_autorecord->integer ) { + if (!sv_mvd_autorecord->integer) { return; } - if( Cmd_Argc() < 2 ) { - Com_Printf( "Usage: %s <filename>\n", Cmd_Argv( 0 ) ); + if (Cmd_Argc() < 2) { + Com_Printf("Usage: %s <filename>\n", Cmd_Argv(0)); return; } - if( !rec_allowed() ) { + if (!rec_allowed()) { return; } - f = FS_EasyOpenFile( buffer, sizeof( buffer ), FS_MODE_WRITE, - "demos/", Cmd_Argv( 1 ), ".mvd2" ); - if( !f ) { + f = FS_EasyOpenFile(buffer, sizeof(buffer), FS_MODE_WRITE, + "demos/", Cmd_Argv(1), ".mvd2"); + if (!f) { return; } - if( !mvd_enable() ) { - FS_FCloseFile( f ); + if (!mvd_enable()) { + FS_FCloseFile(f); return; } - Com_Printf( "Auto-recording local MVD to %s\n", buffer ); + Com_Printf("Auto-recording local MVD to %s\n", buffer); - rec_start( f ); + rec_start(f); } -static void dummy_stop_f( void ) { - if( !sv_mvd_autorecord->integer ) { +static void dummy_stop_f(void) +{ + if (!sv_mvd_autorecord->integer) { return; } - if( !mvd.recording ) { - Com_Printf( "Not recording a local MVD.\n" ); + if (!mvd.recording) { + Com_Printf("Not recording a local MVD.\n"); return; } - Com_Printf( "Stopped local MVD auto-recording.\n" ); + Com_Printf("Stopped local MVD auto-recording.\n"); rec_stop(); } @@ -222,76 +227,78 @@ static const ucmd_t dummy_cmds[] = { { NULL, NULL } }; -static void dummy_exec_string( cmdbuf_t *buf, const char *line ) { +static void dummy_exec_string(cmdbuf_t *buf, const char *line) +{ char *cmd, *alias; const ucmd_t *u; cvar_t *v; - if( !line[0] ) { + if (!line[0]) { return; } - Cmd_TokenizeString( line, qtrue ); + Cmd_TokenizeString(line, qtrue); - cmd = Cmd_Argv( 0 ); - if( !cmd[0] ) { + cmd = Cmd_Argv(0); + if (!cmd[0]) { return; } - if( ( u = Com_Find( dummy_cmds, cmd ) ) != NULL ) { - if( u->func ) { + if ((u = Com_Find(dummy_cmds, cmd)) != NULL) { + if (u->func) { u->func(); } return; } - alias = Cmd_AliasCommand( cmd ); - if( alias ) { - if( ++dummy_buffer.aliasCount == ALIAS_LOOP_COUNT ) { - Com_WPrintf( "%s: runaway alias loop\n", __func__ ); + alias = Cmd_AliasCommand(cmd); + if (alias) { + if (++dummy_buffer.aliasCount == ALIAS_LOOP_COUNT) { + Com_WPrintf("%s: runaway alias loop\n", __func__); return; } - Cbuf_InsertText( &dummy_buffer, alias ); + Cbuf_InsertText(&dummy_buffer, alias); return; } - v = Cvar_FindVar( cmd ); - if( v ) { - Cvar_Command( v ); + v = Cvar_FindVar(cmd); + if (v) { + Cvar_Command(v); return; } - Com_DPrintf( "dummy forward: %s\n", line ); + Com_DPrintf("dummy forward: %s\n", line); dummy_command(); } -static void dummy_add_message( client_t *client, byte *data, - size_t length, qboolean reliable ) +static void dummy_add_message(client_t *client, byte *data, + size_t length, qboolean reliable) { char *text; - if( !length || !reliable || data[0] != svc_stufftext ) { + if (!length || !reliable || data[0] != svc_stufftext) { return; // not interesting } - if( sv_mvd_allow_stufftext->integer <= 0 ) { + if (sv_mvd_allow_stufftext->integer <= 0) { return; // not allowed } data[length] = 0; - text = ( char * )( data + 1 ); - Com_DPrintf( "dummy stufftext: %s\n", text ); - Cbuf_AddText( &dummy_buffer, text ); + text = (char *)(data + 1); + Com_DPrintf("dummy stufftext: %s\n", text); + Cbuf_AddText(&dummy_buffer, text); } -static void dummy_spawn( void ) { +static void dummy_spawn(void) +{ sv_client = mvd.dummy; sv_player = sv_client->edict; - ge->ClientBegin( sv_player ); + ge->ClientBegin(sv_player); sv_client = NULL; sv_player = NULL; - if( sv_mvd_begincmd->string[0] ) { - Cbuf_AddText( &dummy_buffer, sv_mvd_begincmd->string ); + if (sv_mvd_begincmd->string[0]) { + Cbuf_AddText(&dummy_buffer, sv_mvd_begincmd->string); } mvd.layout_time = svs.realtime; @@ -299,23 +306,24 @@ static void dummy_spawn( void ) { mvd.dummy->state = cs_spawned; } -static client_t *dummy_find_slot( void ) { +static client_t *dummy_find_slot(void) +{ client_t *c; int i, j; // first check if there is a free reserved slot j = sv_maxclients->integer - sv_reserved_slots->integer; - for( i = j; i < sv_maxclients->integer; i++ ) { + for (i = j; i < sv_maxclients->integer; i++) { c = &svs.client_pool[i]; - if( !c->state ) { + if (!c->state) { return c; } } // then check regular slots - for( i = 0; i < j; i++ ) { + for (i = 0; i < j; i++) { c = &svs.client_pool[i]; - if( !c->state ) { + if (!c->state) { return c; } } @@ -323,7 +331,8 @@ static client_t *dummy_find_slot( void ) { return NULL; } -static qboolean dummy_create( void ) { +static qboolean dummy_create(void) +{ client_t *newcl; char userinfo[MAX_INFO_STRING]; char *s; @@ -332,73 +341,74 @@ static qboolean dummy_create( void ) { // find a free client slot newcl = dummy_find_slot(); - if( !newcl ) { - Com_EPrintf( "No slot for dummy MVD client\n" ); + if (!newcl) { + Com_EPrintf("No slot for dummy MVD client\n"); return qfalse; } - memset( newcl, 0, sizeof( *newcl ) ); + memset(newcl, 0, sizeof(*newcl)); number = newcl - svs.client_pool; newcl->number = newcl->slot = number; newcl->protocol = -1; newcl->state = cs_connected; newcl->AddMessage = dummy_add_message; - newcl->edict = EDICT_NUM( number + 1 ); - newcl->netchan = SV_Mallocz( sizeof( netchan_t ) ); + newcl->edict = EDICT_NUM(number + 1); + newcl->netchan = SV_Mallocz(sizeof(netchan_t)); newcl->netchan->remote_address.type = NA_LOOPBACK; - List_Init( &newcl->entry ); + List_Init(&newcl->entry); - Q_snprintf( userinfo, sizeof( userinfo ), - "\\name\\[MVDSPEC]\\skin\\male/grunt\\mvdspec\\%d\\ip\\loopback", - PROTOCOL_VERSION_MVD_CURRENT ); + Q_snprintf(userinfo, sizeof(userinfo), + "\\name\\[MVDSPEC]\\skin\\male/grunt\\mvdspec\\%d\\ip\\loopback", + PROTOCOL_VERSION_MVD_CURRENT); mvd.dummy = newcl; // get the game a chance to reject this connection or modify the userinfo sv_client = newcl; sv_player = newcl->edict; - allow = ge->ClientConnect( newcl->edict, userinfo ); + allow = ge->ClientConnect(newcl->edict, userinfo); sv_client = NULL; sv_player = NULL; - if ( !allow ) { - s = Info_ValueForKey( userinfo, "rejmsg" ); - if( *s ) { - Com_EPrintf( "Dummy MVD client rejected by game DLL: %s\n", s ); + if (!allow) { + s = Info_ValueForKey(userinfo, "rejmsg"); + if (*s) { + Com_EPrintf("Dummy MVD client rejected by game DLL: %s\n", s); } mvd.dummy = NULL; return qfalse; } // parse some info from the info strings - strcpy( newcl->userinfo, userinfo ); - SV_UserinfoChanged( newcl ); + strcpy(newcl->userinfo, userinfo); + SV_UserinfoChanged(newcl); return qtrue; } -static void dummy_run( void ) { +static void dummy_run(void) +{ usercmd_t cmd; - Cbuf_Execute( &dummy_buffer ); - if( dummy_buffer.waitCount > 0 ) { + Cbuf_Execute(&dummy_buffer); + if (dummy_buffer.waitCount > 0) { dummy_buffer.waitCount--; } // run ClientThink to prevent timeouts, etc - memset( &cmd, 0, sizeof( cmd ) ); + memset(&cmd, 0, sizeof(cmd)); cmd.msec = BASE_FRAMETIME; sv_client = mvd.dummy; sv_player = sv_client->edict; - ge->ClientThink( sv_player, &cmd ); + ge->ClientThink(sv_player, &cmd); sv_client = NULL; sv_player = NULL; // check if the layout is constantly updated. if not, // game mod has probably closed the scoreboard, open it again - if( mvd.active && sv_mvd_scorecmd->string[0] ) { - if( svs.realtime - mvd.layout_time > 9000 ) { - Cbuf_AddText( &dummy_buffer, sv_mvd_scorecmd->string ); + if (mvd.active && sv_mvd_scorecmd->string[0]) { + if (svs.realtime - mvd.layout_time > 9000) { + Cbuf_AddText(&dummy_buffer, sv_mvd_scorecmd->string); mvd.layout_time = svs.realtime; } } @@ -438,66 +448,67 @@ Entire function is a nasty hack. Ideally a compatible game DLL should do it for us by providing some SVF_* flag or something. ================== */ -static qboolean player_is_active( const edict_t *ent ) { +static qboolean player_is_active(const edict_t *ent) +{ int num; - if( ( g_features->integer & GMF_PROPERINUSE ) && !ent->inuse ) { + if ((g_features->integer & GMF_PROPERINUSE) && !ent->inuse) { return qfalse; } // not a client at all? - if( !ent->client ) { + if (!ent->client) { return qfalse; } - num = NUM_FOR_EDICT( ent ) - 1; - if( num < 0 || num >= sv_maxclients->integer ) { + num = NUM_FOR_EDICT(ent) - 1; + if (num < 0 || num >= sv_maxclients->integer) { return qfalse; } // by default, check if client is actually connected // it may not be the case for bots! - if( sv_mvd_capture_flags->integer & 1 ) { - if( svs.client_pool[num].state != cs_spawned ) { + if (sv_mvd_capture_flags->integer & 1) { + if (svs.client_pool[num].state != cs_spawned) { return qfalse; } } // first of all, make sure player_state_t is valid - if( !ent->client->ps.fov ) { + if (!ent->client->ps.fov) { return qfalse; } // always capture dummy MVD client - if( ent == mvd.dummy->edict ) { + if (ent == mvd.dummy->edict) { return qtrue; } // never capture spectators - if( ent->client->ps.pmove.pm_type == PM_SPECTATOR ) { + if (ent->client->ps.pmove.pm_type == PM_SPECTATOR) { return qfalse; } // check entity visibility - if( ( ent->svflags & SVF_NOCLIENT ) || !ES_INUSE( &ent->s ) ) { + if ((ent->svflags & SVF_NOCLIENT) || !ES_INUSE(&ent->s)) { // never capture invisible entities - if( sv_mvd_capture_flags->integer & 2 ) { + if (sv_mvd_capture_flags->integer & 2) { return qfalse; } } else { // always capture visible entities (default) - if( sv_mvd_capture_flags->integer & 4 ) { + if (sv_mvd_capture_flags->integer & 4) { return qtrue; } } // they are likely following someone in case of PM_FREEZE - if( ent->client->ps.pmove.pm_type == PM_FREEZE ) { + if (ent->client->ps.pmove.pm_type == PM_FREEZE) { return qfalse; } - // they are likely following someone if PMF_NO_PREDICTION is set - if( ent->client->ps.pmove.pm_flags & PMF_NO_PREDICTION ) { + // they are likely following someone if PMF_NO_PREDICTION is set + if (ent->client->ps.pmove.pm_flags & PMF_NO_PREDICTION) { return qfalse; } @@ -511,33 +522,34 @@ build_gamestate Initialize MVD delta compressor for the first time on the given map. ================== */ -static void build_gamestate( void ) { +static void build_gamestate(void) +{ player_state_t *ps; entity_state_t *es; edict_t *ent; int i; - memset( mvd.players, 0, sizeof( player_state_t ) * sv_maxclients->integer ); - memset( mvd.entities, 0, sizeof( entity_state_t ) * MAX_EDICTS ); + memset(mvd.players, 0, sizeof(player_state_t) * sv_maxclients->integer); + memset(mvd.entities, 0, sizeof(entity_state_t) * MAX_EDICTS); // set base player states - for( i = 0; i < sv_maxclients->integer; i++ ) { - ent = EDICT_NUM( i + 1 ); + for (i = 0; i < sv_maxclients->integer; i++) { + ent = EDICT_NUM(i + 1); - if( !player_is_active( ent ) ) { + if (!player_is_active(ent)) { continue; } ps = &mvd.players[i]; *ps = ent->client->ps; - PPS_INUSE( ps ) = qtrue; + PPS_INUSE(ps) = qtrue; } // set base entity states - for( i = 1; i < ge->num_edicts; i++ ) { - ent = EDICT_NUM( i ); + for (i = 1; i < ge->num_edicts; i++) { + ent = EDICT_NUM(i); - if( ( ent->svflags & SVF_NOCLIENT ) || !ES_INUSE( &ent->s ) ) { + if ((ent->svflags & SVF_NOCLIENT) || !ES_INUSE(&ent->s)) { continue; } @@ -556,7 +568,8 @@ Writes a single giant message with all the startup info, followed by an uncompressed (baseline) frame. ================== */ -static void emit_gamestate( void ) { +static void emit_gamestate(void) +{ char *string; int i, j; player_state_t *ps; @@ -567,64 +580,64 @@ static void emit_gamestate( void ) { // pack MVD stream flags into extra bits extra = 0; - if( sv_mvd_nomsgs->integer ) { + if (sv_mvd_nomsgs->integer) { extra |= MVF_NOMSGS << SVCMD_BITS; } // send the serverdata - MSG_WriteByte( mvd_serverdata | extra ); - MSG_WriteLong( PROTOCOL_VERSION_MVD ); - MSG_WriteShort( PROTOCOL_VERSION_MVD_CURRENT ); - MSG_WriteLong( sv.spawncount ); - MSG_WriteString( fs_game->string ); - MSG_WriteShort( mvd.dummy->number ); + MSG_WriteByte(mvd_serverdata | extra); + MSG_WriteLong(PROTOCOL_VERSION_MVD); + MSG_WriteShort(PROTOCOL_VERSION_MVD_CURRENT); + MSG_WriteLong(sv.spawncount); + MSG_WriteString(fs_game->string); + MSG_WriteShort(mvd.dummy->number); // send configstrings - for( i = 0; i < MAX_CONFIGSTRINGS; i++ ) { + for (i = 0; i < MAX_CONFIGSTRINGS; i++) { string = sv.configstrings[i]; - if( !string[0] ) { + if (!string[0]) { continue; } - length = strlen( string ); - if( length > MAX_QPATH ) { + length = strlen(string); + if (length > MAX_QPATH) { length = MAX_QPATH; } - MSG_WriteShort( i ); - MSG_WriteData( string, length ); - MSG_WriteByte( 0 ); + MSG_WriteShort(i); + MSG_WriteData(string, length); + MSG_WriteByte(0); } - MSG_WriteShort( MAX_CONFIGSTRINGS ); + MSG_WriteShort(MAX_CONFIGSTRINGS); // send baseline frame - portalbytes = CM_WritePortalBits( &sv.cm, portalbits ); - MSG_WriteByte( portalbytes ); - MSG_WriteData( portalbits, portalbytes ); - + portalbytes = CM_WritePortalBits(&sv.cm, portalbits); + MSG_WriteByte(portalbytes); + MSG_WriteData(portalbits, portalbytes); + // send player states flags = 0; - if( sv_mvd_noblend->integer ) { + if (sv_mvd_noblend->integer) { flags |= MSG_PS_IGNORE_BLEND; } - if( sv_mvd_nogun->integer ) { - flags |= MSG_PS_IGNORE_GUNINDEX|MSG_PS_IGNORE_GUNFRAMES; + if (sv_mvd_nogun->integer) { + flags |= MSG_PS_IGNORE_GUNINDEX | MSG_PS_IGNORE_GUNFRAMES; } - for( i = 0, ps = mvd.players; i < sv_maxclients->integer; i++, ps++ ) { + for (i = 0, ps = mvd.players; i < sv_maxclients->integer; i++, ps++) { extra = 0; - if( !PPS_INUSE( ps ) ) { + if (!PPS_INUSE(ps)) { extra |= MSG_PS_REMOVE; } - MSG_WriteDeltaPlayerstate_Packet( NULL, ps, i, flags | extra ); + MSG_WriteDeltaPlayerstate_Packet(NULL, ps, i, flags | extra); } - MSG_WriteByte( CLIENTNUM_NONE ); + MSG_WriteByte(CLIENTNUM_NONE); // send entity states - for( i = 1, es = mvd.entities + 1; i < ge->num_edicts; i++, es++ ) { + for (i = 1, es = mvd.entities + 1; i < ge->num_edicts; i++, es++) { flags = MSG_ES_UMASK; - if( ( j = es->number ) != 0 ) { - if( i <= sv_maxclients->integer ) { - ps = &mvd.players[ i - 1 ]; - if( PPS_INUSE( ps ) && ps->pmove.pm_type == PM_NORMAL ) { + if ((j = es->number) != 0) { + if (i <= sv_maxclients->integer) { + ps = &mvd.players[i - 1]; + if (PPS_INUSE(ps) && ps->pmove.pm_type == PM_NORMAL) { flags |= MSG_ES_FIRSTPERSON; } } @@ -632,18 +645,19 @@ static void emit_gamestate( void ) { flags |= MSG_ES_REMOVE; } es->number = i; - MSG_WriteDeltaEntity( NULL, es, flags ); + MSG_WriteDeltaEntity(NULL, es, flags); es->number = j; } - MSG_WriteShort( 0 ); + MSG_WriteShort(0); } -static void copy_entity_state( entity_state_t *dst, const entity_state_t *src, int flags ) { - if( !( flags & MSG_ES_FIRSTPERSON ) ) { - VectorCopy( src->origin, dst->origin ); - VectorCopy( src->angles, dst->angles ); - VectorCopy( src->old_origin, dst->old_origin ); +static void copy_entity_state(entity_state_t *dst, const entity_state_t *src, int flags) +{ + if (!(flags & MSG_ES_FIRSTPERSON)) { + VectorCopy(src->origin, dst->origin); + VectorCopy(src->angles, dst->angles); + VectorCopy(src->old_origin, dst->old_origin); } dst->modelindex = src->modelindex; dst->modelindex2 = src->modelindex2; @@ -667,7 +681,8 @@ and calculating portalbits. The same frame is used for all MVD clients, as well as local recorder. ================== */ -static void emit_frame( void ) { +static void emit_frame(void) +{ player_state_t *oldps, *newps; entity_state_t *oldes, *newes; edict_t *ent; @@ -675,156 +690,159 @@ static void emit_frame( void ) { byte portalbits[MAX_MAP_PORTAL_BYTES]; int i; - MSG_WriteByte( mvd_frame ); + MSG_WriteByte(mvd_frame); // send portal bits - portalbytes = CM_WritePortalBits( &sv.cm, portalbits ); - MSG_WriteByte( portalbytes ); - MSG_WriteData( portalbits, portalbytes ); - - flags = MSG_PS_IGNORE_PREDICTION|MSG_PS_IGNORE_DELTAANGLES; - if( sv_mvd_noblend->integer ) { + portalbytes = CM_WritePortalBits(&sv.cm, portalbits); + MSG_WriteByte(portalbytes); + MSG_WriteData(portalbits, portalbytes); + + flags = MSG_PS_IGNORE_PREDICTION | MSG_PS_IGNORE_DELTAANGLES; + if (sv_mvd_noblend->integer) { flags |= MSG_PS_IGNORE_BLEND; } - if( sv_mvd_nogun->integer ) { - flags |= MSG_PS_IGNORE_GUNINDEX|MSG_PS_IGNORE_GUNFRAMES; + if (sv_mvd_nogun->integer) { + flags |= MSG_PS_IGNORE_GUNINDEX | MSG_PS_IGNORE_GUNFRAMES; } // send player states - for( i = 0; i < sv_maxclients->integer; i++ ) { - ent = EDICT_NUM( i + 1 ); + for (i = 0; i < sv_maxclients->integer; i++) { + ent = EDICT_NUM(i + 1); oldps = &mvd.players[i]; newps = &ent->client->ps; - if( !player_is_active( ent ) ) { - if( PPS_INUSE( oldps ) ) { + if (!player_is_active(ent)) { + if (PPS_INUSE(oldps)) { // the old player isn't present in the new message - MSG_WriteDeltaPlayerstate_Packet( NULL, NULL, i, flags ); - PPS_INUSE( oldps ) = qfalse; + MSG_WriteDeltaPlayerstate_Packet(NULL, NULL, i, flags); + PPS_INUSE(oldps) = qfalse; } continue; } - if( PPS_INUSE( oldps ) ) { + if (PPS_INUSE(oldps)) { // delta update from old position // because the force parm is false, this will not result // in any bytes being emited if the player has not changed at all - MSG_WriteDeltaPlayerstate_Packet( oldps, newps, i, flags ); + MSG_WriteDeltaPlayerstate_Packet(oldps, newps, i, flags); } else { // this is a new player, send it from the last state - MSG_WriteDeltaPlayerstate_Packet( oldps, newps, i, - flags | MSG_PS_FORCE ); + MSG_WriteDeltaPlayerstate_Packet(oldps, newps, i, + flags | MSG_PS_FORCE); } // shuffle current state to previous *oldps = *newps; - PPS_INUSE( oldps ) = qtrue; + PPS_INUSE(oldps) = qtrue; } - MSG_WriteByte( CLIENTNUM_NONE ); // end of packetplayers + MSG_WriteByte(CLIENTNUM_NONE); // end of packetplayers // send entity states - for( i = 1; i < ge->num_edicts; i++ ) { - ent = EDICT_NUM( i ); + for (i = 1; i < ge->num_edicts; i++) { + ent = EDICT_NUM(i); oldes = &mvd.entities[i]; newes = &ent->s; - if( ( ent->svflags & SVF_NOCLIENT ) || !ES_INUSE( newes ) ) { - if( oldes->number ) { + if ((ent->svflags & SVF_NOCLIENT) || !ES_INUSE(newes)) { + if (oldes->number) { // the old entity isn't present in the new message - MSG_WriteDeltaEntity( oldes, NULL, MSG_ES_FORCE ); + MSG_WriteDeltaEntity(oldes, NULL, MSG_ES_FORCE); oldes->number = 0; } continue; } - if( newes->number != i ) { - Com_WPrintf( "%s: fixing ent->s.number: %d to %d\n", - __func__, newes->number, i ); + if (newes->number != i) { + Com_WPrintf("%s: fixing ent->s.number: %d to %d\n", + __func__, newes->number, i); newes->number = i; } // calculate flags flags = MSG_ES_UMASK; - if( i <= sv_maxclients->integer ) { - oldps = &mvd.players[ i - 1 ]; - if( PPS_INUSE( oldps ) && oldps->pmove.pm_type == PM_NORMAL ) { + if (i <= sv_maxclients->integer) { + oldps = &mvd.players[i - 1]; + if (PPS_INUSE(oldps) && oldps->pmove.pm_type == PM_NORMAL) { // do not waste bandwidth on origin/angle updates, // client will recover them from player state flags |= MSG_ES_FIRSTPERSON; } } - - if( !oldes->number ) { + + if (!oldes->number) { // this is a new entity, send it from the last state - flags |= MSG_ES_FORCE|MSG_ES_NEWENTITY; + flags |= MSG_ES_FORCE | MSG_ES_NEWENTITY; } - - MSG_WriteDeltaEntity( oldes, newes, flags ); + + MSG_WriteDeltaEntity(oldes, newes, flags); // shuffle current state to previous - copy_entity_state( oldes, newes, flags ); + copy_entity_state(oldes, newes, flags); oldes->number = i; } - MSG_WriteShort( 0 ); // end of packetentities + MSG_WriteShort(0); // end of packetentities } -static void suspend_streams( void ) { +static void suspend_streams(void) +{ gtv_client_t *client; - FOR_EACH_ACTIVE_GTV( client ) { + FOR_EACH_ACTIVE_GTV(client) { // send stream suspend marker - write_message( client, GTS_STREAM_DATA ); + write_message(client, GTS_STREAM_DATA); #if USE_ZLIB - flush_stream( client, Z_SYNC_FLUSH ); + flush_stream(client, Z_SYNC_FLUSH); #endif - NET_UpdateStream( &client->stream ); + NET_UpdateStream(&client->stream); } - Com_DPrintf( "Suspending MVD streams.\n" ); + Com_DPrintf("Suspending MVD streams.\n"); mvd.active = qfalse; } -static void resume_streams( void ) { +static void resume_streams(void) +{ gtv_client_t *client; // build and emit gamestate build_gamestate(); emit_gamestate(); - FOR_EACH_ACTIVE_GTV( client ) { + FOR_EACH_ACTIVE_GTV(client) { // send gamestate - write_message( client, GTS_STREAM_DATA ); + write_message(client, GTS_STREAM_DATA); #if USE_ZLIB - flush_stream( client, Z_SYNC_FLUSH ); + flush_stream(client, Z_SYNC_FLUSH); #endif - NET_UpdateStream( &client->stream ); + NET_UpdateStream(&client->stream); } // write it to demofile - if( mvd.recording ) { + if (mvd.recording) { rec_write(); } // clear gamestate - SZ_Clear( &msg_write ); + SZ_Clear(&msg_write); - SZ_Clear( &mvd.datagram ); - SZ_Clear( &mvd.message ); + SZ_Clear(&mvd.datagram); + SZ_Clear(&mvd.message); - Com_DPrintf( "Resuming MVD streams.\n" ); + Com_DPrintf("Resuming MVD streams.\n"); mvd.active = qtrue; } -static qboolean players_active( void ) { +static qboolean players_active(void) +{ int i; edict_t *ent; - for( i = 0; i < sv_maxclients->integer; i++ ) { - ent = EDICT_NUM( i + 1 ); - if( ent != mvd.dummy->edict && player_is_active( ent ) ) { + for (i = 0; i < sv_maxclients->integer; i++) { + ent = EDICT_NUM(i + 1); + if (ent != mvd.dummy->edict && player_is_active(ent)) { return qtrue; } } @@ -836,11 +854,12 @@ static qboolean players_active( void ) { SV_MvdBeginFrame ================== */ -void SV_MvdBeginFrame( void ) { +void SV_MvdBeginFrame(void) +{ unsigned delta; // do nothing if not enabled - if( !mvd.dummy ) { + if (!mvd.dummy) { return; } @@ -848,62 +867,61 @@ void SV_MvdBeginFrame( void ) { // disconnect MVD dummy if no MVD clients are active for some time // FIXME: should not really count unauthenticated/zombie clients - if( !delta || mvd.recording || !LIST_EMPTY( >v_client_list ) ) { + if (!delta || mvd.recording || !LIST_EMPTY(>v_client_list)) { mvd.clients_active = svs.realtime; - } else if( svs.realtime - mvd.clients_active > delta ) { - Com_DPrintf( "Disconnecting dummy MVD client.\n" ); - SV_DropClient( mvd.dummy, NULL ); + } else if (svs.realtime - mvd.clients_active > delta) { + Com_DPrintf("Disconnecting dummy MVD client.\n"); + SV_DropClient(mvd.dummy, NULL); return; } delta = sv_mvd_suspend_time->value * 60 * 1000; // suspend/resume MVD streams depending on players activity - if( !delta || players_active() ) { + if (!delta || players_active()) { mvd.players_active = svs.realtime; - if( !mvd.active ) { + if (!mvd.active) { resume_streams(); } - } else if( mvd.active ) { - if( svs.realtime - mvd.players_active > delta ) { + } else if (mvd.active) { + if (svs.realtime - mvd.players_active > delta) { suspend_streams(); } } } -static void rec_frame( size_t total ) { +static void rec_frame(size_t total) +{ uint16_t msglen; ssize_t ret; - if( !total ) + if (!total) return; - msglen = LittleShort( total ); - ret = FS_Write( &msglen, 2, mvd.recording ); - if( ret != 2 ) + msglen = LittleShort(total); + ret = FS_Write(&msglen, 2, mvd.recording); + if (ret != 2) goto fail; - ret = FS_Write( mvd.message.data, mvd.message.cursize, mvd.recording ); - if( ret != mvd.message.cursize ) + ret = FS_Write(mvd.message.data, mvd.message.cursize, mvd.recording); + if (ret != mvd.message.cursize) goto fail; - ret = FS_Write( msg_write.data, msg_write.cursize, mvd.recording ); - if( ret != msg_write.cursize ) + ret = FS_Write(msg_write.data, msg_write.cursize, mvd.recording); + if (ret != msg_write.cursize) goto fail; - ret = FS_Write( mvd.datagram.data, mvd.datagram.cursize, mvd.recording ); - if( ret != mvd.datagram.cursize ) + ret = FS_Write(mvd.datagram.data, mvd.datagram.cursize, mvd.recording); + if (ret != mvd.datagram.cursize) goto fail; - if( sv_mvd_maxsize->value > 0 && - FS_Tell( mvd.recording ) > sv_mvd_maxsize->value * 1000 ) - { - Com_Printf( "Stopping MVD recording, maximum size reached.\n" ); + if (sv_mvd_maxsize->value > 0 && + FS_Tell(mvd.recording) > sv_mvd_maxsize->value * 1000) { + Com_Printf("Stopping MVD recording, maximum size reached.\n"); rec_stop(); return; } - if( sv_mvd_maxtime->value > 0 && - ++mvd.numframes > sv_mvd_maxtime->value * 600 ) - { - Com_Printf( "Stopping MVD recording, maximum duration reached.\n" ); + if (sv_mvd_maxtime->value > 0 && + ++mvd.numframes > sv_mvd_maxtime->value * 600) { + Com_Printf("Stopping MVD recording, maximum duration reached.\n"); rec_stop(); return; } @@ -911,7 +929,7 @@ static void rec_frame( size_t total ) { return; fail: - Com_EPrintf( "Couldn't write local MVD: %s\n", Q_ErrorString( ret ) ); + Com_EPrintf("Couldn't write local MVD: %s\n", Q_ErrorString(ret)); rec_stop(); } @@ -920,86 +938,87 @@ fail: SV_MvdEndFrame ================== */ -void SV_MvdEndFrame( void ) { +void SV_MvdEndFrame(void) +{ gtv_client_t *client; size_t total; byte header[3]; - if( !SV_FRAMESYNC ) + if (!SV_FRAMESYNC) return; // do nothing if not enabled - if( !mvd.dummy ) { + if (!mvd.dummy) { return; } dummy_run(); // do nothing if not active - if( !mvd.active ) { + if (!mvd.active) { return; } // if reliable message overflowed, kick all clients - if( mvd.message.overflowed ) { - Com_EPrintf( "Reliable MVD message overflowed!\n" ); - SV_DropClient( mvd.dummy, NULL ); + if (mvd.message.overflowed) { + Com_EPrintf("Reliable MVD message overflowed!\n"); + SV_DropClient(mvd.dummy, NULL); return; } - if( mvd.datagram.overflowed ) { - Com_WPrintf( "Unreliable MVD datagram overflowed.\n" ); - SZ_Clear( &mvd.datagram ); + if (mvd.datagram.overflowed) { + Com_WPrintf("Unreliable MVD datagram overflowed.\n"); + SZ_Clear(&mvd.datagram); } // emit a delta update common to all clients emit_frame(); // if reliable message and frame update don't fit, kick all clients - if( mvd.message.cursize + msg_write.cursize >= MAX_MSGLEN ) { - Com_EPrintf( "MVD frame overflowed!\n" ); - SZ_Clear( &msg_write ); - SV_DropClient( mvd.dummy, NULL ); + if (mvd.message.cursize + msg_write.cursize >= MAX_MSGLEN) { + Com_EPrintf("MVD frame overflowed!\n"); + SZ_Clear(&msg_write); + SV_DropClient(mvd.dummy, NULL); return; } // check if unreliable datagram fits - if( mvd.message.cursize + msg_write.cursize + mvd.datagram.cursize >= MAX_MSGLEN ) { - Com_WPrintf( "Dumping unreliable MVD datagram.\n" ); - SZ_Clear( &mvd.datagram ); + if (mvd.message.cursize + msg_write.cursize + mvd.datagram.cursize >= MAX_MSGLEN) { + Com_WPrintf("Dumping unreliable MVD datagram.\n"); + SZ_Clear(&mvd.datagram); } // build message header total = mvd.message.cursize + msg_write.cursize + mvd.datagram.cursize + 1; header[0] = total & 255; - header[1] = ( total >> 8 ) & 255; + header[1] = (total >> 8) & 255; header[2] = GTS_STREAM_DATA; // send frame to clients - FOR_EACH_ACTIVE_GTV( client ) { - write_stream( client, header, sizeof( header ) ); - write_stream( client, mvd.message.data, mvd.message.cursize ); - write_stream( client, msg_write.data, msg_write.cursize ); - write_stream( client, mvd.datagram.data, mvd.datagram.cursize ); + FOR_EACH_ACTIVE_GTV(client) { + write_stream(client, header, sizeof(header)); + write_stream(client, mvd.message.data, mvd.message.cursize); + write_stream(client, msg_write.data, msg_write.cursize); + write_stream(client, mvd.datagram.data, mvd.datagram.cursize); #if USE_ZLIB - if( ++client->bufcount > client->maxbuf ) { - flush_stream( client, Z_SYNC_FLUSH ); + if (++client->bufcount > client->maxbuf) { + flush_stream(client, Z_SYNC_FLUSH); } #endif - NET_UpdateStream( &client->stream ); + NET_UpdateStream(&client->stream); } // write frame to demofile - if( mvd.recording ) { - rec_frame( total - 1 ); + if (mvd.recording) { + rec_frame(total - 1); } // clear frame - SZ_Clear( &msg_write ); + SZ_Clear(&msg_write); // clear datagrams - SZ_Clear( &mvd.datagram ); - SZ_Clear( &mvd.message ); + SZ_Clear(&mvd.datagram); + SZ_Clear(&mvd.message); } @@ -1024,28 +1043,29 @@ into one larger message to save space (useful for shotgun patterns as they often occur in the same BSP leaf) ============== */ -void SV_MvdMulticast( int leafnum, multicast_t to ) { +void SV_MvdMulticast(int leafnum, multicast_t to) +{ mvd_ops_t op; sizebuf_t *buf; int bits; - + // do nothing if not active - if( !mvd.active ) { + if (!mvd.active) { return; } op = mvd_multicast_all + to; buf = to < MULTICAST_ALL_R ? &mvd.datagram : &mvd.message; - bits = ( msg_write.cursize >> 8 ) & 7; + bits = (msg_write.cursize >> 8) & 7; - SZ_WriteByte( buf, op | ( bits << SVCMD_BITS ) ); - SZ_WriteByte( buf, msg_write.cursize & 255 ); + SZ_WriteByte(buf, op | (bits << SVCMD_BITS)); + SZ_WriteByte(buf, msg_write.cursize & 255); - if( op != mvd_multicast_all && op != mvd_multicast_all_r ) { - SZ_WriteShort( buf, leafnum ); + if (op != mvd_multicast_all && op != mvd_multicast_all_r) { + SZ_WriteShort(buf, leafnum); } - - SZ_Write( buf, msg_write.data, msg_write.cursize ); + + SZ_Write(buf, msg_write.data, msg_write.cursize); } /* @@ -1056,24 +1076,25 @@ Performs some basic filtering of the unicast data that would be otherwise discarded by the MVD client. ============== */ -void SV_MvdUnicast( edict_t *ent, int clientNum, qboolean reliable ) { +void SV_MvdUnicast(edict_t *ent, int clientNum, qboolean reliable) +{ mvd_ops_t op; sizebuf_t *buf; int bits; // do nothing if not active - if( !mvd.active ) { + if (!mvd.active) { return; } // discard any data to players not in the game - if( !player_is_active( ent ) ) { + if (!player_is_active(ent)) { return; } - switch( msg_write.data[0] ) { + switch (msg_write.data[0]) { case svc_layout: - if( ent == mvd.dummy->edict ) { + if (ent == mvd.dummy->edict) { // special case, send to all observers mvd.layout_time = svs.realtime; } else { @@ -1082,13 +1103,13 @@ void SV_MvdUnicast( edict_t *ent, int clientNum, qboolean reliable ) { } break; case svc_stufftext: - if( memcmp( msg_write.data + 1, "play ", 5 ) ) { + if (memcmp(msg_write.data + 1, "play ", 5)) { // discard any stufftexts, except of play sound hacks return; } break; case svc_print: - if( ent != mvd.dummy->edict && sv_mvd_nomsgs->integer ) { + if (ent != mvd.dummy->edict && sv_mvd_nomsgs->integer) { // optionally discard text messages to players return; } @@ -1096,7 +1117,7 @@ void SV_MvdUnicast( edict_t *ent, int clientNum, qboolean reliable ) { } // decide where should it go - if( reliable ) { + if (reliable) { op = mvd_unicast_r; buf = &mvd.message; } else { @@ -1105,11 +1126,11 @@ void SV_MvdUnicast( edict_t *ent, int clientNum, qboolean reliable ) { } // write it - bits = ( msg_write.cursize >> 8 ) & 7; - SZ_WriteByte( buf, op | ( bits << SVCMD_BITS ) ); - SZ_WriteByte( buf, msg_write.cursize & 255 ); - SZ_WriteByte( buf, clientNum ); - SZ_Write( buf, msg_write.data, msg_write.cursize ); + bits = (msg_write.cursize >> 8) & 7; + SZ_WriteByte(buf, op | (bits << SVCMD_BITS)); + SZ_WriteByte(buf, msg_write.cursize & 255); + SZ_WriteByte(buf, clientNum); + SZ_Write(buf, msg_write.data, msg_write.cursize); } /* @@ -1117,12 +1138,13 @@ void SV_MvdUnicast( edict_t *ent, int clientNum, qboolean reliable ) { SV_MvdConfigstring ============== */ -void SV_MvdConfigstring( int index, const char *string, size_t len ) { - if( mvd.active ) { - SZ_WriteByte( &mvd.message, mvd_configstring ); - SZ_WriteShort( &mvd.message, index ); - SZ_Write( &mvd.message, string, len ); - SZ_WriteByte( &mvd.message, 0 ); +void SV_MvdConfigstring(int index, const char *string, size_t len) +{ + if (mvd.active) { + SZ_WriteByte(&mvd.message, mvd_configstring); + SZ_WriteShort(&mvd.message, index); + SZ_Write(&mvd.message, string, len); + SZ_WriteByte(&mvd.message, 0); } } @@ -1131,11 +1153,12 @@ void SV_MvdConfigstring( int index, const char *string, size_t len ) { SV_MvdBroadcastPrint ============== */ -void SV_MvdBroadcastPrint( int level, const char *string ) { - if( mvd.active ) { - SZ_WriteByte( &mvd.message, mvd_print ); - SZ_WriteByte( &mvd.message, level ); - SZ_WriteString( &mvd.message, string ); +void SV_MvdBroadcastPrint(int level, const char *string) +{ + if (mvd.active) { + SZ_WriteByte(&mvd.message, mvd_print); + SZ_WriteByte(&mvd.message, level); + SZ_WriteString(&mvd.message, string); } } @@ -1146,39 +1169,39 @@ SV_MvdStartSound FIXME: origin will be incorrect on entities not captured this frame ============== */ -void SV_MvdStartSound( int entnum, int channel, int flags, - int soundindex, int volume, - int attenuation, int timeofs ) +void SV_MvdStartSound(int entnum, int channel, int flags, + int soundindex, int volume, + int attenuation, int timeofs) { int extrabits, sendchan; // do nothing if not active - if( !mvd.active ) { + if (!mvd.active) { return; } extrabits = 0; - if( channel & CHAN_NO_PHS_ADD ) { + if (channel & CHAN_NO_PHS_ADD) { extrabits |= 1 << SVCMD_BITS; } - if( channel & CHAN_RELIABLE ) { + if (channel & CHAN_RELIABLE) { // FIXME: write to mvd.message extrabits |= 2 << SVCMD_BITS; } - SZ_WriteByte( &mvd.datagram, mvd_sound | extrabits ); - SZ_WriteByte( &mvd.datagram, flags ); - SZ_WriteByte( &mvd.datagram, soundindex ); + SZ_WriteByte(&mvd.datagram, mvd_sound | extrabits); + SZ_WriteByte(&mvd.datagram, flags); + SZ_WriteByte(&mvd.datagram, soundindex); - if( flags & SND_VOLUME ) - SZ_WriteByte( &mvd.datagram, volume ); - if( flags & SND_ATTENUATION ) - SZ_WriteByte( &mvd.datagram, attenuation ); - if( flags & SND_OFFSET ) - SZ_WriteByte( &mvd.datagram, timeofs ); + if (flags & SND_VOLUME) + SZ_WriteByte(&mvd.datagram, volume); + if (flags & SND_ATTENUATION) + SZ_WriteByte(&mvd.datagram, attenuation); + if (flags & SND_OFFSET) + SZ_WriteByte(&mvd.datagram, timeofs); - sendchan = ( entnum << 3 ) | ( channel & 7 ); - SZ_WriteShort( &mvd.datagram, sendchan ); + sendchan = (entnum << 3) | (channel & 7); + SZ_WriteShort(&mvd.datagram, sendchan); } @@ -1191,28 +1214,30 @@ TCP CLIENTS HANDLING */ -static void remove_client( gtv_client_t *client ) { - NET_Close( &client->stream ); - List_Remove( &client->entry ); - if( client->data ) { - Z_Free( client->data ); +static void remove_client(gtv_client_t *client) +{ + NET_Close(&client->stream); + List_Remove(&client->entry); + if (client->data) { + Z_Free(client->data); client->data = NULL; } client->state = cs_free; } #if USE_ZLIB -static void flush_stream( gtv_client_t *client, int flush ) { +static void flush_stream(gtv_client_t *client, int flush) +{ fifo_t *fifo = &client->stream.send; z_streamp z = &client->z; byte *data; size_t len; int ret; - if( client->state <= cs_zombie ) { + if (client->state <= cs_zombie) { return; } - if( !z->state ) { + if (!z->state) { return; } @@ -1220,161 +1245,166 @@ static void flush_stream( gtv_client_t *client, int flush ) { z->avail_in = 0; do { - data = FIFO_Reserve( fifo, &len ); - if( !len ) { + data = FIFO_Reserve(fifo, &len); + if (!len) { // FIXME: this is not an error when flushing return; } z->next_out = data; - z->avail_out = ( uInt )len; + z->avail_out = (uInt)len; - ret = deflate( z, flush ); + ret = deflate(z, flush); len -= z->avail_out; - if( len ) { - FIFO_Commit( fifo, len ); + if (len) { + FIFO_Commit(fifo, len); client->bufcount = 0; } - } while( ret == Z_OK ); + } while (ret == Z_OK); } #endif -static void drop_client( gtv_client_t *client, const char *error ) { - if( client->state <= cs_zombie ) { +static void drop_client(gtv_client_t *client, const char *error) +{ + if (client->state <= cs_zombie) { return; } - if( error ) { + if (error) { // notify console - Com_Printf( "TCP client %s[%s] dropped: %s\n", client->name, - NET_AdrToString( &client->stream.address ), error ); + Com_Printf("TCP client %s[%s] dropped: %s\n", client->name, + NET_AdrToString(&client->stream.address), error); } #if USE_ZLIB - if( client->z.state ) { + if (client->z.state) { // finish zlib stream - flush_stream( client, Z_FINISH ); - deflateEnd( &client->z ); + flush_stream(client, Z_FINISH); + deflateEnd(&client->z); } #endif - List_Remove( &client->active ); + List_Remove(&client->active); client->state = cs_zombie; client->lastmessage = svs.realtime; } -static void write_stream( gtv_client_t *client, void *data, size_t len ) { +static void write_stream(gtv_client_t *client, void *data, size_t len) +{ fifo_t *fifo = &client->stream.send; - if( client->state <= cs_zombie ) { + if (client->state <= cs_zombie) { return; } - if( !len ) { + if (!len) { return; } #if USE_ZLIB - if( client->z.state ) { + if (client->z.state) { z_streamp z = &client->z; z->next_in = data; - z->avail_in = ( uInt )len; + z->avail_in = (uInt)len; do { - data = FIFO_Reserve( fifo, &len ); - if( !len ) { - drop_client( client, "overflowed" ); + data = FIFO_Reserve(fifo, &len); + if (!len) { + drop_client(client, "overflowed"); return; } z->next_out = data; - z->avail_out = ( uInt )len; + z->avail_out = (uInt)len; - if( deflate( z, Z_NO_FLUSH ) != Z_OK ) { - drop_client( client, "deflate() failed" ); + if (deflate(z, Z_NO_FLUSH) != Z_OK) { + drop_client(client, "deflate() failed"); return; } len -= z->avail_out; - if( len ) { - FIFO_Commit( fifo, len ); + if (len) { + FIFO_Commit(fifo, len); client->bufcount = 0; } - } while( z->avail_in ); + } while (z->avail_in); } else #endif - if( FIFO_Write( fifo, data, len ) != len ) { - drop_client( client, "overflowed" ); - } + if (FIFO_Write(fifo, data, len) != len) { + drop_client(client, "overflowed"); + } } -static void write_message( gtv_client_t *client, gtv_serverop_t op ) { +static void write_message(gtv_client_t *client, gtv_serverop_t op) +{ byte header[3]; size_t len = msg_write.cursize + 1; header[0] = len & 255; - header[1] = ( len >> 8 ) & 255; + header[1] = (len >> 8) & 255; header[2] = op; - write_stream( client, header, sizeof( header ) ); + write_stream(client, header, sizeof(header)); - write_stream( client, msg_write.data, msg_write.cursize ); + write_stream(client, msg_write.data, msg_write.cursize); } -static qboolean auth_client( gtv_client_t *client, const char *password ) { - if( SV_MatchAddress( >v_host_list, &client->stream.address ) ) { +static qboolean auth_client(gtv_client_t *client, const char *password) +{ + if (SV_MatchAddress(>v_host_list, &client->stream.address)) { return qtrue; // dedicated GTV hosts don't need password } - if( !sv_mvd_password->string[0] ) { + if (!sv_mvd_password->string[0]) { return qfalse; // no password set on the server } - if( strcmp( sv_mvd_password->string, password ) ) { + if (strcmp(sv_mvd_password->string, password)) { return qfalse; // password doesn't match } return qtrue; } -static void parse_hello( gtv_client_t *client ) { +static void parse_hello(gtv_client_t *client) +{ char password[MAX_QPATH]; int protocol, flags; size_t size; byte *data; - if( client->state >= cs_primed ) { - drop_client( client, "duplicated hello message" ); + if (client->state >= cs_primed) { + drop_client(client, "duplicated hello message"); return; } // client should have already consumed the magic - if( FIFO_Usage( &client->stream.send ) ) { - drop_client( client, "send buffer not empty" ); + if (FIFO_Usage(&client->stream.send)) { + drop_client(client, "send buffer not empty"); return; } protocol = MSG_ReadWord(); - if( protocol != GTV_PROTOCOL_VERSION ) { - write_message( client, GTS_BADREQUEST ); - drop_client( client, "bad protocol version" ); + if (protocol != GTV_PROTOCOL_VERSION) { + write_message(client, GTS_BADREQUEST); + drop_client(client, "bad protocol version"); return; } flags = MSG_ReadLong(); MSG_ReadLong(); - MSG_ReadString( client->name, sizeof( client->name ) ); - MSG_ReadString( password, sizeof( password ) ); - MSG_ReadString( client->version, sizeof( client->version ) ); + MSG_ReadString(client->name, sizeof(client->name)); + MSG_ReadString(password, sizeof(password)); + MSG_ReadString(client->version, sizeof(client->version)); // authorize access - if( !auth_client( client, password ) ) { - write_message( client, GTS_NOACCESS ); - drop_client( client, "not authorized" ); + if (!auth_client(client, password)) { + write_message(client, GTS_NOACCESS); + drop_client(client, "not authorized"); return; } - if( sv_mvd_allow_stufftext->integer >= 0 ) { + if (sv_mvd_allow_stufftext->integer >= 0) { flags &= ~GTF_STRINGCMDS; } @@ -1382,11 +1412,11 @@ static void parse_hello( gtv_client_t *client ) { flags &= ~GTF_DEFLATE; #endif - Cvar_ClampInteger( sv_mvd_bufsize, 1, 4 ); + Cvar_ClampInteger(sv_mvd_bufsize, 1, 4); // allocate larger send buffer size = MAX_GTS_MSGLEN * sv_mvd_bufsize->integer; - data = SV_Malloc( size ); + data = SV_Malloc(size); client->stream.send.data = data; client->stream.send.size = size; client->data = data; @@ -1394,245 +1424,252 @@ static void parse_hello( gtv_client_t *client ) { client->state = cs_primed; // send hello - MSG_WriteLong( flags ); - write_message( client, GTS_HELLO ); - SZ_Clear( &msg_write ); + MSG_WriteLong(flags); + write_message(client, GTS_HELLO); + SZ_Clear(&msg_write); #if USE_ZLIB // the rest of the stream will be deflated - if( flags & GTF_DEFLATE ) { + if (flags & GTF_DEFLATE) { client->z.zalloc = SV_Zalloc; client->z.zfree = SV_Zfree; - if( deflateInit( &client->z, Z_DEFAULT_COMPRESSION ) != Z_OK ) { - drop_client( client, "deflateInit failed" ); + if (deflateInit(&client->z, Z_DEFAULT_COMPRESSION) != Z_OK) { + drop_client(client, "deflateInit failed"); return; } } #endif - Com_Printf( "Accepted MVD client %s[%s]\n", client->name, - NET_AdrToString( &client->stream.address ) ); + Com_Printf("Accepted MVD client %s[%s]\n", client->name, + NET_AdrToString(&client->stream.address)); } -static void parse_ping( gtv_client_t *client ) { - if( client->state < cs_primed ) { +static void parse_ping(gtv_client_t *client) +{ + if (client->state < cs_primed) { return; } // send ping reply - write_message( client, GTS_PONG ); + write_message(client, GTS_PONG); #if USE_ZLIB - flush_stream( client, Z_SYNC_FLUSH ); + flush_stream(client, Z_SYNC_FLUSH); #endif } -static void parse_stream_start( gtv_client_t *client ) { +static void parse_stream_start(gtv_client_t *client) +{ int maxbuf; - if( client->state != cs_primed ) { - drop_client( client, "unexpected stream start message" ); + if (client->state != cs_primed) { + drop_client(client, "unexpected stream start message"); return; } - if( !mvd_enable() ) { - write_message( client, GTS_ERROR ); - drop_client( client, "couldn't create MVD dummy" ); + if (!mvd_enable()) { + write_message(client, GTS_ERROR); + drop_client(client, "couldn't create MVD dummy"); return; } maxbuf = MSG_ReadShort(); - if( maxbuf < 10 ) { + if (maxbuf < 10) { maxbuf = 10; } client->maxbuf = maxbuf; client->state = cs_spawned; - List_Append( >v_active_list, &client->active ); + List_Append(>v_active_list, &client->active); // send ack to client - write_message( client, GTS_STREAM_START ); + write_message(client, GTS_STREAM_START); // send gamestate if active - if( mvd.active ) { + if (mvd.active) { emit_gamestate(); - write_message( client, GTS_STREAM_DATA ); - SZ_Clear( &msg_write ); + write_message(client, GTS_STREAM_DATA); + SZ_Clear(&msg_write); } else { // send stream suspend marker - write_message( client, GTS_STREAM_DATA ); + write_message(client, GTS_STREAM_DATA); } #if USE_ZLIB - flush_stream( client, Z_SYNC_FLUSH ); + flush_stream(client, Z_SYNC_FLUSH); #endif } -static void parse_stream_stop( gtv_client_t *client ) { - if( client->state != cs_spawned ) { - drop_client( client, "unexpected stream stop message" ); +static void parse_stream_stop(gtv_client_t *client) +{ + if (client->state != cs_spawned) { + drop_client(client, "unexpected stream stop message"); return; } client->state = cs_primed; - List_Delete( &client->active ); + List_Delete(&client->active); // send ack to client - write_message( client, GTS_STREAM_STOP ); + write_message(client, GTS_STREAM_STOP); #if USE_ZLIB - flush_stream( client, Z_SYNC_FLUSH ); + flush_stream(client, Z_SYNC_FLUSH); #endif } -static void parse_stringcmd( gtv_client_t *client ) { +static void parse_stringcmd(gtv_client_t *client) +{ char string[MAX_GTC_MSGLEN]; - if( client->state < cs_primed ) { - drop_client( client, "unexpected stringcmd message" ); + if (client->state < cs_primed) { + drop_client(client, "unexpected stringcmd message"); return; } - if( !mvd.dummy || !( client->flags & GTF_STRINGCMDS ) ) { - Com_DPrintf( "ignored stringcmd from %s[%s]\n", client->name, - NET_AdrToString( &client->stream.address ) ); + if (!mvd.dummy || !(client->flags & GTF_STRINGCMDS)) { + Com_DPrintf("ignored stringcmd from %s[%s]\n", client->name, + NET_AdrToString(&client->stream.address)); return; } - MSG_ReadString( string, sizeof( string ) ); + MSG_ReadString(string, sizeof(string)); - Cmd_TokenizeString( string, qfalse ); + Cmd_TokenizeString(string, qfalse); - Com_DPrintf( "dummy stringcmd from %s[%s]: %s\n", client->name, - NET_AdrToString( &client->stream.address ), string ); + Com_DPrintf("dummy stringcmd from %s[%s]: %s\n", client->name, + NET_AdrToString(&client->stream.address), string); dummy_command(); } -static qboolean parse_message( gtv_client_t *client ) { +static qboolean parse_message(gtv_client_t *client) +{ uint32_t magic; uint16_t msglen; int cmd; - if( client->state <= cs_zombie ) { + if (client->state <= cs_zombie) { return qfalse; } // check magic - if( client->state < cs_connected ) { - if( !FIFO_TryRead( &client->stream.recv, &magic, 4 ) ) { + if (client->state < cs_connected) { + if (!FIFO_TryRead(&client->stream.recv, &magic, 4)) { return qfalse; } - if( magic != MVD_MAGIC ) { - drop_client( client, "not a MVD/GTV stream" ); + if (magic != MVD_MAGIC) { + drop_client(client, "not a MVD/GTV stream"); return qfalse; } client->state = cs_connected; // send it back - write_stream( client, &magic, 4 ); + write_stream(client, &magic, 4); return qfalse; } // parse msglen - if( !client->msglen ) { - if( !FIFO_TryRead( &client->stream.recv, &msglen, 2 ) ) { + if (!client->msglen) { + if (!FIFO_TryRead(&client->stream.recv, &msglen, 2)) { return qfalse; } - msglen = LittleShort( msglen ); - if( !msglen ) { - drop_client( client, "end of stream" ); + msglen = LittleShort(msglen); + if (!msglen) { + drop_client(client, "end of stream"); return qfalse; } - if( msglen > MAX_GTC_MSGLEN ) { - drop_client( client, "oversize message" ); + if (msglen > MAX_GTC_MSGLEN) { + drop_client(client, "oversize message"); return qfalse; } client->msglen = msglen; } // read this message - if( !FIFO_ReadMessage( &client->stream.recv, client->msglen ) ) { + if (!FIFO_ReadMessage(&client->stream.recv, client->msglen)) { return qfalse; } client->msglen = 0; cmd = MSG_ReadByte(); - switch( cmd ) { + switch (cmd) { case GTC_HELLO: - parse_hello( client ); + parse_hello(client); break; case GTC_PING: - parse_ping( client ); + parse_ping(client); break; case GTC_STREAM_START: - parse_stream_start( client ); + parse_stream_start(client); break; case GTC_STREAM_STOP: - parse_stream_stop( client ); + parse_stream_stop(client); break; case GTC_STRINGCMD: - parse_stringcmd( client ); + parse_stringcmd(client); break; default: - drop_client( client, "unknown command byte" ); + drop_client(client, "unknown command byte"); return qfalse; } - if( msg_read.readcount > msg_read.cursize ) { - drop_client( client, "read past end of message" ); + if (msg_read.readcount > msg_read.cursize) { + drop_client(client, "read past end of message"); return qfalse; } - + client->lastmessage = svs.realtime; // don't timeout return qtrue; } -static gtv_client_t *find_slot( void ) { +static gtv_client_t *find_slot(void) +{ gtv_client_t *client; int i; - for( i = 0; i < sv_mvd_maxclients->integer; i++ ) { + for (i = 0; i < sv_mvd_maxclients->integer; i++) { client = &mvd.clients[i]; - if( !client->state ) { + if (!client->state) { return client; } } return NULL; } -static void accept_client( netstream_t *stream ) { +static void accept_client(netstream_t *stream) +{ gtv_client_t *client; netstream_t *s; // limit number of connections from single IP - if( sv_iplimit->integer > 0 ) { + if (sv_iplimit->integer > 0) { int count = 0; - FOR_EACH_GTV( client ) { - if( NET_IsEqualBaseAdr( &client->stream.address, &stream->address ) ) { + FOR_EACH_GTV(client) { + if (NET_IsEqualBaseAdr(&client->stream.address, &stream->address)) { count++; } } - if( count >= sv_iplimit->integer ) { - Com_Printf( "TCP client [%s] rejected: too many connections\n", - NET_AdrToString( &stream->address ) ); - NET_Close( stream ); + if (count >= sv_iplimit->integer) { + Com_Printf("TCP client [%s] rejected: too many connections\n", + NET_AdrToString(&stream->address)); + NET_Close(stream); return; } } // find a free client slot client = find_slot(); - if( !client ) { - Com_Printf( "TCP client [%s] rejected: no free slots\n", - NET_AdrToString( &stream->address ) ); - NET_Close( stream ); + if (!client) { + Com_Printf("TCP client [%s] rejected: no free slots\n", + NET_AdrToString(&stream->address)); + NET_Close(stream); return; } - memset( client, 0, sizeof( *client ) ); + memset(client, 0, sizeof(*client)); s = &client->stream; s->recv.data = client->buffer; @@ -1645,14 +1682,15 @@ static void accept_client( netstream_t *stream ) { client->lastmessage = svs.realtime; client->state = cs_assigned; - List_SeqAdd( >v_client_list, &client->entry ); - List_Init( &client->active ); + List_SeqAdd(>v_client_list, &client->entry); + List_Init(&client->active); - Com_DPrintf( "TCP client [%s] accepted\n", - NET_AdrToString( &stream->address ) ); + Com_DPrintf("TCP client [%s] accepted\n", + NET_AdrToString(&stream->address)); } -void SV_MvdRunClients( void ) { +void SV_MvdRunClients(void) +{ gtv_client_t *client; neterr_t ret; netstream_t stream; @@ -1662,165 +1700,170 @@ void SV_MvdRunClients( void ) { unsigned delta; // accept new connections - ret = NET_Accept( &stream ); - if( ret == NET_ERROR ) { - Com_DPrintf( "%s from %s, ignored\n", NET_ErrorString(), - NET_AdrToString( &net_from ) ); - } else if( ret == NET_OK ) { - accept_client( &stream ); + ret = NET_Accept(&stream); + if (ret == NET_ERROR) { + Com_DPrintf("%s from %s, ignored\n", NET_ErrorString(), + NET_AdrToString(&net_from)); + } else if (ret == NET_OK) { + accept_client(&stream); } // run existing connections - FOR_EACH_GTV( client ) { + FOR_EACH_GTV(client) { // check timeouts delta = svs.realtime - client->lastmessage; - switch( client->state ) { + switch (client->state) { case cs_zombie: - if( delta > zombie_time || !FIFO_Usage( &client->stream.send ) ) { - remove_client( client ); + if (delta > zombie_time || !FIFO_Usage(&client->stream.send)) { + remove_client(client); continue; } break; case cs_assigned: case cs_connected: - if( delta > ghost_time || delta > drop_time ) { - drop_client( client, "request timed out" ); - remove_client( client ); + if (delta > ghost_time || delta > drop_time) { + drop_client(client, "request timed out"); + remove_client(client); continue; } break; default: - if( delta > drop_time ) { - drop_client( client, "connection timed out" ); - remove_client( client ); + if (delta > drop_time) { + drop_client(client, "connection timed out"); + remove_client(client); continue; } break; } // run network stream - ret = NET_RunStream( &client->stream ); - switch( ret ) { + ret = NET_RunStream(&client->stream); + switch (ret) { case NET_AGAIN: break; case NET_OK: // parse the message - while( parse_message( client ) ) + while (parse_message(client)) ; - NET_UpdateStream( &client->stream ); + NET_UpdateStream(&client->stream); break; case NET_CLOSED: - drop_client( client, "EOF from client" ); - remove_client( client ); + drop_client(client, "EOF from client"); + remove_client(client); break; case NET_ERROR: - drop_client( client, "connection reset by peer" ); - remove_client( client ); + drop_client(client, "connection reset by peer"); + remove_client(client); break; } } } -static void dump_clients( void ) { +static void dump_clients(void) +{ gtv_client_t *client; int count; Com_Printf( -"num name buf lastmsg address state\n" -"--- ---------------- --- ------- --------------------- -----\n" ); + "num name buf lastmsg address state\n" + "--- ---------------- --- ------- --------------------- -----\n"); count = 0; - FOR_EACH_GTV( client ) { - Com_Printf( "%3d %-16.16s %3"PRIz" %7u %-21s ", - count, client->name, FIFO_Usage( &client->stream.send ), - svs.realtime - client->lastmessage, - NET_AdrToString( &client->stream.address ) ); + FOR_EACH_GTV(client) { + Com_Printf("%3d %-16.16s %3"PRIz" %7u %-21s ", + count, client->name, FIFO_Usage(&client->stream.send), + svs.realtime - client->lastmessage, + NET_AdrToString(&client->stream.address)); - switch( client->state ) { + switch (client->state) { case cs_zombie: - Com_Printf( "ZMBI " ); + Com_Printf("ZMBI "); break; case cs_assigned: - Com_Printf( "ASGN " ); + Com_Printf("ASGN "); break; case cs_connected: - Com_Printf( "CNCT " ); + Com_Printf("CNCT "); break; case cs_primed: - Com_Printf( "PRIM " ); + Com_Printf("PRIM "); break; default: - Com_Printf( "SEND " ); + Com_Printf("SEND "); break; } - Com_Printf( "\n" ); + Com_Printf("\n"); count++; } } -static void dump_versions( void ) { +static void dump_versions(void) +{ gtv_client_t *client; int count; Com_Printf( -"num name version\n" -"--- ---------------- -----------------------------------------\n" ); + "num name version\n" + "--- ---------------- -----------------------------------------\n"); - FOR_EACH_GTV( client ) { - count = 0; - Com_Printf( "%3i %-16.16s %-40.40s\n", - count, client->name, client->version ); + FOR_EACH_GTV(client) { + count = 0; + Com_Printf("%3i %-16.16s %-40.40s\n", + count, client->name, client->version); count++; } } -void SV_MvdStatus_f( void ) { - if( LIST_EMPTY( >v_client_list ) ) { - Com_Printf( "No TCP clients.\n" ); +void SV_MvdStatus_f(void) +{ + if (LIST_EMPTY(>v_client_list)) { + Com_Printf("No TCP clients.\n"); } else { - if( Cmd_Argc() > 1 ) { + if (Cmd_Argc() > 1) { dump_versions(); } else { dump_clients(); } } - Com_Printf( "\n" ); + Com_Printf("\n"); } -static void mvd_disable( void ) { +static void mvd_disable(void) +{ // remove MVD dummy - if( mvd.dummy ) { - SV_RemoveClient( mvd.dummy ); + if (mvd.dummy) { + SV_RemoveClient(mvd.dummy); mvd.dummy = NULL; } - SZ_Clear( &mvd.datagram ); - SZ_Clear( &mvd.message ); + SZ_Clear(&mvd.datagram); + SZ_Clear(&mvd.message); mvd.active = qfalse; } // something bad happened, remove all clients -static void mvd_drop( gtv_serverop_t op ) { +static void mvd_drop(gtv_serverop_t op) +{ gtv_client_t *client; // stop recording rec_stop(); // drop GTV clients - FOR_EACH_GTV( client ) { - switch( client->state ) { + FOR_EACH_GTV(client) { + switch (client->state) { case cs_spawned: case cs_primed: - write_message( client, op ); - drop_client( client, NULL ); - NET_RunStream( &client->stream ); - NET_RunStream( &client->stream ); - remove_client( client ); + write_message(client, op); + drop_client(client, NULL); + NET_RunStream(&client->stream); + NET_RunStream(&client->stream); + remove_client(client); break; default: - drop_client( client, NULL ); - remove_client( client ); + drop_client(client, NULL); + remove_client(client); break; } } @@ -1829,9 +1872,10 @@ static void mvd_drop( gtv_serverop_t op ) { } // if dummy is not yet connected, create and spawn it -static qboolean mvd_enable( void ) { - if( !mvd.dummy ) { - if( !dummy_create() ) { +static qboolean mvd_enable(void) +{ + if (!mvd.dummy) { + if (!dummy_create()) { return qfalse; } @@ -1864,57 +1908,58 @@ SV_MvdMapChanged Server has just changed the map, spawn the MVD dummy and go! ================== */ -void SV_MvdMapChanged( void ) { +void SV_MvdMapChanged(void) +{ gtv_client_t *client; - if( !sv_mvd_enable->integer ) { + if (!sv_mvd_enable->integer) { return; // do noting if disabled } - if( !mvd.dummy ) { - if( !sv_mvd_autorecord->integer ) { + if (!mvd.dummy) { + if (!sv_mvd_autorecord->integer) { return; // not listening for autorecord command } - if( !dummy_create() ) { + if (!dummy_create()) { return; } - Com_Printf( "Spawning MVD dummy for auto-recording\n" ); - Cvar_Set( "sv_mvd_suspend_time", "0" ); + Com_Printf("Spawning MVD dummy for auto-recording\n"); + Cvar_Set("sv_mvd_suspend_time", "0"); } dummy_spawn(); - if( mvd.active ) { + if (mvd.active) { // build and emit gamestate build_gamestate(); emit_gamestate(); // send gamestate to all MVD clients - FOR_EACH_ACTIVE_GTV( client ) { - write_message( client, GTS_STREAM_DATA ); - NET_UpdateStream( &client->stream ); + FOR_EACH_ACTIVE_GTV(client) { + write_message(client, GTS_STREAM_DATA); + NET_UpdateStream(&client->stream); } } - if( mvd.recording ) { + if (mvd.recording) { int maxlevels = sv_mvd_maxmaps->integer; - + // check if it is time to stop recording - if( maxlevels > 0 && ++mvd.numlevels >= maxlevels ) { - Com_Printf( "Stopping MVD recording, " - "maximum number of level changes reached.\n" ); + if (maxlevels > 0 && ++mvd.numlevels >= maxlevels) { + Com_Printf("Stopping MVD recording, " + "maximum number of level changes reached.\n"); rec_stop(); - } else if( mvd.active ) { + } else if (mvd.active) { // write gamestate to demofile rec_write(); } } // clear gamestate - SZ_Clear( &msg_write ); + SZ_Clear(&msg_write); - SZ_Clear( &mvd.datagram ); - SZ_Clear( &mvd.message ); + SZ_Clear(&mvd.datagram); + SZ_Clear(&mvd.message); } /* @@ -1924,9 +1969,10 @@ SV_MvdClientDropped Server has just dropped a client, check if that was our MVD dummy client. ================== */ -void SV_MvdClientDropped( client_t *client ) { - if( client == mvd.dummy ) { - mvd_drop( GTS_ERROR ); +void SV_MvdClientDropped(client_t *client) +{ + if (client == mvd.dummy) { + mvd_drop(GTS_ERROR); } } @@ -1937,39 +1983,40 @@ SV_MvdInit Server is initializing, prepare MVD server for this game. ================== */ -void SV_MvdInit( void ) { - if( !sv_mvd_enable->integer ) { +void SV_MvdInit(void) +{ + if (!sv_mvd_enable->integer) { return; // do nothing if disabled } // allocate buffers - Z_TagReserve( sizeof( player_state_t ) * sv_maxclients->integer + - sizeof( entity_state_t ) * MAX_EDICTS + MAX_MSGLEN * 2, TAG_SERVER ); - SZ_Init( &mvd.message, Z_ReservedAlloc( MAX_MSGLEN ), MAX_MSGLEN ); - SZ_Init( &mvd.datagram, Z_ReservedAlloc( MAX_MSGLEN ), MAX_MSGLEN ); - mvd.players = Z_ReservedAlloc( sizeof( player_state_t ) * sv_maxclients->integer ); - mvd.entities = Z_ReservedAlloc( sizeof( entity_state_t ) * MAX_EDICTS ); + Z_TagReserve(sizeof(player_state_t) * sv_maxclients->integer + + sizeof(entity_state_t) * MAX_EDICTS + MAX_MSGLEN * 2, TAG_SERVER); + SZ_Init(&mvd.message, Z_ReservedAlloc(MAX_MSGLEN), MAX_MSGLEN); + SZ_Init(&mvd.datagram, Z_ReservedAlloc(MAX_MSGLEN), MAX_MSGLEN); + mvd.players = Z_ReservedAlloc(sizeof(player_state_t) * sv_maxclients->integer); + mvd.entities = Z_ReservedAlloc(sizeof(entity_state_t) * MAX_EDICTS); // reserve the slot for dummy MVD client - if( !sv_reserved_slots->integer ) { - Cvar_Set( "sv_reserved_slots", "1" ); + if (!sv_reserved_slots->integer) { + Cvar_Set("sv_reserved_slots", "1"); } - Cvar_ClampInteger( sv_mvd_maxclients, 1, 256 ); + Cvar_ClampInteger(sv_mvd_maxclients, 1, 256); // open server TCP socket - if( sv_mvd_enable->integer > 1 ) { - if( NET_Listen( qtrue ) == NET_OK ) { - mvd.clients = SV_Mallocz( sizeof( gtv_client_t ) * sv_mvd_maxclients->integer ); + if (sv_mvd_enable->integer > 1) { + if (NET_Listen(qtrue) == NET_OK) { + mvd.clients = SV_Mallocz(sizeof(gtv_client_t) * sv_mvd_maxclients->integer); } else { - Com_EPrintf( "%s while opening server TCP port.\n", NET_ErrorString() ); - Cvar_Set( "sv_mvd_enable", "1" ); + Com_EPrintf("%s while opening server TCP port.\n", NET_ErrorString()); + Cvar_Set("sv_mvd_enable", "1"); } } dummy_buffer.from = FROM_CONSOLE; dummy_buffer.text = dummy_buffer_text; - dummy_buffer.maxsize = sizeof( dummy_buffer_text ); + dummy_buffer.maxsize = sizeof(dummy_buffer_text); dummy_buffer.exec = dummy_exec_string; } @@ -1980,20 +2027,21 @@ SV_MvdShutdown Server is shutting down, clean everything up. ================== */ -void SV_MvdShutdown( error_type_t type ) { +void SV_MvdShutdown(error_type_t type) +{ // drop all clients - mvd_drop( type == ERR_RECONNECT ? GTS_RECONNECT : GTS_DISCONNECT ); + mvd_drop(type == ERR_RECONNECT ? GTS_RECONNECT : GTS_DISCONNECT); // free static data - Z_Free( mvd.message.data ); - Z_Free( mvd.clients ); + Z_Free(mvd.message.data); + Z_Free(mvd.clients); // close server TCP socket - NET_Listen( qfalse ); + NET_Listen(qfalse); - memset( &mvd, 0, sizeof( mvd ) ); + memset(&mvd, 0, sizeof(mvd)); - memset( &dummy_buffer, 0, sizeof( dummy_buffer ) ); + memset(&dummy_buffer, 0, sizeof(dummy_buffer)); } @@ -2005,23 +2053,24 @@ LOCAL MVD RECORDER ============================================================================== */ -static void rec_write( void ) { +static void rec_write(void) +{ uint16_t msglen; ssize_t ret; - if( !msg_write.cursize ) + if (!msg_write.cursize) return; - msglen = LittleShort( msg_write.cursize ); - ret = FS_Write( &msglen, 2, mvd.recording ); - if( ret != 2 ) + msglen = LittleShort(msg_write.cursize); + ret = FS_Write(&msglen, 2, mvd.recording); + if (ret != 2) goto fail; - ret = FS_Write( msg_write.data, msg_write.cursize, mvd.recording ); - if( ret == msg_write.cursize ) + ret = FS_Write(msg_write.data, msg_write.cursize, mvd.recording); + if (ret == msg_write.cursize) return; fail: - Com_EPrintf( "Couldn't write local MVD: %s\n", Q_ErrorString( ret ) ); + Com_EPrintf("Couldn't write local MVD: %s\n", Q_ErrorString(ret)); rec_stop(); } @@ -2032,48 +2081,51 @@ rec_stop Stops server local MVD recording. ============== */ -static void rec_stop( void ) { +static void rec_stop(void) +{ uint16_t msglen; - if( !mvd.recording ) { + if (!mvd.recording) { return; } - + // write demo EOF marker msglen = 0; - FS_Write( &msglen, 2, mvd.recording ); + FS_Write(&msglen, 2, mvd.recording); - FS_FCloseFile( mvd.recording ); + FS_FCloseFile(mvd.recording); mvd.recording = 0; } -static qboolean rec_allowed( void ) { - if( !mvd.entities ) { - Com_Printf( "MVD recording is disabled on this server.\n" ); +static qboolean rec_allowed(void) +{ + if (!mvd.entities) { + Com_Printf("MVD recording is disabled on this server.\n"); return qfalse; } - if( mvd.recording ) { - Com_Printf( "Already recording a local MVD.\n" ); + if (mvd.recording) { + Com_Printf("Already recording a local MVD.\n"); return qfalse; } return qtrue; } -static void rec_start( qhandle_t demofile ) { +static void rec_start(qhandle_t demofile) +{ uint32_t magic; mvd.recording = demofile; mvd.numlevels = 0; mvd.numframes = 0; mvd.clients_active = svs.realtime; - + magic = MVD_MAGIC; - FS_Write( &magic, 4, demofile ); + FS_Write(&magic, 4, demofile); - if( mvd.active ) { + if (mvd.active) { emit_gamestate(); rec_write(); - SZ_Clear( &msg_write ); + SZ_Clear(&msg_write); } } @@ -2085,23 +2137,24 @@ Begins server MVD recording. Every entity, every playerinfo and every message will be recorded. ============== */ -void SV_MvdRecord_f( void ) { +void SV_MvdRecord_f(void) +{ char buffer[MAX_OSPATH]; qhandle_t f; unsigned mode = FS_MODE_WRITE; int c; - if( sv.state != ss_game ) { - Com_Printf( "No server running.\n" ); + if (sv.state != ss_game) { + Com_Printf("No server running.\n"); return; } - while( ( c = Cmd_ParseOptions( o_record ) ) != -1 ) { - switch( c ) { + while ((c = Cmd_ParseOptions(o_record)) != -1) { + switch (c) { case 'h': - Cmd_PrintUsage( o_record, "<filename>" ); - Com_Printf( "Begin local MVD recording.\n" ); - Cmd_PrintHelp( o_record ); + Cmd_PrintUsage(o_record, "<filename>"); + Com_Printf("Begin local MVD recording.\n"); + Cmd_PrintHelp(o_record); return; case 'z': mode |= FS_FLAG_GZIP; @@ -2111,33 +2164,33 @@ void SV_MvdRecord_f( void ) { } } - if( !cmd_optarg[0] ) { - Com_Printf( "Missing filename argument.\n" ); + if (!cmd_optarg[0]) { + Com_Printf("Missing filename argument.\n"); Cmd_PrintHint(); return; } - if( !rec_allowed() ) { + if (!rec_allowed()) { return; } // // open the demo file // - f = FS_EasyOpenFile( buffer, sizeof( buffer ), mode, - "demos/", cmd_optarg, ".mvd2" ); - if( !f ) { + f = FS_EasyOpenFile(buffer, sizeof(buffer), mode, + "demos/", cmd_optarg, ".mvd2"); + if (!f) { return; } - if( !mvd_enable() ) { - FS_FCloseFile( f ); + if (!mvd_enable()) { + FS_FCloseFile(f); return; } - Com_Printf( "Recording local MVD to %s\n", buffer ); + Com_Printf("Recording local MVD to %s\n", buffer); - rec_start( f ); + rec_start(f); } @@ -2148,33 +2201,38 @@ SV_MvdStop_f Ends server MVD recording ============== */ -void SV_MvdStop_f( void ) { - if( !mvd.recording ) { - Com_Printf( "Not recording a local MVD.\n" ); +void SV_MvdStop_f(void) +{ + if (!mvd.recording) { + Com_Printf("Not recording a local MVD.\n"); return; } - Com_Printf( "Stopped local MVD recording.\n" ); + Com_Printf("Stopped local MVD recording.\n"); rec_stop(); } -static void SV_MvdStuff_f( void ) { - if( mvd.dummy ) { - Cbuf_AddText( &dummy_buffer, Cmd_RawArgs() ); - Cbuf_AddText( &dummy_buffer, "\n" ); +static void SV_MvdStuff_f(void) +{ + if (mvd.dummy) { + Cbuf_AddText(&dummy_buffer, Cmd_RawArgs()); + Cbuf_AddText(&dummy_buffer, "\n"); } else { - Com_Printf( "Can't '%s', dummy MVD client is not active\n", Cmd_Argv( 0 ) ); + Com_Printf("Can't '%s', dummy MVD client is not active\n", Cmd_Argv(0)); } } -static void SV_AddGtvHost_f( void ) { - SV_AddMatch_f( >v_host_list ); +static void SV_AddGtvHost_f(void) +{ + SV_AddMatch_f(>v_host_list); } -static void SV_DelGtvHost_f( void ) { - SV_DelMatch_f( >v_host_list ); +static void SV_DelGtvHost_f(void) +{ + SV_DelMatch_f(>v_host_list); } -static void SV_ListGtvHosts_f( void ) { - SV_ListMatches_f( >v_host_list ); +static void SV_ListGtvHosts_f(void) +{ + SV_ListMatches_f(>v_host_list); } static const cmdreg_t c_svmvd[] = { @@ -2186,27 +2244,28 @@ static const cmdreg_t c_svmvd[] = { { NULL } }; -void SV_MvdRegister( void ) { - sv_mvd_enable = Cvar_Get( "sv_mvd_enable", "0", CVAR_LATCH ); - sv_mvd_maxclients = Cvar_Get( "sv_mvd_maxclients", "8", CVAR_LATCH ); - sv_mvd_bufsize = Cvar_Get( "sv_mvd_bufsize", "2", CVAR_LATCH ); - sv_mvd_password = Cvar_Get( "sv_mvd_password", "", CVAR_PRIVATE ); - sv_mvd_maxsize = Cvar_Get( "sv_mvd_maxsize", "0", 0 ); - sv_mvd_maxtime = Cvar_Get( "sv_mvd_maxtime", "0", 0 ); - sv_mvd_maxmaps = Cvar_Get( "sv_mvd_maxmaps", "1", 0 ); - sv_mvd_noblend = Cvar_Get( "sv_mvd_noblend", "0", CVAR_LATCH ); - sv_mvd_nogun = Cvar_Get( "sv_mvd_nogun", "1", CVAR_LATCH ); - sv_mvd_nomsgs = Cvar_Get( "sv_mvd_nomsgs", "1", CVAR_LATCH ); - sv_mvd_begincmd = Cvar_Get( "sv_mvd_begincmd", - "wait 50; putaway; wait 10; help;", 0 ); - sv_mvd_scorecmd = Cvar_Get( "sv_mvd_scorecmd", - "putaway; wait 10; help;", 0 ); - sv_mvd_autorecord = Cvar_Get( "sv_mvd_autorecord", "0", CVAR_LATCH ); - sv_mvd_capture_flags = Cvar_Get( "sv_mvd_capture_flags", "5", 0 ); - sv_mvd_disconnect_time = Cvar_Get( "sv_mvd_disconnect_time", "15", 0 ); - sv_mvd_suspend_time = Cvar_Get( "sv_mvd_suspend_time", "5", 0 ); - sv_mvd_allow_stufftext = Cvar_Get( "sv_mvd_allow_stufftext", "0", CVAR_LATCH ); - - Cmd_Register( c_svmvd ); +void SV_MvdRegister(void) +{ + sv_mvd_enable = Cvar_Get("sv_mvd_enable", "0", CVAR_LATCH); + sv_mvd_maxclients = Cvar_Get("sv_mvd_maxclients", "8", CVAR_LATCH); + sv_mvd_bufsize = Cvar_Get("sv_mvd_bufsize", "2", CVAR_LATCH); + sv_mvd_password = Cvar_Get("sv_mvd_password", "", CVAR_PRIVATE); + sv_mvd_maxsize = Cvar_Get("sv_mvd_maxsize", "0", 0); + sv_mvd_maxtime = Cvar_Get("sv_mvd_maxtime", "0", 0); + sv_mvd_maxmaps = Cvar_Get("sv_mvd_maxmaps", "1", 0); + sv_mvd_noblend = Cvar_Get("sv_mvd_noblend", "0", CVAR_LATCH); + sv_mvd_nogun = Cvar_Get("sv_mvd_nogun", "1", CVAR_LATCH); + sv_mvd_nomsgs = Cvar_Get("sv_mvd_nomsgs", "1", CVAR_LATCH); + sv_mvd_begincmd = Cvar_Get("sv_mvd_begincmd", + "wait 50; putaway; wait 10; help;", 0); + sv_mvd_scorecmd = Cvar_Get("sv_mvd_scorecmd", + "putaway; wait 10; help;", 0); + sv_mvd_autorecord = Cvar_Get("sv_mvd_autorecord", "0", CVAR_LATCH); + sv_mvd_capture_flags = Cvar_Get("sv_mvd_capture_flags", "5", 0); + sv_mvd_disconnect_time = Cvar_Get("sv_mvd_disconnect_time", "15", 0); + sv_mvd_suspend_time = Cvar_Get("sv_mvd_suspend_time", "5", 0); + sv_mvd_allow_stufftext = Cvar_Get("sv_mvd_allow_stufftext", "0", CVAR_LATCH); + + Cmd_Register(c_svmvd); } |