mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 07:11:41 +00:00
"mvd" stuff now gets streamed to the qtv proxy :)
This commit is contained in:
parent
63d787d9e9
commit
966b5ee387
12 changed files with 381 additions and 103 deletions
|
@ -138,11 +138,14 @@
|
|||
#define qtv_stringcmd 2 // [string] message
|
||||
#define qtv_delta 3 // [byte] sequence number, requests delta
|
||||
// compression of message
|
||||
#define qtv_serverdata 4
|
||||
#define qtv_packet 4 // [short] len/type encoding followed by len
|
||||
// bytes of packet data
|
||||
#define qtv_disconnect 5
|
||||
#define qtv_soundlist 6
|
||||
#define qtv_modellist 7
|
||||
#define qtv_signon 8
|
||||
|
||||
#define qtv_p_signon 0x0000
|
||||
#define qtv_p_print 0x1000
|
||||
#define qtv_p_reliable 0x2000 // data would have been sent reliably
|
||||
#define qtv_p_unreliable 0x3000 // data would have been sent unreliably
|
||||
|
||||
// demo recording
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@ typedef struct server_s {
|
|||
int cdtrack;
|
||||
int sounds;
|
||||
struct info_s *info;
|
||||
|
||||
int delta;
|
||||
} server_t;
|
||||
|
||||
void Server_Init (void);
|
||||
|
|
|
@ -67,6 +67,8 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "qtv.h"
|
||||
#include "server.h"
|
||||
|
||||
#undef qtv_print
|
||||
|
||||
SERVER_PLUGIN_PROTOS
|
||||
static plugin_list_t server_plugin_list[] = {
|
||||
SERVER_PLUGIN_LIST
|
||||
|
|
|
@ -97,7 +97,7 @@ server_compare (const void *a, const void *b)
|
|||
}
|
||||
|
||||
static void
|
||||
qtv_server_data (server_t *sv)
|
||||
qtv_serverdata (server_t *sv)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
|
@ -143,7 +143,7 @@ qtv_server_data (server_t *sv)
|
|||
}
|
||||
|
||||
static void
|
||||
qtv_sound_list (server_t *sv)
|
||||
qtv_soundlist (server_t *sv)
|
||||
{
|
||||
int numsounds = MSG_ReadByte (net_message);
|
||||
int n;
|
||||
|
@ -153,7 +153,7 @@ qtv_sound_list (server_t *sv)
|
|||
str = MSG_ReadString (net_message);
|
||||
if (!str[0])
|
||||
break;
|
||||
qtv_printf ("%s\n", str);
|
||||
//qtv_printf ("%s\n", str);
|
||||
numsounds++;
|
||||
if (numsounds == MAX_SOUNDS) {
|
||||
while (str[0])
|
||||
|
@ -177,7 +177,7 @@ qtv_sound_list (server_t *sv)
|
|||
}
|
||||
|
||||
static void
|
||||
qtv_model_list (server_t *sv)
|
||||
qtv_modellist (server_t *sv)
|
||||
{
|
||||
int nummodels = MSG_ReadByte (net_message);
|
||||
int n;
|
||||
|
@ -187,7 +187,7 @@ qtv_model_list (server_t *sv)
|
|||
str = MSG_ReadString (net_message);
|
||||
if (!str[0])
|
||||
break;
|
||||
qtv_printf ("%s\n", str);
|
||||
//qtv_printf ("%s\n", str);
|
||||
nummodels++;
|
||||
if (nummodels == MAX_SOUNDS) {
|
||||
while (str[0])
|
||||
|
@ -211,15 +211,96 @@ qtv_model_list (server_t *sv)
|
|||
}
|
||||
|
||||
static void
|
||||
qtv_sign_on (server_t *sv)
|
||||
qtv_p_signon_f (server_t *sv, int len)
|
||||
{
|
||||
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 = MSG_ReadShort (net_message);
|
||||
buf = malloc (len);
|
||||
MSG_ReadBytes (net_message, buf, len);
|
||||
free (buf); //XXX
|
||||
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
|
||||
|
@ -232,6 +313,19 @@ qtv_cmd_f (server_t *sv)
|
|||
sv->next_run = realtime;
|
||||
}
|
||||
|
||||
static void
|
||||
qtv_skins_f (server_t *sv)
|
||||
{
|
||||
// we don't actually bother checking skins here, but this is a good way
|
||||
// to get everything ready at the last miniute before we start getting
|
||||
// actual in-game update messages
|
||||
MSG_WriteByte (&sv->netchan.message, qtv_stringcmd);
|
||||
MSG_WriteString (&sv->netchan.message, va ("begin %d", sv->spawncount));
|
||||
sv->next_run = realtime;
|
||||
sv->connected = 2;
|
||||
sv->delta = -1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
void (*func) (server_t *sv);
|
||||
|
@ -239,12 +333,13 @@ typedef struct {
|
|||
|
||||
svcmd_t svcmds[] = {
|
||||
{"cmd", qtv_cmd_f},
|
||||
{"skins", qtv_skins_f},
|
||||
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
static void
|
||||
qtv_sv_cmd (server_t *sv)
|
||||
qtv_stringcmd_f (server_t *sv)
|
||||
{
|
||||
svcmd_t *c;
|
||||
const char *name;
|
||||
|
@ -282,6 +377,7 @@ server_handler (connection_t *con, void *object)
|
|||
net_message->readcount++;
|
||||
break;
|
||||
}
|
||||
//qtv_printf ("cmd: %d\n", cmd);
|
||||
switch (cmd) {
|
||||
default:
|
||||
qtv_printf ("Illegible server message: %d\n", cmd);
|
||||
|
@ -289,20 +385,11 @@ server_handler (connection_t *con, void *object)
|
|||
case qtv_disconnect:
|
||||
qtv_printf ("%s: disconnected\n", sv->name);
|
||||
break;
|
||||
case qtv_serverdata:
|
||||
qtv_server_data (sv);
|
||||
break;
|
||||
case qtv_soundlist:
|
||||
qtv_sound_list (sv);
|
||||
break;
|
||||
case qtv_modellist:
|
||||
qtv_model_list (sv);
|
||||
break;
|
||||
case qtv_signon:
|
||||
qtv_sign_on (sv);
|
||||
break;
|
||||
case qtv_stringcmd:
|
||||
qtv_sv_cmd (sv);
|
||||
qtv_stringcmd_f (sv);
|
||||
break;
|
||||
case qtv_packet:
|
||||
qtv_packet_f (sv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -501,11 +588,14 @@ server_shutdown (void)
|
|||
static void
|
||||
server_run (server_t *sv)
|
||||
{
|
||||
//static byte msg[] = {qtv_nop};
|
||||
qtv_printf ("%d\n", sv->netchan.message.cursize);
|
||||
//Netchan_Transmit (&sv->netchan, sizeof (msg), msg);
|
||||
Netchan_Transmit (&sv->netchan, 0, 0);
|
||||
// sv->next_run = realtime + 0.03;
|
||||
static byte msg[2] = {qtv_delta};
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -472,7 +472,7 @@ void SV_FinalMessage (const char *message);
|
|||
void SV_DropClient (client_t *drop);
|
||||
int SV_CalcPing (client_t *cl);
|
||||
void SV_FullClientUpdate (client_t *client, sizebuf_t *buf);
|
||||
void SV_FullClientUpdateToClient (client_t *client, client_t *cl);
|
||||
void SV_FullClientUpdateToClient (client_t *client, backbuf_t *backbuf);
|
||||
|
||||
int SV_ModelIndex (const char *name);
|
||||
|
||||
|
@ -551,6 +551,8 @@ void SV_FindModelNumbers (void);
|
|||
void SV_WriteWorldVars (netchan_t *netchan);
|
||||
void SV_WriteSoundlist (netchan_t *netchan, int n);
|
||||
void SV_WriteModellist (netchan_t *netchan, int n);
|
||||
void SV_WriteSpawn1 (backbuf_t *backbuf, int n);
|
||||
void SV_WriteSpawn2 (backbuf_t *backbuf);
|
||||
void SV_ExecuteClientMessage (client_t *cl);
|
||||
void SV_UserInit (void);
|
||||
void SV_TogglePause (const char *msg);
|
||||
|
|
|
@ -37,5 +37,6 @@ void SV_qtvConnect (int qport, struct info_s *info);
|
|||
int SV_qtvPacket (int qport);
|
||||
void SV_qtvCheckTimeouts (void);
|
||||
void SV_qtvSendMessages (void);
|
||||
void SV_qtvFinalMessage (const char *message);
|
||||
|
||||
#endif//__sv_qtv_h
|
||||
|
|
|
@ -36,10 +36,10 @@ struct sizebuf_s;
|
|||
typedef struct recorder_s recorder_t;
|
||||
|
||||
void SVR_Init (void);
|
||||
recorder_t *SVR_AddUser (void (*writer)(struct sizebuf_s *),
|
||||
int (*frame)(void),
|
||||
void (*finish)(struct sizebuf_s *),
|
||||
int demo);
|
||||
recorder_t *SVR_AddUser (void (*writer)(void *, struct sizebuf_s *, int),
|
||||
int (*frame)(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);
|
||||
|
|
|
@ -102,13 +102,13 @@ memwrite (QFile *_mem, const void *buffer, int size)
|
|||
}
|
||||
|
||||
static void
|
||||
demo_write (sizebuf_t *msg)
|
||||
demo_write (void *unused, sizebuf_t *msg, int unused2)
|
||||
{
|
||||
DWRITE (msg->data, msg->cursize, demo_dest);
|
||||
}
|
||||
|
||||
static int
|
||||
demo_frame (void)
|
||||
demo_frame (void *unused)
|
||||
{
|
||||
double min_fps;
|
||||
|
||||
|
@ -124,7 +124,7 @@ demo_frame (void)
|
|||
}
|
||||
|
||||
static void
|
||||
demo_finish (sizebuf_t *msg)
|
||||
demo_finish (void *unused, sizebuf_t *msg)
|
||||
{
|
||||
// write a disconnect message to the demo file
|
||||
MSG_WriteByte (msg, svc_disconnect);
|
||||
|
@ -406,7 +406,7 @@ SV_Record (char *name)
|
|||
} else
|
||||
QFS_Remove (demo_text->str);
|
||||
|
||||
recorder = SVR_AddUser (demo_write, demo_frame, demo_finish, 1);
|
||||
recorder = SVR_AddUser (demo_write, demo_frame, demo_finish, 1, 0);
|
||||
demo_time = sv.time;
|
||||
|
||||
/*-------------------------------------------------*/
|
||||
|
|
|
@ -313,6 +313,7 @@ SV_FinalMessage (const char *message)
|
|||
if (cl->state >= cs_connected)
|
||||
Netchan_Transmit (&cl->netchan, net_message->message->cursize,
|
||||
net_message->message->data);
|
||||
SV_qtvFinalMessage (message);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -457,16 +458,13 @@ SV_FullClientUpdate (client_t *client, sizebuf_t *buf)
|
|||
Writes all update values to a client's reliable stream
|
||||
*/
|
||||
void
|
||||
SV_FullClientUpdateToClient (client_t *client, client_t *cl)
|
||||
SV_FullClientUpdateToClient (client_t *client, backbuf_t *backbuf)
|
||||
{
|
||||
if (client->state < cs_connected && client->state != cs_server)
|
||||
return;
|
||||
MSG_ReliableCheckBlock (&cl->backbuf, 24 + client->userinfo->cursize);
|
||||
if (cl->backbuf.num_backbuf) {
|
||||
SV_FullClientUpdate (client, &cl->backbuf.backbuf);
|
||||
MSG_Reliable_FinishWrite (&cl->backbuf);
|
||||
} else
|
||||
SV_FullClientUpdate (client, &cl->netchan.message);
|
||||
MSG_ReliableCheckBlock (backbuf, 24 + client->userinfo->cursize);
|
||||
SV_FullClientUpdate (client, &backbuf->backbuf);
|
||||
MSG_Reliable_FinishWrite (backbuf);
|
||||
}
|
||||
|
||||
/* CONNECTIONLESS COMMANDS */
|
||||
|
@ -1983,14 +1981,14 @@ SV_Frame (float time)
|
|||
// send messages back to the clients that had packets read this frame
|
||||
SV_SendClientMessages ();
|
||||
|
||||
SV_qtvSendMessages ();
|
||||
|
||||
demo_start = Sys_DoubleTime ();
|
||||
if (sv.recorders)
|
||||
SV_SendDemoMessage ();
|
||||
demo_end = Sys_DoubleTime ();
|
||||
svs.stats.demo += demo_end - demo_start;
|
||||
|
||||
SV_qtvSendMessages ();
|
||||
|
||||
// send a heartbeat to the master if needed
|
||||
Master_Heartbeat ();
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "compat.h"
|
||||
#include "server.h"
|
||||
#include "sv_qtv.h"
|
||||
#include "sv_recorder.h"
|
||||
|
||||
typedef struct {
|
||||
netchan_t netchan;
|
||||
|
@ -59,6 +60,9 @@ typedef struct {
|
|||
info_t *info;
|
||||
info_key_t *name_key;
|
||||
int packet;
|
||||
recorder_t *recorder;
|
||||
sizebuf_t datagram;
|
||||
byte datagram_buf[MAX_DATAGRAM];
|
||||
} sv_qtv_t;
|
||||
|
||||
#define MAX_PROXIES 2
|
||||
|
@ -81,6 +85,10 @@ static void
|
|||
drop_proxy (sv_qtv_t *proxy)
|
||||
{
|
||||
SV_Printf ("dropped %s\n", proxy->name_key->value);
|
||||
if (proxy->recorder) {
|
||||
SVR_RemoveUser (proxy->recorder);
|
||||
proxy->recorder = 0;
|
||||
}
|
||||
MSG_WriteByte (&proxy->netchan.message, qtv_disconnect);
|
||||
Netchan_Transmit (&proxy->netchan, 0, 0);
|
||||
proxy->packet = 0;
|
||||
|
@ -92,22 +100,33 @@ static void
|
|||
qtv_new_f (sv_qtv_t *proxy)
|
||||
{
|
||||
const char *gamedir;
|
||||
int pos, len;
|
||||
byte *buf;
|
||||
|
||||
gamedir = Info_ValueForKey (svs.info, "*gamedir");
|
||||
if (!gamedir[0])
|
||||
gamedir = "qw";
|
||||
|
||||
MSG_WriteByte (&proxy->netchan.message, qtv_serverdata);
|
||||
MSG_WriteByte (&proxy->netchan.message, qtv_packet);
|
||||
pos = proxy->netchan.message.cursize;
|
||||
MSG_WriteShort (&proxy->netchan.message, qtv_p_signon);
|
||||
MSG_WriteByte (&proxy->netchan.message, svc_serverdata);
|
||||
MSG_WriteLong (&proxy->netchan.message, PROTOCOL_VERSION);
|
||||
MSG_WriteLong (&proxy->netchan.message, svs.spawncount);
|
||||
MSG_WriteString (&proxy->netchan.message, gamedir);
|
||||
SV_WriteWorldVars (&proxy->netchan);
|
||||
len = proxy->netchan.message.cursize - pos - 2;
|
||||
buf = proxy->netchan.message.data + pos;
|
||||
buf[0] = len & 0xff;
|
||||
buf[1] |= (len >> 8) & 0x0f;
|
||||
}
|
||||
|
||||
static void
|
||||
qtv_soundlist_f (sv_qtv_t *proxy)
|
||||
{
|
||||
int n;
|
||||
int pos, len;
|
||||
byte *buf;
|
||||
|
||||
if (atoi (Cmd_Argv (1)) != svs.spawncount) {
|
||||
qtv_new_f (proxy);
|
||||
|
@ -119,14 +138,22 @@ qtv_soundlist_f (sv_qtv_t *proxy)
|
|||
qtv_new_f (proxy);
|
||||
return;
|
||||
}
|
||||
MSG_WriteByte (&proxy->netchan.message, qtv_soundlist);
|
||||
MSG_WriteByte (&proxy->netchan.message, qtv_packet);
|
||||
pos = proxy->netchan.message.cursize;
|
||||
MSG_WriteShort (&proxy->netchan.message, qtv_p_signon);
|
||||
SV_WriteSoundlist (&proxy->netchan, n);
|
||||
len = proxy->netchan.message.cursize - pos - 2;
|
||||
buf = proxy->netchan.message.data + pos;
|
||||
buf[0] = len & 0xff;
|
||||
buf[1] |= (len >> 8) & 0x0f;
|
||||
}
|
||||
|
||||
static void
|
||||
qtv_modellist_f (sv_qtv_t *proxy)
|
||||
{
|
||||
int n;
|
||||
int pos, len;
|
||||
byte *buf;
|
||||
|
||||
if (atoi (Cmd_Argv (1)) != svs.spawncount) {
|
||||
qtv_new_f (proxy);
|
||||
|
@ -138,8 +165,14 @@ qtv_modellist_f (sv_qtv_t *proxy)
|
|||
qtv_new_f (proxy);
|
||||
return;
|
||||
}
|
||||
MSG_WriteByte (&proxy->netchan.message, qtv_modellist);
|
||||
MSG_WriteByte (&proxy->netchan.message, qtv_packet);
|
||||
pos = proxy->netchan.message.cursize;
|
||||
MSG_WriteShort (&proxy->netchan.message, qtv_p_signon);
|
||||
SV_WriteModellist (&proxy->netchan, n);
|
||||
len = proxy->netchan.message.cursize - pos - 2;
|
||||
buf = proxy->netchan.message.data + pos;
|
||||
buf[0] = len & 0xff;
|
||||
buf[1] |= (len >> 8) & 0x0f;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -167,14 +200,83 @@ qtv_prespawn_f (sv_qtv_t *proxy)
|
|||
|
||||
msg = MSG_ReliableCheckBlock (&proxy->backbuf, size);
|
||||
|
||||
MSG_WriteByte (msg, qtv_signon);
|
||||
MSG_WriteShort (msg, sv.signon_buffer_size[buf]);
|
||||
MSG_WriteByte (msg, qtv_packet);
|
||||
MSG_WriteShort (msg, qtv_p_signon | sv.signon_buffer_size[buf]);
|
||||
SZ_Write (msg, sv.signon_buffers[buf], sv.signon_buffer_size[buf]);
|
||||
|
||||
MSG_WriteByte (msg, qtv_stringcmd);
|
||||
MSG_WriteString (msg, command);
|
||||
}
|
||||
|
||||
static void
|
||||
qtv_spawn_f (sv_qtv_t *proxy)
|
||||
{
|
||||
int pos, len;
|
||||
byte *buf;
|
||||
|
||||
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);
|
||||
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_String (&proxy->backbuf, "skins\n");
|
||||
}
|
||||
|
||||
static void
|
||||
qtv_write (void *r, sizebuf_t *msg, int reliable)
|
||||
{
|
||||
sv_qtv_t *proxy = (sv_qtv_t *) r;
|
||||
sizebuf_t *buf;
|
||||
int size;
|
||||
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
MSG_WriteByte (&proxy->datagram, qtv_packet);
|
||||
MSG_WriteShort (&proxy->datagram, qtv_p_unreliable | msg->cursize);
|
||||
SZ_Write (&proxy->datagram, msg->data, msg->cursize);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
qtv_frame (void *r)
|
||||
{
|
||||
sv_qtv_t *proxy = (sv_qtv_t *) r;
|
||||
SV_Printf ("A proxy->packet: %d\n", proxy->packet);
|
||||
return proxy->packet;
|
||||
}
|
||||
|
||||
static void
|
||||
qtv_finish (void *r, sizebuf_t *msg)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
qtv_begin_f (sv_qtv_t *proxy)
|
||||
{
|
||||
if (atoi (Cmd_Argv (1)) != svs.spawncount) {
|
||||
qtv_new_f (proxy);
|
||||
return;
|
||||
}
|
||||
proxy->recorder = SVR_AddUser (qtv_write, qtv_frame, qtv_finish, 0, proxy);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
void (*func) (sv_qtv_t *proxy);
|
||||
|
@ -187,6 +289,8 @@ qcmd_t qcmds[] = {
|
|||
{"soundlist", qtv_soundlist_f},
|
||||
{"modellist", qtv_modellist_f},
|
||||
{"prespawn", qtv_prespawn_f},
|
||||
{"spawn", qtv_spawn_f},
|
||||
{"begin", qtv_begin_f},
|
||||
|
||||
{0, 0},
|
||||
};
|
||||
|
@ -247,6 +351,22 @@ qtv_parse (sv_qtv_t *proxy)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
qtv_reliable_send (sv_qtv_t *proxy)
|
||||
{
|
||||
int pos, len;
|
||||
byte *buf;
|
||||
|
||||
MSG_WriteByte (&proxy->netchan.message, qtv_packet);
|
||||
pos = proxy->netchan.message.cursize;
|
||||
MSG_WriteShort (&proxy->netchan.message, qtv_p_reliable);
|
||||
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;
|
||||
}
|
||||
|
||||
void
|
||||
SV_qtvConnect (int qport, info_t *info)
|
||||
{
|
||||
|
@ -267,6 +387,8 @@ SV_qtvConnect (int qport, info_t *info)
|
|||
Netchan_Setup (&proxy->netchan, net_from, qport, NC_READ_QPORT);
|
||||
proxy->backbuf.netchan = &proxy->netchan;
|
||||
proxy->backbuf.name = proxy->name_key->value;
|
||||
proxy->datagram.data = proxy->datagram_buf;
|
||||
proxy->datagram.maxsize = sizeof (proxy->datagram_buf);
|
||||
|
||||
Netchan_OutOfBandPrint (net_from, "%c", S2C_CONNECTION);
|
||||
}
|
||||
|
@ -329,7 +451,50 @@ SV_qtvSendMessages (void)
|
|||
continue;
|
||||
if (!proxy->packet)
|
||||
continue;
|
||||
if (proxy->backbuf.num_backbuf)
|
||||
qtv_reliable_send (proxy);
|
||||
if (proxy->netchan.message.overflowed) {
|
||||
SZ_Clear (&proxy->netchan.message);
|
||||
drop_proxy (proxy);
|
||||
continue;
|
||||
}
|
||||
if (proxy->datagram.cursize) {
|
||||
Netchan_Transmit (&proxy->netchan, proxy->datagram.cursize,
|
||||
proxy->datagram.data);
|
||||
SZ_Clear (&proxy->datagram);
|
||||
} else {
|
||||
Netchan_Transmit (&proxy->netchan, 0, 0);
|
||||
}
|
||||
SV_Printf ("B proxy->packet: %d\n", proxy->packet);
|
||||
proxy->packet = 0;
|
||||
Netchan_Transmit (&proxy->netchan, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SV_qtvFinalMessage (const char *message)
|
||||
{
|
||||
sv_qtv_t *proxy;
|
||||
int i;
|
||||
int pos, len;
|
||||
byte *buf;
|
||||
|
||||
SZ_Clear (net_message->message);
|
||||
MSG_WriteByte (net_message->message, qtv_packet);
|
||||
pos = net_message->message->cursize;
|
||||
MSG_WriteShort (net_message->message, qtv_p_print);
|
||||
MSG_WriteByte (net_message->message, PRINT_HIGH);
|
||||
MSG_WriteString (net_message->message, message);
|
||||
len = net_message->message->cursize - pos - 2;
|
||||
buf = net_message->message->data + pos;
|
||||
buf[0] = len & 0xff;
|
||||
buf[1] |= (len >> 8) & 0x0f;
|
||||
MSG_WriteByte (net_message->message, qtv_disconnect);
|
||||
|
||||
for (i = 0; i < MAX_PROXIES; i++) {
|
||||
proxy = proxies + i;
|
||||
if (!proxy->info)
|
||||
continue;
|
||||
Netchan_Transmit (&proxy->netchan, net_message->message->cursize,
|
||||
net_message->message->data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,9 +102,10 @@ typedef struct rec_s {
|
|||
|
||||
struct recorder_s {
|
||||
recorder_t *next;
|
||||
void (*write)(sizebuf_t *);
|
||||
int (*frame)(void);
|
||||
void (*finish)(sizebuf_t *);
|
||||
void (*write)(void *, sizebuf_t *, int);
|
||||
int (*frame)(void *);
|
||||
void (*finish)(void *, sizebuf_t *);
|
||||
void *user;
|
||||
delta_t delta;
|
||||
entity_state_t entities[UPDATE_MASK][MAX_DEMO_PACKET_ENTITIES];
|
||||
plent_state_t players[UPDATE_MASK][MAX_CLIENTS];
|
||||
|
@ -325,8 +326,8 @@ SVR_Init (void)
|
|||
}
|
||||
|
||||
recorder_t *
|
||||
SVR_AddUser (void (*write)(sizebuf_t *), int (*frame)(void),
|
||||
void (*finish)(sizebuf_t *), int demo)
|
||||
SVR_AddUser (void (*write)(void *, sizebuf_t *, int), int (*frame)(void *),
|
||||
void (*finish)(void *, sizebuf_t *), int demo, void *user)
|
||||
{
|
||||
recorder_t *r;
|
||||
int i;
|
||||
|
@ -358,6 +359,7 @@ SVR_AddUser (void (*write)(sizebuf_t *), int (*frame)(void),
|
|||
r->write = write;
|
||||
r->frame = frame;
|
||||
r->finish = finish;
|
||||
r->user = user;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -379,13 +381,13 @@ SVR_RemoveUser (recorder_t *r)
|
|||
MSG_WriteByte (&msg, 0);
|
||||
MSG_WriteByte (&msg, dem_all);
|
||||
MSG_WriteLong (&msg, 0);
|
||||
r->finish (&msg);
|
||||
r->finish (r->user, &msg);
|
||||
if (msg.cursize > 6) {
|
||||
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;
|
||||
r->write (&msg);
|
||||
r->write (r->user, &msg, 1);
|
||||
}
|
||||
|
||||
for (_r = &sv.recorders; *_r; _r = &(*_r)->next) {
|
||||
|
@ -434,7 +436,7 @@ write_datagram (recorder_t *r)
|
|||
// 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 (&dst);
|
||||
r->write (r->user, &dst, 0);
|
||||
}
|
||||
|
||||
r->delta.delta_sequence++;
|
||||
|
@ -463,7 +465,7 @@ write_packet (void)
|
|||
write_to_msg (0, 0, time, &msg);
|
||||
|
||||
for (r = sv.recorders; r; r = r->next)
|
||||
r->write (&msg);
|
||||
r->write (r->user, &msg, 1);
|
||||
|
||||
rec.dbuf = &rec.frames[rec.parsecount & DEMO_FRAMES_MASK].buf;
|
||||
rec.dbuf->sz.maxsize = MAXSIZE + rec.dbuf->bufsize;
|
||||
|
@ -530,7 +532,7 @@ SVR_Frame (void)
|
|||
return 1;
|
||||
}
|
||||
for (r = sv.recorders; r; r = r->next)
|
||||
if (r->frame ())
|
||||
if (r->frame (r->user))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ static __attribute__ ((unused)) const char rcsid[] =
|
|||
#include "QF/sys.h"
|
||||
#include "QF/va.h"
|
||||
|
||||
#include "qw/msg_ucmd.h"
|
||||
#include "qw/msg_ucmd.h"
|
||||
|
||||
#include "bothdefs.h"
|
||||
|
@ -191,6 +192,7 @@ SV_WriteSoundlist (netchan_t *netchan, int n)
|
|||
{
|
||||
const char **s;
|
||||
|
||||
MSG_WriteByte (&netchan->message, svc_soundlist);
|
||||
MSG_WriteByte (&netchan->message, n);
|
||||
for (s = sv.sound_precache + 1 + n;
|
||||
*s && netchan->message.cursize < (MAX_MSGLEN / 2);
|
||||
|
@ -237,7 +239,6 @@ SV_Soundlist_f (void *unused)
|
|||
SZ_Clear (&host_client->netchan.message);
|
||||
}
|
||||
|
||||
MSG_WriteByte (&host_client->netchan.message, svc_soundlist);
|
||||
SV_WriteSoundlist (&host_client->netchan, n);
|
||||
}
|
||||
|
||||
|
@ -246,6 +247,7 @@ SV_WriteModellist (netchan_t *netchan, int n)
|
|||
{
|
||||
const char **s;
|
||||
|
||||
MSG_WriteByte (&netchan->message, svc_modellist);
|
||||
MSG_WriteByte (&netchan->message, n);
|
||||
for (s = sv.model_precache + 1 + n;
|
||||
*s && netchan->message.cursize < (MAX_MSGLEN / 2);
|
||||
|
@ -291,7 +293,6 @@ SV_Modellist_f (void *unused)
|
|||
SZ_Clear (&host_client->netchan.message);
|
||||
}
|
||||
|
||||
MSG_WriteByte (&host_client->netchan.message, svc_modellist);
|
||||
SV_WriteModellist (&host_client->netchan, n);
|
||||
}
|
||||
|
||||
|
@ -379,11 +380,51 @@ SV_Spawn (client_t *client)
|
|||
SVfloat (ent, maxspeed) = sv_maxspeed->value;
|
||||
}
|
||||
|
||||
void
|
||||
SV_WriteSpawn1 (backbuf_t *backbuf, int n)
|
||||
{
|
||||
int i;
|
||||
client_t *client;
|
||||
|
||||
// normally this could overflow, but no need to check due to backbuf
|
||||
for (i = n, client = svs.clients + n; i < MAX_CLIENTS; i++, client++)
|
||||
SV_FullClientUpdateToClient (client, backbuf);
|
||||
|
||||
// send all current light styles
|
||||
for (i = 0; i < MAX_LIGHTSTYLES; i++) {
|
||||
MSG_ReliableWrite_Begin (backbuf, svc_lightstyle,
|
||||
3 + (sv.lightstyles[i] ?
|
||||
strlen (sv.lightstyles[i]) : 1));
|
||||
MSG_ReliableWrite_Byte (backbuf, (char) i);
|
||||
MSG_ReliableWrite_String (backbuf, sv.lightstyles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SV_WriteSpawn2 (backbuf_t *backbuf)
|
||||
{
|
||||
|
||||
MSG_ReliableWrite_Begin (backbuf, svc_updatestatlong, 6);
|
||||
MSG_ReliableWrite_Byte (backbuf, STAT_TOTALSECRETS);
|
||||
MSG_ReliableWrite_Long (backbuf, *sv_globals.total_secrets);
|
||||
|
||||
MSG_ReliableWrite_Begin (backbuf, svc_updatestatlong, 6);
|
||||
MSG_ReliableWrite_Byte (backbuf, STAT_TOTALMONSTERS);
|
||||
MSG_ReliableWrite_Long (backbuf, *sv_globals.total_monsters);
|
||||
|
||||
MSG_ReliableWrite_Begin (backbuf, svc_updatestatlong, 6);
|
||||
MSG_ReliableWrite_Byte (backbuf, STAT_SECRETS);
|
||||
MSG_ReliableWrite_Long (backbuf, *sv_globals.found_secrets);
|
||||
|
||||
MSG_ReliableWrite_Begin (backbuf, svc_updatestatlong, 6);
|
||||
MSG_ReliableWrite_Byte (backbuf, STAT_MONSTERS);
|
||||
MSG_ReliableWrite_Long (backbuf, *sv_globals.killed_monsters);
|
||||
}
|
||||
|
||||
static void
|
||||
SV_Spawn_f (void *unused)
|
||||
{
|
||||
int i, n;
|
||||
client_t *client;
|
||||
int n;
|
||||
|
||||
if (host_client->state != cs_connected) {
|
||||
SV_Printf ("Spawn not valid -- already spawned\n");
|
||||
|
@ -419,45 +460,17 @@ SV_Spawn_f (void *unused)
|
|||
SZ_Clear (&host_client->netchan.message);
|
||||
|
||||
// send current status of all other players
|
||||
|
||||
// normally this could overflow, but no need to check due to backbuf
|
||||
for (i = n, client = svs.clients + n; i < MAX_CLIENTS; i++, client++)
|
||||
SV_FullClientUpdateToClient (client, host_client);
|
||||
|
||||
// send all current light styles
|
||||
for (i = 0; i < MAX_LIGHTSTYLES; i++) {
|
||||
MSG_ReliableWrite_Begin (&host_client->backbuf, svc_lightstyle,
|
||||
3 + (sv.lightstyles[i] ?
|
||||
strlen (sv.lightstyles[i]) : 1));
|
||||
MSG_ReliableWrite_Byte (&host_client->backbuf, (char) i);
|
||||
MSG_ReliableWrite_String (&host_client->backbuf, sv.lightstyles[i]);
|
||||
}
|
||||
SV_WriteSpawn1 (&host_client->backbuf, n);
|
||||
|
||||
SV_Spawn (host_client);
|
||||
|
||||
SV_WriteSpawn2 (&host_client->backbuf);
|
||||
|
||||
//
|
||||
// force stats to be updated
|
||||
//
|
||||
memset (host_client->stats, 0, sizeof (host_client->stats));
|
||||
|
||||
MSG_ReliableWrite_Begin (&host_client->backbuf, svc_updatestatlong, 6);
|
||||
MSG_ReliableWrite_Byte (&host_client->backbuf, STAT_TOTALSECRETS);
|
||||
MSG_ReliableWrite_Long (&host_client->backbuf, *sv_globals.total_secrets);
|
||||
|
||||
MSG_ReliableWrite_Begin (&host_client->backbuf, svc_updatestatlong, 6);
|
||||
MSG_ReliableWrite_Byte (&host_client->backbuf, STAT_TOTALMONSTERS);
|
||||
MSG_ReliableWrite_Long (&host_client->backbuf,
|
||||
*sv_globals.total_monsters);
|
||||
|
||||
MSG_ReliableWrite_Begin (&host_client->backbuf, svc_updatestatlong, 6);
|
||||
MSG_ReliableWrite_Byte (&host_client->backbuf, STAT_SECRETS);
|
||||
MSG_ReliableWrite_Long (&host_client->backbuf, *sv_globals.found_secrets);
|
||||
|
||||
MSG_ReliableWrite_Begin (&host_client->backbuf, svc_updatestatlong, 6);
|
||||
MSG_ReliableWrite_Byte (&host_client->backbuf, STAT_MONSTERS);
|
||||
MSG_ReliableWrite_Long (&host_client->backbuf,
|
||||
*sv_globals.killed_monsters);
|
||||
|
||||
// get the client to check and download skins
|
||||
// when that is completed, a begin command will be issued
|
||||
MSG_ReliableWrite_Begin (&host_client->backbuf, svc_stufftext, 8);
|
||||
|
|
Loading…
Reference in a new issue