lots of progress, however mvd player deltas are borked atm

This commit is contained in:
Bill Currie 2005-05-05 11:46:29 +00:00
parent 978ad6ff48
commit d017b87c2b
6 changed files with 489 additions and 161 deletions

View file

@ -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

View file

@ -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

View file

@ -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;
/*-------------------------------------------------*/

View file

@ -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;

View file

@ -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;

View file

@ -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;
}