diff --git a/include/Makefile.am b/include/Makefile.am index 0bbccdb2f..4578ff53b 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -12,7 +12,7 @@ EXTRA_DIST = asm_i386.h alsa_funcs_list.h adivtab.h anorm_dots.h anorms.h \ r_local.h r_screen.h r_shared.h rua_internal.h sbar.h skin_stencil.h \ snd_render.h varrays.h vgamodes.h view.h vregset.h winquake.h world.h \ \ - qw/msg_backbuf.h qw/msg_ucmd.h qw/protocol.h \ + qw/msg_backbuf.h qw/msg_ucmd.h qw/pmove.h qw/protocol.h \ \ win32/fnmatch.h \ \ diff --git a/qw/include/pmove.h b/include/qw/pmove.h similarity index 100% rename from qw/include/pmove.h rename to include/qw/pmove.h diff --git a/include/qw/protocol.h b/include/qw/protocol.h index 61130b532..210dc0c42 100644 --- a/include/qw/protocol.h +++ b/include/qw/protocol.h @@ -131,6 +131,16 @@ #define clc_tmove 6 // teleport request, spectator only #define clc_upload 7 // teleport request, spectator only +// qtv ======================================================================== + +#define qtv_bad 0 +#define qtv_nop 1 +#define qtv_stringcmd 2 // [string] message +#define qtv_delta 3 // [byte] sequence number, requests delta + // compression of message +#define qtv_serverdata 4 +#define qtv_disconnect 5 + // demo recording #define dem_cmd 0 diff --git a/libs/util/sys.c b/libs/util/sys.c index 1be18de4e..d3de9e52c 100644 --- a/libs/util/sys.c +++ b/libs/util/sys.c @@ -523,10 +523,10 @@ Sys_CheckInput (int idle, int net_socket) } _timeout.tv_sec = 0; - _timeout.tv_usec = net_socket < 0 ? 0 : 100; + _timeout.tv_usec = net_socket < 0 ? 0 : 20; #else _timeout.tv_sec = 0; - _timeout.tv_usec = net_socket < 0 ? 0 : 10000; + _timeout.tv_usec = net_socket < 0 ? 0 : 2000; #endif // select on the net socket and stdin // the only reason we have a timeout at all is so that if the last diff --git a/qtv/include/server.h b/qtv/include/server.h index 7a6e15533..d42c977e6 100644 --- a/qtv/include/server.h +++ b/qtv/include/server.h @@ -33,18 +33,30 @@ #define __server_h #include "netchan.h" +#include "qw/pmove.h" typedef struct server_s { + struct server_s *next; const char *name; const char *address; int qport; int connected; - struct info_s *info; struct connection_s *con; netadr_t adr; netchan_t netchan; + double next_run; + + int ver; + int spawncount; + const char *gamedir; + const char *message; + movevars_t movevars; + int cdtrack; + int sounds; + struct info_s *info; } server_t; void Server_Init (void); +void Server_Frame (void); #endif//__server_h diff --git a/qtv/source/qtv.c b/qtv/source/qtv.c index 8f0dd62a4..97bdd9076 100644 --- a/qtv/source/qtv.c +++ b/qtv/source/qtv.c @@ -388,6 +388,8 @@ main (int argc, const char *argv[]) qtv_read_packets (); Con_ProcessInput (); + + Server_Frame (); } return 0; } diff --git a/qtv/source/server.c b/qtv/source/server.c index 30ae9e8d5..a695230ee 100644 --- a/qtv/source/server.c +++ b/qtv/source/server.c @@ -61,7 +61,8 @@ static __attribute__ ((unused)) const char rcsid[] = #include "qtv.h" #include "server.h" -static hashtab_t *servers; +static hashtab_t *server_hash; +static server_t *servers; static const char * server_get_key (void *sv, void *unused) @@ -73,11 +74,20 @@ static void server_free (void *_sv, void *unused) { server_t *sv = (server_t *) _sv; - static byte final[] = {clc_stringcmd, 'd', 'r', 'o', 'p', 0}; + server_t **s; + + static byte final[] = {qtv_stringcmd, 'd', 'r', 'o', 'p', 0}; if (sv->connected) Netchan_Transmit (&sv->netchan, sizeof (final), final); Connection_Del (sv->con); + + for (s = &servers; *s; s = &(*s)->next) { + if (*s == sv) { + *s = sv->next; + break; + } + } } static int @@ -86,11 +96,51 @@ server_compare (const void *a, const void *b) return strcmp ((*(server_t **) a)->name, (*(server_t **) b)->name); } +static void +qtv_server_data (server_t *sv) +{ + const char *str; + + sv->ver = MSG_ReadLong (net_message); + sv->spawncount = MSG_ReadLong (net_message); + sv->gamedir = strdup (MSG_ReadString (net_message)); + + sv->message = strdup (MSG_ReadString (net_message)); + sv->movevars.gravity = MSG_ReadFloat (net_message); + sv->movevars.stopspeed = MSG_ReadFloat (net_message); + sv->movevars.maxspeed = MSG_ReadFloat (net_message); + sv->movevars.spectatormaxspeed = MSG_ReadFloat (net_message); + sv->movevars.accelerate = MSG_ReadFloat (net_message); + sv->movevars.airaccelerate = MSG_ReadFloat (net_message); + sv->movevars.wateraccelerate = MSG_ReadFloat (net_message); + sv->movevars.friction = MSG_ReadFloat (net_message); + sv->movevars.waterfriction = MSG_ReadFloat (net_message); + sv->movevars.entgravity = MSG_ReadFloat (net_message); + + sv->cdtrack = MSG_ReadByte (net_message); + sv->sounds = MSG_ReadByte (net_message); + + COM_TokenizeString (MSG_ReadString (net_message), qtv_args); + cmd_args = qtv_args; + sv->info = Info_ParseString (Cmd_Argv (1), MAX_SERVERINFO_STRING, 0); + + str = Info_ValueForKey (sv->info, "hostname"); + if (strcmp (str, "unnamed")) + qtv_printf ("%s: %s\n", sv->name, str); + str = Info_ValueForKey (sv->info, "*version"); + qtv_printf ("%s: QW %s\n", sv->name, str); + str = Info_ValueForKey (sv->info, "*qf_version"); + if (str[0]) + qtv_printf ("%s: QuakeForge %s\n", sv->name, str); + qtv_printf ("%s: gamedir: %s\n", sv->name, sv->gamedir); + str = Info_ValueForKey (sv->info, "map"); + qtv_printf ("%s: (%s) %s\n", sv->name, str, sv->message); +} + static void server_handler (connection_t *con, void *object) { server_t *sv = (server_t *) object; - byte d = clc_nop; if (*(int *) net_message->message->data == -1) return; @@ -110,13 +160,16 @@ server_handler (connection_t *con, void *object) default: qtv_printf ("Illegible server message: %d\n", cmd); goto bail; - case svc_disconnect: + case qtv_disconnect: qtv_printf ("%s: disconnected\n", sv->name); break; + case qtv_serverdata: + qtv_server_data (sv); + break; } } bail: - Netchan_Transmit (&sv->netchan, 1, &d); + return; } static inline const char * @@ -157,10 +210,12 @@ server_connect (connection_t *con, void *object) Netchan_Setup (&sv->netchan, con->address, sv->qport, NC_SEND_QPORT); sv->netchan.outgoing_sequence = 1; sv->connected = 1; - MSG_WriteByte (msg, clc_stringcmd); + MSG_WriteByte (msg, qtv_stringcmd); MSG_WriteString (msg, "new"); Netchan_Transmit (&sv->netchan, 0, 0); con->handler = server_handler; + + sv->next_run = realtime; } static void @@ -192,8 +247,8 @@ server_challenge (connection_t *con, void *object) if (!qtv) { qtv_printf ("%s can't handle qtv.\n", sv->name); - Hash_Del (servers, sv->name); - Hash_Free (servers, sv); + Hash_Del (server_hash, sv->name); + Hash_Free (server_hash, sv); return; } @@ -228,7 +283,7 @@ sv_new_f (void) return; } name = Cmd_Argv (1); - if (Hash_Find (servers, name)) { + if (Hash_Find (server_hash, name)) { qtv_printf ("sv_new: %s already exists\n", name); return; } @@ -241,6 +296,8 @@ sv_new_f (void) adr.port = BigShort (27500); sv = calloc (1, sizeof (server_t)); + sv->next = servers; + servers = sv; sv->name = strdup (name); sv->address = strdup (address); sv->adr = adr; @@ -250,7 +307,7 @@ sv_new_f (void) va ("%s QTV %s", QW_VERSION, VERSION), 0); Info_SetValueForStarKey (sv->info, "*qsg_version", QW_QSG_VERSION, 0); Info_SetValueForKey (sv->info, "name", "QTV Proxy", 0); - Hash_Add (servers, sv); + Hash_Add (server_hash, sv); sv->con = Connection_Add (&adr, sv, server_challenge); @@ -268,11 +325,11 @@ sv_del_f (void) return; } name = Cmd_Argv (1); - if (!(sv = Hash_Del (servers, name))) { + if (!(sv = Hash_Del (server_hash, name))) { qtv_printf ("sv_new: %s unkown\n", name); return; } - Hash_Free (servers, sv); + Hash_Free (server_hash, sv); } static void @@ -281,33 +338,57 @@ sv_list_f (void) server_t **list, **l, *sv; int count; - list = (server_t **) Hash_GetList (servers); - for (l = list, count = 0; *l; l++) + for (l = &servers, count = 0; *l; l = &(*l)->next) count++; if (!count) { qtv_printf ("no servers\n"); return; } + list = malloc (count * sizeof (server_t **)); + for (l = &servers, count = 0; *l; l = &(*l)->next) + list[count] = *l; qsort (list, count, sizeof (*list), server_compare); for (l = list; *l; l++) { sv = *l; qtv_printf ("%-20s %s(%s)\n", sv->name, sv->address, NET_AdrToString (sv->adr)); } + free (list); } static void server_shutdown (void) { - Hash_FlushTable (servers); + Hash_FlushTable (server_hash); +} + +static void +server_run (server_t *sv) +{ + static byte msg[] = {qtv_nop}; + Netchan_Transmit (&sv->netchan, sizeof (msg), msg); + sv->next_run = realtime + 0.03; } void Server_Init (void) { Sys_RegisterShutdown (server_shutdown); - servers = Hash_NewTable (61, server_get_key, server_free, 0); + server_hash = Hash_NewTable (61, server_get_key, server_free, 0); Cmd_AddCommand ("sv_new", sv_new_f, "Add a new server"); Cmd_AddCommand ("sv_del", sv_del_f, "Remove an existing server"); Cmd_AddCommand ("sv_list", sv_list_f, "List available servers"); } + +void +Server_Frame (void) +{ + server_t *sv; + + for (sv = servers; sv; sv = sv->next) { + if (sv->next_run && sv->next_run <= realtime) { + sv->next_run = 0; + server_run (sv); + } + } +} diff --git a/qw/include/Makefile.am b/qw/include/Makefile.am index 4a8088fd7..9dec1b7bb 100644 --- a/qw/include/Makefile.am +++ b/qw/include/Makefile.am @@ -4,6 +4,5 @@ AUTOMAKE_OPTIONS= foreign EXTRA_DIST = \ bothdefs.h cl_cam.h cl_chat.h cl_demo.h cl_ents.h cl_input.h \ cl_main.h cl_parse.h cl_pred.h cl_skin.h cl_slist.h cl_tent.h \ - client.h crudefile.h game.h host.h pmove.h \ - server.h sv_gib.h sv_demo.h sv_pr_cmds.h sv_pr_qwe.h sv_progs.h \ - sv_qtv.h + client.h crudefile.h game.h host.h server.h sv_gib.h sv_demo.h \ + sv_pr_cmds.h sv_pr_qwe.h sv_progs.h sv_qtv.h diff --git a/qw/include/server.h b/qw/include/server.h index c102b76a9..d40a1b310 100644 --- a/qw/include/server.h +++ b/qw/include/server.h @@ -548,6 +548,7 @@ void SV_FindModelNumbers (void); #define UCMD_NO_REDIRECT 1 #define UCMD_OVERRIDABLE 2 +void SV_WriteWorldVars (netchan_t *netchan); void SV_ExecuteClientMessage (client_t *cl); void SV_UserInit (void); void SV_TogglePause (const char *msg); diff --git a/qw/include/sv_qtv.h b/qw/include/sv_qtv.h index 41be49102..e02900f29 100644 --- a/qw/include/sv_qtv.h +++ b/qw/include/sv_qtv.h @@ -36,5 +36,6 @@ struct info_s; void SV_qtvConnect (int qport, struct info_s *info); int SV_qtvPacket (int qport); void SV_qtvCheckTimeouts (void); +void SV_qtvSendMessages (void); #endif//__sv_qtv_h diff --git a/qw/source/cl_cam.c b/qw/source/cl_cam.c index 819d45384..5cf89e1ca 100644 --- a/qw/source/cl_cam.c +++ b/qw/source/cl_cam.c @@ -53,7 +53,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "cl_input.h" #include "client.h" #include "compat.h" -#include "pmove.h" +#include "qw/pmove.h" #include "sbar.h" #define PM_SPECTATORMAXSPEED 500 diff --git a/qw/source/cl_demo.c b/qw/source/cl_demo.c index c3c078737..7fc3ffe06 100644 --- a/qw/source/cl_demo.c +++ b/qw/source/cl_demo.c @@ -60,7 +60,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "client.h" #include "compat.h" #include "host.h" -#include "pmove.h" +#include "qw/pmove.h" typedef struct { int frames; diff --git a/qw/source/cl_ents.c b/qw/source/cl_ents.c index 0c32cb9d2..ac7854640 100644 --- a/qw/source/cl_ents.c +++ b/qw/source/cl_ents.c @@ -57,7 +57,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "compat.h" #include "d_iface.h" #include "host.h" -#include "pmove.h" +#include "qw/pmove.h" #include "r_cvar.h" #include "r_dynamic.h" #include "view.h" diff --git a/qw/source/cl_main.c b/qw/source/cl_main.c index 6ef268e46..a2759d03f 100644 --- a/qw/source/cl_main.c +++ b/qw/source/cl_main.c @@ -103,7 +103,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "game.h" #include "host.h" #include "netchan.h" -#include "pmove.h" +#include "qw/pmove.h" #include "r_cvar.h" #include "r_dynamic.h" #include "sbar.h" diff --git a/qw/source/cl_parse.c b/qw/source/cl_parse.c index d32ece027..366b88fbd 100644 --- a/qw/source/cl_parse.c +++ b/qw/source/cl_parse.c @@ -73,7 +73,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "client.h" #include "compat.h" #include "host.h" -#include "pmove.h" +#include "qw/pmove.h" #include "qw/protocol.h" #include "sbar.h" #include "view.h" diff --git a/qw/source/cl_pred.c b/qw/source/cl_pred.c index 9087c60bd..f4b0a8843 100644 --- a/qw/source/cl_pred.c +++ b/qw/source/cl_pred.c @@ -42,7 +42,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "cl_ents.h" #include "cl_pred.h" #include "client.h" -#include "pmove.h" +#include "qw/pmove.h" cvar_t *cl_predict; cvar_t *cl_pushlatency; diff --git a/qw/source/cl_view.c b/qw/source/cl_view.c index f912e8f91..dfead6e6f 100644 --- a/qw/source/cl_view.c +++ b/qw/source/cl_view.c @@ -45,7 +45,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "client.h" #include "compat.h" #include "host.h" -#include "pmove.h" +#include "qw/pmove.h" #include "view.h" /* diff --git a/qw/source/pmove.c b/qw/source/pmove.c index 08f9ef19b..151024532 100644 --- a/qw/source/pmove.c +++ b/qw/source/pmove.c @@ -39,7 +39,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "client.h" #include "compat.h" -#include "pmove.h" +#include "qw/pmove.h" cvar_t *no_pogo_stick; movevars_t movevars; diff --git a/qw/source/pmovetst.c b/qw/source/pmovetst.c index e30c5f32e..6fb338f6a 100644 --- a/qw/source/pmovetst.c +++ b/qw/source/pmovetst.c @@ -44,7 +44,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "QF/sys.h" #include "compat.h" -#include "pmove.h" +#include "qw/pmove.h" #include "world.h" static hull_t box_hull; diff --git a/qw/source/sv_demo.c b/qw/source/sv_demo.c index bde3b07a7..81346b800 100644 --- a/qw/source/sv_demo.c +++ b/qw/source/sv_demo.c @@ -48,7 +48,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "QF/va.h" #include "compat.h" -#include "pmove.h" +#include "qw/pmove.h" #include "server.h" #include "sv_demo.h" #include "sv_progs.h" diff --git a/qw/source/sv_init.c b/qw/source/sv_init.c index 7676ae52e..2f91aa824 100644 --- a/qw/source/sv_init.c +++ b/qw/source/sv_init.c @@ -48,7 +48,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "compat.h" #include "crudefile.h" -#include "pmove.h" +#include "qw/pmove.h" #include "server.h" #include "sv_progs.h" #include "sv_gib.h" diff --git a/qw/source/sv_main.c b/qw/source/sv_main.c index 957b864b6..fb4baaa22 100644 --- a/qw/source/sv_main.c +++ b/qw/source/sv_main.c @@ -85,7 +85,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "crudefile.h" #include "game.h" #include "netchan.h" -#include "pmove.h" +#include "qw/pmove.h" #include "server.h" #include "sv_demo.h" #include "sv_progs.h" @@ -1983,6 +1983,8 @@ 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 (); diff --git a/qw/source/sv_phys.c b/qw/source/sv_phys.c index 7d1df065f..85900e7cd 100644 --- a/qw/source/sv_phys.c +++ b/qw/source/sv_phys.c @@ -35,7 +35,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "QF/cvar.h" #include "QF/sys.h" -#include "pmove.h" +#include "qw/pmove.h" #include "server.h" #include "sv_progs.h" #include "world.h" diff --git a/qw/source/sv_qtv.c b/qw/source/sv_qtv.c index 6a3b751d8..68a7f6024 100644 --- a/qw/source/sv_qtv.c +++ b/qw/source/sv_qtv.c @@ -34,10 +34,21 @@ static __attribute__ ((unused)) const char rcsid[] = "$Id$"; +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif + #include "QF/cmd.h" +#include "QF/cbuf.h" +#include "QF/dstring.h" #include "QF/hash.h" +#include "QF/idparse.h" #include "QF/info.h" +#include "compat.h" #include "server.h" #include "sv_qtv.h" @@ -46,6 +57,7 @@ typedef struct { backbuf_t backbuf; info_t *info; info_key_t *name_key; + int packet; } sv_qtv_t; #define MAX_PROXIES 2 @@ -64,6 +76,102 @@ alloc_proxy (void) return 0; } +static void +drop_proxy (sv_qtv_t *proxy) +{ + SV_Printf ("dropped %s\n", proxy->name_key->value); + MSG_WriteByte (&proxy->netchan.message, qtv_disconnect); + Netchan_Transmit (&proxy->netchan, 0, 0); + proxy->packet = 0; + Info_Destroy (proxy->info); + proxy->info = 0; +} + +static void +qtv_new_f (sv_qtv_t *proxy) +{ + const char *gamedir; + + gamedir = Info_ValueForKey (svs.info, "*gamedir"); + if (!gamedir[0]) + gamedir = "qw"; + + MSG_WriteByte (&proxy->netchan.message, qtv_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); +} + +typedef struct { + const char *name; + void (*func) (sv_qtv_t *proxy); + unsigned no_redirect:1; +} qcmd_t; + +qcmd_t qcmds[] = { + {"drop", drop_proxy}, + {"new", qtv_new_f}, + + {0, 0}, +}; + +static void +qtv_command (sv_qtv_t *proxy, const char *s) +{ + qcmd_t *c; + const char *name; + + COM_TokenizeString (s, sv_args); + cmd_args = sv_args; + name = Cmd_Argv (0); + + for (c = qcmds; c->name; c++) + if (strcmp (c->name, name) == 0) + break; + if (!c->name) { + SV_Printf ("Bad QTV command: %s\n", sv_args->argv[0]->str); + return; + } + c->func (proxy); +} + +static void +qtv_parse (sv_qtv_t *proxy) +{ + int c; + + proxy->packet = 1; + while (1) { + if (net_message->badread) { + SV_Printf ("SV_ReadClientMessage: badread\n"); + drop_proxy (proxy); + return; + } + + c = MSG_ReadByte (net_message); + if (c == -1) + return; + + switch (c) { + default: + SV_Printf ("SV_ReadClientMessage: unknown command char\n"); + drop_proxy (proxy); + return; + case qtv_nop: + break; + + case qtv_stringcmd: + qtv_command (proxy, MSG_ReadString (net_message)); + break; + + case qtv_delta: + MSG_ReadByte (net_message); + break; + } + } +} + void SV_qtvConnect (int qport, info_t *info) { @@ -104,12 +212,11 @@ SV_qtvPacket (int qport) Con_DPrintf ("SV_ReadPackets: fixing up a translated port\n"); proxies[i].netchan.remote_address.port = net_from.port; } - Con_Printf ("boo\n"); if (Netchan_Process (&proxies[i].netchan)) { // this is a valid, sequenced packet, so process it svs.stats.packets++; } - Netchan_Transmit (&proxies[i].netchan, 0, 0); + qtv_parse (&proxies[i]); return 1; } return 0; @@ -129,11 +236,25 @@ SV_qtvCheckTimeouts (void) if (proxy->info) { if (proxy->netchan.last_received < droptime) { SV_Printf ("%s timed out\n", proxy->name_key->value); - MSG_WriteByte (&proxy->netchan.message, svc_disconnect); - Netchan_Transmit (&proxy->netchan, 0, 0); - Info_Destroy (proxy->info); - proxy->info = 0; + drop_proxy (proxy); } } } } + +void +SV_qtvSendMessages (void) +{ + int i; + sv_qtv_t *proxy; + + for (i = 0; i < MAX_PROXIES; i++) { + proxy = proxies + i; + if (!proxy->info) + continue; + if (!proxy->packet) + continue; + proxy->packet = 0; + Netchan_Transmit (&proxy->netchan, 0, 0); + } +} diff --git a/qw/source/sv_user.c b/qw/source/sv_user.c index 6421088a2..e856da322 100644 --- a/qw/source/sv_user.c +++ b/qw/source/sv_user.c @@ -60,7 +60,7 @@ static __attribute__ ((unused)) const char rcsid[] = #include "bothdefs.h" #include "compat.h" -#include "pmove.h" +#include "qw/pmove.h" #include "server.h" #include "sv_gib.h" #include "sv_progs.h" @@ -108,25 +108,55 @@ static void OutofBandPrintf (netadr_t where, const char *fmt, ...) __attribute__ Sends the first message from the server to a connected client. This will be sent on the initial connection and upon each server load. */ +void +SV_WriteWorldVars (netchan_t *netchan) +{ + + // send full levelname + MSG_WriteString (&netchan->message, + PR_GetString (&sv_pr_state, + SVstring (sv.edicts, message))); + + // send the movevars + MSG_WriteFloat (&netchan->message, movevars.gravity); + MSG_WriteFloat (&netchan->message, movevars.stopspeed); + MSG_WriteFloat (&netchan->message, movevars.maxspeed); + MSG_WriteFloat (&netchan->message, movevars.spectatormaxspeed); + MSG_WriteFloat (&netchan->message, movevars.accelerate); + MSG_WriteFloat (&netchan->message, movevars.airaccelerate); + MSG_WriteFloat (&netchan->message, movevars.wateraccelerate); + MSG_WriteFloat (&netchan->message, movevars.friction); + MSG_WriteFloat (&netchan->message, movevars.waterfriction); + MSG_WriteFloat (&netchan->message, movevars.entgravity); + + // send music + MSG_WriteByte (&netchan->message, svc_cdtrack); + MSG_WriteByte (&netchan->message, SVfloat (sv.edicts, sounds)); + + // send server info string + MSG_WriteByte (&netchan->message, svc_stufftext); + MSG_WriteString (&netchan->message, + va ("fullserverinfo \"%s\"\n", + Info_MakeString (svs.info, 0))); +} + static void SV_New_f (void *unused) { - const char *gamedir; int playernum; + const char *gamedir; if (host_client->state == cs_spawned) return; + gamedir = Info_ValueForKey (svs.info, "*gamedir"); + if (!gamedir[0]) + gamedir = "qw"; + host_client->state = cs_connected; host_client->connection_started = realtime; // send the info about the new client to all connected clients -// SV_FullClientUpdate (host_client, &sv.reliable_datagram); -// host_client->sendinfo = true; - - gamedir = Info_ValueForKey (svs.info, "*gamedir"); - if (!gamedir[0]) - gamedir = "qw"; // NOTE: This doesn't go through MSG_ReliableWrite since it's before the // user spawns. These functions are written to not overflow @@ -136,6 +166,7 @@ SV_New_f (void *unused) host_client->backbuf.num_backbuf = 0; SZ_Clear (&host_client->netchan.message); } + // send the serverdata MSG_WriteByte (&host_client->netchan.message, svc_serverdata); MSG_WriteLong (&host_client->netchan.message, PROTOCOL_VERSION); @@ -147,32 +178,7 @@ SV_New_f (void *unused) playernum |= 128; MSG_WriteByte (&host_client->netchan.message, playernum); - // send full levelname - MSG_WriteString (&host_client->netchan.message, - PR_GetString (&sv_pr_state, - SVstring (sv.edicts, message))); - - // send the movevars - MSG_WriteFloat (&host_client->netchan.message, movevars.gravity); - MSG_WriteFloat (&host_client->netchan.message, movevars.stopspeed); - MSG_WriteFloat (&host_client->netchan.message, movevars.maxspeed); - MSG_WriteFloat (&host_client->netchan.message, movevars.spectatormaxspeed); - MSG_WriteFloat (&host_client->netchan.message, movevars.accelerate); - MSG_WriteFloat (&host_client->netchan.message, movevars.airaccelerate); - MSG_WriteFloat (&host_client->netchan.message, movevars.wateraccelerate); - MSG_WriteFloat (&host_client->netchan.message, movevars.friction); - MSG_WriteFloat (&host_client->netchan.message, movevars.waterfriction); - MSG_WriteFloat (&host_client->netchan.message, movevars.entgravity); - - // send music - MSG_WriteByte (&host_client->netchan.message, svc_cdtrack); - MSG_WriteByte (&host_client->netchan.message, SVfloat (sv.edicts, sounds)); - - // send server info string - MSG_WriteByte (&host_client->netchan.message, svc_stufftext); - MSG_WriteString (&host_client->netchan.message, - va ("fullserverinfo \"%s\"\n", - Info_MakeString (svs.info, 0))); + SV_WriteWorldVars (&host_client->netchan); // Trigger GIB connection event if (sv_client_connect_e->func)