diff --git a/qtv/source/server.c b/qtv/source/server.c index 5bd499100..e859b8b17 100644 --- a/qtv/source/server.c +++ b/qtv/source/server.c @@ -210,99 +210,6 @@ qtv_modellist (server_t *sv) sv->next_run = realtime; } -static void -qtv_p_signon_f (server_t *sv, int len) -{ - int c, start; - vec3_t v, a; - - start = net_message->readcount; - while (net_message->readcount - start < len) { - c = MSG_ReadByte (net_message); - if (c == -1) - break; - //qtv_printf ("svc: %d\n", c); - switch (c) { - case svc_serverdata: - qtv_serverdata (sv); - break; - case svc_soundlist: - qtv_soundlist (sv); - break; - case svc_modellist: - qtv_modellist (sv); - break; - case svc_spawnstaticsound: - MSG_ReadCoordV (net_message, v); - MSG_ReadByte (net_message); - MSG_ReadByte (net_message); - MSG_ReadByte (net_message); - break; - case svc_spawnbaseline: - MSG_ReadShort (net_message); - case svc_spawnstatic: - MSG_ReadByte (net_message); - MSG_ReadByte (net_message); - MSG_ReadByte (net_message); - MSG_ReadByte (net_message); - MSG_ReadCoordAngleV (net_message, v, a); - break; - case svc_lightstyle: - MSG_ReadByte (net_message); - MSG_ReadString (net_message); - break; - case svc_updatestatlong: - MSG_ReadByte (net_message); - MSG_ReadLong (net_message); - break; - case svc_updatestat: - MSG_ReadByte (net_message); - MSG_ReadByte (net_message); - break; - default: - qtv_printf ("unkown svc: %d\n", c); - return; - } - } -} - -static void -qtv_packet_f (server_t *sv) -{ - int len_type, len, type, pos; - byte *buf; - - len_type = MSG_ReadShort (net_message); - len = len_type & 0x0fff; - type = len_type & 0xf000; - pos = net_message->readcount; - qtv_printf ("qtv_packet: %d %d\n", type, len); - switch (type) { - case qtv_p_signon: - qtv_p_signon_f (sv, len); - break; - case qtv_p_print: - qtv_printf ("%s\n", MSG_ReadString (net_message)); - break; - case qtv_p_reliable: - case qtv_p_unreliable: - default: - //absorb unhandled packet types - qtv_printf ("unknown packet type %x (%d bytes)\n", type, len); - break; - } - if (net_message->readcount - pos != len) { - qtv_printf ("packet not completely read\n"); - - len -= net_message->readcount - pos; - if (len > 0) { - buf = malloc (len); - MSG_ReadBytes (net_message, buf, len); - free (buf); //XXX - } - } -} - static void qtv_cmd_f (server_t *sv) { @@ -358,6 +265,378 @@ qtv_stringcmd_f (server_t *sv) c->func (sv); } +static void +qtv_p_signon_f (server_t *sv, int len) +{ + int c, start; + vec3_t v, a; + + start = net_message->readcount; + while (net_message->readcount - start < len) { + c = MSG_ReadByte (net_message); + if (c == -1) + break; + //qtv_printf ("svc: %d\n", c); + switch (c) { + case svc_serverdata: + qtv_serverdata (sv); + break; + case svc_stufftext: + qtv_stringcmd_f (sv); + break; + case svc_soundlist: + qtv_soundlist (sv); + break; + case svc_modellist: + qtv_modellist (sv); + break; + case svc_spawnstaticsound: + MSG_ReadCoordV (net_message, v); + MSG_ReadByte (net_message); + MSG_ReadByte (net_message); + MSG_ReadByte (net_message); + break; + case svc_spawnbaseline: + MSG_ReadShort (net_message); + case svc_spawnstatic: + MSG_ReadByte (net_message); + MSG_ReadByte (net_message); + MSG_ReadByte (net_message); + MSG_ReadByte (net_message); + MSG_ReadCoordAngleV (net_message, v, a); + break; + case svc_lightstyle: + MSG_ReadByte (net_message); + MSG_ReadString (net_message); + break; + case svc_updatestatlong: + MSG_ReadByte (net_message); + MSG_ReadLong (net_message); + break; + case svc_updatestat: + MSG_ReadByte (net_message); + MSG_ReadByte (net_message); + break; + default: + qtv_printf ("unknown svc: %d\n", c); + return; + } + } +} + +static void +qtv_parse_delta (server_t *sv, qmsg_t *msg, int bits) +{ + bits &= ~511; + + if (bits & U_MOREBITS) + bits |= MSG_ReadByte (msg); + if (bits & U_EXTEND1) { + bits |= MSG_ReadByte (msg) << 16; + if (bits & U_EXTEND2) + bits |= MSG_ReadByte (msg) << 24; + } + if (bits & U_MODEL) + MSG_ReadByte (msg); + if (bits & U_FRAME) + MSG_ReadByte (msg); + if (bits & U_COLORMAP) + MSG_ReadByte (msg); + if (bits & U_SKIN) + MSG_ReadByte (msg); + if (bits & U_EFFECTS) + MSG_ReadByte (msg); + if (bits & U_ORIGIN1) + MSG_ReadCoord (msg); + if (bits & U_ANGLE1) + MSG_ReadAngle (msg); + if (bits & U_ORIGIN2) + MSG_ReadCoord (msg); + if (bits & U_ANGLE2) + MSG_ReadAngle (msg); + if (bits & U_ORIGIN3) + MSG_ReadCoord (msg); + if (bits & U_ANGLE3) + MSG_ReadAngle (msg); + if (bits & U_SOLID) { + // FIXME + } + if (!(bits & U_EXTEND1)) + return; + if (bits & U_ALPHA) + MSG_ReadByte (msg); + if (bits & U_SCALE) + MSG_ReadByte (msg); + if (bits & U_EFFECTS2) + MSG_ReadByte (msg); + if (bits & U_GLOWSIZE) + MSG_ReadByte (msg); + if (bits & U_GLOWCOLOR) + MSG_ReadByte (msg); + if (bits & U_COLORMOD) + MSG_ReadByte (msg); + if (!(bits & U_EXTEND1)) + return; + if (bits & U_FRAME2) + MSG_ReadByte (msg); +} + +static void +qtv_packetentities (server_t *sv, qmsg_t *msg, int delta) +{ + unsigned short word; + int newnum, oldnum; + + newnum = oldnum = 0; + if (delta) { + /*from =*/ MSG_ReadByte (msg); + } else { + } + sv->delta = sv->netchan.incoming_sequence; + while (1) { + word = (unsigned short) MSG_ReadShort (msg); + if (msg->badread) { // something didn't parse right... + qtv_printf ("msg_badread in packetentities\n"); + return; + } + if (!word) { + // copy rest of ents from old packet + break; + } + if (newnum < oldnum) { + if (word & U_REMOVE) { + continue; + } + qtv_parse_delta (sv, msg, word); + continue; + } + if (newnum == oldnum) { + if (word & U_REMOVE) { + continue; + } + qtv_parse_delta (sv, msg, word); + continue; + } + } +} + +static void +qtv_parse_updates (server_t *sv, int reliable, int len) +{ + int c, msec, type, to, start; + sizebuf_t sub_message_buf; + qmsg_t sub_message; + vec3_t v; + + memset (&sub_message_buf, 0, sizeof (sub_message_buf)); + memset (&sub_message, 0, sizeof (sub_message)); + sub_message.message = &sub_message_buf; + + start = net_message->readcount; + while (net_message->readcount - start < len) { + msec = MSG_ReadByte (net_message); + type = MSG_ReadByte (net_message); + if (type == dem_multiple) { + to = MSG_ReadLong (net_message); + } else if (type == dem_single) { + to = MSG_ReadByte (net_message); + } + + sub_message_buf.cursize = MSG_ReadLong (net_message); + sub_message_buf.maxsize = sub_message_buf.cursize; + sub_message_buf.data = net_message->message->data; + sub_message_buf.data += net_message->readcount; + sub_message.readcount = 0; + sub_message.badread = 0; + net_message->readcount += sub_message_buf.cursize; + + while (1) { + c = MSG_ReadByte (&sub_message); + if (c == -1) + break; + //qtv_printf ("qtv_parse_updates: svc: %d\n", c); + switch (c) { + default: + qtv_printf ("qtv_parse_updates: unknown svc: %d\n", c); + return; + case svc_nop: + break; + case svc_updatestat: + MSG_ReadByte (&sub_message); + MSG_ReadByte (&sub_message); + break; + case svc_setview: + break; + case svc_sound: + c = MSG_ReadShort (&sub_message); + if (c & SND_VOLUME) + MSG_ReadByte (&sub_message); + if (c & SND_ATTENUATION) + MSG_ReadByte (&sub_message); + MSG_ReadByte (&sub_message); + MSG_ReadCoordV (&sub_message, v); + break; + case svc_print: + MSG_ReadByte (&sub_message); + MSG_ReadString (&sub_message); + break; + case svc_stufftext: + MSG_ReadString (&sub_message); + break; + case svc_setangle: + MSG_ReadByte (&sub_message); + MSG_ReadAngleV(&sub_message, v); + break; + case svc_lightstyle: + MSG_ReadByte (&sub_message); + MSG_ReadString (&sub_message); + break; + case svc_updatefrags: + MSG_ReadByte (&sub_message); + MSG_ReadShort (&sub_message); + break; + case svc_stopsound: + MSG_ReadShort (&sub_message); + break; + case svc_damage: + MSG_ReadByte (&sub_message); + MSG_ReadByte (&sub_message); + MSG_ReadCoordV (&sub_message, v); + break; + case svc_temp_entity: + //XXX + break; + case svc_setpause: + MSG_ReadByte (&sub_message); + break; + case svc_centerprint: + MSG_ReadString (&sub_message); + break; + case svc_killedmonster: + //XXX + break; + case svc_foundsecret: + //XXX + break; + case svc_intermission: + MSG_ReadCoordV (&sub_message, v); + MSG_ReadAngleV (&sub_message, v); + break; + case svc_finale: + MSG_ReadString (&sub_message); + break; + case svc_cdtrack: + MSG_ReadByte (&sub_message); + break; + case svc_sellscreen: + //XXX + break; + case svc_smallkick: + //XXX + break; + case svc_bigkick: + //XXX + break; + case svc_updateping: + MSG_ReadByte (&sub_message); + MSG_ReadShort (&sub_message); + break; + case svc_updateentertime: + MSG_ReadByte (&sub_message); + MSG_ReadFloat (&sub_message); + break; + case svc_updatestatlong: + MSG_ReadByte (&sub_message); + MSG_ReadLong (&sub_message); + break; + case svc_muzzleflash: + MSG_ReadShort (&sub_message); + break; + case svc_updateuserinfo: + MSG_ReadByte (&sub_message); + MSG_ReadLong (&sub_message); + MSG_ReadString (&sub_message); + break; + case svc_playerinfo: + //XXX + break; + case svc_nails: + //XXX + break; + case svc_packetentities: + qtv_packetentities (sv, &sub_message, 0); + break; + case svc_deltapacketentities: + qtv_packetentities (sv, &sub_message, 1); + break; + case svc_maxspeed: + MSG_ReadFloat (&sub_message); + break; + case svc_entgravity: + MSG_ReadFloat (&sub_message); + break; + case svc_setinfo: + MSG_ReadByte (&sub_message); + MSG_ReadString (&sub_message); + MSG_ReadString (&sub_message); + break; + case svc_serverinfo: + MSG_ReadString (&sub_message); + MSG_ReadString (&sub_message); + break; + case svc_updatepl: + MSG_ReadByte (&sub_message); + MSG_ReadByte (&sub_message); + break; + case svc_nails2: + //XXX + break; + } + } + } +} + +static void +qtv_packet_f (server_t *sv) +{ + int len_type, len, type, pos; + byte *buf; + int reliable = 0; + + len_type = MSG_ReadShort (net_message); + len = len_type & 0x0fff; + type = len_type & 0xf000; + pos = net_message->readcount; + qtv_printf ("qtv_packet: %x %d\n", type, len); + switch (type) { + case qtv_p_signon: + qtv_p_signon_f (sv, len); + break; + case qtv_p_print: + qtv_printf ("%s\n", MSG_ReadString (net_message)); + break; + case qtv_p_reliable: + reliable = 1; + case qtv_p_unreliable: + qtv_parse_updates (sv, reliable, len); + break; + default: + //absorb unhandled packet types + qtv_printf ("unknown packet type %x (%d bytes)\n", type, len); + break; + } + if (net_message->readcount - pos != len) { + qtv_printf ("packet not completely read\n"); + + len -= net_message->readcount - pos; + if (len > 0) { + buf = malloc (len); + MSG_ReadBytes (net_message, buf, len); + free (buf); //XXX + } + } +} + static void server_handler (connection_t *con, void *object) { @@ -380,7 +659,13 @@ server_handler (connection_t *con, void *object) //qtv_printf ("cmd: %d\n", cmd); switch (cmd) { default: - qtv_printf ("Illegible server message: %d\n", cmd); + qtv_printf ("Illegible server message: %d [%d]\n", cmd, + net_message->readcount); + while ((cmd = MSG_ReadByte (net_message)) != -1) { + qtv_printf ("%02x (%c) ", cmd, cmd ? sys_char_map[cmd] + : '#'); + } + qtv_printf ("\n"); goto bail; case qtv_disconnect: qtv_printf ("%s: disconnected\n", sv->name); @@ -549,7 +834,7 @@ sv_del_f (void) } name = Cmd_Argv (1); if (!(sv = Hash_Del (server_hash, name))) { - qtv_printf ("sv_new: %s unkown\n", name); + qtv_printf ("sv_new: %s unknown\n", name); return; } Hash_Free (server_hash, sv); @@ -588,14 +873,20 @@ server_shutdown (void) static void server_run (server_t *sv) { - static byte msg[2] = {qtv_delta}; + static byte delta_msg[2] = {qtv_delta}; + static byte nop_msg[1] = {qtv_nop}; if (sv->connected > 1) { sv->next_run = realtime + 0.03; - msg[1] = sv->delta; - Netchan_Transmit (&sv->netchan, sizeof (msg), msg); - } else { - Netchan_Transmit (&sv->netchan, 0, 0); + if (sv->delta != -1) { + delta_msg[1] = sv->delta; + Netchan_Transmit (&sv->netchan, sizeof (delta_msg), delta_msg); + return; + } else if (!sv->netchan.message.cursize) { + Netchan_Transmit (&sv->netchan, sizeof (nop_msg), nop_msg); + return; + } } + Netchan_Transmit (&sv->netchan, 0, 0); } void diff --git a/qw/include/sv_recorder.h b/qw/include/sv_recorder.h index d0aad8511..34c1fcfc0 100644 --- a/qw/include/sv_recorder.h +++ b/qw/include/sv_recorder.h @@ -38,13 +38,14 @@ typedef struct recorder_s recorder_t; void SVR_Init (void); recorder_t *SVR_AddUser (void (*writer)(void *, struct sizebuf_s *, int), int (*frame)(void *), + void (*end_frame)(recorder_t *, void *), void (*finish)(void *, struct sizebuf_s *), int demo, void *user); void SVR_RemoveUser (recorder_t *r); struct sizebuf_s *SVR_WriteBegin (byte type, int to, int size); struct sizebuf_s *SVR_Datagram (void); void SVR_ForceFrame (void); -int SVR_Frame (void); +void SVR_SetDelta (recorder_t *r, int delta, int in_frame); void SV_SendDemoMessage (void); #endif//__sv_recorder_h diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index 0c299ba74..0cb3fe088 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -63,6 +63,7 @@ static void *demo_dest; static double demo_time; static recorder_t *recorder; +static int delta_sequence; #define MIN_DEMO_MEMORY 0x100000 #define USECACHE (sv_demoUseCache->int_val && svs.demomemsize) @@ -123,6 +124,12 @@ demo_frame (void *unused) return 1; } +static void +demo_end_frame (recorder_t *r, void *unused) +{ + SVR_SetDelta (r, ++delta_sequence, -1); +} + static void demo_finish (void *unused, sizebuf_t *msg) { @@ -406,7 +413,9 @@ SV_Record (char *name) } else QFS_Remove (demo_text->str); - recorder = SVR_AddUser (demo_write, demo_frame, demo_finish, 1, 0); + recorder = SVR_AddUser (demo_write, demo_frame, demo_end_frame, + demo_finish, 1, 0); + delta_sequence = -1; demo_time = sv.time; /*-------------------------------------------------*/ diff --git a/qw/source/sv_ents.c b/qw/source/sv_ents.c index cfd7e67c6..1930d3853 100644 --- a/qw/source/sv_ents.c +++ b/qw/source/sv_ents.c @@ -556,7 +556,7 @@ SV_WritePlayersToClient (delta_t *delta, byte *pvs, sizebuf_t *msg) int stdver = 2, full = stdver; edict_t *ent; packet_players_t *pack; - client_frame_t *frame = &delta->frames[delta->cur_frame]; + client_frame_t *frame = &delta->frames[delta->in_frame]; packet_players_t *from_pack = 0; plent_state_t dummy_player_state, *state = &dummy_player_state; static plent_state_t null_player_state; diff --git a/qw/source/sv_qtv.c b/qw/source/sv_qtv.c index 83ba2cc17..2f2841945 100644 --- a/qw/source/sv_qtv.c +++ b/qw/source/sv_qtv.c @@ -59,10 +59,11 @@ typedef struct { backbuf_t backbuf; info_t *info; info_key_t *name_key; - int packet; + qboolean packet; recorder_t *recorder; sizebuf_t datagram; byte datagram_buf[MAX_DATAGRAM]; + int begun; } sv_qtv_t; #define MAX_PROXIES 2 @@ -91,7 +92,7 @@ drop_proxy (sv_qtv_t *proxy) } MSG_WriteByte (&proxy->netchan.message, qtv_disconnect); Netchan_Transmit (&proxy->netchan, 0, 0); - proxy->packet = 0; + proxy->packet = false; Info_Destroy (proxy->info); proxy->info = 0; } @@ -196,7 +197,7 @@ qtv_prespawn_f (sv_qtv_t *proxy) command = va ("cmd spawn %i 0\n", svs.spawncount); else command = va ("cmd prespawn %i %i\n", svs.spawncount, buf + 1); - size = 5 + sv.signon_buffer_size[buf] + 1 + strlen (command) + 2; + size = (5 + sv.signon_buffer_size[buf]) + (1 + strlen (command) + 1); msg = MSG_ReliableCheckBlock (&proxy->backbuf, size); @@ -211,24 +212,28 @@ qtv_prespawn_f (sv_qtv_t *proxy) static void qtv_spawn_f (sv_qtv_t *proxy) { - int pos, len; - byte *buf; + int pos = -1, len = 0; + byte *buf = 0; if (atoi (Cmd_Argv (1)) != svs.spawncount) { qtv_new_f (proxy); return; } - MSG_WriteByte (&proxy->netchan.message, qtv_packet); - pos = proxy->netchan.message.cursize; - MSG_WriteShort (&proxy->netchan.message, qtv_p_signon); + if (!proxy->backbuf.num_backbuf) { + MSG_WriteByte (&proxy->netchan.message, qtv_packet); + pos = proxy->netchan.message.cursize; + MSG_WriteShort (&proxy->netchan.message, qtv_p_signon); + } SV_WriteSpawn1 (&proxy->backbuf, 0); SV_WriteSpawn2 (&proxy->backbuf); - len = proxy->netchan.message.cursize - pos - 2; - buf = proxy->netchan.message.data + pos; - buf[0] = len & 0xff; - buf[1] |= (len >> 8) & 0x0f; - MSG_ReliableWrite_Begin (&proxy->backbuf, qtv_stringcmd, 8); + MSG_ReliableWrite_Begin (&proxy->backbuf, svc_stufftext, 8); MSG_ReliableWrite_String (&proxy->backbuf, "skins\n"); + if (pos != -1) { + len = proxy->netchan.message.cursize - pos - 2; + buf = proxy->netchan.message.data + pos; + buf[0] = len & 0xff; + buf[1] |= (len >> 8) & 0x0f; + } } static void @@ -236,22 +241,20 @@ qtv_write (void *r, sizebuf_t *msg, int reliable) { sv_qtv_t *proxy = (sv_qtv_t *) r; sizebuf_t *buf; - int size; + int type; + if (!msg->cursize) + return; if (reliable) { - if (msg->cursize) { - size = msg->cursize + 3; - buf = MSG_ReliableCheckBlock (&proxy->backbuf, size); - - MSG_WriteByte (buf, qtv_packet); - MSG_WriteShort (buf, qtv_p_reliable | msg->cursize); - SZ_Write (buf, msg->data, msg->cursize); - } + buf = MSG_ReliableCheckBlock (&proxy->backbuf, msg->cursize); + type = qtv_p_reliable; } else { - MSG_WriteByte (&proxy->datagram, qtv_packet); - MSG_WriteShort (&proxy->datagram, qtv_p_unreliable | msg->cursize); - SZ_Write (&proxy->datagram, msg->data, msg->cursize); + buf = &proxy->datagram; + type = qtv_p_unreliable; } + MSG_WriteByte (buf, qtv_packet); + MSG_WriteShort (buf, type | msg->cursize); + SZ_Write (buf, msg->data, msg->cursize); } static int @@ -273,7 +276,9 @@ qtv_begin_f (sv_qtv_t *proxy) qtv_new_f (proxy); return; } - proxy->recorder = SVR_AddUser (qtv_write, qtv_frame, qtv_finish, 0, proxy); + proxy->recorder = SVR_AddUser (qtv_write, qtv_frame, 0, qtv_finish, 0, + proxy); + proxy->begun = 1; } typedef struct { @@ -317,9 +322,19 @@ qtv_command (sv_qtv_t *proxy, const char *s) static void qtv_parse (sv_qtv_t *proxy) { - int c; + int c, delta; - proxy->packet = 1; + // make sure the reply sequence number matches the incoming + // sequence number + if (proxy->netchan.incoming_sequence >= proxy->netchan.outgoing_sequence) { + proxy->netchan.outgoing_sequence = proxy->netchan.incoming_sequence; + proxy->packet = true; + } else { + proxy->packet = false; // don't reply, sequences have slipped + return; // FIXME right thing? + } + if (proxy->recorder) + SVR_SetDelta (proxy->recorder, -1, proxy->netchan.incoming_sequence); while (1) { if (net_message->badread) { SV_Printf ("SV_ReadClientMessage: badread\n"); @@ -344,7 +359,10 @@ qtv_parse (sv_qtv_t *proxy) break; case qtv_delta: - MSG_ReadByte (net_message); + delta = MSG_ReadByte (net_message); + if (proxy->recorder) + SVR_SetDelta (proxy->recorder, delta, + proxy->netchan.incoming_sequence); break; } } @@ -353,17 +371,22 @@ qtv_parse (sv_qtv_t *proxy) static void qtv_reliable_send (sv_qtv_t *proxy) { - int pos, len; - byte *buf; + int pos = 0, len = 0; + byte *buf = 0; - MSG_WriteByte (&proxy->netchan.message, qtv_packet); - pos = proxy->netchan.message.cursize; - MSG_WriteShort (&proxy->netchan.message, qtv_p_reliable); + SV_Printf ("proxy->begun: %d\n", proxy->begun); + if (!proxy->begun) { + MSG_WriteByte (&proxy->netchan.message, qtv_packet); + pos = proxy->netchan.message.cursize; + MSG_WriteShort (&proxy->netchan.message, qtv_p_signon); + } MSG_Reliable_Send (&proxy->backbuf); - len = proxy->netchan.message.cursize - pos - 2; - buf = proxy->netchan.message.data + pos; - buf[0] = len & 0xff; - buf[1] |= (len >> 8) & 0x0f; + if (!proxy->begun) { + len = proxy->netchan.message.cursize - pos - 2; + buf = proxy->netchan.message.data + pos; + buf[0] = len & 0xff; + buf[1] |= (len >> 8) & 0x0f; + } } void @@ -371,8 +394,7 @@ SV_qtvConnect (int qport, info_t *info) { sv_qtv_t *proxy; - SV_Printf ("QTV proxy connection: %d %s\n", Cmd_Argc (), Cmd_Args (1)); - SV_Printf ("qport: %d\n", qport); + SV_Printf ("QTV proxy connection: %s\n", NET_AdrToString (net_from)); if (!(proxy = alloc_proxy ())) { SV_Printf ("%s:full proxy connect\n", NET_AdrToString (net_from)); @@ -388,6 +410,7 @@ SV_qtvConnect (int qport, info_t *info) proxy->backbuf.name = proxy->name_key->value; proxy->datagram.data = proxy->datagram_buf; proxy->datagram.maxsize = sizeof (proxy->datagram_buf); + proxy->begun = 0; Netchan_OutOfBandPrint (net_from, "%c", S2C_CONNECTION); } @@ -411,8 +434,8 @@ SV_qtvPacket (int qport) if (Netchan_Process (&proxies[i].netchan)) { // this is a valid, sequenced packet, so process it svs.stats.packets++; + qtv_parse (&proxies[i]); } - qtv_parse (&proxies[i]); return 1; } return 0; diff --git a/qw/source/sv_recorder.c b/qw/source/sv_recorder.c index c4661f959..65240affd 100644 --- a/qw/source/sv_recorder.c +++ b/qw/source/sv_recorder.c @@ -104,6 +104,7 @@ struct recorder_s { recorder_t *next; void (*write)(void *, sizebuf_t *, int); int (*frame)(void *); + void (*end_frame)(recorder_t *, void *); void (*finish)(void *, sizebuf_t *); void *user; delta_t delta; @@ -327,6 +328,7 @@ SVR_Init (void) recorder_t * SVR_AddUser (void (*write)(void *, sizebuf_t *, int), int (*frame)(void *), + void (*end_frame)(recorder_t *, void *), void (*finish)(void *, sizebuf_t *), int demo, void *user) { recorder_t *r; @@ -356,8 +358,11 @@ SVR_AddUser (void (*write)(void *, sizebuf_t *, int), int (*frame)(void *), r->delta.frames[i].entities.entities = r->entities[i]; r->delta.frames[i].players.players = r->players[i]; } + r->delta.delta_sequence = -1; + r->write = write; r->frame = frame; + r->end_frame = end_frame; r->finish = finish; r->user = user; @@ -415,32 +420,17 @@ write_datagram (recorder_t *r) dst.maxsize = sizeof (msg_buffer[1]); dst.allowoverflow = true; -// MSG_WriteByte (&msg, 0); -// MSG_WriteByte (&msg, dem_all); -// MSG_WriteLong (&msg, 0); - - if (!r->delta.delta_sequence) - r->delta.delta_sequence = -1; - r->delta.cur_frame = (r->delta.delta_sequence + 1) & UPDATE_MASK; - r->delta.out_frame = r->delta.cur_frame; SV_WriteEntitiesToClient (&r->delta, &msg); // copy the accumulated multicast datagram // for this client out to the message if (rec.datagram.cursize) SZ_Write (&msg, rec.datagram.data, rec.datagram.cursize); -// if (msg.cursize > 6) { if (msg.cursize) { -// msg.data[2] = ((msg.cursize - 6) >> 0) & 0xff; -// msg.data[3] = ((msg.cursize - 6) >> 8) & 0xff; -// msg.data[4] = ((msg.cursize - 6) >> 16) & 0xff; -// msg.data[5] = ((msg.cursize - 6) >> 24) & 0xff; double time = rec.frames[rec.lastwritten & DEMO_FRAMES_MASK].time; write_msg (&msg, dem_all, 0, time, &dst); r->write (r->user, &dst, 0); } - r->delta.delta_sequence++; - r->delta.delta_sequence &= UPDATE_MASK; rec.frames[rec.parsecount & DEMO_FRAMES_MASK].time = rec.time = sv.time; } @@ -522,7 +512,7 @@ SVR_ForceFrame (void) rec.forceFrame = 1; } -int +static int SVR_Frame (void) { recorder_t *r; @@ -605,11 +595,25 @@ SV_SendDemoMessage (void) // send over all the objects that are in the PVS // this will include clients, a packetentities, and // possibly a nails update - for (r = sv.recorders; r; r = r->next) + for (r = sv.recorders; r; r = r->next) { write_datagram (r); + if (r->end_frame) + r->end_frame (r, r->user); + } SZ_Clear (&rec.datagram); rec.parsecount++; set_msgbuf (rec.dbuf, &rec.frames[rec.parsecount & DEMO_FRAMES_MASK].buf); rec.lastwritten++; } + +void +SVR_SetDelta (recorder_t *r, int delta, int in_frame) +{ + r->delta.delta_sequence = -1; + if (delta != -1) + r->delta.delta_sequence = delta & UPDATE_MASK; + r->delta.in_frame = (r->delta.delta_sequence + 1) & UPDATE_MASK; + if (in_frame != -1) + r->delta.in_frame = in_frame & UPDATE_MASK; +}